##// END OF EJS Templates
Use nullrev+count instead of count-1 in a newly introduced expression....
Thomas Arendsen Hein -
r3671:86d3f966 default
parent child Browse files
Show More
@@ -1,3037 +1,3037
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 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 demandload import demandload
8 from demandload import demandload
9 from node import *
9 from node import *
10 from i18n import gettext as _
10 from i18n import gettext as _
11 demandload(globals(), "os re sys signal imp urllib pdb shlex")
11 demandload(globals(), "os re sys signal imp urllib pdb shlex")
12 demandload(globals(), "fancyopts ui hg util lock revlog bundlerepo")
12 demandload(globals(), "fancyopts ui hg util lock revlog bundlerepo")
13 demandload(globals(), "difflib patch time")
13 demandload(globals(), "difflib patch time")
14 demandload(globals(), "traceback errno version atexit")
14 demandload(globals(), "traceback errno version atexit")
15 demandload(globals(), "archival changegroup cmdutil hgweb.server sshserver")
15 demandload(globals(), "archival changegroup cmdutil hgweb.server sshserver")
16
16
17 class UnknownCommand(Exception):
17 class UnknownCommand(Exception):
18 """Exception raised if command is not in the command table."""
18 """Exception raised if command is not in the command table."""
19 class AmbiguousCommand(Exception):
19 class AmbiguousCommand(Exception):
20 """Exception raised if command shortcut matches more than one command."""
20 """Exception raised if command shortcut matches more than one command."""
21
21
22 def bail_if_changed(repo):
22 def bail_if_changed(repo):
23 modified, added, removed, deleted = repo.status()[:4]
23 modified, added, removed, deleted = repo.status()[:4]
24 if modified or added or removed or deleted:
24 if modified or added or removed or deleted:
25 raise util.Abort(_("outstanding uncommitted changes"))
25 raise util.Abort(_("outstanding uncommitted changes"))
26
26
27 def logmessage(opts):
27 def logmessage(opts):
28 """ get the log message according to -m and -l option """
28 """ get the log message according to -m and -l option """
29 message = opts['message']
29 message = opts['message']
30 logfile = opts['logfile']
30 logfile = opts['logfile']
31
31
32 if message and logfile:
32 if message and logfile:
33 raise util.Abort(_('options --message and --logfile are mutually '
33 raise util.Abort(_('options --message and --logfile are mutually '
34 'exclusive'))
34 'exclusive'))
35 if not message and logfile:
35 if not message and logfile:
36 try:
36 try:
37 if logfile == '-':
37 if logfile == '-':
38 message = sys.stdin.read()
38 message = sys.stdin.read()
39 else:
39 else:
40 message = open(logfile).read()
40 message = open(logfile).read()
41 except IOError, inst:
41 except IOError, inst:
42 raise util.Abort(_("can't read commit message '%s': %s") %
42 raise util.Abort(_("can't read commit message '%s': %s") %
43 (logfile, inst.strerror))
43 (logfile, inst.strerror))
44 return message
44 return message
45
45
46 def setremoteconfig(ui, opts):
46 def setremoteconfig(ui, opts):
47 "copy remote options to ui tree"
47 "copy remote options to ui tree"
48 if opts.get('ssh'):
48 if opts.get('ssh'):
49 ui.setconfig("ui", "ssh", opts['ssh'])
49 ui.setconfig("ui", "ssh", opts['ssh'])
50 if opts.get('remotecmd'):
50 if opts.get('remotecmd'):
51 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
51 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
52
52
53 # Commands start here, listed alphabetically
53 # Commands start here, listed alphabetically
54
54
55 def add(ui, repo, *pats, **opts):
55 def add(ui, repo, *pats, **opts):
56 """add the specified files on the next commit
56 """add the specified files on the next commit
57
57
58 Schedule files to be version controlled and added to the repository.
58 Schedule files to be version controlled and added to the repository.
59
59
60 The files will be added to the repository at the next commit.
60 The files will be added to the repository at the next commit.
61
61
62 If no names are given, add all files in the repository.
62 If no names are given, add all files in the repository.
63 """
63 """
64
64
65 names = []
65 names = []
66 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
66 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
67 if exact:
67 if exact:
68 if ui.verbose:
68 if ui.verbose:
69 ui.status(_('adding %s\n') % rel)
69 ui.status(_('adding %s\n') % rel)
70 names.append(abs)
70 names.append(abs)
71 elif repo.dirstate.state(abs) == '?':
71 elif repo.dirstate.state(abs) == '?':
72 ui.status(_('adding %s\n') % rel)
72 ui.status(_('adding %s\n') % rel)
73 names.append(abs)
73 names.append(abs)
74 if not opts.get('dry_run'):
74 if not opts.get('dry_run'):
75 repo.add(names)
75 repo.add(names)
76
76
77 def addremove(ui, repo, *pats, **opts):
77 def addremove(ui, repo, *pats, **opts):
78 """add all new files, delete all missing files
78 """add all new files, delete all missing files
79
79
80 Add all new files and remove all missing files from the repository.
80 Add all new files and remove all missing files from the repository.
81
81
82 New files are ignored if they match any of the patterns in .hgignore. As
82 New files are ignored if they match any of the patterns in .hgignore. As
83 with add, these changes take effect at the next commit.
83 with add, these changes take effect at the next commit.
84
84
85 Use the -s option to detect renamed files. With a parameter > 0,
85 Use the -s option to detect renamed files. With a parameter > 0,
86 this compares every removed file with every added file and records
86 this compares every removed file with every added file and records
87 those similar enough as renames. This option takes a percentage
87 those similar enough as renames. This option takes a percentage
88 between 0 (disabled) and 100 (files must be identical) as its
88 between 0 (disabled) and 100 (files must be identical) as its
89 parameter. Detecting renamed files this way can be expensive.
89 parameter. Detecting renamed files this way can be expensive.
90 """
90 """
91 sim = float(opts.get('similarity') or 0)
91 sim = float(opts.get('similarity') or 0)
92 if sim < 0 or sim > 100:
92 if sim < 0 or sim > 100:
93 raise util.Abort(_('similarity must be between 0 and 100'))
93 raise util.Abort(_('similarity must be between 0 and 100'))
94 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
94 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
95
95
96 def annotate(ui, repo, *pats, **opts):
96 def annotate(ui, repo, *pats, **opts):
97 """show changeset information per file line
97 """show changeset information per file line
98
98
99 List changes in files, showing the revision id responsible for each line
99 List changes in files, showing the revision id responsible for each line
100
100
101 This command is useful to discover who did a change or when a change took
101 This command is useful to discover who did a change or when a change took
102 place.
102 place.
103
103
104 Without the -a option, annotate will avoid processing files it
104 Without the -a option, annotate will avoid processing files it
105 detects as binary. With -a, annotate will generate an annotation
105 detects as binary. With -a, annotate will generate an annotation
106 anyway, probably with undesirable results.
106 anyway, probably with undesirable results.
107 """
107 """
108 getdate = util.cachefunc(lambda x: util.datestr(x.date()))
108 getdate = util.cachefunc(lambda x: util.datestr(x.date()))
109
109
110 if not pats:
110 if not pats:
111 raise util.Abort(_('at least one file name or pattern required'))
111 raise util.Abort(_('at least one file name or pattern required'))
112
112
113 opmap = [['user', lambda x: ui.shortuser(x.user())],
113 opmap = [['user', lambda x: ui.shortuser(x.user())],
114 ['number', lambda x: str(x.rev())],
114 ['number', lambda x: str(x.rev())],
115 ['changeset', lambda x: short(x.node())],
115 ['changeset', lambda x: short(x.node())],
116 ['date', getdate], ['follow', lambda x: x.path()]]
116 ['date', getdate], ['follow', lambda x: x.path()]]
117 if (not opts['user'] and not opts['changeset'] and not opts['date']
117 if (not opts['user'] and not opts['changeset'] and not opts['date']
118 and not opts['follow']):
118 and not opts['follow']):
119 opts['number'] = 1
119 opts['number'] = 1
120
120
121 ctx = repo.changectx(opts['rev'])
121 ctx = repo.changectx(opts['rev'])
122
122
123 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
123 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
124 node=ctx.node()):
124 node=ctx.node()):
125 fctx = ctx.filectx(abs)
125 fctx = ctx.filectx(abs)
126 if not opts['text'] and util.binary(fctx.data()):
126 if not opts['text'] and util.binary(fctx.data()):
127 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
127 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
128 continue
128 continue
129
129
130 lines = fctx.annotate(follow=opts.get('follow'))
130 lines = fctx.annotate(follow=opts.get('follow'))
131 pieces = []
131 pieces = []
132
132
133 for o, f in opmap:
133 for o, f in opmap:
134 if opts[o]:
134 if opts[o]:
135 l = [f(n) for n, dummy in lines]
135 l = [f(n) for n, dummy in lines]
136 if l:
136 if l:
137 m = max(map(len, l))
137 m = max(map(len, l))
138 pieces.append(["%*s" % (m, x) for x in l])
138 pieces.append(["%*s" % (m, x) for x in l])
139
139
140 if pieces:
140 if pieces:
141 for p, l in zip(zip(*pieces), lines):
141 for p, l in zip(zip(*pieces), lines):
142 ui.write("%s: %s" % (" ".join(p), l[1]))
142 ui.write("%s: %s" % (" ".join(p), l[1]))
143
143
144 def archive(ui, repo, dest, **opts):
144 def archive(ui, repo, dest, **opts):
145 '''create unversioned archive of a repository revision
145 '''create unversioned archive of a repository revision
146
146
147 By default, the revision used is the parent of the working
147 By default, the revision used is the parent of the working
148 directory; use "-r" to specify a different revision.
148 directory; use "-r" to specify a different revision.
149
149
150 To specify the type of archive to create, use "-t". Valid
150 To specify the type of archive to create, use "-t". Valid
151 types are:
151 types are:
152
152
153 "files" (default): a directory full of files
153 "files" (default): a directory full of files
154 "tar": tar archive, uncompressed
154 "tar": tar archive, uncompressed
155 "tbz2": tar archive, compressed using bzip2
155 "tbz2": tar archive, compressed using bzip2
156 "tgz": tar archive, compressed using gzip
156 "tgz": tar archive, compressed using gzip
157 "uzip": zip archive, uncompressed
157 "uzip": zip archive, uncompressed
158 "zip": zip archive, compressed using deflate
158 "zip": zip archive, compressed using deflate
159
159
160 The exact name of the destination archive or directory is given
160 The exact name of the destination archive or directory is given
161 using a format string; see "hg help export" for details.
161 using a format string; see "hg help export" for details.
162
162
163 Each member added to an archive file has a directory prefix
163 Each member added to an archive file has a directory prefix
164 prepended. Use "-p" to specify a format string for the prefix.
164 prepended. Use "-p" to specify a format string for the prefix.
165 The default is the basename of the archive, with suffixes removed.
165 The default is the basename of the archive, with suffixes removed.
166 '''
166 '''
167
167
168 node = repo.changectx(opts['rev']).node()
168 node = repo.changectx(opts['rev']).node()
169 dest = cmdutil.make_filename(repo, dest, node)
169 dest = cmdutil.make_filename(repo, dest, node)
170 if os.path.realpath(dest) == repo.root:
170 if os.path.realpath(dest) == repo.root:
171 raise util.Abort(_('repository root cannot be destination'))
171 raise util.Abort(_('repository root cannot be destination'))
172 dummy, matchfn, dummy = cmdutil.matchpats(repo, [], opts)
172 dummy, matchfn, dummy = cmdutil.matchpats(repo, [], opts)
173 kind = opts.get('type') or 'files'
173 kind = opts.get('type') or 'files'
174 prefix = opts['prefix']
174 prefix = opts['prefix']
175 if dest == '-':
175 if dest == '-':
176 if kind == 'files':
176 if kind == 'files':
177 raise util.Abort(_('cannot archive plain files to stdout'))
177 raise util.Abort(_('cannot archive plain files to stdout'))
178 dest = sys.stdout
178 dest = sys.stdout
179 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
179 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
180 prefix = cmdutil.make_filename(repo, prefix, node)
180 prefix = cmdutil.make_filename(repo, prefix, node)
181 archival.archive(repo, dest, node, kind, not opts['no_decode'],
181 archival.archive(repo, dest, node, kind, not opts['no_decode'],
182 matchfn, prefix)
182 matchfn, prefix)
183
183
184 def backout(ui, repo, rev, **opts):
184 def backout(ui, repo, rev, **opts):
185 '''reverse effect of earlier changeset
185 '''reverse effect of earlier changeset
186
186
187 Commit the backed out changes as a new changeset. The new
187 Commit the backed out changes as a new changeset. The new
188 changeset is a child of the backed out changeset.
188 changeset is a child of the backed out changeset.
189
189
190 If you back out a changeset other than the tip, a new head is
190 If you back out a changeset other than the tip, a new head is
191 created. This head is the parent of the working directory. If
191 created. This head is the parent of the working directory. If
192 you back out an old changeset, your working directory will appear
192 you back out an old changeset, your working directory will appear
193 old after the backout. You should merge the backout changeset
193 old after the backout. You should merge the backout changeset
194 with another head.
194 with another head.
195
195
196 The --merge option remembers the parent of the working directory
196 The --merge option remembers the parent of the working directory
197 before starting the backout, then merges the new head with that
197 before starting the backout, then merges the new head with that
198 changeset afterwards. This saves you from doing the merge by
198 changeset afterwards. This saves you from doing the merge by
199 hand. The result of this merge is not committed, as for a normal
199 hand. The result of this merge is not committed, as for a normal
200 merge.'''
200 merge.'''
201
201
202 bail_if_changed(repo)
202 bail_if_changed(repo)
203 op1, op2 = repo.dirstate.parents()
203 op1, op2 = repo.dirstate.parents()
204 if op2 != nullid:
204 if op2 != nullid:
205 raise util.Abort(_('outstanding uncommitted merge'))
205 raise util.Abort(_('outstanding uncommitted merge'))
206 node = repo.lookup(rev)
206 node = repo.lookup(rev)
207 p1, p2 = repo.changelog.parents(node)
207 p1, p2 = repo.changelog.parents(node)
208 if p1 == nullid:
208 if p1 == nullid:
209 raise util.Abort(_('cannot back out a change with no parents'))
209 raise util.Abort(_('cannot back out a change with no parents'))
210 if p2 != nullid:
210 if p2 != nullid:
211 if not opts['parent']:
211 if not opts['parent']:
212 raise util.Abort(_('cannot back out a merge changeset without '
212 raise util.Abort(_('cannot back out a merge changeset without '
213 '--parent'))
213 '--parent'))
214 p = repo.lookup(opts['parent'])
214 p = repo.lookup(opts['parent'])
215 if p not in (p1, p2):
215 if p not in (p1, p2):
216 raise util.Abort(_('%s is not a parent of %s' %
216 raise util.Abort(_('%s is not a parent of %s' %
217 (short(p), short(node))))
217 (short(p), short(node))))
218 parent = p
218 parent = p
219 else:
219 else:
220 if opts['parent']:
220 if opts['parent']:
221 raise util.Abort(_('cannot use --parent on non-merge changeset'))
221 raise util.Abort(_('cannot use --parent on non-merge changeset'))
222 parent = p1
222 parent = p1
223 hg.clean(repo, node, show_stats=False)
223 hg.clean(repo, node, show_stats=False)
224 revert_opts = opts.copy()
224 revert_opts = opts.copy()
225 revert_opts['all'] = True
225 revert_opts['all'] = True
226 revert_opts['rev'] = hex(parent)
226 revert_opts['rev'] = hex(parent)
227 revert(ui, repo, **revert_opts)
227 revert(ui, repo, **revert_opts)
228 commit_opts = opts.copy()
228 commit_opts = opts.copy()
229 commit_opts['addremove'] = False
229 commit_opts['addremove'] = False
230 if not commit_opts['message'] and not commit_opts['logfile']:
230 if not commit_opts['message'] and not commit_opts['logfile']:
231 commit_opts['message'] = _("Backed out changeset %s") % (hex(node))
231 commit_opts['message'] = _("Backed out changeset %s") % (hex(node))
232 commit_opts['force_editor'] = True
232 commit_opts['force_editor'] = True
233 commit(ui, repo, **commit_opts)
233 commit(ui, repo, **commit_opts)
234 def nice(node):
234 def nice(node):
235 return '%d:%s' % (repo.changelog.rev(node), short(node))
235 return '%d:%s' % (repo.changelog.rev(node), short(node))
236 ui.status(_('changeset %s backs out changeset %s\n') %
236 ui.status(_('changeset %s backs out changeset %s\n') %
237 (nice(repo.changelog.tip()), nice(node)))
237 (nice(repo.changelog.tip()), nice(node)))
238 if op1 != node:
238 if op1 != node:
239 if opts['merge']:
239 if opts['merge']:
240 ui.status(_('merging with changeset %s\n') % nice(op1))
240 ui.status(_('merging with changeset %s\n') % nice(op1))
241 n = _lookup(repo, hex(op1))
241 n = _lookup(repo, hex(op1))
242 hg.merge(repo, n)
242 hg.merge(repo, n)
243 else:
243 else:
244 ui.status(_('the backout changeset is a new head - '
244 ui.status(_('the backout changeset is a new head - '
245 'do not forget to merge\n'))
245 'do not forget to merge\n'))
246 ui.status(_('(use "backout --merge" '
246 ui.status(_('(use "backout --merge" '
247 'if you want to auto-merge)\n'))
247 'if you want to auto-merge)\n'))
248
248
249 def branch(ui, repo, label=None):
249 def branch(ui, repo, label=None):
250 """set or show the current branch name
250 """set or show the current branch name
251
251
252 With <name>, set the current branch name. Otherwise, show the
252 With <name>, set the current branch name. Otherwise, show the
253 current branch name.
253 current branch name.
254 """
254 """
255
255
256 if label is not None:
256 if label is not None:
257 repo.opener("branch", "w").write(label)
257 repo.opener("branch", "w").write(label)
258 else:
258 else:
259 b = repo.workingctx().branch()
259 b = repo.workingctx().branch()
260 if b:
260 if b:
261 ui.write("%s\n" % b)
261 ui.write("%s\n" % b)
262
262
263 def branches(ui, repo):
263 def branches(ui, repo):
264 """list repository named branches
264 """list repository named branches
265
265
266 List the repository's named branches.
266 List the repository's named branches.
267 """
267 """
268 b = repo.branchtags()
268 b = repo.branchtags()
269 l = [(-repo.changelog.rev(n), n, t) for t,n in b.items()]
269 l = [(-repo.changelog.rev(n), n, t) for t,n in b.items()]
270 l.sort()
270 l.sort()
271 for r, n, t in l:
271 for r, n, t in l:
272 hexfunc = ui.debugflag and hex or short
272 hexfunc = ui.debugflag and hex or short
273 if ui.quiet:
273 if ui.quiet:
274 ui.write("%s\n" % t)
274 ui.write("%s\n" % t)
275 else:
275 else:
276 ui.write("%-30s %s:%s\n" % (t, -r, hexfunc(n)))
276 ui.write("%-30s %s:%s\n" % (t, -r, hexfunc(n)))
277
277
278 def bundle(ui, repo, fname, dest=None, **opts):
278 def bundle(ui, repo, fname, dest=None, **opts):
279 """create a changegroup file
279 """create a changegroup file
280
280
281 Generate a compressed changegroup file collecting changesets not
281 Generate a compressed changegroup file collecting changesets not
282 found in the other repository.
282 found in the other repository.
283
283
284 If no destination repository is specified the destination is assumed
284 If no destination repository is specified the destination is assumed
285 to have all the nodes specified by one or more --base parameters.
285 to have all the nodes specified by one or more --base parameters.
286
286
287 The bundle file can then be transferred using conventional means and
287 The bundle file can then be transferred using conventional means and
288 applied to another repository with the unbundle or pull command.
288 applied to another repository with the unbundle or pull command.
289 This is useful when direct push and pull are not available or when
289 This is useful when direct push and pull are not available or when
290 exporting an entire repository is undesirable.
290 exporting an entire repository is undesirable.
291
291
292 Applying bundles preserves all changeset contents including
292 Applying bundles preserves all changeset contents including
293 permissions, copy/rename information, and revision history.
293 permissions, copy/rename information, and revision history.
294 """
294 """
295 revs = opts.get('rev') or None
295 revs = opts.get('rev') or None
296 if revs:
296 if revs:
297 revs = [repo.lookup(rev) for rev in revs]
297 revs = [repo.lookup(rev) for rev in revs]
298 base = opts.get('base')
298 base = opts.get('base')
299 if base:
299 if base:
300 if dest:
300 if dest:
301 raise util.Abort(_("--base is incompatible with specifiying "
301 raise util.Abort(_("--base is incompatible with specifiying "
302 "a destination"))
302 "a destination"))
303 base = [repo.lookup(rev) for rev in base]
303 base = [repo.lookup(rev) for rev in base]
304 # create the right base
304 # create the right base
305 # XXX: nodesbetween / changegroup* should be "fixed" instead
305 # XXX: nodesbetween / changegroup* should be "fixed" instead
306 o = []
306 o = []
307 has = {nullid: None}
307 has = {nullid: None}
308 for n in base:
308 for n in base:
309 has.update(repo.changelog.reachable(n))
309 has.update(repo.changelog.reachable(n))
310 if revs:
310 if revs:
311 visit = list(revs)
311 visit = list(revs)
312 else:
312 else:
313 visit = repo.changelog.heads()
313 visit = repo.changelog.heads()
314 seen = {}
314 seen = {}
315 while visit:
315 while visit:
316 n = visit.pop(0)
316 n = visit.pop(0)
317 parents = [p for p in repo.changelog.parents(n) if p not in has]
317 parents = [p for p in repo.changelog.parents(n) if p not in has]
318 if len(parents) == 0:
318 if len(parents) == 0:
319 o.insert(0, n)
319 o.insert(0, n)
320 else:
320 else:
321 for p in parents:
321 for p in parents:
322 if p not in seen:
322 if p not in seen:
323 seen[p] = 1
323 seen[p] = 1
324 visit.append(p)
324 visit.append(p)
325 else:
325 else:
326 setremoteconfig(ui, opts)
326 setremoteconfig(ui, opts)
327 dest = ui.expandpath(dest or 'default-push', dest or 'default')
327 dest = ui.expandpath(dest or 'default-push', dest or 'default')
328 other = hg.repository(ui, dest)
328 other = hg.repository(ui, dest)
329 o = repo.findoutgoing(other, force=opts['force'])
329 o = repo.findoutgoing(other, force=opts['force'])
330
330
331 if revs:
331 if revs:
332 cg = repo.changegroupsubset(o, revs, 'bundle')
332 cg = repo.changegroupsubset(o, revs, 'bundle')
333 else:
333 else:
334 cg = repo.changegroup(o, 'bundle')
334 cg = repo.changegroup(o, 'bundle')
335 changegroup.writebundle(cg, fname, "HG10")
335 changegroup.writebundle(cg, fname, "HG10")
336
336
337 def cat(ui, repo, file1, *pats, **opts):
337 def cat(ui, repo, file1, *pats, **opts):
338 """output the latest or given revisions of files
338 """output the latest or given revisions of files
339
339
340 Print the specified files as they were at the given revision.
340 Print the specified files as they were at the given revision.
341 If no revision is given then working dir parent is used, or tip
341 If no revision is given then working dir parent is used, or tip
342 if no revision is checked out.
342 if no revision is checked out.
343
343
344 Output may be to a file, in which case the name of the file is
344 Output may be to a file, in which case the name of the file is
345 given using a format string. The formatting rules are the same as
345 given using a format string. The formatting rules are the same as
346 for the export command, with the following additions:
346 for the export command, with the following additions:
347
347
348 %s basename of file being printed
348 %s basename of file being printed
349 %d dirname of file being printed, or '.' if in repo root
349 %d dirname of file being printed, or '.' if in repo root
350 %p root-relative path name of file being printed
350 %p root-relative path name of file being printed
351 """
351 """
352 ctx = repo.changectx(opts['rev'])
352 ctx = repo.changectx(opts['rev'])
353 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
353 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
354 ctx.node()):
354 ctx.node()):
355 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
355 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
356 fp.write(ctx.filectx(abs).data())
356 fp.write(ctx.filectx(abs).data())
357
357
358 def clone(ui, source, dest=None, **opts):
358 def clone(ui, source, dest=None, **opts):
359 """make a copy of an existing repository
359 """make a copy of an existing repository
360
360
361 Create a copy of an existing repository in a new directory.
361 Create a copy of an existing repository in a new directory.
362
362
363 If no destination directory name is specified, it defaults to the
363 If no destination directory name is specified, it defaults to the
364 basename of the source.
364 basename of the source.
365
365
366 The location of the source is added to the new repository's
366 The location of the source is added to the new repository's
367 .hg/hgrc file, as the default to be used for future pulls.
367 .hg/hgrc file, as the default to be used for future pulls.
368
368
369 For efficiency, hardlinks are used for cloning whenever the source
369 For efficiency, hardlinks are used for cloning whenever the source
370 and destination are on the same filesystem (note this applies only
370 and destination are on the same filesystem (note this applies only
371 to the repository data, not to the checked out files). Some
371 to the repository data, not to the checked out files). Some
372 filesystems, such as AFS, implement hardlinking incorrectly, but
372 filesystems, such as AFS, implement hardlinking incorrectly, but
373 do not report errors. In these cases, use the --pull option to
373 do not report errors. In these cases, use the --pull option to
374 avoid hardlinking.
374 avoid hardlinking.
375
375
376 You can safely clone repositories and checked out files using full
376 You can safely clone repositories and checked out files using full
377 hardlinks with
377 hardlinks with
378
378
379 $ cp -al REPO REPOCLONE
379 $ cp -al REPO REPOCLONE
380
380
381 which is the fastest way to clone. However, the operation is not
381 which is the fastest way to clone. However, the operation is not
382 atomic (making sure REPO is not modified during the operation is
382 atomic (making sure REPO is not modified during the operation is
383 up to you) and you have to make sure your editor breaks hardlinks
383 up to you) and you have to make sure your editor breaks hardlinks
384 (Emacs and most Linux Kernel tools do so).
384 (Emacs and most Linux Kernel tools do so).
385
385
386 If you use the -r option to clone up to a specific revision, no
386 If you use the -r option to clone up to a specific revision, no
387 subsequent revisions will be present in the cloned repository.
387 subsequent revisions will be present in the cloned repository.
388 This option implies --pull, even on local repositories.
388 This option implies --pull, even on local repositories.
389
389
390 See pull for valid source format details.
390 See pull for valid source format details.
391
391
392 It is possible to specify an ssh:// URL as the destination, but no
392 It is possible to specify an ssh:// URL as the destination, but no
393 .hg/hgrc and working directory will be created on the remote side.
393 .hg/hgrc and working directory will be created on the remote side.
394 Look at the help text for the pull command for important details
394 Look at the help text for the pull command for important details
395 about ssh:// URLs.
395 about ssh:// URLs.
396 """
396 """
397 setremoteconfig(ui, opts)
397 setremoteconfig(ui, opts)
398 hg.clone(ui, ui.expandpath(source), dest,
398 hg.clone(ui, ui.expandpath(source), dest,
399 pull=opts['pull'],
399 pull=opts['pull'],
400 stream=opts['uncompressed'],
400 stream=opts['uncompressed'],
401 rev=opts['rev'],
401 rev=opts['rev'],
402 update=not opts['noupdate'])
402 update=not opts['noupdate'])
403
403
404 def commit(ui, repo, *pats, **opts):
404 def commit(ui, repo, *pats, **opts):
405 """commit the specified files or all outstanding changes
405 """commit the specified files or all outstanding changes
406
406
407 Commit changes to the given files into the repository.
407 Commit changes to the given files into the repository.
408
408
409 If a list of files is omitted, all changes reported by "hg status"
409 If a list of files is omitted, all changes reported by "hg status"
410 will be committed.
410 will be committed.
411
411
412 If no commit message is specified, the editor configured in your hgrc
412 If no commit message is specified, the editor configured in your hgrc
413 or in the EDITOR environment variable is started to enter a message.
413 or in the EDITOR environment variable is started to enter a message.
414 """
414 """
415 message = logmessage(opts)
415 message = logmessage(opts)
416
416
417 if opts['addremove']:
417 if opts['addremove']:
418 cmdutil.addremove(repo, pats, opts)
418 cmdutil.addremove(repo, pats, opts)
419 fns, match, anypats = cmdutil.matchpats(repo, pats, opts)
419 fns, match, anypats = cmdutil.matchpats(repo, pats, opts)
420 if pats:
420 if pats:
421 status = repo.status(files=fns, match=match)
421 status = repo.status(files=fns, match=match)
422 modified, added, removed, deleted, unknown = status[:5]
422 modified, added, removed, deleted, unknown = status[:5]
423 files = modified + added + removed
423 files = modified + added + removed
424 for f in fns:
424 for f in fns:
425 if f not in modified + added + removed:
425 if f not in modified + added + removed:
426 if f in unknown:
426 if f in unknown:
427 raise util.Abort(_("file %s not tracked!") % f)
427 raise util.Abort(_("file %s not tracked!") % f)
428 else:
428 else:
429 raise util.Abort(_("file %s not found!") % f)
429 raise util.Abort(_("file %s not found!") % f)
430 else:
430 else:
431 files = []
431 files = []
432 try:
432 try:
433 repo.commit(files, message, opts['user'], opts['date'], match,
433 repo.commit(files, message, opts['user'], opts['date'], match,
434 force_editor=opts.get('force_editor'))
434 force_editor=opts.get('force_editor'))
435 except ValueError, inst:
435 except ValueError, inst:
436 raise util.Abort(str(inst))
436 raise util.Abort(str(inst))
437
437
438 def docopy(ui, repo, pats, opts, wlock):
438 def docopy(ui, repo, pats, opts, wlock):
439 # called with the repo lock held
439 # called with the repo lock held
440 cwd = repo.getcwd()
440 cwd = repo.getcwd()
441 errors = 0
441 errors = 0
442 copied = []
442 copied = []
443 targets = {}
443 targets = {}
444
444
445 def okaytocopy(abs, rel, exact):
445 def okaytocopy(abs, rel, exact):
446 reasons = {'?': _('is not managed'),
446 reasons = {'?': _('is not managed'),
447 'a': _('has been marked for add'),
447 'a': _('has been marked for add'),
448 'r': _('has been marked for remove')}
448 'r': _('has been marked for remove')}
449 state = repo.dirstate.state(abs)
449 state = repo.dirstate.state(abs)
450 reason = reasons.get(state)
450 reason = reasons.get(state)
451 if reason:
451 if reason:
452 if state == 'a':
452 if state == 'a':
453 origsrc = repo.dirstate.copied(abs)
453 origsrc = repo.dirstate.copied(abs)
454 if origsrc is not None:
454 if origsrc is not None:
455 return origsrc
455 return origsrc
456 if exact:
456 if exact:
457 ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
457 ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
458 else:
458 else:
459 return abs
459 return abs
460
460
461 def copy(origsrc, abssrc, relsrc, target, exact):
461 def copy(origsrc, abssrc, relsrc, target, exact):
462 abstarget = util.canonpath(repo.root, cwd, target)
462 abstarget = util.canonpath(repo.root, cwd, target)
463 reltarget = util.pathto(cwd, abstarget)
463 reltarget = util.pathto(cwd, abstarget)
464 prevsrc = targets.get(abstarget)
464 prevsrc = targets.get(abstarget)
465 if prevsrc is not None:
465 if prevsrc is not None:
466 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
466 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
467 (reltarget, abssrc, prevsrc))
467 (reltarget, abssrc, prevsrc))
468 return
468 return
469 if (not opts['after'] and os.path.exists(reltarget) or
469 if (not opts['after'] and os.path.exists(reltarget) or
470 opts['after'] and repo.dirstate.state(abstarget) not in '?r'):
470 opts['after'] and repo.dirstate.state(abstarget) not in '?r'):
471 if not opts['force']:
471 if not opts['force']:
472 ui.warn(_('%s: not overwriting - file exists\n') %
472 ui.warn(_('%s: not overwriting - file exists\n') %
473 reltarget)
473 reltarget)
474 return
474 return
475 if not opts['after'] and not opts.get('dry_run'):
475 if not opts['after'] and not opts.get('dry_run'):
476 os.unlink(reltarget)
476 os.unlink(reltarget)
477 if opts['after']:
477 if opts['after']:
478 if not os.path.exists(reltarget):
478 if not os.path.exists(reltarget):
479 return
479 return
480 else:
480 else:
481 targetdir = os.path.dirname(reltarget) or '.'
481 targetdir = os.path.dirname(reltarget) or '.'
482 if not os.path.isdir(targetdir) and not opts.get('dry_run'):
482 if not os.path.isdir(targetdir) and not opts.get('dry_run'):
483 os.makedirs(targetdir)
483 os.makedirs(targetdir)
484 try:
484 try:
485 restore = repo.dirstate.state(abstarget) == 'r'
485 restore = repo.dirstate.state(abstarget) == 'r'
486 if restore and not opts.get('dry_run'):
486 if restore and not opts.get('dry_run'):
487 repo.undelete([abstarget], wlock)
487 repo.undelete([abstarget], wlock)
488 try:
488 try:
489 if not opts.get('dry_run'):
489 if not opts.get('dry_run'):
490 util.copyfile(relsrc, reltarget)
490 util.copyfile(relsrc, reltarget)
491 restore = False
491 restore = False
492 finally:
492 finally:
493 if restore:
493 if restore:
494 repo.remove([abstarget], wlock)
494 repo.remove([abstarget], wlock)
495 except IOError, inst:
495 except IOError, inst:
496 if inst.errno == errno.ENOENT:
496 if inst.errno == errno.ENOENT:
497 ui.warn(_('%s: deleted in working copy\n') % relsrc)
497 ui.warn(_('%s: deleted in working copy\n') % relsrc)
498 else:
498 else:
499 ui.warn(_('%s: cannot copy - %s\n') %
499 ui.warn(_('%s: cannot copy - %s\n') %
500 (relsrc, inst.strerror))
500 (relsrc, inst.strerror))
501 errors += 1
501 errors += 1
502 return
502 return
503 if ui.verbose or not exact:
503 if ui.verbose or not exact:
504 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
504 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
505 targets[abstarget] = abssrc
505 targets[abstarget] = abssrc
506 if abstarget != origsrc and not opts.get('dry_run'):
506 if abstarget != origsrc and not opts.get('dry_run'):
507 repo.copy(origsrc, abstarget, wlock)
507 repo.copy(origsrc, abstarget, wlock)
508 copied.append((abssrc, relsrc, exact))
508 copied.append((abssrc, relsrc, exact))
509
509
510 def targetpathfn(pat, dest, srcs):
510 def targetpathfn(pat, dest, srcs):
511 if os.path.isdir(pat):
511 if os.path.isdir(pat):
512 abspfx = util.canonpath(repo.root, cwd, pat)
512 abspfx = util.canonpath(repo.root, cwd, pat)
513 if destdirexists:
513 if destdirexists:
514 striplen = len(os.path.split(abspfx)[0])
514 striplen = len(os.path.split(abspfx)[0])
515 else:
515 else:
516 striplen = len(abspfx)
516 striplen = len(abspfx)
517 if striplen:
517 if striplen:
518 striplen += len(os.sep)
518 striplen += len(os.sep)
519 res = lambda p: os.path.join(dest, p[striplen:])
519 res = lambda p: os.path.join(dest, p[striplen:])
520 elif destdirexists:
520 elif destdirexists:
521 res = lambda p: os.path.join(dest, os.path.basename(p))
521 res = lambda p: os.path.join(dest, os.path.basename(p))
522 else:
522 else:
523 res = lambda p: dest
523 res = lambda p: dest
524 return res
524 return res
525
525
526 def targetpathafterfn(pat, dest, srcs):
526 def targetpathafterfn(pat, dest, srcs):
527 if util.patkind(pat, None)[0]:
527 if util.patkind(pat, None)[0]:
528 # a mercurial pattern
528 # a mercurial pattern
529 res = lambda p: os.path.join(dest, os.path.basename(p))
529 res = lambda p: os.path.join(dest, os.path.basename(p))
530 else:
530 else:
531 abspfx = util.canonpath(repo.root, cwd, pat)
531 abspfx = util.canonpath(repo.root, cwd, pat)
532 if len(abspfx) < len(srcs[0][0]):
532 if len(abspfx) < len(srcs[0][0]):
533 # A directory. Either the target path contains the last
533 # A directory. Either the target path contains the last
534 # component of the source path or it does not.
534 # component of the source path or it does not.
535 def evalpath(striplen):
535 def evalpath(striplen):
536 score = 0
536 score = 0
537 for s in srcs:
537 for s in srcs:
538 t = os.path.join(dest, s[0][striplen:])
538 t = os.path.join(dest, s[0][striplen:])
539 if os.path.exists(t):
539 if os.path.exists(t):
540 score += 1
540 score += 1
541 return score
541 return score
542
542
543 striplen = len(abspfx)
543 striplen = len(abspfx)
544 if striplen:
544 if striplen:
545 striplen += len(os.sep)
545 striplen += len(os.sep)
546 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
546 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
547 score = evalpath(striplen)
547 score = evalpath(striplen)
548 striplen1 = len(os.path.split(abspfx)[0])
548 striplen1 = len(os.path.split(abspfx)[0])
549 if striplen1:
549 if striplen1:
550 striplen1 += len(os.sep)
550 striplen1 += len(os.sep)
551 if evalpath(striplen1) > score:
551 if evalpath(striplen1) > score:
552 striplen = striplen1
552 striplen = striplen1
553 res = lambda p: os.path.join(dest, p[striplen:])
553 res = lambda p: os.path.join(dest, p[striplen:])
554 else:
554 else:
555 # a file
555 # a file
556 if destdirexists:
556 if destdirexists:
557 res = lambda p: os.path.join(dest, os.path.basename(p))
557 res = lambda p: os.path.join(dest, os.path.basename(p))
558 else:
558 else:
559 res = lambda p: dest
559 res = lambda p: dest
560 return res
560 return res
561
561
562
562
563 pats = list(pats)
563 pats = list(pats)
564 if not pats:
564 if not pats:
565 raise util.Abort(_('no source or destination specified'))
565 raise util.Abort(_('no source or destination specified'))
566 if len(pats) == 1:
566 if len(pats) == 1:
567 raise util.Abort(_('no destination specified'))
567 raise util.Abort(_('no destination specified'))
568 dest = pats.pop()
568 dest = pats.pop()
569 destdirexists = os.path.isdir(dest)
569 destdirexists = os.path.isdir(dest)
570 if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists:
570 if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists:
571 raise util.Abort(_('with multiple sources, destination must be an '
571 raise util.Abort(_('with multiple sources, destination must be an '
572 'existing directory'))
572 'existing directory'))
573 if opts['after']:
573 if opts['after']:
574 tfn = targetpathafterfn
574 tfn = targetpathafterfn
575 else:
575 else:
576 tfn = targetpathfn
576 tfn = targetpathfn
577 copylist = []
577 copylist = []
578 for pat in pats:
578 for pat in pats:
579 srcs = []
579 srcs = []
580 for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts):
580 for tag, abssrc, relsrc, exact in cmdutil.walk(repo, [pat], opts):
581 origsrc = okaytocopy(abssrc, relsrc, exact)
581 origsrc = okaytocopy(abssrc, relsrc, exact)
582 if origsrc:
582 if origsrc:
583 srcs.append((origsrc, abssrc, relsrc, exact))
583 srcs.append((origsrc, abssrc, relsrc, exact))
584 if not srcs:
584 if not srcs:
585 continue
585 continue
586 copylist.append((tfn(pat, dest, srcs), srcs))
586 copylist.append((tfn(pat, dest, srcs), srcs))
587 if not copylist:
587 if not copylist:
588 raise util.Abort(_('no files to copy'))
588 raise util.Abort(_('no files to copy'))
589
589
590 for targetpath, srcs in copylist:
590 for targetpath, srcs in copylist:
591 for origsrc, abssrc, relsrc, exact in srcs:
591 for origsrc, abssrc, relsrc, exact in srcs:
592 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
592 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
593
593
594 if errors:
594 if errors:
595 ui.warn(_('(consider using --after)\n'))
595 ui.warn(_('(consider using --after)\n'))
596 return errors, copied
596 return errors, copied
597
597
598 def copy(ui, repo, *pats, **opts):
598 def copy(ui, repo, *pats, **opts):
599 """mark files as copied for the next commit
599 """mark files as copied for the next commit
600
600
601 Mark dest as having copies of source files. If dest is a
601 Mark dest as having copies of source files. If dest is a
602 directory, copies are put in that directory. If dest is a file,
602 directory, copies are put in that directory. If dest is a file,
603 there can only be one source.
603 there can only be one source.
604
604
605 By default, this command copies the contents of files as they
605 By default, this command copies the contents of files as they
606 stand in the working directory. If invoked with --after, the
606 stand in the working directory. If invoked with --after, the
607 operation is recorded, but no copying is performed.
607 operation is recorded, but no copying is performed.
608
608
609 This command takes effect in the next commit.
609 This command takes effect in the next commit.
610 """
610 """
611 wlock = repo.wlock(0)
611 wlock = repo.wlock(0)
612 errs, copied = docopy(ui, repo, pats, opts, wlock)
612 errs, copied = docopy(ui, repo, pats, opts, wlock)
613 return errs
613 return errs
614
614
615 def debugancestor(ui, index, rev1, rev2):
615 def debugancestor(ui, index, rev1, rev2):
616 """find the ancestor revision of two revisions in a given index"""
616 """find the ancestor revision of two revisions in a given index"""
617 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index, "", 0)
617 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index, "", 0)
618 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
618 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
619 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
619 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
620
620
621 def debugcomplete(ui, cmd='', **opts):
621 def debugcomplete(ui, cmd='', **opts):
622 """returns the completion list associated with the given command"""
622 """returns the completion list associated with the given command"""
623
623
624 if opts['options']:
624 if opts['options']:
625 options = []
625 options = []
626 otables = [globalopts]
626 otables = [globalopts]
627 if cmd:
627 if cmd:
628 aliases, entry = findcmd(ui, cmd)
628 aliases, entry = findcmd(ui, cmd)
629 otables.append(entry[1])
629 otables.append(entry[1])
630 for t in otables:
630 for t in otables:
631 for o in t:
631 for o in t:
632 if o[0]:
632 if o[0]:
633 options.append('-%s' % o[0])
633 options.append('-%s' % o[0])
634 options.append('--%s' % o[1])
634 options.append('--%s' % o[1])
635 ui.write("%s\n" % "\n".join(options))
635 ui.write("%s\n" % "\n".join(options))
636 return
636 return
637
637
638 clist = findpossible(ui, cmd).keys()
638 clist = findpossible(ui, cmd).keys()
639 clist.sort()
639 clist.sort()
640 ui.write("%s\n" % "\n".join(clist))
640 ui.write("%s\n" % "\n".join(clist))
641
641
642 def debugrebuildstate(ui, repo, rev=None):
642 def debugrebuildstate(ui, repo, rev=None):
643 """rebuild the dirstate as it would look like for the given revision"""
643 """rebuild the dirstate as it would look like for the given revision"""
644 if not rev:
644 if not rev:
645 rev = repo.changelog.tip()
645 rev = repo.changelog.tip()
646 else:
646 else:
647 rev = repo.lookup(rev)
647 rev = repo.lookup(rev)
648 change = repo.changelog.read(rev)
648 change = repo.changelog.read(rev)
649 n = change[0]
649 n = change[0]
650 files = repo.manifest.read(n)
650 files = repo.manifest.read(n)
651 wlock = repo.wlock()
651 wlock = repo.wlock()
652 repo.dirstate.rebuild(rev, files)
652 repo.dirstate.rebuild(rev, files)
653
653
654 def debugcheckstate(ui, repo):
654 def debugcheckstate(ui, repo):
655 """validate the correctness of the current dirstate"""
655 """validate the correctness of the current dirstate"""
656 parent1, parent2 = repo.dirstate.parents()
656 parent1, parent2 = repo.dirstate.parents()
657 repo.dirstate.read()
657 repo.dirstate.read()
658 dc = repo.dirstate.map
658 dc = repo.dirstate.map
659 keys = dc.keys()
659 keys = dc.keys()
660 keys.sort()
660 keys.sort()
661 m1n = repo.changelog.read(parent1)[0]
661 m1n = repo.changelog.read(parent1)[0]
662 m2n = repo.changelog.read(parent2)[0]
662 m2n = repo.changelog.read(parent2)[0]
663 m1 = repo.manifest.read(m1n)
663 m1 = repo.manifest.read(m1n)
664 m2 = repo.manifest.read(m2n)
664 m2 = repo.manifest.read(m2n)
665 errors = 0
665 errors = 0
666 for f in dc:
666 for f in dc:
667 state = repo.dirstate.state(f)
667 state = repo.dirstate.state(f)
668 if state in "nr" and f not in m1:
668 if state in "nr" and f not in m1:
669 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
669 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
670 errors += 1
670 errors += 1
671 if state in "a" and f in m1:
671 if state in "a" and f in m1:
672 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
672 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
673 errors += 1
673 errors += 1
674 if state in "m" and f not in m1 and f not in m2:
674 if state in "m" and f not in m1 and f not in m2:
675 ui.warn(_("%s in state %s, but not in either manifest\n") %
675 ui.warn(_("%s in state %s, but not in either manifest\n") %
676 (f, state))
676 (f, state))
677 errors += 1
677 errors += 1
678 for f in m1:
678 for f in m1:
679 state = repo.dirstate.state(f)
679 state = repo.dirstate.state(f)
680 if state not in "nrm":
680 if state not in "nrm":
681 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
681 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
682 errors += 1
682 errors += 1
683 if errors:
683 if errors:
684 error = _(".hg/dirstate inconsistent with current parent's manifest")
684 error = _(".hg/dirstate inconsistent with current parent's manifest")
685 raise util.Abort(error)
685 raise util.Abort(error)
686
686
687 def showconfig(ui, repo, *values, **opts):
687 def showconfig(ui, repo, *values, **opts):
688 """show combined config settings from all hgrc files
688 """show combined config settings from all hgrc files
689
689
690 With no args, print names and values of all config items.
690 With no args, print names and values of all config items.
691
691
692 With one arg of the form section.name, print just the value of
692 With one arg of the form section.name, print just the value of
693 that config item.
693 that config item.
694
694
695 With multiple args, print names and values of all config items
695 With multiple args, print names and values of all config items
696 with matching section names."""
696 with matching section names."""
697
697
698 untrusted = bool(opts.get('untrusted'))
698 untrusted = bool(opts.get('untrusted'))
699 if values:
699 if values:
700 if len([v for v in values if '.' in v]) > 1:
700 if len([v for v in values if '.' in v]) > 1:
701 raise util.Abort(_('only one config item permitted'))
701 raise util.Abort(_('only one config item permitted'))
702 for section, name, value in ui.walkconfig(untrusted=untrusted):
702 for section, name, value in ui.walkconfig(untrusted=untrusted):
703 sectname = section + '.' + name
703 sectname = section + '.' + name
704 if values:
704 if values:
705 for v in values:
705 for v in values:
706 if v == section:
706 if v == section:
707 ui.write('%s=%s\n' % (sectname, value))
707 ui.write('%s=%s\n' % (sectname, value))
708 elif v == sectname:
708 elif v == sectname:
709 ui.write(value, '\n')
709 ui.write(value, '\n')
710 else:
710 else:
711 ui.write('%s=%s\n' % (sectname, value))
711 ui.write('%s=%s\n' % (sectname, value))
712
712
713 def debugsetparents(ui, repo, rev1, rev2=None):
713 def debugsetparents(ui, repo, rev1, rev2=None):
714 """manually set the parents of the current working directory
714 """manually set the parents of the current working directory
715
715
716 This is useful for writing repository conversion tools, but should
716 This is useful for writing repository conversion tools, but should
717 be used with care.
717 be used with care.
718 """
718 """
719
719
720 if not rev2:
720 if not rev2:
721 rev2 = hex(nullid)
721 rev2 = hex(nullid)
722
722
723 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
723 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
724
724
725 def debugstate(ui, repo):
725 def debugstate(ui, repo):
726 """show the contents of the current dirstate"""
726 """show the contents of the current dirstate"""
727 repo.dirstate.read()
727 repo.dirstate.read()
728 dc = repo.dirstate.map
728 dc = repo.dirstate.map
729 keys = dc.keys()
729 keys = dc.keys()
730 keys.sort()
730 keys.sort()
731 for file_ in keys:
731 for file_ in keys:
732 ui.write("%c %3o %10d %s %s\n"
732 ui.write("%c %3o %10d %s %s\n"
733 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
733 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
734 time.strftime("%x %X",
734 time.strftime("%x %X",
735 time.localtime(dc[file_][3])), file_))
735 time.localtime(dc[file_][3])), file_))
736 for f in repo.dirstate.copies():
736 for f in repo.dirstate.copies():
737 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
737 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
738
738
739 def debugdata(ui, file_, rev):
739 def debugdata(ui, file_, rev):
740 """dump the contents of an data file revision"""
740 """dump the contents of an data file revision"""
741 r = revlog.revlog(util.opener(os.getcwd(), audit=False),
741 r = revlog.revlog(util.opener(os.getcwd(), audit=False),
742 file_[:-2] + ".i", file_, 0)
742 file_[:-2] + ".i", file_, 0)
743 try:
743 try:
744 ui.write(r.revision(r.lookup(rev)))
744 ui.write(r.revision(r.lookup(rev)))
745 except KeyError:
745 except KeyError:
746 raise util.Abort(_('invalid revision identifier %s') % rev)
746 raise util.Abort(_('invalid revision identifier %s') % rev)
747
747
748 def debugindex(ui, file_):
748 def debugindex(ui, file_):
749 """dump the contents of an index file"""
749 """dump the contents of an index file"""
750 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0)
750 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0)
751 ui.write(" rev offset length base linkrev" +
751 ui.write(" rev offset length base linkrev" +
752 " nodeid p1 p2\n")
752 " nodeid p1 p2\n")
753 for i in xrange(r.count()):
753 for i in xrange(r.count()):
754 node = r.node(i)
754 node = r.node(i)
755 pp = r.parents(node)
755 pp = r.parents(node)
756 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
756 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
757 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
757 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
758 short(node), short(pp[0]), short(pp[1])))
758 short(node), short(pp[0]), short(pp[1])))
759
759
760 def debugindexdot(ui, file_):
760 def debugindexdot(ui, file_):
761 """dump an index DAG as a .dot file"""
761 """dump an index DAG as a .dot file"""
762 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0)
762 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0)
763 ui.write("digraph G {\n")
763 ui.write("digraph G {\n")
764 for i in xrange(r.count()):
764 for i in xrange(r.count()):
765 node = r.node(i)
765 node = r.node(i)
766 pp = r.parents(node)
766 pp = r.parents(node)
767 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
767 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
768 if pp[1] != nullid:
768 if pp[1] != nullid:
769 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
769 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
770 ui.write("}\n")
770 ui.write("}\n")
771
771
772 def debugrename(ui, repo, file1, *pats, **opts):
772 def debugrename(ui, repo, file1, *pats, **opts):
773 """dump rename information"""
773 """dump rename information"""
774
774
775 ctx = repo.changectx(opts.get('rev', 'tip'))
775 ctx = repo.changectx(opts.get('rev', 'tip'))
776 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
776 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
777 ctx.node()):
777 ctx.node()):
778 m = ctx.filectx(abs).renamed()
778 m = ctx.filectx(abs).renamed()
779 if m:
779 if m:
780 ui.write(_("%s renamed from %s:%s\n") % (rel, m[0], hex(m[1])))
780 ui.write(_("%s renamed from %s:%s\n") % (rel, m[0], hex(m[1])))
781 else:
781 else:
782 ui.write(_("%s not renamed\n") % rel)
782 ui.write(_("%s not renamed\n") % rel)
783
783
784 def debugwalk(ui, repo, *pats, **opts):
784 def debugwalk(ui, repo, *pats, **opts):
785 """show how files match on given patterns"""
785 """show how files match on given patterns"""
786 items = list(cmdutil.walk(repo, pats, opts))
786 items = list(cmdutil.walk(repo, pats, opts))
787 if not items:
787 if not items:
788 return
788 return
789 fmt = '%%s %%-%ds %%-%ds %%s' % (
789 fmt = '%%s %%-%ds %%-%ds %%s' % (
790 max([len(abs) for (src, abs, rel, exact) in items]),
790 max([len(abs) for (src, abs, rel, exact) in items]),
791 max([len(rel) for (src, abs, rel, exact) in items]))
791 max([len(rel) for (src, abs, rel, exact) in items]))
792 for src, abs, rel, exact in items:
792 for src, abs, rel, exact in items:
793 line = fmt % (src, abs, rel, exact and 'exact' or '')
793 line = fmt % (src, abs, rel, exact and 'exact' or '')
794 ui.write("%s\n" % line.rstrip())
794 ui.write("%s\n" % line.rstrip())
795
795
796 def diff(ui, repo, *pats, **opts):
796 def diff(ui, repo, *pats, **opts):
797 """diff repository (or selected files)
797 """diff repository (or selected files)
798
798
799 Show differences between revisions for the specified files.
799 Show differences between revisions for the specified files.
800
800
801 Differences between files are shown using the unified diff format.
801 Differences between files are shown using the unified diff format.
802
802
803 When two revision arguments are given, then changes are shown
803 When two revision arguments are given, then changes are shown
804 between those revisions. If only one revision is specified then
804 between those revisions. If only one revision is specified then
805 that revision is compared to the working directory, and, when no
805 that revision is compared to the working directory, and, when no
806 revisions are specified, the working directory files are compared
806 revisions are specified, the working directory files are compared
807 to its parent.
807 to its parent.
808
808
809 Without the -a option, diff will avoid generating diffs of files
809 Without the -a option, diff will avoid generating diffs of files
810 it detects as binary. With -a, diff will generate a diff anyway,
810 it detects as binary. With -a, diff will generate a diff anyway,
811 probably with undesirable results.
811 probably with undesirable results.
812 """
812 """
813 node1, node2 = cmdutil.revpair(ui, repo, opts['rev'])
813 node1, node2 = cmdutil.revpair(ui, repo, opts['rev'])
814
814
815 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
815 fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
816
816
817 patch.diff(repo, node1, node2, fns, match=matchfn,
817 patch.diff(repo, node1, node2, fns, match=matchfn,
818 opts=patch.diffopts(ui, opts))
818 opts=patch.diffopts(ui, opts))
819
819
820 def export(ui, repo, *changesets, **opts):
820 def export(ui, repo, *changesets, **opts):
821 """dump the header and diffs for one or more changesets
821 """dump the header and diffs for one or more changesets
822
822
823 Print the changeset header and diffs for one or more revisions.
823 Print the changeset header and diffs for one or more revisions.
824
824
825 The information shown in the changeset header is: author,
825 The information shown in the changeset header is: author,
826 changeset hash, parent and commit comment.
826 changeset hash, parent and commit comment.
827
827
828 Output may be to a file, in which case the name of the file is
828 Output may be to a file, in which case the name of the file is
829 given using a format string. The formatting rules are as follows:
829 given using a format string. The formatting rules are as follows:
830
830
831 %% literal "%" character
831 %% literal "%" character
832 %H changeset hash (40 bytes of hexadecimal)
832 %H changeset hash (40 bytes of hexadecimal)
833 %N number of patches being generated
833 %N number of patches being generated
834 %R changeset revision number
834 %R changeset revision number
835 %b basename of the exporting repository
835 %b basename of the exporting repository
836 %h short-form changeset hash (12 bytes of hexadecimal)
836 %h short-form changeset hash (12 bytes of hexadecimal)
837 %n zero-padded sequence number, starting at 1
837 %n zero-padded sequence number, starting at 1
838 %r zero-padded changeset revision number
838 %r zero-padded changeset revision number
839
839
840 Without the -a option, export will avoid generating diffs of files
840 Without the -a option, export will avoid generating diffs of files
841 it detects as binary. With -a, export will generate a diff anyway,
841 it detects as binary. With -a, export will generate a diff anyway,
842 probably with undesirable results.
842 probably with undesirable results.
843
843
844 With the --switch-parent option, the diff will be against the second
844 With the --switch-parent option, the diff will be against the second
845 parent. It can be useful to review a merge.
845 parent. It can be useful to review a merge.
846 """
846 """
847 if not changesets:
847 if not changesets:
848 raise util.Abort(_("export requires at least one changeset"))
848 raise util.Abort(_("export requires at least one changeset"))
849 revs = cmdutil.revrange(ui, repo, changesets)
849 revs = cmdutil.revrange(ui, repo, changesets)
850 if len(revs) > 1:
850 if len(revs) > 1:
851 ui.note(_('exporting patches:\n'))
851 ui.note(_('exporting patches:\n'))
852 else:
852 else:
853 ui.note(_('exporting patch:\n'))
853 ui.note(_('exporting patch:\n'))
854 patch.export(repo, map(repo.lookup, revs), template=opts['output'],
854 patch.export(repo, map(repo.lookup, revs), template=opts['output'],
855 switch_parent=opts['switch_parent'],
855 switch_parent=opts['switch_parent'],
856 opts=patch.diffopts(ui, opts))
856 opts=patch.diffopts(ui, opts))
857
857
858 def grep(ui, repo, pattern, *pats, **opts):
858 def grep(ui, repo, pattern, *pats, **opts):
859 """search for a pattern in specified files and revisions
859 """search for a pattern in specified files and revisions
860
860
861 Search revisions of files for a regular expression.
861 Search revisions of files for a regular expression.
862
862
863 This command behaves differently than Unix grep. It only accepts
863 This command behaves differently than Unix grep. It only accepts
864 Python/Perl regexps. It searches repository history, not the
864 Python/Perl regexps. It searches repository history, not the
865 working directory. It always prints the revision number in which
865 working directory. It always prints the revision number in which
866 a match appears.
866 a match appears.
867
867
868 By default, grep only prints output for the first revision of a
868 By default, grep only prints output for the first revision of a
869 file in which it finds a match. To get it to print every revision
869 file in which it finds a match. To get it to print every revision
870 that contains a change in match status ("-" for a match that
870 that contains a change in match status ("-" for a match that
871 becomes a non-match, or "+" for a non-match that becomes a match),
871 becomes a non-match, or "+" for a non-match that becomes a match),
872 use the --all flag.
872 use the --all flag.
873 """
873 """
874 reflags = 0
874 reflags = 0
875 if opts['ignore_case']:
875 if opts['ignore_case']:
876 reflags |= re.I
876 reflags |= re.I
877 regexp = re.compile(pattern, reflags)
877 regexp = re.compile(pattern, reflags)
878 sep, eol = ':', '\n'
878 sep, eol = ':', '\n'
879 if opts['print0']:
879 if opts['print0']:
880 sep = eol = '\0'
880 sep = eol = '\0'
881
881
882 fcache = {}
882 fcache = {}
883 def getfile(fn):
883 def getfile(fn):
884 if fn not in fcache:
884 if fn not in fcache:
885 fcache[fn] = repo.file(fn)
885 fcache[fn] = repo.file(fn)
886 return fcache[fn]
886 return fcache[fn]
887
887
888 def matchlines(body):
888 def matchlines(body):
889 begin = 0
889 begin = 0
890 linenum = 0
890 linenum = 0
891 while True:
891 while True:
892 match = regexp.search(body, begin)
892 match = regexp.search(body, begin)
893 if not match:
893 if not match:
894 break
894 break
895 mstart, mend = match.span()
895 mstart, mend = match.span()
896 linenum += body.count('\n', begin, mstart) + 1
896 linenum += body.count('\n', begin, mstart) + 1
897 lstart = body.rfind('\n', begin, mstart) + 1 or begin
897 lstart = body.rfind('\n', begin, mstart) + 1 or begin
898 lend = body.find('\n', mend)
898 lend = body.find('\n', mend)
899 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
899 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
900 begin = lend + 1
900 begin = lend + 1
901
901
902 class linestate(object):
902 class linestate(object):
903 def __init__(self, line, linenum, colstart, colend):
903 def __init__(self, line, linenum, colstart, colend):
904 self.line = line
904 self.line = line
905 self.linenum = linenum
905 self.linenum = linenum
906 self.colstart = colstart
906 self.colstart = colstart
907 self.colend = colend
907 self.colend = colend
908
908
909 def __eq__(self, other):
909 def __eq__(self, other):
910 return self.line == other.line
910 return self.line == other.line
911
911
912 matches = {}
912 matches = {}
913 copies = {}
913 copies = {}
914 def grepbody(fn, rev, body):
914 def grepbody(fn, rev, body):
915 matches[rev].setdefault(fn, [])
915 matches[rev].setdefault(fn, [])
916 m = matches[rev][fn]
916 m = matches[rev][fn]
917 for lnum, cstart, cend, line in matchlines(body):
917 for lnum, cstart, cend, line in matchlines(body):
918 s = linestate(line, lnum, cstart, cend)
918 s = linestate(line, lnum, cstart, cend)
919 m.append(s)
919 m.append(s)
920
920
921 def difflinestates(a, b):
921 def difflinestates(a, b):
922 sm = difflib.SequenceMatcher(None, a, b)
922 sm = difflib.SequenceMatcher(None, a, b)
923 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
923 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
924 if tag == 'insert':
924 if tag == 'insert':
925 for i in xrange(blo, bhi):
925 for i in xrange(blo, bhi):
926 yield ('+', b[i])
926 yield ('+', b[i])
927 elif tag == 'delete':
927 elif tag == 'delete':
928 for i in xrange(alo, ahi):
928 for i in xrange(alo, ahi):
929 yield ('-', a[i])
929 yield ('-', a[i])
930 elif tag == 'replace':
930 elif tag == 'replace':
931 for i in xrange(alo, ahi):
931 for i in xrange(alo, ahi):
932 yield ('-', a[i])
932 yield ('-', a[i])
933 for i in xrange(blo, bhi):
933 for i in xrange(blo, bhi):
934 yield ('+', b[i])
934 yield ('+', b[i])
935
935
936 prev = {}
936 prev = {}
937 def display(fn, rev, states, prevstates):
937 def display(fn, rev, states, prevstates):
938 counts = {'-': 0, '+': 0}
938 counts = {'-': 0, '+': 0}
939 filerevmatches = {}
939 filerevmatches = {}
940 if incrementing or not opts['all']:
940 if incrementing or not opts['all']:
941 a, b, r = prevstates, states, rev
941 a, b, r = prevstates, states, rev
942 else:
942 else:
943 a, b, r = states, prevstates, prev.get(fn, -1)
943 a, b, r = states, prevstates, prev.get(fn, -1)
944 for change, l in difflinestates(a, b):
944 for change, l in difflinestates(a, b):
945 cols = [fn, str(r)]
945 cols = [fn, str(r)]
946 if opts['line_number']:
946 if opts['line_number']:
947 cols.append(str(l.linenum))
947 cols.append(str(l.linenum))
948 if opts['all']:
948 if opts['all']:
949 cols.append(change)
949 cols.append(change)
950 if opts['user']:
950 if opts['user']:
951 cols.append(ui.shortuser(get(r)[1]))
951 cols.append(ui.shortuser(get(r)[1]))
952 if opts['files_with_matches']:
952 if opts['files_with_matches']:
953 c = (fn, r)
953 c = (fn, r)
954 if c in filerevmatches:
954 if c in filerevmatches:
955 continue
955 continue
956 filerevmatches[c] = 1
956 filerevmatches[c] = 1
957 else:
957 else:
958 cols.append(l.line)
958 cols.append(l.line)
959 ui.write(sep.join(cols), eol)
959 ui.write(sep.join(cols), eol)
960 counts[change] += 1
960 counts[change] += 1
961 return counts['+'], counts['-']
961 return counts['+'], counts['-']
962
962
963 fstate = {}
963 fstate = {}
964 skip = {}
964 skip = {}
965 get = util.cachefunc(lambda r:repo.changectx(r).changeset())
965 get = util.cachefunc(lambda r:repo.changectx(r).changeset())
966 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
966 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
967 count = 0
967 count = 0
968 incrementing = False
968 incrementing = False
969 follow = opts.get('follow')
969 follow = opts.get('follow')
970 for st, rev, fns in changeiter:
970 for st, rev, fns in changeiter:
971 if st == 'window':
971 if st == 'window':
972 incrementing = rev
972 incrementing = rev
973 matches.clear()
973 matches.clear()
974 elif st == 'add':
974 elif st == 'add':
975 mf = repo.changectx(rev).manifest()
975 mf = repo.changectx(rev).manifest()
976 matches[rev] = {}
976 matches[rev] = {}
977 for fn in fns:
977 for fn in fns:
978 if fn in skip:
978 if fn in skip:
979 continue
979 continue
980 fstate.setdefault(fn, {})
980 fstate.setdefault(fn, {})
981 try:
981 try:
982 grepbody(fn, rev, getfile(fn).read(mf[fn]))
982 grepbody(fn, rev, getfile(fn).read(mf[fn]))
983 if follow:
983 if follow:
984 copied = getfile(fn).renamed(mf[fn])
984 copied = getfile(fn).renamed(mf[fn])
985 if copied:
985 if copied:
986 copies.setdefault(rev, {})[fn] = copied[0]
986 copies.setdefault(rev, {})[fn] = copied[0]
987 except KeyError:
987 except KeyError:
988 pass
988 pass
989 elif st == 'iter':
989 elif st == 'iter':
990 states = matches[rev].items()
990 states = matches[rev].items()
991 states.sort()
991 states.sort()
992 for fn, m in states:
992 for fn, m in states:
993 copy = copies.get(rev, {}).get(fn)
993 copy = copies.get(rev, {}).get(fn)
994 if fn in skip:
994 if fn in skip:
995 if copy:
995 if copy:
996 skip[copy] = True
996 skip[copy] = True
997 continue
997 continue
998 if incrementing or not opts['all'] or fstate[fn]:
998 if incrementing or not opts['all'] or fstate[fn]:
999 pos, neg = display(fn, rev, m, fstate[fn])
999 pos, neg = display(fn, rev, m, fstate[fn])
1000 count += pos + neg
1000 count += pos + neg
1001 if pos and not opts['all']:
1001 if pos and not opts['all']:
1002 skip[fn] = True
1002 skip[fn] = True
1003 if copy:
1003 if copy:
1004 skip[copy] = True
1004 skip[copy] = True
1005 fstate[fn] = m
1005 fstate[fn] = m
1006 if copy:
1006 if copy:
1007 fstate[copy] = m
1007 fstate[copy] = m
1008 prev[fn] = rev
1008 prev[fn] = rev
1009
1009
1010 if not incrementing:
1010 if not incrementing:
1011 fstate = fstate.items()
1011 fstate = fstate.items()
1012 fstate.sort()
1012 fstate.sort()
1013 for fn, state in fstate:
1013 for fn, state in fstate:
1014 if fn in skip:
1014 if fn in skip:
1015 continue
1015 continue
1016 if fn not in copies.get(prev[fn], {}):
1016 if fn not in copies.get(prev[fn], {}):
1017 display(fn, rev, {}, state)
1017 display(fn, rev, {}, state)
1018 return (count == 0 and 1) or 0
1018 return (count == 0 and 1) or 0
1019
1019
1020 def heads(ui, repo, **opts):
1020 def heads(ui, repo, **opts):
1021 """show current repository heads
1021 """show current repository heads
1022
1022
1023 Show all repository head changesets.
1023 Show all repository head changesets.
1024
1024
1025 Repository "heads" are changesets that don't have children
1025 Repository "heads" are changesets that don't have children
1026 changesets. They are where development generally takes place and
1026 changesets. They are where development generally takes place and
1027 are the usual targets for update and merge operations.
1027 are the usual targets for update and merge operations.
1028 """
1028 """
1029 if opts['rev']:
1029 if opts['rev']:
1030 heads = repo.heads(repo.lookup(opts['rev']))
1030 heads = repo.heads(repo.lookup(opts['rev']))
1031 else:
1031 else:
1032 heads = repo.heads()
1032 heads = repo.heads()
1033 displayer = cmdutil.show_changeset(ui, repo, opts)
1033 displayer = cmdutil.show_changeset(ui, repo, opts)
1034 for n in heads:
1034 for n in heads:
1035 displayer.show(changenode=n)
1035 displayer.show(changenode=n)
1036
1036
1037 def help_(ui, name=None, with_version=False):
1037 def help_(ui, name=None, with_version=False):
1038 """show help for a command, extension, or list of commands
1038 """show help for a command, extension, or list of commands
1039
1039
1040 With no arguments, print a list of commands and short help.
1040 With no arguments, print a list of commands and short help.
1041
1041
1042 Given a command name, print help for that command.
1042 Given a command name, print help for that command.
1043
1043
1044 Given an extension name, print help for that extension, and the
1044 Given an extension name, print help for that extension, and the
1045 commands it provides."""
1045 commands it provides."""
1046 option_lists = []
1046 option_lists = []
1047
1047
1048 def helpcmd(name):
1048 def helpcmd(name):
1049 if with_version:
1049 if with_version:
1050 version_(ui)
1050 version_(ui)
1051 ui.write('\n')
1051 ui.write('\n')
1052 aliases, i = findcmd(ui, name)
1052 aliases, i = findcmd(ui, name)
1053 # synopsis
1053 # synopsis
1054 ui.write("%s\n\n" % i[2])
1054 ui.write("%s\n\n" % i[2])
1055
1055
1056 # description
1056 # description
1057 doc = i[0].__doc__
1057 doc = i[0].__doc__
1058 if not doc:
1058 if not doc:
1059 doc = _("(No help text available)")
1059 doc = _("(No help text available)")
1060 if ui.quiet:
1060 if ui.quiet:
1061 doc = doc.splitlines(0)[0]
1061 doc = doc.splitlines(0)[0]
1062 ui.write("%s\n" % doc.rstrip())
1062 ui.write("%s\n" % doc.rstrip())
1063
1063
1064 if not ui.quiet:
1064 if not ui.quiet:
1065 # aliases
1065 # aliases
1066 if len(aliases) > 1:
1066 if len(aliases) > 1:
1067 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1067 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1068
1068
1069 # options
1069 # options
1070 if i[1]:
1070 if i[1]:
1071 option_lists.append(("options", i[1]))
1071 option_lists.append(("options", i[1]))
1072
1072
1073 def helplist(select=None):
1073 def helplist(select=None):
1074 h = {}
1074 h = {}
1075 cmds = {}
1075 cmds = {}
1076 for c, e in table.items():
1076 for c, e in table.items():
1077 f = c.split("|", 1)[0]
1077 f = c.split("|", 1)[0]
1078 if select and not select(f):
1078 if select and not select(f):
1079 continue
1079 continue
1080 if name == "shortlist" and not f.startswith("^"):
1080 if name == "shortlist" and not f.startswith("^"):
1081 continue
1081 continue
1082 f = f.lstrip("^")
1082 f = f.lstrip("^")
1083 if not ui.debugflag and f.startswith("debug"):
1083 if not ui.debugflag and f.startswith("debug"):
1084 continue
1084 continue
1085 doc = e[0].__doc__
1085 doc = e[0].__doc__
1086 if not doc:
1086 if not doc:
1087 doc = _("(No help text available)")
1087 doc = _("(No help text available)")
1088 h[f] = doc.splitlines(0)[0].rstrip()
1088 h[f] = doc.splitlines(0)[0].rstrip()
1089 cmds[f] = c.lstrip("^")
1089 cmds[f] = c.lstrip("^")
1090
1090
1091 fns = h.keys()
1091 fns = h.keys()
1092 fns.sort()
1092 fns.sort()
1093 m = max(map(len, fns))
1093 m = max(map(len, fns))
1094 for f in fns:
1094 for f in fns:
1095 if ui.verbose:
1095 if ui.verbose:
1096 commands = cmds[f].replace("|",", ")
1096 commands = cmds[f].replace("|",", ")
1097 ui.write(" %s:\n %s\n"%(commands, h[f]))
1097 ui.write(" %s:\n %s\n"%(commands, h[f]))
1098 else:
1098 else:
1099 ui.write(' %-*s %s\n' % (m, f, h[f]))
1099 ui.write(' %-*s %s\n' % (m, f, h[f]))
1100
1100
1101 def helpext(name):
1101 def helpext(name):
1102 try:
1102 try:
1103 mod = findext(name)
1103 mod = findext(name)
1104 except KeyError:
1104 except KeyError:
1105 raise UnknownCommand(name)
1105 raise UnknownCommand(name)
1106
1106
1107 doc = (mod.__doc__ or _('No help text available')).splitlines(0)
1107 doc = (mod.__doc__ or _('No help text available')).splitlines(0)
1108 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1108 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1109 for d in doc[1:]:
1109 for d in doc[1:]:
1110 ui.write(d, '\n')
1110 ui.write(d, '\n')
1111
1111
1112 ui.status('\n')
1112 ui.status('\n')
1113 if ui.verbose:
1113 if ui.verbose:
1114 ui.status(_('list of commands:\n\n'))
1114 ui.status(_('list of commands:\n\n'))
1115 else:
1115 else:
1116 ui.status(_('list of commands (use "hg help -v %s" '
1116 ui.status(_('list of commands (use "hg help -v %s" '
1117 'to show aliases and global options):\n\n') % name)
1117 'to show aliases and global options):\n\n') % name)
1118
1118
1119 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in mod.cmdtable])
1119 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in mod.cmdtable])
1120 helplist(modcmds.has_key)
1120 helplist(modcmds.has_key)
1121
1121
1122 if name and name != 'shortlist':
1122 if name and name != 'shortlist':
1123 try:
1123 try:
1124 helpcmd(name)
1124 helpcmd(name)
1125 except UnknownCommand:
1125 except UnknownCommand:
1126 helpext(name)
1126 helpext(name)
1127
1127
1128 else:
1128 else:
1129 # program name
1129 # program name
1130 if ui.verbose or with_version:
1130 if ui.verbose or with_version:
1131 version_(ui)
1131 version_(ui)
1132 else:
1132 else:
1133 ui.status(_("Mercurial Distributed SCM\n"))
1133 ui.status(_("Mercurial Distributed SCM\n"))
1134 ui.status('\n')
1134 ui.status('\n')
1135
1135
1136 # list of commands
1136 # list of commands
1137 if name == "shortlist":
1137 if name == "shortlist":
1138 ui.status(_('basic commands (use "hg help" '
1138 ui.status(_('basic commands (use "hg help" '
1139 'for the full list or option "-v" for details):\n\n'))
1139 'for the full list or option "-v" for details):\n\n'))
1140 elif ui.verbose:
1140 elif ui.verbose:
1141 ui.status(_('list of commands:\n\n'))
1141 ui.status(_('list of commands:\n\n'))
1142 else:
1142 else:
1143 ui.status(_('list of commands (use "hg help -v" '
1143 ui.status(_('list of commands (use "hg help -v" '
1144 'to show aliases and global options):\n\n'))
1144 'to show aliases and global options):\n\n'))
1145
1145
1146 helplist()
1146 helplist()
1147
1147
1148 # global options
1148 # global options
1149 if ui.verbose:
1149 if ui.verbose:
1150 option_lists.append(("global options", globalopts))
1150 option_lists.append(("global options", globalopts))
1151
1151
1152 # list all option lists
1152 # list all option lists
1153 opt_output = []
1153 opt_output = []
1154 for title, options in option_lists:
1154 for title, options in option_lists:
1155 opt_output.append(("\n%s:\n" % title, None))
1155 opt_output.append(("\n%s:\n" % title, None))
1156 for shortopt, longopt, default, desc in options:
1156 for shortopt, longopt, default, desc in options:
1157 if "DEPRECATED" in desc and not ui.verbose: continue
1157 if "DEPRECATED" in desc and not ui.verbose: continue
1158 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1158 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1159 longopt and " --%s" % longopt),
1159 longopt and " --%s" % longopt),
1160 "%s%s" % (desc,
1160 "%s%s" % (desc,
1161 default
1161 default
1162 and _(" (default: %s)") % default
1162 and _(" (default: %s)") % default
1163 or "")))
1163 or "")))
1164
1164
1165 if opt_output:
1165 if opt_output:
1166 opts_len = max([len(line[0]) for line in opt_output if line[1]])
1166 opts_len = max([len(line[0]) for line in opt_output if line[1]])
1167 for first, second in opt_output:
1167 for first, second in opt_output:
1168 if second:
1168 if second:
1169 ui.write(" %-*s %s\n" % (opts_len, first, second))
1169 ui.write(" %-*s %s\n" % (opts_len, first, second))
1170 else:
1170 else:
1171 ui.write("%s\n" % first)
1171 ui.write("%s\n" % first)
1172
1172
1173 def identify(ui, repo):
1173 def identify(ui, repo):
1174 """print information about the working copy
1174 """print information about the working copy
1175
1175
1176 Print a short summary of the current state of the repo.
1176 Print a short summary of the current state of the repo.
1177
1177
1178 This summary identifies the repository state using one or two parent
1178 This summary identifies the repository state using one or two parent
1179 hash identifiers, followed by a "+" if there are uncommitted changes
1179 hash identifiers, followed by a "+" if there are uncommitted changes
1180 in the working directory, followed by a list of tags for this revision.
1180 in the working directory, followed by a list of tags for this revision.
1181 """
1181 """
1182 parents = [p for p in repo.dirstate.parents() if p != nullid]
1182 parents = [p for p in repo.dirstate.parents() if p != nullid]
1183 if not parents:
1183 if not parents:
1184 ui.write(_("unknown\n"))
1184 ui.write(_("unknown\n"))
1185 return
1185 return
1186
1186
1187 hexfunc = ui.debugflag and hex or short
1187 hexfunc = ui.debugflag and hex or short
1188 modified, added, removed, deleted = repo.status()[:4]
1188 modified, added, removed, deleted = repo.status()[:4]
1189 output = ["%s%s" %
1189 output = ["%s%s" %
1190 ('+'.join([hexfunc(parent) for parent in parents]),
1190 ('+'.join([hexfunc(parent) for parent in parents]),
1191 (modified or added or removed or deleted) and "+" or "")]
1191 (modified or added or removed or deleted) and "+" or "")]
1192
1192
1193 if not ui.quiet:
1193 if not ui.quiet:
1194
1194
1195 branch = repo.workingctx().branch()
1195 branch = repo.workingctx().branch()
1196 if branch:
1196 if branch:
1197 output.append("(%s)" % branch)
1197 output.append("(%s)" % branch)
1198
1198
1199 # multiple tags for a single parent separated by '/'
1199 # multiple tags for a single parent separated by '/'
1200 parenttags = ['/'.join(tags)
1200 parenttags = ['/'.join(tags)
1201 for tags in map(repo.nodetags, parents) if tags]
1201 for tags in map(repo.nodetags, parents) if tags]
1202 # tags for multiple parents separated by ' + '
1202 # tags for multiple parents separated by ' + '
1203 if parenttags:
1203 if parenttags:
1204 output.append(' + '.join(parenttags))
1204 output.append(' + '.join(parenttags))
1205
1205
1206 ui.write("%s\n" % ' '.join(output))
1206 ui.write("%s\n" % ' '.join(output))
1207
1207
1208 def import_(ui, repo, patch1, *patches, **opts):
1208 def import_(ui, repo, patch1, *patches, **opts):
1209 """import an ordered set of patches
1209 """import an ordered set of patches
1210
1210
1211 Import a list of patches and commit them individually.
1211 Import a list of patches and commit them individually.
1212
1212
1213 If there are outstanding changes in the working directory, import
1213 If there are outstanding changes in the working directory, import
1214 will abort unless given the -f flag.
1214 will abort unless given the -f flag.
1215
1215
1216 You can import a patch straight from a mail message. Even patches
1216 You can import a patch straight from a mail message. Even patches
1217 as attachments work (body part must be type text/plain or
1217 as attachments work (body part must be type text/plain or
1218 text/x-patch to be used). From and Subject headers of email
1218 text/x-patch to be used). From and Subject headers of email
1219 message are used as default committer and commit message. All
1219 message are used as default committer and commit message. All
1220 text/plain body parts before first diff are added to commit
1220 text/plain body parts before first diff are added to commit
1221 message.
1221 message.
1222
1222
1223 If imported patch was generated by hg export, user and description
1223 If imported patch was generated by hg export, user and description
1224 from patch override values from message headers and body. Values
1224 from patch override values from message headers and body. Values
1225 given on command line with -m and -u override these.
1225 given on command line with -m and -u override these.
1226
1226
1227 To read a patch from standard input, use patch name "-".
1227 To read a patch from standard input, use patch name "-".
1228 """
1228 """
1229 patches = (patch1,) + patches
1229 patches = (patch1,) + patches
1230
1230
1231 if not opts['force']:
1231 if not opts['force']:
1232 bail_if_changed(repo)
1232 bail_if_changed(repo)
1233
1233
1234 d = opts["base"]
1234 d = opts["base"]
1235 strip = opts["strip"]
1235 strip = opts["strip"]
1236
1236
1237 wlock = repo.wlock()
1237 wlock = repo.wlock()
1238 lock = repo.lock()
1238 lock = repo.lock()
1239
1239
1240 for p in patches:
1240 for p in patches:
1241 pf = os.path.join(d, p)
1241 pf = os.path.join(d, p)
1242
1242
1243 if pf == '-':
1243 if pf == '-':
1244 ui.status(_("applying patch from stdin\n"))
1244 ui.status(_("applying patch from stdin\n"))
1245 tmpname, message, user, date = patch.extract(ui, sys.stdin)
1245 tmpname, message, user, date = patch.extract(ui, sys.stdin)
1246 else:
1246 else:
1247 ui.status(_("applying %s\n") % p)
1247 ui.status(_("applying %s\n") % p)
1248 tmpname, message, user, date = patch.extract(ui, file(pf))
1248 tmpname, message, user, date = patch.extract(ui, file(pf))
1249
1249
1250 if tmpname is None:
1250 if tmpname is None:
1251 raise util.Abort(_('no diffs found'))
1251 raise util.Abort(_('no diffs found'))
1252
1252
1253 try:
1253 try:
1254 if opts['message']:
1254 if opts['message']:
1255 # pickup the cmdline msg
1255 # pickup the cmdline msg
1256 message = opts['message']
1256 message = opts['message']
1257 elif message:
1257 elif message:
1258 # pickup the patch msg
1258 # pickup the patch msg
1259 message = message.strip()
1259 message = message.strip()
1260 else:
1260 else:
1261 # launch the editor
1261 # launch the editor
1262 message = None
1262 message = None
1263 ui.debug(_('message:\n%s\n') % message)
1263 ui.debug(_('message:\n%s\n') % message)
1264
1264
1265 files = {}
1265 files = {}
1266 try:
1266 try:
1267 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1267 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1268 files=files)
1268 files=files)
1269 finally:
1269 finally:
1270 files = patch.updatedir(ui, repo, files, wlock=wlock)
1270 files = patch.updatedir(ui, repo, files, wlock=wlock)
1271 repo.commit(files, message, user, date, wlock=wlock, lock=lock)
1271 repo.commit(files, message, user, date, wlock=wlock, lock=lock)
1272 finally:
1272 finally:
1273 os.unlink(tmpname)
1273 os.unlink(tmpname)
1274
1274
1275 def incoming(ui, repo, source="default", **opts):
1275 def incoming(ui, repo, source="default", **opts):
1276 """show new changesets found in source
1276 """show new changesets found in source
1277
1277
1278 Show new changesets found in the specified path/URL or the default
1278 Show new changesets found in the specified path/URL or the default
1279 pull location. These are the changesets that would be pulled if a pull
1279 pull location. These are the changesets that would be pulled if a pull
1280 was requested.
1280 was requested.
1281
1281
1282 For remote repository, using --bundle avoids downloading the changesets
1282 For remote repository, using --bundle avoids downloading the changesets
1283 twice if the incoming is followed by a pull.
1283 twice if the incoming is followed by a pull.
1284
1284
1285 See pull for valid source format details.
1285 See pull for valid source format details.
1286 """
1286 """
1287 source = ui.expandpath(source)
1287 source = ui.expandpath(source)
1288 setremoteconfig(ui, opts)
1288 setremoteconfig(ui, opts)
1289
1289
1290 other = hg.repository(ui, source)
1290 other = hg.repository(ui, source)
1291 incoming = repo.findincoming(other, force=opts["force"])
1291 incoming = repo.findincoming(other, force=opts["force"])
1292 if not incoming:
1292 if not incoming:
1293 ui.status(_("no changes found\n"))
1293 ui.status(_("no changes found\n"))
1294 return
1294 return
1295
1295
1296 cleanup = None
1296 cleanup = None
1297 try:
1297 try:
1298 fname = opts["bundle"]
1298 fname = opts["bundle"]
1299 if fname or not other.local():
1299 if fname or not other.local():
1300 # create a bundle (uncompressed if other repo is not local)
1300 # create a bundle (uncompressed if other repo is not local)
1301 cg = other.changegroup(incoming, "incoming")
1301 cg = other.changegroup(incoming, "incoming")
1302 type = other.local() and "HG10" or "HG10UN"
1302 type = other.local() and "HG10" or "HG10UN"
1303 fname = cleanup = changegroup.writebundle(cg, fname, type)
1303 fname = cleanup = changegroup.writebundle(cg, fname, type)
1304 # keep written bundle?
1304 # keep written bundle?
1305 if opts["bundle"]:
1305 if opts["bundle"]:
1306 cleanup = None
1306 cleanup = None
1307 if not other.local():
1307 if not other.local():
1308 # use the created uncompressed bundlerepo
1308 # use the created uncompressed bundlerepo
1309 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1309 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1310
1310
1311 revs = None
1311 revs = None
1312 if opts['rev']:
1312 if opts['rev']:
1313 revs = [other.lookup(rev) for rev in opts['rev']]
1313 revs = [other.lookup(rev) for rev in opts['rev']]
1314 o = other.changelog.nodesbetween(incoming, revs)[0]
1314 o = other.changelog.nodesbetween(incoming, revs)[0]
1315 if opts['newest_first']:
1315 if opts['newest_first']:
1316 o.reverse()
1316 o.reverse()
1317 displayer = cmdutil.show_changeset(ui, other, opts)
1317 displayer = cmdutil.show_changeset(ui, other, opts)
1318 for n in o:
1318 for n in o:
1319 parents = [p for p in other.changelog.parents(n) if p != nullid]
1319 parents = [p for p in other.changelog.parents(n) if p != nullid]
1320 if opts['no_merges'] and len(parents) == 2:
1320 if opts['no_merges'] and len(parents) == 2:
1321 continue
1321 continue
1322 displayer.show(changenode=n)
1322 displayer.show(changenode=n)
1323 finally:
1323 finally:
1324 if hasattr(other, 'close'):
1324 if hasattr(other, 'close'):
1325 other.close()
1325 other.close()
1326 if cleanup:
1326 if cleanup:
1327 os.unlink(cleanup)
1327 os.unlink(cleanup)
1328
1328
1329 def init(ui, dest=".", **opts):
1329 def init(ui, dest=".", **opts):
1330 """create a new repository in the given directory
1330 """create a new repository in the given directory
1331
1331
1332 Initialize a new repository in the given directory. If the given
1332 Initialize a new repository in the given directory. If the given
1333 directory does not exist, it is created.
1333 directory does not exist, it is created.
1334
1334
1335 If no directory is given, the current directory is used.
1335 If no directory is given, the current directory is used.
1336
1336
1337 It is possible to specify an ssh:// URL as the destination.
1337 It is possible to specify an ssh:// URL as the destination.
1338 Look at the help text for the pull command for important details
1338 Look at the help text for the pull command for important details
1339 about ssh:// URLs.
1339 about ssh:// URLs.
1340 """
1340 """
1341 setremoteconfig(ui, opts)
1341 setremoteconfig(ui, opts)
1342 hg.repository(ui, dest, create=1)
1342 hg.repository(ui, dest, create=1)
1343
1343
1344 def locate(ui, repo, *pats, **opts):
1344 def locate(ui, repo, *pats, **opts):
1345 """locate files matching specific patterns
1345 """locate files matching specific patterns
1346
1346
1347 Print all files under Mercurial control whose names match the
1347 Print all files under Mercurial control whose names match the
1348 given patterns.
1348 given patterns.
1349
1349
1350 This command searches the current directory and its
1350 This command searches the current directory and its
1351 subdirectories. To search an entire repository, move to the root
1351 subdirectories. To search an entire repository, move to the root
1352 of the repository.
1352 of the repository.
1353
1353
1354 If no patterns are given to match, this command prints all file
1354 If no patterns are given to match, this command prints all file
1355 names.
1355 names.
1356
1356
1357 If you want to feed the output of this command into the "xargs"
1357 If you want to feed the output of this command into the "xargs"
1358 command, use the "-0" option to both this command and "xargs".
1358 command, use the "-0" option to both this command and "xargs".
1359 This will avoid the problem of "xargs" treating single filenames
1359 This will avoid the problem of "xargs" treating single filenames
1360 that contain white space as multiple filenames.
1360 that contain white space as multiple filenames.
1361 """
1361 """
1362 end = opts['print0'] and '\0' or '\n'
1362 end = opts['print0'] and '\0' or '\n'
1363 rev = opts['rev']
1363 rev = opts['rev']
1364 if rev:
1364 if rev:
1365 node = repo.lookup(rev)
1365 node = repo.lookup(rev)
1366 else:
1366 else:
1367 node = None
1367 node = None
1368
1368
1369 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
1369 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
1370 head='(?:.*/|)'):
1370 head='(?:.*/|)'):
1371 if not node and repo.dirstate.state(abs) == '?':
1371 if not node and repo.dirstate.state(abs) == '?':
1372 continue
1372 continue
1373 if opts['fullpath']:
1373 if opts['fullpath']:
1374 ui.write(os.path.join(repo.root, abs), end)
1374 ui.write(os.path.join(repo.root, abs), end)
1375 else:
1375 else:
1376 ui.write(((pats and rel) or abs), end)
1376 ui.write(((pats and rel) or abs), end)
1377
1377
1378 def log(ui, repo, *pats, **opts):
1378 def log(ui, repo, *pats, **opts):
1379 """show revision history of entire repository or files
1379 """show revision history of entire repository or files
1380
1380
1381 Print the revision history of the specified files or the entire
1381 Print the revision history of the specified files or the entire
1382 project.
1382 project.
1383
1383
1384 File history is shown without following rename or copy history of
1384 File history is shown without following rename or copy history of
1385 files. Use -f/--follow with a file name to follow history across
1385 files. Use -f/--follow with a file name to follow history across
1386 renames and copies. --follow without a file name will only show
1386 renames and copies. --follow without a file name will only show
1387 ancestors or descendants of the starting revision. --follow-first
1387 ancestors or descendants of the starting revision. --follow-first
1388 only follows the first parent of merge revisions.
1388 only follows the first parent of merge revisions.
1389
1389
1390 If no revision range is specified, the default is tip:0 unless
1390 If no revision range is specified, the default is tip:0 unless
1391 --follow is set, in which case the working directory parent is
1391 --follow is set, in which case the working directory parent is
1392 used as the starting revision.
1392 used as the starting revision.
1393
1393
1394 By default this command outputs: changeset id and hash, tags,
1394 By default this command outputs: changeset id and hash, tags,
1395 non-trivial parents, user, date and time, and a summary for each
1395 non-trivial parents, user, date and time, and a summary for each
1396 commit. When the -v/--verbose switch is used, the list of changed
1396 commit. When the -v/--verbose switch is used, the list of changed
1397 files and full commit message is shown.
1397 files and full commit message is shown.
1398 """
1398 """
1399
1399
1400 get = util.cachefunc(lambda r:repo.changectx(r).changeset())
1400 get = util.cachefunc(lambda r:repo.changectx(r).changeset())
1401 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1401 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1402
1402
1403 if opts['limit']:
1403 if opts['limit']:
1404 try:
1404 try:
1405 limit = int(opts['limit'])
1405 limit = int(opts['limit'])
1406 except ValueError:
1406 except ValueError:
1407 raise util.Abort(_('limit must be a positive integer'))
1407 raise util.Abort(_('limit must be a positive integer'))
1408 if limit <= 0: raise util.Abort(_('limit must be positive'))
1408 if limit <= 0: raise util.Abort(_('limit must be positive'))
1409 else:
1409 else:
1410 limit = sys.maxint
1410 limit = sys.maxint
1411 count = 0
1411 count = 0
1412
1412
1413 if opts['copies'] and opts['rev']:
1413 if opts['copies'] and opts['rev']:
1414 endrev = max(cmdutil.revrange(ui, repo, opts['rev'])) + 1
1414 endrev = max(cmdutil.revrange(ui, repo, opts['rev'])) + 1
1415 else:
1415 else:
1416 endrev = repo.changelog.count()
1416 endrev = repo.changelog.count()
1417 rcache = {}
1417 rcache = {}
1418 ncache = {}
1418 ncache = {}
1419 dcache = []
1419 dcache = []
1420 def getrenamed(fn, rev, man):
1420 def getrenamed(fn, rev, man):
1421 '''looks up all renames for a file (up to endrev) the first
1421 '''looks up all renames for a file (up to endrev) the first
1422 time the file is given. It indexes on the changerev and only
1422 time the file is given. It indexes on the changerev and only
1423 parses the manifest if linkrev != changerev.
1423 parses the manifest if linkrev != changerev.
1424 Returns rename info for fn at changerev rev.'''
1424 Returns rename info for fn at changerev rev.'''
1425 if fn not in rcache:
1425 if fn not in rcache:
1426 rcache[fn] = {}
1426 rcache[fn] = {}
1427 ncache[fn] = {}
1427 ncache[fn] = {}
1428 fl = repo.file(fn)
1428 fl = repo.file(fn)
1429 for i in xrange(fl.count()):
1429 for i in xrange(fl.count()):
1430 node = fl.node(i)
1430 node = fl.node(i)
1431 lr = fl.linkrev(node)
1431 lr = fl.linkrev(node)
1432 renamed = fl.renamed(node)
1432 renamed = fl.renamed(node)
1433 rcache[fn][lr] = renamed
1433 rcache[fn][lr] = renamed
1434 if renamed:
1434 if renamed:
1435 ncache[fn][node] = renamed
1435 ncache[fn][node] = renamed
1436 if lr >= endrev:
1436 if lr >= endrev:
1437 break
1437 break
1438 if rev in rcache[fn]:
1438 if rev in rcache[fn]:
1439 return rcache[fn][rev]
1439 return rcache[fn][rev]
1440 mr = repo.manifest.rev(man)
1440 mr = repo.manifest.rev(man)
1441 if repo.manifest.parentrevs(mr) != (mr - 1, nullrev):
1441 if repo.manifest.parentrevs(mr) != (mr - 1, nullrev):
1442 return ncache[fn].get(repo.manifest.find(man, fn)[0])
1442 return ncache[fn].get(repo.manifest.find(man, fn)[0])
1443 if not dcache or dcache[0] != man:
1443 if not dcache or dcache[0] != man:
1444 dcache[:] = [man, repo.manifest.readdelta(man)]
1444 dcache[:] = [man, repo.manifest.readdelta(man)]
1445 if fn in dcache[1]:
1445 if fn in dcache[1]:
1446 return ncache[fn].get(dcache[1][fn])
1446 return ncache[fn].get(dcache[1][fn])
1447 return None
1447 return None
1448
1448
1449 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
1449 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
1450 for st, rev, fns in changeiter:
1450 for st, rev, fns in changeiter:
1451 if st == 'add':
1451 if st == 'add':
1452 changenode = repo.changelog.node(rev)
1452 changenode = repo.changelog.node(rev)
1453 parents = [p for p in repo.changelog.parentrevs(rev)
1453 parents = [p for p in repo.changelog.parentrevs(rev)
1454 if p != nullrev]
1454 if p != nullrev]
1455 if opts['no_merges'] and len(parents) == 2:
1455 if opts['no_merges'] and len(parents) == 2:
1456 continue
1456 continue
1457 if opts['only_merges'] and len(parents) != 2:
1457 if opts['only_merges'] and len(parents) != 2:
1458 continue
1458 continue
1459
1459
1460 if opts['keyword']:
1460 if opts['keyword']:
1461 changes = get(rev)
1461 changes = get(rev)
1462 miss = 0
1462 miss = 0
1463 for k in [kw.lower() for kw in opts['keyword']]:
1463 for k in [kw.lower() for kw in opts['keyword']]:
1464 if not (k in changes[1].lower() or
1464 if not (k in changes[1].lower() or
1465 k in changes[4].lower() or
1465 k in changes[4].lower() or
1466 k in " ".join(changes[3][:20]).lower()):
1466 k in " ".join(changes[3][:20]).lower()):
1467 miss = 1
1467 miss = 1
1468 break
1468 break
1469 if miss:
1469 if miss:
1470 continue
1470 continue
1471
1471
1472 copies = []
1472 copies = []
1473 if opts.get('copies') and rev:
1473 if opts.get('copies') and rev:
1474 mf = get(rev)[0]
1474 mf = get(rev)[0]
1475 for fn in get(rev)[3]:
1475 for fn in get(rev)[3]:
1476 rename = getrenamed(fn, rev, mf)
1476 rename = getrenamed(fn, rev, mf)
1477 if rename:
1477 if rename:
1478 copies.append((fn, rename[0]))
1478 copies.append((fn, rename[0]))
1479 displayer.show(rev, changenode, copies=copies)
1479 displayer.show(rev, changenode, copies=copies)
1480 elif st == 'iter':
1480 elif st == 'iter':
1481 if count == limit: break
1481 if count == limit: break
1482 if displayer.flush(rev):
1482 if displayer.flush(rev):
1483 count += 1
1483 count += 1
1484
1484
1485 def manifest(ui, repo, rev=None):
1485 def manifest(ui, repo, rev=None):
1486 """output the latest or given revision of the project manifest
1486 """output the latest or given revision of the project manifest
1487
1487
1488 Print a list of version controlled files for the given revision.
1488 Print a list of version controlled files for the given revision.
1489
1489
1490 The manifest is the list of files being version controlled. If no revision
1490 The manifest is the list of files being version controlled. If no revision
1491 is given then the tip is used.
1491 is given then the tip is used.
1492 """
1492 """
1493 if rev:
1493 if rev:
1494 try:
1494 try:
1495 # assume all revision numbers are for changesets
1495 # assume all revision numbers are for changesets
1496 n = repo.lookup(rev)
1496 n = repo.lookup(rev)
1497 change = repo.changelog.read(n)
1497 change = repo.changelog.read(n)
1498 n = change[0]
1498 n = change[0]
1499 except hg.RepoError:
1499 except hg.RepoError:
1500 n = repo.manifest.lookup(rev)
1500 n = repo.manifest.lookup(rev)
1501 else:
1501 else:
1502 n = repo.manifest.tip()
1502 n = repo.manifest.tip()
1503 m = repo.manifest.read(n)
1503 m = repo.manifest.read(n)
1504 files = m.keys()
1504 files = m.keys()
1505 files.sort()
1505 files.sort()
1506
1506
1507 for f in files:
1507 for f in files:
1508 ui.write("%40s %3s %s\n" % (hex(m[f]),
1508 ui.write("%40s %3s %s\n" % (hex(m[f]),
1509 m.execf(f) and "755" or "644", f))
1509 m.execf(f) and "755" or "644", f))
1510
1510
1511 def merge(ui, repo, node=None, force=None, branch=None):
1511 def merge(ui, repo, node=None, force=None, branch=None):
1512 """Merge working directory with another revision
1512 """Merge working directory with another revision
1513
1513
1514 Merge the contents of the current working directory and the
1514 Merge the contents of the current working directory and the
1515 requested revision. Files that changed between either parent are
1515 requested revision. Files that changed between either parent are
1516 marked as changed for the next commit and a commit must be
1516 marked as changed for the next commit and a commit must be
1517 performed before any further updates are allowed.
1517 performed before any further updates are allowed.
1518
1518
1519 If no revision is specified, the working directory's parent is a
1519 If no revision is specified, the working directory's parent is a
1520 head revision, and the repository contains exactly one other head,
1520 head revision, and the repository contains exactly one other head,
1521 the other head is merged with by default. Otherwise, an explicit
1521 the other head is merged with by default. Otherwise, an explicit
1522 revision to merge with must be provided.
1522 revision to merge with must be provided.
1523 """
1523 """
1524
1524
1525 if node or branch:
1525 if node or branch:
1526 node = _lookup(repo, node, branch)
1526 node = _lookup(repo, node, branch)
1527 else:
1527 else:
1528 heads = repo.heads()
1528 heads = repo.heads()
1529 if len(heads) > 2:
1529 if len(heads) > 2:
1530 raise util.Abort(_('repo has %d heads - '
1530 raise util.Abort(_('repo has %d heads - '
1531 'please merge with an explicit rev') %
1531 'please merge with an explicit rev') %
1532 len(heads))
1532 len(heads))
1533 if len(heads) == 1:
1533 if len(heads) == 1:
1534 raise util.Abort(_('there is nothing to merge - '
1534 raise util.Abort(_('there is nothing to merge - '
1535 'use "hg update" instead'))
1535 'use "hg update" instead'))
1536 parent = repo.dirstate.parents()[0]
1536 parent = repo.dirstate.parents()[0]
1537 if parent not in heads:
1537 if parent not in heads:
1538 raise util.Abort(_('working dir not at a head rev - '
1538 raise util.Abort(_('working dir not at a head rev - '
1539 'use "hg update" or merge with an explicit rev'))
1539 'use "hg update" or merge with an explicit rev'))
1540 node = parent == heads[0] and heads[-1] or heads[0]
1540 node = parent == heads[0] and heads[-1] or heads[0]
1541 return hg.merge(repo, node, force=force)
1541 return hg.merge(repo, node, force=force)
1542
1542
1543 def outgoing(ui, repo, dest=None, **opts):
1543 def outgoing(ui, repo, dest=None, **opts):
1544 """show changesets not found in destination
1544 """show changesets not found in destination
1545
1545
1546 Show changesets not found in the specified destination repository or
1546 Show changesets not found in the specified destination repository or
1547 the default push location. These are the changesets that would be pushed
1547 the default push location. These are the changesets that would be pushed
1548 if a push was requested.
1548 if a push was requested.
1549
1549
1550 See pull for valid destination format details.
1550 See pull for valid destination format details.
1551 """
1551 """
1552 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1552 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1553 setremoteconfig(ui, opts)
1553 setremoteconfig(ui, opts)
1554 revs = None
1554 revs = None
1555 if opts['rev']:
1555 if opts['rev']:
1556 revs = [repo.lookup(rev) for rev in opts['rev']]
1556 revs = [repo.lookup(rev) for rev in opts['rev']]
1557
1557
1558 other = hg.repository(ui, dest)
1558 other = hg.repository(ui, dest)
1559 o = repo.findoutgoing(other, force=opts['force'])
1559 o = repo.findoutgoing(other, force=opts['force'])
1560 if not o:
1560 if not o:
1561 ui.status(_("no changes found\n"))
1561 ui.status(_("no changes found\n"))
1562 return
1562 return
1563 o = repo.changelog.nodesbetween(o, revs)[0]
1563 o = repo.changelog.nodesbetween(o, revs)[0]
1564 if opts['newest_first']:
1564 if opts['newest_first']:
1565 o.reverse()
1565 o.reverse()
1566 displayer = cmdutil.show_changeset(ui, repo, opts)
1566 displayer = cmdutil.show_changeset(ui, repo, opts)
1567 for n in o:
1567 for n in o:
1568 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1568 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1569 if opts['no_merges'] and len(parents) == 2:
1569 if opts['no_merges'] and len(parents) == 2:
1570 continue
1570 continue
1571 displayer.show(changenode=n)
1571 displayer.show(changenode=n)
1572
1572
1573 def parents(ui, repo, file_=None, **opts):
1573 def parents(ui, repo, file_=None, **opts):
1574 """show the parents of the working dir or revision
1574 """show the parents of the working dir or revision
1575
1575
1576 Print the working directory's parent revisions.
1576 Print the working directory's parent revisions.
1577 """
1577 """
1578 rev = opts.get('rev')
1578 rev = opts.get('rev')
1579 if rev:
1579 if rev:
1580 if file_:
1580 if file_:
1581 ctx = repo.filectx(file_, changeid=rev)
1581 ctx = repo.filectx(file_, changeid=rev)
1582 else:
1582 else:
1583 ctx = repo.changectx(rev)
1583 ctx = repo.changectx(rev)
1584 p = [cp.node() for cp in ctx.parents()]
1584 p = [cp.node() for cp in ctx.parents()]
1585 else:
1585 else:
1586 p = repo.dirstate.parents()
1586 p = repo.dirstate.parents()
1587
1587
1588 displayer = cmdutil.show_changeset(ui, repo, opts)
1588 displayer = cmdutil.show_changeset(ui, repo, opts)
1589 for n in p:
1589 for n in p:
1590 if n != nullid:
1590 if n != nullid:
1591 displayer.show(changenode=n)
1591 displayer.show(changenode=n)
1592
1592
1593 def paths(ui, repo, search=None):
1593 def paths(ui, repo, search=None):
1594 """show definition of symbolic path names
1594 """show definition of symbolic path names
1595
1595
1596 Show definition of symbolic path name NAME. If no name is given, show
1596 Show definition of symbolic path name NAME. If no name is given, show
1597 definition of available names.
1597 definition of available names.
1598
1598
1599 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1599 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1600 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1600 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1601 """
1601 """
1602 if search:
1602 if search:
1603 for name, path in ui.configitems("paths"):
1603 for name, path in ui.configitems("paths"):
1604 if name == search:
1604 if name == search:
1605 ui.write("%s\n" % path)
1605 ui.write("%s\n" % path)
1606 return
1606 return
1607 ui.warn(_("not found!\n"))
1607 ui.warn(_("not found!\n"))
1608 return 1
1608 return 1
1609 else:
1609 else:
1610 for name, path in ui.configitems("paths"):
1610 for name, path in ui.configitems("paths"):
1611 ui.write("%s = %s\n" % (name, path))
1611 ui.write("%s = %s\n" % (name, path))
1612
1612
1613 def postincoming(ui, repo, modheads, optupdate):
1613 def postincoming(ui, repo, modheads, optupdate):
1614 if modheads == 0:
1614 if modheads == 0:
1615 return
1615 return
1616 if optupdate:
1616 if optupdate:
1617 if modheads == 1:
1617 if modheads == 1:
1618 return hg.update(repo, repo.changelog.tip()) # update
1618 return hg.update(repo, repo.changelog.tip()) # update
1619 else:
1619 else:
1620 ui.status(_("not updating, since new heads added\n"))
1620 ui.status(_("not updating, since new heads added\n"))
1621 if modheads > 1:
1621 if modheads > 1:
1622 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
1622 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
1623 else:
1623 else:
1624 ui.status(_("(run 'hg update' to get a working copy)\n"))
1624 ui.status(_("(run 'hg update' to get a working copy)\n"))
1625
1625
1626 def pull(ui, repo, source="default", **opts):
1626 def pull(ui, repo, source="default", **opts):
1627 """pull changes from the specified source
1627 """pull changes from the specified source
1628
1628
1629 Pull changes from a remote repository to a local one.
1629 Pull changes from a remote repository to a local one.
1630
1630
1631 This finds all changes from the repository at the specified path
1631 This finds all changes from the repository at the specified path
1632 or URL and adds them to the local repository. By default, this
1632 or URL and adds them to the local repository. By default, this
1633 does not update the copy of the project in the working directory.
1633 does not update the copy of the project in the working directory.
1634
1634
1635 Valid URLs are of the form:
1635 Valid URLs are of the form:
1636
1636
1637 local/filesystem/path (or file://local/filesystem/path)
1637 local/filesystem/path (or file://local/filesystem/path)
1638 http://[user@]host[:port]/[path]
1638 http://[user@]host[:port]/[path]
1639 https://[user@]host[:port]/[path]
1639 https://[user@]host[:port]/[path]
1640 ssh://[user@]host[:port]/[path]
1640 ssh://[user@]host[:port]/[path]
1641 static-http://host[:port]/[path]
1641 static-http://host[:port]/[path]
1642
1642
1643 Paths in the local filesystem can either point to Mercurial
1643 Paths in the local filesystem can either point to Mercurial
1644 repositories or to bundle files (as created by 'hg bundle' or
1644 repositories or to bundle files (as created by 'hg bundle' or
1645 'hg incoming --bundle'). The static-http:// protocol, albeit slow,
1645 'hg incoming --bundle'). The static-http:// protocol, albeit slow,
1646 allows access to a Mercurial repository where you simply use a web
1646 allows access to a Mercurial repository where you simply use a web
1647 server to publish the .hg directory as static content.
1647 server to publish the .hg directory as static content.
1648
1648
1649 Some notes about using SSH with Mercurial:
1649 Some notes about using SSH with Mercurial:
1650 - SSH requires an accessible shell account on the destination machine
1650 - SSH requires an accessible shell account on the destination machine
1651 and a copy of hg in the remote path or specified with as remotecmd.
1651 and a copy of hg in the remote path or specified with as remotecmd.
1652 - path is relative to the remote user's home directory by default.
1652 - path is relative to the remote user's home directory by default.
1653 Use an extra slash at the start of a path to specify an absolute path:
1653 Use an extra slash at the start of a path to specify an absolute path:
1654 ssh://example.com//tmp/repository
1654 ssh://example.com//tmp/repository
1655 - Mercurial doesn't use its own compression via SSH; the right thing
1655 - Mercurial doesn't use its own compression via SSH; the right thing
1656 to do is to configure it in your ~/.ssh/config, e.g.:
1656 to do is to configure it in your ~/.ssh/config, e.g.:
1657 Host *.mylocalnetwork.example.com
1657 Host *.mylocalnetwork.example.com
1658 Compression no
1658 Compression no
1659 Host *
1659 Host *
1660 Compression yes
1660 Compression yes
1661 Alternatively specify "ssh -C" as your ssh command in your hgrc or
1661 Alternatively specify "ssh -C" as your ssh command in your hgrc or
1662 with the --ssh command line option.
1662 with the --ssh command line option.
1663 """
1663 """
1664 source = ui.expandpath(source)
1664 source = ui.expandpath(source)
1665 setremoteconfig(ui, opts)
1665 setremoteconfig(ui, opts)
1666
1666
1667 other = hg.repository(ui, source)
1667 other = hg.repository(ui, source)
1668 ui.status(_('pulling from %s\n') % (source))
1668 ui.status(_('pulling from %s\n') % (source))
1669 revs = None
1669 revs = None
1670 if opts['rev']:
1670 if opts['rev']:
1671 if 'lookup' in other.capabilities:
1671 if 'lookup' in other.capabilities:
1672 revs = [other.lookup(rev) for rev in opts['rev']]
1672 revs = [other.lookup(rev) for rev in opts['rev']]
1673 else:
1673 else:
1674 error = _("Other repository doesn't support revision lookup, so a rev cannot be specified.")
1674 error = _("Other repository doesn't support revision lookup, so a rev cannot be specified.")
1675 raise util.Abort(error)
1675 raise util.Abort(error)
1676 modheads = repo.pull(other, heads=revs, force=opts['force'])
1676 modheads = repo.pull(other, heads=revs, force=opts['force'])
1677 return postincoming(ui, repo, modheads, opts['update'])
1677 return postincoming(ui, repo, modheads, opts['update'])
1678
1678
1679 def push(ui, repo, dest=None, **opts):
1679 def push(ui, repo, dest=None, **opts):
1680 """push changes to the specified destination
1680 """push changes to the specified destination
1681
1681
1682 Push changes from the local repository to the given destination.
1682 Push changes from the local repository to the given destination.
1683
1683
1684 This is the symmetrical operation for pull. It helps to move
1684 This is the symmetrical operation for pull. It helps to move
1685 changes from the current repository to a different one. If the
1685 changes from the current repository to a different one. If the
1686 destination is local this is identical to a pull in that directory
1686 destination is local this is identical to a pull in that directory
1687 from the current one.
1687 from the current one.
1688
1688
1689 By default, push will refuse to run if it detects the result would
1689 By default, push will refuse to run if it detects the result would
1690 increase the number of remote heads. This generally indicates the
1690 increase the number of remote heads. This generally indicates the
1691 the client has forgotten to sync and merge before pushing.
1691 the client has forgotten to sync and merge before pushing.
1692
1692
1693 Valid URLs are of the form:
1693 Valid URLs are of the form:
1694
1694
1695 local/filesystem/path (or file://local/filesystem/path)
1695 local/filesystem/path (or file://local/filesystem/path)
1696 ssh://[user@]host[:port]/[path]
1696 ssh://[user@]host[:port]/[path]
1697 http://[user@]host[:port]/[path]
1697 http://[user@]host[:port]/[path]
1698 https://[user@]host[:port]/[path]
1698 https://[user@]host[:port]/[path]
1699
1699
1700 Look at the help text for the pull command for important details
1700 Look at the help text for the pull command for important details
1701 about ssh:// URLs.
1701 about ssh:// URLs.
1702
1702
1703 Pushing to http:// and https:// URLs is only possible, if this
1703 Pushing to http:// and https:// URLs is only possible, if this
1704 feature is explicitly enabled on the remote Mercurial server.
1704 feature is explicitly enabled on the remote Mercurial server.
1705 """
1705 """
1706 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1706 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1707 setremoteconfig(ui, opts)
1707 setremoteconfig(ui, opts)
1708
1708
1709 other = hg.repository(ui, dest)
1709 other = hg.repository(ui, dest)
1710 ui.status('pushing to %s\n' % (dest))
1710 ui.status('pushing to %s\n' % (dest))
1711 revs = None
1711 revs = None
1712 if opts['rev']:
1712 if opts['rev']:
1713 revs = [repo.lookup(rev) for rev in opts['rev']]
1713 revs = [repo.lookup(rev) for rev in opts['rev']]
1714 r = repo.push(other, opts['force'], revs=revs)
1714 r = repo.push(other, opts['force'], revs=revs)
1715 return r == 0
1715 return r == 0
1716
1716
1717 def rawcommit(ui, repo, *pats, **opts):
1717 def rawcommit(ui, repo, *pats, **opts):
1718 """raw commit interface (DEPRECATED)
1718 """raw commit interface (DEPRECATED)
1719
1719
1720 (DEPRECATED)
1720 (DEPRECATED)
1721 Lowlevel commit, for use in helper scripts.
1721 Lowlevel commit, for use in helper scripts.
1722
1722
1723 This command is not intended to be used by normal users, as it is
1723 This command is not intended to be used by normal users, as it is
1724 primarily useful for importing from other SCMs.
1724 primarily useful for importing from other SCMs.
1725
1725
1726 This command is now deprecated and will be removed in a future
1726 This command is now deprecated and will be removed in a future
1727 release, please use debugsetparents and commit instead.
1727 release, please use debugsetparents and commit instead.
1728 """
1728 """
1729
1729
1730 ui.warn(_("(the rawcommit command is deprecated)\n"))
1730 ui.warn(_("(the rawcommit command is deprecated)\n"))
1731
1731
1732 message = logmessage(opts)
1732 message = logmessage(opts)
1733
1733
1734 files, match, anypats = cmdutil.matchpats(repo, pats, opts)
1734 files, match, anypats = cmdutil.matchpats(repo, pats, opts)
1735 if opts['files']:
1735 if opts['files']:
1736 files += open(opts['files']).read().splitlines()
1736 files += open(opts['files']).read().splitlines()
1737
1737
1738 parents = [repo.lookup(p) for p in opts['parent']]
1738 parents = [repo.lookup(p) for p in opts['parent']]
1739
1739
1740 try:
1740 try:
1741 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
1741 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
1742 except ValueError, inst:
1742 except ValueError, inst:
1743 raise util.Abort(str(inst))
1743 raise util.Abort(str(inst))
1744
1744
1745 def recover(ui, repo):
1745 def recover(ui, repo):
1746 """roll back an interrupted transaction
1746 """roll back an interrupted transaction
1747
1747
1748 Recover from an interrupted commit or pull.
1748 Recover from an interrupted commit or pull.
1749
1749
1750 This command tries to fix the repository status after an interrupted
1750 This command tries to fix the repository status after an interrupted
1751 operation. It should only be necessary when Mercurial suggests it.
1751 operation. It should only be necessary when Mercurial suggests it.
1752 """
1752 """
1753 if repo.recover():
1753 if repo.recover():
1754 return hg.verify(repo)
1754 return hg.verify(repo)
1755 return 1
1755 return 1
1756
1756
1757 def remove(ui, repo, *pats, **opts):
1757 def remove(ui, repo, *pats, **opts):
1758 """remove the specified files on the next commit
1758 """remove the specified files on the next commit
1759
1759
1760 Schedule the indicated files for removal from the repository.
1760 Schedule the indicated files for removal from the repository.
1761
1761
1762 This command schedules the files to be removed at the next commit.
1762 This command schedules the files to be removed at the next commit.
1763 This only removes files from the current branch, not from the
1763 This only removes files from the current branch, not from the
1764 entire project history. If the files still exist in the working
1764 entire project history. If the files still exist in the working
1765 directory, they will be deleted from it. If invoked with --after,
1765 directory, they will be deleted from it. If invoked with --after,
1766 files that have been manually deleted are marked as removed.
1766 files that have been manually deleted are marked as removed.
1767
1767
1768 Modified files and added files are not removed by default. To
1768 Modified files and added files are not removed by default. To
1769 remove them, use the -f/--force option.
1769 remove them, use the -f/--force option.
1770 """
1770 """
1771 names = []
1771 names = []
1772 if not opts['after'] and not pats:
1772 if not opts['after'] and not pats:
1773 raise util.Abort(_('no files specified'))
1773 raise util.Abort(_('no files specified'))
1774 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
1774 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
1775 exact = dict.fromkeys(files)
1775 exact = dict.fromkeys(files)
1776 mardu = map(dict.fromkeys, repo.status(files=files, match=matchfn))[:5]
1776 mardu = map(dict.fromkeys, repo.status(files=files, match=matchfn))[:5]
1777 modified, added, removed, deleted, unknown = mardu
1777 modified, added, removed, deleted, unknown = mardu
1778 remove, forget = [], []
1778 remove, forget = [], []
1779 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
1779 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
1780 reason = None
1780 reason = None
1781 if abs not in deleted and opts['after']:
1781 if abs not in deleted and opts['after']:
1782 reason = _('is still present')
1782 reason = _('is still present')
1783 elif abs in modified and not opts['force']:
1783 elif abs in modified and not opts['force']:
1784 reason = _('is modified (use -f to force removal)')
1784 reason = _('is modified (use -f to force removal)')
1785 elif abs in added:
1785 elif abs in added:
1786 if opts['force']:
1786 if opts['force']:
1787 forget.append(abs)
1787 forget.append(abs)
1788 continue
1788 continue
1789 reason = _('has been marked for add (use -f to force removal)')
1789 reason = _('has been marked for add (use -f to force removal)')
1790 elif abs in unknown:
1790 elif abs in unknown:
1791 reason = _('is not managed')
1791 reason = _('is not managed')
1792 elif abs in removed:
1792 elif abs in removed:
1793 continue
1793 continue
1794 if reason:
1794 if reason:
1795 if exact:
1795 if exact:
1796 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1796 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1797 else:
1797 else:
1798 if ui.verbose or not exact:
1798 if ui.verbose or not exact:
1799 ui.status(_('removing %s\n') % rel)
1799 ui.status(_('removing %s\n') % rel)
1800 remove.append(abs)
1800 remove.append(abs)
1801 repo.forget(forget)
1801 repo.forget(forget)
1802 repo.remove(remove, unlink=not opts['after'])
1802 repo.remove(remove, unlink=not opts['after'])
1803
1803
1804 def rename(ui, repo, *pats, **opts):
1804 def rename(ui, repo, *pats, **opts):
1805 """rename files; equivalent of copy + remove
1805 """rename files; equivalent of copy + remove
1806
1806
1807 Mark dest as copies of sources; mark sources for deletion. If
1807 Mark dest as copies of sources; mark sources for deletion. If
1808 dest is a directory, copies are put in that directory. If dest is
1808 dest is a directory, copies are put in that directory. If dest is
1809 a file, there can only be one source.
1809 a file, there can only be one source.
1810
1810
1811 By default, this command copies the contents of files as they
1811 By default, this command copies the contents of files as they
1812 stand in the working directory. If invoked with --after, the
1812 stand in the working directory. If invoked with --after, the
1813 operation is recorded, but no copying is performed.
1813 operation is recorded, but no copying is performed.
1814
1814
1815 This command takes effect in the next commit.
1815 This command takes effect in the next commit.
1816 """
1816 """
1817 wlock = repo.wlock(0)
1817 wlock = repo.wlock(0)
1818 errs, copied = docopy(ui, repo, pats, opts, wlock)
1818 errs, copied = docopy(ui, repo, pats, opts, wlock)
1819 names = []
1819 names = []
1820 for abs, rel, exact in copied:
1820 for abs, rel, exact in copied:
1821 if ui.verbose or not exact:
1821 if ui.verbose or not exact:
1822 ui.status(_('removing %s\n') % rel)
1822 ui.status(_('removing %s\n') % rel)
1823 names.append(abs)
1823 names.append(abs)
1824 if not opts.get('dry_run'):
1824 if not opts.get('dry_run'):
1825 repo.remove(names, True, wlock)
1825 repo.remove(names, True, wlock)
1826 return errs
1826 return errs
1827
1827
1828 def revert(ui, repo, *pats, **opts):
1828 def revert(ui, repo, *pats, **opts):
1829 """revert files or dirs to their states as of some revision
1829 """revert files or dirs to their states as of some revision
1830
1830
1831 With no revision specified, revert the named files or directories
1831 With no revision specified, revert the named files or directories
1832 to the contents they had in the parent of the working directory.
1832 to the contents they had in the parent of the working directory.
1833 This restores the contents of the affected files to an unmodified
1833 This restores the contents of the affected files to an unmodified
1834 state. If the working directory has two parents, you must
1834 state. If the working directory has two parents, you must
1835 explicitly specify the revision to revert to.
1835 explicitly specify the revision to revert to.
1836
1836
1837 Modified files are saved with a .orig suffix before reverting.
1837 Modified files are saved with a .orig suffix before reverting.
1838 To disable these backups, use --no-backup.
1838 To disable these backups, use --no-backup.
1839
1839
1840 Using the -r option, revert the given files or directories to their
1840 Using the -r option, revert the given files or directories to their
1841 contents as of a specific revision. This can be helpful to "roll
1841 contents as of a specific revision. This can be helpful to "roll
1842 back" some or all of a change that should not have been committed.
1842 back" some or all of a change that should not have been committed.
1843
1843
1844 Revert modifies the working directory. It does not commit any
1844 Revert modifies the working directory. It does not commit any
1845 changes, or change the parent of the working directory. If you
1845 changes, or change the parent of the working directory. If you
1846 revert to a revision other than the parent of the working
1846 revert to a revision other than the parent of the working
1847 directory, the reverted files will thus appear modified
1847 directory, the reverted files will thus appear modified
1848 afterwards.
1848 afterwards.
1849
1849
1850 If a file has been deleted, it is recreated. If the executable
1850 If a file has been deleted, it is recreated. If the executable
1851 mode of a file was changed, it is reset.
1851 mode of a file was changed, it is reset.
1852
1852
1853 If names are given, all files matching the names are reverted.
1853 If names are given, all files matching the names are reverted.
1854
1854
1855 If no arguments are given, no files are reverted.
1855 If no arguments are given, no files are reverted.
1856 """
1856 """
1857
1857
1858 if not pats and not opts['all']:
1858 if not pats and not opts['all']:
1859 raise util.Abort(_('no files or directories specified; '
1859 raise util.Abort(_('no files or directories specified; '
1860 'use --all to revert the whole repo'))
1860 'use --all to revert the whole repo'))
1861
1861
1862 parent, p2 = repo.dirstate.parents()
1862 parent, p2 = repo.dirstate.parents()
1863 if not opts['rev'] and p2 != nullid:
1863 if not opts['rev'] and p2 != nullid:
1864 raise util.Abort(_('uncommitted merge - please provide a '
1864 raise util.Abort(_('uncommitted merge - please provide a '
1865 'specific revision'))
1865 'specific revision'))
1866 node = repo.changectx(opts['rev']).node()
1866 node = repo.changectx(opts['rev']).node()
1867 mf = repo.manifest.read(repo.changelog.read(node)[0])
1867 mf = repo.manifest.read(repo.changelog.read(node)[0])
1868 if node == parent:
1868 if node == parent:
1869 pmf = mf
1869 pmf = mf
1870 else:
1870 else:
1871 pmf = None
1871 pmf = None
1872
1872
1873 wlock = repo.wlock()
1873 wlock = repo.wlock()
1874
1874
1875 # need all matching names in dirstate and manifest of target rev,
1875 # need all matching names in dirstate and manifest of target rev,
1876 # so have to walk both. do not print errors if files exist in one
1876 # so have to walk both. do not print errors if files exist in one
1877 # but not other.
1877 # but not other.
1878
1878
1879 names = {}
1879 names = {}
1880 target_only = {}
1880 target_only = {}
1881
1881
1882 # walk dirstate.
1882 # walk dirstate.
1883
1883
1884 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
1884 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
1885 badmatch=mf.has_key):
1885 badmatch=mf.has_key):
1886 names[abs] = (rel, exact)
1886 names[abs] = (rel, exact)
1887 if src == 'b':
1887 if src == 'b':
1888 target_only[abs] = True
1888 target_only[abs] = True
1889
1889
1890 # walk target manifest.
1890 # walk target manifest.
1891
1891
1892 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
1892 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
1893 badmatch=names.has_key):
1893 badmatch=names.has_key):
1894 if abs in names: continue
1894 if abs in names: continue
1895 names[abs] = (rel, exact)
1895 names[abs] = (rel, exact)
1896 target_only[abs] = True
1896 target_only[abs] = True
1897
1897
1898 changes = repo.status(match=names.has_key, wlock=wlock)[:5]
1898 changes = repo.status(match=names.has_key, wlock=wlock)[:5]
1899 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
1899 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
1900
1900
1901 revert = ([], _('reverting %s\n'))
1901 revert = ([], _('reverting %s\n'))
1902 add = ([], _('adding %s\n'))
1902 add = ([], _('adding %s\n'))
1903 remove = ([], _('removing %s\n'))
1903 remove = ([], _('removing %s\n'))
1904 forget = ([], _('forgetting %s\n'))
1904 forget = ([], _('forgetting %s\n'))
1905 undelete = ([], _('undeleting %s\n'))
1905 undelete = ([], _('undeleting %s\n'))
1906 update = {}
1906 update = {}
1907
1907
1908 disptable = (
1908 disptable = (
1909 # dispatch table:
1909 # dispatch table:
1910 # file state
1910 # file state
1911 # action if in target manifest
1911 # action if in target manifest
1912 # action if not in target manifest
1912 # action if not in target manifest
1913 # make backup if in target manifest
1913 # make backup if in target manifest
1914 # make backup if not in target manifest
1914 # make backup if not in target manifest
1915 (modified, revert, remove, True, True),
1915 (modified, revert, remove, True, True),
1916 (added, revert, forget, True, False),
1916 (added, revert, forget, True, False),
1917 (removed, undelete, None, False, False),
1917 (removed, undelete, None, False, False),
1918 (deleted, revert, remove, False, False),
1918 (deleted, revert, remove, False, False),
1919 (unknown, add, None, True, False),
1919 (unknown, add, None, True, False),
1920 (target_only, add, None, False, False),
1920 (target_only, add, None, False, False),
1921 )
1921 )
1922
1922
1923 entries = names.items()
1923 entries = names.items()
1924 entries.sort()
1924 entries.sort()
1925
1925
1926 for abs, (rel, exact) in entries:
1926 for abs, (rel, exact) in entries:
1927 mfentry = mf.get(abs)
1927 mfentry = mf.get(abs)
1928 def handle(xlist, dobackup):
1928 def handle(xlist, dobackup):
1929 xlist[0].append(abs)
1929 xlist[0].append(abs)
1930 update[abs] = 1
1930 update[abs] = 1
1931 if dobackup and not opts['no_backup'] and os.path.exists(rel):
1931 if dobackup and not opts['no_backup'] and os.path.exists(rel):
1932 bakname = "%s.orig" % rel
1932 bakname = "%s.orig" % rel
1933 ui.note(_('saving current version of %s as %s\n') %
1933 ui.note(_('saving current version of %s as %s\n') %
1934 (rel, bakname))
1934 (rel, bakname))
1935 if not opts.get('dry_run'):
1935 if not opts.get('dry_run'):
1936 util.copyfile(rel, bakname)
1936 util.copyfile(rel, bakname)
1937 if ui.verbose or not exact:
1937 if ui.verbose or not exact:
1938 ui.status(xlist[1] % rel)
1938 ui.status(xlist[1] % rel)
1939 for table, hitlist, misslist, backuphit, backupmiss in disptable:
1939 for table, hitlist, misslist, backuphit, backupmiss in disptable:
1940 if abs not in table: continue
1940 if abs not in table: continue
1941 # file has changed in dirstate
1941 # file has changed in dirstate
1942 if mfentry:
1942 if mfentry:
1943 handle(hitlist, backuphit)
1943 handle(hitlist, backuphit)
1944 elif misslist is not None:
1944 elif misslist is not None:
1945 handle(misslist, backupmiss)
1945 handle(misslist, backupmiss)
1946 else:
1946 else:
1947 if exact: ui.warn(_('file not managed: %s\n' % rel))
1947 if exact: ui.warn(_('file not managed: %s\n' % rel))
1948 break
1948 break
1949 else:
1949 else:
1950 # file has not changed in dirstate
1950 # file has not changed in dirstate
1951 if node == parent:
1951 if node == parent:
1952 if exact: ui.warn(_('no changes needed to %s\n' % rel))
1952 if exact: ui.warn(_('no changes needed to %s\n' % rel))
1953 continue
1953 continue
1954 if pmf is None:
1954 if pmf is None:
1955 # only need parent manifest in this unlikely case,
1955 # only need parent manifest in this unlikely case,
1956 # so do not read by default
1956 # so do not read by default
1957 pmf = repo.manifest.read(repo.changelog.read(parent)[0])
1957 pmf = repo.manifest.read(repo.changelog.read(parent)[0])
1958 if abs in pmf:
1958 if abs in pmf:
1959 if mfentry:
1959 if mfentry:
1960 # if version of file is same in parent and target
1960 # if version of file is same in parent and target
1961 # manifests, do nothing
1961 # manifests, do nothing
1962 if pmf[abs] != mfentry:
1962 if pmf[abs] != mfentry:
1963 handle(revert, False)
1963 handle(revert, False)
1964 else:
1964 else:
1965 handle(remove, False)
1965 handle(remove, False)
1966
1966
1967 if not opts.get('dry_run'):
1967 if not opts.get('dry_run'):
1968 repo.dirstate.forget(forget[0])
1968 repo.dirstate.forget(forget[0])
1969 r = hg.revert(repo, node, update.has_key, wlock)
1969 r = hg.revert(repo, node, update.has_key, wlock)
1970 repo.dirstate.update(add[0], 'a')
1970 repo.dirstate.update(add[0], 'a')
1971 repo.dirstate.update(undelete[0], 'n')
1971 repo.dirstate.update(undelete[0], 'n')
1972 repo.dirstate.update(remove[0], 'r')
1972 repo.dirstate.update(remove[0], 'r')
1973 return r
1973 return r
1974
1974
1975 def rollback(ui, repo):
1975 def rollback(ui, repo):
1976 """roll back the last transaction in this repository
1976 """roll back the last transaction in this repository
1977
1977
1978 Roll back the last transaction in this repository, restoring the
1978 Roll back the last transaction in this repository, restoring the
1979 project to its state prior to the transaction.
1979 project to its state prior to the transaction.
1980
1980
1981 Transactions are used to encapsulate the effects of all commands
1981 Transactions are used to encapsulate the effects of all commands
1982 that create new changesets or propagate existing changesets into a
1982 that create new changesets or propagate existing changesets into a
1983 repository. For example, the following commands are transactional,
1983 repository. For example, the following commands are transactional,
1984 and their effects can be rolled back:
1984 and their effects can be rolled back:
1985
1985
1986 commit
1986 commit
1987 import
1987 import
1988 pull
1988 pull
1989 push (with this repository as destination)
1989 push (with this repository as destination)
1990 unbundle
1990 unbundle
1991
1991
1992 This command should be used with care. There is only one level of
1992 This command should be used with care. There is only one level of
1993 rollback, and there is no way to undo a rollback.
1993 rollback, and there is no way to undo a rollback.
1994
1994
1995 This command is not intended for use on public repositories. Once
1995 This command is not intended for use on public repositories. Once
1996 changes are visible for pull by other users, rolling a transaction
1996 changes are visible for pull by other users, rolling a transaction
1997 back locally is ineffective (someone else may already have pulled
1997 back locally is ineffective (someone else may already have pulled
1998 the changes). Furthermore, a race is possible with readers of the
1998 the changes). Furthermore, a race is possible with readers of the
1999 repository; for example an in-progress pull from the repository
1999 repository; for example an in-progress pull from the repository
2000 may fail if a rollback is performed.
2000 may fail if a rollback is performed.
2001 """
2001 """
2002 repo.rollback()
2002 repo.rollback()
2003
2003
2004 def root(ui, repo):
2004 def root(ui, repo):
2005 """print the root (top) of the current working dir
2005 """print the root (top) of the current working dir
2006
2006
2007 Print the root directory of the current repository.
2007 Print the root directory of the current repository.
2008 """
2008 """
2009 ui.write(repo.root + "\n")
2009 ui.write(repo.root + "\n")
2010
2010
2011 def serve(ui, repo, **opts):
2011 def serve(ui, repo, **opts):
2012 """export the repository via HTTP
2012 """export the repository via HTTP
2013
2013
2014 Start a local HTTP repository browser and pull server.
2014 Start a local HTTP repository browser and pull server.
2015
2015
2016 By default, the server logs accesses to stdout and errors to
2016 By default, the server logs accesses to stdout and errors to
2017 stderr. Use the "-A" and "-E" options to log to files.
2017 stderr. Use the "-A" and "-E" options to log to files.
2018 """
2018 """
2019
2019
2020 if opts["stdio"]:
2020 if opts["stdio"]:
2021 if repo is None:
2021 if repo is None:
2022 raise hg.RepoError(_("There is no Mercurial repository here"
2022 raise hg.RepoError(_("There is no Mercurial repository here"
2023 " (.hg not found)"))
2023 " (.hg not found)"))
2024 s = sshserver.sshserver(ui, repo)
2024 s = sshserver.sshserver(ui, repo)
2025 s.serve_forever()
2025 s.serve_forever()
2026
2026
2027 optlist = ("name templates style address port ipv6"
2027 optlist = ("name templates style address port ipv6"
2028 " accesslog errorlog webdir_conf")
2028 " accesslog errorlog webdir_conf")
2029 for o in optlist.split():
2029 for o in optlist.split():
2030 if opts[o]:
2030 if opts[o]:
2031 ui.setconfig("web", o, str(opts[o]))
2031 ui.setconfig("web", o, str(opts[o]))
2032
2032
2033 if repo is None and not ui.config("web", "webdir_conf"):
2033 if repo is None and not ui.config("web", "webdir_conf"):
2034 raise hg.RepoError(_("There is no Mercurial repository here"
2034 raise hg.RepoError(_("There is no Mercurial repository here"
2035 " (.hg not found)"))
2035 " (.hg not found)"))
2036
2036
2037 if opts['daemon'] and not opts['daemon_pipefds']:
2037 if opts['daemon'] and not opts['daemon_pipefds']:
2038 rfd, wfd = os.pipe()
2038 rfd, wfd = os.pipe()
2039 args = sys.argv[:]
2039 args = sys.argv[:]
2040 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
2040 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
2041 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
2041 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
2042 args[0], args)
2042 args[0], args)
2043 os.close(wfd)
2043 os.close(wfd)
2044 os.read(rfd, 1)
2044 os.read(rfd, 1)
2045 os._exit(0)
2045 os._exit(0)
2046
2046
2047 httpd = hgweb.server.create_server(ui, repo)
2047 httpd = hgweb.server.create_server(ui, repo)
2048
2048
2049 if ui.verbose:
2049 if ui.verbose:
2050 if httpd.port != 80:
2050 if httpd.port != 80:
2051 ui.status(_('listening at http://%s:%d/\n') %
2051 ui.status(_('listening at http://%s:%d/\n') %
2052 (httpd.addr, httpd.port))
2052 (httpd.addr, httpd.port))
2053 else:
2053 else:
2054 ui.status(_('listening at http://%s/\n') % httpd.addr)
2054 ui.status(_('listening at http://%s/\n') % httpd.addr)
2055
2055
2056 if opts['pid_file']:
2056 if opts['pid_file']:
2057 fp = open(opts['pid_file'], 'w')
2057 fp = open(opts['pid_file'], 'w')
2058 fp.write(str(os.getpid()) + '\n')
2058 fp.write(str(os.getpid()) + '\n')
2059 fp.close()
2059 fp.close()
2060
2060
2061 if opts['daemon_pipefds']:
2061 if opts['daemon_pipefds']:
2062 rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
2062 rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
2063 os.close(rfd)
2063 os.close(rfd)
2064 os.write(wfd, 'y')
2064 os.write(wfd, 'y')
2065 os.close(wfd)
2065 os.close(wfd)
2066 sys.stdout.flush()
2066 sys.stdout.flush()
2067 sys.stderr.flush()
2067 sys.stderr.flush()
2068 fd = os.open(util.nulldev, os.O_RDWR)
2068 fd = os.open(util.nulldev, os.O_RDWR)
2069 if fd != 0: os.dup2(fd, 0)
2069 if fd != 0: os.dup2(fd, 0)
2070 if fd != 1: os.dup2(fd, 1)
2070 if fd != 1: os.dup2(fd, 1)
2071 if fd != 2: os.dup2(fd, 2)
2071 if fd != 2: os.dup2(fd, 2)
2072 if fd not in (0, 1, 2): os.close(fd)
2072 if fd not in (0, 1, 2): os.close(fd)
2073
2073
2074 httpd.serve_forever()
2074 httpd.serve_forever()
2075
2075
2076 def status(ui, repo, *pats, **opts):
2076 def status(ui, repo, *pats, **opts):
2077 """show changed files in the working directory
2077 """show changed files in the working directory
2078
2078
2079 Show status of files in the repository. If names are given, only
2079 Show status of files in the repository. If names are given, only
2080 files that match are shown. Files that are clean or ignored, are
2080 files that match are shown. Files that are clean or ignored, are
2081 not listed unless -c (clean), -i (ignored) or -A is given.
2081 not listed unless -c (clean), -i (ignored) or -A is given.
2082
2082
2083 If one revision is given, it is used as the base revision.
2083 If one revision is given, it is used as the base revision.
2084 If two revisions are given, the difference between them is shown.
2084 If two revisions are given, the difference between them is shown.
2085
2085
2086 The codes used to show the status of files are:
2086 The codes used to show the status of files are:
2087 M = modified
2087 M = modified
2088 A = added
2088 A = added
2089 R = removed
2089 R = removed
2090 C = clean
2090 C = clean
2091 ! = deleted, but still tracked
2091 ! = deleted, but still tracked
2092 ? = not tracked
2092 ? = not tracked
2093 I = ignored (not shown by default)
2093 I = ignored (not shown by default)
2094 = the previous added file was copied from here
2094 = the previous added file was copied from here
2095 """
2095 """
2096
2096
2097 all = opts['all']
2097 all = opts['all']
2098 node1, node2 = cmdutil.revpair(ui, repo, opts.get('rev'))
2098 node1, node2 = cmdutil.revpair(ui, repo, opts.get('rev'))
2099
2099
2100 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2100 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2101 cwd = (pats and repo.getcwd()) or ''
2101 cwd = (pats and repo.getcwd()) or ''
2102 modified, added, removed, deleted, unknown, ignored, clean = [
2102 modified, added, removed, deleted, unknown, ignored, clean = [
2103 [util.pathto(cwd, x) for x in n]
2103 [util.pathto(cwd, x) for x in n]
2104 for n in repo.status(node1=node1, node2=node2, files=files,
2104 for n in repo.status(node1=node1, node2=node2, files=files,
2105 match=matchfn,
2105 match=matchfn,
2106 list_ignored=all or opts['ignored'],
2106 list_ignored=all or opts['ignored'],
2107 list_clean=all or opts['clean'])]
2107 list_clean=all or opts['clean'])]
2108
2108
2109 changetypes = (('modified', 'M', modified),
2109 changetypes = (('modified', 'M', modified),
2110 ('added', 'A', added),
2110 ('added', 'A', added),
2111 ('removed', 'R', removed),
2111 ('removed', 'R', removed),
2112 ('deleted', '!', deleted),
2112 ('deleted', '!', deleted),
2113 ('unknown', '?', unknown),
2113 ('unknown', '?', unknown),
2114 ('ignored', 'I', ignored))
2114 ('ignored', 'I', ignored))
2115
2115
2116 explicit_changetypes = changetypes + (('clean', 'C', clean),)
2116 explicit_changetypes = changetypes + (('clean', 'C', clean),)
2117
2117
2118 end = opts['print0'] and '\0' or '\n'
2118 end = opts['print0'] and '\0' or '\n'
2119
2119
2120 for opt, char, changes in ([ct for ct in explicit_changetypes
2120 for opt, char, changes in ([ct for ct in explicit_changetypes
2121 if all or opts[ct[0]]]
2121 if all or opts[ct[0]]]
2122 or changetypes):
2122 or changetypes):
2123 if opts['no_status']:
2123 if opts['no_status']:
2124 format = "%%s%s" % end
2124 format = "%%s%s" % end
2125 else:
2125 else:
2126 format = "%s %%s%s" % (char, end)
2126 format = "%s %%s%s" % (char, end)
2127
2127
2128 for f in changes:
2128 for f in changes:
2129 ui.write(format % f)
2129 ui.write(format % f)
2130 if ((all or opts.get('copies')) and not opts.get('no_status')):
2130 if ((all or opts.get('copies')) and not opts.get('no_status')):
2131 copied = repo.dirstate.copied(f)
2131 copied = repo.dirstate.copied(f)
2132 if copied:
2132 if copied:
2133 ui.write(' %s%s' % (copied, end))
2133 ui.write(' %s%s' % (copied, end))
2134
2134
2135 def tag(ui, repo, name, rev_=None, **opts):
2135 def tag(ui, repo, name, rev_=None, **opts):
2136 """add a tag for the current tip or a given revision
2136 """add a tag for the current tip or a given revision
2137
2137
2138 Name a particular revision using <name>.
2138 Name a particular revision using <name>.
2139
2139
2140 Tags are used to name particular revisions of the repository and are
2140 Tags are used to name particular revisions of the repository and are
2141 very useful to compare different revision, to go back to significant
2141 very useful to compare different revision, to go back to significant
2142 earlier versions or to mark branch points as releases, etc.
2142 earlier versions or to mark branch points as releases, etc.
2143
2143
2144 If no revision is given, the parent of the working directory is used.
2144 If no revision is given, the parent of the working directory is used.
2145
2145
2146 To facilitate version control, distribution, and merging of tags,
2146 To facilitate version control, distribution, and merging of tags,
2147 they are stored as a file named ".hgtags" which is managed
2147 they are stored as a file named ".hgtags" which is managed
2148 similarly to other project files and can be hand-edited if
2148 similarly to other project files and can be hand-edited if
2149 necessary. The file '.hg/localtags' is used for local tags (not
2149 necessary. The file '.hg/localtags' is used for local tags (not
2150 shared among repositories).
2150 shared among repositories).
2151 """
2151 """
2152 if name in ['tip', '.']:
2152 if name in ['tip', '.']:
2153 raise util.Abort(_("the name '%s' is reserved") % name)
2153 raise util.Abort(_("the name '%s' is reserved") % name)
2154 if rev_ is not None:
2154 if rev_ is not None:
2155 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2155 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2156 "please use 'hg tag [-r REV] NAME' instead\n"))
2156 "please use 'hg tag [-r REV] NAME' instead\n"))
2157 if opts['rev']:
2157 if opts['rev']:
2158 raise util.Abort(_("use only one form to specify the revision"))
2158 raise util.Abort(_("use only one form to specify the revision"))
2159 if opts['rev']:
2159 if opts['rev']:
2160 rev_ = opts['rev']
2160 rev_ = opts['rev']
2161 if not rev_ and repo.dirstate.parents()[1] != nullid:
2161 if not rev_ and repo.dirstate.parents()[1] != nullid:
2162 raise util.Abort(_('uncommitted merge - please provide a '
2162 raise util.Abort(_('uncommitted merge - please provide a '
2163 'specific revision'))
2163 'specific revision'))
2164 r = repo.changectx(rev_).node()
2164 r = repo.changectx(rev_).node()
2165
2165
2166 message = opts['message']
2166 message = opts['message']
2167 if not message:
2167 if not message:
2168 message = _('Added tag %s for changeset %s') % (name, short(r))
2168 message = _('Added tag %s for changeset %s') % (name, short(r))
2169
2169
2170 repo.tag(name, r, message, opts['local'], opts['user'], opts['date'])
2170 repo.tag(name, r, message, opts['local'], opts['user'], opts['date'])
2171
2171
2172 def tags(ui, repo):
2172 def tags(ui, repo):
2173 """list repository tags
2173 """list repository tags
2174
2174
2175 List the repository tags.
2175 List the repository tags.
2176
2176
2177 This lists both regular and local tags.
2177 This lists both regular and local tags.
2178 """
2178 """
2179
2179
2180 l = repo.tagslist()
2180 l = repo.tagslist()
2181 l.reverse()
2181 l.reverse()
2182 hexfunc = ui.debugflag and hex or short
2182 hexfunc = ui.debugflag and hex or short
2183 for t, n in l:
2183 for t, n in l:
2184 try:
2184 try:
2185 r = "%5d:%s" % (repo.changelog.rev(n), hexfunc(n))
2185 r = "%5d:%s" % (repo.changelog.rev(n), hexfunc(n))
2186 except KeyError:
2186 except KeyError:
2187 r = " ?:?"
2187 r = " ?:?"
2188 if ui.quiet:
2188 if ui.quiet:
2189 ui.write("%s\n" % t)
2189 ui.write("%s\n" % t)
2190 else:
2190 else:
2191 ui.write("%-30s %s\n" % (t, r))
2191 ui.write("%-30s %s\n" % (t, r))
2192
2192
2193 def tip(ui, repo, **opts):
2193 def tip(ui, repo, **opts):
2194 """show the tip revision
2194 """show the tip revision
2195
2195
2196 Show the tip revision.
2196 Show the tip revision.
2197 """
2197 """
2198 cmdutil.show_changeset(ui, repo, opts).show(repo.changelog.count()-1)
2198 cmdutil.show_changeset(ui, repo, opts).show(nullrev+repo.changelog.count())
2199
2199
2200 def unbundle(ui, repo, fname, **opts):
2200 def unbundle(ui, repo, fname, **opts):
2201 """apply a changegroup file
2201 """apply a changegroup file
2202
2202
2203 Apply a compressed changegroup file generated by the bundle
2203 Apply a compressed changegroup file generated by the bundle
2204 command.
2204 command.
2205 """
2205 """
2206 gen = changegroup.readbundle(urllib.urlopen(fname))
2206 gen = changegroup.readbundle(urllib.urlopen(fname))
2207 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2207 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2208 return postincoming(ui, repo, modheads, opts['update'])
2208 return postincoming(ui, repo, modheads, opts['update'])
2209
2209
2210 def update(ui, repo, node=None, merge=False, clean=False, force=None,
2210 def update(ui, repo, node=None, merge=False, clean=False, force=None,
2211 branch=None):
2211 branch=None):
2212 """update or merge working directory
2212 """update or merge working directory
2213
2213
2214 Update the working directory to the specified revision.
2214 Update the working directory to the specified revision.
2215
2215
2216 If there are no outstanding changes in the working directory and
2216 If there are no outstanding changes in the working directory and
2217 there is a linear relationship between the current version and the
2217 there is a linear relationship between the current version and the
2218 requested version, the result is the requested version.
2218 requested version, the result is the requested version.
2219
2219
2220 To merge the working directory with another revision, use the
2220 To merge the working directory with another revision, use the
2221 merge command.
2221 merge command.
2222
2222
2223 By default, update will refuse to run if doing so would require
2223 By default, update will refuse to run if doing so would require
2224 merging or discarding local changes.
2224 merging or discarding local changes.
2225 """
2225 """
2226 node = _lookup(repo, node, branch)
2226 node = _lookup(repo, node, branch)
2227 if clean:
2227 if clean:
2228 return hg.clean(repo, node)
2228 return hg.clean(repo, node)
2229 else:
2229 else:
2230 return hg.update(repo, node)
2230 return hg.update(repo, node)
2231
2231
2232 def _lookup(repo, node, branch=None):
2232 def _lookup(repo, node, branch=None):
2233 if branch:
2233 if branch:
2234 repo.ui.warn(_("the --branch option is deprecated, "
2234 repo.ui.warn(_("the --branch option is deprecated, "
2235 "please use 'hg branch' instead\n"))
2235 "please use 'hg branch' instead\n"))
2236 br = repo.branchlookup(branch=branch)
2236 br = repo.branchlookup(branch=branch)
2237 found = []
2237 found = []
2238 for x in br:
2238 for x in br:
2239 if branch in br[x]:
2239 if branch in br[x]:
2240 found.append(x)
2240 found.append(x)
2241 if len(found) > 1:
2241 if len(found) > 1:
2242 repo.ui.warn(_("Found multiple heads for %s\n") % branch)
2242 repo.ui.warn(_("Found multiple heads for %s\n") % branch)
2243 for x in found:
2243 for x in found:
2244 cmdutil.show_changeset(ui, repo, {}).show(changenode=x)
2244 cmdutil.show_changeset(ui, repo, {}).show(changenode=x)
2245 raise util.Abort("")
2245 raise util.Abort("")
2246 if len(found) == 1:
2246 if len(found) == 1:
2247 node = found[0]
2247 node = found[0]
2248 repo.ui.warn(_("Using head %s for branch %s\n")
2248 repo.ui.warn(_("Using head %s for branch %s\n")
2249 % (short(node), branch))
2249 % (short(node), branch))
2250 else:
2250 else:
2251 raise util.Abort(_("branch %s not found") % branch)
2251 raise util.Abort(_("branch %s not found") % branch)
2252 else:
2252 else:
2253 node = node and repo.lookup(node) or repo.changelog.tip()
2253 node = node and repo.lookup(node) or repo.changelog.tip()
2254 return node
2254 return node
2255
2255
2256 def verify(ui, repo):
2256 def verify(ui, repo):
2257 """verify the integrity of the repository
2257 """verify the integrity of the repository
2258
2258
2259 Verify the integrity of the current repository.
2259 Verify the integrity of the current repository.
2260
2260
2261 This will perform an extensive check of the repository's
2261 This will perform an extensive check of the repository's
2262 integrity, validating the hashes and checksums of each entry in
2262 integrity, validating the hashes and checksums of each entry in
2263 the changelog, manifest, and tracked files, as well as the
2263 the changelog, manifest, and tracked files, as well as the
2264 integrity of their crosslinks and indices.
2264 integrity of their crosslinks and indices.
2265 """
2265 """
2266 return hg.verify(repo)
2266 return hg.verify(repo)
2267
2267
2268 def version_(ui):
2268 def version_(ui):
2269 """output version and copyright information"""
2269 """output version and copyright information"""
2270 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2270 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2271 % version.get_version())
2271 % version.get_version())
2272 ui.status(_(
2272 ui.status(_(
2273 "\nCopyright (C) 2005, 2006 Matt Mackall <mpm@selenic.com>\n"
2273 "\nCopyright (C) 2005, 2006 Matt Mackall <mpm@selenic.com>\n"
2274 "This is free software; see the source for copying conditions. "
2274 "This is free software; see the source for copying conditions. "
2275 "There is NO\nwarranty; "
2275 "There is NO\nwarranty; "
2276 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2276 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2277 ))
2277 ))
2278
2278
2279 # Command options and aliases are listed here, alphabetically
2279 # Command options and aliases are listed here, alphabetically
2280
2280
2281 globalopts = [
2281 globalopts = [
2282 ('R', 'repository', '',
2282 ('R', 'repository', '',
2283 _('repository root directory or symbolic path name')),
2283 _('repository root directory or symbolic path name')),
2284 ('', 'cwd', '', _('change working directory')),
2284 ('', 'cwd', '', _('change working directory')),
2285 ('y', 'noninteractive', None,
2285 ('y', 'noninteractive', None,
2286 _('do not prompt, assume \'yes\' for any required answers')),
2286 _('do not prompt, assume \'yes\' for any required answers')),
2287 ('q', 'quiet', None, _('suppress output')),
2287 ('q', 'quiet', None, _('suppress output')),
2288 ('v', 'verbose', None, _('enable additional output')),
2288 ('v', 'verbose', None, _('enable additional output')),
2289 ('', 'config', [], _('set/override config option')),
2289 ('', 'config', [], _('set/override config option')),
2290 ('', 'debug', None, _('enable debugging output')),
2290 ('', 'debug', None, _('enable debugging output')),
2291 ('', 'debugger', None, _('start debugger')),
2291 ('', 'debugger', None, _('start debugger')),
2292 ('', 'lsprof', None, _('print improved command execution profile')),
2292 ('', 'lsprof', None, _('print improved command execution profile')),
2293 ('', 'traceback', None, _('print traceback on exception')),
2293 ('', 'traceback', None, _('print traceback on exception')),
2294 ('', 'time', None, _('time how long the command takes')),
2294 ('', 'time', None, _('time how long the command takes')),
2295 ('', 'profile', None, _('print command execution profile')),
2295 ('', 'profile', None, _('print command execution profile')),
2296 ('', 'version', None, _('output version information and exit')),
2296 ('', 'version', None, _('output version information and exit')),
2297 ('h', 'help', None, _('display help and exit')),
2297 ('h', 'help', None, _('display help and exit')),
2298 ]
2298 ]
2299
2299
2300 dryrunopts = [('n', 'dry-run', None,
2300 dryrunopts = [('n', 'dry-run', None,
2301 _('do not perform actions, just print output'))]
2301 _('do not perform actions, just print output'))]
2302
2302
2303 remoteopts = [
2303 remoteopts = [
2304 ('e', 'ssh', '', _('specify ssh command to use')),
2304 ('e', 'ssh', '', _('specify ssh command to use')),
2305 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2305 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2306 ]
2306 ]
2307
2307
2308 walkopts = [
2308 walkopts = [
2309 ('I', 'include', [], _('include names matching the given patterns')),
2309 ('I', 'include', [], _('include names matching the given patterns')),
2310 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2310 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2311 ]
2311 ]
2312
2312
2313 table = {
2313 table = {
2314 "^add":
2314 "^add":
2315 (add,
2315 (add,
2316 walkopts + dryrunopts,
2316 walkopts + dryrunopts,
2317 _('hg add [OPTION]... [FILE]...')),
2317 _('hg add [OPTION]... [FILE]...')),
2318 "addremove":
2318 "addremove":
2319 (addremove,
2319 (addremove,
2320 [('s', 'similarity', '',
2320 [('s', 'similarity', '',
2321 _('guess renamed files by similarity (0<=s<=100)')),
2321 _('guess renamed files by similarity (0<=s<=100)')),
2322 ] + walkopts + dryrunopts,
2322 ] + walkopts + dryrunopts,
2323 _('hg addremove [OPTION]... [FILE]...')),
2323 _('hg addremove [OPTION]... [FILE]...')),
2324 "^annotate":
2324 "^annotate":
2325 (annotate,
2325 (annotate,
2326 [('r', 'rev', '', _('annotate the specified revision')),
2326 [('r', 'rev', '', _('annotate the specified revision')),
2327 ('f', 'follow', None, _('follow file copies and renames')),
2327 ('f', 'follow', None, _('follow file copies and renames')),
2328 ('a', 'text', None, _('treat all files as text')),
2328 ('a', 'text', None, _('treat all files as text')),
2329 ('u', 'user', None, _('list the author')),
2329 ('u', 'user', None, _('list the author')),
2330 ('d', 'date', None, _('list the date')),
2330 ('d', 'date', None, _('list the date')),
2331 ('n', 'number', None, _('list the revision number (default)')),
2331 ('n', 'number', None, _('list the revision number (default)')),
2332 ('c', 'changeset', None, _('list the changeset')),
2332 ('c', 'changeset', None, _('list the changeset')),
2333 ] + walkopts,
2333 ] + walkopts,
2334 _('hg annotate [-r REV] [-a] [-u] [-d] [-n] [-c] FILE...')),
2334 _('hg annotate [-r REV] [-a] [-u] [-d] [-n] [-c] FILE...')),
2335 "archive":
2335 "archive":
2336 (archive,
2336 (archive,
2337 [('', 'no-decode', None, _('do not pass files through decoders')),
2337 [('', 'no-decode', None, _('do not pass files through decoders')),
2338 ('p', 'prefix', '', _('directory prefix for files in archive')),
2338 ('p', 'prefix', '', _('directory prefix for files in archive')),
2339 ('r', 'rev', '', _('revision to distribute')),
2339 ('r', 'rev', '', _('revision to distribute')),
2340 ('t', 'type', '', _('type of distribution to create')),
2340 ('t', 'type', '', _('type of distribution to create')),
2341 ] + walkopts,
2341 ] + walkopts,
2342 _('hg archive [OPTION]... DEST')),
2342 _('hg archive [OPTION]... DEST')),
2343 "backout":
2343 "backout":
2344 (backout,
2344 (backout,
2345 [('', 'merge', None,
2345 [('', 'merge', None,
2346 _('merge with old dirstate parent after backout')),
2346 _('merge with old dirstate parent after backout')),
2347 ('m', 'message', '', _('use <text> as commit message')),
2347 ('m', 'message', '', _('use <text> as commit message')),
2348 ('l', 'logfile', '', _('read commit message from <file>')),
2348 ('l', 'logfile', '', _('read commit message from <file>')),
2349 ('d', 'date', '', _('record datecode as commit date')),
2349 ('d', 'date', '', _('record datecode as commit date')),
2350 ('', 'parent', '', _('parent to choose when backing out merge')),
2350 ('', 'parent', '', _('parent to choose when backing out merge')),
2351 ('u', 'user', '', _('record user as committer')),
2351 ('u', 'user', '', _('record user as committer')),
2352 ] + walkopts,
2352 ] + walkopts,
2353 _('hg backout [OPTION]... REV')),
2353 _('hg backout [OPTION]... REV')),
2354 "branch": (branch, [], _('hg branch [NAME]')),
2354 "branch": (branch, [], _('hg branch [NAME]')),
2355 "branches": (branches, [], _('hg branches')),
2355 "branches": (branches, [], _('hg branches')),
2356 "bundle":
2356 "bundle":
2357 (bundle,
2357 (bundle,
2358 [('f', 'force', None,
2358 [('f', 'force', None,
2359 _('run even when remote repository is unrelated')),
2359 _('run even when remote repository is unrelated')),
2360 ('r', 'rev', [],
2360 ('r', 'rev', [],
2361 _('a changeset you would like to bundle')),
2361 _('a changeset you would like to bundle')),
2362 ('', 'base', [],
2362 ('', 'base', [],
2363 _('a base changeset to specify instead of a destination')),
2363 _('a base changeset to specify instead of a destination')),
2364 ] + remoteopts,
2364 ] + remoteopts,
2365 _('hg bundle [--base REV]... [--rev REV]... FILE [DEST]')),
2365 _('hg bundle [--base REV]... [--rev REV]... FILE [DEST]')),
2366 "cat":
2366 "cat":
2367 (cat,
2367 (cat,
2368 [('o', 'output', '', _('print output to file with formatted name')),
2368 [('o', 'output', '', _('print output to file with formatted name')),
2369 ('r', 'rev', '', _('print the given revision')),
2369 ('r', 'rev', '', _('print the given revision')),
2370 ] + walkopts,
2370 ] + walkopts,
2371 _('hg cat [OPTION]... FILE...')),
2371 _('hg cat [OPTION]... FILE...')),
2372 "^clone":
2372 "^clone":
2373 (clone,
2373 (clone,
2374 [('U', 'noupdate', None, _('do not update the new working directory')),
2374 [('U', 'noupdate', None, _('do not update the new working directory')),
2375 ('r', 'rev', [],
2375 ('r', 'rev', [],
2376 _('a changeset you would like to have after cloning')),
2376 _('a changeset you would like to have after cloning')),
2377 ('', 'pull', None, _('use pull protocol to copy metadata')),
2377 ('', 'pull', None, _('use pull protocol to copy metadata')),
2378 ('', 'uncompressed', None,
2378 ('', 'uncompressed', None,
2379 _('use uncompressed transfer (fast over LAN)')),
2379 _('use uncompressed transfer (fast over LAN)')),
2380 ] + remoteopts,
2380 ] + remoteopts,
2381 _('hg clone [OPTION]... SOURCE [DEST]')),
2381 _('hg clone [OPTION]... SOURCE [DEST]')),
2382 "^commit|ci":
2382 "^commit|ci":
2383 (commit,
2383 (commit,
2384 [('A', 'addremove', None,
2384 [('A', 'addremove', None,
2385 _('mark new/missing files as added/removed before committing')),
2385 _('mark new/missing files as added/removed before committing')),
2386 ('m', 'message', '', _('use <text> as commit message')),
2386 ('m', 'message', '', _('use <text> as commit message')),
2387 ('l', 'logfile', '', _('read the commit message from <file>')),
2387 ('l', 'logfile', '', _('read the commit message from <file>')),
2388 ('d', 'date', '', _('record datecode as commit date')),
2388 ('d', 'date', '', _('record datecode as commit date')),
2389 ('u', 'user', '', _('record user as commiter')),
2389 ('u', 'user', '', _('record user as commiter')),
2390 ] + walkopts,
2390 ] + walkopts,
2391 _('hg commit [OPTION]... [FILE]...')),
2391 _('hg commit [OPTION]... [FILE]...')),
2392 "copy|cp":
2392 "copy|cp":
2393 (copy,
2393 (copy,
2394 [('A', 'after', None, _('record a copy that has already occurred')),
2394 [('A', 'after', None, _('record a copy that has already occurred')),
2395 ('f', 'force', None,
2395 ('f', 'force', None,
2396 _('forcibly copy over an existing managed file')),
2396 _('forcibly copy over an existing managed file')),
2397 ] + walkopts + dryrunopts,
2397 ] + walkopts + dryrunopts,
2398 _('hg copy [OPTION]... [SOURCE]... DEST')),
2398 _('hg copy [OPTION]... [SOURCE]... DEST')),
2399 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2399 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2400 "debugcomplete":
2400 "debugcomplete":
2401 (debugcomplete,
2401 (debugcomplete,
2402 [('o', 'options', None, _('show the command options'))],
2402 [('o', 'options', None, _('show the command options'))],
2403 _('debugcomplete [-o] CMD')),
2403 _('debugcomplete [-o] CMD')),
2404 "debugrebuildstate":
2404 "debugrebuildstate":
2405 (debugrebuildstate,
2405 (debugrebuildstate,
2406 [('r', 'rev', '', _('revision to rebuild to'))],
2406 [('r', 'rev', '', _('revision to rebuild to'))],
2407 _('debugrebuildstate [-r REV] [REV]')),
2407 _('debugrebuildstate [-r REV] [REV]')),
2408 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2408 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2409 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2409 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2410 "debugstate": (debugstate, [], _('debugstate')),
2410 "debugstate": (debugstate, [], _('debugstate')),
2411 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2411 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2412 "debugindex": (debugindex, [], _('debugindex FILE')),
2412 "debugindex": (debugindex, [], _('debugindex FILE')),
2413 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2413 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2414 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2414 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2415 "debugwalk":
2415 "debugwalk":
2416 (debugwalk, walkopts, _('debugwalk [OPTION]... [FILE]...')),
2416 (debugwalk, walkopts, _('debugwalk [OPTION]... [FILE]...')),
2417 "^diff":
2417 "^diff":
2418 (diff,
2418 (diff,
2419 [('r', 'rev', [], _('revision')),
2419 [('r', 'rev', [], _('revision')),
2420 ('a', 'text', None, _('treat all files as text')),
2420 ('a', 'text', None, _('treat all files as text')),
2421 ('p', 'show-function', None,
2421 ('p', 'show-function', None,
2422 _('show which function each change is in')),
2422 _('show which function each change is in')),
2423 ('g', 'git', None, _('use git extended diff format')),
2423 ('g', 'git', None, _('use git extended diff format')),
2424 ('', 'nodates', None, _("don't include dates in diff headers")),
2424 ('', 'nodates', None, _("don't include dates in diff headers")),
2425 ('w', 'ignore-all-space', None,
2425 ('w', 'ignore-all-space', None,
2426 _('ignore white space when comparing lines')),
2426 _('ignore white space when comparing lines')),
2427 ('b', 'ignore-space-change', None,
2427 ('b', 'ignore-space-change', None,
2428 _('ignore changes in the amount of white space')),
2428 _('ignore changes in the amount of white space')),
2429 ('B', 'ignore-blank-lines', None,
2429 ('B', 'ignore-blank-lines', None,
2430 _('ignore changes whose lines are all blank')),
2430 _('ignore changes whose lines are all blank')),
2431 ] + walkopts,
2431 ] + walkopts,
2432 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2432 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2433 "^export":
2433 "^export":
2434 (export,
2434 (export,
2435 [('o', 'output', '', _('print output to file with formatted name')),
2435 [('o', 'output', '', _('print output to file with formatted name')),
2436 ('a', 'text', None, _('treat all files as text')),
2436 ('a', 'text', None, _('treat all files as text')),
2437 ('g', 'git', None, _('use git extended diff format')),
2437 ('g', 'git', None, _('use git extended diff format')),
2438 ('', 'nodates', None, _("don't include dates in diff headers")),
2438 ('', 'nodates', None, _("don't include dates in diff headers")),
2439 ('', 'switch-parent', None, _('diff against the second parent'))],
2439 ('', 'switch-parent', None, _('diff against the second parent'))],
2440 _('hg export [-a] [-o OUTFILESPEC] REV...')),
2440 _('hg export [-a] [-o OUTFILESPEC] REV...')),
2441 "grep":
2441 "grep":
2442 (grep,
2442 (grep,
2443 [('0', 'print0', None, _('end fields with NUL')),
2443 [('0', 'print0', None, _('end fields with NUL')),
2444 ('', 'all', None, _('print all revisions that match')),
2444 ('', 'all', None, _('print all revisions that match')),
2445 ('f', 'follow', None,
2445 ('f', 'follow', None,
2446 _('follow changeset history, or file history across copies and renames')),
2446 _('follow changeset history, or file history across copies and renames')),
2447 ('i', 'ignore-case', None, _('ignore case when matching')),
2447 ('i', 'ignore-case', None, _('ignore case when matching')),
2448 ('l', 'files-with-matches', None,
2448 ('l', 'files-with-matches', None,
2449 _('print only filenames and revs that match')),
2449 _('print only filenames and revs that match')),
2450 ('n', 'line-number', None, _('print matching line numbers')),
2450 ('n', 'line-number', None, _('print matching line numbers')),
2451 ('r', 'rev', [], _('search in given revision range')),
2451 ('r', 'rev', [], _('search in given revision range')),
2452 ('u', 'user', None, _('print user who committed change')),
2452 ('u', 'user', None, _('print user who committed change')),
2453 ] + walkopts,
2453 ] + walkopts,
2454 _('hg grep [OPTION]... PATTERN [FILE]...')),
2454 _('hg grep [OPTION]... PATTERN [FILE]...')),
2455 "heads":
2455 "heads":
2456 (heads,
2456 (heads,
2457 [('b', 'branches', None, _('show branches (DEPRECATED)')),
2457 [('b', 'branches', None, _('show branches (DEPRECATED)')),
2458 ('', 'style', '', _('display using template map file')),
2458 ('', 'style', '', _('display using template map file')),
2459 ('r', 'rev', '', _('show only heads which are descendants of rev')),
2459 ('r', 'rev', '', _('show only heads which are descendants of rev')),
2460 ('', 'template', '', _('display with template'))],
2460 ('', 'template', '', _('display with template'))],
2461 _('hg heads [-r REV]')),
2461 _('hg heads [-r REV]')),
2462 "help": (help_, [], _('hg help [COMMAND]')),
2462 "help": (help_, [], _('hg help [COMMAND]')),
2463 "identify|id": (identify, [], _('hg identify')),
2463 "identify|id": (identify, [], _('hg identify')),
2464 "import|patch":
2464 "import|patch":
2465 (import_,
2465 (import_,
2466 [('p', 'strip', 1,
2466 [('p', 'strip', 1,
2467 _('directory strip option for patch. This has the same\n'
2467 _('directory strip option for patch. This has the same\n'
2468 'meaning as the corresponding patch option')),
2468 'meaning as the corresponding patch option')),
2469 ('m', 'message', '', _('use <text> as commit message')),
2469 ('m', 'message', '', _('use <text> as commit message')),
2470 ('b', 'base', '', _('base path (DEPRECATED)')),
2470 ('b', 'base', '', _('base path (DEPRECATED)')),
2471 ('f', 'force', None,
2471 ('f', 'force', None,
2472 _('skip check for outstanding uncommitted changes'))],
2472 _('skip check for outstanding uncommitted changes'))],
2473 _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')),
2473 _('hg import [-p NUM] [-m MESSAGE] [-f] PATCH...')),
2474 "incoming|in": (incoming,
2474 "incoming|in": (incoming,
2475 [('M', 'no-merges', None, _('do not show merges')),
2475 [('M', 'no-merges', None, _('do not show merges')),
2476 ('f', 'force', None,
2476 ('f', 'force', None,
2477 _('run even when remote repository is unrelated')),
2477 _('run even when remote repository is unrelated')),
2478 ('', 'style', '', _('display using template map file')),
2478 ('', 'style', '', _('display using template map file')),
2479 ('n', 'newest-first', None, _('show newest record first')),
2479 ('n', 'newest-first', None, _('show newest record first')),
2480 ('', 'bundle', '', _('file to store the bundles into')),
2480 ('', 'bundle', '', _('file to store the bundles into')),
2481 ('p', 'patch', None, _('show patch')),
2481 ('p', 'patch', None, _('show patch')),
2482 ('r', 'rev', [], _('a specific revision up to which you would like to pull')),
2482 ('r', 'rev', [], _('a specific revision up to which you would like to pull')),
2483 ('', 'template', '', _('display with template')),
2483 ('', 'template', '', _('display with template')),
2484 ] + remoteopts,
2484 ] + remoteopts,
2485 _('hg incoming [-p] [-n] [-M] [-r REV]...'
2485 _('hg incoming [-p] [-n] [-M] [-r REV]...'
2486 ' [--bundle FILENAME] [SOURCE]')),
2486 ' [--bundle FILENAME] [SOURCE]')),
2487 "^init":
2487 "^init":
2488 (init, remoteopts, _('hg init [-e FILE] [--remotecmd FILE] [DEST]')),
2488 (init, remoteopts, _('hg init [-e FILE] [--remotecmd FILE] [DEST]')),
2489 "locate":
2489 "locate":
2490 (locate,
2490 (locate,
2491 [('r', 'rev', '', _('search the repository as it stood at rev')),
2491 [('r', 'rev', '', _('search the repository as it stood at rev')),
2492 ('0', 'print0', None,
2492 ('0', 'print0', None,
2493 _('end filenames with NUL, for use with xargs')),
2493 _('end filenames with NUL, for use with xargs')),
2494 ('f', 'fullpath', None,
2494 ('f', 'fullpath', None,
2495 _('print complete paths from the filesystem root')),
2495 _('print complete paths from the filesystem root')),
2496 ] + walkopts,
2496 ] + walkopts,
2497 _('hg locate [OPTION]... [PATTERN]...')),
2497 _('hg locate [OPTION]... [PATTERN]...')),
2498 "^log|history":
2498 "^log|history":
2499 (log,
2499 (log,
2500 [('b', 'branches', None, _('show branches (DEPRECATED)')),
2500 [('b', 'branches', None, _('show branches (DEPRECATED)')),
2501 ('f', 'follow', None,
2501 ('f', 'follow', None,
2502 _('follow changeset history, or file history across copies and renames')),
2502 _('follow changeset history, or file history across copies and renames')),
2503 ('', 'follow-first', None,
2503 ('', 'follow-first', None,
2504 _('only follow the first parent of merge changesets')),
2504 _('only follow the first parent of merge changesets')),
2505 ('C', 'copies', None, _('show copied files')),
2505 ('C', 'copies', None, _('show copied files')),
2506 ('k', 'keyword', [], _('search for a keyword')),
2506 ('k', 'keyword', [], _('search for a keyword')),
2507 ('l', 'limit', '', _('limit number of changes displayed')),
2507 ('l', 'limit', '', _('limit number of changes displayed')),
2508 ('r', 'rev', [], _('show the specified revision or range')),
2508 ('r', 'rev', [], _('show the specified revision or range')),
2509 ('', 'removed', None, _('include revs where files were removed')),
2509 ('', 'removed', None, _('include revs where files were removed')),
2510 ('M', 'no-merges', None, _('do not show merges')),
2510 ('M', 'no-merges', None, _('do not show merges')),
2511 ('', 'style', '', _('display using template map file')),
2511 ('', 'style', '', _('display using template map file')),
2512 ('m', 'only-merges', None, _('show only merges')),
2512 ('m', 'only-merges', None, _('show only merges')),
2513 ('p', 'patch', None, _('show patch')),
2513 ('p', 'patch', None, _('show patch')),
2514 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
2514 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
2515 ('', 'template', '', _('display with template')),
2515 ('', 'template', '', _('display with template')),
2516 ] + walkopts,
2516 ] + walkopts,
2517 _('hg log [OPTION]... [FILE]')),
2517 _('hg log [OPTION]... [FILE]')),
2518 "manifest": (manifest, [], _('hg manifest [REV]')),
2518 "manifest": (manifest, [], _('hg manifest [REV]')),
2519 "merge":
2519 "merge":
2520 (merge,
2520 (merge,
2521 [('b', 'branch', '', _('merge with head of a specific branch (DEPRECATED)')),
2521 [('b', 'branch', '', _('merge with head of a specific branch (DEPRECATED)')),
2522 ('f', 'force', None, _('force a merge with outstanding changes'))],
2522 ('f', 'force', None, _('force a merge with outstanding changes'))],
2523 _('hg merge [-f] [REV]')),
2523 _('hg merge [-f] [REV]')),
2524 "outgoing|out": (outgoing,
2524 "outgoing|out": (outgoing,
2525 [('M', 'no-merges', None, _('do not show merges')),
2525 [('M', 'no-merges', None, _('do not show merges')),
2526 ('f', 'force', None,
2526 ('f', 'force', None,
2527 _('run even when remote repository is unrelated')),
2527 _('run even when remote repository is unrelated')),
2528 ('p', 'patch', None, _('show patch')),
2528 ('p', 'patch', None, _('show patch')),
2529 ('', 'style', '', _('display using template map file')),
2529 ('', 'style', '', _('display using template map file')),
2530 ('r', 'rev', [], _('a specific revision you would like to push')),
2530 ('r', 'rev', [], _('a specific revision you would like to push')),
2531 ('n', 'newest-first', None, _('show newest record first')),
2531 ('n', 'newest-first', None, _('show newest record first')),
2532 ('', 'template', '', _('display with template')),
2532 ('', 'template', '', _('display with template')),
2533 ] + remoteopts,
2533 ] + remoteopts,
2534 _('hg outgoing [-M] [-p] [-n] [-r REV]... [DEST]')),
2534 _('hg outgoing [-M] [-p] [-n] [-r REV]... [DEST]')),
2535 "^parents":
2535 "^parents":
2536 (parents,
2536 (parents,
2537 [('b', 'branches', None, _('show branches (DEPRECATED)')),
2537 [('b', 'branches', None, _('show branches (DEPRECATED)')),
2538 ('r', 'rev', '', _('show parents from the specified rev')),
2538 ('r', 'rev', '', _('show parents from the specified rev')),
2539 ('', 'style', '', _('display using template map file')),
2539 ('', 'style', '', _('display using template map file')),
2540 ('', 'template', '', _('display with template'))],
2540 ('', 'template', '', _('display with template'))],
2541 _('hg parents [-r REV] [FILE]')),
2541 _('hg parents [-r REV] [FILE]')),
2542 "paths": (paths, [], _('hg paths [NAME]')),
2542 "paths": (paths, [], _('hg paths [NAME]')),
2543 "^pull":
2543 "^pull":
2544 (pull,
2544 (pull,
2545 [('u', 'update', None,
2545 [('u', 'update', None,
2546 _('update to new tip if changesets were pulled')),
2546 _('update to new tip if changesets were pulled')),
2547 ('f', 'force', None,
2547 ('f', 'force', None,
2548 _('run even when remote repository is unrelated')),
2548 _('run even when remote repository is unrelated')),
2549 ('r', 'rev', [], _('a specific revision up to which you would like to pull')),
2549 ('r', 'rev', [], _('a specific revision up to which you would like to pull')),
2550 ] + remoteopts,
2550 ] + remoteopts,
2551 _('hg pull [-u] [-r REV]... [-e FILE] [--remotecmd FILE] [SOURCE]')),
2551 _('hg pull [-u] [-r REV]... [-e FILE] [--remotecmd FILE] [SOURCE]')),
2552 "^push":
2552 "^push":
2553 (push,
2553 (push,
2554 [('f', 'force', None, _('force push')),
2554 [('f', 'force', None, _('force push')),
2555 ('r', 'rev', [], _('a specific revision you would like to push')),
2555 ('r', 'rev', [], _('a specific revision you would like to push')),
2556 ] + remoteopts,
2556 ] + remoteopts,
2557 _('hg push [-f] [-r REV]... [-e FILE] [--remotecmd FILE] [DEST]')),
2557 _('hg push [-f] [-r REV]... [-e FILE] [--remotecmd FILE] [DEST]')),
2558 "debugrawcommit|rawcommit":
2558 "debugrawcommit|rawcommit":
2559 (rawcommit,
2559 (rawcommit,
2560 [('p', 'parent', [], _('parent')),
2560 [('p', 'parent', [], _('parent')),
2561 ('d', 'date', '', _('date code')),
2561 ('d', 'date', '', _('date code')),
2562 ('u', 'user', '', _('user')),
2562 ('u', 'user', '', _('user')),
2563 ('F', 'files', '', _('file list')),
2563 ('F', 'files', '', _('file list')),
2564 ('m', 'message', '', _('commit message')),
2564 ('m', 'message', '', _('commit message')),
2565 ('l', 'logfile', '', _('commit message file'))],
2565 ('l', 'logfile', '', _('commit message file'))],
2566 _('hg debugrawcommit [OPTION]... [FILE]...')),
2566 _('hg debugrawcommit [OPTION]... [FILE]...')),
2567 "recover": (recover, [], _('hg recover')),
2567 "recover": (recover, [], _('hg recover')),
2568 "^remove|rm":
2568 "^remove|rm":
2569 (remove,
2569 (remove,
2570 [('A', 'after', None, _('record remove that has already occurred')),
2570 [('A', 'after', None, _('record remove that has already occurred')),
2571 ('f', 'force', None, _('remove file even if modified')),
2571 ('f', 'force', None, _('remove file even if modified')),
2572 ] + walkopts,
2572 ] + walkopts,
2573 _('hg remove [OPTION]... FILE...')),
2573 _('hg remove [OPTION]... FILE...')),
2574 "rename|mv":
2574 "rename|mv":
2575 (rename,
2575 (rename,
2576 [('A', 'after', None, _('record a rename that has already occurred')),
2576 [('A', 'after', None, _('record a rename that has already occurred')),
2577 ('f', 'force', None,
2577 ('f', 'force', None,
2578 _('forcibly copy over an existing managed file')),
2578 _('forcibly copy over an existing managed file')),
2579 ] + walkopts + dryrunopts,
2579 ] + walkopts + dryrunopts,
2580 _('hg rename [OPTION]... SOURCE... DEST')),
2580 _('hg rename [OPTION]... SOURCE... DEST')),
2581 "^revert":
2581 "^revert":
2582 (revert,
2582 (revert,
2583 [('a', 'all', None, _('revert all changes when no arguments given')),
2583 [('a', 'all', None, _('revert all changes when no arguments given')),
2584 ('r', 'rev', '', _('revision to revert to')),
2584 ('r', 'rev', '', _('revision to revert to')),
2585 ('', 'no-backup', None, _('do not save backup copies of files')),
2585 ('', 'no-backup', None, _('do not save backup copies of files')),
2586 ] + walkopts + dryrunopts,
2586 ] + walkopts + dryrunopts,
2587 _('hg revert [-r REV] [NAME]...')),
2587 _('hg revert [-r REV] [NAME]...')),
2588 "rollback": (rollback, [], _('hg rollback')),
2588 "rollback": (rollback, [], _('hg rollback')),
2589 "root": (root, [], _('hg root')),
2589 "root": (root, [], _('hg root')),
2590 "showconfig|debugconfig":
2590 "showconfig|debugconfig":
2591 (showconfig,
2591 (showconfig,
2592 [('u', 'untrusted', None, _('show untrusted configuration options'))],
2592 [('u', 'untrusted', None, _('show untrusted configuration options'))],
2593 _('showconfig [-u] [NAME]...')),
2593 _('showconfig [-u] [NAME]...')),
2594 "^serve":
2594 "^serve":
2595 (serve,
2595 (serve,
2596 [('A', 'accesslog', '', _('name of access log file to write to')),
2596 [('A', 'accesslog', '', _('name of access log file to write to')),
2597 ('d', 'daemon', None, _('run server in background')),
2597 ('d', 'daemon', None, _('run server in background')),
2598 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
2598 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
2599 ('E', 'errorlog', '', _('name of error log file to write to')),
2599 ('E', 'errorlog', '', _('name of error log file to write to')),
2600 ('p', 'port', 0, _('port to use (default: 8000)')),
2600 ('p', 'port', 0, _('port to use (default: 8000)')),
2601 ('a', 'address', '', _('address to use')),
2601 ('a', 'address', '', _('address to use')),
2602 ('n', 'name', '',
2602 ('n', 'name', '',
2603 _('name to show in web pages (default: working dir)')),
2603 _('name to show in web pages (default: working dir)')),
2604 ('', 'webdir-conf', '', _('name of the webdir config file'
2604 ('', 'webdir-conf', '', _('name of the webdir config file'
2605 ' (serve more than one repo)')),
2605 ' (serve more than one repo)')),
2606 ('', 'pid-file', '', _('name of file to write process ID to')),
2606 ('', 'pid-file', '', _('name of file to write process ID to')),
2607 ('', 'stdio', None, _('for remote clients')),
2607 ('', 'stdio', None, _('for remote clients')),
2608 ('t', 'templates', '', _('web templates to use')),
2608 ('t', 'templates', '', _('web templates to use')),
2609 ('', 'style', '', _('template style to use')),
2609 ('', 'style', '', _('template style to use')),
2610 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
2610 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
2611 _('hg serve [OPTION]...')),
2611 _('hg serve [OPTION]...')),
2612 "^status|st":
2612 "^status|st":
2613 (status,
2613 (status,
2614 [('A', 'all', None, _('show status of all files')),
2614 [('A', 'all', None, _('show status of all files')),
2615 ('m', 'modified', None, _('show only modified files')),
2615 ('m', 'modified', None, _('show only modified files')),
2616 ('a', 'added', None, _('show only added files')),
2616 ('a', 'added', None, _('show only added files')),
2617 ('r', 'removed', None, _('show only removed files')),
2617 ('r', 'removed', None, _('show only removed files')),
2618 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
2618 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
2619 ('c', 'clean', None, _('show only files without changes')),
2619 ('c', 'clean', None, _('show only files without changes')),
2620 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
2620 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
2621 ('i', 'ignored', None, _('show ignored files')),
2621 ('i', 'ignored', None, _('show ignored files')),
2622 ('n', 'no-status', None, _('hide status prefix')),
2622 ('n', 'no-status', None, _('hide status prefix')),
2623 ('C', 'copies', None, _('show source of copied files')),
2623 ('C', 'copies', None, _('show source of copied files')),
2624 ('0', 'print0', None,
2624 ('0', 'print0', None,
2625 _('end filenames with NUL, for use with xargs')),
2625 _('end filenames with NUL, for use with xargs')),
2626 ('', 'rev', [], _('show difference from revision')),
2626 ('', 'rev', [], _('show difference from revision')),
2627 ] + walkopts,
2627 ] + walkopts,
2628 _('hg status [OPTION]... [FILE]...')),
2628 _('hg status [OPTION]... [FILE]...')),
2629 "tag":
2629 "tag":
2630 (tag,
2630 (tag,
2631 [('l', 'local', None, _('make the tag local')),
2631 [('l', 'local', None, _('make the tag local')),
2632 ('m', 'message', '', _('message for tag commit log entry')),
2632 ('m', 'message', '', _('message for tag commit log entry')),
2633 ('d', 'date', '', _('record datecode as commit date')),
2633 ('d', 'date', '', _('record datecode as commit date')),
2634 ('u', 'user', '', _('record user as commiter')),
2634 ('u', 'user', '', _('record user as commiter')),
2635 ('r', 'rev', '', _('revision to tag'))],
2635 ('r', 'rev', '', _('revision to tag'))],
2636 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
2636 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
2637 "tags": (tags, [], _('hg tags')),
2637 "tags": (tags, [], _('hg tags')),
2638 "tip":
2638 "tip":
2639 (tip,
2639 (tip,
2640 [('b', 'branches', None, _('show branches (DEPRECATED)')),
2640 [('b', 'branches', None, _('show branches (DEPRECATED)')),
2641 ('', 'style', '', _('display using template map file')),
2641 ('', 'style', '', _('display using template map file')),
2642 ('p', 'patch', None, _('show patch')),
2642 ('p', 'patch', None, _('show patch')),
2643 ('', 'template', '', _('display with template'))],
2643 ('', 'template', '', _('display with template'))],
2644 _('hg tip [-p]')),
2644 _('hg tip [-p]')),
2645 "unbundle":
2645 "unbundle":
2646 (unbundle,
2646 (unbundle,
2647 [('u', 'update', None,
2647 [('u', 'update', None,
2648 _('update to new tip if changesets were unbundled'))],
2648 _('update to new tip if changesets were unbundled'))],
2649 _('hg unbundle [-u] FILE')),
2649 _('hg unbundle [-u] FILE')),
2650 "^update|up|checkout|co":
2650 "^update|up|checkout|co":
2651 (update,
2651 (update,
2652 [('b', 'branch', '',
2652 [('b', 'branch', '',
2653 _('checkout the head of a specific branch (DEPRECATED)')),
2653 _('checkout the head of a specific branch (DEPRECATED)')),
2654 ('m', 'merge', None, _('allow merging of branches (DEPRECATED)')),
2654 ('m', 'merge', None, _('allow merging of branches (DEPRECATED)')),
2655 ('C', 'clean', None, _('overwrite locally modified files')),
2655 ('C', 'clean', None, _('overwrite locally modified files')),
2656 ('f', 'force', None, _('force a merge with outstanding changes'))],
2656 ('f', 'force', None, _('force a merge with outstanding changes'))],
2657 _('hg update [-C] [-f] [REV]')),
2657 _('hg update [-C] [-f] [REV]')),
2658 "verify": (verify, [], _('hg verify')),
2658 "verify": (verify, [], _('hg verify')),
2659 "version": (version_, [], _('hg version')),
2659 "version": (version_, [], _('hg version')),
2660 }
2660 }
2661
2661
2662 norepo = ("clone init version help debugancestor debugcomplete debugdata"
2662 norepo = ("clone init version help debugancestor debugcomplete debugdata"
2663 " debugindex debugindexdot")
2663 " debugindex debugindexdot")
2664 optionalrepo = ("paths serve showconfig")
2664 optionalrepo = ("paths serve showconfig")
2665
2665
2666 def findpossible(ui, cmd):
2666 def findpossible(ui, cmd):
2667 """
2667 """
2668 Return cmd -> (aliases, command table entry)
2668 Return cmd -> (aliases, command table entry)
2669 for each matching command.
2669 for each matching command.
2670 Return debug commands (or their aliases) only if no normal command matches.
2670 Return debug commands (or their aliases) only if no normal command matches.
2671 """
2671 """
2672 choice = {}
2672 choice = {}
2673 debugchoice = {}
2673 debugchoice = {}
2674 for e in table.keys():
2674 for e in table.keys():
2675 aliases = e.lstrip("^").split("|")
2675 aliases = e.lstrip("^").split("|")
2676 found = None
2676 found = None
2677 if cmd in aliases:
2677 if cmd in aliases:
2678 found = cmd
2678 found = cmd
2679 elif not ui.config("ui", "strict"):
2679 elif not ui.config("ui", "strict"):
2680 for a in aliases:
2680 for a in aliases:
2681 if a.startswith(cmd):
2681 if a.startswith(cmd):
2682 found = a
2682 found = a
2683 break
2683 break
2684 if found is not None:
2684 if found is not None:
2685 if aliases[0].startswith("debug") or found.startswith("debug"):
2685 if aliases[0].startswith("debug") or found.startswith("debug"):
2686 debugchoice[found] = (aliases, table[e])
2686 debugchoice[found] = (aliases, table[e])
2687 else:
2687 else:
2688 choice[found] = (aliases, table[e])
2688 choice[found] = (aliases, table[e])
2689
2689
2690 if not choice and debugchoice:
2690 if not choice and debugchoice:
2691 choice = debugchoice
2691 choice = debugchoice
2692
2692
2693 return choice
2693 return choice
2694
2694
2695 def findcmd(ui, cmd):
2695 def findcmd(ui, cmd):
2696 """Return (aliases, command table entry) for command string."""
2696 """Return (aliases, command table entry) for command string."""
2697 choice = findpossible(ui, cmd)
2697 choice = findpossible(ui, cmd)
2698
2698
2699 if choice.has_key(cmd):
2699 if choice.has_key(cmd):
2700 return choice[cmd]
2700 return choice[cmd]
2701
2701
2702 if len(choice) > 1:
2702 if len(choice) > 1:
2703 clist = choice.keys()
2703 clist = choice.keys()
2704 clist.sort()
2704 clist.sort()
2705 raise AmbiguousCommand(cmd, clist)
2705 raise AmbiguousCommand(cmd, clist)
2706
2706
2707 if choice:
2707 if choice:
2708 return choice.values()[0]
2708 return choice.values()[0]
2709
2709
2710 raise UnknownCommand(cmd)
2710 raise UnknownCommand(cmd)
2711
2711
2712 def catchterm(*args):
2712 def catchterm(*args):
2713 raise util.SignalInterrupt
2713 raise util.SignalInterrupt
2714
2714
2715 def run():
2715 def run():
2716 sys.exit(dispatch(sys.argv[1:]))
2716 sys.exit(dispatch(sys.argv[1:]))
2717
2717
2718 class ParseError(Exception):
2718 class ParseError(Exception):
2719 """Exception raised on errors in parsing the command line."""
2719 """Exception raised on errors in parsing the command line."""
2720
2720
2721 def parse(ui, args):
2721 def parse(ui, args):
2722 options = {}
2722 options = {}
2723 cmdoptions = {}
2723 cmdoptions = {}
2724
2724
2725 try:
2725 try:
2726 args = fancyopts.fancyopts(args, globalopts, options)
2726 args = fancyopts.fancyopts(args, globalopts, options)
2727 except fancyopts.getopt.GetoptError, inst:
2727 except fancyopts.getopt.GetoptError, inst:
2728 raise ParseError(None, inst)
2728 raise ParseError(None, inst)
2729
2729
2730 if args:
2730 if args:
2731 cmd, args = args[0], args[1:]
2731 cmd, args = args[0], args[1:]
2732 aliases, i = findcmd(ui, cmd)
2732 aliases, i = findcmd(ui, cmd)
2733 cmd = aliases[0]
2733 cmd = aliases[0]
2734 defaults = ui.config("defaults", cmd)
2734 defaults = ui.config("defaults", cmd)
2735 if defaults:
2735 if defaults:
2736 args = shlex.split(defaults) + args
2736 args = shlex.split(defaults) + args
2737 c = list(i[1])
2737 c = list(i[1])
2738 else:
2738 else:
2739 cmd = None
2739 cmd = None
2740 c = []
2740 c = []
2741
2741
2742 # combine global options into local
2742 # combine global options into local
2743 for o in globalopts:
2743 for o in globalopts:
2744 c.append((o[0], o[1], options[o[1]], o[3]))
2744 c.append((o[0], o[1], options[o[1]], o[3]))
2745
2745
2746 try:
2746 try:
2747 args = fancyopts.fancyopts(args, c, cmdoptions)
2747 args = fancyopts.fancyopts(args, c, cmdoptions)
2748 except fancyopts.getopt.GetoptError, inst:
2748 except fancyopts.getopt.GetoptError, inst:
2749 raise ParseError(cmd, inst)
2749 raise ParseError(cmd, inst)
2750
2750
2751 # separate global options back out
2751 # separate global options back out
2752 for o in globalopts:
2752 for o in globalopts:
2753 n = o[1]
2753 n = o[1]
2754 options[n] = cmdoptions[n]
2754 options[n] = cmdoptions[n]
2755 del cmdoptions[n]
2755 del cmdoptions[n]
2756
2756
2757 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2757 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2758
2758
2759 external = {}
2759 external = {}
2760
2760
2761 def findext(name):
2761 def findext(name):
2762 '''return module with given extension name'''
2762 '''return module with given extension name'''
2763 try:
2763 try:
2764 return sys.modules[external[name]]
2764 return sys.modules[external[name]]
2765 except KeyError:
2765 except KeyError:
2766 for k, v in external.iteritems():
2766 for k, v in external.iteritems():
2767 if k.endswith('.' + name) or k.endswith('/' + name) or v == name:
2767 if k.endswith('.' + name) or k.endswith('/' + name) or v == name:
2768 return sys.modules[v]
2768 return sys.modules[v]
2769 raise KeyError(name)
2769 raise KeyError(name)
2770
2770
2771 def load_extensions(ui):
2771 def load_extensions(ui):
2772 added = []
2772 added = []
2773 for ext_name, load_from_name in ui.extensions():
2773 for ext_name, load_from_name in ui.extensions():
2774 if ext_name in external:
2774 if ext_name in external:
2775 continue
2775 continue
2776 try:
2776 try:
2777 if load_from_name:
2777 if load_from_name:
2778 # the module will be loaded in sys.modules
2778 # the module will be loaded in sys.modules
2779 # choose an unique name so that it doesn't
2779 # choose an unique name so that it doesn't
2780 # conflicts with other modules
2780 # conflicts with other modules
2781 module_name = "hgext_%s" % ext_name.replace('.', '_')
2781 module_name = "hgext_%s" % ext_name.replace('.', '_')
2782 mod = imp.load_source(module_name, load_from_name)
2782 mod = imp.load_source(module_name, load_from_name)
2783 else:
2783 else:
2784 def importh(name):
2784 def importh(name):
2785 mod = __import__(name)
2785 mod = __import__(name)
2786 components = name.split('.')
2786 components = name.split('.')
2787 for comp in components[1:]:
2787 for comp in components[1:]:
2788 mod = getattr(mod, comp)
2788 mod = getattr(mod, comp)
2789 return mod
2789 return mod
2790 try:
2790 try:
2791 mod = importh("hgext.%s" % ext_name)
2791 mod = importh("hgext.%s" % ext_name)
2792 except ImportError:
2792 except ImportError:
2793 mod = importh(ext_name)
2793 mod = importh(ext_name)
2794 external[ext_name] = mod.__name__
2794 external[ext_name] = mod.__name__
2795 added.append((mod, ext_name))
2795 added.append((mod, ext_name))
2796 except (util.SignalInterrupt, KeyboardInterrupt):
2796 except (util.SignalInterrupt, KeyboardInterrupt):
2797 raise
2797 raise
2798 except Exception, inst:
2798 except Exception, inst:
2799 ui.warn(_("*** failed to import extension %s: %s\n") %
2799 ui.warn(_("*** failed to import extension %s: %s\n") %
2800 (ext_name, inst))
2800 (ext_name, inst))
2801 if ui.print_exc():
2801 if ui.print_exc():
2802 return 1
2802 return 1
2803
2803
2804 for mod, name in added:
2804 for mod, name in added:
2805 uisetup = getattr(mod, 'uisetup', None)
2805 uisetup = getattr(mod, 'uisetup', None)
2806 if uisetup:
2806 if uisetup:
2807 uisetup(ui)
2807 uisetup(ui)
2808 cmdtable = getattr(mod, 'cmdtable', {})
2808 cmdtable = getattr(mod, 'cmdtable', {})
2809 for t in cmdtable:
2809 for t in cmdtable:
2810 if t in table:
2810 if t in table:
2811 ui.warn(_("module %s overrides %s\n") % (name, t))
2811 ui.warn(_("module %s overrides %s\n") % (name, t))
2812 table.update(cmdtable)
2812 table.update(cmdtable)
2813
2813
2814 def parseconfig(config):
2814 def parseconfig(config):
2815 """parse the --config options from the command line"""
2815 """parse the --config options from the command line"""
2816 parsed = []
2816 parsed = []
2817 for cfg in config:
2817 for cfg in config:
2818 try:
2818 try:
2819 name, value = cfg.split('=', 1)
2819 name, value = cfg.split('=', 1)
2820 section, name = name.split('.', 1)
2820 section, name = name.split('.', 1)
2821 if not section or not name:
2821 if not section or not name:
2822 raise IndexError
2822 raise IndexError
2823 parsed.append((section, name, value))
2823 parsed.append((section, name, value))
2824 except (IndexError, ValueError):
2824 except (IndexError, ValueError):
2825 raise util.Abort(_('malformed --config option: %s') % cfg)
2825 raise util.Abort(_('malformed --config option: %s') % cfg)
2826 return parsed
2826 return parsed
2827
2827
2828 def dispatch(args):
2828 def dispatch(args):
2829 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
2829 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
2830 num = getattr(signal, name, None)
2830 num = getattr(signal, name, None)
2831 if num: signal.signal(num, catchterm)
2831 if num: signal.signal(num, catchterm)
2832
2832
2833 try:
2833 try:
2834 u = ui.ui(traceback='--traceback' in sys.argv[1:])
2834 u = ui.ui(traceback='--traceback' in sys.argv[1:])
2835 except util.Abort, inst:
2835 except util.Abort, inst:
2836 sys.stderr.write(_("abort: %s\n") % inst)
2836 sys.stderr.write(_("abort: %s\n") % inst)
2837 return -1
2837 return -1
2838
2838
2839 load_extensions(u)
2839 load_extensions(u)
2840 u.addreadhook(load_extensions)
2840 u.addreadhook(load_extensions)
2841
2841
2842 try:
2842 try:
2843 cmd, func, args, options, cmdoptions = parse(u, args)
2843 cmd, func, args, options, cmdoptions = parse(u, args)
2844 if options["time"]:
2844 if options["time"]:
2845 def get_times():
2845 def get_times():
2846 t = os.times()
2846 t = os.times()
2847 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2847 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2848 t = (t[0], t[1], t[2], t[3], time.clock())
2848 t = (t[0], t[1], t[2], t[3], time.clock())
2849 return t
2849 return t
2850 s = get_times()
2850 s = get_times()
2851 def print_time():
2851 def print_time():
2852 t = get_times()
2852 t = get_times()
2853 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2853 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2854 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2854 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2855 atexit.register(print_time)
2855 atexit.register(print_time)
2856
2856
2857 # enter the debugger before command execution
2857 # enter the debugger before command execution
2858 if options['debugger']:
2858 if options['debugger']:
2859 pdb.set_trace()
2859 pdb.set_trace()
2860
2860
2861 try:
2861 try:
2862 if options['cwd']:
2862 if options['cwd']:
2863 try:
2863 try:
2864 os.chdir(options['cwd'])
2864 os.chdir(options['cwd'])
2865 except OSError, inst:
2865 except OSError, inst:
2866 raise util.Abort('%s: %s' %
2866 raise util.Abort('%s: %s' %
2867 (options['cwd'], inst.strerror))
2867 (options['cwd'], inst.strerror))
2868
2868
2869 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2869 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2870 not options["noninteractive"], options["traceback"],
2870 not options["noninteractive"], options["traceback"],
2871 parseconfig(options["config"]))
2871 parseconfig(options["config"]))
2872
2872
2873 path = u.expandpath(options["repository"]) or ""
2873 path = u.expandpath(options["repository"]) or ""
2874 repo = path and hg.repository(u, path=path) or None
2874 repo = path and hg.repository(u, path=path) or None
2875 if repo and not repo.local():
2875 if repo and not repo.local():
2876 raise util.Abort(_("repository '%s' is not local") % path)
2876 raise util.Abort(_("repository '%s' is not local") % path)
2877
2877
2878 if options['help']:
2878 if options['help']:
2879 return help_(u, cmd, options['version'])
2879 return help_(u, cmd, options['version'])
2880 elif options['version']:
2880 elif options['version']:
2881 return version_(u)
2881 return version_(u)
2882 elif not cmd:
2882 elif not cmd:
2883 return help_(u, 'shortlist')
2883 return help_(u, 'shortlist')
2884
2884
2885 if cmd not in norepo.split():
2885 if cmd not in norepo.split():
2886 try:
2886 try:
2887 if not repo:
2887 if not repo:
2888 repo = hg.repository(u, path=path)
2888 repo = hg.repository(u, path=path)
2889 u = repo.ui
2889 u = repo.ui
2890 for name in external.itervalues():
2890 for name in external.itervalues():
2891 mod = sys.modules[name]
2891 mod = sys.modules[name]
2892 if hasattr(mod, 'reposetup'):
2892 if hasattr(mod, 'reposetup'):
2893 mod.reposetup(u, repo)
2893 mod.reposetup(u, repo)
2894 hg.repo_setup_hooks.append(mod.reposetup)
2894 hg.repo_setup_hooks.append(mod.reposetup)
2895 except hg.RepoError:
2895 except hg.RepoError:
2896 if cmd not in optionalrepo.split():
2896 if cmd not in optionalrepo.split():
2897 raise
2897 raise
2898 d = lambda: func(u, repo, *args, **cmdoptions)
2898 d = lambda: func(u, repo, *args, **cmdoptions)
2899 else:
2899 else:
2900 d = lambda: func(u, *args, **cmdoptions)
2900 d = lambda: func(u, *args, **cmdoptions)
2901
2901
2902 try:
2902 try:
2903 if options['profile']:
2903 if options['profile']:
2904 import hotshot, hotshot.stats
2904 import hotshot, hotshot.stats
2905 prof = hotshot.Profile("hg.prof")
2905 prof = hotshot.Profile("hg.prof")
2906 try:
2906 try:
2907 try:
2907 try:
2908 return prof.runcall(d)
2908 return prof.runcall(d)
2909 except:
2909 except:
2910 try:
2910 try:
2911 u.warn(_('exception raised - generating '
2911 u.warn(_('exception raised - generating '
2912 'profile anyway\n'))
2912 'profile anyway\n'))
2913 except:
2913 except:
2914 pass
2914 pass
2915 raise
2915 raise
2916 finally:
2916 finally:
2917 prof.close()
2917 prof.close()
2918 stats = hotshot.stats.load("hg.prof")
2918 stats = hotshot.stats.load("hg.prof")
2919 stats.strip_dirs()
2919 stats.strip_dirs()
2920 stats.sort_stats('time', 'calls')
2920 stats.sort_stats('time', 'calls')
2921 stats.print_stats(40)
2921 stats.print_stats(40)
2922 elif options['lsprof']:
2922 elif options['lsprof']:
2923 try:
2923 try:
2924 from mercurial import lsprof
2924 from mercurial import lsprof
2925 except ImportError:
2925 except ImportError:
2926 raise util.Abort(_(
2926 raise util.Abort(_(
2927 'lsprof not available - install from '
2927 'lsprof not available - install from '
2928 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
2928 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
2929 p = lsprof.Profiler()
2929 p = lsprof.Profiler()
2930 p.enable(subcalls=True)
2930 p.enable(subcalls=True)
2931 try:
2931 try:
2932 return d()
2932 return d()
2933 finally:
2933 finally:
2934 p.disable()
2934 p.disable()
2935 stats = lsprof.Stats(p.getstats())
2935 stats = lsprof.Stats(p.getstats())
2936 stats.sort()
2936 stats.sort()
2937 stats.pprint(top=10, file=sys.stderr, climit=5)
2937 stats.pprint(top=10, file=sys.stderr, climit=5)
2938 else:
2938 else:
2939 return d()
2939 return d()
2940 finally:
2940 finally:
2941 u.flush()
2941 u.flush()
2942 except:
2942 except:
2943 # enter the debugger when we hit an exception
2943 # enter the debugger when we hit an exception
2944 if options['debugger']:
2944 if options['debugger']:
2945 pdb.post_mortem(sys.exc_info()[2])
2945 pdb.post_mortem(sys.exc_info()[2])
2946 u.print_exc()
2946 u.print_exc()
2947 raise
2947 raise
2948 except ParseError, inst:
2948 except ParseError, inst:
2949 if inst.args[0]:
2949 if inst.args[0]:
2950 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2950 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2951 help_(u, inst.args[0])
2951 help_(u, inst.args[0])
2952 else:
2952 else:
2953 u.warn(_("hg: %s\n") % inst.args[1])
2953 u.warn(_("hg: %s\n") % inst.args[1])
2954 help_(u, 'shortlist')
2954 help_(u, 'shortlist')
2955 except AmbiguousCommand, inst:
2955 except AmbiguousCommand, inst:
2956 u.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
2956 u.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
2957 (inst.args[0], " ".join(inst.args[1])))
2957 (inst.args[0], " ".join(inst.args[1])))
2958 except UnknownCommand, inst:
2958 except UnknownCommand, inst:
2959 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2959 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2960 help_(u, 'shortlist')
2960 help_(u, 'shortlist')
2961 except hg.RepoError, inst:
2961 except hg.RepoError, inst:
2962 u.warn(_("abort: %s!\n") % inst)
2962 u.warn(_("abort: %s!\n") % inst)
2963 except lock.LockHeld, inst:
2963 except lock.LockHeld, inst:
2964 if inst.errno == errno.ETIMEDOUT:
2964 if inst.errno == errno.ETIMEDOUT:
2965 reason = _('timed out waiting for lock held by %s') % inst.locker
2965 reason = _('timed out waiting for lock held by %s') % inst.locker
2966 else:
2966 else:
2967 reason = _('lock held by %s') % inst.locker
2967 reason = _('lock held by %s') % inst.locker
2968 u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
2968 u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
2969 except lock.LockUnavailable, inst:
2969 except lock.LockUnavailable, inst:
2970 u.warn(_("abort: could not lock %s: %s\n") %
2970 u.warn(_("abort: could not lock %s: %s\n") %
2971 (inst.desc or inst.filename, inst.strerror))
2971 (inst.desc or inst.filename, inst.strerror))
2972 except revlog.RevlogError, inst:
2972 except revlog.RevlogError, inst:
2973 u.warn(_("abort: %s!\n") % inst)
2973 u.warn(_("abort: %s!\n") % inst)
2974 except util.SignalInterrupt:
2974 except util.SignalInterrupt:
2975 u.warn(_("killed!\n"))
2975 u.warn(_("killed!\n"))
2976 except KeyboardInterrupt:
2976 except KeyboardInterrupt:
2977 try:
2977 try:
2978 u.warn(_("interrupted!\n"))
2978 u.warn(_("interrupted!\n"))
2979 except IOError, inst:
2979 except IOError, inst:
2980 if inst.errno == errno.EPIPE:
2980 if inst.errno == errno.EPIPE:
2981 if u.debugflag:
2981 if u.debugflag:
2982 u.warn(_("\nbroken pipe\n"))
2982 u.warn(_("\nbroken pipe\n"))
2983 else:
2983 else:
2984 raise
2984 raise
2985 except IOError, inst:
2985 except IOError, inst:
2986 if hasattr(inst, "code"):
2986 if hasattr(inst, "code"):
2987 u.warn(_("abort: %s\n") % inst)
2987 u.warn(_("abort: %s\n") % inst)
2988 elif hasattr(inst, "reason"):
2988 elif hasattr(inst, "reason"):
2989 u.warn(_("abort: error: %s\n") % inst.reason[1])
2989 u.warn(_("abort: error: %s\n") % inst.reason[1])
2990 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2990 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2991 if u.debugflag:
2991 if u.debugflag:
2992 u.warn(_("broken pipe\n"))
2992 u.warn(_("broken pipe\n"))
2993 elif getattr(inst, "strerror", None):
2993 elif getattr(inst, "strerror", None):
2994 if getattr(inst, "filename", None):
2994 if getattr(inst, "filename", None):
2995 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2995 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2996 else:
2996 else:
2997 u.warn(_("abort: %s\n") % inst.strerror)
2997 u.warn(_("abort: %s\n") % inst.strerror)
2998 else:
2998 else:
2999 raise
2999 raise
3000 except OSError, inst:
3000 except OSError, inst:
3001 if getattr(inst, "filename", None):
3001 if getattr(inst, "filename", None):
3002 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
3002 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
3003 else:
3003 else:
3004 u.warn(_("abort: %s\n") % inst.strerror)
3004 u.warn(_("abort: %s\n") % inst.strerror)
3005 except util.UnexpectedOutput, inst:
3005 except util.UnexpectedOutput, inst:
3006 u.warn(_("abort: %s") % inst[0])
3006 u.warn(_("abort: %s") % inst[0])
3007 if not isinstance(inst[1], basestring):
3007 if not isinstance(inst[1], basestring):
3008 u.warn(" %r\n" % (inst[1],))
3008 u.warn(" %r\n" % (inst[1],))
3009 elif not inst[1]:
3009 elif not inst[1]:
3010 u.warn(_(" empty string\n"))
3010 u.warn(_(" empty string\n"))
3011 else:
3011 else:
3012 u.warn("\n%r%s\n" %
3012 u.warn("\n%r%s\n" %
3013 (inst[1][:400], len(inst[1]) > 400 and '...' or ''))
3013 (inst[1][:400], len(inst[1]) > 400 and '...' or ''))
3014 except util.Abort, inst:
3014 except util.Abort, inst:
3015 u.warn(_("abort: %s\n") % inst)
3015 u.warn(_("abort: %s\n") % inst)
3016 except TypeError, inst:
3016 except TypeError, inst:
3017 # was this an argument error?
3017 # was this an argument error?
3018 tb = traceback.extract_tb(sys.exc_info()[2])
3018 tb = traceback.extract_tb(sys.exc_info()[2])
3019 if len(tb) > 2: # no
3019 if len(tb) > 2: # no
3020 raise
3020 raise
3021 u.debug(inst, "\n")
3021 u.debug(inst, "\n")
3022 u.warn(_("%s: invalid arguments\n") % cmd)
3022 u.warn(_("%s: invalid arguments\n") % cmd)
3023 help_(u, cmd)
3023 help_(u, cmd)
3024 except SystemExit, inst:
3024 except SystemExit, inst:
3025 # Commands shouldn't sys.exit directly, but give a return code.
3025 # Commands shouldn't sys.exit directly, but give a return code.
3026 # Just in case catch this and and pass exit code to caller.
3026 # Just in case catch this and and pass exit code to caller.
3027 return inst.code
3027 return inst.code
3028 except:
3028 except:
3029 u.warn(_("** unknown exception encountered, details follow\n"))
3029 u.warn(_("** unknown exception encountered, details follow\n"))
3030 u.warn(_("** report bug details to "
3030 u.warn(_("** report bug details to "
3031 "http://www.selenic.com/mercurial/bts\n"))
3031 "http://www.selenic.com/mercurial/bts\n"))
3032 u.warn(_("** or mercurial@selenic.com\n"))
3032 u.warn(_("** or mercurial@selenic.com\n"))
3033 u.warn(_("** Mercurial Distributed SCM (version %s)\n")
3033 u.warn(_("** Mercurial Distributed SCM (version %s)\n")
3034 % version.get_version())
3034 % version.get_version())
3035 raise
3035 raise
3036
3036
3037 return -1
3037 return -1
General Comments 0
You need to be logged in to leave comments. Login now