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