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