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