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