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