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