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