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