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