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