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