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