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