##// END OF EJS Templates
Merge with crew-stable
Patrick Mezard -
r8042:fd35e9d7 merge default
parent child Browse files
Show More
@@ -1,3463 +1,3463
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from i18n import _, gettext
9 from i18n import _, gettext
10 import os, re, sys, textwrap
10 import os, re, sys, textwrap
11 import hg, util, revlog, bundlerepo, extensions, copies, context, error
11 import hg, util, revlog, bundlerepo, extensions, copies, context, error
12 import difflib, patch, time, help, mdiff, tempfile, url, encoding
12 import difflib, patch, time, help, mdiff, tempfile, url, encoding
13 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
13 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
14 import merge as merge_
14 import merge as merge_
15
15
16 # Commands start here, listed alphabetically
16 # Commands start here, listed alphabetically
17
17
18 def add(ui, repo, *pats, **opts):
18 def add(ui, repo, *pats, **opts):
19 """add the specified files on the next commit
19 """add the specified files on the next commit
20
20
21 Schedule files to be version controlled and added to the
21 Schedule files to be version controlled and added to the
22 repository.
22 repository.
23
23
24 The files will be added to the repository at the next commit. To
24 The files will be added to the repository at the next commit. To
25 undo an add before that, see hg revert.
25 undo an add before that, see hg revert.
26
26
27 If no names are given, add all files to the repository.
27 If no names are given, add all files to the repository.
28 """
28 """
29
29
30 rejected = None
30 rejected = None
31 exacts = {}
31 exacts = {}
32 names = []
32 names = []
33 m = cmdutil.match(repo, pats, opts)
33 m = cmdutil.match(repo, pats, opts)
34 m.bad = lambda x,y: True
34 m.bad = lambda x,y: True
35 for abs in repo.walk(m):
35 for abs in repo.walk(m):
36 if m.exact(abs):
36 if m.exact(abs):
37 if ui.verbose:
37 if ui.verbose:
38 ui.status(_('adding %s\n') % m.rel(abs))
38 ui.status(_('adding %s\n') % m.rel(abs))
39 names.append(abs)
39 names.append(abs)
40 exacts[abs] = 1
40 exacts[abs] = 1
41 elif abs not in repo.dirstate:
41 elif abs not in repo.dirstate:
42 ui.status(_('adding %s\n') % m.rel(abs))
42 ui.status(_('adding %s\n') % m.rel(abs))
43 names.append(abs)
43 names.append(abs)
44 if not opts.get('dry_run'):
44 if not opts.get('dry_run'):
45 rejected = repo.add(names)
45 rejected = repo.add(names)
46 rejected = [p for p in rejected if p in exacts]
46 rejected = [p for p in rejected if p in exacts]
47 return rejected and 1 or 0
47 return rejected and 1 or 0
48
48
49 def addremove(ui, repo, *pats, **opts):
49 def addremove(ui, repo, *pats, **opts):
50 """add all new files, delete all missing files
50 """add all new files, delete all missing files
51
51
52 Add all new files and remove all missing files from the
52 Add all new files and remove all missing files from the
53 repository.
53 repository.
54
54
55 New files are ignored if they match any of the patterns in
55 New files are ignored if they match any of the patterns in
56 .hgignore. As with add, these changes take effect at the next
56 .hgignore. As with add, these changes take effect at the next
57 commit.
57 commit.
58
58
59 Use the -s/--similarity option to detect renamed files. With a
59 Use the -s/--similarity option to detect renamed files. With a
60 parameter > 0, this compares every removed file with every added
60 parameter > 0, this compares every removed file with every added
61 file and records those similar enough as renames. This option
61 file and records those similar enough as renames. This option
62 takes a percentage between 0 (disabled) and 100 (files must be
62 takes a percentage between 0 (disabled) and 100 (files must be
63 identical) as its parameter. Detecting renamed files this way can
63 identical) as its parameter. Detecting renamed files this way can
64 be expensive.
64 be expensive.
65 """
65 """
66 try:
66 try:
67 sim = float(opts.get('similarity') or 0)
67 sim = float(opts.get('similarity') or 0)
68 except ValueError:
68 except ValueError:
69 raise util.Abort(_('similarity must be a number'))
69 raise util.Abort(_('similarity must be a number'))
70 if sim < 0 or sim > 100:
70 if sim < 0 or sim > 100:
71 raise util.Abort(_('similarity must be between 0 and 100'))
71 raise util.Abort(_('similarity must be between 0 and 100'))
72 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
72 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
73
73
74 def annotate(ui, repo, *pats, **opts):
74 def annotate(ui, repo, *pats, **opts):
75 """show changeset information per file line
75 """show changeset information per file line
76
76
77 List changes in files, showing the revision id responsible for
77 List changes in files, showing the revision id responsible for
78 each line
78 each line
79
79
80 This command is useful to discover who did a change or when a
80 This command is useful to discover who did a change or when a
81 change took place.
81 change took place.
82
82
83 Without the -a/--text option, annotate will avoid processing files
83 Without the -a/--text option, annotate will avoid processing files
84 it detects as binary. With -a, annotate will generate an
84 it detects as binary. With -a, annotate will generate an
85 annotation anyway, probably with undesirable results.
85 annotation anyway, probably with undesirable results.
86 """
86 """
87 datefunc = ui.quiet and util.shortdate or util.datestr
87 datefunc = ui.quiet and util.shortdate or util.datestr
88 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
88 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
89
89
90 if not pats:
90 if not pats:
91 raise util.Abort(_('at least one file name or pattern required'))
91 raise util.Abort(_('at least one file name or pattern required'))
92
92
93 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
93 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
94 ('number', lambda x: str(x[0].rev())),
94 ('number', lambda x: str(x[0].rev())),
95 ('changeset', lambda x: short(x[0].node())),
95 ('changeset', lambda x: short(x[0].node())),
96 ('date', getdate),
96 ('date', getdate),
97 ('follow', lambda x: x[0].path()),
97 ('follow', lambda x: x[0].path()),
98 ]
98 ]
99
99
100 if (not opts.get('user') and not opts.get('changeset') and not opts.get('date')
100 if (not opts.get('user') and not opts.get('changeset') and not opts.get('date')
101 and not opts.get('follow')):
101 and not opts.get('follow')):
102 opts['number'] = 1
102 opts['number'] = 1
103
103
104 linenumber = opts.get('line_number') is not None
104 linenumber = opts.get('line_number') is not None
105 if (linenumber and (not opts.get('changeset')) and (not opts.get('number'))):
105 if (linenumber and (not opts.get('changeset')) and (not opts.get('number'))):
106 raise util.Abort(_('at least one of -n/-c is required for -l'))
106 raise util.Abort(_('at least one of -n/-c is required for -l'))
107
107
108 funcmap = [func for op, func in opmap if opts.get(op)]
108 funcmap = [func for op, func in opmap if opts.get(op)]
109 if linenumber:
109 if linenumber:
110 lastfunc = funcmap[-1]
110 lastfunc = funcmap[-1]
111 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
111 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
112
112
113 ctx = repo[opts.get('rev')]
113 ctx = repo[opts.get('rev')]
114
114
115 m = cmdutil.match(repo, pats, opts)
115 m = cmdutil.match(repo, pats, opts)
116 for abs in ctx.walk(m):
116 for abs in ctx.walk(m):
117 fctx = ctx[abs]
117 fctx = ctx[abs]
118 if not opts.get('text') and util.binary(fctx.data()):
118 if not opts.get('text') and util.binary(fctx.data()):
119 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
119 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
120 continue
120 continue
121
121
122 lines = fctx.annotate(follow=opts.get('follow'),
122 lines = fctx.annotate(follow=opts.get('follow'),
123 linenumber=linenumber)
123 linenumber=linenumber)
124 pieces = []
124 pieces = []
125
125
126 for f in funcmap:
126 for f in funcmap:
127 l = [f(n) for n, dummy in lines]
127 l = [f(n) for n, dummy in lines]
128 if l:
128 if l:
129 ml = max(map(len, l))
129 ml = max(map(len, l))
130 pieces.append(["%*s" % (ml, x) for x in l])
130 pieces.append(["%*s" % (ml, x) for x in l])
131
131
132 if pieces:
132 if pieces:
133 for p, l in zip(zip(*pieces), lines):
133 for p, l in zip(zip(*pieces), lines):
134 ui.write("%s: %s" % (" ".join(p), l[1]))
134 ui.write("%s: %s" % (" ".join(p), l[1]))
135
135
136 def archive(ui, repo, dest, **opts):
136 def archive(ui, repo, dest, **opts):
137 '''create unversioned archive of a repository revision
137 '''create unversioned archive of a repository revision
138
138
139 By default, the revision used is the parent of the working
139 By default, the revision used is the parent of the working
140 directory; use -r/--rev to specify a different revision.
140 directory; use -r/--rev to specify a different revision.
141
141
142 To specify the type of archive to create, use -t/--type. Valid
142 To specify the type of archive to create, use -t/--type. Valid
143 types are:
143 types are:
144
144
145 "files" (default): a directory full of files
145 "files" (default): a directory full of files
146 "tar": tar archive, uncompressed
146 "tar": tar archive, uncompressed
147 "tbz2": tar archive, compressed using bzip2
147 "tbz2": tar archive, compressed using bzip2
148 "tgz": tar archive, compressed using gzip
148 "tgz": tar archive, compressed using gzip
149 "uzip": zip archive, uncompressed
149 "uzip": zip archive, uncompressed
150 "zip": zip archive, compressed using deflate
150 "zip": zip archive, compressed using deflate
151
151
152 The exact name of the destination archive or directory is given
152 The exact name of the destination archive or directory is given
153 using a format string; see 'hg help export' for details.
153 using a format string; see 'hg help export' for details.
154
154
155 Each member added to an archive file has a directory prefix
155 Each member added to an archive file has a directory prefix
156 prepended. Use -p/--prefix to specify a format string for the
156 prepended. Use -p/--prefix to specify a format string for the
157 prefix. The default is the basename of the archive, with suffixes
157 prefix. The default is the basename of the archive, with suffixes
158 removed.
158 removed.
159 '''
159 '''
160
160
161 ctx = repo[opts.get('rev')]
161 ctx = repo[opts.get('rev')]
162 if not ctx:
162 if not ctx:
163 raise util.Abort(_('no working directory: please specify a revision'))
163 raise util.Abort(_('no working directory: please specify a revision'))
164 node = ctx.node()
164 node = ctx.node()
165 dest = cmdutil.make_filename(repo, dest, node)
165 dest = cmdutil.make_filename(repo, dest, node)
166 if os.path.realpath(dest) == repo.root:
166 if os.path.realpath(dest) == repo.root:
167 raise util.Abort(_('repository root cannot be destination'))
167 raise util.Abort(_('repository root cannot be destination'))
168 matchfn = cmdutil.match(repo, [], opts)
168 matchfn = cmdutil.match(repo, [], opts)
169 kind = opts.get('type') or 'files'
169 kind = opts.get('type') or 'files'
170 prefix = opts.get('prefix')
170 prefix = opts.get('prefix')
171 if dest == '-':
171 if dest == '-':
172 if kind == 'files':
172 if kind == 'files':
173 raise util.Abort(_('cannot archive plain files to stdout'))
173 raise util.Abort(_('cannot archive plain files to stdout'))
174 dest = sys.stdout
174 dest = sys.stdout
175 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
175 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
176 prefix = cmdutil.make_filename(repo, prefix, node)
176 prefix = cmdutil.make_filename(repo, prefix, node)
177 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
177 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
178 matchfn, prefix)
178 matchfn, prefix)
179
179
180 def backout(ui, repo, node=None, rev=None, **opts):
180 def backout(ui, repo, node=None, rev=None, **opts):
181 '''reverse effect of earlier changeset
181 '''reverse effect of earlier changeset
182
182
183 Commit the backed out changes as a new changeset. The new
183 Commit the backed out changes as a new changeset. The new
184 changeset is a child of the backed out changeset.
184 changeset is a child of the backed out changeset.
185
185
186 If you back out a changeset other than the tip, a new head is
186 If you back out a changeset other than the tip, a new head is
187 created. This head will be the new tip and you should merge this
187 created. This head will be the new tip and you should merge this
188 backout changeset with another head (current one by default).
188 backout changeset with another head (current one by default).
189
189
190 The --merge option remembers the parent of the working directory
190 The --merge option remembers the parent of the working directory
191 before starting the backout, then merges the new head with that
191 before starting the backout, then merges the new head with that
192 changeset afterwards. This saves you from doing the merge by hand.
192 changeset afterwards. This saves you from doing the merge by hand.
193 The result of this merge is not committed, as with a normal merge.
193 The result of this merge is not committed, as with a normal merge.
194
194
195 See \'hg help dates\' for a list of formats valid for -d/--date.
195 See \'hg help dates\' for a list of formats valid for -d/--date.
196 '''
196 '''
197 if rev and node:
197 if rev and node:
198 raise util.Abort(_("please specify just one revision"))
198 raise util.Abort(_("please specify just one revision"))
199
199
200 if not rev:
200 if not rev:
201 rev = node
201 rev = node
202
202
203 if not rev:
203 if not rev:
204 raise util.Abort(_("please specify a revision to backout"))
204 raise util.Abort(_("please specify a revision to backout"))
205
205
206 date = opts.get('date')
206 date = opts.get('date')
207 if date:
207 if date:
208 opts['date'] = util.parsedate(date)
208 opts['date'] = util.parsedate(date)
209
209
210 cmdutil.bail_if_changed(repo)
210 cmdutil.bail_if_changed(repo)
211 node = repo.lookup(rev)
211 node = repo.lookup(rev)
212
212
213 op1, op2 = repo.dirstate.parents()
213 op1, op2 = repo.dirstate.parents()
214 a = repo.changelog.ancestor(op1, node)
214 a = repo.changelog.ancestor(op1, node)
215 if a != node:
215 if a != node:
216 raise util.Abort(_('cannot back out change on a different branch'))
216 raise util.Abort(_('cannot back out change on a different branch'))
217
217
218 p1, p2 = repo.changelog.parents(node)
218 p1, p2 = repo.changelog.parents(node)
219 if p1 == nullid:
219 if p1 == nullid:
220 raise util.Abort(_('cannot back out a change with no parents'))
220 raise util.Abort(_('cannot back out a change with no parents'))
221 if p2 != nullid:
221 if p2 != nullid:
222 if not opts.get('parent'):
222 if not opts.get('parent'):
223 raise util.Abort(_('cannot back out a merge changeset without '
223 raise util.Abort(_('cannot back out a merge changeset without '
224 '--parent'))
224 '--parent'))
225 p = repo.lookup(opts['parent'])
225 p = repo.lookup(opts['parent'])
226 if p not in (p1, p2):
226 if p not in (p1, p2):
227 raise util.Abort(_('%s is not a parent of %s') %
227 raise util.Abort(_('%s is not a parent of %s') %
228 (short(p), short(node)))
228 (short(p), short(node)))
229 parent = p
229 parent = p
230 else:
230 else:
231 if opts.get('parent'):
231 if opts.get('parent'):
232 raise util.Abort(_('cannot use --parent on non-merge changeset'))
232 raise util.Abort(_('cannot use --parent on non-merge changeset'))
233 parent = p1
233 parent = p1
234
234
235 # the backout should appear on the same branch
235 # the backout should appear on the same branch
236 branch = repo.dirstate.branch()
236 branch = repo.dirstate.branch()
237 hg.clean(repo, node, show_stats=False)
237 hg.clean(repo, node, show_stats=False)
238 repo.dirstate.setbranch(branch)
238 repo.dirstate.setbranch(branch)
239 revert_opts = opts.copy()
239 revert_opts = opts.copy()
240 revert_opts['date'] = None
240 revert_opts['date'] = None
241 revert_opts['all'] = True
241 revert_opts['all'] = True
242 revert_opts['rev'] = hex(parent)
242 revert_opts['rev'] = hex(parent)
243 revert_opts['no_backup'] = None
243 revert_opts['no_backup'] = None
244 revert(ui, repo, **revert_opts)
244 revert(ui, repo, **revert_opts)
245 commit_opts = opts.copy()
245 commit_opts = opts.copy()
246 commit_opts['addremove'] = False
246 commit_opts['addremove'] = False
247 if not commit_opts['message'] and not commit_opts['logfile']:
247 if not commit_opts['message'] and not commit_opts['logfile']:
248 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
248 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
249 commit_opts['force_editor'] = True
249 commit_opts['force_editor'] = True
250 commit(ui, repo, **commit_opts)
250 commit(ui, repo, **commit_opts)
251 def nice(node):
251 def nice(node):
252 return '%d:%s' % (repo.changelog.rev(node), short(node))
252 return '%d:%s' % (repo.changelog.rev(node), short(node))
253 ui.status(_('changeset %s backs out changeset %s\n') %
253 ui.status(_('changeset %s backs out changeset %s\n') %
254 (nice(repo.changelog.tip()), nice(node)))
254 (nice(repo.changelog.tip()), nice(node)))
255 if op1 != node:
255 if op1 != node:
256 hg.clean(repo, op1, show_stats=False)
256 hg.clean(repo, op1, show_stats=False)
257 if opts.get('merge'):
257 if opts.get('merge'):
258 ui.status(_('merging with changeset %s\n') % nice(repo.changelog.tip()))
258 ui.status(_('merging with changeset %s\n') % nice(repo.changelog.tip()))
259 hg.merge(repo, hex(repo.changelog.tip()))
259 hg.merge(repo, hex(repo.changelog.tip()))
260 else:
260 else:
261 ui.status(_('the backout changeset is a new head - '
261 ui.status(_('the backout changeset is a new head - '
262 'do not forget to merge\n'))
262 'do not forget to merge\n'))
263 ui.status(_('(use "backout --merge" '
263 ui.status(_('(use "backout --merge" '
264 'if you want to auto-merge)\n'))
264 'if you want to auto-merge)\n'))
265
265
266 def bisect(ui, repo, rev=None, extra=None, command=None,
266 def bisect(ui, repo, rev=None, extra=None, command=None,
267 reset=None, good=None, bad=None, skip=None, noupdate=None):
267 reset=None, good=None, bad=None, skip=None, noupdate=None):
268 """subdivision search of changesets
268 """subdivision search of changesets
269
269
270 This command helps to find changesets which introduce problems. To
270 This command helps to find changesets which introduce problems. To
271 use, mark the earliest changeset you know exhibits the problem as
271 use, mark the earliest changeset you know exhibits the problem as
272 bad, then mark the latest changeset which is free from the problem
272 bad, then mark the latest changeset which is free from the problem
273 as good. Bisect will update your working directory to a revision
273 as good. Bisect will update your working directory to a revision
274 for testing (unless the -U/--noupdate option is specified). Once
274 for testing (unless the -U/--noupdate option is specified). Once
275 you have performed tests, mark the working directory as bad or
275 you have performed tests, mark the working directory as bad or
276 good and bisect will either update to another candidate changeset
276 good and bisect will either update to another candidate changeset
277 or announce that it has found the bad revision.
277 or announce that it has found the bad revision.
278
278
279 As a shortcut, you can also use the revision argument to mark a
279 As a shortcut, you can also use the revision argument to mark a
280 revision as good or bad without checking it out first.
280 revision as good or bad without checking it out first.
281
281
282 If you supply a command it will be used for automatic bisection.
282 If you supply a command it will be used for automatic bisection.
283 Its exit status will be used as flag to mark revision as bad or
283 Its exit status will be used as flag to mark revision as bad or
284 good. In case exit status is 0 the revision is marked as good, 125
284 good. In case exit status is 0 the revision is marked as good, 125
285 - skipped, 127 (command not found) - bisection will be aborted;
285 - skipped, 127 (command not found) - bisection will be aborted;
286 any other status bigger than 0 will mark revision as bad.
286 any other status bigger than 0 will mark revision as bad.
287 """
287 """
288 def print_result(nodes, good):
288 def print_result(nodes, good):
289 displayer = cmdutil.show_changeset(ui, repo, {})
289 displayer = cmdutil.show_changeset(ui, repo, {})
290 transition = (good and "good" or "bad")
290 transition = (good and "good" or "bad")
291 if len(nodes) == 1:
291 if len(nodes) == 1:
292 # narrowed it down to a single revision
292 # narrowed it down to a single revision
293 ui.write(_("The first %s revision is:\n") % transition)
293 ui.write(_("The first %s revision is:\n") % transition)
294 displayer.show(repo[nodes[0]])
294 displayer.show(repo[nodes[0]])
295 else:
295 else:
296 # multiple possible revisions
296 # multiple possible revisions
297 ui.write(_("Due to skipped revisions, the first "
297 ui.write(_("Due to skipped revisions, the first "
298 "%s revision could be any of:\n") % transition)
298 "%s revision could be any of:\n") % transition)
299 for n in nodes:
299 for n in nodes:
300 displayer.show(repo[n])
300 displayer.show(repo[n])
301
301
302 def check_state(state, interactive=True):
302 def check_state(state, interactive=True):
303 if not state['good'] or not state['bad']:
303 if not state['good'] or not state['bad']:
304 if (good or bad or skip or reset) and interactive:
304 if (good or bad or skip or reset) and interactive:
305 return
305 return
306 if not state['good']:
306 if not state['good']:
307 raise util.Abort(_('cannot bisect (no known good revisions)'))
307 raise util.Abort(_('cannot bisect (no known good revisions)'))
308 else:
308 else:
309 raise util.Abort(_('cannot bisect (no known bad revisions)'))
309 raise util.Abort(_('cannot bisect (no known bad revisions)'))
310 return True
310 return True
311
311
312 # backward compatibility
312 # backward compatibility
313 if rev in "good bad reset init".split():
313 if rev in "good bad reset init".split():
314 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
314 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
315 cmd, rev, extra = rev, extra, None
315 cmd, rev, extra = rev, extra, None
316 if cmd == "good":
316 if cmd == "good":
317 good = True
317 good = True
318 elif cmd == "bad":
318 elif cmd == "bad":
319 bad = True
319 bad = True
320 else:
320 else:
321 reset = True
321 reset = True
322 elif extra or good + bad + skip + reset + bool(command) > 1:
322 elif extra or good + bad + skip + reset + bool(command) > 1:
323 raise util.Abort(_('incompatible arguments'))
323 raise util.Abort(_('incompatible arguments'))
324
324
325 if reset:
325 if reset:
326 p = repo.join("bisect.state")
326 p = repo.join("bisect.state")
327 if os.path.exists(p):
327 if os.path.exists(p):
328 os.unlink(p)
328 os.unlink(p)
329 return
329 return
330
330
331 state = hbisect.load_state(repo)
331 state = hbisect.load_state(repo)
332
332
333 if command:
333 if command:
334 commandpath = util.find_exe(command)
334 commandpath = util.find_exe(command)
335 changesets = 1
335 changesets = 1
336 try:
336 try:
337 while changesets:
337 while changesets:
338 # update state
338 # update state
339 status = os.spawnl(os.P_WAIT, commandpath, commandpath)
339 status = os.spawnl(os.P_WAIT, commandpath, commandpath)
340 if status == 125:
340 if status == 125:
341 transition = "skip"
341 transition = "skip"
342 elif status == 0:
342 elif status == 0:
343 transition = "good"
343 transition = "good"
344 # status < 0 means process was killed
344 # status < 0 means process was killed
345 elif status == 127:
345 elif status == 127:
346 raise util.Abort(_("failed to execute %s") % command)
346 raise util.Abort(_("failed to execute %s") % command)
347 elif status < 0:
347 elif status < 0:
348 raise util.Abort(_("%s killed") % command)
348 raise util.Abort(_("%s killed") % command)
349 else:
349 else:
350 transition = "bad"
350 transition = "bad"
351 node = repo.lookup(rev or '.')
351 node = repo.lookup(rev or '.')
352 state[transition].append(node)
352 state[transition].append(node)
353 ui.note(_('Changeset %s: %s\n') % (short(node), transition))
353 ui.note(_('Changeset %s: %s\n') % (short(node), transition))
354 check_state(state, interactive=False)
354 check_state(state, interactive=False)
355 # bisect
355 # bisect
356 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
356 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
357 # update to next check
357 # update to next check
358 cmdutil.bail_if_changed(repo)
358 cmdutil.bail_if_changed(repo)
359 hg.clean(repo, nodes[0], show_stats=False)
359 hg.clean(repo, nodes[0], show_stats=False)
360 finally:
360 finally:
361 hbisect.save_state(repo, state)
361 hbisect.save_state(repo, state)
362 return print_result(nodes, not status)
362 return print_result(nodes, not status)
363
363
364 # update state
364 # update state
365 node = repo.lookup(rev or '.')
365 node = repo.lookup(rev or '.')
366 if good:
366 if good:
367 state['good'].append(node)
367 state['good'].append(node)
368 elif bad:
368 elif bad:
369 state['bad'].append(node)
369 state['bad'].append(node)
370 elif skip:
370 elif skip:
371 state['skip'].append(node)
371 state['skip'].append(node)
372
372
373 hbisect.save_state(repo, state)
373 hbisect.save_state(repo, state)
374
374
375 if not check_state(state):
375 if not check_state(state):
376 return
376 return
377
377
378 # actually bisect
378 # actually bisect
379 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
379 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
380 if changesets == 0:
380 if changesets == 0:
381 print_result(nodes, good)
381 print_result(nodes, good)
382 else:
382 else:
383 assert len(nodes) == 1 # only a single node can be tested next
383 assert len(nodes) == 1 # only a single node can be tested next
384 node = nodes[0]
384 node = nodes[0]
385 # compute the approximate number of remaining tests
385 # compute the approximate number of remaining tests
386 tests, size = 0, 2
386 tests, size = 0, 2
387 while size <= changesets:
387 while size <= changesets:
388 tests, size = tests + 1, size * 2
388 tests, size = tests + 1, size * 2
389 rev = repo.changelog.rev(node)
389 rev = repo.changelog.rev(node)
390 ui.write(_("Testing changeset %s:%s "
390 ui.write(_("Testing changeset %s:%s "
391 "(%s changesets remaining, ~%s tests)\n")
391 "(%s changesets remaining, ~%s tests)\n")
392 % (rev, short(node), changesets, tests))
392 % (rev, short(node), changesets, tests))
393 if not noupdate:
393 if not noupdate:
394 cmdutil.bail_if_changed(repo)
394 cmdutil.bail_if_changed(repo)
395 return hg.clean(repo, node)
395 return hg.clean(repo, node)
396
396
397 def branch(ui, repo, label=None, **opts):
397 def branch(ui, repo, label=None, **opts):
398 """set or show the current branch name
398 """set or show the current branch name
399
399
400 With no argument, show the current branch name. With one argument,
400 With no argument, show the current branch name. With one argument,
401 set the working directory branch name (the branch does not exist
401 set the working directory branch name (the branch does not exist
402 in the repository until the next commit). It is recommended to use
402 in the repository until the next commit). It is recommended to use
403 the 'default' branch as your primary development branch.
403 the 'default' branch as your primary development branch.
404
404
405 Unless -f/--force is specified, branch will not let you set a
405 Unless -f/--force is specified, branch will not let you set a
406 branch name that shadows an existing branch.
406 branch name that shadows an existing branch.
407
407
408 Use -C/--clean to reset the working directory branch to that of
408 Use -C/--clean to reset the working directory branch to that of
409 the parent of the working directory, negating a previous branch
409 the parent of the working directory, negating a previous branch
410 change.
410 change.
411
411
412 Use the command 'hg update' to switch to an existing branch.
412 Use the command 'hg update' to switch to an existing branch.
413 """
413 """
414
414
415 if opts.get('clean'):
415 if opts.get('clean'):
416 label = repo[None].parents()[0].branch()
416 label = repo[None].parents()[0].branch()
417 repo.dirstate.setbranch(label)
417 repo.dirstate.setbranch(label)
418 ui.status(_('reset working directory to branch %s\n') % label)
418 ui.status(_('reset working directory to branch %s\n') % label)
419 elif label:
419 elif label:
420 if not opts.get('force') and label in repo.branchtags():
420 if not opts.get('force') and label in repo.branchtags():
421 if label not in [p.branch() for p in repo.parents()]:
421 if label not in [p.branch() for p in repo.parents()]:
422 raise util.Abort(_('a branch of the same name already exists'
422 raise util.Abort(_('a branch of the same name already exists'
423 ' (use --force to override)'))
423 ' (use --force to override)'))
424 repo.dirstate.setbranch(encoding.fromlocal(label))
424 repo.dirstate.setbranch(encoding.fromlocal(label))
425 ui.status(_('marked working directory as branch %s\n') % label)
425 ui.status(_('marked working directory as branch %s\n') % label)
426 else:
426 else:
427 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
427 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
428
428
429 def branches(ui, repo, active=False):
429 def branches(ui, repo, active=False):
430 """list repository named branches
430 """list repository named branches
431
431
432 List the repository's named branches, indicating which ones are
432 List the repository's named branches, indicating which ones are
433 inactive. If active is specified, only show active branches.
433 inactive. If active is specified, only show active branches.
434
434
435 A branch is considered active if it contains repository heads.
435 A branch is considered active if it contains repository heads.
436
436
437 Use the command 'hg update' to switch to an existing branch.
437 Use the command 'hg update' to switch to an existing branch.
438 """
438 """
439 hexfunc = ui.debugflag and hex or short
439 hexfunc = ui.debugflag and hex or short
440 activebranches = [encoding.tolocal(repo[n].branch())
440 activebranches = [encoding.tolocal(repo[n].branch())
441 for n in repo.heads(closed=False)]
441 for n in repo.heads(closed=False)]
442 branches = util.sort([(tag in activebranches, repo.changelog.rev(node), tag)
442 branches = util.sort([(tag in activebranches, repo.changelog.rev(node), tag)
443 for tag, node in repo.branchtags().items()])
443 for tag, node in repo.branchtags().items()])
444 branches.reverse()
444 branches.reverse()
445
445
446 for isactive, node, tag in branches:
446 for isactive, node, tag in branches:
447 if (not active) or isactive:
447 if (not active) or isactive:
448 if ui.quiet:
448 if ui.quiet:
449 ui.write("%s\n" % tag)
449 ui.write("%s\n" % tag)
450 else:
450 else:
451 hn = repo.lookup(node)
451 hn = repo.lookup(node)
452 if isactive:
452 if isactive:
453 notice = ''
453 notice = ''
454 elif hn not in repo.branchheads(tag, closed=False):
454 elif hn not in repo.branchheads(tag, closed=False):
455 notice = ' (closed)'
455 notice = ' (closed)'
456 else:
456 else:
457 notice = ' (inactive)'
457 notice = ' (inactive)'
458 rev = str(node).rjust(31 - encoding.colwidth(tag))
458 rev = str(node).rjust(31 - encoding.colwidth(tag))
459 data = tag, rev, hexfunc(hn), notice
459 data = tag, rev, hexfunc(hn), notice
460 ui.write("%s %s:%s%s\n" % data)
460 ui.write("%s %s:%s%s\n" % data)
461
461
462 def bundle(ui, repo, fname, dest=None, **opts):
462 def bundle(ui, repo, fname, dest=None, **opts):
463 """create a changegroup file
463 """create a changegroup file
464
464
465 Generate a compressed changegroup file collecting changesets not
465 Generate a compressed changegroup file collecting changesets not
466 known to be in another repository.
466 known to be in another repository.
467
467
468 If no destination repository is specified the destination is
468 If no destination repository is specified the destination is
469 assumed to have all the nodes specified by one or more --base
469 assumed to have all the nodes specified by one or more --base
470 parameters. To create a bundle containing all changesets, use
470 parameters. To create a bundle containing all changesets, use
471 -a/--all (or --base null). To change the compression method
471 -a/--all (or --base null). To change the compression method
472 applied, use the -t/--type option (by default, bundles are
472 applied, use the -t/--type option (by default, bundles are
473 compressed using bz2).
473 compressed using bz2).
474
474
475 The bundle file can then be transferred using conventional means
475 The bundle file can then be transferred using conventional means
476 and applied to another repository with the unbundle or pull
476 and applied to another repository with the unbundle or pull
477 command. This is useful when direct push and pull are not
477 command. This is useful when direct push and pull are not
478 available or when exporting an entire repository is undesirable.
478 available or when exporting an entire repository is undesirable.
479
479
480 Applying bundles preserves all changeset contents including
480 Applying bundles preserves all changeset contents including
481 permissions, copy/rename information, and revision history.
481 permissions, copy/rename information, and revision history.
482 """
482 """
483 revs = opts.get('rev') or None
483 revs = opts.get('rev') or None
484 if revs:
484 if revs:
485 revs = [repo.lookup(rev) for rev in revs]
485 revs = [repo.lookup(rev) for rev in revs]
486 if opts.get('all'):
486 if opts.get('all'):
487 base = ['null']
487 base = ['null']
488 else:
488 else:
489 base = opts.get('base')
489 base = opts.get('base')
490 if base:
490 if base:
491 if dest:
491 if dest:
492 raise util.Abort(_("--base is incompatible with specifiying "
492 raise util.Abort(_("--base is incompatible with specifiying "
493 "a destination"))
493 "a destination"))
494 base = [repo.lookup(rev) for rev in base]
494 base = [repo.lookup(rev) for rev in base]
495 # create the right base
495 # create the right base
496 # XXX: nodesbetween / changegroup* should be "fixed" instead
496 # XXX: nodesbetween / changegroup* should be "fixed" instead
497 o = []
497 o = []
498 has = {nullid: None}
498 has = {nullid: None}
499 for n in base:
499 for n in base:
500 has.update(repo.changelog.reachable(n))
500 has.update(repo.changelog.reachable(n))
501 if revs:
501 if revs:
502 visit = list(revs)
502 visit = list(revs)
503 else:
503 else:
504 visit = repo.changelog.heads()
504 visit = repo.changelog.heads()
505 seen = {}
505 seen = {}
506 while visit:
506 while visit:
507 n = visit.pop(0)
507 n = visit.pop(0)
508 parents = [p for p in repo.changelog.parents(n) if p not in has]
508 parents = [p for p in repo.changelog.parents(n) if p not in has]
509 if len(parents) == 0:
509 if len(parents) == 0:
510 o.insert(0, n)
510 o.insert(0, n)
511 else:
511 else:
512 for p in parents:
512 for p in parents:
513 if p not in seen:
513 if p not in seen:
514 seen[p] = 1
514 seen[p] = 1
515 visit.append(p)
515 visit.append(p)
516 else:
516 else:
517 cmdutil.setremoteconfig(ui, opts)
517 cmdutil.setremoteconfig(ui, opts)
518 dest, revs, checkout = hg.parseurl(
518 dest, revs, checkout = hg.parseurl(
519 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
519 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
520 other = hg.repository(ui, dest)
520 other = hg.repository(ui, dest)
521 o = repo.findoutgoing(other, force=opts.get('force'))
521 o = repo.findoutgoing(other, force=opts.get('force'))
522
522
523 if revs:
523 if revs:
524 cg = repo.changegroupsubset(o, revs, 'bundle')
524 cg = repo.changegroupsubset(o, revs, 'bundle')
525 else:
525 else:
526 cg = repo.changegroup(o, 'bundle')
526 cg = repo.changegroup(o, 'bundle')
527
527
528 bundletype = opts.get('type', 'bzip2').lower()
528 bundletype = opts.get('type', 'bzip2').lower()
529 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
529 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
530 bundletype = btypes.get(bundletype)
530 bundletype = btypes.get(bundletype)
531 if bundletype not in changegroup.bundletypes:
531 if bundletype not in changegroup.bundletypes:
532 raise util.Abort(_('unknown bundle type specified with --type'))
532 raise util.Abort(_('unknown bundle type specified with --type'))
533
533
534 changegroup.writebundle(cg, fname, bundletype)
534 changegroup.writebundle(cg, fname, bundletype)
535
535
536 def cat(ui, repo, file1, *pats, **opts):
536 def cat(ui, repo, file1, *pats, **opts):
537 """output the current or given revision of files
537 """output the current or given revision of files
538
538
539 Print the specified files as they were at the given revision. If
539 Print the specified files as they were at the given revision. If
540 no revision is given, the parent of the working directory is used,
540 no revision is given, the parent of the working directory is used,
541 or tip if no revision is checked out.
541 or tip if no revision is checked out.
542
542
543 Output may be to a file, in which case the name of the file is
543 Output may be to a file, in which case the name of the file is
544 given using a format string. The formatting rules are the same as
544 given using a format string. The formatting rules are the same as
545 for the export command, with the following additions:
545 for the export command, with the following additions:
546
546
547 %s basename of file being printed
547 %s basename of file being printed
548 %d dirname of file being printed, or '.' if in repository root
548 %d dirname of file being printed, or '.' if in repository root
549 %p root-relative path name of file being printed
549 %p root-relative path name of file being printed
550 """
550 """
551 ctx = repo[opts.get('rev')]
551 ctx = repo[opts.get('rev')]
552 err = 1
552 err = 1
553 m = cmdutil.match(repo, (file1,) + pats, opts)
553 m = cmdutil.match(repo, (file1,) + pats, opts)
554 for abs in ctx.walk(m):
554 for abs in ctx.walk(m):
555 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
555 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
556 data = ctx[abs].data()
556 data = ctx[abs].data()
557 if opts.get('decode'):
557 if opts.get('decode'):
558 data = repo.wwritedata(abs, data)
558 data = repo.wwritedata(abs, data)
559 fp.write(data)
559 fp.write(data)
560 err = 0
560 err = 0
561 return err
561 return err
562
562
563 def clone(ui, source, dest=None, **opts):
563 def clone(ui, source, dest=None, **opts):
564 """make a copy of an existing repository
564 """make a copy of an existing repository
565
565
566 Create a copy of an existing repository in a new directory.
566 Create a copy of an existing repository in a new directory.
567
567
568 If no destination directory name is specified, it defaults to the
568 If no destination directory name is specified, it defaults to the
569 basename of the source.
569 basename of the source.
570
570
571 The location of the source is added to the new repository's
571 The location of the source is added to the new repository's
572 .hg/hgrc file, as the default to be used for future pulls.
572 .hg/hgrc file, as the default to be used for future pulls.
573
573
574 If you use the -r/--rev option to clone up to a specific revision,
574 If you use the -r/--rev option to clone up to a specific revision,
575 no subsequent revisions (including subsequent tags) will be
575 no subsequent revisions (including subsequent tags) will be
576 present in the cloned repository. This option implies --pull, even
576 present in the cloned repository. This option implies --pull, even
577 on local repositories.
577 on local repositories.
578
578
579 By default, clone will check out the head of the 'default' branch.
579 By default, clone will check out the head of the 'default' branch.
580 If the -U/--noupdate option is used, the new clone will contain
580 If the -U/--noupdate option is used, the new clone will contain
581 only a repository (.hg) and no working copy (the working copy
581 only a repository (.hg) and no working copy (the working copy
582 parent is the null revision).
582 parent is the null revision).
583
583
584 See 'hg help urls' for valid source format details.
584 See 'hg help urls' for valid source format details.
585
585
586 It is possible to specify an ssh:// URL as the destination, but no
586 It is possible to specify an ssh:// URL as the destination, but no
587 .hg/hgrc and working directory will be created on the remote side.
587 .hg/hgrc and working directory will be created on the remote side.
588 Look at the help text for URLs for important details about ssh://
588 Look at the help text for URLs for important details about ssh://
589 URLs.
589 URLs.
590
590
591 For efficiency, hardlinks are used for cloning whenever the source
591 For efficiency, hardlinks are used for cloning whenever the source
592 and destination are on the same filesystem (note this applies only
592 and destination are on the same filesystem (note this applies only
593 to the repository data, not to the checked out files). Some
593 to the repository data, not to the checked out files). Some
594 filesystems, such as AFS, implement hardlinking incorrectly, but
594 filesystems, such as AFS, implement hardlinking incorrectly, but
595 do not report errors. In these cases, use the --pull option to
595 do not report errors. In these cases, use the --pull option to
596 avoid hardlinking.
596 avoid hardlinking.
597
597
598 In some cases, you can clone repositories and checked out files
598 In some cases, you can clone repositories and checked out files
599 using full hardlinks with
599 using full hardlinks with
600
600
601 $ cp -al REPO REPOCLONE
601 $ cp -al REPO REPOCLONE
602
602
603 This is the fastest way to clone, but it is not always safe. The
603 This is the fastest way to clone, but it is not always safe. The
604 operation is not atomic (making sure REPO is not modified during
604 operation is not atomic (making sure REPO is not modified during
605 the operation is up to you) and you have to make sure your editor
605 the operation is up to you) and you have to make sure your editor
606 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
606 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
607 this is not compatible with certain extensions that place their
607 this is not compatible with certain extensions that place their
608 metadata under the .hg directory, such as mq.
608 metadata under the .hg directory, such as mq.
609
609
610 """
610 """
611 cmdutil.setremoteconfig(ui, opts)
611 cmdutil.setremoteconfig(ui, opts)
612 hg.clone(ui, source, dest,
612 hg.clone(ui, source, dest,
613 pull=opts.get('pull'),
613 pull=opts.get('pull'),
614 stream=opts.get('uncompressed'),
614 stream=opts.get('uncompressed'),
615 rev=opts.get('rev'),
615 rev=opts.get('rev'),
616 update=not opts.get('noupdate'))
616 update=not opts.get('noupdate'))
617
617
618 def commit(ui, repo, *pats, **opts):
618 def commit(ui, repo, *pats, **opts):
619 """commit the specified files or all outstanding changes
619 """commit the specified files or all outstanding changes
620
620
621 Commit changes to the given files into the repository. Unlike a
621 Commit changes to the given files into the repository. Unlike a
622 centralized RCS, this operation is a local operation. See hg push
622 centralized RCS, this operation is a local operation. See hg push
623 for means to actively distribute your changes.
623 for means to actively distribute your changes.
624
624
625 If a list of files is omitted, all changes reported by "hg status"
625 If a list of files is omitted, all changes reported by "hg status"
626 will be committed.
626 will be committed.
627
627
628 If you are committing the result of a merge, do not provide any
628 If you are committing the result of a merge, do not provide any
629 file names or -I/-X filters.
629 file names or -I/-X filters.
630
630
631 If no commit message is specified, the configured editor is
631 If no commit message is specified, the configured editor is
632 started to prompt you for a message.
632 started to prompt you for a message.
633
633
634 See 'hg help dates' for a list of formats valid for -d/--date.
634 See 'hg help dates' for a list of formats valid for -d/--date.
635 """
635 """
636 extra = {}
636 extra = {}
637 if opts.get('close_branch'):
637 if opts.get('close_branch'):
638 extra['close'] = 1
638 extra['close'] = 1
639 def commitfunc(ui, repo, message, match, opts):
639 def commitfunc(ui, repo, message, match, opts):
640 return repo.commit(match.files(), message, opts.get('user'),
640 return repo.commit(match.files(), message, opts.get('user'),
641 opts.get('date'), match, force_editor=opts.get('force_editor'),
641 opts.get('date'), match, force_editor=opts.get('force_editor'),
642 extra=extra)
642 extra=extra)
643
643
644 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
644 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
645 if not node:
645 if not node:
646 return
646 return
647 cl = repo.changelog
647 cl = repo.changelog
648 rev = cl.rev(node)
648 rev = cl.rev(node)
649 parents = cl.parentrevs(rev)
649 parents = cl.parentrevs(rev)
650 if rev - 1 in parents:
650 if rev - 1 in parents:
651 # one of the parents was the old tip
651 # one of the parents was the old tip
652 pass
652 pass
653 elif (parents == (nullrev, nullrev) or
653 elif (parents == (nullrev, nullrev) or
654 len(cl.heads(cl.node(parents[0]))) > 1 and
654 len(cl.heads(cl.node(parents[0]))) > 1 and
655 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
655 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
656 ui.status(_('created new head\n'))
656 ui.status(_('created new head\n'))
657
657
658 if ui.debugflag:
658 if ui.debugflag:
659 ui.write(_('committed changeset %d:%s\n') % (rev,hex(node)))
659 ui.write(_('committed changeset %d:%s\n') % (rev,hex(node)))
660 elif ui.verbose:
660 elif ui.verbose:
661 ui.write(_('committed changeset %d:%s\n') % (rev,short(node)))
661 ui.write(_('committed changeset %d:%s\n') % (rev,short(node)))
662
662
663 def copy(ui, repo, *pats, **opts):
663 def copy(ui, repo, *pats, **opts):
664 """mark files as copied for the next commit
664 """mark files as copied for the next commit
665
665
666 Mark dest as having copies of source files. If dest is a
666 Mark dest as having copies of source files. If dest is a
667 directory, copies are put in that directory. If dest is a file,
667 directory, copies are put in that directory. If dest is a file,
668 the source must be a single file.
668 the source must be a single file.
669
669
670 By default, this command copies the contents of files as they
670 By default, this command copies the contents of files as they
671 stand in the working directory. If invoked with -A/--after, the
671 stand in the working directory. If invoked with -A/--after, the
672 operation is recorded, but no copying is performed.
672 operation is recorded, but no copying is performed.
673
673
674 This command takes effect with the next commit. To undo a copy
674 This command takes effect with the next commit. To undo a copy
675 before that, see hg revert.
675 before that, see hg revert.
676 """
676 """
677 wlock = repo.wlock(False)
677 wlock = repo.wlock(False)
678 try:
678 try:
679 return cmdutil.copy(ui, repo, pats, opts)
679 return cmdutil.copy(ui, repo, pats, opts)
680 finally:
680 finally:
681 del wlock
681 del wlock
682
682
683 def debugancestor(ui, repo, *args):
683 def debugancestor(ui, repo, *args):
684 """find the ancestor revision of two revisions in a given index"""
684 """find the ancestor revision of two revisions in a given index"""
685 if len(args) == 3:
685 if len(args) == 3:
686 index, rev1, rev2 = args
686 index, rev1, rev2 = args
687 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
687 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
688 lookup = r.lookup
688 lookup = r.lookup
689 elif len(args) == 2:
689 elif len(args) == 2:
690 if not repo:
690 if not repo:
691 raise util.Abort(_("There is no Mercurial repository here "
691 raise util.Abort(_("There is no Mercurial repository here "
692 "(.hg not found)"))
692 "(.hg not found)"))
693 rev1, rev2 = args
693 rev1, rev2 = args
694 r = repo.changelog
694 r = repo.changelog
695 lookup = repo.lookup
695 lookup = repo.lookup
696 else:
696 else:
697 raise util.Abort(_('either two or three arguments required'))
697 raise util.Abort(_('either two or three arguments required'))
698 a = r.ancestor(lookup(rev1), lookup(rev2))
698 a = r.ancestor(lookup(rev1), lookup(rev2))
699 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
699 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
700
700
701 def debugcommands(ui, cmd='', *args):
701 def debugcommands(ui, cmd='', *args):
702 for cmd, vals in util.sort(table.iteritems()):
702 for cmd, vals in util.sort(table.iteritems()):
703 cmd = cmd.split('|')[0].strip('^')
703 cmd = cmd.split('|')[0].strip('^')
704 opts = ', '.join([i[1] for i in vals[1]])
704 opts = ', '.join([i[1] for i in vals[1]])
705 ui.write('%s: %s\n' % (cmd, opts))
705 ui.write('%s: %s\n' % (cmd, opts))
706
706
707 def debugcomplete(ui, cmd='', **opts):
707 def debugcomplete(ui, cmd='', **opts):
708 """returns the completion list associated with the given command"""
708 """returns the completion list associated with the given command"""
709
709
710 if opts.get('options'):
710 if opts.get('options'):
711 options = []
711 options = []
712 otables = [globalopts]
712 otables = [globalopts]
713 if cmd:
713 if cmd:
714 aliases, entry = cmdutil.findcmd(cmd, table, False)
714 aliases, entry = cmdutil.findcmd(cmd, table, False)
715 otables.append(entry[1])
715 otables.append(entry[1])
716 for t in otables:
716 for t in otables:
717 for o in t:
717 for o in t:
718 if o[0]:
718 if o[0]:
719 options.append('-%s' % o[0])
719 options.append('-%s' % o[0])
720 options.append('--%s' % o[1])
720 options.append('--%s' % o[1])
721 ui.write("%s\n" % "\n".join(options))
721 ui.write("%s\n" % "\n".join(options))
722 return
722 return
723
723
724 cmdlist = cmdutil.findpossible(cmd, table)
724 cmdlist = cmdutil.findpossible(cmd, table)
725 if ui.verbose:
725 if ui.verbose:
726 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
726 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
727 ui.write("%s\n" % "\n".join(util.sort(cmdlist)))
727 ui.write("%s\n" % "\n".join(util.sort(cmdlist)))
728
728
729 def debugfsinfo(ui, path = "."):
729 def debugfsinfo(ui, path = "."):
730 file('.debugfsinfo', 'w').write('')
730 file('.debugfsinfo', 'w').write('')
731 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
731 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
732 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
732 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
733 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
733 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
734 and 'yes' or 'no'))
734 and 'yes' or 'no'))
735 os.unlink('.debugfsinfo')
735 os.unlink('.debugfsinfo')
736
736
737 def debugrebuildstate(ui, repo, rev="tip"):
737 def debugrebuildstate(ui, repo, rev="tip"):
738 """rebuild the dirstate as it would look like for the given revision"""
738 """rebuild the dirstate as it would look like for the given revision"""
739 ctx = repo[rev]
739 ctx = repo[rev]
740 wlock = repo.wlock()
740 wlock = repo.wlock()
741 try:
741 try:
742 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
742 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
743 finally:
743 finally:
744 del wlock
744 del wlock
745
745
746 def debugcheckstate(ui, repo):
746 def debugcheckstate(ui, repo):
747 """validate the correctness of the current dirstate"""
747 """validate the correctness of the current dirstate"""
748 parent1, parent2 = repo.dirstate.parents()
748 parent1, parent2 = repo.dirstate.parents()
749 m1 = repo[parent1].manifest()
749 m1 = repo[parent1].manifest()
750 m2 = repo[parent2].manifest()
750 m2 = repo[parent2].manifest()
751 errors = 0
751 errors = 0
752 for f in repo.dirstate:
752 for f in repo.dirstate:
753 state = repo.dirstate[f]
753 state = repo.dirstate[f]
754 if state in "nr" and f not in m1:
754 if state in "nr" and f not in m1:
755 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
755 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
756 errors += 1
756 errors += 1
757 if state in "a" and f in m1:
757 if state in "a" and f in m1:
758 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
758 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
759 errors += 1
759 errors += 1
760 if state in "m" and f not in m1 and f not in m2:
760 if state in "m" and f not in m1 and f not in m2:
761 ui.warn(_("%s in state %s, but not in either manifest\n") %
761 ui.warn(_("%s in state %s, but not in either manifest\n") %
762 (f, state))
762 (f, state))
763 errors += 1
763 errors += 1
764 for f in m1:
764 for f in m1:
765 state = repo.dirstate[f]
765 state = repo.dirstate[f]
766 if state not in "nrm":
766 if state not in "nrm":
767 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
767 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
768 errors += 1
768 errors += 1
769 if errors:
769 if errors:
770 error = _(".hg/dirstate inconsistent with current parent's manifest")
770 error = _(".hg/dirstate inconsistent with current parent's manifest")
771 raise util.Abort(error)
771 raise util.Abort(error)
772
772
773 def showconfig(ui, repo, *values, **opts):
773 def showconfig(ui, repo, *values, **opts):
774 """show combined config settings from all hgrc files
774 """show combined config settings from all hgrc files
775
775
776 With no args, print names and values of all config items.
776 With no args, print names and values of all config items.
777
777
778 With one arg of the form section.name, print just the value of
778 With one arg of the form section.name, print just the value of
779 that config item.
779 that config item.
780
780
781 With multiple args, print names and values of all config items
781 With multiple args, print names and values of all config items
782 with matching section names."""
782 with matching section names."""
783
783
784 untrusted = bool(opts.get('untrusted'))
784 untrusted = bool(opts.get('untrusted'))
785 if values:
785 if values:
786 if len([v for v in values if '.' in v]) > 1:
786 if len([v for v in values if '.' in v]) > 1:
787 raise util.Abort(_('only one config item permitted'))
787 raise util.Abort(_('only one config item permitted'))
788 for section, name, value in ui.walkconfig(untrusted=untrusted):
788 for section, name, value in ui.walkconfig(untrusted=untrusted):
789 sectname = section + '.' + name
789 sectname = section + '.' + name
790 if values:
790 if values:
791 for v in values:
791 for v in values:
792 if v == section:
792 if v == section:
793 ui.write('%s=%s\n' % (sectname, value))
793 ui.write('%s=%s\n' % (sectname, value))
794 elif v == sectname:
794 elif v == sectname:
795 ui.write(value, '\n')
795 ui.write(value, '\n')
796 else:
796 else:
797 ui.write('%s=%s\n' % (sectname, value))
797 ui.write('%s=%s\n' % (sectname, value))
798
798
799 def debugsetparents(ui, repo, rev1, rev2=None):
799 def debugsetparents(ui, repo, rev1, rev2=None):
800 """manually set the parents of the current working directory
800 """manually set the parents of the current working directory
801
801
802 This is useful for writing repository conversion tools, but should
802 This is useful for writing repository conversion tools, but should
803 be used with care.
803 be used with care.
804 """
804 """
805
805
806 if not rev2:
806 if not rev2:
807 rev2 = hex(nullid)
807 rev2 = hex(nullid)
808
808
809 wlock = repo.wlock()
809 wlock = repo.wlock()
810 try:
810 try:
811 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
811 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
812 finally:
812 finally:
813 del wlock
813 del wlock
814
814
815 def debugstate(ui, repo, nodates=None):
815 def debugstate(ui, repo, nodates=None):
816 """show the contents of the current dirstate"""
816 """show the contents of the current dirstate"""
817 timestr = ""
817 timestr = ""
818 showdate = not nodates
818 showdate = not nodates
819 for file_, ent in util.sort(repo.dirstate._map.iteritems()):
819 for file_, ent in util.sort(repo.dirstate._map.iteritems()):
820 if showdate:
820 if showdate:
821 if ent[3] == -1:
821 if ent[3] == -1:
822 # Pad or slice to locale representation
822 # Pad or slice to locale representation
823 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(0)))
823 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(0)))
824 timestr = 'unset'
824 timestr = 'unset'
825 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
825 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
826 else:
826 else:
827 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(ent[3]))
827 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(ent[3]))
828 if ent[1] & 020000:
828 if ent[1] & 020000:
829 mode = 'lnk'
829 mode = 'lnk'
830 else:
830 else:
831 mode = '%3o' % (ent[1] & 0777)
831 mode = '%3o' % (ent[1] & 0777)
832 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
832 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
833 for f in repo.dirstate.copies():
833 for f in repo.dirstate.copies():
834 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
834 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
835
835
836 def debugdata(ui, file_, rev):
836 def debugdata(ui, file_, rev):
837 """dump the contents of a data file revision"""
837 """dump the contents of a data file revision"""
838 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
838 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
839 try:
839 try:
840 ui.write(r.revision(r.lookup(rev)))
840 ui.write(r.revision(r.lookup(rev)))
841 except KeyError:
841 except KeyError:
842 raise util.Abort(_('invalid revision identifier %s') % rev)
842 raise util.Abort(_('invalid revision identifier %s') % rev)
843
843
844 def debugdate(ui, date, range=None, **opts):
844 def debugdate(ui, date, range=None, **opts):
845 """parse and display a date"""
845 """parse and display a date"""
846 if opts["extended"]:
846 if opts["extended"]:
847 d = util.parsedate(date, util.extendeddateformats)
847 d = util.parsedate(date, util.extendeddateformats)
848 else:
848 else:
849 d = util.parsedate(date)
849 d = util.parsedate(date)
850 ui.write("internal: %s %s\n" % d)
850 ui.write("internal: %s %s\n" % d)
851 ui.write("standard: %s\n" % util.datestr(d))
851 ui.write("standard: %s\n" % util.datestr(d))
852 if range:
852 if range:
853 m = util.matchdate(range)
853 m = util.matchdate(range)
854 ui.write("match: %s\n" % m(d[0]))
854 ui.write("match: %s\n" % m(d[0]))
855
855
856 def debugindex(ui, file_):
856 def debugindex(ui, file_):
857 """dump the contents of an index file"""
857 """dump the contents of an index file"""
858 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
858 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
859 ui.write(" rev offset length base linkrev"
859 ui.write(" rev offset length base linkrev"
860 " nodeid p1 p2\n")
860 " nodeid p1 p2\n")
861 for i in r:
861 for i in r:
862 node = r.node(i)
862 node = r.node(i)
863 try:
863 try:
864 pp = r.parents(node)
864 pp = r.parents(node)
865 except:
865 except:
866 pp = [nullid, nullid]
866 pp = [nullid, nullid]
867 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
867 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
868 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
868 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
869 short(node), short(pp[0]), short(pp[1])))
869 short(node), short(pp[0]), short(pp[1])))
870
870
871 def debugindexdot(ui, file_):
871 def debugindexdot(ui, file_):
872 """dump an index DAG as a .dot file"""
872 """dump an index DAG as a .dot file"""
873 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
873 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
874 ui.write("digraph G {\n")
874 ui.write("digraph G {\n")
875 for i in r:
875 for i in r:
876 node = r.node(i)
876 node = r.node(i)
877 pp = r.parents(node)
877 pp = r.parents(node)
878 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
878 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
879 if pp[1] != nullid:
879 if pp[1] != nullid:
880 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
880 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
881 ui.write("}\n")
881 ui.write("}\n")
882
882
883 def debuginstall(ui):
883 def debuginstall(ui):
884 '''test Mercurial installation'''
884 '''test Mercurial installation'''
885
885
886 def writetemp(contents):
886 def writetemp(contents):
887 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
887 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
888 f = os.fdopen(fd, "wb")
888 f = os.fdopen(fd, "wb")
889 f.write(contents)
889 f.write(contents)
890 f.close()
890 f.close()
891 return name
891 return name
892
892
893 problems = 0
893 problems = 0
894
894
895 # encoding
895 # encoding
896 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
896 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
897 try:
897 try:
898 encoding.fromlocal("test")
898 encoding.fromlocal("test")
899 except util.Abort, inst:
899 except util.Abort, inst:
900 ui.write(" %s\n" % inst)
900 ui.write(" %s\n" % inst)
901 ui.write(_(" (check that your locale is properly set)\n"))
901 ui.write(_(" (check that your locale is properly set)\n"))
902 problems += 1
902 problems += 1
903
903
904 # compiled modules
904 # compiled modules
905 ui.status(_("Checking extensions...\n"))
905 ui.status(_("Checking extensions...\n"))
906 try:
906 try:
907 import bdiff, mpatch, base85
907 import bdiff, mpatch, base85
908 except Exception, inst:
908 except Exception, inst:
909 ui.write(" %s\n" % inst)
909 ui.write(" %s\n" % inst)
910 ui.write(_(" One or more extensions could not be found"))
910 ui.write(_(" One or more extensions could not be found"))
911 ui.write(_(" (check that you compiled the extensions)\n"))
911 ui.write(_(" (check that you compiled the extensions)\n"))
912 problems += 1
912 problems += 1
913
913
914 # templates
914 # templates
915 ui.status(_("Checking templates...\n"))
915 ui.status(_("Checking templates...\n"))
916 try:
916 try:
917 import templater
917 import templater
918 templater.templater(templater.templatepath("map-cmdline.default"))
918 templater.templater(templater.templatepath("map-cmdline.default"))
919 except Exception, inst:
919 except Exception, inst:
920 ui.write(" %s\n" % inst)
920 ui.write(" %s\n" % inst)
921 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
921 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
922 problems += 1
922 problems += 1
923
923
924 # patch
924 # patch
925 ui.status(_("Checking patch...\n"))
925 ui.status(_("Checking patch...\n"))
926 patchproblems = 0
926 patchproblems = 0
927 a = "1\n2\n3\n4\n"
927 a = "1\n2\n3\n4\n"
928 b = "1\n2\n3\ninsert\n4\n"
928 b = "1\n2\n3\ninsert\n4\n"
929 fa = writetemp(a)
929 fa = writetemp(a)
930 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
930 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
931 os.path.basename(fa))
931 os.path.basename(fa))
932 fd = writetemp(d)
932 fd = writetemp(d)
933
933
934 files = {}
934 files = {}
935 try:
935 try:
936 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
936 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
937 except util.Abort, e:
937 except util.Abort, e:
938 ui.write(_(" patch call failed:\n"))
938 ui.write(_(" patch call failed:\n"))
939 ui.write(" " + str(e) + "\n")
939 ui.write(" " + str(e) + "\n")
940 patchproblems += 1
940 patchproblems += 1
941 else:
941 else:
942 if list(files) != [os.path.basename(fa)]:
942 if list(files) != [os.path.basename(fa)]:
943 ui.write(_(" unexpected patch output!\n"))
943 ui.write(_(" unexpected patch output!\n"))
944 patchproblems += 1
944 patchproblems += 1
945 a = file(fa).read()
945 a = file(fa).read()
946 if a != b:
946 if a != b:
947 ui.write(_(" patch test failed!\n"))
947 ui.write(_(" patch test failed!\n"))
948 patchproblems += 1
948 patchproblems += 1
949
949
950 if patchproblems:
950 if patchproblems:
951 if ui.config('ui', 'patch'):
951 if ui.config('ui', 'patch'):
952 ui.write(_(" (Current patch tool may be incompatible with patch,"
952 ui.write(_(" (Current patch tool may be incompatible with patch,"
953 " or misconfigured. Please check your .hgrc file)\n"))
953 " or misconfigured. Please check your .hgrc file)\n"))
954 else:
954 else:
955 ui.write(_(" Internal patcher failure, please report this error"
955 ui.write(_(" Internal patcher failure, please report this error"
956 " to http://www.selenic.com/mercurial/bts\n"))
956 " to http://www.selenic.com/mercurial/bts\n"))
957 problems += patchproblems
957 problems += patchproblems
958
958
959 os.unlink(fa)
959 os.unlink(fa)
960 os.unlink(fd)
960 os.unlink(fd)
961
961
962 # editor
962 # editor
963 ui.status(_("Checking commit editor...\n"))
963 ui.status(_("Checking commit editor...\n"))
964 editor = ui.geteditor()
964 editor = ui.geteditor()
965 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
965 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
966 if not cmdpath:
966 if not cmdpath:
967 if editor == 'vi':
967 if editor == 'vi':
968 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
968 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
969 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
969 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
970 else:
970 else:
971 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
971 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
972 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
972 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
973 problems += 1
973 problems += 1
974
974
975 # check username
975 # check username
976 ui.status(_("Checking username...\n"))
976 ui.status(_("Checking username...\n"))
977 user = os.environ.get("HGUSER")
977 user = os.environ.get("HGUSER")
978 if user is None:
978 if user is None:
979 user = ui.config("ui", "username")
979 user = ui.config("ui", "username")
980 if user is None:
980 if user is None:
981 user = os.environ.get("EMAIL")
981 user = os.environ.get("EMAIL")
982 if not user:
982 if not user:
983 ui.warn(" ")
983 ui.warn(" ")
984 ui.username()
984 ui.username()
985 ui.write(_(" (specify a username in your .hgrc file)\n"))
985 ui.write(_(" (specify a username in your .hgrc file)\n"))
986
986
987 if not problems:
987 if not problems:
988 ui.status(_("No problems detected\n"))
988 ui.status(_("No problems detected\n"))
989 else:
989 else:
990 ui.write(_("%s problems detected,"
990 ui.write(_("%s problems detected,"
991 " please check your install!\n") % problems)
991 " please check your install!\n") % problems)
992
992
993 return problems
993 return problems
994
994
995 def debugrename(ui, repo, file1, *pats, **opts):
995 def debugrename(ui, repo, file1, *pats, **opts):
996 """dump rename information"""
996 """dump rename information"""
997
997
998 ctx = repo[opts.get('rev')]
998 ctx = repo[opts.get('rev')]
999 m = cmdutil.match(repo, (file1,) + pats, opts)
999 m = cmdutil.match(repo, (file1,) + pats, opts)
1000 for abs in ctx.walk(m):
1000 for abs in ctx.walk(m):
1001 fctx = ctx[abs]
1001 fctx = ctx[abs]
1002 o = fctx.filelog().renamed(fctx.filenode())
1002 o = fctx.filelog().renamed(fctx.filenode())
1003 rel = m.rel(abs)
1003 rel = m.rel(abs)
1004 if o:
1004 if o:
1005 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1005 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1006 else:
1006 else:
1007 ui.write(_("%s not renamed\n") % rel)
1007 ui.write(_("%s not renamed\n") % rel)
1008
1008
1009 def debugwalk(ui, repo, *pats, **opts):
1009 def debugwalk(ui, repo, *pats, **opts):
1010 """show how files match on given patterns"""
1010 """show how files match on given patterns"""
1011 m = cmdutil.match(repo, pats, opts)
1011 m = cmdutil.match(repo, pats, opts)
1012 items = list(repo.walk(m))
1012 items = list(repo.walk(m))
1013 if not items:
1013 if not items:
1014 return
1014 return
1015 fmt = 'f %%-%ds %%-%ds %%s' % (
1015 fmt = 'f %%-%ds %%-%ds %%s' % (
1016 max([len(abs) for abs in items]),
1016 max([len(abs) for abs in items]),
1017 max([len(m.rel(abs)) for abs in items]))
1017 max([len(m.rel(abs)) for abs in items]))
1018 for abs in items:
1018 for abs in items:
1019 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1019 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1020 ui.write("%s\n" % line.rstrip())
1020 ui.write("%s\n" % line.rstrip())
1021
1021
1022 def diff(ui, repo, *pats, **opts):
1022 def diff(ui, repo, *pats, **opts):
1023 """diff repository (or selected files)
1023 """diff repository (or selected files)
1024
1024
1025 Show differences between revisions for the specified files.
1025 Show differences between revisions for the specified files.
1026
1026
1027 Differences between files are shown using the unified diff format.
1027 Differences between files are shown using the unified diff format.
1028
1028
1029 NOTE: diff may generate unexpected results for merges, as it will
1029 NOTE: diff may generate unexpected results for merges, as it will
1030 default to comparing against the working directory's first parent
1030 default to comparing against the working directory's first parent
1031 changeset if no revisions are specified.
1031 changeset if no revisions are specified.
1032
1032
1033 When two revision arguments are given, then changes are shown
1033 When two revision arguments are given, then changes are shown
1034 between those revisions. If only one revision is specified then
1034 between those revisions. If only one revision is specified then
1035 that revision is compared to the working directory, and, when no
1035 that revision is compared to the working directory, and, when no
1036 revisions are specified, the working directory files are compared
1036 revisions are specified, the working directory files are compared
1037 to its parent.
1037 to its parent.
1038
1038
1039 Without the -a/--text option, diff will avoid generating diffs of
1039 Without the -a/--text option, diff will avoid generating diffs of
1040 files it detects as binary. With -a, diff will generate a diff
1040 files it detects as binary. With -a, diff will generate a diff
1041 anyway, probably with undesirable results.
1041 anyway, probably with undesirable results.
1042
1042
1043 Use the -g/--git option to generate diffs in the git extended diff
1043 Use the -g/--git option to generate diffs in the git extended diff
1044 format. For more information, read 'hg help diffs'.
1044 format. For more information, read 'hg help diffs'.
1045 """
1045 """
1046
1046
1047 revs = opts.get('rev')
1047 revs = opts.get('rev')
1048 change = opts.get('change')
1048 change = opts.get('change')
1049
1049
1050 if revs and change:
1050 if revs and change:
1051 msg = _('cannot specify --rev and --change at the same time')
1051 msg = _('cannot specify --rev and --change at the same time')
1052 raise util.Abort(msg)
1052 raise util.Abort(msg)
1053 elif change:
1053 elif change:
1054 node2 = repo.lookup(change)
1054 node2 = repo.lookup(change)
1055 node1 = repo[node2].parents()[0].node()
1055 node1 = repo[node2].parents()[0].node()
1056 else:
1056 else:
1057 node1, node2 = cmdutil.revpair(repo, revs)
1057 node1, node2 = cmdutil.revpair(repo, revs)
1058
1058
1059 m = cmdutil.match(repo, pats, opts)
1059 m = cmdutil.match(repo, pats, opts)
1060 it = patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, opts))
1060 it = patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, opts))
1061 for chunk in it:
1061 for chunk in it:
1062 repo.ui.write(chunk)
1062 repo.ui.write(chunk)
1063
1063
1064 def export(ui, repo, *changesets, **opts):
1064 def export(ui, repo, *changesets, **opts):
1065 """dump the header and diffs for one or more changesets
1065 """dump the header and diffs for one or more changesets
1066
1066
1067 Print the changeset header and diffs for one or more revisions.
1067 Print the changeset header and diffs for one or more revisions.
1068
1068
1069 The information shown in the changeset header is: author,
1069 The information shown in the changeset header is: author,
1070 changeset hash, parent(s) and commit comment.
1070 changeset hash, parent(s) and commit comment.
1071
1071
1072 NOTE: export may generate unexpected diff output for merge
1072 NOTE: export may generate unexpected diff output for merge
1073 changesets, as it will compare the merge changeset against its
1073 changesets, as it will compare the merge changeset against its
1074 first parent only.
1074 first parent only.
1075
1075
1076 Output may be to a file, in which case the name of the file is
1076 Output may be to a file, in which case the name of the file is
1077 given using a format string. The formatting rules are as follows:
1077 given using a format string. The formatting rules are as follows:
1078
1078
1079 %% literal "%" character
1079 %% literal "%" character
1080 %H changeset hash (40 bytes of hexadecimal)
1080 %H changeset hash (40 bytes of hexadecimal)
1081 %N number of patches being generated
1081 %N number of patches being generated
1082 %R changeset revision number
1082 %R changeset revision number
1083 %b basename of the exporting repository
1083 %b basename of the exporting repository
1084 %h short-form changeset hash (12 bytes of hexadecimal)
1084 %h short-form changeset hash (12 bytes of hexadecimal)
1085 %n zero-padded sequence number, starting at 1
1085 %n zero-padded sequence number, starting at 1
1086 %r zero-padded changeset revision number
1086 %r zero-padded changeset revision number
1087
1087
1088 Without the -a/--text option, export will avoid generating diffs
1088 Without the -a/--text option, export will avoid generating diffs
1089 of files it detects as binary. With -a, export will generate a
1089 of files it detects as binary. With -a, export will generate a
1090 diff anyway, probably with undesirable results.
1090 diff anyway, probably with undesirable results.
1091
1091
1092 Use the -g/--git option to generate diffs in the git extended diff
1092 Use the -g/--git option to generate diffs in the git extended diff
1093 format. Read the diffs help topic for more information.
1093 format. Read the diffs help topic for more information.
1094
1094
1095 With the --switch-parent option, the diff will be against the
1095 With the --switch-parent option, the diff will be against the
1096 second parent. It can be useful to review a merge.
1096 second parent. It can be useful to review a merge.
1097 """
1097 """
1098 if not changesets:
1098 if not changesets:
1099 raise util.Abort(_("export requires at least one changeset"))
1099 raise util.Abort(_("export requires at least one changeset"))
1100 revs = cmdutil.revrange(repo, changesets)
1100 revs = cmdutil.revrange(repo, changesets)
1101 if len(revs) > 1:
1101 if len(revs) > 1:
1102 ui.note(_('exporting patches:\n'))
1102 ui.note(_('exporting patches:\n'))
1103 else:
1103 else:
1104 ui.note(_('exporting patch:\n'))
1104 ui.note(_('exporting patch:\n'))
1105 patch.export(repo, revs, template=opts.get('output'),
1105 patch.export(repo, revs, template=opts.get('output'),
1106 switch_parent=opts.get('switch_parent'),
1106 switch_parent=opts.get('switch_parent'),
1107 opts=patch.diffopts(ui, opts))
1107 opts=patch.diffopts(ui, opts))
1108
1108
1109 def grep(ui, repo, pattern, *pats, **opts):
1109 def grep(ui, repo, pattern, *pats, **opts):
1110 """search for a pattern in specified files and revisions
1110 """search for a pattern in specified files and revisions
1111
1111
1112 Search revisions of files for a regular expression.
1112 Search revisions of files for a regular expression.
1113
1113
1114 This command behaves differently than Unix grep. It only accepts
1114 This command behaves differently than Unix grep. It only accepts
1115 Python/Perl regexps. It searches repository history, not the
1115 Python/Perl regexps. It searches repository history, not the
1116 working directory. It always prints the revision number in which a
1116 working directory. It always prints the revision number in which a
1117 match appears.
1117 match appears.
1118
1118
1119 By default, grep only prints output for the first revision of a
1119 By default, grep only prints output for the first revision of a
1120 file in which it finds a match. To get it to print every revision
1120 file in which it finds a match. To get it to print every revision
1121 that contains a change in match status ("-" for a match that
1121 that contains a change in match status ("-" for a match that
1122 becomes a non-match, or "+" for a non-match that becomes a match),
1122 becomes a non-match, or "+" for a non-match that becomes a match),
1123 use the --all flag.
1123 use the --all flag.
1124 """
1124 """
1125 reflags = 0
1125 reflags = 0
1126 if opts.get('ignore_case'):
1126 if opts.get('ignore_case'):
1127 reflags |= re.I
1127 reflags |= re.I
1128 try:
1128 try:
1129 regexp = re.compile(pattern, reflags)
1129 regexp = re.compile(pattern, reflags)
1130 except Exception, inst:
1130 except Exception, inst:
1131 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1131 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1132 return None
1132 return None
1133 sep, eol = ':', '\n'
1133 sep, eol = ':', '\n'
1134 if opts.get('print0'):
1134 if opts.get('print0'):
1135 sep = eol = '\0'
1135 sep = eol = '\0'
1136
1136
1137 fcache = {}
1137 fcache = {}
1138 def getfile(fn):
1138 def getfile(fn):
1139 if fn not in fcache:
1139 if fn not in fcache:
1140 fcache[fn] = repo.file(fn)
1140 fcache[fn] = repo.file(fn)
1141 return fcache[fn]
1141 return fcache[fn]
1142
1142
1143 def matchlines(body):
1143 def matchlines(body):
1144 begin = 0
1144 begin = 0
1145 linenum = 0
1145 linenum = 0
1146 while True:
1146 while True:
1147 match = regexp.search(body, begin)
1147 match = regexp.search(body, begin)
1148 if not match:
1148 if not match:
1149 break
1149 break
1150 mstart, mend = match.span()
1150 mstart, mend = match.span()
1151 linenum += body.count('\n', begin, mstart) + 1
1151 linenum += body.count('\n', begin, mstart) + 1
1152 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1152 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1153 begin = body.find('\n', mend) + 1 or len(body)
1153 begin = body.find('\n', mend) + 1 or len(body)
1154 lend = begin - 1
1154 lend = begin - 1
1155 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1155 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1156
1156
1157 class linestate(object):
1157 class linestate(object):
1158 def __init__(self, line, linenum, colstart, colend):
1158 def __init__(self, line, linenum, colstart, colend):
1159 self.line = line
1159 self.line = line
1160 self.linenum = linenum
1160 self.linenum = linenum
1161 self.colstart = colstart
1161 self.colstart = colstart
1162 self.colend = colend
1162 self.colend = colend
1163
1163
1164 def __hash__(self):
1164 def __hash__(self):
1165 return hash((self.linenum, self.line))
1165 return hash((self.linenum, self.line))
1166
1166
1167 def __eq__(self, other):
1167 def __eq__(self, other):
1168 return self.line == other.line
1168 return self.line == other.line
1169
1169
1170 matches = {}
1170 matches = {}
1171 copies = {}
1171 copies = {}
1172 def grepbody(fn, rev, body):
1172 def grepbody(fn, rev, body):
1173 matches[rev].setdefault(fn, [])
1173 matches[rev].setdefault(fn, [])
1174 m = matches[rev][fn]
1174 m = matches[rev][fn]
1175 for lnum, cstart, cend, line in matchlines(body):
1175 for lnum, cstart, cend, line in matchlines(body):
1176 s = linestate(line, lnum, cstart, cend)
1176 s = linestate(line, lnum, cstart, cend)
1177 m.append(s)
1177 m.append(s)
1178
1178
1179 def difflinestates(a, b):
1179 def difflinestates(a, b):
1180 sm = difflib.SequenceMatcher(None, a, b)
1180 sm = difflib.SequenceMatcher(None, a, b)
1181 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1181 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1182 if tag == 'insert':
1182 if tag == 'insert':
1183 for i in xrange(blo, bhi):
1183 for i in xrange(blo, bhi):
1184 yield ('+', b[i])
1184 yield ('+', b[i])
1185 elif tag == 'delete':
1185 elif tag == 'delete':
1186 for i in xrange(alo, ahi):
1186 for i in xrange(alo, ahi):
1187 yield ('-', a[i])
1187 yield ('-', a[i])
1188 elif tag == 'replace':
1188 elif tag == 'replace':
1189 for i in xrange(alo, ahi):
1189 for i in xrange(alo, ahi):
1190 yield ('-', a[i])
1190 yield ('-', a[i])
1191 for i in xrange(blo, bhi):
1191 for i in xrange(blo, bhi):
1192 yield ('+', b[i])
1192 yield ('+', b[i])
1193
1193
1194 prev = {}
1194 prev = {}
1195 def display(fn, rev, states, prevstates):
1195 def display(fn, rev, states, prevstates):
1196 datefunc = ui.quiet and util.shortdate or util.datestr
1196 datefunc = ui.quiet and util.shortdate or util.datestr
1197 found = False
1197 found = False
1198 filerevmatches = {}
1198 filerevmatches = {}
1199 r = prev.get(fn, -1)
1199 r = prev.get(fn, -1)
1200 if opts.get('all'):
1200 if opts.get('all'):
1201 iter = difflinestates(states, prevstates)
1201 iter = difflinestates(states, prevstates)
1202 else:
1202 else:
1203 iter = [('', l) for l in prevstates]
1203 iter = [('', l) for l in prevstates]
1204 for change, l in iter:
1204 for change, l in iter:
1205 cols = [fn, str(r)]
1205 cols = [fn, str(r)]
1206 if opts.get('line_number'):
1206 if opts.get('line_number'):
1207 cols.append(str(l.linenum))
1207 cols.append(str(l.linenum))
1208 if opts.get('all'):
1208 if opts.get('all'):
1209 cols.append(change)
1209 cols.append(change)
1210 if opts.get('user'):
1210 if opts.get('user'):
1211 cols.append(ui.shortuser(get(r)[1]))
1211 cols.append(ui.shortuser(get(r)[1]))
1212 if opts.get('date'):
1212 if opts.get('date'):
1213 cols.append(datefunc(get(r)[2]))
1213 cols.append(datefunc(get(r)[2]))
1214 if opts.get('files_with_matches'):
1214 if opts.get('files_with_matches'):
1215 c = (fn, r)
1215 c = (fn, r)
1216 if c in filerevmatches:
1216 if c in filerevmatches:
1217 continue
1217 continue
1218 filerevmatches[c] = 1
1218 filerevmatches[c] = 1
1219 else:
1219 else:
1220 cols.append(l.line)
1220 cols.append(l.line)
1221 ui.write(sep.join(cols), eol)
1221 ui.write(sep.join(cols), eol)
1222 found = True
1222 found = True
1223 return found
1223 return found
1224
1224
1225 fstate = {}
1225 fstate = {}
1226 skip = {}
1226 skip = {}
1227 get = util.cachefunc(lambda r: repo[r].changeset())
1227 get = util.cachefunc(lambda r: repo[r].changeset())
1228 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1228 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1229 found = False
1229 found = False
1230 follow = opts.get('follow')
1230 follow = opts.get('follow')
1231 for st, rev, fns in changeiter:
1231 for st, rev, fns in changeiter:
1232 if st == 'window':
1232 if st == 'window':
1233 matches.clear()
1233 matches.clear()
1234 elif st == 'add':
1234 elif st == 'add':
1235 ctx = repo[rev]
1235 ctx = repo[rev]
1236 matches[rev] = {}
1236 matches[rev] = {}
1237 for fn in fns:
1237 for fn in fns:
1238 if fn in skip:
1238 if fn in skip:
1239 continue
1239 continue
1240 try:
1240 try:
1241 grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn)))
1241 grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn)))
1242 fstate.setdefault(fn, [])
1242 fstate.setdefault(fn, [])
1243 if follow:
1243 if follow:
1244 copied = getfile(fn).renamed(ctx.filenode(fn))
1244 copied = getfile(fn).renamed(ctx.filenode(fn))
1245 if copied:
1245 if copied:
1246 copies.setdefault(rev, {})[fn] = copied[0]
1246 copies.setdefault(rev, {})[fn] = copied[0]
1247 except error.LookupError:
1247 except error.LookupError:
1248 pass
1248 pass
1249 elif st == 'iter':
1249 elif st == 'iter':
1250 for fn, m in util.sort(matches[rev].items()):
1250 for fn, m in util.sort(matches[rev].items()):
1251 copy = copies.get(rev, {}).get(fn)
1251 copy = copies.get(rev, {}).get(fn)
1252 if fn in skip:
1252 if fn in skip:
1253 if copy:
1253 if copy:
1254 skip[copy] = True
1254 skip[copy] = True
1255 continue
1255 continue
1256 if fn in prev or fstate[fn]:
1256 if fn in prev or fstate[fn]:
1257 r = display(fn, rev, m, fstate[fn])
1257 r = display(fn, rev, m, fstate[fn])
1258 found = found or r
1258 found = found or r
1259 if r and not opts.get('all'):
1259 if r and not opts.get('all'):
1260 skip[fn] = True
1260 skip[fn] = True
1261 if copy:
1261 if copy:
1262 skip[copy] = True
1262 skip[copy] = True
1263 fstate[fn] = m
1263 fstate[fn] = m
1264 if copy:
1264 if copy:
1265 fstate[copy] = m
1265 fstate[copy] = m
1266 prev[fn] = rev
1266 prev[fn] = rev
1267
1267
1268 for fn, state in util.sort(fstate.items()):
1268 for fn, state in util.sort(fstate.items()):
1269 if fn in skip:
1269 if fn in skip:
1270 continue
1270 continue
1271 if fn not in copies.get(prev[fn], {}):
1271 if fn not in copies.get(prev[fn], {}):
1272 found = display(fn, rev, {}, state) or found
1272 found = display(fn, rev, {}, state) or found
1273 return (not found and 1) or 0
1273 return (not found and 1) or 0
1274
1274
1275 def heads(ui, repo, *branchrevs, **opts):
1275 def heads(ui, repo, *branchrevs, **opts):
1276 """show current repository heads or show branch heads
1276 """show current repository heads or show branch heads
1277
1277
1278 With no arguments, show all repository head changesets.
1278 With no arguments, show all repository head changesets.
1279
1279
1280 If branch or revisions names are given this will show the heads of
1280 If branch or revisions names are given this will show the heads of
1281 the specified branches or the branches those revisions are tagged
1281 the specified branches or the branches those revisions are tagged
1282 with.
1282 with.
1283
1283
1284 Repository "heads" are changesets that don't have child
1284 Repository "heads" are changesets that don't have child
1285 changesets. They are where development generally takes place and
1285 changesets. They are where development generally takes place and
1286 are the usual targets for update and merge operations.
1286 are the usual targets for update and merge operations.
1287
1287
1288 Branch heads are changesets that have a given branch tag, but have
1288 Branch heads are changesets that have a given branch tag, but have
1289 no child changesets with that tag. They are usually where
1289 no child changesets with that tag. They are usually where
1290 development on the given branch takes place.
1290 development on the given branch takes place.
1291 """
1291 """
1292 if opts.get('rev'):
1292 if opts.get('rev'):
1293 start = repo.lookup(opts['rev'])
1293 start = repo.lookup(opts['rev'])
1294 else:
1294 else:
1295 start = None
1295 start = None
1296 closed = not opts.get('active')
1296 closed = not opts.get('active')
1297 if not branchrevs:
1297 if not branchrevs:
1298 # Assume we're looking repo-wide heads if no revs were specified.
1298 # Assume we're looking repo-wide heads if no revs were specified.
1299 heads = repo.heads(start, closed=closed)
1299 heads = repo.heads(start, closed=closed)
1300 else:
1300 else:
1301 heads = []
1301 heads = []
1302 visitedset = util.set()
1302 visitedset = util.set()
1303 for branchrev in branchrevs:
1303 for branchrev in branchrevs:
1304 branch = repo[branchrev].branch()
1304 branch = repo[branchrev].branch()
1305 if branch in visitedset:
1305 if branch in visitedset:
1306 continue
1306 continue
1307 visitedset.add(branch)
1307 visitedset.add(branch)
1308 bheads = repo.branchheads(branch, start, closed=closed)
1308 bheads = repo.branchheads(branch, start, closed=closed)
1309 if not bheads:
1309 if not bheads:
1310 if branch != branchrev:
1310 if branch != branchrev:
1311 ui.warn(_("no changes on branch %s containing %s are "
1311 ui.warn(_("no changes on branch %s containing %s are "
1312 "reachable from %s\n")
1312 "reachable from %s\n")
1313 % (branch, branchrev, opts.get('rev')))
1313 % (branch, branchrev, opts.get('rev')))
1314 else:
1314 else:
1315 ui.warn(_("no changes on branch %s are reachable from %s\n")
1315 ui.warn(_("no changes on branch %s are reachable from %s\n")
1316 % (branch, opts.get('rev')))
1316 % (branch, opts.get('rev')))
1317 heads.extend(bheads)
1317 heads.extend(bheads)
1318 if not heads:
1318 if not heads:
1319 return 1
1319 return 1
1320 displayer = cmdutil.show_changeset(ui, repo, opts)
1320 displayer = cmdutil.show_changeset(ui, repo, opts)
1321 for n in heads:
1321 for n in heads:
1322 displayer.show(repo[n])
1322 displayer.show(repo[n])
1323
1323
1324 def help_(ui, name=None, with_version=False):
1324 def help_(ui, name=None, with_version=False):
1325 """show help for a given topic or a help overview
1325 """show help for a given topic or a help overview
1326
1326
1327 With no arguments, print a list of commands and short help.
1327 With no arguments, print a list of commands and short help.
1328
1328
1329 Given a topic, extension, or command name, print help for that
1329 Given a topic, extension, or command name, print help for that
1330 topic."""
1330 topic."""
1331 option_lists = []
1331 option_lists = []
1332
1332
1333 def addglobalopts(aliases):
1333 def addglobalopts(aliases):
1334 if ui.verbose:
1334 if ui.verbose:
1335 option_lists.append((_("global options:"), globalopts))
1335 option_lists.append((_("global options:"), globalopts))
1336 if name == 'shortlist':
1336 if name == 'shortlist':
1337 option_lists.append((_('use "hg help" for the full list '
1337 option_lists.append((_('use "hg help" for the full list '
1338 'of commands'), ()))
1338 'of commands'), ()))
1339 else:
1339 else:
1340 if name == 'shortlist':
1340 if name == 'shortlist':
1341 msg = _('use "hg help" for the full list of commands '
1341 msg = _('use "hg help" for the full list of commands '
1342 'or "hg -v" for details')
1342 'or "hg -v" for details')
1343 elif aliases:
1343 elif aliases:
1344 msg = _('use "hg -v help%s" to show aliases and '
1344 msg = _('use "hg -v help%s" to show aliases and '
1345 'global options') % (name and " " + name or "")
1345 'global options') % (name and " " + name or "")
1346 else:
1346 else:
1347 msg = _('use "hg -v help %s" to show global options') % name
1347 msg = _('use "hg -v help %s" to show global options') % name
1348 option_lists.append((msg, ()))
1348 option_lists.append((msg, ()))
1349
1349
1350 def helpcmd(name):
1350 def helpcmd(name):
1351 if with_version:
1351 if with_version:
1352 version_(ui)
1352 version_(ui)
1353 ui.write('\n')
1353 ui.write('\n')
1354
1354
1355 try:
1355 try:
1356 aliases, i = cmdutil.findcmd(name, table, False)
1356 aliases, i = cmdutil.findcmd(name, table, False)
1357 except error.AmbiguousCommand, inst:
1357 except error.AmbiguousCommand, inst:
1358 select = lambda c: c.lstrip('^').startswith(inst.args[0])
1358 select = lambda c: c.lstrip('^').startswith(inst.args[0])
1359 helplist(_('list of commands:\n\n'), select)
1359 helplist(_('list of commands:\n\n'), select)
1360 return
1360 return
1361
1361
1362 # synopsis
1362 # synopsis
1363 if len(i) > 2:
1363 if len(i) > 2:
1364 if i[2].startswith('hg'):
1364 if i[2].startswith('hg'):
1365 ui.write("%s\n" % i[2])
1365 ui.write("%s\n" % i[2])
1366 else:
1366 else:
1367 ui.write('hg %s %s\n' % (aliases[0], i[2]))
1367 ui.write('hg %s %s\n' % (aliases[0], i[2]))
1368 else:
1368 else:
1369 ui.write('hg %s\n' % aliases[0])
1369 ui.write('hg %s\n' % aliases[0])
1370
1370
1371 # aliases
1371 # aliases
1372 if not ui.quiet and len(aliases) > 1:
1372 if not ui.quiet and len(aliases) > 1:
1373 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1373 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1374
1374
1375 # description
1375 # description
1376 doc = gettext(i[0].__doc__)
1376 doc = gettext(i[0].__doc__)
1377 if not doc:
1377 if not doc:
1378 doc = _("(no help text available)")
1378 doc = _("(no help text available)")
1379 if ui.quiet:
1379 if ui.quiet:
1380 doc = doc.splitlines(0)[0]
1380 doc = doc.splitlines(0)[0]
1381 ui.write("\n%s\n" % doc.rstrip())
1381 ui.write("\n%s\n" % doc.rstrip())
1382
1382
1383 if not ui.quiet:
1383 if not ui.quiet:
1384 # options
1384 # options
1385 if i[1]:
1385 if i[1]:
1386 option_lists.append((_("options:\n"), i[1]))
1386 option_lists.append((_("options:\n"), i[1]))
1387
1387
1388 addglobalopts(False)
1388 addglobalopts(False)
1389
1389
1390 def helplist(header, select=None):
1390 def helplist(header, select=None):
1391 h = {}
1391 h = {}
1392 cmds = {}
1392 cmds = {}
1393 for c, e in table.iteritems():
1393 for c, e in table.iteritems():
1394 f = c.split("|", 1)[0]
1394 f = c.split("|", 1)[0]
1395 if select and not select(f):
1395 if select and not select(f):
1396 continue
1396 continue
1397 if (not select and name != 'shortlist' and
1397 if (not select and name != 'shortlist' and
1398 e[0].__module__ != __name__):
1398 e[0].__module__ != __name__):
1399 continue
1399 continue
1400 if name == "shortlist" and not f.startswith("^"):
1400 if name == "shortlist" and not f.startswith("^"):
1401 continue
1401 continue
1402 f = f.lstrip("^")
1402 f = f.lstrip("^")
1403 if not ui.debugflag and f.startswith("debug"):
1403 if not ui.debugflag and f.startswith("debug"):
1404 continue
1404 continue
1405 doc = gettext(e[0].__doc__)
1405 doc = gettext(e[0].__doc__)
1406 if not doc:
1406 if not doc:
1407 doc = _("(no help text available)")
1407 doc = _("(no help text available)")
1408 h[f] = doc.splitlines(0)[0].rstrip()
1408 h[f] = doc.splitlines(0)[0].rstrip()
1409 cmds[f] = c.lstrip("^")
1409 cmds[f] = c.lstrip("^")
1410
1410
1411 if not h:
1411 if not h:
1412 ui.status(_('no commands defined\n'))
1412 ui.status(_('no commands defined\n'))
1413 return
1413 return
1414
1414
1415 ui.status(header)
1415 ui.status(header)
1416 fns = util.sort(h)
1416 fns = util.sort(h)
1417 m = max(map(len, fns))
1417 m = max(map(len, fns))
1418 for f in fns:
1418 for f in fns:
1419 if ui.verbose:
1419 if ui.verbose:
1420 commands = cmds[f].replace("|",", ")
1420 commands = cmds[f].replace("|",", ")
1421 ui.write(" %s:\n %s\n"%(commands, h[f]))
1421 ui.write(" %s:\n %s\n"%(commands, h[f]))
1422 else:
1422 else:
1423 ui.write(' %-*s %s\n' % (m, f, h[f]))
1423 ui.write(' %-*s %s\n' % (m, f, h[f]))
1424
1424
1425 exts = list(extensions.extensions())
1425 exts = list(extensions.extensions())
1426 if exts and name != 'shortlist':
1426 if exts and name != 'shortlist':
1427 ui.write(_('\nenabled extensions:\n\n'))
1427 ui.write(_('\nenabled extensions:\n\n'))
1428 maxlength = 0
1428 maxlength = 0
1429 exthelps = []
1429 exthelps = []
1430 for ename, ext in exts:
1430 for ename, ext in exts:
1431 doc = (gettext(ext.__doc__) or _('(no help text available)'))
1431 doc = (gettext(ext.__doc__) or _('(no help text available)'))
1432 ename = ename.split('.')[-1]
1432 ename = ename.split('.')[-1]
1433 maxlength = max(len(ename), maxlength)
1433 maxlength = max(len(ename), maxlength)
1434 exthelps.append((ename, doc.splitlines(0)[0].strip()))
1434 exthelps.append((ename, doc.splitlines(0)[0].strip()))
1435 for ename, text in exthelps:
1435 for ename, text in exthelps:
1436 ui.write(_(' %s %s\n') % (ename.ljust(maxlength), text))
1436 ui.write(_(' %s %s\n') % (ename.ljust(maxlength), text))
1437
1437
1438 if not ui.quiet:
1438 if not ui.quiet:
1439 addglobalopts(True)
1439 addglobalopts(True)
1440
1440
1441 def helptopic(name):
1441 def helptopic(name):
1442 for names, header, doc in help.helptable:
1442 for names, header, doc in help.helptable:
1443 if name in names:
1443 if name in names:
1444 break
1444 break
1445 else:
1445 else:
1446 raise error.UnknownCommand(name)
1446 raise error.UnknownCommand(name)
1447
1447
1448 # description
1448 # description
1449 if not doc:
1449 if not doc:
1450 doc = _("(no help text available)")
1450 doc = _("(no help text available)")
1451 if callable(doc):
1451 if callable(doc):
1452 doc = doc()
1452 doc = doc()
1453
1453
1454 ui.write("%s\n" % header)
1454 ui.write("%s\n" % header)
1455 ui.write("%s\n" % doc.rstrip())
1455 ui.write("%s\n" % doc.rstrip())
1456
1456
1457 def helpext(name):
1457 def helpext(name):
1458 try:
1458 try:
1459 mod = extensions.find(name)
1459 mod = extensions.find(name)
1460 except KeyError:
1460 except KeyError:
1461 raise error.UnknownCommand(name)
1461 raise error.UnknownCommand(name)
1462
1462
1463 doc = gettext(mod.__doc__) or _('no help text available')
1463 doc = gettext(mod.__doc__) or _('no help text available')
1464 doc = doc.splitlines(0)
1464 doc = doc.splitlines(0)
1465 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1465 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1466 for d in doc[1:]:
1466 for d in doc[1:]:
1467 ui.write(d, '\n')
1467 ui.write(d, '\n')
1468
1468
1469 ui.status('\n')
1469 ui.status('\n')
1470
1470
1471 try:
1471 try:
1472 ct = mod.cmdtable
1472 ct = mod.cmdtable
1473 except AttributeError:
1473 except AttributeError:
1474 ct = {}
1474 ct = {}
1475
1475
1476 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1476 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1477 helplist(_('list of commands:\n\n'), modcmds.has_key)
1477 helplist(_('list of commands:\n\n'), modcmds.has_key)
1478
1478
1479 if name and name != 'shortlist':
1479 if name and name != 'shortlist':
1480 i = None
1480 i = None
1481 for f in (helptopic, helpcmd, helpext):
1481 for f in (helptopic, helpcmd, helpext):
1482 try:
1482 try:
1483 f(name)
1483 f(name)
1484 i = None
1484 i = None
1485 break
1485 break
1486 except error.UnknownCommand, inst:
1486 except error.UnknownCommand, inst:
1487 i = inst
1487 i = inst
1488 if i:
1488 if i:
1489 raise i
1489 raise i
1490
1490
1491 else:
1491 else:
1492 # program name
1492 # program name
1493 if ui.verbose or with_version:
1493 if ui.verbose or with_version:
1494 version_(ui)
1494 version_(ui)
1495 else:
1495 else:
1496 ui.status(_("Mercurial Distributed SCM\n"))
1496 ui.status(_("Mercurial Distributed SCM\n"))
1497 ui.status('\n')
1497 ui.status('\n')
1498
1498
1499 # list of commands
1499 # list of commands
1500 if name == "shortlist":
1500 if name == "shortlist":
1501 header = _('basic commands:\n\n')
1501 header = _('basic commands:\n\n')
1502 else:
1502 else:
1503 header = _('list of commands:\n\n')
1503 header = _('list of commands:\n\n')
1504
1504
1505 helplist(header)
1505 helplist(header)
1506
1506
1507 # list all option lists
1507 # list all option lists
1508 opt_output = []
1508 opt_output = []
1509 for title, options in option_lists:
1509 for title, options in option_lists:
1510 opt_output.append(("\n%s" % title, None))
1510 opt_output.append(("\n%s" % title, None))
1511 for shortopt, longopt, default, desc in options:
1511 for shortopt, longopt, default, desc in options:
1512 if "DEPRECATED" in desc and not ui.verbose: continue
1512 if "DEPRECATED" in desc and not ui.verbose: continue
1513 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1513 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1514 longopt and " --%s" % longopt),
1514 longopt and " --%s" % longopt),
1515 "%s%s" % (desc,
1515 "%s%s" % (desc,
1516 default
1516 default
1517 and _(" (default: %s)") % default
1517 and _(" (default: %s)") % default
1518 or "")))
1518 or "")))
1519
1519
1520 if not name:
1520 if not name:
1521 ui.write(_("\nadditional help topics:\n\n"))
1521 ui.write(_("\nadditional help topics:\n\n"))
1522 topics = []
1522 topics = []
1523 for names, header, doc in help.helptable:
1523 for names, header, doc in help.helptable:
1524 names = [(-len(name), name) for name in names]
1524 names = [(-len(name), name) for name in names]
1525 names.sort()
1525 names.sort()
1526 topics.append((names[0][1], header))
1526 topics.append((names[0][1], header))
1527 topics_len = max([len(s[0]) for s in topics])
1527 topics_len = max([len(s[0]) for s in topics])
1528 for t, desc in topics:
1528 for t, desc in topics:
1529 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1529 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1530
1530
1531 if opt_output:
1531 if opt_output:
1532 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1532 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1533 for first, second in opt_output:
1533 for first, second in opt_output:
1534 if second:
1534 if second:
1535 # wrap descriptions at 70 characters, just like the
1535 # wrap descriptions at 70 characters, just like the
1536 # main help texts
1536 # main help texts
1537 second = textwrap.wrap(second, width=70 - opts_len - 3)
1537 second = textwrap.wrap(second, width=70 - opts_len - 3)
1538 pad = '\n' + ' ' * (opts_len + 3)
1538 pad = '\n' + ' ' * (opts_len + 3)
1539 ui.write(" %-*s %s\n" % (opts_len, first, pad.join(second)))
1539 ui.write(" %-*s %s\n" % (opts_len, first, pad.join(second)))
1540 else:
1540 else:
1541 ui.write("%s\n" % first)
1541 ui.write("%s\n" % first)
1542
1542
1543 def identify(ui, repo, source=None,
1543 def identify(ui, repo, source=None,
1544 rev=None, num=None, id=None, branch=None, tags=None):
1544 rev=None, num=None, id=None, branch=None, tags=None):
1545 """identify the working copy or specified revision
1545 """identify the working copy or specified revision
1546
1546
1547 With no revision, print a summary of the current state of the
1547 With no revision, print a summary of the current state of the
1548 repository.
1548 repository.
1549
1549
1550 With a path, do a lookup in another repository.
1550 With a path, do a lookup in another repository.
1551
1551
1552 This summary identifies the repository state using one or two
1552 This summary identifies the repository state using one or two
1553 parent hash identifiers, followed by a "+" if there are
1553 parent hash identifiers, followed by a "+" if there are
1554 uncommitted changes in the working directory, a list of tags for
1554 uncommitted changes in the working directory, a list of tags for
1555 this revision and a branch name for non-default branches.
1555 this revision and a branch name for non-default branches.
1556 """
1556 """
1557
1557
1558 if not repo and not source:
1558 if not repo and not source:
1559 raise util.Abort(_("There is no Mercurial repository here "
1559 raise util.Abort(_("There is no Mercurial repository here "
1560 "(.hg not found)"))
1560 "(.hg not found)"))
1561
1561
1562 hexfunc = ui.debugflag and hex or short
1562 hexfunc = ui.debugflag and hex or short
1563 default = not (num or id or branch or tags)
1563 default = not (num or id or branch or tags)
1564 output = []
1564 output = []
1565
1565
1566 revs = []
1566 revs = []
1567 if source:
1567 if source:
1568 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1568 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1569 repo = hg.repository(ui, source)
1569 repo = hg.repository(ui, source)
1570
1570
1571 if not repo.local():
1571 if not repo.local():
1572 if not rev and revs:
1572 if not rev and revs:
1573 rev = revs[0]
1573 rev = revs[0]
1574 if not rev:
1574 if not rev:
1575 rev = "tip"
1575 rev = "tip"
1576 if num or branch or tags:
1576 if num or branch or tags:
1577 raise util.Abort(
1577 raise util.Abort(
1578 "can't query remote revision number, branch, or tags")
1578 "can't query remote revision number, branch, or tags")
1579 output = [hexfunc(repo.lookup(rev))]
1579 output = [hexfunc(repo.lookup(rev))]
1580 elif not rev:
1580 elif not rev:
1581 ctx = repo[None]
1581 ctx = repo[None]
1582 parents = ctx.parents()
1582 parents = ctx.parents()
1583 changed = False
1583 changed = False
1584 if default or id or num:
1584 if default or id or num:
1585 changed = ctx.files() + ctx.deleted()
1585 changed = ctx.files() + ctx.deleted()
1586 if default or id:
1586 if default or id:
1587 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1587 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1588 (changed) and "+" or "")]
1588 (changed) and "+" or "")]
1589 if num:
1589 if num:
1590 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1590 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1591 (changed) and "+" or ""))
1591 (changed) and "+" or ""))
1592 else:
1592 else:
1593 ctx = repo[rev]
1593 ctx = repo[rev]
1594 if default or id:
1594 if default or id:
1595 output = [hexfunc(ctx.node())]
1595 output = [hexfunc(ctx.node())]
1596 if num:
1596 if num:
1597 output.append(str(ctx.rev()))
1597 output.append(str(ctx.rev()))
1598
1598
1599 if repo.local() and default and not ui.quiet:
1599 if repo.local() and default and not ui.quiet:
1600 b = encoding.tolocal(ctx.branch())
1600 b = encoding.tolocal(ctx.branch())
1601 if b != 'default':
1601 if b != 'default':
1602 output.append("(%s)" % b)
1602 output.append("(%s)" % b)
1603
1603
1604 # multiple tags for a single parent separated by '/'
1604 # multiple tags for a single parent separated by '/'
1605 t = "/".join(ctx.tags())
1605 t = "/".join(ctx.tags())
1606 if t:
1606 if t:
1607 output.append(t)
1607 output.append(t)
1608
1608
1609 if branch:
1609 if branch:
1610 output.append(encoding.tolocal(ctx.branch()))
1610 output.append(encoding.tolocal(ctx.branch()))
1611
1611
1612 if tags:
1612 if tags:
1613 output.extend(ctx.tags())
1613 output.extend(ctx.tags())
1614
1614
1615 ui.write("%s\n" % ' '.join(output))
1615 ui.write("%s\n" % ' '.join(output))
1616
1616
1617 def import_(ui, repo, patch1, *patches, **opts):
1617 def import_(ui, repo, patch1, *patches, **opts):
1618 """import an ordered set of patches
1618 """import an ordered set of patches
1619
1619
1620 Import a list of patches and commit them individually.
1620 Import a list of patches and commit them individually.
1621
1621
1622 If there are outstanding changes in the working directory, import
1622 If there are outstanding changes in the working directory, import
1623 will abort unless given the -f/--force flag.
1623 will abort unless given the -f/--force flag.
1624
1624
1625 You can import a patch straight from a mail message. Even patches
1625 You can import a patch straight from a mail message. Even patches
1626 as attachments work (body part must be type text/plain or
1626 as attachments work (body part must be type text/plain or
1627 text/x-patch to be used). From and Subject headers of email
1627 text/x-patch to be used). From and Subject headers of email
1628 message are used as default committer and commit message. All
1628 message are used as default committer and commit message. All
1629 text/plain body parts before first diff are added to commit
1629 text/plain body parts before first diff are added to commit
1630 message.
1630 message.
1631
1631
1632 If the imported patch was generated by hg export, user and
1632 If the imported patch was generated by hg export, user and
1633 description from patch override values from message headers and
1633 description from patch override values from message headers and
1634 body. Values given on command line with -m/--message and -u/--user
1634 body. Values given on command line with -m/--message and -u/--user
1635 override these.
1635 override these.
1636
1636
1637 If --exact is specified, import will set the working directory to
1637 If --exact is specified, import will set the working directory to
1638 the parent of each patch before applying it, and will abort if the
1638 the parent of each patch before applying it, and will abort if the
1639 resulting changeset has a different ID than the one recorded in
1639 resulting changeset has a different ID than the one recorded in
1640 the patch. This may happen due to character set problems or other
1640 the patch. This may happen due to character set problems or other
1641 deficiencies in the text patch format.
1641 deficiencies in the text patch format.
1642
1642
1643 With -s/--similarity, hg will attempt to discover renames and
1643 With -s/--similarity, hg will attempt to discover renames and
1644 copies in the patch in the same way as 'addremove'.
1644 copies in the patch in the same way as 'addremove'.
1645
1645
1646 To read a patch from standard input, use patch name "-". See 'hg
1646 To read a patch from standard input, use patch name "-". See 'hg
1647 help dates' for a list of formats valid for -d/--date.
1647 help dates' for a list of formats valid for -d/--date.
1648 """
1648 """
1649 patches = (patch1,) + patches
1649 patches = (patch1,) + patches
1650
1650
1651 date = opts.get('date')
1651 date = opts.get('date')
1652 if date:
1652 if date:
1653 opts['date'] = util.parsedate(date)
1653 opts['date'] = util.parsedate(date)
1654
1654
1655 try:
1655 try:
1656 sim = float(opts.get('similarity') or 0)
1656 sim = float(opts.get('similarity') or 0)
1657 except ValueError:
1657 except ValueError:
1658 raise util.Abort(_('similarity must be a number'))
1658 raise util.Abort(_('similarity must be a number'))
1659 if sim < 0 or sim > 100:
1659 if sim < 0 or sim > 100:
1660 raise util.Abort(_('similarity must be between 0 and 100'))
1660 raise util.Abort(_('similarity must be between 0 and 100'))
1661
1661
1662 if opts.get('exact') or not opts.get('force'):
1662 if opts.get('exact') or not opts.get('force'):
1663 cmdutil.bail_if_changed(repo)
1663 cmdutil.bail_if_changed(repo)
1664
1664
1665 d = opts["base"]
1665 d = opts["base"]
1666 strip = opts["strip"]
1666 strip = opts["strip"]
1667 wlock = lock = None
1667 wlock = lock = None
1668 try:
1668 try:
1669 wlock = repo.wlock()
1669 wlock = repo.wlock()
1670 lock = repo.lock()
1670 lock = repo.lock()
1671 for p in patches:
1671 for p in patches:
1672 pf = os.path.join(d, p)
1672 pf = os.path.join(d, p)
1673
1673
1674 if pf == '-':
1674 if pf == '-':
1675 ui.status(_("applying patch from stdin\n"))
1675 ui.status(_("applying patch from stdin\n"))
1676 pf = sys.stdin
1676 pf = sys.stdin
1677 else:
1677 else:
1678 ui.status(_("applying %s\n") % p)
1678 ui.status(_("applying %s\n") % p)
1679 pf = url.open(ui, pf)
1679 pf = url.open(ui, pf)
1680 data = patch.extract(ui, pf)
1680 data = patch.extract(ui, pf)
1681 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1681 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1682
1682
1683 if tmpname is None:
1683 if tmpname is None:
1684 raise util.Abort(_('no diffs found'))
1684 raise util.Abort(_('no diffs found'))
1685
1685
1686 try:
1686 try:
1687 cmdline_message = cmdutil.logmessage(opts)
1687 cmdline_message = cmdutil.logmessage(opts)
1688 if cmdline_message:
1688 if cmdline_message:
1689 # pickup the cmdline msg
1689 # pickup the cmdline msg
1690 message = cmdline_message
1690 message = cmdline_message
1691 elif message:
1691 elif message:
1692 # pickup the patch msg
1692 # pickup the patch msg
1693 message = message.strip()
1693 message = message.strip()
1694 else:
1694 else:
1695 # launch the editor
1695 # launch the editor
1696 message = None
1696 message = None
1697 ui.debug(_('message:\n%s\n') % message)
1697 ui.debug(_('message:\n%s\n') % message)
1698
1698
1699 wp = repo.parents()
1699 wp = repo.parents()
1700 if opts.get('exact'):
1700 if opts.get('exact'):
1701 if not nodeid or not p1:
1701 if not nodeid or not p1:
1702 raise util.Abort(_('not a mercurial patch'))
1702 raise util.Abort(_('not a mercurial patch'))
1703 p1 = repo.lookup(p1)
1703 p1 = repo.lookup(p1)
1704 p2 = repo.lookup(p2 or hex(nullid))
1704 p2 = repo.lookup(p2 or hex(nullid))
1705
1705
1706 if p1 != wp[0].node():
1706 if p1 != wp[0].node():
1707 hg.clean(repo, p1)
1707 hg.clean(repo, p1)
1708 repo.dirstate.setparents(p1, p2)
1708 repo.dirstate.setparents(p1, p2)
1709 elif p2:
1709 elif p2:
1710 try:
1710 try:
1711 p1 = repo.lookup(p1)
1711 p1 = repo.lookup(p1)
1712 p2 = repo.lookup(p2)
1712 p2 = repo.lookup(p2)
1713 if p1 == wp[0].node():
1713 if p1 == wp[0].node():
1714 repo.dirstate.setparents(p1, p2)
1714 repo.dirstate.setparents(p1, p2)
1715 except error.RepoError:
1715 except error.RepoError:
1716 pass
1716 pass
1717 if opts.get('exact') or opts.get('import_branch'):
1717 if opts.get('exact') or opts.get('import_branch'):
1718 repo.dirstate.setbranch(branch or 'default')
1718 repo.dirstate.setbranch(branch or 'default')
1719
1719
1720 files = {}
1720 files = {}
1721 try:
1721 try:
1722 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1722 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1723 files=files)
1723 files=files)
1724 finally:
1724 finally:
1725 files = patch.updatedir(ui, repo, files, similarity=sim/100.)
1725 files = patch.updatedir(ui, repo, files, similarity=sim/100.)
1726 if not opts.get('no_commit'):
1726 if not opts.get('no_commit'):
1727 n = repo.commit(files, message, opts.get('user') or user,
1727 n = repo.commit(files, message, opts.get('user') or user,
1728 opts.get('date') or date)
1728 opts.get('date') or date)
1729 if opts.get('exact'):
1729 if opts.get('exact'):
1730 if hex(n) != nodeid:
1730 if hex(n) != nodeid:
1731 repo.rollback()
1731 repo.rollback()
1732 raise util.Abort(_('patch is damaged'
1732 raise util.Abort(_('patch is damaged'
1733 ' or loses information'))
1733 ' or loses information'))
1734 # Force a dirstate write so that the next transaction
1734 # Force a dirstate write so that the next transaction
1735 # backups an up-do-date file.
1735 # backups an up-do-date file.
1736 repo.dirstate.write()
1736 repo.dirstate.write()
1737 finally:
1737 finally:
1738 os.unlink(tmpname)
1738 os.unlink(tmpname)
1739 finally:
1739 finally:
1740 del lock, wlock
1740 del lock, wlock
1741
1741
1742 def incoming(ui, repo, source="default", **opts):
1742 def incoming(ui, repo, source="default", **opts):
1743 """show new changesets found in source
1743 """show new changesets found in source
1744
1744
1745 Show new changesets found in the specified path/URL or the default
1745 Show new changesets found in the specified path/URL or the default
1746 pull location. These are the changesets that would be pulled if a
1746 pull location. These are the changesets that would be pulled if a
1747 pull was requested.
1747 pull was requested.
1748
1748
1749 For remote repository, using --bundle avoids downloading the
1749 For remote repository, using --bundle avoids downloading the
1750 changesets twice if the incoming is followed by a pull.
1750 changesets twice if the incoming is followed by a pull.
1751
1751
1752 See pull for valid source format details.
1752 See pull for valid source format details.
1753 """
1753 """
1754 limit = cmdutil.loglimit(opts)
1754 limit = cmdutil.loglimit(opts)
1755 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
1755 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
1756 cmdutil.setremoteconfig(ui, opts)
1756 cmdutil.setremoteconfig(ui, opts)
1757
1757
1758 other = hg.repository(ui, source)
1758 other = hg.repository(ui, source)
1759 ui.status(_('comparing with %s\n') % url.hidepassword(source))
1759 ui.status(_('comparing with %s\n') % url.hidepassword(source))
1760 if revs:
1760 if revs:
1761 revs = [other.lookup(rev) for rev in revs]
1761 revs = [other.lookup(rev) for rev in revs]
1762 common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
1762 common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
1763 force=opts["force"])
1763 force=opts["force"])
1764 if not incoming:
1764 if not incoming:
1765 try:
1765 try:
1766 os.unlink(opts["bundle"])
1766 os.unlink(opts["bundle"])
1767 except:
1767 except:
1768 pass
1768 pass
1769 ui.status(_("no changes found\n"))
1769 ui.status(_("no changes found\n"))
1770 return 1
1770 return 1
1771
1771
1772 cleanup = None
1772 cleanup = None
1773 try:
1773 try:
1774 fname = opts["bundle"]
1774 fname = opts["bundle"]
1775 if fname or not other.local():
1775 if fname or not other.local():
1776 # create a bundle (uncompressed if other repo is not local)
1776 # create a bundle (uncompressed if other repo is not local)
1777
1777
1778 if revs is None and other.capable('changegroupsubset'):
1778 if revs is None and other.capable('changegroupsubset'):
1779 revs = rheads
1779 revs = rheads
1780
1780
1781 if revs is None:
1781 if revs is None:
1782 cg = other.changegroup(incoming, "incoming")
1782 cg = other.changegroup(incoming, "incoming")
1783 else:
1783 else:
1784 cg = other.changegroupsubset(incoming, revs, 'incoming')
1784 cg = other.changegroupsubset(incoming, revs, 'incoming')
1785 bundletype = other.local() and "HG10BZ" or "HG10UN"
1785 bundletype = other.local() and "HG10BZ" or "HG10UN"
1786 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1786 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1787 # keep written bundle?
1787 # keep written bundle?
1788 if opts["bundle"]:
1788 if opts["bundle"]:
1789 cleanup = None
1789 cleanup = None
1790 if not other.local():
1790 if not other.local():
1791 # use the created uncompressed bundlerepo
1791 # use the created uncompressed bundlerepo
1792 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1792 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1793
1793
1794 o = other.changelog.nodesbetween(incoming, revs)[0]
1794 o = other.changelog.nodesbetween(incoming, revs)[0]
1795 if opts.get('newest_first'):
1795 if opts.get('newest_first'):
1796 o.reverse()
1796 o.reverse()
1797 displayer = cmdutil.show_changeset(ui, other, opts)
1797 displayer = cmdutil.show_changeset(ui, other, opts)
1798 count = 0
1798 count = 0
1799 for n in o:
1799 for n in o:
1800 if count >= limit:
1800 if count >= limit:
1801 break
1801 break
1802 parents = [p for p in other.changelog.parents(n) if p != nullid]
1802 parents = [p for p in other.changelog.parents(n) if p != nullid]
1803 if opts.get('no_merges') and len(parents) == 2:
1803 if opts.get('no_merges') and len(parents) == 2:
1804 continue
1804 continue
1805 count += 1
1805 count += 1
1806 displayer.show(other[n])
1806 displayer.show(other[n])
1807 finally:
1807 finally:
1808 if hasattr(other, 'close'):
1808 if hasattr(other, 'close'):
1809 other.close()
1809 other.close()
1810 if cleanup:
1810 if cleanup:
1811 os.unlink(cleanup)
1811 os.unlink(cleanup)
1812
1812
1813 def init(ui, dest=".", **opts):
1813 def init(ui, dest=".", **opts):
1814 """create a new repository in the given directory
1814 """create a new repository in the given directory
1815
1815
1816 Initialize a new repository in the given directory. If the given
1816 Initialize a new repository in the given directory. If the given
1817 directory does not exist, it is created.
1817 directory does not exist, it is created.
1818
1818
1819 If no directory is given, the current directory is used.
1819 If no directory is given, the current directory is used.
1820
1820
1821 It is possible to specify an ssh:// URL as the destination.
1821 It is possible to specify an ssh:// URL as the destination.
1822 See 'hg help urls' for more information.
1822 See 'hg help urls' for more information.
1823 """
1823 """
1824 cmdutil.setremoteconfig(ui, opts)
1824 cmdutil.setremoteconfig(ui, opts)
1825 hg.repository(ui, dest, create=1)
1825 hg.repository(ui, dest, create=1)
1826
1826
1827 def locate(ui, repo, *pats, **opts):
1827 def locate(ui, repo, *pats, **opts):
1828 """locate files matching specific patterns
1828 """locate files matching specific patterns
1829
1829
1830 Print all files under Mercurial control whose names match the
1830 Print all files under Mercurial control whose names match the
1831 given patterns.
1831 given patterns.
1832
1832
1833 This command searches the entire repository by default. To search
1833 This command searches the entire repository by default. To search
1834 just the current directory and its subdirectories, use
1834 just the current directory and its subdirectories, use
1835 "--include .".
1835 "--include .".
1836
1836
1837 If no patterns are given to match, this command prints all file
1837 If no patterns are given to match, this command prints all file
1838 names.
1838 names.
1839
1839
1840 If you want to feed the output of this command into the "xargs"
1840 If you want to feed the output of this command into the "xargs"
1841 command, use the -0 option to both this command and "xargs". This
1841 command, use the -0 option to both this command and "xargs". This
1842 will avoid the problem of "xargs" treating single filenames that
1842 will avoid the problem of "xargs" treating single filenames that
1843 contain white space as multiple filenames.
1843 contain white space as multiple filenames.
1844 """
1844 """
1845 end = opts.get('print0') and '\0' or '\n'
1845 end = opts.get('print0') and '\0' or '\n'
1846 rev = opts.get('rev') or None
1846 rev = opts.get('rev') or None
1847
1847
1848 ret = 1
1848 ret = 1
1849 m = cmdutil.match(repo, pats, opts, default='relglob')
1849 m = cmdutil.match(repo, pats, opts, default='relglob')
1850 m.bad = lambda x,y: False
1850 m.bad = lambda x,y: False
1851 for abs in repo[rev].walk(m):
1851 for abs in repo[rev].walk(m):
1852 if not rev and abs not in repo.dirstate:
1852 if not rev and abs not in repo.dirstate:
1853 continue
1853 continue
1854 if opts.get('fullpath'):
1854 if opts.get('fullpath'):
1855 ui.write(repo.wjoin(abs), end)
1855 ui.write(repo.wjoin(abs), end)
1856 else:
1856 else:
1857 ui.write(((pats and m.rel(abs)) or abs), end)
1857 ui.write(((pats and m.rel(abs)) or abs), end)
1858 ret = 0
1858 ret = 0
1859
1859
1860 return ret
1860 return ret
1861
1861
1862 def log(ui, repo, *pats, **opts):
1862 def log(ui, repo, *pats, **opts):
1863 """show revision history of entire repository or files
1863 """show revision history of entire repository or files
1864
1864
1865 Print the revision history of the specified files or the entire
1865 Print the revision history of the specified files or the entire
1866 project.
1866 project.
1867
1867
1868 File history is shown without following rename or copy history of
1868 File history is shown without following rename or copy history of
1869 files. Use -f/--follow with a file name to follow history across
1869 files. Use -f/--follow with a file name to follow history across
1870 renames and copies. --follow without a file name will only show
1870 renames and copies. --follow without a file name will only show
1871 ancestors or descendants of the starting revision. --follow-first
1871 ancestors or descendants of the starting revision. --follow-first
1872 only follows the first parent of merge revisions.
1872 only follows the first parent of merge revisions.
1873
1873
1874 If no revision range is specified, the default is tip:0 unless
1874 If no revision range is specified, the default is tip:0 unless
1875 --follow is set, in which case the working directory parent is
1875 --follow is set, in which case the working directory parent is
1876 used as the starting revision.
1876 used as the starting revision.
1877
1877
1878 See 'hg help dates' for a list of formats valid for -d/--date.
1878 See 'hg help dates' for a list of formats valid for -d/--date.
1879
1879
1880 By default this command outputs: changeset id and hash, tags,
1880 By default this command outputs: changeset id and hash, tags,
1881 non-trivial parents, user, date and time, and a summary for each
1881 non-trivial parents, user, date and time, and a summary for each
1882 commit. When the -v/--verbose switch is used, the list of changed
1882 commit. When the -v/--verbose switch is used, the list of changed
1883 files and full commit message is shown.
1883 files and full commit message is shown.
1884
1884
1885 NOTE: log -p/--patch may generate unexpected diff output for merge
1885 NOTE: log -p/--patch may generate unexpected diff output for merge
1886 changesets, as it will only compare the merge changeset against
1886 changesets, as it will only compare the merge changeset against
1887 its first parent. Also, the files: list will only reflect files
1887 its first parent. Also, the files: list will only reflect files
1888 that are different from BOTH parents.
1888 that are different from BOTH parents.
1889
1889
1890 """
1890 """
1891
1891
1892 get = util.cachefunc(lambda r: repo[r].changeset())
1892 get = util.cachefunc(lambda r: repo[r].changeset())
1893 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1893 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1894
1894
1895 limit = cmdutil.loglimit(opts)
1895 limit = cmdutil.loglimit(opts)
1896 count = 0
1896 count = 0
1897
1897
1898 if opts.get('copies') and opts.get('rev'):
1898 if opts.get('copies') and opts.get('rev'):
1899 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
1899 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
1900 else:
1900 else:
1901 endrev = len(repo)
1901 endrev = len(repo)
1902 rcache = {}
1902 rcache = {}
1903 ncache = {}
1903 ncache = {}
1904 def getrenamed(fn, rev):
1904 def getrenamed(fn, rev):
1905 '''looks up all renames for a file (up to endrev) the first
1905 '''looks up all renames for a file (up to endrev) the first
1906 time the file is given. It indexes on the changerev and only
1906 time the file is given. It indexes on the changerev and only
1907 parses the manifest if linkrev != changerev.
1907 parses the manifest if linkrev != changerev.
1908 Returns rename info for fn at changerev rev.'''
1908 Returns rename info for fn at changerev rev.'''
1909 if fn not in rcache:
1909 if fn not in rcache:
1910 rcache[fn] = {}
1910 rcache[fn] = {}
1911 ncache[fn] = {}
1911 ncache[fn] = {}
1912 fl = repo.file(fn)
1912 fl = repo.file(fn)
1913 for i in fl:
1913 for i in fl:
1914 node = fl.node(i)
1914 node = fl.node(i)
1915 lr = fl.linkrev(i)
1915 lr = fl.linkrev(i)
1916 renamed = fl.renamed(node)
1916 renamed = fl.renamed(node)
1917 rcache[fn][lr] = renamed
1917 rcache[fn][lr] = renamed
1918 if renamed:
1918 if renamed:
1919 ncache[fn][node] = renamed
1919 ncache[fn][node] = renamed
1920 if lr >= endrev:
1920 if lr >= endrev:
1921 break
1921 break
1922 if rev in rcache[fn]:
1922 if rev in rcache[fn]:
1923 return rcache[fn][rev]
1923 return rcache[fn][rev]
1924
1924
1925 # If linkrev != rev (i.e. rev not found in rcache) fallback to
1925 # If linkrev != rev (i.e. rev not found in rcache) fallback to
1926 # filectx logic.
1926 # filectx logic.
1927
1927
1928 try:
1928 try:
1929 return repo[rev][fn].renamed()
1929 return repo[rev][fn].renamed()
1930 except error.LookupError:
1930 except error.LookupError:
1931 pass
1931 pass
1932 return None
1932 return None
1933
1933
1934 df = False
1934 df = False
1935 if opts["date"]:
1935 if opts["date"]:
1936 df = util.matchdate(opts["date"])
1936 df = util.matchdate(opts["date"])
1937
1937
1938 only_branches = opts.get('only_branch')
1938 only_branches = opts.get('only_branch')
1939
1939
1940 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1940 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1941 for st, rev, fns in changeiter:
1941 for st, rev, fns in changeiter:
1942 if st == 'add':
1942 if st == 'add':
1943 parents = [p for p in repo.changelog.parentrevs(rev)
1943 parents = [p for p in repo.changelog.parentrevs(rev)
1944 if p != nullrev]
1944 if p != nullrev]
1945 if opts.get('no_merges') and len(parents) == 2:
1945 if opts.get('no_merges') and len(parents) == 2:
1946 continue
1946 continue
1947 if opts.get('only_merges') and len(parents) != 2:
1947 if opts.get('only_merges') and len(parents) != 2:
1948 continue
1948 continue
1949
1949
1950 if only_branches:
1950 if only_branches:
1951 revbranch = get(rev)[5]['branch']
1951 revbranch = get(rev)[5]['branch']
1952 if revbranch not in only_branches:
1952 if revbranch not in only_branches:
1953 continue
1953 continue
1954
1954
1955 if df:
1955 if df:
1956 changes = get(rev)
1956 changes = get(rev)
1957 if not df(changes[2][0]):
1957 if not df(changes[2][0]):
1958 continue
1958 continue
1959
1959
1960 if opts.get('keyword'):
1960 if opts.get('keyword'):
1961 changes = get(rev)
1961 changes = get(rev)
1962 miss = 0
1962 miss = 0
1963 for k in [kw.lower() for kw in opts['keyword']]:
1963 for k in [kw.lower() for kw in opts['keyword']]:
1964 if not (k in changes[1].lower() or
1964 if not (k in changes[1].lower() or
1965 k in changes[4].lower() or
1965 k in changes[4].lower() or
1966 k in " ".join(changes[3]).lower()):
1966 k in " ".join(changes[3]).lower()):
1967 miss = 1
1967 miss = 1
1968 break
1968 break
1969 if miss:
1969 if miss:
1970 continue
1970 continue
1971
1971
1972 if opts['user']:
1972 if opts['user']:
1973 changes = get(rev)
1973 changes = get(rev)
1974 if not [k for k in opts['user'] if k in changes[1]]:
1974 if not [k for k in opts['user'] if k in changes[1]]:
1975 continue
1975 continue
1976
1976
1977 copies = []
1977 copies = []
1978 if opts.get('copies') and rev:
1978 if opts.get('copies') and rev:
1979 for fn in get(rev)[3]:
1979 for fn in get(rev)[3]:
1980 rename = getrenamed(fn, rev)
1980 rename = getrenamed(fn, rev)
1981 if rename:
1981 if rename:
1982 copies.append((fn, rename[0]))
1982 copies.append((fn, rename[0]))
1983 displayer.show(context.changectx(repo, rev), copies=copies)
1983 displayer.show(context.changectx(repo, rev), copies=copies)
1984 elif st == 'iter':
1984 elif st == 'iter':
1985 if count == limit: break
1985 if count == limit: break
1986 if displayer.flush(rev):
1986 if displayer.flush(rev):
1987 count += 1
1987 count += 1
1988
1988
1989 def manifest(ui, repo, node=None, rev=None):
1989 def manifest(ui, repo, node=None, rev=None):
1990 """output the current or given revision of the project manifest
1990 """output the current or given revision of the project manifest
1991
1991
1992 Print a list of version controlled files for the given revision.
1992 Print a list of version controlled files for the given revision.
1993 If no revision is given, the first parent of the working directory
1993 If no revision is given, the first parent of the working directory
1994 is used, or tip if no revision is checked out.
1994 is used, or the null revision if none is checked out.
1995
1995
1996 With -v flag, print file permissions, symlink and executable bits.
1996 With -v flag, print file permissions, symlink and executable bits.
1997 With --debug flag, print file revision hashes.
1997 With --debug flag, print file revision hashes.
1998 """
1998 """
1999
1999
2000 if rev and node:
2000 if rev and node:
2001 raise util.Abort(_("please specify just one revision"))
2001 raise util.Abort(_("please specify just one revision"))
2002
2002
2003 if not node:
2003 if not node:
2004 node = rev
2004 node = rev
2005
2005
2006 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2006 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2007 ctx = repo[node]
2007 ctx = repo[node]
2008 for f in ctx:
2008 for f in ctx:
2009 if ui.debugflag:
2009 if ui.debugflag:
2010 ui.write("%40s " % hex(ctx.manifest()[f]))
2010 ui.write("%40s " % hex(ctx.manifest()[f]))
2011 if ui.verbose:
2011 if ui.verbose:
2012 ui.write(decor[ctx.flags(f)])
2012 ui.write(decor[ctx.flags(f)])
2013 ui.write("%s\n" % f)
2013 ui.write("%s\n" % f)
2014
2014
2015 def merge(ui, repo, node=None, force=None, rev=None):
2015 def merge(ui, repo, node=None, force=None, rev=None):
2016 """merge working directory with another revision
2016 """merge working directory with another revision
2017
2017
2018 The contents of the current working directory is updated with all
2018 The contents of the current working directory is updated with all
2019 changes made in the requested revision since the last common
2019 changes made in the requested revision since the last common
2020 predecessor revision.
2020 predecessor revision.
2021
2021
2022 Files that changed between either parent are marked as changed for
2022 Files that changed between either parent are marked as changed for
2023 the next commit and a commit must be performed before any further
2023 the next commit and a commit must be performed before any further
2024 updates are allowed. The next commit has two parents.
2024 updates are allowed. The next commit has two parents.
2025
2025
2026 If no revision is specified, the working directory's parent is a
2026 If no revision is specified, the working directory's parent is a
2027 head revision, and the current branch contains exactly one other
2027 head revision, and the current branch contains exactly one other
2028 head, the other head is merged with by default. Otherwise, an
2028 head, the other head is merged with by default. Otherwise, an
2029 explicit revision to merge with must be provided.
2029 explicit revision to merge with must be provided.
2030 """
2030 """
2031
2031
2032 if rev and node:
2032 if rev and node:
2033 raise util.Abort(_("please specify just one revision"))
2033 raise util.Abort(_("please specify just one revision"))
2034 if not node:
2034 if not node:
2035 node = rev
2035 node = rev
2036
2036
2037 if not node:
2037 if not node:
2038 branch = repo.changectx(None).branch()
2038 branch = repo.changectx(None).branch()
2039 bheads = repo.branchheads(branch)
2039 bheads = repo.branchheads(branch)
2040 if len(bheads) > 2:
2040 if len(bheads) > 2:
2041 raise util.Abort(_("branch '%s' has %d heads - "
2041 raise util.Abort(_("branch '%s' has %d heads - "
2042 "please merge with an explicit rev") %
2042 "please merge with an explicit rev") %
2043 (branch, len(bheads)))
2043 (branch, len(bheads)))
2044
2044
2045 parent = repo.dirstate.parents()[0]
2045 parent = repo.dirstate.parents()[0]
2046 if len(bheads) == 1:
2046 if len(bheads) == 1:
2047 if len(repo.heads()) > 1:
2047 if len(repo.heads()) > 1:
2048 raise util.Abort(_("branch '%s' has one head - "
2048 raise util.Abort(_("branch '%s' has one head - "
2049 "please merge with an explicit rev") %
2049 "please merge with an explicit rev") %
2050 branch)
2050 branch)
2051 msg = _('there is nothing to merge')
2051 msg = _('there is nothing to merge')
2052 if parent != repo.lookup(repo[None].branch()):
2052 if parent != repo.lookup(repo[None].branch()):
2053 msg = _('%s - use "hg update" instead') % msg
2053 msg = _('%s - use "hg update" instead') % msg
2054 raise util.Abort(msg)
2054 raise util.Abort(msg)
2055
2055
2056 if parent not in bheads:
2056 if parent not in bheads:
2057 raise util.Abort(_('working dir not at a head rev - '
2057 raise util.Abort(_('working dir not at a head rev - '
2058 'use "hg update" or merge with an explicit rev'))
2058 'use "hg update" or merge with an explicit rev'))
2059 node = parent == bheads[0] and bheads[-1] or bheads[0]
2059 node = parent == bheads[0] and bheads[-1] or bheads[0]
2060 return hg.merge(repo, node, force=force)
2060 return hg.merge(repo, node, force=force)
2061
2061
2062 def outgoing(ui, repo, dest=None, **opts):
2062 def outgoing(ui, repo, dest=None, **opts):
2063 """show changesets not found in destination
2063 """show changesets not found in destination
2064
2064
2065 Show changesets not found in the specified destination repository
2065 Show changesets not found in the specified destination repository
2066 or the default push location. These are the changesets that would
2066 or the default push location. These are the changesets that would
2067 be pushed if a push was requested.
2067 be pushed if a push was requested.
2068
2068
2069 See pull for valid destination format details.
2069 See pull for valid destination format details.
2070 """
2070 """
2071 limit = cmdutil.loglimit(opts)
2071 limit = cmdutil.loglimit(opts)
2072 dest, revs, checkout = hg.parseurl(
2072 dest, revs, checkout = hg.parseurl(
2073 ui.expandpath(dest or 'default-push', dest or 'default'), opts.get('rev'))
2073 ui.expandpath(dest or 'default-push', dest or 'default'), opts.get('rev'))
2074 cmdutil.setremoteconfig(ui, opts)
2074 cmdutil.setremoteconfig(ui, opts)
2075 if revs:
2075 if revs:
2076 revs = [repo.lookup(rev) for rev in revs]
2076 revs = [repo.lookup(rev) for rev in revs]
2077
2077
2078 other = hg.repository(ui, dest)
2078 other = hg.repository(ui, dest)
2079 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2079 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2080 o = repo.findoutgoing(other, force=opts.get('force'))
2080 o = repo.findoutgoing(other, force=opts.get('force'))
2081 if not o:
2081 if not o:
2082 ui.status(_("no changes found\n"))
2082 ui.status(_("no changes found\n"))
2083 return 1
2083 return 1
2084 o = repo.changelog.nodesbetween(o, revs)[0]
2084 o = repo.changelog.nodesbetween(o, revs)[0]
2085 if opts.get('newest_first'):
2085 if opts.get('newest_first'):
2086 o.reverse()
2086 o.reverse()
2087 displayer = cmdutil.show_changeset(ui, repo, opts)
2087 displayer = cmdutil.show_changeset(ui, repo, opts)
2088 count = 0
2088 count = 0
2089 for n in o:
2089 for n in o:
2090 if count >= limit:
2090 if count >= limit:
2091 break
2091 break
2092 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2092 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2093 if opts.get('no_merges') and len(parents) == 2:
2093 if opts.get('no_merges') and len(parents) == 2:
2094 continue
2094 continue
2095 count += 1
2095 count += 1
2096 displayer.show(repo[n])
2096 displayer.show(repo[n])
2097
2097
2098 def parents(ui, repo, file_=None, **opts):
2098 def parents(ui, repo, file_=None, **opts):
2099 """show the parents of the working directory or revision
2099 """show the parents of the working directory or revision
2100
2100
2101 Print the working directory's parent revisions. If a revision is
2101 Print the working directory's parent revisions. If a revision is
2102 given via -r/--rev, the parent of that revision will be printed.
2102 given via -r/--rev, the parent of that revision will be printed.
2103 If a file argument is given, revision in which the file was last
2103 If a file argument is given, revision in which the file was last
2104 changed (before the working directory revision or the argument to
2104 changed (before the working directory revision or the argument to
2105 --rev if given) is printed.
2105 --rev if given) is printed.
2106 """
2106 """
2107 rev = opts.get('rev')
2107 rev = opts.get('rev')
2108 if rev:
2108 if rev:
2109 ctx = repo[rev]
2109 ctx = repo[rev]
2110 else:
2110 else:
2111 ctx = repo[None]
2111 ctx = repo[None]
2112
2112
2113 if file_:
2113 if file_:
2114 m = cmdutil.match(repo, (file_,), opts)
2114 m = cmdutil.match(repo, (file_,), opts)
2115 if m.anypats() or len(m.files()) != 1:
2115 if m.anypats() or len(m.files()) != 1:
2116 raise util.Abort(_('can only specify an explicit file name'))
2116 raise util.Abort(_('can only specify an explicit file name'))
2117 file_ = m.files()[0]
2117 file_ = m.files()[0]
2118 filenodes = []
2118 filenodes = []
2119 for cp in ctx.parents():
2119 for cp in ctx.parents():
2120 if not cp:
2120 if not cp:
2121 continue
2121 continue
2122 try:
2122 try:
2123 filenodes.append(cp.filenode(file_))
2123 filenodes.append(cp.filenode(file_))
2124 except error.LookupError:
2124 except error.LookupError:
2125 pass
2125 pass
2126 if not filenodes:
2126 if not filenodes:
2127 raise util.Abort(_("'%s' not found in manifest!") % file_)
2127 raise util.Abort(_("'%s' not found in manifest!") % file_)
2128 fl = repo.file(file_)
2128 fl = repo.file(file_)
2129 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2129 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2130 else:
2130 else:
2131 p = [cp.node() for cp in ctx.parents()]
2131 p = [cp.node() for cp in ctx.parents()]
2132
2132
2133 displayer = cmdutil.show_changeset(ui, repo, opts)
2133 displayer = cmdutil.show_changeset(ui, repo, opts)
2134 for n in p:
2134 for n in p:
2135 if n != nullid:
2135 if n != nullid:
2136 displayer.show(repo[n])
2136 displayer.show(repo[n])
2137
2137
2138 def paths(ui, repo, search=None):
2138 def paths(ui, repo, search=None):
2139 """show aliases for remote repositories
2139 """show aliases for remote repositories
2140
2140
2141 Show definition of symbolic path name NAME. If no name is given,
2141 Show definition of symbolic path name NAME. If no name is given,
2142 show definition of available names.
2142 show definition of available names.
2143
2143
2144 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2144 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2145 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2145 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2146
2146
2147 See 'hg help urls' for more information.
2147 See 'hg help urls' for more information.
2148 """
2148 """
2149 if search:
2149 if search:
2150 for name, path in ui.configitems("paths"):
2150 for name, path in ui.configitems("paths"):
2151 if name == search:
2151 if name == search:
2152 ui.write("%s\n" % url.hidepassword(path))
2152 ui.write("%s\n" % url.hidepassword(path))
2153 return
2153 return
2154 ui.warn(_("not found!\n"))
2154 ui.warn(_("not found!\n"))
2155 return 1
2155 return 1
2156 else:
2156 else:
2157 for name, path in ui.configitems("paths"):
2157 for name, path in ui.configitems("paths"):
2158 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2158 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2159
2159
2160 def postincoming(ui, repo, modheads, optupdate, checkout):
2160 def postincoming(ui, repo, modheads, optupdate, checkout):
2161 if modheads == 0:
2161 if modheads == 0:
2162 return
2162 return
2163 if optupdate:
2163 if optupdate:
2164 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2164 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2165 return hg.update(repo, checkout)
2165 return hg.update(repo, checkout)
2166 else:
2166 else:
2167 ui.status(_("not updating, since new heads added\n"))
2167 ui.status(_("not updating, since new heads added\n"))
2168 if modheads > 1:
2168 if modheads > 1:
2169 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2169 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2170 else:
2170 else:
2171 ui.status(_("(run 'hg update' to get a working copy)\n"))
2171 ui.status(_("(run 'hg update' to get a working copy)\n"))
2172
2172
2173 def pull(ui, repo, source="default", **opts):
2173 def pull(ui, repo, source="default", **opts):
2174 """pull changes from the specified source
2174 """pull changes from the specified source
2175
2175
2176 Pull changes from a remote repository to the local one.
2176 Pull changes from a remote repository to the local one.
2177
2177
2178 This finds all changes from the repository at the specified path
2178 This finds all changes from the repository at the specified path
2179 or URL and adds them to the local repository. By default, this
2179 or URL and adds them to the local repository. By default, this
2180 does not update the copy of the project in the working directory.
2180 does not update the copy of the project in the working directory.
2181
2181
2182 Use hg incoming if you want to see what will be added by the next
2182 Use hg incoming if you want to see what will be added by the next
2183 pull without actually adding the changes to the repository.
2183 pull without actually adding the changes to the repository.
2184
2184
2185 If SOURCE is omitted, the 'default' path will be used.
2185 If SOURCE is omitted, the 'default' path will be used.
2186 See 'hg help urls' for more information.
2186 See 'hg help urls' for more information.
2187 """
2187 """
2188 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
2188 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
2189 cmdutil.setremoteconfig(ui, opts)
2189 cmdutil.setremoteconfig(ui, opts)
2190
2190
2191 other = hg.repository(ui, source)
2191 other = hg.repository(ui, source)
2192 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2192 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2193 if revs:
2193 if revs:
2194 try:
2194 try:
2195 revs = [other.lookup(rev) for rev in revs]
2195 revs = [other.lookup(rev) for rev in revs]
2196 except error.CapabilityError:
2196 except error.CapabilityError:
2197 err = _("Other repository doesn't support revision lookup, "
2197 err = _("Other repository doesn't support revision lookup, "
2198 "so a rev cannot be specified.")
2198 "so a rev cannot be specified.")
2199 raise util.Abort(err)
2199 raise util.Abort(err)
2200
2200
2201 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2201 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2202 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2202 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2203
2203
2204 def push(ui, repo, dest=None, **opts):
2204 def push(ui, repo, dest=None, **opts):
2205 """push changes to the specified destination
2205 """push changes to the specified destination
2206
2206
2207 Push changes from the local repository to the given destination.
2207 Push changes from the local repository to the given destination.
2208
2208
2209 This is the symmetrical operation for pull. It moves changes from
2209 This is the symmetrical operation for pull. It moves changes from
2210 the current repository to a different one. If the destination is
2210 the current repository to a different one. If the destination is
2211 local this is identical to a pull in that directory from the
2211 local this is identical to a pull in that directory from the
2212 current one.
2212 current one.
2213
2213
2214 By default, push will refuse to run if it detects the result would
2214 By default, push will refuse to run if it detects the result would
2215 increase the number of remote heads. This generally indicates the
2215 increase the number of remote heads. This generally indicates the
2216 the client has forgotten to pull and merge before pushing.
2216 the client has forgotten to pull and merge before pushing.
2217
2217
2218 If -r/--rev is used, the named revision and all its ancestors will
2218 If -r/--rev is used, the named revision and all its ancestors will
2219 be pushed to the remote repository.
2219 be pushed to the remote repository.
2220
2220
2221 Look at the help text for URLs for important details about ssh://
2221 Look at the help text for URLs for important details about ssh://
2222 URLs. If DESTINATION is omitted, a default path will be used.
2222 URLs. If DESTINATION is omitted, a default path will be used.
2223 See 'hg help urls' for more information.
2223 See 'hg help urls' for more information.
2224 """
2224 """
2225 dest, revs, checkout = hg.parseurl(
2225 dest, revs, checkout = hg.parseurl(
2226 ui.expandpath(dest or 'default-push', dest or 'default'), opts.get('rev'))
2226 ui.expandpath(dest or 'default-push', dest or 'default'), opts.get('rev'))
2227 cmdutil.setremoteconfig(ui, opts)
2227 cmdutil.setremoteconfig(ui, opts)
2228
2228
2229 other = hg.repository(ui, dest)
2229 other = hg.repository(ui, dest)
2230 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2230 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2231 if revs:
2231 if revs:
2232 revs = [repo.lookup(rev) for rev in revs]
2232 revs = [repo.lookup(rev) for rev in revs]
2233 r = repo.push(other, opts.get('force'), revs=revs)
2233 r = repo.push(other, opts.get('force'), revs=revs)
2234 return r == 0
2234 return r == 0
2235
2235
2236 def rawcommit(ui, repo, *pats, **opts):
2236 def rawcommit(ui, repo, *pats, **opts):
2237 """raw commit interface (DEPRECATED)
2237 """raw commit interface (DEPRECATED)
2238
2238
2239 (DEPRECATED)
2239 (DEPRECATED)
2240 Lowlevel commit, for use in helper scripts.
2240 Lowlevel commit, for use in helper scripts.
2241
2241
2242 This command is not intended to be used by normal users, as it is
2242 This command is not intended to be used by normal users, as it is
2243 primarily useful for importing from other SCMs.
2243 primarily useful for importing from other SCMs.
2244
2244
2245 This command is now deprecated and will be removed in a future
2245 This command is now deprecated and will be removed in a future
2246 release, please use debugsetparents and commit instead.
2246 release, please use debugsetparents and commit instead.
2247 """
2247 """
2248
2248
2249 ui.warn(_("(the rawcommit command is deprecated)\n"))
2249 ui.warn(_("(the rawcommit command is deprecated)\n"))
2250
2250
2251 message = cmdutil.logmessage(opts)
2251 message = cmdutil.logmessage(opts)
2252
2252
2253 files = cmdutil.match(repo, pats, opts).files()
2253 files = cmdutil.match(repo, pats, opts).files()
2254 if opts.get('files'):
2254 if opts.get('files'):
2255 files += open(opts['files']).read().splitlines()
2255 files += open(opts['files']).read().splitlines()
2256
2256
2257 parents = [repo.lookup(p) for p in opts['parent']]
2257 parents = [repo.lookup(p) for p in opts['parent']]
2258
2258
2259 try:
2259 try:
2260 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2260 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2261 except ValueError, inst:
2261 except ValueError, inst:
2262 raise util.Abort(str(inst))
2262 raise util.Abort(str(inst))
2263
2263
2264 def recover(ui, repo):
2264 def recover(ui, repo):
2265 """roll back an interrupted transaction
2265 """roll back an interrupted transaction
2266
2266
2267 Recover from an interrupted commit or pull.
2267 Recover from an interrupted commit or pull.
2268
2268
2269 This command tries to fix the repository status after an
2269 This command tries to fix the repository status after an
2270 interrupted operation. It should only be necessary when Mercurial
2270 interrupted operation. It should only be necessary when Mercurial
2271 suggests it.
2271 suggests it.
2272 """
2272 """
2273 if repo.recover():
2273 if repo.recover():
2274 return hg.verify(repo)
2274 return hg.verify(repo)
2275 return 1
2275 return 1
2276
2276
2277 def remove(ui, repo, *pats, **opts):
2277 def remove(ui, repo, *pats, **opts):
2278 """remove the specified files on the next commit
2278 """remove the specified files on the next commit
2279
2279
2280 Schedule the indicated files for removal from the repository.
2280 Schedule the indicated files for removal from the repository.
2281
2281
2282 This only removes files from the current branch, not from the
2282 This only removes files from the current branch, not from the
2283 entire project history. -A/--after can be used to remove only
2283 entire project history. -A/--after can be used to remove only
2284 files that have already been deleted, -f/--force can be used to
2284 files that have already been deleted, -f/--force can be used to
2285 force deletion, and -Af can be used to remove files from the next
2285 force deletion, and -Af can be used to remove files from the next
2286 revision without deleting them.
2286 revision without deleting them.
2287
2287
2288 The following table details the behavior of remove for different
2288 The following table details the behavior of remove for different
2289 file states (columns) and option combinations (rows). The file
2289 file states (columns) and option combinations (rows). The file
2290 states are Added, Clean, Modified and Missing (as reported by hg
2290 states are Added, Clean, Modified and Missing (as reported by hg
2291 status). The actions are Warn, Remove (from branch) and Delete
2291 status). The actions are Warn, Remove (from branch) and Delete
2292 (from disk).
2292 (from disk).
2293
2293
2294 A C M !
2294 A C M !
2295 none W RD W R
2295 none W RD W R
2296 -f R RD RD R
2296 -f R RD RD R
2297 -A W W W R
2297 -A W W W R
2298 -Af R R R R
2298 -Af R R R R
2299
2299
2300 This command schedules the files to be removed at the next commit.
2300 This command schedules the files to be removed at the next commit.
2301 To undo a remove before that, see hg revert.
2301 To undo a remove before that, see hg revert.
2302 """
2302 """
2303
2303
2304 after, force = opts.get('after'), opts.get('force')
2304 after, force = opts.get('after'), opts.get('force')
2305 if not pats and not after:
2305 if not pats and not after:
2306 raise util.Abort(_('no files specified'))
2306 raise util.Abort(_('no files specified'))
2307
2307
2308 m = cmdutil.match(repo, pats, opts)
2308 m = cmdutil.match(repo, pats, opts)
2309 s = repo.status(match=m, clean=True)
2309 s = repo.status(match=m, clean=True)
2310 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2310 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2311
2311
2312 def warn(files, reason):
2312 def warn(files, reason):
2313 for f in files:
2313 for f in files:
2314 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2314 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2315 % (m.rel(f), reason))
2315 % (m.rel(f), reason))
2316
2316
2317 if force:
2317 if force:
2318 remove, forget = modified + deleted + clean, added
2318 remove, forget = modified + deleted + clean, added
2319 elif after:
2319 elif after:
2320 remove, forget = deleted, []
2320 remove, forget = deleted, []
2321 warn(modified + added + clean, _('still exists'))
2321 warn(modified + added + clean, _('still exists'))
2322 else:
2322 else:
2323 remove, forget = deleted + clean, []
2323 remove, forget = deleted + clean, []
2324 warn(modified, _('is modified'))
2324 warn(modified, _('is modified'))
2325 warn(added, _('has been marked for add'))
2325 warn(added, _('has been marked for add'))
2326
2326
2327 for f in util.sort(remove + forget):
2327 for f in util.sort(remove + forget):
2328 if ui.verbose or not m.exact(f):
2328 if ui.verbose or not m.exact(f):
2329 ui.status(_('removing %s\n') % m.rel(f))
2329 ui.status(_('removing %s\n') % m.rel(f))
2330
2330
2331 repo.forget(forget)
2331 repo.forget(forget)
2332 repo.remove(remove, unlink=not after)
2332 repo.remove(remove, unlink=not after)
2333
2333
2334 def rename(ui, repo, *pats, **opts):
2334 def rename(ui, repo, *pats, **opts):
2335 """rename files; equivalent of copy + remove
2335 """rename files; equivalent of copy + remove
2336
2336
2337 Mark dest as copies of sources; mark sources for deletion. If dest
2337 Mark dest as copies of sources; mark sources for deletion. If dest
2338 is a directory, copies are put in that directory. If dest is a
2338 is a directory, copies are put in that directory. If dest is a
2339 file, there can only be one source.
2339 file, there can only be one source.
2340
2340
2341 By default, this command copies the contents of files as they
2341 By default, this command copies the contents of files as they
2342 exist in the working directory. If invoked with -A/--after, the
2342 exist in the working directory. If invoked with -A/--after, the
2343 operation is recorded, but no copying is performed.
2343 operation is recorded, but no copying is performed.
2344
2344
2345 This command takes effect at the next commit. To undo a rename
2345 This command takes effect at the next commit. To undo a rename
2346 before that, see hg revert.
2346 before that, see hg revert.
2347 """
2347 """
2348 wlock = repo.wlock(False)
2348 wlock = repo.wlock(False)
2349 try:
2349 try:
2350 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2350 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2351 finally:
2351 finally:
2352 del wlock
2352 del wlock
2353
2353
2354 def resolve(ui, repo, *pats, **opts):
2354 def resolve(ui, repo, *pats, **opts):
2355 """retry file merges from a merge or update
2355 """retry file merges from a merge or update
2356
2356
2357 This command will cleanly retry unresolved file merges using file
2357 This command will cleanly retry unresolved file merges using file
2358 revisions preserved from the last update or merge. To attempt to
2358 revisions preserved from the last update or merge. To attempt to
2359 resolve all unresolved files, use the -a/--all switch.
2359 resolve all unresolved files, use the -a/--all switch.
2360
2360
2361 If a conflict is resolved manually, please note that the changes
2361 If a conflict is resolved manually, please note that the changes
2362 will be overwritten if the merge is retried with resolve. The
2362 will be overwritten if the merge is retried with resolve. The
2363 -m/--mark switch should be used to mark the file as resolved.
2363 -m/--mark switch should be used to mark the file as resolved.
2364
2364
2365 This command will also allow listing resolved files and manually
2365 This command will also allow listing resolved files and manually
2366 marking and unmarking files as resolved. All files must be marked
2366 marking and unmarking files as resolved. All files must be marked
2367 as resolved before the new commits are permitted.
2367 as resolved before the new commits are permitted.
2368
2368
2369 The codes used to show the status of files are:
2369 The codes used to show the status of files are:
2370 U = unresolved
2370 U = unresolved
2371 R = resolved
2371 R = resolved
2372 """
2372 """
2373
2373
2374 all, mark, unmark, show = [opts.get(o) for o in 'all mark unmark list'.split()]
2374 all, mark, unmark, show = [opts.get(o) for o in 'all mark unmark list'.split()]
2375
2375
2376 if (show and (mark or unmark)) or (mark and unmark):
2376 if (show and (mark or unmark)) or (mark and unmark):
2377 raise util.Abort(_("too many options specified"))
2377 raise util.Abort(_("too many options specified"))
2378 if pats and all:
2378 if pats and all:
2379 raise util.Abort(_("can't specify --all and patterns"))
2379 raise util.Abort(_("can't specify --all and patterns"))
2380 if not (all or pats or show or mark or unmark):
2380 if not (all or pats or show or mark or unmark):
2381 raise util.Abort(_('no files or directories specified; '
2381 raise util.Abort(_('no files or directories specified; '
2382 'use --all to remerge all files'))
2382 'use --all to remerge all files'))
2383
2383
2384 ms = merge_.mergestate(repo)
2384 ms = merge_.mergestate(repo)
2385 m = cmdutil.match(repo, pats, opts)
2385 m = cmdutil.match(repo, pats, opts)
2386
2386
2387 for f in ms:
2387 for f in ms:
2388 if m(f):
2388 if m(f):
2389 if show:
2389 if show:
2390 ui.write("%s %s\n" % (ms[f].upper(), f))
2390 ui.write("%s %s\n" % (ms[f].upper(), f))
2391 elif mark:
2391 elif mark:
2392 ms.mark(f, "r")
2392 ms.mark(f, "r")
2393 elif unmark:
2393 elif unmark:
2394 ms.mark(f, "u")
2394 ms.mark(f, "u")
2395 else:
2395 else:
2396 wctx = repo[None]
2396 wctx = repo[None]
2397 mctx = wctx.parents()[-1]
2397 mctx = wctx.parents()[-1]
2398
2398
2399 # backup pre-resolve (merge uses .orig for its own purposes)
2399 # backup pre-resolve (merge uses .orig for its own purposes)
2400 a = repo.wjoin(f)
2400 a = repo.wjoin(f)
2401 util.copyfile(a, a + ".resolve")
2401 util.copyfile(a, a + ".resolve")
2402
2402
2403 # resolve file
2403 # resolve file
2404 ms.resolve(f, wctx, mctx)
2404 ms.resolve(f, wctx, mctx)
2405
2405
2406 # replace filemerge's .orig file with our resolve file
2406 # replace filemerge's .orig file with our resolve file
2407 util.rename(a + ".resolve", a + ".orig")
2407 util.rename(a + ".resolve", a + ".orig")
2408
2408
2409 def revert(ui, repo, *pats, **opts):
2409 def revert(ui, repo, *pats, **opts):
2410 """restore individual files or directories to an earlier state
2410 """restore individual files or directories to an earlier state
2411
2411
2412 (use update -r to check out earlier revisions, revert does not
2412 (use update -r to check out earlier revisions, revert does not
2413 change the working directory parents)
2413 change the working directory parents)
2414
2414
2415 With no revision specified, revert the named files or directories
2415 With no revision specified, revert the named files or directories
2416 to the contents they had in the parent of the working directory.
2416 to the contents they had in the parent of the working directory.
2417 This restores the contents of the affected files to an unmodified
2417 This restores the contents of the affected files to an unmodified
2418 state and unschedules adds, removes, copies, and renames. If the
2418 state and unschedules adds, removes, copies, and renames. If the
2419 working directory has two parents, you must explicitly specify the
2419 working directory has two parents, you must explicitly specify the
2420 revision to revert to.
2420 revision to revert to.
2421
2421
2422 Using the -r/--rev option, revert the given files or directories
2422 Using the -r/--rev option, revert the given files or directories
2423 to their contents as of a specific revision. This can be helpful
2423 to their contents as of a specific revision. This can be helpful
2424 to "roll back" some or all of an earlier change. See 'hg help
2424 to "roll back" some or all of an earlier change. See 'hg help
2425 dates' for a list of formats valid for -d/--date.
2425 dates' for a list of formats valid for -d/--date.
2426
2426
2427 Revert modifies the working directory. It does not commit any
2427 Revert modifies the working directory. It does not commit any
2428 changes, or change the parent of the working directory. If you
2428 changes, or change the parent of the working directory. If you
2429 revert to a revision other than the parent of the working
2429 revert to a revision other than the parent of the working
2430 directory, the reverted files will thus appear modified
2430 directory, the reverted files will thus appear modified
2431 afterwards.
2431 afterwards.
2432
2432
2433 If a file has been deleted, it is restored. If the executable mode
2433 If a file has been deleted, it is restored. If the executable mode
2434 of a file was changed, it is reset.
2434 of a file was changed, it is reset.
2435
2435
2436 If names are given, all files matching the names are reverted.
2436 If names are given, all files matching the names are reverted.
2437 If no arguments are given, no files are reverted.
2437 If no arguments are given, no files are reverted.
2438
2438
2439 Modified files are saved with a .orig suffix before reverting.
2439 Modified files are saved with a .orig suffix before reverting.
2440 To disable these backups, use --no-backup.
2440 To disable these backups, use --no-backup.
2441 """
2441 """
2442
2442
2443 if opts["date"]:
2443 if opts["date"]:
2444 if opts["rev"]:
2444 if opts["rev"]:
2445 raise util.Abort(_("you can't specify a revision and a date"))
2445 raise util.Abort(_("you can't specify a revision and a date"))
2446 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2446 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2447
2447
2448 if not pats and not opts.get('all'):
2448 if not pats and not opts.get('all'):
2449 raise util.Abort(_('no files or directories specified; '
2449 raise util.Abort(_('no files or directories specified; '
2450 'use --all to revert the whole repo'))
2450 'use --all to revert the whole repo'))
2451
2451
2452 parent, p2 = repo.dirstate.parents()
2452 parent, p2 = repo.dirstate.parents()
2453 if not opts.get('rev') and p2 != nullid:
2453 if not opts.get('rev') and p2 != nullid:
2454 raise util.Abort(_('uncommitted merge - please provide a '
2454 raise util.Abort(_('uncommitted merge - please provide a '
2455 'specific revision'))
2455 'specific revision'))
2456 ctx = repo[opts.get('rev')]
2456 ctx = repo[opts.get('rev')]
2457 node = ctx.node()
2457 node = ctx.node()
2458 mf = ctx.manifest()
2458 mf = ctx.manifest()
2459 if node == parent:
2459 if node == parent:
2460 pmf = mf
2460 pmf = mf
2461 else:
2461 else:
2462 pmf = None
2462 pmf = None
2463
2463
2464 # need all matching names in dirstate and manifest of target rev,
2464 # need all matching names in dirstate and manifest of target rev,
2465 # so have to walk both. do not print errors if files exist in one
2465 # so have to walk both. do not print errors if files exist in one
2466 # but not other.
2466 # but not other.
2467
2467
2468 names = {}
2468 names = {}
2469
2469
2470 wlock = repo.wlock()
2470 wlock = repo.wlock()
2471 try:
2471 try:
2472 # walk dirstate.
2472 # walk dirstate.
2473
2473
2474 m = cmdutil.match(repo, pats, opts)
2474 m = cmdutil.match(repo, pats, opts)
2475 m.bad = lambda x,y: False
2475 m.bad = lambda x,y: False
2476 for abs in repo.walk(m):
2476 for abs in repo.walk(m):
2477 names[abs] = m.rel(abs), m.exact(abs)
2477 names[abs] = m.rel(abs), m.exact(abs)
2478
2478
2479 # walk target manifest.
2479 # walk target manifest.
2480
2480
2481 def badfn(path, msg):
2481 def badfn(path, msg):
2482 if path in names:
2482 if path in names:
2483 return False
2483 return False
2484 path_ = path + '/'
2484 path_ = path + '/'
2485 for f in names:
2485 for f in names:
2486 if f.startswith(path_):
2486 if f.startswith(path_):
2487 return False
2487 return False
2488 repo.ui.warn("%s: %s\n" % (m.rel(path), msg))
2488 repo.ui.warn("%s: %s\n" % (m.rel(path), msg))
2489 return False
2489 return False
2490
2490
2491 m = cmdutil.match(repo, pats, opts)
2491 m = cmdutil.match(repo, pats, opts)
2492 m.bad = badfn
2492 m.bad = badfn
2493 for abs in repo[node].walk(m):
2493 for abs in repo[node].walk(m):
2494 if abs not in names:
2494 if abs not in names:
2495 names[abs] = m.rel(abs), m.exact(abs)
2495 names[abs] = m.rel(abs), m.exact(abs)
2496
2496
2497 m = cmdutil.matchfiles(repo, names)
2497 m = cmdutil.matchfiles(repo, names)
2498 changes = repo.status(match=m)[:4]
2498 changes = repo.status(match=m)[:4]
2499 modified, added, removed, deleted = map(dict.fromkeys, changes)
2499 modified, added, removed, deleted = map(dict.fromkeys, changes)
2500
2500
2501 # if f is a rename, also revert the source
2501 # if f is a rename, also revert the source
2502 cwd = repo.getcwd()
2502 cwd = repo.getcwd()
2503 for f in added:
2503 for f in added:
2504 src = repo.dirstate.copied(f)
2504 src = repo.dirstate.copied(f)
2505 if src and src not in names and repo.dirstate[src] == 'r':
2505 if src and src not in names and repo.dirstate[src] == 'r':
2506 removed[src] = None
2506 removed[src] = None
2507 names[src] = (repo.pathto(src, cwd), True)
2507 names[src] = (repo.pathto(src, cwd), True)
2508
2508
2509 def removeforget(abs):
2509 def removeforget(abs):
2510 if repo.dirstate[abs] == 'a':
2510 if repo.dirstate[abs] == 'a':
2511 return _('forgetting %s\n')
2511 return _('forgetting %s\n')
2512 return _('removing %s\n')
2512 return _('removing %s\n')
2513
2513
2514 revert = ([], _('reverting %s\n'))
2514 revert = ([], _('reverting %s\n'))
2515 add = ([], _('adding %s\n'))
2515 add = ([], _('adding %s\n'))
2516 remove = ([], removeforget)
2516 remove = ([], removeforget)
2517 undelete = ([], _('undeleting %s\n'))
2517 undelete = ([], _('undeleting %s\n'))
2518
2518
2519 disptable = (
2519 disptable = (
2520 # dispatch table:
2520 # dispatch table:
2521 # file state
2521 # file state
2522 # action if in target manifest
2522 # action if in target manifest
2523 # action if not in target manifest
2523 # action if not in target manifest
2524 # make backup if in target manifest
2524 # make backup if in target manifest
2525 # make backup if not in target manifest
2525 # make backup if not in target manifest
2526 (modified, revert, remove, True, True),
2526 (modified, revert, remove, True, True),
2527 (added, revert, remove, True, False),
2527 (added, revert, remove, True, False),
2528 (removed, undelete, None, False, False),
2528 (removed, undelete, None, False, False),
2529 (deleted, revert, remove, False, False),
2529 (deleted, revert, remove, False, False),
2530 )
2530 )
2531
2531
2532 for abs, (rel, exact) in util.sort(names.items()):
2532 for abs, (rel, exact) in util.sort(names.items()):
2533 mfentry = mf.get(abs)
2533 mfentry = mf.get(abs)
2534 target = repo.wjoin(abs)
2534 target = repo.wjoin(abs)
2535 def handle(xlist, dobackup):
2535 def handle(xlist, dobackup):
2536 xlist[0].append(abs)
2536 xlist[0].append(abs)
2537 if dobackup and not opts.get('no_backup') and util.lexists(target):
2537 if dobackup and not opts.get('no_backup') and util.lexists(target):
2538 bakname = "%s.orig" % rel
2538 bakname = "%s.orig" % rel
2539 ui.note(_('saving current version of %s as %s\n') %
2539 ui.note(_('saving current version of %s as %s\n') %
2540 (rel, bakname))
2540 (rel, bakname))
2541 if not opts.get('dry_run'):
2541 if not opts.get('dry_run'):
2542 util.copyfile(target, bakname)
2542 util.copyfile(target, bakname)
2543 if ui.verbose or not exact:
2543 if ui.verbose or not exact:
2544 msg = xlist[1]
2544 msg = xlist[1]
2545 if not isinstance(msg, basestring):
2545 if not isinstance(msg, basestring):
2546 msg = msg(abs)
2546 msg = msg(abs)
2547 ui.status(msg % rel)
2547 ui.status(msg % rel)
2548 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2548 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2549 if abs not in table: continue
2549 if abs not in table: continue
2550 # file has changed in dirstate
2550 # file has changed in dirstate
2551 if mfentry:
2551 if mfentry:
2552 handle(hitlist, backuphit)
2552 handle(hitlist, backuphit)
2553 elif misslist is not None:
2553 elif misslist is not None:
2554 handle(misslist, backupmiss)
2554 handle(misslist, backupmiss)
2555 break
2555 break
2556 else:
2556 else:
2557 if abs not in repo.dirstate:
2557 if abs not in repo.dirstate:
2558 if mfentry:
2558 if mfentry:
2559 handle(add, True)
2559 handle(add, True)
2560 elif exact:
2560 elif exact:
2561 ui.warn(_('file not managed: %s\n') % rel)
2561 ui.warn(_('file not managed: %s\n') % rel)
2562 continue
2562 continue
2563 # file has not changed in dirstate
2563 # file has not changed in dirstate
2564 if node == parent:
2564 if node == parent:
2565 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2565 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2566 continue
2566 continue
2567 if pmf is None:
2567 if pmf is None:
2568 # only need parent manifest in this unlikely case,
2568 # only need parent manifest in this unlikely case,
2569 # so do not read by default
2569 # so do not read by default
2570 pmf = repo[parent].manifest()
2570 pmf = repo[parent].manifest()
2571 if abs in pmf:
2571 if abs in pmf:
2572 if mfentry:
2572 if mfentry:
2573 # if version of file is same in parent and target
2573 # if version of file is same in parent and target
2574 # manifests, do nothing
2574 # manifests, do nothing
2575 if (pmf[abs] != mfentry or
2575 if (pmf[abs] != mfentry or
2576 pmf.flags(abs) != mf.flags(abs)):
2576 pmf.flags(abs) != mf.flags(abs)):
2577 handle(revert, False)
2577 handle(revert, False)
2578 else:
2578 else:
2579 handle(remove, False)
2579 handle(remove, False)
2580
2580
2581 if not opts.get('dry_run'):
2581 if not opts.get('dry_run'):
2582 def checkout(f):
2582 def checkout(f):
2583 fc = ctx[f]
2583 fc = ctx[f]
2584 repo.wwrite(f, fc.data(), fc.flags())
2584 repo.wwrite(f, fc.data(), fc.flags())
2585
2585
2586 audit_path = util.path_auditor(repo.root)
2586 audit_path = util.path_auditor(repo.root)
2587 for f in remove[0]:
2587 for f in remove[0]:
2588 if repo.dirstate[f] == 'a':
2588 if repo.dirstate[f] == 'a':
2589 repo.dirstate.forget(f)
2589 repo.dirstate.forget(f)
2590 continue
2590 continue
2591 audit_path(f)
2591 audit_path(f)
2592 try:
2592 try:
2593 util.unlink(repo.wjoin(f))
2593 util.unlink(repo.wjoin(f))
2594 except OSError:
2594 except OSError:
2595 pass
2595 pass
2596 repo.dirstate.remove(f)
2596 repo.dirstate.remove(f)
2597
2597
2598 normal = None
2598 normal = None
2599 if node == parent:
2599 if node == parent:
2600 # We're reverting to our parent. If possible, we'd like status
2600 # We're reverting to our parent. If possible, we'd like status
2601 # to report the file as clean. We have to use normallookup for
2601 # to report the file as clean. We have to use normallookup for
2602 # merges to avoid losing information about merged/dirty files.
2602 # merges to avoid losing information about merged/dirty files.
2603 if p2 != nullid:
2603 if p2 != nullid:
2604 normal = repo.dirstate.normallookup
2604 normal = repo.dirstate.normallookup
2605 else:
2605 else:
2606 normal = repo.dirstate.normal
2606 normal = repo.dirstate.normal
2607 for f in revert[0]:
2607 for f in revert[0]:
2608 checkout(f)
2608 checkout(f)
2609 if normal:
2609 if normal:
2610 normal(f)
2610 normal(f)
2611
2611
2612 for f in add[0]:
2612 for f in add[0]:
2613 checkout(f)
2613 checkout(f)
2614 repo.dirstate.add(f)
2614 repo.dirstate.add(f)
2615
2615
2616 normal = repo.dirstate.normallookup
2616 normal = repo.dirstate.normallookup
2617 if node == parent and p2 == nullid:
2617 if node == parent and p2 == nullid:
2618 normal = repo.dirstate.normal
2618 normal = repo.dirstate.normal
2619 for f in undelete[0]:
2619 for f in undelete[0]:
2620 checkout(f)
2620 checkout(f)
2621 normal(f)
2621 normal(f)
2622
2622
2623 finally:
2623 finally:
2624 del wlock
2624 del wlock
2625
2625
2626 def rollback(ui, repo):
2626 def rollback(ui, repo):
2627 """roll back the last transaction
2627 """roll back the last transaction
2628
2628
2629 This command should be used with care. There is only one level of
2629 This command should be used with care. There is only one level of
2630 rollback, and there is no way to undo a rollback. It will also
2630 rollback, and there is no way to undo a rollback. It will also
2631 restore the dirstate at the time of the last transaction, losing
2631 restore the dirstate at the time of the last transaction, losing
2632 any dirstate changes since that time.
2632 any dirstate changes since that time.
2633
2633
2634 Transactions are used to encapsulate the effects of all commands
2634 Transactions are used to encapsulate the effects of all commands
2635 that create new changesets or propagate existing changesets into a
2635 that create new changesets or propagate existing changesets into a
2636 repository. For example, the following commands are transactional,
2636 repository. For example, the following commands are transactional,
2637 and their effects can be rolled back:
2637 and their effects can be rolled back:
2638
2638
2639 commit
2639 commit
2640 import
2640 import
2641 pull
2641 pull
2642 push (with this repository as destination)
2642 push (with this repository as destination)
2643 unbundle
2643 unbundle
2644
2644
2645 This command is not intended for use on public repositories. Once
2645 This command is not intended for use on public repositories. Once
2646 changes are visible for pull by other users, rolling a transaction
2646 changes are visible for pull by other users, rolling a transaction
2647 back locally is ineffective (someone else may already have pulled
2647 back locally is ineffective (someone else may already have pulled
2648 the changes). Furthermore, a race is possible with readers of the
2648 the changes). Furthermore, a race is possible with readers of the
2649 repository; for example an in-progress pull from the repository
2649 repository; for example an in-progress pull from the repository
2650 may fail if a rollback is performed.
2650 may fail if a rollback is performed.
2651 """
2651 """
2652 repo.rollback()
2652 repo.rollback()
2653
2653
2654 def root(ui, repo):
2654 def root(ui, repo):
2655 """print the root (top) of the current working directory
2655 """print the root (top) of the current working directory
2656
2656
2657 Print the root directory of the current repository.
2657 Print the root directory of the current repository.
2658 """
2658 """
2659 ui.write(repo.root + "\n")
2659 ui.write(repo.root + "\n")
2660
2660
2661 def serve(ui, repo, **opts):
2661 def serve(ui, repo, **opts):
2662 """export the repository via HTTP
2662 """export the repository via HTTP
2663
2663
2664 Start a local HTTP repository browser and pull server.
2664 Start a local HTTP repository browser and pull server.
2665
2665
2666 By default, the server logs accesses to stdout and errors to
2666 By default, the server logs accesses to stdout and errors to
2667 stderr. Use the -A and -E options to log to files.
2667 stderr. Use the -A and -E options to log to files.
2668 """
2668 """
2669
2669
2670 if opts["stdio"]:
2670 if opts["stdio"]:
2671 if repo is None:
2671 if repo is None:
2672 raise error.RepoError(_("There is no Mercurial repository here"
2672 raise error.RepoError(_("There is no Mercurial repository here"
2673 " (.hg not found)"))
2673 " (.hg not found)"))
2674 s = sshserver.sshserver(ui, repo)
2674 s = sshserver.sshserver(ui, repo)
2675 s.serve_forever()
2675 s.serve_forever()
2676
2676
2677 parentui = ui.parentui or ui
2677 parentui = ui.parentui or ui
2678 optlist = ("name templates style address port prefix ipv6"
2678 optlist = ("name templates style address port prefix ipv6"
2679 " accesslog errorlog webdir_conf certificate")
2679 " accesslog errorlog webdir_conf certificate")
2680 for o in optlist.split():
2680 for o in optlist.split():
2681 if opts[o]:
2681 if opts[o]:
2682 parentui.setconfig("web", o, str(opts[o]))
2682 parentui.setconfig("web", o, str(opts[o]))
2683 if (repo is not None) and (repo.ui != parentui):
2683 if (repo is not None) and (repo.ui != parentui):
2684 repo.ui.setconfig("web", o, str(opts[o]))
2684 repo.ui.setconfig("web", o, str(opts[o]))
2685
2685
2686 if repo is None and not ui.config("web", "webdir_conf"):
2686 if repo is None and not ui.config("web", "webdir_conf"):
2687 raise error.RepoError(_("There is no Mercurial repository here"
2687 raise error.RepoError(_("There is no Mercurial repository here"
2688 " (.hg not found)"))
2688 " (.hg not found)"))
2689
2689
2690 class service:
2690 class service:
2691 def init(self):
2691 def init(self):
2692 util.set_signal_handler()
2692 util.set_signal_handler()
2693 self.httpd = hgweb.server.create_server(parentui, repo)
2693 self.httpd = hgweb.server.create_server(parentui, repo)
2694
2694
2695 if not ui.verbose: return
2695 if not ui.verbose: return
2696
2696
2697 if self.httpd.prefix:
2697 if self.httpd.prefix:
2698 prefix = self.httpd.prefix.strip('/') + '/'
2698 prefix = self.httpd.prefix.strip('/') + '/'
2699 else:
2699 else:
2700 prefix = ''
2700 prefix = ''
2701
2701
2702 port = ':%d' % self.httpd.port
2702 port = ':%d' % self.httpd.port
2703 if port == ':80':
2703 if port == ':80':
2704 port = ''
2704 port = ''
2705
2705
2706 bindaddr = self.httpd.addr
2706 bindaddr = self.httpd.addr
2707 if bindaddr == '0.0.0.0':
2707 if bindaddr == '0.0.0.0':
2708 bindaddr = '*'
2708 bindaddr = '*'
2709 elif ':' in bindaddr: # IPv6
2709 elif ':' in bindaddr: # IPv6
2710 bindaddr = '[%s]' % bindaddr
2710 bindaddr = '[%s]' % bindaddr
2711
2711
2712 fqaddr = self.httpd.fqaddr
2712 fqaddr = self.httpd.fqaddr
2713 if ':' in fqaddr:
2713 if ':' in fqaddr:
2714 fqaddr = '[%s]' % fqaddr
2714 fqaddr = '[%s]' % fqaddr
2715 ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2715 ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2716 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2716 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2717
2717
2718 def run(self):
2718 def run(self):
2719 self.httpd.serve_forever()
2719 self.httpd.serve_forever()
2720
2720
2721 service = service()
2721 service = service()
2722
2722
2723 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2723 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2724
2724
2725 def status(ui, repo, *pats, **opts):
2725 def status(ui, repo, *pats, **opts):
2726 """show changed files in the working directory
2726 """show changed files in the working directory
2727
2727
2728 Show status of files in the repository. If names are given, only
2728 Show status of files in the repository. If names are given, only
2729 files that match are shown. Files that are clean or ignored or
2729 files that match are shown. Files that are clean or ignored or
2730 source of a copy/move operation, are not listed unless -c/--clean,
2730 source of a copy/move operation, are not listed unless -c/--clean,
2731 -i/--ignored, -C/--copies or -A/--all is given. Unless options
2731 -i/--ignored, -C/--copies or -A/--all is given. Unless options
2732 described with "show only ..." are given, the options -mardu are
2732 described with "show only ..." are given, the options -mardu are
2733 used.
2733 used.
2734
2734
2735 Option -q/--quiet hides untracked (unknown and ignored) files
2735 Option -q/--quiet hides untracked (unknown and ignored) files
2736 unless explicitly requested with -u/--unknown or -i/--ignored.
2736 unless explicitly requested with -u/--unknown or -i/--ignored.
2737
2737
2738 NOTE: status may appear to disagree with diff if permissions have
2738 NOTE: status may appear to disagree with diff if permissions have
2739 changed or a merge has occurred. The standard diff format does not
2739 changed or a merge has occurred. The standard diff format does not
2740 report permission changes and diff only reports changes relative
2740 report permission changes and diff only reports changes relative
2741 to one merge parent.
2741 to one merge parent.
2742
2742
2743 If one revision is given, it is used as the base revision.
2743 If one revision is given, it is used as the base revision.
2744 If two revisions are given, the difference between them is shown.
2744 If two revisions are given, the difference between them is shown.
2745
2745
2746 The codes used to show the status of files are:
2746 The codes used to show the status of files are:
2747 M = modified
2747 M = modified
2748 A = added
2748 A = added
2749 R = removed
2749 R = removed
2750 C = clean
2750 C = clean
2751 ! = missing (deleted by non-hg command, but still tracked)
2751 ! = missing (deleted by non-hg command, but still tracked)
2752 ? = not tracked
2752 ? = not tracked
2753 I = ignored
2753 I = ignored
2754 = the previous added file was copied from here
2754 = the previous added file was copied from here
2755 """
2755 """
2756
2756
2757 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2757 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2758 cwd = (pats and repo.getcwd()) or ''
2758 cwd = (pats and repo.getcwd()) or ''
2759 end = opts.get('print0') and '\0' or '\n'
2759 end = opts.get('print0') and '\0' or '\n'
2760 copy = {}
2760 copy = {}
2761 states = 'modified added removed deleted unknown ignored clean'.split()
2761 states = 'modified added removed deleted unknown ignored clean'.split()
2762 show = [k for k in states if opts.get(k)]
2762 show = [k for k in states if opts.get(k)]
2763 if opts.get('all'):
2763 if opts.get('all'):
2764 show += ui.quiet and (states[:4] + ['clean']) or states
2764 show += ui.quiet and (states[:4] + ['clean']) or states
2765 if not show:
2765 if not show:
2766 show = ui.quiet and states[:4] or states[:5]
2766 show = ui.quiet and states[:4] or states[:5]
2767
2767
2768 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
2768 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
2769 'ignored' in show, 'clean' in show, 'unknown' in show)
2769 'ignored' in show, 'clean' in show, 'unknown' in show)
2770 changestates = zip(states, 'MAR!?IC', stat)
2770 changestates = zip(states, 'MAR!?IC', stat)
2771
2771
2772 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
2772 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
2773 ctxn = repo[nullid]
2773 ctxn = repo[nullid]
2774 ctx1 = repo[node1]
2774 ctx1 = repo[node1]
2775 ctx2 = repo[node2]
2775 ctx2 = repo[node2]
2776 added = stat[1]
2776 added = stat[1]
2777 if node2 is None:
2777 if node2 is None:
2778 added = stat[0] + stat[1] # merged?
2778 added = stat[0] + stat[1] # merged?
2779
2779
2780 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
2780 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
2781 if k in added:
2781 if k in added:
2782 copy[k] = v
2782 copy[k] = v
2783 elif v in added:
2783 elif v in added:
2784 copy[v] = k
2784 copy[v] = k
2785
2785
2786 for state, char, files in changestates:
2786 for state, char, files in changestates:
2787 if state in show:
2787 if state in show:
2788 format = "%s %%s%s" % (char, end)
2788 format = "%s %%s%s" % (char, end)
2789 if opts.get('no_status'):
2789 if opts.get('no_status'):
2790 format = "%%s%s" % end
2790 format = "%%s%s" % end
2791
2791
2792 for f in files:
2792 for f in files:
2793 ui.write(format % repo.pathto(f, cwd))
2793 ui.write(format % repo.pathto(f, cwd))
2794 if f in copy:
2794 if f in copy:
2795 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2795 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2796
2796
2797 def tag(ui, repo, name1, *names, **opts):
2797 def tag(ui, repo, name1, *names, **opts):
2798 """add one or more tags for the current or given revision
2798 """add one or more tags for the current or given revision
2799
2799
2800 Name a particular revision using <name>.
2800 Name a particular revision using <name>.
2801
2801
2802 Tags are used to name particular revisions of the repository and are
2802 Tags are used to name particular revisions of the repository and are
2803 very useful to compare different revisions, to go back to significant
2803 very useful to compare different revisions, to go back to significant
2804 earlier versions or to mark branch points as releases, etc.
2804 earlier versions or to mark branch points as releases, etc.
2805
2805
2806 If no revision is given, the parent of the working directory is
2806 If no revision is given, the parent of the working directory is
2807 used, or tip if no revision is checked out.
2807 used, or tip if no revision is checked out.
2808
2808
2809 To facilitate version control, distribution, and merging of tags,
2809 To facilitate version control, distribution, and merging of tags,
2810 they are stored as a file named ".hgtags" which is managed
2810 they are stored as a file named ".hgtags" which is managed
2811 similarly to other project files and can be hand-edited if
2811 similarly to other project files and can be hand-edited if
2812 necessary. The file '.hg/localtags' is used for local tags (not
2812 necessary. The file '.hg/localtags' is used for local tags (not
2813 shared among repositories).
2813 shared among repositories).
2814
2814
2815 See 'hg help dates' for a list of formats valid for -d/--date.
2815 See 'hg help dates' for a list of formats valid for -d/--date.
2816 """
2816 """
2817
2817
2818 rev_ = "."
2818 rev_ = "."
2819 names = (name1,) + names
2819 names = (name1,) + names
2820 if len(names) != len(dict.fromkeys(names)):
2820 if len(names) != len(dict.fromkeys(names)):
2821 raise util.Abort(_('tag names must be unique'))
2821 raise util.Abort(_('tag names must be unique'))
2822 for n in names:
2822 for n in names:
2823 if n in ['tip', '.', 'null']:
2823 if n in ['tip', '.', 'null']:
2824 raise util.Abort(_('the name \'%s\' is reserved') % n)
2824 raise util.Abort(_('the name \'%s\' is reserved') % n)
2825 if opts.get('rev') and opts.get('remove'):
2825 if opts.get('rev') and opts.get('remove'):
2826 raise util.Abort(_("--rev and --remove are incompatible"))
2826 raise util.Abort(_("--rev and --remove are incompatible"))
2827 if opts.get('rev'):
2827 if opts.get('rev'):
2828 rev_ = opts['rev']
2828 rev_ = opts['rev']
2829 message = opts.get('message')
2829 message = opts.get('message')
2830 if opts.get('remove'):
2830 if opts.get('remove'):
2831 expectedtype = opts.get('local') and 'local' or 'global'
2831 expectedtype = opts.get('local') and 'local' or 'global'
2832 for n in names:
2832 for n in names:
2833 if not repo.tagtype(n):
2833 if not repo.tagtype(n):
2834 raise util.Abort(_('tag \'%s\' does not exist') % n)
2834 raise util.Abort(_('tag \'%s\' does not exist') % n)
2835 if repo.tagtype(n) != expectedtype:
2835 if repo.tagtype(n) != expectedtype:
2836 if expectedtype == 'global':
2836 if expectedtype == 'global':
2837 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
2837 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
2838 else:
2838 else:
2839 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
2839 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
2840 rev_ = nullid
2840 rev_ = nullid
2841 if not message:
2841 if not message:
2842 message = _('Removed tag %s') % ', '.join(names)
2842 message = _('Removed tag %s') % ', '.join(names)
2843 elif not opts.get('force'):
2843 elif not opts.get('force'):
2844 for n in names:
2844 for n in names:
2845 if n in repo.tags():
2845 if n in repo.tags():
2846 raise util.Abort(_('tag \'%s\' already exists '
2846 raise util.Abort(_('tag \'%s\' already exists '
2847 '(use -f to force)') % n)
2847 '(use -f to force)') % n)
2848 if not rev_ and repo.dirstate.parents()[1] != nullid:
2848 if not rev_ and repo.dirstate.parents()[1] != nullid:
2849 raise util.Abort(_('uncommitted merge - please provide a '
2849 raise util.Abort(_('uncommitted merge - please provide a '
2850 'specific revision'))
2850 'specific revision'))
2851 r = repo[rev_].node()
2851 r = repo[rev_].node()
2852
2852
2853 if not message:
2853 if not message:
2854 message = (_('Added tag %s for changeset %s') %
2854 message = (_('Added tag %s for changeset %s') %
2855 (', '.join(names), short(r)))
2855 (', '.join(names), short(r)))
2856
2856
2857 date = opts.get('date')
2857 date = opts.get('date')
2858 if date:
2858 if date:
2859 date = util.parsedate(date)
2859 date = util.parsedate(date)
2860
2860
2861 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
2861 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
2862
2862
2863 def tags(ui, repo):
2863 def tags(ui, repo):
2864 """list repository tags
2864 """list repository tags
2865
2865
2866 This lists both regular and local tags. When the -v/--verbose
2866 This lists both regular and local tags. When the -v/--verbose
2867 switch is used, a third column "local" is printed for local tags.
2867 switch is used, a third column "local" is printed for local tags.
2868 """
2868 """
2869
2869
2870 l = repo.tagslist()
2870 l = repo.tagslist()
2871 l.reverse()
2871 l.reverse()
2872 hexfunc = ui.debugflag and hex or short
2872 hexfunc = ui.debugflag and hex or short
2873 tagtype = ""
2873 tagtype = ""
2874
2874
2875 for t, n in l:
2875 for t, n in l:
2876 if ui.quiet:
2876 if ui.quiet:
2877 ui.write("%s\n" % t)
2877 ui.write("%s\n" % t)
2878 continue
2878 continue
2879
2879
2880 try:
2880 try:
2881 hn = hexfunc(n)
2881 hn = hexfunc(n)
2882 r = "%5d:%s" % (repo.changelog.rev(n), hn)
2882 r = "%5d:%s" % (repo.changelog.rev(n), hn)
2883 except error.LookupError:
2883 except error.LookupError:
2884 r = " ?:%s" % hn
2884 r = " ?:%s" % hn
2885 else:
2885 else:
2886 spaces = " " * (30 - encoding.colwidth(t))
2886 spaces = " " * (30 - encoding.colwidth(t))
2887 if ui.verbose:
2887 if ui.verbose:
2888 if repo.tagtype(t) == 'local':
2888 if repo.tagtype(t) == 'local':
2889 tagtype = " local"
2889 tagtype = " local"
2890 else:
2890 else:
2891 tagtype = ""
2891 tagtype = ""
2892 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
2892 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
2893
2893
2894 def tip(ui, repo, **opts):
2894 def tip(ui, repo, **opts):
2895 """show the tip revision
2895 """show the tip revision
2896
2896
2897 The tip revision (usually just called the tip) is the most
2897 The tip revision (usually just called the tip) is the most
2898 recently added changeset in the repository, the most recently
2898 recently added changeset in the repository, the most recently
2899 changed head.
2899 changed head.
2900
2900
2901 If you have just made a commit, that commit will be the tip. If
2901 If you have just made a commit, that commit will be the tip. If
2902 you have just pulled changes from another repository, the tip of
2902 you have just pulled changes from another repository, the tip of
2903 that repository becomes the current tip. The "tip" tag is special
2903 that repository becomes the current tip. The "tip" tag is special
2904 and cannot be renamed or assigned to a different changeset.
2904 and cannot be renamed or assigned to a different changeset.
2905 """
2905 """
2906 cmdutil.show_changeset(ui, repo, opts).show(repo[len(repo) - 1])
2906 cmdutil.show_changeset(ui, repo, opts).show(repo[len(repo) - 1])
2907
2907
2908 def unbundle(ui, repo, fname1, *fnames, **opts):
2908 def unbundle(ui, repo, fname1, *fnames, **opts):
2909 """apply one or more changegroup files
2909 """apply one or more changegroup files
2910
2910
2911 Apply one or more compressed changegroup files generated by the
2911 Apply one or more compressed changegroup files generated by the
2912 bundle command.
2912 bundle command.
2913 """
2913 """
2914 fnames = (fname1,) + fnames
2914 fnames = (fname1,) + fnames
2915
2915
2916 lock = None
2916 lock = None
2917 try:
2917 try:
2918 lock = repo.lock()
2918 lock = repo.lock()
2919 for fname in fnames:
2919 for fname in fnames:
2920 f = url.open(ui, fname)
2920 f = url.open(ui, fname)
2921 gen = changegroup.readbundle(f, fname)
2921 gen = changegroup.readbundle(f, fname)
2922 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2922 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2923 finally:
2923 finally:
2924 del lock
2924 del lock
2925
2925
2926 return postincoming(ui, repo, modheads, opts.get('update'), None)
2926 return postincoming(ui, repo, modheads, opts.get('update'), None)
2927
2927
2928 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2928 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2929 """update working directory
2929 """update working directory
2930
2930
2931 Update the repository's working directory to the specified
2931 Update the repository's working directory to the specified
2932 revision, or the tip of the current branch if none is specified.
2932 revision, or the tip of the current branch if none is specified.
2933 Use null as the revision to remove the working copy (like 'hg
2933 Use null as the revision to remove the working copy (like 'hg
2934 clone -U').
2934 clone -U').
2935
2935
2936 When the working directory contains no uncommitted changes, it
2936 When the working directory contains no uncommitted changes, it
2937 will be replaced by the state of the requested revision from the
2937 will be replaced by the state of the requested revision from the
2938 repository. When the requested revision is on a different branch,
2938 repository. When the requested revision is on a different branch,
2939 the working directory will additionally be switched to that
2939 the working directory will additionally be switched to that
2940 branch.
2940 branch.
2941
2941
2942 When there are uncommitted changes, use option -C to discard them,
2942 When there are uncommitted changes, use option -C to discard them,
2943 forcibly replacing the state of the working directory with the
2943 forcibly replacing the state of the working directory with the
2944 requested revision.
2944 requested revision.
2945
2945
2946 When there are uncommitted changes and option -C is not used, and
2946 When there are uncommitted changes and option -C is not used, and
2947 the parent revision and requested revision are on the same branch,
2947 the parent revision and requested revision are on the same branch,
2948 and one of them is an ancestor of the other, then the new working
2948 and one of them is an ancestor of the other, then the new working
2949 directory will contain the requested revision merged with the
2949 directory will contain the requested revision merged with the
2950 uncommitted changes. Otherwise, the update will fail with a
2950 uncommitted changes. Otherwise, the update will fail with a
2951 suggestion to use 'merge' or 'update -C' instead.
2951 suggestion to use 'merge' or 'update -C' instead.
2952
2952
2953 If you want to update just one file to an older revision, use
2953 If you want to update just one file to an older revision, use
2954 revert.
2954 revert.
2955
2955
2956 See 'hg help dates' for a list of formats valid for -d/--date.
2956 See 'hg help dates' for a list of formats valid for -d/--date.
2957 """
2957 """
2958 if rev and node:
2958 if rev and node:
2959 raise util.Abort(_("please specify just one revision"))
2959 raise util.Abort(_("please specify just one revision"))
2960
2960
2961 if not rev:
2961 if not rev:
2962 rev = node
2962 rev = node
2963
2963
2964 if date:
2964 if date:
2965 if rev:
2965 if rev:
2966 raise util.Abort(_("you can't specify a revision and a date"))
2966 raise util.Abort(_("you can't specify a revision and a date"))
2967 rev = cmdutil.finddate(ui, repo, date)
2967 rev = cmdutil.finddate(ui, repo, date)
2968
2968
2969 if clean:
2969 if clean:
2970 return hg.clean(repo, rev)
2970 return hg.clean(repo, rev)
2971 else:
2971 else:
2972 return hg.update(repo, rev)
2972 return hg.update(repo, rev)
2973
2973
2974 def verify(ui, repo):
2974 def verify(ui, repo):
2975 """verify the integrity of the repository
2975 """verify the integrity of the repository
2976
2976
2977 Verify the integrity of the current repository.
2977 Verify the integrity of the current repository.
2978
2978
2979 This will perform an extensive check of the repository's
2979 This will perform an extensive check of the repository's
2980 integrity, validating the hashes and checksums of each entry in
2980 integrity, validating the hashes and checksums of each entry in
2981 the changelog, manifest, and tracked files, as well as the
2981 the changelog, manifest, and tracked files, as well as the
2982 integrity of their crosslinks and indices.
2982 integrity of their crosslinks and indices.
2983 """
2983 """
2984 return hg.verify(repo)
2984 return hg.verify(repo)
2985
2985
2986 def version_(ui):
2986 def version_(ui):
2987 """output version and copyright information"""
2987 """output version and copyright information"""
2988 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2988 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2989 % util.version())
2989 % util.version())
2990 ui.status(_(
2990 ui.status(_(
2991 "\nCopyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others\n"
2991 "\nCopyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others\n"
2992 "This is free software; see the source for copying conditions. "
2992 "This is free software; see the source for copying conditions. "
2993 "There is NO\nwarranty; "
2993 "There is NO\nwarranty; "
2994 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2994 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2995 ))
2995 ))
2996
2996
2997 # Command options and aliases are listed here, alphabetically
2997 # Command options and aliases are listed here, alphabetically
2998
2998
2999 globalopts = [
2999 globalopts = [
3000 ('R', 'repository', '',
3000 ('R', 'repository', '',
3001 _('repository root directory or symbolic path name')),
3001 _('repository root directory or symbolic path name')),
3002 ('', 'cwd', '', _('change working directory')),
3002 ('', 'cwd', '', _('change working directory')),
3003 ('y', 'noninteractive', None,
3003 ('y', 'noninteractive', None,
3004 _('do not prompt, assume \'yes\' for any required answers')),
3004 _('do not prompt, assume \'yes\' for any required answers')),
3005 ('q', 'quiet', None, _('suppress output')),
3005 ('q', 'quiet', None, _('suppress output')),
3006 ('v', 'verbose', None, _('enable additional output')),
3006 ('v', 'verbose', None, _('enable additional output')),
3007 ('', 'config', [], _('set/override config option')),
3007 ('', 'config', [], _('set/override config option')),
3008 ('', 'debug', None, _('enable debugging output')),
3008 ('', 'debug', None, _('enable debugging output')),
3009 ('', 'debugger', None, _('start debugger')),
3009 ('', 'debugger', None, _('start debugger')),
3010 ('', 'encoding', encoding.encoding, _('set the charset encoding')),
3010 ('', 'encoding', encoding.encoding, _('set the charset encoding')),
3011 ('', 'encodingmode', encoding.encodingmode,
3011 ('', 'encodingmode', encoding.encodingmode,
3012 _('set the charset encoding mode')),
3012 _('set the charset encoding mode')),
3013 ('', 'traceback', None, _('print traceback on exception')),
3013 ('', 'traceback', None, _('print traceback on exception')),
3014 ('', 'time', None, _('time how long the command takes')),
3014 ('', 'time', None, _('time how long the command takes')),
3015 ('', 'profile', None, _('print command execution profile')),
3015 ('', 'profile', None, _('print command execution profile')),
3016 ('', 'version', None, _('output version information and exit')),
3016 ('', 'version', None, _('output version information and exit')),
3017 ('h', 'help', None, _('display help and exit')),
3017 ('h', 'help', None, _('display help and exit')),
3018 ]
3018 ]
3019
3019
3020 dryrunopts = [('n', 'dry-run', None,
3020 dryrunopts = [('n', 'dry-run', None,
3021 _('do not perform actions, just print output'))]
3021 _('do not perform actions, just print output'))]
3022
3022
3023 remoteopts = [
3023 remoteopts = [
3024 ('e', 'ssh', '', _('specify ssh command to use')),
3024 ('e', 'ssh', '', _('specify ssh command to use')),
3025 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
3025 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
3026 ]
3026 ]
3027
3027
3028 walkopts = [
3028 walkopts = [
3029 ('I', 'include', [], _('include names matching the given patterns')),
3029 ('I', 'include', [], _('include names matching the given patterns')),
3030 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3030 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3031 ]
3031 ]
3032
3032
3033 commitopts = [
3033 commitopts = [
3034 ('m', 'message', '', _('use <text> as commit message')),
3034 ('m', 'message', '', _('use <text> as commit message')),
3035 ('l', 'logfile', '', _('read commit message from <file>')),
3035 ('l', 'logfile', '', _('read commit message from <file>')),
3036 ]
3036 ]
3037
3037
3038 commitopts2 = [
3038 commitopts2 = [
3039 ('d', 'date', '', _('record datecode as commit date')),
3039 ('d', 'date', '', _('record datecode as commit date')),
3040 ('u', 'user', '', _('record user as committer')),
3040 ('u', 'user', '', _('record user as committer')),
3041 ]
3041 ]
3042
3042
3043 templateopts = [
3043 templateopts = [
3044 ('', 'style', '', _('display using template map file')),
3044 ('', 'style', '', _('display using template map file')),
3045 ('', 'template', '', _('display with template')),
3045 ('', 'template', '', _('display with template')),
3046 ]
3046 ]
3047
3047
3048 logopts = [
3048 logopts = [
3049 ('p', 'patch', None, _('show patch')),
3049 ('p', 'patch', None, _('show patch')),
3050 ('g', 'git', None, _('use git extended diff format')),
3050 ('g', 'git', None, _('use git extended diff format')),
3051 ('l', 'limit', '', _('limit number of changes displayed')),
3051 ('l', 'limit', '', _('limit number of changes displayed')),
3052 ('M', 'no-merges', None, _('do not show merges')),
3052 ('M', 'no-merges', None, _('do not show merges')),
3053 ] + templateopts
3053 ] + templateopts
3054
3054
3055 diffopts = [
3055 diffopts = [
3056 ('a', 'text', None, _('treat all files as text')),
3056 ('a', 'text', None, _('treat all files as text')),
3057 ('g', 'git', None, _('use git extended diff format')),
3057 ('g', 'git', None, _('use git extended diff format')),
3058 ('', 'nodates', None, _("don't include dates in diff headers"))
3058 ('', 'nodates', None, _("don't include dates in diff headers"))
3059 ]
3059 ]
3060
3060
3061 diffopts2 = [
3061 diffopts2 = [
3062 ('p', 'show-function', None, _('show which function each change is in')),
3062 ('p', 'show-function', None, _('show which function each change is in')),
3063 ('w', 'ignore-all-space', None,
3063 ('w', 'ignore-all-space', None,
3064 _('ignore white space when comparing lines')),
3064 _('ignore white space when comparing lines')),
3065 ('b', 'ignore-space-change', None,
3065 ('b', 'ignore-space-change', None,
3066 _('ignore changes in the amount of white space')),
3066 _('ignore changes in the amount of white space')),
3067 ('B', 'ignore-blank-lines', None,
3067 ('B', 'ignore-blank-lines', None,
3068 _('ignore changes whose lines are all blank')),
3068 _('ignore changes whose lines are all blank')),
3069 ('U', 'unified', '', _('number of lines of context to show'))
3069 ('U', 'unified', '', _('number of lines of context to show'))
3070 ]
3070 ]
3071
3071
3072 similarityopts = [
3072 similarityopts = [
3073 ('s', 'similarity', '',
3073 ('s', 'similarity', '',
3074 _('guess renamed files by similarity (0<=s<=100)'))
3074 _('guess renamed files by similarity (0<=s<=100)'))
3075 ]
3075 ]
3076
3076
3077 table = {
3077 table = {
3078 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3078 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3079 "addremove":
3079 "addremove":
3080 (addremove, similarityopts + walkopts + dryrunopts,
3080 (addremove, similarityopts + walkopts + dryrunopts,
3081 _('[OPTION]... [FILE]...')),
3081 _('[OPTION]... [FILE]...')),
3082 "^annotate|blame":
3082 "^annotate|blame":
3083 (annotate,
3083 (annotate,
3084 [('r', 'rev', '', _('annotate the specified revision')),
3084 [('r', 'rev', '', _('annotate the specified revision')),
3085 ('f', 'follow', None, _('follow file copies and renames')),
3085 ('f', 'follow', None, _('follow file copies and renames')),
3086 ('a', 'text', None, _('treat all files as text')),
3086 ('a', 'text', None, _('treat all files as text')),
3087 ('u', 'user', None, _('list the author (long with -v)')),
3087 ('u', 'user', None, _('list the author (long with -v)')),
3088 ('d', 'date', None, _('list the date (short with -q)')),
3088 ('d', 'date', None, _('list the date (short with -q)')),
3089 ('n', 'number', None, _('list the revision number (default)')),
3089 ('n', 'number', None, _('list the revision number (default)')),
3090 ('c', 'changeset', None, _('list the changeset')),
3090 ('c', 'changeset', None, _('list the changeset')),
3091 ('l', 'line-number', None,
3091 ('l', 'line-number', None,
3092 _('show line number at the first appearance'))
3092 _('show line number at the first appearance'))
3093 ] + walkopts,
3093 ] + walkopts,
3094 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3094 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3095 "archive":
3095 "archive":
3096 (archive,
3096 (archive,
3097 [('', 'no-decode', None, _('do not pass files through decoders')),
3097 [('', 'no-decode', None, _('do not pass files through decoders')),
3098 ('p', 'prefix', '', _('directory prefix for files in archive')),
3098 ('p', 'prefix', '', _('directory prefix for files in archive')),
3099 ('r', 'rev', '', _('revision to distribute')),
3099 ('r', 'rev', '', _('revision to distribute')),
3100 ('t', 'type', '', _('type of distribution to create')),
3100 ('t', 'type', '', _('type of distribution to create')),
3101 ] + walkopts,
3101 ] + walkopts,
3102 _('[OPTION]... DEST')),
3102 _('[OPTION]... DEST')),
3103 "backout":
3103 "backout":
3104 (backout,
3104 (backout,
3105 [('', 'merge', None,
3105 [('', 'merge', None,
3106 _('merge with old dirstate parent after backout')),
3106 _('merge with old dirstate parent after backout')),
3107 ('', 'parent', '', _('parent to choose when backing out merge')),
3107 ('', 'parent', '', _('parent to choose when backing out merge')),
3108 ('r', 'rev', '', _('revision to backout')),
3108 ('r', 'rev', '', _('revision to backout')),
3109 ] + walkopts + commitopts + commitopts2,
3109 ] + walkopts + commitopts + commitopts2,
3110 _('[OPTION]... [-r] REV')),
3110 _('[OPTION]... [-r] REV')),
3111 "bisect":
3111 "bisect":
3112 (bisect,
3112 (bisect,
3113 [('r', 'reset', False, _('reset bisect state')),
3113 [('r', 'reset', False, _('reset bisect state')),
3114 ('g', 'good', False, _('mark changeset good')),
3114 ('g', 'good', False, _('mark changeset good')),
3115 ('b', 'bad', False, _('mark changeset bad')),
3115 ('b', 'bad', False, _('mark changeset bad')),
3116 ('s', 'skip', False, _('skip testing changeset')),
3116 ('s', 'skip', False, _('skip testing changeset')),
3117 ('c', 'command', '', _('use command to check changeset state')),
3117 ('c', 'command', '', _('use command to check changeset state')),
3118 ('U', 'noupdate', False, _('do not update to target'))],
3118 ('U', 'noupdate', False, _('do not update to target'))],
3119 _("[-gbsr] [-c CMD] [REV]")),
3119 _("[-gbsr] [-c CMD] [REV]")),
3120 "branch":
3120 "branch":
3121 (branch,
3121 (branch,
3122 [('f', 'force', None,
3122 [('f', 'force', None,
3123 _('set branch name even if it shadows an existing branch')),
3123 _('set branch name even if it shadows an existing branch')),
3124 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3124 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3125 _('[-fC] [NAME]')),
3125 _('[-fC] [NAME]')),
3126 "branches":
3126 "branches":
3127 (branches,
3127 (branches,
3128 [('a', 'active', False,
3128 [('a', 'active', False,
3129 _('show only branches that have unmerged heads'))],
3129 _('show only branches that have unmerged heads'))],
3130 _('[-a]')),
3130 _('[-a]')),
3131 "bundle":
3131 "bundle":
3132 (bundle,
3132 (bundle,
3133 [('f', 'force', None,
3133 [('f', 'force', None,
3134 _('run even when remote repository is unrelated')),
3134 _('run even when remote repository is unrelated')),
3135 ('r', 'rev', [],
3135 ('r', 'rev', [],
3136 _('a changeset up to which you would like to bundle')),
3136 _('a changeset up to which you would like to bundle')),
3137 ('', 'base', [],
3137 ('', 'base', [],
3138 _('a base changeset to specify instead of a destination')),
3138 _('a base changeset to specify instead of a destination')),
3139 ('a', 'all', None, _('bundle all changesets in the repository')),
3139 ('a', 'all', None, _('bundle all changesets in the repository')),
3140 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3140 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3141 ] + remoteopts,
3141 ] + remoteopts,
3142 _('[-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3142 _('[-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3143 "cat":
3143 "cat":
3144 (cat,
3144 (cat,
3145 [('o', 'output', '', _('print output to file with formatted name')),
3145 [('o', 'output', '', _('print output to file with formatted name')),
3146 ('r', 'rev', '', _('print the given revision')),
3146 ('r', 'rev', '', _('print the given revision')),
3147 ('', 'decode', None, _('apply any matching decode filter')),
3147 ('', 'decode', None, _('apply any matching decode filter')),
3148 ] + walkopts,
3148 ] + walkopts,
3149 _('[OPTION]... FILE...')),
3149 _('[OPTION]... FILE...')),
3150 "^clone":
3150 "^clone":
3151 (clone,
3151 (clone,
3152 [('U', 'noupdate', None,
3152 [('U', 'noupdate', None,
3153 _('the clone will only contain a repository (no working copy)')),
3153 _('the clone will only contain a repository (no working copy)')),
3154 ('r', 'rev', [],
3154 ('r', 'rev', [],
3155 _('a changeset you would like to have after cloning')),
3155 _('a changeset you would like to have after cloning')),
3156 ('', 'pull', None, _('use pull protocol to copy metadata')),
3156 ('', 'pull', None, _('use pull protocol to copy metadata')),
3157 ('', 'uncompressed', None,
3157 ('', 'uncompressed', None,
3158 _('use uncompressed transfer (fast over LAN)')),
3158 _('use uncompressed transfer (fast over LAN)')),
3159 ] + remoteopts,
3159 ] + remoteopts,
3160 _('[OPTION]... SOURCE [DEST]')),
3160 _('[OPTION]... SOURCE [DEST]')),
3161 "^commit|ci":
3161 "^commit|ci":
3162 (commit,
3162 (commit,
3163 [('A', 'addremove', None,
3163 [('A', 'addremove', None,
3164 _('mark new/missing files as added/removed before committing')),
3164 _('mark new/missing files as added/removed before committing')),
3165 ('', 'close-branch', None,
3165 ('', 'close-branch', None,
3166 _('mark a branch as closed, hiding it from the branch list')),
3166 _('mark a branch as closed, hiding it from the branch list')),
3167 ] + walkopts + commitopts + commitopts2,
3167 ] + walkopts + commitopts + commitopts2,
3168 _('[OPTION]... [FILE]...')),
3168 _('[OPTION]... [FILE]...')),
3169 "copy|cp":
3169 "copy|cp":
3170 (copy,
3170 (copy,
3171 [('A', 'after', None, _('record a copy that has already occurred')),
3171 [('A', 'after', None, _('record a copy that has already occurred')),
3172 ('f', 'force', None,
3172 ('f', 'force', None,
3173 _('forcibly copy over an existing managed file')),
3173 _('forcibly copy over an existing managed file')),
3174 ] + walkopts + dryrunopts,
3174 ] + walkopts + dryrunopts,
3175 _('[OPTION]... [SOURCE]... DEST')),
3175 _('[OPTION]... [SOURCE]... DEST')),
3176 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
3176 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
3177 "debugcheckstate": (debugcheckstate, []),
3177 "debugcheckstate": (debugcheckstate, []),
3178 "debugcommands": (debugcommands, [], _('[COMMAND]')),
3178 "debugcommands": (debugcommands, [], _('[COMMAND]')),
3179 "debugcomplete":
3179 "debugcomplete":
3180 (debugcomplete,
3180 (debugcomplete,
3181 [('o', 'options', None, _('show the command options'))],
3181 [('o', 'options', None, _('show the command options'))],
3182 _('[-o] CMD')),
3182 _('[-o] CMD')),
3183 "debugdate":
3183 "debugdate":
3184 (debugdate,
3184 (debugdate,
3185 [('e', 'extended', None, _('try extended date formats'))],
3185 [('e', 'extended', None, _('try extended date formats'))],
3186 _('[-e] DATE [RANGE]')),
3186 _('[-e] DATE [RANGE]')),
3187 "debugdata": (debugdata, [], _('FILE REV')),
3187 "debugdata": (debugdata, [], _('FILE REV')),
3188 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
3188 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
3189 "debugindex": (debugindex, [], _('FILE')),
3189 "debugindex": (debugindex, [], _('FILE')),
3190 "debugindexdot": (debugindexdot, [], _('FILE')),
3190 "debugindexdot": (debugindexdot, [], _('FILE')),
3191 "debuginstall": (debuginstall, []),
3191 "debuginstall": (debuginstall, []),
3192 "debugrawcommit|rawcommit":
3192 "debugrawcommit|rawcommit":
3193 (rawcommit,
3193 (rawcommit,
3194 [('p', 'parent', [], _('parent')),
3194 [('p', 'parent', [], _('parent')),
3195 ('F', 'files', '', _('file list'))
3195 ('F', 'files', '', _('file list'))
3196 ] + commitopts + commitopts2,
3196 ] + commitopts + commitopts2,
3197 _('[OPTION]... [FILE]...')),
3197 _('[OPTION]... [FILE]...')),
3198 "debugrebuildstate":
3198 "debugrebuildstate":
3199 (debugrebuildstate,
3199 (debugrebuildstate,
3200 [('r', 'rev', '', _('revision to rebuild to'))],
3200 [('r', 'rev', '', _('revision to rebuild to'))],
3201 _('[-r REV] [REV]')),
3201 _('[-r REV] [REV]')),
3202 "debugrename":
3202 "debugrename":
3203 (debugrename,
3203 (debugrename,
3204 [('r', 'rev', '', _('revision to debug'))],
3204 [('r', 'rev', '', _('revision to debug'))],
3205 _('[-r REV] FILE')),
3205 _('[-r REV] FILE')),
3206 "debugsetparents":
3206 "debugsetparents":
3207 (debugsetparents, [], _('REV1 [REV2]')),
3207 (debugsetparents, [], _('REV1 [REV2]')),
3208 "debugstate":
3208 "debugstate":
3209 (debugstate,
3209 (debugstate,
3210 [('', 'nodates', None, _('do not display the saved mtime'))],
3210 [('', 'nodates', None, _('do not display the saved mtime'))],
3211 _('[OPTION]...')),
3211 _('[OPTION]...')),
3212 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
3212 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
3213 "^diff":
3213 "^diff":
3214 (diff,
3214 (diff,
3215 [('r', 'rev', [], _('revision')),
3215 [('r', 'rev', [], _('revision')),
3216 ('c', 'change', '', _('change made by revision'))
3216 ('c', 'change', '', _('change made by revision'))
3217 ] + diffopts + diffopts2 + walkopts,
3217 ] + diffopts + diffopts2 + walkopts,
3218 _('[OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
3218 _('[OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
3219 "^export":
3219 "^export":
3220 (export,
3220 (export,
3221 [('o', 'output', '', _('print output to file with formatted name')),
3221 [('o', 'output', '', _('print output to file with formatted name')),
3222 ('', 'switch-parent', None, _('diff against the second parent'))
3222 ('', 'switch-parent', None, _('diff against the second parent'))
3223 ] + diffopts,
3223 ] + diffopts,
3224 _('[OPTION]... [-o OUTFILESPEC] REV...')),
3224 _('[OPTION]... [-o OUTFILESPEC] REV...')),
3225 "grep":
3225 "grep":
3226 (grep,
3226 (grep,
3227 [('0', 'print0', None, _('end fields with NUL')),
3227 [('0', 'print0', None, _('end fields with NUL')),
3228 ('', 'all', None, _('print all revisions that match')),
3228 ('', 'all', None, _('print all revisions that match')),
3229 ('f', 'follow', None,
3229 ('f', 'follow', None,
3230 _('follow changeset history, or file history across copies and renames')),
3230 _('follow changeset history, or file history across copies and renames')),
3231 ('i', 'ignore-case', None, _('ignore case when matching')),
3231 ('i', 'ignore-case', None, _('ignore case when matching')),
3232 ('l', 'files-with-matches', None,
3232 ('l', 'files-with-matches', None,
3233 _('print only filenames and revisions that match')),
3233 _('print only filenames and revisions that match')),
3234 ('n', 'line-number', None, _('print matching line numbers')),
3234 ('n', 'line-number', None, _('print matching line numbers')),
3235 ('r', 'rev', [], _('search in given revision range')),
3235 ('r', 'rev', [], _('search in given revision range')),
3236 ('u', 'user', None, _('list the author (long with -v)')),
3236 ('u', 'user', None, _('list the author (long with -v)')),
3237 ('d', 'date', None, _('list the date (short with -q)')),
3237 ('d', 'date', None, _('list the date (short with -q)')),
3238 ] + walkopts,
3238 ] + walkopts,
3239 _('[OPTION]... PATTERN [FILE]...')),
3239 _('[OPTION]... PATTERN [FILE]...')),
3240 "heads":
3240 "heads":
3241 (heads,
3241 (heads,
3242 [('r', 'rev', '', _('show only heads which are descendants of REV')),
3242 [('r', 'rev', '', _('show only heads which are descendants of REV')),
3243 ('a', 'active', False,
3243 ('a', 'active', False,
3244 _('show only the active heads from open branches')),
3244 _('show only the active heads from open branches')),
3245 ] + templateopts,
3245 ] + templateopts,
3246 _('[-r REV] [REV]...')),
3246 _('[-r REV] [REV]...')),
3247 "help": (help_, [], _('[TOPIC]')),
3247 "help": (help_, [], _('[TOPIC]')),
3248 "identify|id":
3248 "identify|id":
3249 (identify,
3249 (identify,
3250 [('r', 'rev', '', _('identify the specified revision')),
3250 [('r', 'rev', '', _('identify the specified revision')),
3251 ('n', 'num', None, _('show local revision number')),
3251 ('n', 'num', None, _('show local revision number')),
3252 ('i', 'id', None, _('show global revision id')),
3252 ('i', 'id', None, _('show global revision id')),
3253 ('b', 'branch', None, _('show branch')),
3253 ('b', 'branch', None, _('show branch')),
3254 ('t', 'tags', None, _('show tags'))],
3254 ('t', 'tags', None, _('show tags'))],
3255 _('[-nibt] [-r REV] [SOURCE]')),
3255 _('[-nibt] [-r REV] [SOURCE]')),
3256 "import|patch":
3256 "import|patch":
3257 (import_,
3257 (import_,
3258 [('p', 'strip', 1,
3258 [('p', 'strip', 1,
3259 _('directory strip option for patch. This has the same '
3259 _('directory strip option for patch. This has the same '
3260 'meaning as the corresponding patch option')),
3260 'meaning as the corresponding patch option')),
3261 ('b', 'base', '', _('base path')),
3261 ('b', 'base', '', _('base path')),
3262 ('f', 'force', None,
3262 ('f', 'force', None,
3263 _('skip check for outstanding uncommitted changes')),
3263 _('skip check for outstanding uncommitted changes')),
3264 ('', 'no-commit', None, _("don't commit, just update the working directory")),
3264 ('', 'no-commit', None, _("don't commit, just update the working directory")),
3265 ('', 'exact', None,
3265 ('', 'exact', None,
3266 _('apply patch to the nodes from which it was generated')),
3266 _('apply patch to the nodes from which it was generated')),
3267 ('', 'import-branch', None,
3267 ('', 'import-branch', None,
3268 _('use any branch information in patch (implied by --exact)'))] +
3268 _('use any branch information in patch (implied by --exact)'))] +
3269 commitopts + commitopts2 + similarityopts,
3269 commitopts + commitopts2 + similarityopts,
3270 _('[OPTION]... PATCH...')),
3270 _('[OPTION]... PATCH...')),
3271 "incoming|in":
3271 "incoming|in":
3272 (incoming,
3272 (incoming,
3273 [('f', 'force', None,
3273 [('f', 'force', None,
3274 _('run even when remote repository is unrelated')),
3274 _('run even when remote repository is unrelated')),
3275 ('n', 'newest-first', None, _('show newest record first')),
3275 ('n', 'newest-first', None, _('show newest record first')),
3276 ('', 'bundle', '', _('file to store the bundles into')),
3276 ('', 'bundle', '', _('file to store the bundles into')),
3277 ('r', 'rev', [],
3277 ('r', 'rev', [],
3278 _('a specific revision up to which you would like to pull')),
3278 _('a specific revision up to which you would like to pull')),
3279 ] + logopts + remoteopts,
3279 ] + logopts + remoteopts,
3280 _('[-p] [-n] [-M] [-f] [-r REV]...'
3280 _('[-p] [-n] [-M] [-f] [-r REV]...'
3281 ' [--bundle FILENAME] [SOURCE]')),
3281 ' [--bundle FILENAME] [SOURCE]')),
3282 "^init":
3282 "^init":
3283 (init,
3283 (init,
3284 remoteopts,
3284 remoteopts,
3285 _('[-e CMD] [--remotecmd CMD] [DEST]')),
3285 _('[-e CMD] [--remotecmd CMD] [DEST]')),
3286 "locate":
3286 "locate":
3287 (locate,
3287 (locate,
3288 [('r', 'rev', '', _('search the repository as it stood at REV')),
3288 [('r', 'rev', '', _('search the repository as it stood at REV')),
3289 ('0', 'print0', None,
3289 ('0', 'print0', None,
3290 _('end filenames with NUL, for use with xargs')),
3290 _('end filenames with NUL, for use with xargs')),
3291 ('f', 'fullpath', None,
3291 ('f', 'fullpath', None,
3292 _('print complete paths from the filesystem root')),
3292 _('print complete paths from the filesystem root')),
3293 ] + walkopts,
3293 ] + walkopts,
3294 _('[OPTION]... [PATTERN]...')),
3294 _('[OPTION]... [PATTERN]...')),
3295 "^log|history":
3295 "^log|history":
3296 (log,
3296 (log,
3297 [('f', 'follow', None,
3297 [('f', 'follow', None,
3298 _('follow changeset history, or file history across copies and renames')),
3298 _('follow changeset history, or file history across copies and renames')),
3299 ('', 'follow-first', None,
3299 ('', 'follow-first', None,
3300 _('only follow the first parent of merge changesets')),
3300 _('only follow the first parent of merge changesets')),
3301 ('d', 'date', '', _('show revisions matching date spec')),
3301 ('d', 'date', '', _('show revisions matching date spec')),
3302 ('C', 'copies', None, _('show copied files')),
3302 ('C', 'copies', None, _('show copied files')),
3303 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3303 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3304 ('r', 'rev', [], _('show the specified revision or range')),
3304 ('r', 'rev', [], _('show the specified revision or range')),
3305 ('', 'removed', None, _('include revisions where files were removed')),
3305 ('', 'removed', None, _('include revisions where files were removed')),
3306 ('m', 'only-merges', None, _('show only merges')),
3306 ('m', 'only-merges', None, _('show only merges')),
3307 ('u', 'user', [], _('revisions committed by user')),
3307 ('u', 'user', [], _('revisions committed by user')),
3308 ('b', 'only-branch', [],
3308 ('b', 'only-branch', [],
3309 _('show only changesets within the given named branch')),
3309 _('show only changesets within the given named branch')),
3310 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3310 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3311 ] + logopts + walkopts,
3311 ] + logopts + walkopts,
3312 _('[OPTION]... [FILE]')),
3312 _('[OPTION]... [FILE]')),
3313 "manifest":
3313 "manifest":
3314 (manifest,
3314 (manifest,
3315 [('r', 'rev', '', _('revision to display'))],
3315 [('r', 'rev', '', _('revision to display'))],
3316 _('[-r REV]')),
3316 _('[-r REV]')),
3317 "^merge":
3317 "^merge":
3318 (merge,
3318 (merge,
3319 [('f', 'force', None, _('force a merge with outstanding changes')),
3319 [('f', 'force', None, _('force a merge with outstanding changes')),
3320 ('r', 'rev', '', _('revision to merge')),
3320 ('r', 'rev', '', _('revision to merge')),
3321 ],
3321 ],
3322 _('[-f] [[-r] REV]')),
3322 _('[-f] [[-r] REV]')),
3323 "outgoing|out":
3323 "outgoing|out":
3324 (outgoing,
3324 (outgoing,
3325 [('f', 'force', None,
3325 [('f', 'force', None,
3326 _('run even when remote repository is unrelated')),
3326 _('run even when remote repository is unrelated')),
3327 ('r', 'rev', [],
3327 ('r', 'rev', [],
3328 _('a specific revision up to which you would like to push')),
3328 _('a specific revision up to which you would like to push')),
3329 ('n', 'newest-first', None, _('show newest record first')),
3329 ('n', 'newest-first', None, _('show newest record first')),
3330 ] + logopts + remoteopts,
3330 ] + logopts + remoteopts,
3331 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3331 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3332 "^parents":
3332 "^parents":
3333 (parents,
3333 (parents,
3334 [('r', 'rev', '', _('show parents from the specified revision')),
3334 [('r', 'rev', '', _('show parents from the specified revision')),
3335 ] + templateopts,
3335 ] + templateopts,
3336 _('hg parents [-r REV] [FILE]')),
3336 _('hg parents [-r REV] [FILE]')),
3337 "paths": (paths, [], _('[NAME]')),
3337 "paths": (paths, [], _('[NAME]')),
3338 "^pull":
3338 "^pull":
3339 (pull,
3339 (pull,
3340 [('u', 'update', None,
3340 [('u', 'update', None,
3341 _('update to new tip if changesets were pulled')),
3341 _('update to new tip if changesets were pulled')),
3342 ('f', 'force', None,
3342 ('f', 'force', None,
3343 _('run even when remote repository is unrelated')),
3343 _('run even when remote repository is unrelated')),
3344 ('r', 'rev', [],
3344 ('r', 'rev', [],
3345 _('a specific revision up to which you would like to pull')),
3345 _('a specific revision up to which you would like to pull')),
3346 ] + remoteopts,
3346 ] + remoteopts,
3347 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3347 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3348 "^push":
3348 "^push":
3349 (push,
3349 (push,
3350 [('f', 'force', None, _('force push')),
3350 [('f', 'force', None, _('force push')),
3351 ('r', 'rev', [],
3351 ('r', 'rev', [],
3352 _('a specific revision up to which you would like to push')),
3352 _('a specific revision up to which you would like to push')),
3353 ] + remoteopts,
3353 ] + remoteopts,
3354 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3354 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3355 "recover": (recover, []),
3355 "recover": (recover, []),
3356 "^remove|rm":
3356 "^remove|rm":
3357 (remove,
3357 (remove,
3358 [('A', 'after', None, _('record delete for missing files')),
3358 [('A', 'after', None, _('record delete for missing files')),
3359 ('f', 'force', None,
3359 ('f', 'force', None,
3360 _('remove (and delete) file even if added or modified')),
3360 _('remove (and delete) file even if added or modified')),
3361 ] + walkopts,
3361 ] + walkopts,
3362 _('[OPTION]... FILE...')),
3362 _('[OPTION]... FILE...')),
3363 "rename|mv":
3363 "rename|mv":
3364 (rename,
3364 (rename,
3365 [('A', 'after', None, _('record a rename that has already occurred')),
3365 [('A', 'after', None, _('record a rename that has already occurred')),
3366 ('f', 'force', None,
3366 ('f', 'force', None,
3367 _('forcibly copy over an existing managed file')),
3367 _('forcibly copy over an existing managed file')),
3368 ] + walkopts + dryrunopts,
3368 ] + walkopts + dryrunopts,
3369 _('[OPTION]... SOURCE... DEST')),
3369 _('[OPTION]... SOURCE... DEST')),
3370 "resolve":
3370 "resolve":
3371 (resolve,
3371 (resolve,
3372 [('a', 'all', None, _('remerge all unresolved files')),
3372 [('a', 'all', None, _('remerge all unresolved files')),
3373 ('l', 'list', None, _('list state of files needing merge')),
3373 ('l', 'list', None, _('list state of files needing merge')),
3374 ('m', 'mark', None, _('mark files as resolved')),
3374 ('m', 'mark', None, _('mark files as resolved')),
3375 ('u', 'unmark', None, _('unmark files as resolved'))]
3375 ('u', 'unmark', None, _('unmark files as resolved'))]
3376 + walkopts,
3376 + walkopts,
3377 _('[OPTION]... [FILE]...')),
3377 _('[OPTION]... [FILE]...')),
3378 "revert":
3378 "revert":
3379 (revert,
3379 (revert,
3380 [('a', 'all', None, _('revert all changes when no arguments given')),
3380 [('a', 'all', None, _('revert all changes when no arguments given')),
3381 ('d', 'date', '', _('tipmost revision matching date')),
3381 ('d', 'date', '', _('tipmost revision matching date')),
3382 ('r', 'rev', '', _('revision to revert to')),
3382 ('r', 'rev', '', _('revision to revert to')),
3383 ('', 'no-backup', None, _('do not save backup copies of files')),
3383 ('', 'no-backup', None, _('do not save backup copies of files')),
3384 ] + walkopts + dryrunopts,
3384 ] + walkopts + dryrunopts,
3385 _('[OPTION]... [-r REV] [NAME]...')),
3385 _('[OPTION]... [-r REV] [NAME]...')),
3386 "rollback": (rollback, []),
3386 "rollback": (rollback, []),
3387 "root": (root, []),
3387 "root": (root, []),
3388 "^serve":
3388 "^serve":
3389 (serve,
3389 (serve,
3390 [('A', 'accesslog', '', _('name of access log file to write to')),
3390 [('A', 'accesslog', '', _('name of access log file to write to')),
3391 ('d', 'daemon', None, _('run server in background')),
3391 ('d', 'daemon', None, _('run server in background')),
3392 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3392 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3393 ('E', 'errorlog', '', _('name of error log file to write to')),
3393 ('E', 'errorlog', '', _('name of error log file to write to')),
3394 ('p', 'port', 0, _('port to listen on (default: 8000)')),
3394 ('p', 'port', 0, _('port to listen on (default: 8000)')),
3395 ('a', 'address', '', _('address to listen on (default: all interfaces)')),
3395 ('a', 'address', '', _('address to listen on (default: all interfaces)')),
3396 ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
3396 ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
3397 ('n', 'name', '',
3397 ('n', 'name', '',
3398 _('name to show in web pages (default: working directory)')),
3398 _('name to show in web pages (default: working directory)')),
3399 ('', 'webdir-conf', '', _('name of the webdir config file'
3399 ('', 'webdir-conf', '', _('name of the webdir config file'
3400 ' (serve more than one repository)')),
3400 ' (serve more than one repository)')),
3401 ('', 'pid-file', '', _('name of file to write process ID to')),
3401 ('', 'pid-file', '', _('name of file to write process ID to')),
3402 ('', 'stdio', None, _('for remote clients')),
3402 ('', 'stdio', None, _('for remote clients')),
3403 ('t', 'templates', '', _('web templates to use')),
3403 ('t', 'templates', '', _('web templates to use')),
3404 ('', 'style', '', _('template style to use')),
3404 ('', 'style', '', _('template style to use')),
3405 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3405 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3406 ('', 'certificate', '', _('SSL certificate file'))],
3406 ('', 'certificate', '', _('SSL certificate file'))],
3407 _('[OPTION]...')),
3407 _('[OPTION]...')),
3408 "showconfig|debugconfig":
3408 "showconfig|debugconfig":
3409 (showconfig,
3409 (showconfig,
3410 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3410 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3411 _('[-u] [NAME]...')),
3411 _('[-u] [NAME]...')),
3412 "^status|st":
3412 "^status|st":
3413 (status,
3413 (status,
3414 [('A', 'all', None, _('show status of all files')),
3414 [('A', 'all', None, _('show status of all files')),
3415 ('m', 'modified', None, _('show only modified files')),
3415 ('m', 'modified', None, _('show only modified files')),
3416 ('a', 'added', None, _('show only added files')),
3416 ('a', 'added', None, _('show only added files')),
3417 ('r', 'removed', None, _('show only removed files')),
3417 ('r', 'removed', None, _('show only removed files')),
3418 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3418 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3419 ('c', 'clean', None, _('show only files without changes')),
3419 ('c', 'clean', None, _('show only files without changes')),
3420 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3420 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3421 ('i', 'ignored', None, _('show only ignored files')),
3421 ('i', 'ignored', None, _('show only ignored files')),
3422 ('n', 'no-status', None, _('hide status prefix')),
3422 ('n', 'no-status', None, _('hide status prefix')),
3423 ('C', 'copies', None, _('show source of copied files')),
3423 ('C', 'copies', None, _('show source of copied files')),
3424 ('0', 'print0', None,
3424 ('0', 'print0', None,
3425 _('end filenames with NUL, for use with xargs')),
3425 _('end filenames with NUL, for use with xargs')),
3426 ('', 'rev', [], _('show difference from revision')),
3426 ('', 'rev', [], _('show difference from revision')),
3427 ] + walkopts,
3427 ] + walkopts,
3428 _('[OPTION]... [FILE]...')),
3428 _('[OPTION]... [FILE]...')),
3429 "tag":
3429 "tag":
3430 (tag,
3430 (tag,
3431 [('f', 'force', None, _('replace existing tag')),
3431 [('f', 'force', None, _('replace existing tag')),
3432 ('l', 'local', None, _('make the tag local')),
3432 ('l', 'local', None, _('make the tag local')),
3433 ('r', 'rev', '', _('revision to tag')),
3433 ('r', 'rev', '', _('revision to tag')),
3434 ('', 'remove', None, _('remove a tag')),
3434 ('', 'remove', None, _('remove a tag')),
3435 # -l/--local is already there, commitopts cannot be used
3435 # -l/--local is already there, commitopts cannot be used
3436 ('m', 'message', '', _('use <text> as commit message')),
3436 ('m', 'message', '', _('use <text> as commit message')),
3437 ] + commitopts2,
3437 ] + commitopts2,
3438 _('[-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3438 _('[-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3439 "tags": (tags, []),
3439 "tags": (tags, []),
3440 "tip":
3440 "tip":
3441 (tip,
3441 (tip,
3442 [('p', 'patch', None, _('show patch')),
3442 [('p', 'patch', None, _('show patch')),
3443 ('g', 'git', None, _('use git extended diff format')),
3443 ('g', 'git', None, _('use git extended diff format')),
3444 ] + templateopts,
3444 ] + templateopts,
3445 _('[-p]')),
3445 _('[-p]')),
3446 "unbundle":
3446 "unbundle":
3447 (unbundle,
3447 (unbundle,
3448 [('u', 'update', None,
3448 [('u', 'update', None,
3449 _('update to new tip if changesets were unbundled'))],
3449 _('update to new tip if changesets were unbundled'))],
3450 _('[-u] FILE...')),
3450 _('[-u] FILE...')),
3451 "^update|up|checkout|co":
3451 "^update|up|checkout|co":
3452 (update,
3452 (update,
3453 [('C', 'clean', None, _('overwrite locally modified files (no backup)')),
3453 [('C', 'clean', None, _('overwrite locally modified files (no backup)')),
3454 ('d', 'date', '', _('tipmost revision matching date')),
3454 ('d', 'date', '', _('tipmost revision matching date')),
3455 ('r', 'rev', '', _('revision'))],
3455 ('r', 'rev', '', _('revision'))],
3456 _('[-C] [-d DATE] [[-r] REV]')),
3456 _('[-C] [-d DATE] [[-r] REV]')),
3457 "verify": (verify, []),
3457 "verify": (verify, []),
3458 "version": (version_, []),
3458 "version": (version_, []),
3459 }
3459 }
3460
3460
3461 norepo = ("clone init version help debugcommands debugcomplete debugdata"
3461 norepo = ("clone init version help debugcommands debugcomplete debugdata"
3462 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3462 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3463 optionalrepo = ("identify paths serve showconfig debugancestor")
3463 optionalrepo = ("identify paths serve showconfig debugancestor")
General Comments 0
You need to be logged in to leave comments. Login now