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