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