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