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