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