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