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