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