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