##// END OF EJS Templates
traceback: point to BugTracker on the wiki
Matt Mackall -
r12831:4d657b52 stable
parent child Browse files
Show More
@@ -1,4492 +1,4492
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 of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, extensions, copies, error
12 import hg, util, revlog, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 opts.get('subrepos'), prefix="")
51 opts.get('subrepos'), prefix="")
52 return rejected and 1 or 0
52 return rejected and 1 or 0
53
53
54 def addremove(ui, repo, *pats, **opts):
54 def addremove(ui, repo, *pats, **opts):
55 """add all new files, delete all missing files
55 """add all new files, delete all missing files
56
56
57 Add all new files and remove all missing files from the
57 Add all new files and remove all missing files from the
58 repository.
58 repository.
59
59
60 New files are ignored if they match any of the patterns in
60 New files are ignored if they match any of the patterns in
61 .hgignore. As with add, these changes take effect at the next
61 .hgignore. As with add, these changes take effect at the next
62 commit.
62 commit.
63
63
64 Use the -s/--similarity option to detect renamed files. With a
64 Use the -s/--similarity option to detect renamed files. With a
65 parameter greater than 0, this compares every removed file with
65 parameter greater than 0, this compares every removed file with
66 every added file and records those similar enough as renames. This
66 every added file and records those similar enough as renames. This
67 option takes a percentage between 0 (disabled) and 100 (files must
67 option takes a percentage between 0 (disabled) and 100 (files must
68 be identical) as its parameter. Detecting renamed files this way
68 be identical) as its parameter. Detecting renamed files this way
69 can be expensive. After using this option, :hg:`status -C` can be
69 can be expensive. After using this option, :hg:`status -C` can be
70 used to check which files were identified as moved or renamed.
70 used to check which files were identified as moved or renamed.
71
71
72 Returns 0 if all files are successfully added.
72 Returns 0 if all files are successfully added.
73 """
73 """
74 try:
74 try:
75 sim = float(opts.get('similarity') or 100)
75 sim = float(opts.get('similarity') or 100)
76 except ValueError:
76 except ValueError:
77 raise util.Abort(_('similarity must be a number'))
77 raise util.Abort(_('similarity must be a number'))
78 if sim < 0 or sim > 100:
78 if sim < 0 or sim > 100:
79 raise util.Abort(_('similarity must be between 0 and 100'))
79 raise util.Abort(_('similarity must be between 0 and 100'))
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81
81
82 def annotate(ui, repo, *pats, **opts):
82 def annotate(ui, repo, *pats, **opts):
83 """show changeset information by line for each file
83 """show changeset information by line for each file
84
84
85 List changes in files, showing the revision id responsible for
85 List changes in files, showing the revision id responsible for
86 each line
86 each line
87
87
88 This command is useful for discovering when a change was made and
88 This command is useful for discovering when a change was made and
89 by whom.
89 by whom.
90
90
91 Without the -a/--text option, annotate will avoid processing files
91 Without the -a/--text option, annotate will avoid processing files
92 it detects as binary. With -a, annotate will annotate the file
92 it detects as binary. With -a, annotate will annotate the file
93 anyway, although the results will probably be neither useful
93 anyway, although the results will probably be neither useful
94 nor desirable.
94 nor desirable.
95
95
96 Returns 0 on success.
96 Returns 0 on success.
97 """
97 """
98 if opts.get('follow'):
98 if opts.get('follow'):
99 # --follow is deprecated and now just an alias for -f/--file
99 # --follow is deprecated and now just an alias for -f/--file
100 # to mimic the behavior of Mercurial before version 1.5
100 # to mimic the behavior of Mercurial before version 1.5
101 opts['file'] = 1
101 opts['file'] = 1
102
102
103 datefunc = ui.quiet and util.shortdate or util.datestr
103 datefunc = ui.quiet and util.shortdate or util.datestr
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105
105
106 if not pats:
106 if not pats:
107 raise util.Abort(_('at least one filename or pattern is required'))
107 raise util.Abort(_('at least one filename or pattern is required'))
108
108
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 ('number', lambda x: str(x[0].rev())),
110 ('number', lambda x: str(x[0].rev())),
111 ('changeset', lambda x: short(x[0].node())),
111 ('changeset', lambda x: short(x[0].node())),
112 ('date', getdate),
112 ('date', getdate),
113 ('file', lambda x: x[0].path()),
113 ('file', lambda x: x[0].path()),
114 ]
114 ]
115
115
116 if (not opts.get('user') and not opts.get('changeset')
116 if (not opts.get('user') and not opts.get('changeset')
117 and not opts.get('date') and not opts.get('file')):
117 and not opts.get('date') and not opts.get('file')):
118 opts['number'] = 1
118 opts['number'] = 1
119
119
120 linenumber = opts.get('line_number') is not None
120 linenumber = opts.get('line_number') is not None
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123
123
124 funcmap = [func for op, func in opmap if opts.get(op)]
124 funcmap = [func for op, func in opmap if opts.get(op)]
125 if linenumber:
125 if linenumber:
126 lastfunc = funcmap[-1]
126 lastfunc = funcmap[-1]
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128
128
129 ctx = repo[opts.get('rev')]
129 ctx = repo[opts.get('rev')]
130 m = cmdutil.match(repo, pats, opts)
130 m = cmdutil.match(repo, pats, opts)
131 follow = not opts.get('no_follow')
131 follow = not opts.get('no_follow')
132 for abs in ctx.walk(m):
132 for abs in ctx.walk(m):
133 fctx = ctx[abs]
133 fctx = ctx[abs]
134 if not opts.get('text') and util.binary(fctx.data()):
134 if not opts.get('text') and util.binary(fctx.data()):
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 continue
136 continue
137
137
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 pieces = []
139 pieces = []
140
140
141 for f in funcmap:
141 for f in funcmap:
142 l = [f(n) for n, dummy in lines]
142 l = [f(n) for n, dummy in lines]
143 if l:
143 if l:
144 sized = [(x, encoding.colwidth(x)) for x in l]
144 sized = [(x, encoding.colwidth(x)) for x in l]
145 ml = max([w for x, w in sized])
145 ml = max([w for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147
147
148 if pieces:
148 if pieces:
149 for p, l in zip(zip(*pieces), lines):
149 for p, l in zip(zip(*pieces), lines):
150 ui.write("%s: %s" % (" ".join(p), l[1]))
150 ui.write("%s: %s" % (" ".join(p), l[1]))
151
151
152 def archive(ui, repo, dest, **opts):
152 def archive(ui, repo, dest, **opts):
153 '''create an unversioned archive of a repository revision
153 '''create an unversioned archive of a repository revision
154
154
155 By default, the revision used is the parent of the working
155 By default, the revision used is the parent of the working
156 directory; use -r/--rev to specify a different revision.
156 directory; use -r/--rev to specify a different revision.
157
157
158 The archive type is automatically detected based on file
158 The archive type is automatically detected based on file
159 extension (or override using -t/--type).
159 extension (or override using -t/--type).
160
160
161 Valid types are:
161 Valid types are:
162
162
163 :``files``: a directory full of files (default)
163 :``files``: a directory full of files (default)
164 :``tar``: tar archive, uncompressed
164 :``tar``: tar archive, uncompressed
165 :``tbz2``: tar archive, compressed using bzip2
165 :``tbz2``: tar archive, compressed using bzip2
166 :``tgz``: tar archive, compressed using gzip
166 :``tgz``: tar archive, compressed using gzip
167 :``uzip``: zip archive, uncompressed
167 :``uzip``: zip archive, uncompressed
168 :``zip``: zip archive, compressed using deflate
168 :``zip``: zip archive, compressed using deflate
169
169
170 The exact name of the destination archive or directory is given
170 The exact name of the destination archive or directory is given
171 using a format string; see :hg:`help export` for details.
171 using a format string; see :hg:`help export` for details.
172
172
173 Each member added to an archive file has a directory prefix
173 Each member added to an archive file has a directory prefix
174 prepended. Use -p/--prefix to specify a format string for the
174 prepended. Use -p/--prefix to specify a format string for the
175 prefix. The default is the basename of the archive, with suffixes
175 prefix. The default is the basename of the archive, with suffixes
176 removed.
176 removed.
177
177
178 Returns 0 on success.
178 Returns 0 on success.
179 '''
179 '''
180
180
181 ctx = repo[opts.get('rev')]
181 ctx = repo[opts.get('rev')]
182 if not ctx:
182 if not ctx:
183 raise util.Abort(_('no working directory: please specify a revision'))
183 raise util.Abort(_('no working directory: please specify a revision'))
184 node = ctx.node()
184 node = ctx.node()
185 dest = cmdutil.make_filename(repo, dest, node)
185 dest = cmdutil.make_filename(repo, dest, node)
186 if os.path.realpath(dest) == repo.root:
186 if os.path.realpath(dest) == repo.root:
187 raise util.Abort(_('repository root cannot be destination'))
187 raise util.Abort(_('repository root cannot be destination'))
188
188
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 prefix = opts.get('prefix')
190 prefix = opts.get('prefix')
191
191
192 if dest == '-':
192 if dest == '-':
193 if kind == 'files':
193 if kind == 'files':
194 raise util.Abort(_('cannot archive plain files to stdout'))
194 raise util.Abort(_('cannot archive plain files to stdout'))
195 dest = sys.stdout
195 dest = sys.stdout
196 if not prefix:
196 if not prefix:
197 prefix = os.path.basename(repo.root) + '-%h'
197 prefix = os.path.basename(repo.root) + '-%h'
198
198
199 prefix = cmdutil.make_filename(repo, prefix, node)
199 prefix = cmdutil.make_filename(repo, prefix, node)
200 matchfn = cmdutil.match(repo, [], opts)
200 matchfn = cmdutil.match(repo, [], opts)
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 matchfn, prefix, subrepos=opts.get('subrepos'))
202 matchfn, prefix, subrepos=opts.get('subrepos'))
203
203
204 def backout(ui, repo, node=None, rev=None, **opts):
204 def backout(ui, repo, node=None, rev=None, **opts):
205 '''reverse effect of earlier changeset
205 '''reverse effect of earlier changeset
206
206
207 The backout command merges the reverse effect of the reverted
207 The backout command merges the reverse effect of the reverted
208 changeset into the working directory.
208 changeset into the working directory.
209
209
210 With the --merge option, it first commits the reverted changes
210 With the --merge option, it first commits the reverted changes
211 as a new changeset. This new changeset is a child of the reverted
211 as a new changeset. This new changeset is a child of the reverted
212 changeset.
212 changeset.
213 The --merge option remembers the parent of the working directory
213 The --merge option remembers the parent of the working directory
214 before starting the backout, then merges the new head with that
214 before starting the backout, then merges the new head with that
215 changeset afterwards.
215 changeset afterwards.
216 This will result in an explicit merge in the history.
216 This will result in an explicit merge in the history.
217
217
218 If you backout a changeset other than the original parent of the
218 If you backout a changeset other than the original parent of the
219 working directory, the result of this merge is not committed,
219 working directory, the result of this merge is not committed,
220 as with a normal merge. Otherwise, no merge is needed and the
220 as with a normal merge. Otherwise, no merge is needed and the
221 commit is automatic.
221 commit is automatic.
222
222
223 Note that the default behavior (without --merge) has changed in
223 Note that the default behavior (without --merge) has changed in
224 version 1.7. To restore the previous default behavior, use
224 version 1.7. To restore the previous default behavior, use
225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
226 the ongoing merge.
226 the ongoing merge.
227
227
228 See :hg:`help dates` for a list of formats valid for -d/--date.
228 See :hg:`help dates` for a list of formats valid for -d/--date.
229
229
230 Returns 0 on success.
230 Returns 0 on success.
231 '''
231 '''
232 if rev and node:
232 if rev and node:
233 raise util.Abort(_("please specify just one revision"))
233 raise util.Abort(_("please specify just one revision"))
234
234
235 if not rev:
235 if not rev:
236 rev = node
236 rev = node
237
237
238 if not rev:
238 if not rev:
239 raise util.Abort(_("please specify a revision to backout"))
239 raise util.Abort(_("please specify a revision to backout"))
240
240
241 date = opts.get('date')
241 date = opts.get('date')
242 if date:
242 if date:
243 opts['date'] = util.parsedate(date)
243 opts['date'] = util.parsedate(date)
244
244
245 cmdutil.bail_if_changed(repo)
245 cmdutil.bail_if_changed(repo)
246 node = repo.lookup(rev)
246 node = repo.lookup(rev)
247
247
248 op1, op2 = repo.dirstate.parents()
248 op1, op2 = repo.dirstate.parents()
249 a = repo.changelog.ancestor(op1, node)
249 a = repo.changelog.ancestor(op1, node)
250 if a != node:
250 if a != node:
251 raise util.Abort(_('cannot backout change on a different branch'))
251 raise util.Abort(_('cannot backout change on a different branch'))
252
252
253 p1, p2 = repo.changelog.parents(node)
253 p1, p2 = repo.changelog.parents(node)
254 if p1 == nullid:
254 if p1 == nullid:
255 raise util.Abort(_('cannot backout a change with no parents'))
255 raise util.Abort(_('cannot backout a change with no parents'))
256 if p2 != nullid:
256 if p2 != nullid:
257 if not opts.get('parent'):
257 if not opts.get('parent'):
258 raise util.Abort(_('cannot backout a merge changeset without '
258 raise util.Abort(_('cannot backout a merge changeset without '
259 '--parent'))
259 '--parent'))
260 p = repo.lookup(opts['parent'])
260 p = repo.lookup(opts['parent'])
261 if p not in (p1, p2):
261 if p not in (p1, p2):
262 raise util.Abort(_('%s is not a parent of %s') %
262 raise util.Abort(_('%s is not a parent of %s') %
263 (short(p), short(node)))
263 (short(p), short(node)))
264 parent = p
264 parent = p
265 else:
265 else:
266 if opts.get('parent'):
266 if opts.get('parent'):
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
268 parent = p1
268 parent = p1
269
269
270 # the backout should appear on the same branch
270 # the backout should appear on the same branch
271 branch = repo.dirstate.branch()
271 branch = repo.dirstate.branch()
272 hg.clean(repo, node, show_stats=False)
272 hg.clean(repo, node, show_stats=False)
273 repo.dirstate.setbranch(branch)
273 repo.dirstate.setbranch(branch)
274 revert_opts = opts.copy()
274 revert_opts = opts.copy()
275 revert_opts['date'] = None
275 revert_opts['date'] = None
276 revert_opts['all'] = True
276 revert_opts['all'] = True
277 revert_opts['rev'] = hex(parent)
277 revert_opts['rev'] = hex(parent)
278 revert_opts['no_backup'] = None
278 revert_opts['no_backup'] = None
279 revert(ui, repo, **revert_opts)
279 revert(ui, repo, **revert_opts)
280 if not opts.get('merge') and op1 != node:
280 if not opts.get('merge') and op1 != node:
281 try:
281 try:
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
283 return hg.update(repo, op1)
283 return hg.update(repo, op1)
284 finally:
284 finally:
285 ui.setconfig('ui', 'forcemerge', '')
285 ui.setconfig('ui', 'forcemerge', '')
286
286
287 commit_opts = opts.copy()
287 commit_opts = opts.copy()
288 commit_opts['addremove'] = False
288 commit_opts['addremove'] = False
289 if not commit_opts['message'] and not commit_opts['logfile']:
289 if not commit_opts['message'] and not commit_opts['logfile']:
290 # we don't translate commit messages
290 # we don't translate commit messages
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
292 commit_opts['force_editor'] = True
292 commit_opts['force_editor'] = True
293 commit(ui, repo, **commit_opts)
293 commit(ui, repo, **commit_opts)
294 def nice(node):
294 def nice(node):
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
296 ui.status(_('changeset %s backs out changeset %s\n') %
296 ui.status(_('changeset %s backs out changeset %s\n') %
297 (nice(repo.changelog.tip()), nice(node)))
297 (nice(repo.changelog.tip()), nice(node)))
298 if opts.get('merge') and op1 != node:
298 if opts.get('merge') and op1 != node:
299 hg.clean(repo, op1, show_stats=False)
299 hg.clean(repo, op1, show_stats=False)
300 ui.status(_('merging with changeset %s\n')
300 ui.status(_('merging with changeset %s\n')
301 % nice(repo.changelog.tip()))
301 % nice(repo.changelog.tip()))
302 try:
302 try:
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
304 return hg.merge(repo, hex(repo.changelog.tip()))
304 return hg.merge(repo, hex(repo.changelog.tip()))
305 finally:
305 finally:
306 ui.setconfig('ui', 'forcemerge', '')
306 ui.setconfig('ui', 'forcemerge', '')
307 return 0
307 return 0
308
308
309 def bisect(ui, repo, rev=None, extra=None, command=None,
309 def bisect(ui, repo, rev=None, extra=None, command=None,
310 reset=None, good=None, bad=None, skip=None, noupdate=None):
310 reset=None, good=None, bad=None, skip=None, noupdate=None):
311 """subdivision search of changesets
311 """subdivision search of changesets
312
312
313 This command helps to find changesets which introduce problems. To
313 This command helps to find changesets which introduce problems. To
314 use, mark the earliest changeset you know exhibits the problem as
314 use, mark the earliest changeset you know exhibits the problem as
315 bad, then mark the latest changeset which is free from the problem
315 bad, then mark the latest changeset which is free from the problem
316 as good. Bisect will update your working directory to a revision
316 as good. Bisect will update your working directory to a revision
317 for testing (unless the -U/--noupdate option is specified). Once
317 for testing (unless the -U/--noupdate option is specified). Once
318 you have performed tests, mark the working directory as good or
318 you have performed tests, mark the working directory as good or
319 bad, and bisect will either update to another candidate changeset
319 bad, and bisect will either update to another candidate changeset
320 or announce that it has found the bad revision.
320 or announce that it has found the bad revision.
321
321
322 As a shortcut, you can also use the revision argument to mark a
322 As a shortcut, you can also use the revision argument to mark a
323 revision as good or bad without checking it out first.
323 revision as good or bad without checking it out first.
324
324
325 If you supply a command, it will be used for automatic bisection.
325 If you supply a command, it will be used for automatic bisection.
326 Its exit status will be used to mark revisions as good or bad:
326 Its exit status will be used to mark revisions as good or bad:
327 status 0 means good, 125 means to skip the revision, 127
327 status 0 means good, 125 means to skip the revision, 127
328 (command not found) will abort the bisection, and any other
328 (command not found) will abort the bisection, and any other
329 non-zero exit status means the revision is bad.
329 non-zero exit status means the revision is bad.
330
330
331 Returns 0 on success.
331 Returns 0 on success.
332 """
332 """
333 def print_result(nodes, good):
333 def print_result(nodes, good):
334 displayer = cmdutil.show_changeset(ui, repo, {})
334 displayer = cmdutil.show_changeset(ui, repo, {})
335 if len(nodes) == 1:
335 if len(nodes) == 1:
336 # narrowed it down to a single revision
336 # narrowed it down to a single revision
337 if good:
337 if good:
338 ui.write(_("The first good revision is:\n"))
338 ui.write(_("The first good revision is:\n"))
339 else:
339 else:
340 ui.write(_("The first bad revision is:\n"))
340 ui.write(_("The first bad revision is:\n"))
341 displayer.show(repo[nodes[0]])
341 displayer.show(repo[nodes[0]])
342 parents = repo[nodes[0]].parents()
342 parents = repo[nodes[0]].parents()
343 if len(parents) > 1:
343 if len(parents) > 1:
344 side = good and state['bad'] or state['good']
344 side = good and state['bad'] or state['good']
345 num = len(set(i.node() for i in parents) & set(side))
345 num = len(set(i.node() for i in parents) & set(side))
346 if num == 1:
346 if num == 1:
347 common = parents[0].ancestor(parents[1])
347 common = parents[0].ancestor(parents[1])
348 ui.write(_('Not all ancestors of this changeset have been'
348 ui.write(_('Not all ancestors of this changeset have been'
349 ' checked.\nTo check the other ancestors, start'
349 ' checked.\nTo check the other ancestors, start'
350 ' from the common ancestor, %s.\n' % common))
350 ' from the common ancestor, %s.\n' % common))
351 else:
351 else:
352 # multiple possible revisions
352 # multiple possible revisions
353 if good:
353 if good:
354 ui.write(_("Due to skipped revisions, the first "
354 ui.write(_("Due to skipped revisions, the first "
355 "good revision could be any of:\n"))
355 "good revision could be any of:\n"))
356 else:
356 else:
357 ui.write(_("Due to skipped revisions, the first "
357 ui.write(_("Due to skipped revisions, the first "
358 "bad revision could be any of:\n"))
358 "bad revision could be any of:\n"))
359 for n in nodes:
359 for n in nodes:
360 displayer.show(repo[n])
360 displayer.show(repo[n])
361 displayer.close()
361 displayer.close()
362
362
363 def check_state(state, interactive=True):
363 def check_state(state, interactive=True):
364 if not state['good'] or not state['bad']:
364 if not state['good'] or not state['bad']:
365 if (good or bad or skip or reset) and interactive:
365 if (good or bad or skip or reset) and interactive:
366 return
366 return
367 if not state['good']:
367 if not state['good']:
368 raise util.Abort(_('cannot bisect (no known good revisions)'))
368 raise util.Abort(_('cannot bisect (no known good revisions)'))
369 else:
369 else:
370 raise util.Abort(_('cannot bisect (no known bad revisions)'))
370 raise util.Abort(_('cannot bisect (no known bad revisions)'))
371 return True
371 return True
372
372
373 # backward compatibility
373 # backward compatibility
374 if rev in "good bad reset init".split():
374 if rev in "good bad reset init".split():
375 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
375 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
376 cmd, rev, extra = rev, extra, None
376 cmd, rev, extra = rev, extra, None
377 if cmd == "good":
377 if cmd == "good":
378 good = True
378 good = True
379 elif cmd == "bad":
379 elif cmd == "bad":
380 bad = True
380 bad = True
381 else:
381 else:
382 reset = True
382 reset = True
383 elif extra or good + bad + skip + reset + bool(command) > 1:
383 elif extra or good + bad + skip + reset + bool(command) > 1:
384 raise util.Abort(_('incompatible arguments'))
384 raise util.Abort(_('incompatible arguments'))
385
385
386 if reset:
386 if reset:
387 p = repo.join("bisect.state")
387 p = repo.join("bisect.state")
388 if os.path.exists(p):
388 if os.path.exists(p):
389 os.unlink(p)
389 os.unlink(p)
390 return
390 return
391
391
392 state = hbisect.load_state(repo)
392 state = hbisect.load_state(repo)
393
393
394 if command:
394 if command:
395 changesets = 1
395 changesets = 1
396 try:
396 try:
397 while changesets:
397 while changesets:
398 # update state
398 # update state
399 status = util.system(command)
399 status = util.system(command)
400 if status == 125:
400 if status == 125:
401 transition = "skip"
401 transition = "skip"
402 elif status == 0:
402 elif status == 0:
403 transition = "good"
403 transition = "good"
404 # status < 0 means process was killed
404 # status < 0 means process was killed
405 elif status == 127:
405 elif status == 127:
406 raise util.Abort(_("failed to execute %s") % command)
406 raise util.Abort(_("failed to execute %s") % command)
407 elif status < 0:
407 elif status < 0:
408 raise util.Abort(_("%s killed") % command)
408 raise util.Abort(_("%s killed") % command)
409 else:
409 else:
410 transition = "bad"
410 transition = "bad"
411 ctx = repo[rev or '.']
411 ctx = repo[rev or '.']
412 state[transition].append(ctx.node())
412 state[transition].append(ctx.node())
413 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
413 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
414 check_state(state, interactive=False)
414 check_state(state, interactive=False)
415 # bisect
415 # bisect
416 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
416 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
417 # update to next check
417 # update to next check
418 cmdutil.bail_if_changed(repo)
418 cmdutil.bail_if_changed(repo)
419 hg.clean(repo, nodes[0], show_stats=False)
419 hg.clean(repo, nodes[0], show_stats=False)
420 finally:
420 finally:
421 hbisect.save_state(repo, state)
421 hbisect.save_state(repo, state)
422 print_result(nodes, good)
422 print_result(nodes, good)
423 return
423 return
424
424
425 # update state
425 # update state
426
426
427 if rev:
427 if rev:
428 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
428 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
429 else:
429 else:
430 nodes = [repo.lookup('.')]
430 nodes = [repo.lookup('.')]
431
431
432 if good or bad or skip:
432 if good or bad or skip:
433 if good:
433 if good:
434 state['good'] += nodes
434 state['good'] += nodes
435 elif bad:
435 elif bad:
436 state['bad'] += nodes
436 state['bad'] += nodes
437 elif skip:
437 elif skip:
438 state['skip'] += nodes
438 state['skip'] += nodes
439 hbisect.save_state(repo, state)
439 hbisect.save_state(repo, state)
440
440
441 if not check_state(state):
441 if not check_state(state):
442 return
442 return
443
443
444 # actually bisect
444 # actually bisect
445 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
445 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
446 if changesets == 0:
446 if changesets == 0:
447 print_result(nodes, good)
447 print_result(nodes, good)
448 else:
448 else:
449 assert len(nodes) == 1 # only a single node can be tested next
449 assert len(nodes) == 1 # only a single node can be tested next
450 node = nodes[0]
450 node = nodes[0]
451 # compute the approximate number of remaining tests
451 # compute the approximate number of remaining tests
452 tests, size = 0, 2
452 tests, size = 0, 2
453 while size <= changesets:
453 while size <= changesets:
454 tests, size = tests + 1, size * 2
454 tests, size = tests + 1, size * 2
455 rev = repo.changelog.rev(node)
455 rev = repo.changelog.rev(node)
456 ui.write(_("Testing changeset %d:%s "
456 ui.write(_("Testing changeset %d:%s "
457 "(%d changesets remaining, ~%d tests)\n")
457 "(%d changesets remaining, ~%d tests)\n")
458 % (rev, short(node), changesets, tests))
458 % (rev, short(node), changesets, tests))
459 if not noupdate:
459 if not noupdate:
460 cmdutil.bail_if_changed(repo)
460 cmdutil.bail_if_changed(repo)
461 return hg.clean(repo, node)
461 return hg.clean(repo, node)
462
462
463 def branch(ui, repo, label=None, **opts):
463 def branch(ui, repo, label=None, **opts):
464 """set or show the current branch name
464 """set or show the current branch name
465
465
466 With no argument, show the current branch name. With one argument,
466 With no argument, show the current branch name. With one argument,
467 set the working directory branch name (the branch will not exist
467 set the working directory branch name (the branch will not exist
468 in the repository until the next commit). Standard practice
468 in the repository until the next commit). Standard practice
469 recommends that primary development take place on the 'default'
469 recommends that primary development take place on the 'default'
470 branch.
470 branch.
471
471
472 Unless -f/--force is specified, branch will not let you set a
472 Unless -f/--force is specified, branch will not let you set a
473 branch name that already exists, even if it's inactive.
473 branch name that already exists, even if it's inactive.
474
474
475 Use -C/--clean to reset the working directory branch to that of
475 Use -C/--clean to reset the working directory branch to that of
476 the parent of the working directory, negating a previous branch
476 the parent of the working directory, negating a previous branch
477 change.
477 change.
478
478
479 Use the command :hg:`update` to switch to an existing branch. Use
479 Use the command :hg:`update` to switch to an existing branch. Use
480 :hg:`commit --close-branch` to mark this branch as closed.
480 :hg:`commit --close-branch` to mark this branch as closed.
481
481
482 Returns 0 on success.
482 Returns 0 on success.
483 """
483 """
484
484
485 if opts.get('clean'):
485 if opts.get('clean'):
486 label = repo[None].parents()[0].branch()
486 label = repo[None].parents()[0].branch()
487 repo.dirstate.setbranch(label)
487 repo.dirstate.setbranch(label)
488 ui.status(_('reset working directory to branch %s\n') % label)
488 ui.status(_('reset working directory to branch %s\n') % label)
489 elif label:
489 elif label:
490 utflabel = encoding.fromlocal(label)
490 utflabel = encoding.fromlocal(label)
491 if not opts.get('force') and utflabel in repo.branchtags():
491 if not opts.get('force') and utflabel in repo.branchtags():
492 if label not in [p.branch() for p in repo.parents()]:
492 if label not in [p.branch() for p in repo.parents()]:
493 raise util.Abort(_('a branch of the same name already exists'
493 raise util.Abort(_('a branch of the same name already exists'
494 " (use 'hg update' to switch to it)"))
494 " (use 'hg update' to switch to it)"))
495 repo.dirstate.setbranch(utflabel)
495 repo.dirstate.setbranch(utflabel)
496 ui.status(_('marked working directory as branch %s\n') % label)
496 ui.status(_('marked working directory as branch %s\n') % label)
497 else:
497 else:
498 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
498 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
499
499
500 def branches(ui, repo, active=False, closed=False):
500 def branches(ui, repo, active=False, closed=False):
501 """list repository named branches
501 """list repository named branches
502
502
503 List the repository's named branches, indicating which ones are
503 List the repository's named branches, indicating which ones are
504 inactive. If -c/--closed is specified, also list branches which have
504 inactive. If -c/--closed is specified, also list branches which have
505 been marked closed (see :hg:`commit --close-branch`).
505 been marked closed (see :hg:`commit --close-branch`).
506
506
507 If -a/--active is specified, only show active branches. A branch
507 If -a/--active is specified, only show active branches. A branch
508 is considered active if it contains repository heads.
508 is considered active if it contains repository heads.
509
509
510 Use the command :hg:`update` to switch to an existing branch.
510 Use the command :hg:`update` to switch to an existing branch.
511
511
512 Returns 0.
512 Returns 0.
513 """
513 """
514
514
515 hexfunc = ui.debugflag and hex or short
515 hexfunc = ui.debugflag and hex or short
516 activebranches = [repo[n].branch() for n in repo.heads()]
516 activebranches = [repo[n].branch() for n in repo.heads()]
517 def testactive(tag, node):
517 def testactive(tag, node):
518 realhead = tag in activebranches
518 realhead = tag in activebranches
519 open = node in repo.branchheads(tag, closed=False)
519 open = node in repo.branchheads(tag, closed=False)
520 return realhead and open
520 return realhead and open
521 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
521 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
522 for tag, node in repo.branchtags().items()],
522 for tag, node in repo.branchtags().items()],
523 reverse=True)
523 reverse=True)
524
524
525 for isactive, node, tag in branches:
525 for isactive, node, tag in branches:
526 if (not active) or isactive:
526 if (not active) or isactive:
527 encodedtag = encoding.tolocal(tag)
527 encodedtag = encoding.tolocal(tag)
528 if ui.quiet:
528 if ui.quiet:
529 ui.write("%s\n" % encodedtag)
529 ui.write("%s\n" % encodedtag)
530 else:
530 else:
531 hn = repo.lookup(node)
531 hn = repo.lookup(node)
532 if isactive:
532 if isactive:
533 label = 'branches.active'
533 label = 'branches.active'
534 notice = ''
534 notice = ''
535 elif hn not in repo.branchheads(tag, closed=False):
535 elif hn not in repo.branchheads(tag, closed=False):
536 if not closed:
536 if not closed:
537 continue
537 continue
538 label = 'branches.closed'
538 label = 'branches.closed'
539 notice = _(' (closed)')
539 notice = _(' (closed)')
540 else:
540 else:
541 label = 'branches.inactive'
541 label = 'branches.inactive'
542 notice = _(' (inactive)')
542 notice = _(' (inactive)')
543 if tag == repo.dirstate.branch():
543 if tag == repo.dirstate.branch():
544 label = 'branches.current'
544 label = 'branches.current'
545 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
545 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
546 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
546 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
547 encodedtag = ui.label(encodedtag, label)
547 encodedtag = ui.label(encodedtag, label)
548 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
548 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
549
549
550 def bundle(ui, repo, fname, dest=None, **opts):
550 def bundle(ui, repo, fname, dest=None, **opts):
551 """create a changegroup file
551 """create a changegroup file
552
552
553 Generate a compressed changegroup file collecting changesets not
553 Generate a compressed changegroup file collecting changesets not
554 known to be in another repository.
554 known to be in another repository.
555
555
556 If you omit the destination repository, then hg assumes the
556 If you omit the destination repository, then hg assumes the
557 destination will have all the nodes you specify with --base
557 destination will have all the nodes you specify with --base
558 parameters. To create a bundle containing all changesets, use
558 parameters. To create a bundle containing all changesets, use
559 -a/--all (or --base null).
559 -a/--all (or --base null).
560
560
561 You can change compression method with the -t/--type option.
561 You can change compression method with the -t/--type option.
562 The available compression methods are: none, bzip2, and
562 The available compression methods are: none, bzip2, and
563 gzip (by default, bundles are compressed using bzip2).
563 gzip (by default, bundles are compressed using bzip2).
564
564
565 The bundle file can then be transferred using conventional means
565 The bundle file can then be transferred using conventional means
566 and applied to another repository with the unbundle or pull
566 and applied to another repository with the unbundle or pull
567 command. This is useful when direct push and pull are not
567 command. This is useful when direct push and pull are not
568 available or when exporting an entire repository is undesirable.
568 available or when exporting an entire repository is undesirable.
569
569
570 Applying bundles preserves all changeset contents including
570 Applying bundles preserves all changeset contents including
571 permissions, copy/rename information, and revision history.
571 permissions, copy/rename information, and revision history.
572
572
573 Returns 0 on success, 1 if no changes found.
573 Returns 0 on success, 1 if no changes found.
574 """
574 """
575 revs = opts.get('rev') or None
575 revs = opts.get('rev') or None
576 if opts.get('all'):
576 if opts.get('all'):
577 base = ['null']
577 base = ['null']
578 else:
578 else:
579 base = opts.get('base')
579 base = opts.get('base')
580 if base:
580 if base:
581 if dest:
581 if dest:
582 raise util.Abort(_("--base is incompatible with specifying "
582 raise util.Abort(_("--base is incompatible with specifying "
583 "a destination"))
583 "a destination"))
584 base = [repo.lookup(rev) for rev in base]
584 base = [repo.lookup(rev) for rev in base]
585 # create the right base
585 # create the right base
586 # XXX: nodesbetween / changegroup* should be "fixed" instead
586 # XXX: nodesbetween / changegroup* should be "fixed" instead
587 o = []
587 o = []
588 has = set((nullid,))
588 has = set((nullid,))
589 for n in base:
589 for n in base:
590 has.update(repo.changelog.reachable(n))
590 has.update(repo.changelog.reachable(n))
591 if revs:
591 if revs:
592 revs = [repo.lookup(rev) for rev in revs]
592 revs = [repo.lookup(rev) for rev in revs]
593 visit = revs[:]
593 visit = revs[:]
594 has.difference_update(visit)
594 has.difference_update(visit)
595 else:
595 else:
596 visit = repo.changelog.heads()
596 visit = repo.changelog.heads()
597 seen = {}
597 seen = {}
598 while visit:
598 while visit:
599 n = visit.pop(0)
599 n = visit.pop(0)
600 parents = [p for p in repo.changelog.parents(n) if p not in has]
600 parents = [p for p in repo.changelog.parents(n) if p not in has]
601 if len(parents) == 0:
601 if len(parents) == 0:
602 if n not in has:
602 if n not in has:
603 o.append(n)
603 o.append(n)
604 else:
604 else:
605 for p in parents:
605 for p in parents:
606 if p not in seen:
606 if p not in seen:
607 seen[p] = 1
607 seen[p] = 1
608 visit.append(p)
608 visit.append(p)
609 else:
609 else:
610 dest = ui.expandpath(dest or 'default-push', dest or 'default')
610 dest = ui.expandpath(dest or 'default-push', dest or 'default')
611 dest, branches = hg.parseurl(dest, opts.get('branch'))
611 dest, branches = hg.parseurl(dest, opts.get('branch'))
612 other = hg.repository(hg.remoteui(repo, opts), dest)
612 other = hg.repository(hg.remoteui(repo, opts), dest)
613 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
613 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
614 if revs:
614 if revs:
615 revs = [repo.lookup(rev) for rev in revs]
615 revs = [repo.lookup(rev) for rev in revs]
616 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
616 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
617
617
618 if not o:
618 if not o:
619 ui.status(_("no changes found\n"))
619 ui.status(_("no changes found\n"))
620 return 1
620 return 1
621
621
622 if revs:
622 if revs:
623 cg = repo.changegroupsubset(o, revs, 'bundle')
623 cg = repo.changegroupsubset(o, revs, 'bundle')
624 else:
624 else:
625 cg = repo.changegroup(o, 'bundle')
625 cg = repo.changegroup(o, 'bundle')
626
626
627 bundletype = opts.get('type', 'bzip2').lower()
627 bundletype = opts.get('type', 'bzip2').lower()
628 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
628 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
629 bundletype = btypes.get(bundletype)
629 bundletype = btypes.get(bundletype)
630 if bundletype not in changegroup.bundletypes:
630 if bundletype not in changegroup.bundletypes:
631 raise util.Abort(_('unknown bundle type specified with --type'))
631 raise util.Abort(_('unknown bundle type specified with --type'))
632
632
633 changegroup.writebundle(cg, fname, bundletype)
633 changegroup.writebundle(cg, fname, bundletype)
634
634
635 def cat(ui, repo, file1, *pats, **opts):
635 def cat(ui, repo, file1, *pats, **opts):
636 """output the current or given revision of files
636 """output the current or given revision of files
637
637
638 Print the specified files as they were at the given revision. If
638 Print the specified files as they were at the given revision. If
639 no revision is given, the parent of the working directory is used,
639 no revision is given, the parent of the working directory is used,
640 or tip if no revision is checked out.
640 or tip if no revision is checked out.
641
641
642 Output may be to a file, in which case the name of the file is
642 Output may be to a file, in which case the name of the file is
643 given using a format string. The formatting rules are the same as
643 given using a format string. The formatting rules are the same as
644 for the export command, with the following additions:
644 for the export command, with the following additions:
645
645
646 :``%s``: basename of file being printed
646 :``%s``: basename of file being printed
647 :``%d``: dirname of file being printed, or '.' if in repository root
647 :``%d``: dirname of file being printed, or '.' if in repository root
648 :``%p``: root-relative path name of file being printed
648 :``%p``: root-relative path name of file being printed
649
649
650 Returns 0 on success.
650 Returns 0 on success.
651 """
651 """
652 ctx = cmdutil.revsingle(repo, opts.get('rev'))
652 ctx = cmdutil.revsingle(repo, opts.get('rev'))
653 err = 1
653 err = 1
654 m = cmdutil.match(repo, (file1,) + pats, opts)
654 m = cmdutil.match(repo, (file1,) + pats, opts)
655 for abs in ctx.walk(m):
655 for abs in ctx.walk(m):
656 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
656 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
657 data = ctx[abs].data()
657 data = ctx[abs].data()
658 if opts.get('decode'):
658 if opts.get('decode'):
659 data = repo.wwritedata(abs, data)
659 data = repo.wwritedata(abs, data)
660 fp.write(data)
660 fp.write(data)
661 err = 0
661 err = 0
662 return err
662 return err
663
663
664 def clone(ui, source, dest=None, **opts):
664 def clone(ui, source, dest=None, **opts):
665 """make a copy of an existing repository
665 """make a copy of an existing repository
666
666
667 Create a copy of an existing repository in a new directory.
667 Create a copy of an existing repository in a new directory.
668
668
669 If no destination directory name is specified, it defaults to the
669 If no destination directory name is specified, it defaults to the
670 basename of the source.
670 basename of the source.
671
671
672 The location of the source is added to the new repository's
672 The location of the source is added to the new repository's
673 .hg/hgrc file, as the default to be used for future pulls.
673 .hg/hgrc file, as the default to be used for future pulls.
674
674
675 See :hg:`help urls` for valid source format details.
675 See :hg:`help urls` for valid source format details.
676
676
677 It is possible to specify an ``ssh://`` URL as the destination, but no
677 It is possible to specify an ``ssh://`` URL as the destination, but no
678 .hg/hgrc and working directory will be created on the remote side.
678 .hg/hgrc and working directory will be created on the remote side.
679 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
679 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
680
680
681 A set of changesets (tags, or branch names) to pull may be specified
681 A set of changesets (tags, or branch names) to pull may be specified
682 by listing each changeset (tag, or branch name) with -r/--rev.
682 by listing each changeset (tag, or branch name) with -r/--rev.
683 If -r/--rev is used, the cloned repository will contain only a subset
683 If -r/--rev is used, the cloned repository will contain only a subset
684 of the changesets of the source repository. Only the set of changesets
684 of the changesets of the source repository. Only the set of changesets
685 defined by all -r/--rev options (including all their ancestors)
685 defined by all -r/--rev options (including all their ancestors)
686 will be pulled into the destination repository.
686 will be pulled into the destination repository.
687 No subsequent changesets (including subsequent tags) will be present
687 No subsequent changesets (including subsequent tags) will be present
688 in the destination.
688 in the destination.
689
689
690 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
690 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
691 local source repositories.
691 local source repositories.
692
692
693 For efficiency, hardlinks are used for cloning whenever the source
693 For efficiency, hardlinks are used for cloning whenever the source
694 and destination are on the same filesystem (note this applies only
694 and destination are on the same filesystem (note this applies only
695 to the repository data, not to the working directory). Some
695 to the repository data, not to the working directory). Some
696 filesystems, such as AFS, implement hardlinking incorrectly, but
696 filesystems, such as AFS, implement hardlinking incorrectly, but
697 do not report errors. In these cases, use the --pull option to
697 do not report errors. In these cases, use the --pull option to
698 avoid hardlinking.
698 avoid hardlinking.
699
699
700 In some cases, you can clone repositories and the working directory
700 In some cases, you can clone repositories and the working directory
701 using full hardlinks with ::
701 using full hardlinks with ::
702
702
703 $ cp -al REPO REPOCLONE
703 $ cp -al REPO REPOCLONE
704
704
705 This is the fastest way to clone, but it is not always safe. The
705 This is the fastest way to clone, but it is not always safe. The
706 operation is not atomic (making sure REPO is not modified during
706 operation is not atomic (making sure REPO is not modified during
707 the operation is up to you) and you have to make sure your editor
707 the operation is up to you) and you have to make sure your editor
708 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
708 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
709 this is not compatible with certain extensions that place their
709 this is not compatible with certain extensions that place their
710 metadata under the .hg directory, such as mq.
710 metadata under the .hg directory, such as mq.
711
711
712 Mercurial will update the working directory to the first applicable
712 Mercurial will update the working directory to the first applicable
713 revision from this list:
713 revision from this list:
714
714
715 a) null if -U or the source repository has no changesets
715 a) null if -U or the source repository has no changesets
716 b) if -u . and the source repository is local, the first parent of
716 b) if -u . and the source repository is local, the first parent of
717 the source repository's working directory
717 the source repository's working directory
718 c) the changeset specified with -u (if a branch name, this means the
718 c) the changeset specified with -u (if a branch name, this means the
719 latest head of that branch)
719 latest head of that branch)
720 d) the changeset specified with -r
720 d) the changeset specified with -r
721 e) the tipmost head specified with -b
721 e) the tipmost head specified with -b
722 f) the tipmost head specified with the url#branch source syntax
722 f) the tipmost head specified with the url#branch source syntax
723 g) the tipmost head of the default branch
723 g) the tipmost head of the default branch
724 h) tip
724 h) tip
725
725
726 Returns 0 on success.
726 Returns 0 on success.
727 """
727 """
728 if opts.get('noupdate') and opts.get('updaterev'):
728 if opts.get('noupdate') and opts.get('updaterev'):
729 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
729 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
730
730
731 r = hg.clone(hg.remoteui(ui, opts), source, dest,
731 r = hg.clone(hg.remoteui(ui, opts), source, dest,
732 pull=opts.get('pull'),
732 pull=opts.get('pull'),
733 stream=opts.get('uncompressed'),
733 stream=opts.get('uncompressed'),
734 rev=opts.get('rev'),
734 rev=opts.get('rev'),
735 update=opts.get('updaterev') or not opts.get('noupdate'),
735 update=opts.get('updaterev') or not opts.get('noupdate'),
736 branch=opts.get('branch'))
736 branch=opts.get('branch'))
737
737
738 return r is None
738 return r is None
739
739
740 def commit(ui, repo, *pats, **opts):
740 def commit(ui, repo, *pats, **opts):
741 """commit the specified files or all outstanding changes
741 """commit the specified files or all outstanding changes
742
742
743 Commit changes to the given files into the repository. Unlike a
743 Commit changes to the given files into the repository. Unlike a
744 centralized RCS, this operation is a local operation. See
744 centralized RCS, this operation is a local operation. See
745 :hg:`push` for a way to actively distribute your changes.
745 :hg:`push` for a way to actively distribute your changes.
746
746
747 If a list of files is omitted, all changes reported by :hg:`status`
747 If a list of files is omitted, all changes reported by :hg:`status`
748 will be committed.
748 will be committed.
749
749
750 If you are committing the result of a merge, do not provide any
750 If you are committing the result of a merge, do not provide any
751 filenames or -I/-X filters.
751 filenames or -I/-X filters.
752
752
753 If no commit message is specified, Mercurial starts your
753 If no commit message is specified, Mercurial starts your
754 configured editor where you can enter a message. In case your
754 configured editor where you can enter a message. In case your
755 commit fails, you will find a backup of your message in
755 commit fails, you will find a backup of your message in
756 ``.hg/last-message.txt``.
756 ``.hg/last-message.txt``.
757
757
758 See :hg:`help dates` for a list of formats valid for -d/--date.
758 See :hg:`help dates` for a list of formats valid for -d/--date.
759
759
760 Returns 0 on success, 1 if nothing changed.
760 Returns 0 on success, 1 if nothing changed.
761 """
761 """
762 extra = {}
762 extra = {}
763 if opts.get('close_branch'):
763 if opts.get('close_branch'):
764 if repo['.'].node() not in repo.branchheads():
764 if repo['.'].node() not in repo.branchheads():
765 # The topo heads set is included in the branch heads set of the
765 # The topo heads set is included in the branch heads set of the
766 # current branch, so it's sufficient to test branchheads
766 # current branch, so it's sufficient to test branchheads
767 raise util.Abort(_('can only close branch heads'))
767 raise util.Abort(_('can only close branch heads'))
768 extra['close'] = 1
768 extra['close'] = 1
769 e = cmdutil.commiteditor
769 e = cmdutil.commiteditor
770 if opts.get('force_editor'):
770 if opts.get('force_editor'):
771 e = cmdutil.commitforceeditor
771 e = cmdutil.commitforceeditor
772
772
773 def commitfunc(ui, repo, message, match, opts):
773 def commitfunc(ui, repo, message, match, opts):
774 return repo.commit(message, opts.get('user'), opts.get('date'), match,
774 return repo.commit(message, opts.get('user'), opts.get('date'), match,
775 editor=e, extra=extra)
775 editor=e, extra=extra)
776
776
777 branch = repo[None].branch()
777 branch = repo[None].branch()
778 bheads = repo.branchheads(branch)
778 bheads = repo.branchheads(branch)
779
779
780 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
780 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
781 if not node:
781 if not node:
782 ui.status(_("nothing changed\n"))
782 ui.status(_("nothing changed\n"))
783 return 1
783 return 1
784
784
785 ctx = repo[node]
785 ctx = repo[node]
786 parents = ctx.parents()
786 parents = ctx.parents()
787
787
788 if bheads and not [x for x in parents
788 if bheads and not [x for x in parents
789 if x.node() in bheads and x.branch() == branch]:
789 if x.node() in bheads and x.branch() == branch]:
790 ui.status(_('created new head\n'))
790 ui.status(_('created new head\n'))
791 # The message is not printed for initial roots. For the other
791 # The message is not printed for initial roots. For the other
792 # changesets, it is printed in the following situations:
792 # changesets, it is printed in the following situations:
793 #
793 #
794 # Par column: for the 2 parents with ...
794 # Par column: for the 2 parents with ...
795 # N: null or no parent
795 # N: null or no parent
796 # B: parent is on another named branch
796 # B: parent is on another named branch
797 # C: parent is a regular non head changeset
797 # C: parent is a regular non head changeset
798 # H: parent was a branch head of the current branch
798 # H: parent was a branch head of the current branch
799 # Msg column: whether we print "created new head" message
799 # Msg column: whether we print "created new head" message
800 # In the following, it is assumed that there already exists some
800 # In the following, it is assumed that there already exists some
801 # initial branch heads of the current branch, otherwise nothing is
801 # initial branch heads of the current branch, otherwise nothing is
802 # printed anyway.
802 # printed anyway.
803 #
803 #
804 # Par Msg Comment
804 # Par Msg Comment
805 # NN y additional topo root
805 # NN y additional topo root
806 #
806 #
807 # BN y additional branch root
807 # BN y additional branch root
808 # CN y additional topo head
808 # CN y additional topo head
809 # HN n usual case
809 # HN n usual case
810 #
810 #
811 # BB y weird additional branch root
811 # BB y weird additional branch root
812 # CB y branch merge
812 # CB y branch merge
813 # HB n merge with named branch
813 # HB n merge with named branch
814 #
814 #
815 # CC y additional head from merge
815 # CC y additional head from merge
816 # CH n merge with a head
816 # CH n merge with a head
817 #
817 #
818 # HH n head merge: head count decreases
818 # HH n head merge: head count decreases
819
819
820 if not opts.get('close_branch'):
820 if not opts.get('close_branch'):
821 for r in parents:
821 for r in parents:
822 if r.extra().get('close') and r.branch() == branch:
822 if r.extra().get('close') and r.branch() == branch:
823 ui.status(_('reopening closed branch head %d\n') % r)
823 ui.status(_('reopening closed branch head %d\n') % r)
824
824
825 if ui.debugflag:
825 if ui.debugflag:
826 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
826 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
827 elif ui.verbose:
827 elif ui.verbose:
828 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
828 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
829
829
830 def copy(ui, repo, *pats, **opts):
830 def copy(ui, repo, *pats, **opts):
831 """mark files as copied for the next commit
831 """mark files as copied for the next commit
832
832
833 Mark dest as having copies of source files. If dest is a
833 Mark dest as having copies of source files. If dest is a
834 directory, copies are put in that directory. If dest is a file,
834 directory, copies are put in that directory. If dest is a file,
835 the source must be a single file.
835 the source must be a single file.
836
836
837 By default, this command copies the contents of files as they
837 By default, this command copies the contents of files as they
838 exist in the working directory. If invoked with -A/--after, the
838 exist in the working directory. If invoked with -A/--after, the
839 operation is recorded, but no copying is performed.
839 operation is recorded, but no copying is performed.
840
840
841 This command takes effect with the next commit. To undo a copy
841 This command takes effect with the next commit. To undo a copy
842 before that, see :hg:`revert`.
842 before that, see :hg:`revert`.
843
843
844 Returns 0 on success, 1 if errors are encountered.
844 Returns 0 on success, 1 if errors are encountered.
845 """
845 """
846 wlock = repo.wlock(False)
846 wlock = repo.wlock(False)
847 try:
847 try:
848 return cmdutil.copy(ui, repo, pats, opts)
848 return cmdutil.copy(ui, repo, pats, opts)
849 finally:
849 finally:
850 wlock.release()
850 wlock.release()
851
851
852 def debugancestor(ui, repo, *args):
852 def debugancestor(ui, repo, *args):
853 """find the ancestor revision of two revisions in a given index"""
853 """find the ancestor revision of two revisions in a given index"""
854 if len(args) == 3:
854 if len(args) == 3:
855 index, rev1, rev2 = args
855 index, rev1, rev2 = args
856 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
856 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
857 lookup = r.lookup
857 lookup = r.lookup
858 elif len(args) == 2:
858 elif len(args) == 2:
859 if not repo:
859 if not repo:
860 raise util.Abort(_("there is no Mercurial repository here "
860 raise util.Abort(_("there is no Mercurial repository here "
861 "(.hg not found)"))
861 "(.hg not found)"))
862 rev1, rev2 = args
862 rev1, rev2 = args
863 r = repo.changelog
863 r = repo.changelog
864 lookup = repo.lookup
864 lookup = repo.lookup
865 else:
865 else:
866 raise util.Abort(_('either two or three arguments required'))
866 raise util.Abort(_('either two or three arguments required'))
867 a = r.ancestor(lookup(rev1), lookup(rev2))
867 a = r.ancestor(lookup(rev1), lookup(rev2))
868 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
868 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
869
869
870 def debugbuilddag(ui, repo, text,
870 def debugbuilddag(ui, repo, text,
871 mergeable_file=False,
871 mergeable_file=False,
872 appended_file=False,
872 appended_file=False,
873 overwritten_file=False,
873 overwritten_file=False,
874 new_file=False):
874 new_file=False):
875 """builds a repo with a given dag from scratch in the current empty repo
875 """builds a repo with a given dag from scratch in the current empty repo
876
876
877 Elements:
877 Elements:
878
878
879 - "+n" is a linear run of n nodes based on the current default parent
879 - "+n" is a linear run of n nodes based on the current default parent
880 - "." is a single node based on the current default parent
880 - "." is a single node based on the current default parent
881 - "$" resets the default parent to null (implied at the start);
881 - "$" resets the default parent to null (implied at the start);
882 otherwise the default parent is always the last node created
882 otherwise the default parent is always the last node created
883 - "<p" sets the default parent to the backref p
883 - "<p" sets the default parent to the backref p
884 - "*p" is a fork at parent p, which is a backref
884 - "*p" is a fork at parent p, which is a backref
885 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
885 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
886 - "/p2" is a merge of the preceding node and p2
886 - "/p2" is a merge of the preceding node and p2
887 - ":tag" defines a local tag for the preceding node
887 - ":tag" defines a local tag for the preceding node
888 - "@branch" sets the named branch for subsequent nodes
888 - "@branch" sets the named branch for subsequent nodes
889 - "!command" runs the command using your shell
889 - "!command" runs the command using your shell
890 - "!!my command\\n" is like "!", but to the end of the line
890 - "!!my command\\n" is like "!", but to the end of the line
891 - "#...\\n" is a comment up to the end of the line
891 - "#...\\n" is a comment up to the end of the line
892
892
893 Whitespace between the above elements is ignored.
893 Whitespace between the above elements is ignored.
894
894
895 A backref is either
895 A backref is either
896
896
897 - a number n, which references the node curr-n, where curr is the current
897 - a number n, which references the node curr-n, where curr is the current
898 node, or
898 node, or
899 - the name of a local tag you placed earlier using ":tag", or
899 - the name of a local tag you placed earlier using ":tag", or
900 - empty to denote the default parent.
900 - empty to denote the default parent.
901
901
902 All string valued-elements are either strictly alphanumeric, or must
902 All string valued-elements are either strictly alphanumeric, or must
903 be enclosed in double quotes ("..."), with "\\" as escape character.
903 be enclosed in double quotes ("..."), with "\\" as escape character.
904
904
905 Note that the --overwritten-file and --appended-file options imply the
905 Note that the --overwritten-file and --appended-file options imply the
906 use of "HGMERGE=internal:local" during DAG buildup.
906 use of "HGMERGE=internal:local" during DAG buildup.
907 """
907 """
908
908
909 if not (mergeable_file or appended_file or overwritten_file or new_file):
909 if not (mergeable_file or appended_file or overwritten_file or new_file):
910 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
910 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
911
911
912 if len(repo.changelog) > 0:
912 if len(repo.changelog) > 0:
913 raise util.Abort(_('repository is not empty'))
913 raise util.Abort(_('repository is not empty'))
914
914
915 if overwritten_file or appended_file:
915 if overwritten_file or appended_file:
916 # we don't want to fail in merges during buildup
916 # we don't want to fail in merges during buildup
917 os.environ['HGMERGE'] = 'internal:local'
917 os.environ['HGMERGE'] = 'internal:local'
918
918
919 def writefile(fname, text, fmode="wb"):
919 def writefile(fname, text, fmode="wb"):
920 f = open(fname, fmode)
920 f = open(fname, fmode)
921 try:
921 try:
922 f.write(text)
922 f.write(text)
923 finally:
923 finally:
924 f.close()
924 f.close()
925
925
926 if mergeable_file:
926 if mergeable_file:
927 linesperrev = 2
927 linesperrev = 2
928 # determine number of revs in DAG
928 # determine number of revs in DAG
929 n = 0
929 n = 0
930 for type, data in dagparser.parsedag(text):
930 for type, data in dagparser.parsedag(text):
931 if type == 'n':
931 if type == 'n':
932 n += 1
932 n += 1
933 # make a file with k lines per rev
933 # make a file with k lines per rev
934 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
934 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
935 + "\n")
935 + "\n")
936
936
937 at = -1
937 at = -1
938 atbranch = 'default'
938 atbranch = 'default'
939 for type, data in dagparser.parsedag(text):
939 for type, data in dagparser.parsedag(text):
940 if type == 'n':
940 if type == 'n':
941 ui.status('node %s\n' % str(data))
941 ui.status('node %s\n' % str(data))
942 id, ps = data
942 id, ps = data
943 p1 = ps[0]
943 p1 = ps[0]
944 if p1 != at:
944 if p1 != at:
945 update(ui, repo, node=str(p1), clean=True)
945 update(ui, repo, node=str(p1), clean=True)
946 at = p1
946 at = p1
947 if repo.dirstate.branch() != atbranch:
947 if repo.dirstate.branch() != atbranch:
948 branch(ui, repo, atbranch, force=True)
948 branch(ui, repo, atbranch, force=True)
949 if len(ps) > 1:
949 if len(ps) > 1:
950 p2 = ps[1]
950 p2 = ps[1]
951 merge(ui, repo, node=p2)
951 merge(ui, repo, node=p2)
952
952
953 if mergeable_file:
953 if mergeable_file:
954 f = open("mf", "rb+")
954 f = open("mf", "rb+")
955 try:
955 try:
956 lines = f.read().split("\n")
956 lines = f.read().split("\n")
957 lines[id * linesperrev] += " r%i" % id
957 lines[id * linesperrev] += " r%i" % id
958 f.seek(0)
958 f.seek(0)
959 f.write("\n".join(lines))
959 f.write("\n".join(lines))
960 finally:
960 finally:
961 f.close()
961 f.close()
962
962
963 if appended_file:
963 if appended_file:
964 writefile("af", "r%i\n" % id, "ab")
964 writefile("af", "r%i\n" % id, "ab")
965
965
966 if overwritten_file:
966 if overwritten_file:
967 writefile("of", "r%i\n" % id)
967 writefile("of", "r%i\n" % id)
968
968
969 if new_file:
969 if new_file:
970 writefile("nf%i" % id, "r%i\n" % id)
970 writefile("nf%i" % id, "r%i\n" % id)
971
971
972 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
972 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
973 at = id
973 at = id
974 elif type == 'l':
974 elif type == 'l':
975 id, name = data
975 id, name = data
976 ui.status('tag %s\n' % name)
976 ui.status('tag %s\n' % name)
977 tag(ui, repo, name, local=True)
977 tag(ui, repo, name, local=True)
978 elif type == 'a':
978 elif type == 'a':
979 ui.status('branch %s\n' % data)
979 ui.status('branch %s\n' % data)
980 atbranch = data
980 atbranch = data
981 elif type in 'cC':
981 elif type in 'cC':
982 r = util.system(data, cwd=repo.root)
982 r = util.system(data, cwd=repo.root)
983 if r:
983 if r:
984 desc, r = util.explain_exit(r)
984 desc, r = util.explain_exit(r)
985 raise util.Abort(_('%s command %s') % (data, desc))
985 raise util.Abort(_('%s command %s') % (data, desc))
986
986
987 def debugcommands(ui, cmd='', *args):
987 def debugcommands(ui, cmd='', *args):
988 """list all available commands and options"""
988 """list all available commands and options"""
989 for cmd, vals in sorted(table.iteritems()):
989 for cmd, vals in sorted(table.iteritems()):
990 cmd = cmd.split('|')[0].strip('^')
990 cmd = cmd.split('|')[0].strip('^')
991 opts = ', '.join([i[1] for i in vals[1]])
991 opts = ', '.join([i[1] for i in vals[1]])
992 ui.write('%s: %s\n' % (cmd, opts))
992 ui.write('%s: %s\n' % (cmd, opts))
993
993
994 def debugcomplete(ui, cmd='', **opts):
994 def debugcomplete(ui, cmd='', **opts):
995 """returns the completion list associated with the given command"""
995 """returns the completion list associated with the given command"""
996
996
997 if opts.get('options'):
997 if opts.get('options'):
998 options = []
998 options = []
999 otables = [globalopts]
999 otables = [globalopts]
1000 if cmd:
1000 if cmd:
1001 aliases, entry = cmdutil.findcmd(cmd, table, False)
1001 aliases, entry = cmdutil.findcmd(cmd, table, False)
1002 otables.append(entry[1])
1002 otables.append(entry[1])
1003 for t in otables:
1003 for t in otables:
1004 for o in t:
1004 for o in t:
1005 if "(DEPRECATED)" in o[3]:
1005 if "(DEPRECATED)" in o[3]:
1006 continue
1006 continue
1007 if o[0]:
1007 if o[0]:
1008 options.append('-%s' % o[0])
1008 options.append('-%s' % o[0])
1009 options.append('--%s' % o[1])
1009 options.append('--%s' % o[1])
1010 ui.write("%s\n" % "\n".join(options))
1010 ui.write("%s\n" % "\n".join(options))
1011 return
1011 return
1012
1012
1013 cmdlist = cmdutil.findpossible(cmd, table)
1013 cmdlist = cmdutil.findpossible(cmd, table)
1014 if ui.verbose:
1014 if ui.verbose:
1015 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1015 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1016 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1016 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1017
1017
1018 def debugfsinfo(ui, path = "."):
1018 def debugfsinfo(ui, path = "."):
1019 """show information detected about current filesystem"""
1019 """show information detected about current filesystem"""
1020 open('.debugfsinfo', 'w').write('')
1020 open('.debugfsinfo', 'w').write('')
1021 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1021 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1022 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1022 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1023 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1023 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1024 and 'yes' or 'no'))
1024 and 'yes' or 'no'))
1025 os.unlink('.debugfsinfo')
1025 os.unlink('.debugfsinfo')
1026
1026
1027 def debugrebuildstate(ui, repo, rev="tip"):
1027 def debugrebuildstate(ui, repo, rev="tip"):
1028 """rebuild the dirstate as it would look like for the given revision"""
1028 """rebuild the dirstate as it would look like for the given revision"""
1029 ctx = repo[rev]
1029 ctx = repo[rev]
1030 wlock = repo.wlock()
1030 wlock = repo.wlock()
1031 try:
1031 try:
1032 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1032 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1033 finally:
1033 finally:
1034 wlock.release()
1034 wlock.release()
1035
1035
1036 def debugcheckstate(ui, repo):
1036 def debugcheckstate(ui, repo):
1037 """validate the correctness of the current dirstate"""
1037 """validate the correctness of the current dirstate"""
1038 parent1, parent2 = repo.dirstate.parents()
1038 parent1, parent2 = repo.dirstate.parents()
1039 m1 = repo[parent1].manifest()
1039 m1 = repo[parent1].manifest()
1040 m2 = repo[parent2].manifest()
1040 m2 = repo[parent2].manifest()
1041 errors = 0
1041 errors = 0
1042 for f in repo.dirstate:
1042 for f in repo.dirstate:
1043 state = repo.dirstate[f]
1043 state = repo.dirstate[f]
1044 if state in "nr" and f not in m1:
1044 if state in "nr" and f not in m1:
1045 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1045 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1046 errors += 1
1046 errors += 1
1047 if state in "a" and f in m1:
1047 if state in "a" and f in m1:
1048 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1048 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1049 errors += 1
1049 errors += 1
1050 if state in "m" and f not in m1 and f not in m2:
1050 if state in "m" and f not in m1 and f not in m2:
1051 ui.warn(_("%s in state %s, but not in either manifest\n") %
1051 ui.warn(_("%s in state %s, but not in either manifest\n") %
1052 (f, state))
1052 (f, state))
1053 errors += 1
1053 errors += 1
1054 for f in m1:
1054 for f in m1:
1055 state = repo.dirstate[f]
1055 state = repo.dirstate[f]
1056 if state not in "nrm":
1056 if state not in "nrm":
1057 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1057 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1058 errors += 1
1058 errors += 1
1059 if errors:
1059 if errors:
1060 error = _(".hg/dirstate inconsistent with current parent's manifest")
1060 error = _(".hg/dirstate inconsistent with current parent's manifest")
1061 raise util.Abort(error)
1061 raise util.Abort(error)
1062
1062
1063 def showconfig(ui, repo, *values, **opts):
1063 def showconfig(ui, repo, *values, **opts):
1064 """show combined config settings from all hgrc files
1064 """show combined config settings from all hgrc files
1065
1065
1066 With no arguments, print names and values of all config items.
1066 With no arguments, print names and values of all config items.
1067
1067
1068 With one argument of the form section.name, print just the value
1068 With one argument of the form section.name, print just the value
1069 of that config item.
1069 of that config item.
1070
1070
1071 With multiple arguments, print names and values of all config
1071 With multiple arguments, print names and values of all config
1072 items with matching section names.
1072 items with matching section names.
1073
1073
1074 With --debug, the source (filename and line number) is printed
1074 With --debug, the source (filename and line number) is printed
1075 for each config item.
1075 for each config item.
1076
1076
1077 Returns 0 on success.
1077 Returns 0 on success.
1078 """
1078 """
1079
1079
1080 for f in util.rcpath():
1080 for f in util.rcpath():
1081 ui.debug(_('read config from: %s\n') % f)
1081 ui.debug(_('read config from: %s\n') % f)
1082 untrusted = bool(opts.get('untrusted'))
1082 untrusted = bool(opts.get('untrusted'))
1083 if values:
1083 if values:
1084 sections = [v for v in values if '.' not in v]
1084 sections = [v for v in values if '.' not in v]
1085 items = [v for v in values if '.' in v]
1085 items = [v for v in values if '.' in v]
1086 if len(items) > 1 or items and sections:
1086 if len(items) > 1 or items and sections:
1087 raise util.Abort(_('only one config item permitted'))
1087 raise util.Abort(_('only one config item permitted'))
1088 for section, name, value in ui.walkconfig(untrusted=untrusted):
1088 for section, name, value in ui.walkconfig(untrusted=untrusted):
1089 sectname = section + '.' + name
1089 sectname = section + '.' + name
1090 if values:
1090 if values:
1091 for v in values:
1091 for v in values:
1092 if v == section:
1092 if v == section:
1093 ui.debug('%s: ' %
1093 ui.debug('%s: ' %
1094 ui.configsource(section, name, untrusted))
1094 ui.configsource(section, name, untrusted))
1095 ui.write('%s=%s\n' % (sectname, value))
1095 ui.write('%s=%s\n' % (sectname, value))
1096 elif v == sectname:
1096 elif v == sectname:
1097 ui.debug('%s: ' %
1097 ui.debug('%s: ' %
1098 ui.configsource(section, name, untrusted))
1098 ui.configsource(section, name, untrusted))
1099 ui.write(value, '\n')
1099 ui.write(value, '\n')
1100 else:
1100 else:
1101 ui.debug('%s: ' %
1101 ui.debug('%s: ' %
1102 ui.configsource(section, name, untrusted))
1102 ui.configsource(section, name, untrusted))
1103 ui.write('%s=%s\n' % (sectname, value))
1103 ui.write('%s=%s\n' % (sectname, value))
1104
1104
1105 def debugpushkey(ui, repopath, namespace, *keyinfo):
1105 def debugpushkey(ui, repopath, namespace, *keyinfo):
1106 '''access the pushkey key/value protocol
1106 '''access the pushkey key/value protocol
1107
1107
1108 With two args, list the keys in the given namespace.
1108 With two args, list the keys in the given namespace.
1109
1109
1110 With five args, set a key to new if it currently is set to old.
1110 With five args, set a key to new if it currently is set to old.
1111 Reports success or failure.
1111 Reports success or failure.
1112 '''
1112 '''
1113
1113
1114 target = hg.repository(ui, repopath)
1114 target = hg.repository(ui, repopath)
1115 if keyinfo:
1115 if keyinfo:
1116 key, old, new = keyinfo
1116 key, old, new = keyinfo
1117 r = target.pushkey(namespace, key, old, new)
1117 r = target.pushkey(namespace, key, old, new)
1118 ui.status(str(r) + '\n')
1118 ui.status(str(r) + '\n')
1119 return not(r)
1119 return not(r)
1120 else:
1120 else:
1121 for k, v in target.listkeys(namespace).iteritems():
1121 for k, v in target.listkeys(namespace).iteritems():
1122 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1122 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1123 v.encode('string-escape')))
1123 v.encode('string-escape')))
1124
1124
1125 def debugrevspec(ui, repo, expr):
1125 def debugrevspec(ui, repo, expr):
1126 '''parse and apply a revision specification'''
1126 '''parse and apply a revision specification'''
1127 if ui.verbose:
1127 if ui.verbose:
1128 tree = revset.parse(expr)
1128 tree = revset.parse(expr)
1129 ui.note(tree, "\n")
1129 ui.note(tree, "\n")
1130 func = revset.match(expr)
1130 func = revset.match(expr)
1131 for c in func(repo, range(len(repo))):
1131 for c in func(repo, range(len(repo))):
1132 ui.write("%s\n" % c)
1132 ui.write("%s\n" % c)
1133
1133
1134 def debugsetparents(ui, repo, rev1, rev2=None):
1134 def debugsetparents(ui, repo, rev1, rev2=None):
1135 """manually set the parents of the current working directory
1135 """manually set the parents of the current working directory
1136
1136
1137 This is useful for writing repository conversion tools, but should
1137 This is useful for writing repository conversion tools, but should
1138 be used with care.
1138 be used with care.
1139
1139
1140 Returns 0 on success.
1140 Returns 0 on success.
1141 """
1141 """
1142
1142
1143 if not rev2:
1143 if not rev2:
1144 rev2 = hex(nullid)
1144 rev2 = hex(nullid)
1145
1145
1146 wlock = repo.wlock()
1146 wlock = repo.wlock()
1147 try:
1147 try:
1148 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1148 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1149 finally:
1149 finally:
1150 wlock.release()
1150 wlock.release()
1151
1151
1152 def debugstate(ui, repo, nodates=None):
1152 def debugstate(ui, repo, nodates=None):
1153 """show the contents of the current dirstate"""
1153 """show the contents of the current dirstate"""
1154 timestr = ""
1154 timestr = ""
1155 showdate = not nodates
1155 showdate = not nodates
1156 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1156 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1157 if showdate:
1157 if showdate:
1158 if ent[3] == -1:
1158 if ent[3] == -1:
1159 # Pad or slice to locale representation
1159 # Pad or slice to locale representation
1160 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1160 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1161 time.localtime(0)))
1161 time.localtime(0)))
1162 timestr = 'unset'
1162 timestr = 'unset'
1163 timestr = (timestr[:locale_len] +
1163 timestr = (timestr[:locale_len] +
1164 ' ' * (locale_len - len(timestr)))
1164 ' ' * (locale_len - len(timestr)))
1165 else:
1165 else:
1166 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1166 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1167 time.localtime(ent[3]))
1167 time.localtime(ent[3]))
1168 if ent[1] & 020000:
1168 if ent[1] & 020000:
1169 mode = 'lnk'
1169 mode = 'lnk'
1170 else:
1170 else:
1171 mode = '%3o' % (ent[1] & 0777)
1171 mode = '%3o' % (ent[1] & 0777)
1172 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1172 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1173 for f in repo.dirstate.copies():
1173 for f in repo.dirstate.copies():
1174 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1174 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1175
1175
1176 def debugsub(ui, repo, rev=None):
1176 def debugsub(ui, repo, rev=None):
1177 if rev == '':
1177 if rev == '':
1178 rev = None
1178 rev = None
1179 for k, v in sorted(repo[rev].substate.items()):
1179 for k, v in sorted(repo[rev].substate.items()):
1180 ui.write('path %s\n' % k)
1180 ui.write('path %s\n' % k)
1181 ui.write(' source %s\n' % v[0])
1181 ui.write(' source %s\n' % v[0])
1182 ui.write(' revision %s\n' % v[1])
1182 ui.write(' revision %s\n' % v[1])
1183
1183
1184 def debugdag(ui, repo, file_=None, *revs, **opts):
1184 def debugdag(ui, repo, file_=None, *revs, **opts):
1185 """format the changelog or an index DAG as a concise textual description
1185 """format the changelog or an index DAG as a concise textual description
1186
1186
1187 If you pass a revlog index, the revlog's DAG is emitted. If you list
1187 If you pass a revlog index, the revlog's DAG is emitted. If you list
1188 revision numbers, they get labelled in the output as rN.
1188 revision numbers, they get labelled in the output as rN.
1189
1189
1190 Otherwise, the changelog DAG of the current repo is emitted.
1190 Otherwise, the changelog DAG of the current repo is emitted.
1191 """
1191 """
1192 spaces = opts.get('spaces')
1192 spaces = opts.get('spaces')
1193 dots = opts.get('dots')
1193 dots = opts.get('dots')
1194 if file_:
1194 if file_:
1195 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1195 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1196 revs = set((int(r) for r in revs))
1196 revs = set((int(r) for r in revs))
1197 def events():
1197 def events():
1198 for r in rlog:
1198 for r in rlog:
1199 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1199 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1200 if r in revs:
1200 if r in revs:
1201 yield 'l', (r, "r%i" % r)
1201 yield 'l', (r, "r%i" % r)
1202 elif repo:
1202 elif repo:
1203 cl = repo.changelog
1203 cl = repo.changelog
1204 tags = opts.get('tags')
1204 tags = opts.get('tags')
1205 branches = opts.get('branches')
1205 branches = opts.get('branches')
1206 if tags:
1206 if tags:
1207 labels = {}
1207 labels = {}
1208 for l, n in repo.tags().items():
1208 for l, n in repo.tags().items():
1209 labels.setdefault(cl.rev(n), []).append(l)
1209 labels.setdefault(cl.rev(n), []).append(l)
1210 def events():
1210 def events():
1211 b = "default"
1211 b = "default"
1212 for r in cl:
1212 for r in cl:
1213 if branches:
1213 if branches:
1214 newb = cl.read(cl.node(r))[5]['branch']
1214 newb = cl.read(cl.node(r))[5]['branch']
1215 if newb != b:
1215 if newb != b:
1216 yield 'a', newb
1216 yield 'a', newb
1217 b = newb
1217 b = newb
1218 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1218 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1219 if tags:
1219 if tags:
1220 ls = labels.get(r)
1220 ls = labels.get(r)
1221 if ls:
1221 if ls:
1222 for l in ls:
1222 for l in ls:
1223 yield 'l', (r, l)
1223 yield 'l', (r, l)
1224 else:
1224 else:
1225 raise util.Abort(_('need repo for changelog dag'))
1225 raise util.Abort(_('need repo for changelog dag'))
1226
1226
1227 for line in dagparser.dagtextlines(events(),
1227 for line in dagparser.dagtextlines(events(),
1228 addspaces=spaces,
1228 addspaces=spaces,
1229 wraplabels=True,
1229 wraplabels=True,
1230 wrapannotations=True,
1230 wrapannotations=True,
1231 wrapnonlinear=dots,
1231 wrapnonlinear=dots,
1232 usedots=dots,
1232 usedots=dots,
1233 maxlinewidth=70):
1233 maxlinewidth=70):
1234 ui.write(line)
1234 ui.write(line)
1235 ui.write("\n")
1235 ui.write("\n")
1236
1236
1237 def debugdata(ui, repo, file_, rev):
1237 def debugdata(ui, repo, file_, rev):
1238 """dump the contents of a data file revision"""
1238 """dump the contents of a data file revision"""
1239 r = None
1239 r = None
1240 if repo:
1240 if repo:
1241 filelog = repo.file(file_)
1241 filelog = repo.file(file_)
1242 if len(filelog):
1242 if len(filelog):
1243 r = filelog
1243 r = filelog
1244 if not r:
1244 if not r:
1245 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1245 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1246 try:
1246 try:
1247 ui.write(r.revision(r.lookup(rev)))
1247 ui.write(r.revision(r.lookup(rev)))
1248 except KeyError:
1248 except KeyError:
1249 raise util.Abort(_('invalid revision identifier %s') % rev)
1249 raise util.Abort(_('invalid revision identifier %s') % rev)
1250
1250
1251 def debugdate(ui, date, range=None, **opts):
1251 def debugdate(ui, date, range=None, **opts):
1252 """parse and display a date"""
1252 """parse and display a date"""
1253 if opts["extended"]:
1253 if opts["extended"]:
1254 d = util.parsedate(date, util.extendeddateformats)
1254 d = util.parsedate(date, util.extendeddateformats)
1255 else:
1255 else:
1256 d = util.parsedate(date)
1256 d = util.parsedate(date)
1257 ui.write("internal: %s %s\n" % d)
1257 ui.write("internal: %s %s\n" % d)
1258 ui.write("standard: %s\n" % util.datestr(d))
1258 ui.write("standard: %s\n" % util.datestr(d))
1259 if range:
1259 if range:
1260 m = util.matchdate(range)
1260 m = util.matchdate(range)
1261 ui.write("match: %s\n" % m(d[0]))
1261 ui.write("match: %s\n" % m(d[0]))
1262
1262
1263 def debugindex(ui, repo, file_):
1263 def debugindex(ui, repo, file_):
1264 """dump the contents of an index file"""
1264 """dump the contents of an index file"""
1265 r = None
1265 r = None
1266 if repo:
1266 if repo:
1267 filelog = repo.file(file_)
1267 filelog = repo.file(file_)
1268 if len(filelog):
1268 if len(filelog):
1269 r = filelog
1269 r = filelog
1270 if not r:
1270 if not r:
1271 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1271 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1272 ui.write(" rev offset length base linkrev"
1272 ui.write(" rev offset length base linkrev"
1273 " nodeid p1 p2\n")
1273 " nodeid p1 p2\n")
1274 for i in r:
1274 for i in r:
1275 node = r.node(i)
1275 node = r.node(i)
1276 try:
1276 try:
1277 pp = r.parents(node)
1277 pp = r.parents(node)
1278 except:
1278 except:
1279 pp = [nullid, nullid]
1279 pp = [nullid, nullid]
1280 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1280 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1281 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1281 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1282 short(node), short(pp[0]), short(pp[1])))
1282 short(node), short(pp[0]), short(pp[1])))
1283
1283
1284 def debugindexdot(ui, repo, file_):
1284 def debugindexdot(ui, repo, file_):
1285 """dump an index DAG as a graphviz dot file"""
1285 """dump an index DAG as a graphviz dot file"""
1286 r = None
1286 r = None
1287 if repo:
1287 if repo:
1288 filelog = repo.file(file_)
1288 filelog = repo.file(file_)
1289 if len(filelog):
1289 if len(filelog):
1290 r = filelog
1290 r = filelog
1291 if not r:
1291 if not r:
1292 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1292 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1293 ui.write("digraph G {\n")
1293 ui.write("digraph G {\n")
1294 for i in r:
1294 for i in r:
1295 node = r.node(i)
1295 node = r.node(i)
1296 pp = r.parents(node)
1296 pp = r.parents(node)
1297 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1297 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1298 if pp[1] != nullid:
1298 if pp[1] != nullid:
1299 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1299 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1300 ui.write("}\n")
1300 ui.write("}\n")
1301
1301
1302 def debuginstall(ui):
1302 def debuginstall(ui):
1303 '''test Mercurial installation
1303 '''test Mercurial installation
1304
1304
1305 Returns 0 on success.
1305 Returns 0 on success.
1306 '''
1306 '''
1307
1307
1308 def writetemp(contents):
1308 def writetemp(contents):
1309 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1309 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1310 f = os.fdopen(fd, "wb")
1310 f = os.fdopen(fd, "wb")
1311 f.write(contents)
1311 f.write(contents)
1312 f.close()
1312 f.close()
1313 return name
1313 return name
1314
1314
1315 problems = 0
1315 problems = 0
1316
1316
1317 # encoding
1317 # encoding
1318 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1318 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1319 try:
1319 try:
1320 encoding.fromlocal("test")
1320 encoding.fromlocal("test")
1321 except util.Abort, inst:
1321 except util.Abort, inst:
1322 ui.write(" %s\n" % inst)
1322 ui.write(" %s\n" % inst)
1323 ui.write(_(" (check that your locale is properly set)\n"))
1323 ui.write(_(" (check that your locale is properly set)\n"))
1324 problems += 1
1324 problems += 1
1325
1325
1326 # compiled modules
1326 # compiled modules
1327 ui.status(_("Checking installed modules (%s)...\n")
1327 ui.status(_("Checking installed modules (%s)...\n")
1328 % os.path.dirname(__file__))
1328 % os.path.dirname(__file__))
1329 try:
1329 try:
1330 import bdiff, mpatch, base85, osutil
1330 import bdiff, mpatch, base85, osutil
1331 except Exception, inst:
1331 except Exception, inst:
1332 ui.write(" %s\n" % inst)
1332 ui.write(" %s\n" % inst)
1333 ui.write(_(" One or more extensions could not be found"))
1333 ui.write(_(" One or more extensions could not be found"))
1334 ui.write(_(" (check that you compiled the extensions)\n"))
1334 ui.write(_(" (check that you compiled the extensions)\n"))
1335 problems += 1
1335 problems += 1
1336
1336
1337 # templates
1337 # templates
1338 ui.status(_("Checking templates...\n"))
1338 ui.status(_("Checking templates...\n"))
1339 try:
1339 try:
1340 import templater
1340 import templater
1341 templater.templater(templater.templatepath("map-cmdline.default"))
1341 templater.templater(templater.templatepath("map-cmdline.default"))
1342 except Exception, inst:
1342 except Exception, inst:
1343 ui.write(" %s\n" % inst)
1343 ui.write(" %s\n" % inst)
1344 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1344 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1345 problems += 1
1345 problems += 1
1346
1346
1347 # patch
1347 # patch
1348 ui.status(_("Checking patch...\n"))
1348 ui.status(_("Checking patch...\n"))
1349 patchproblems = 0
1349 patchproblems = 0
1350 a = "1\n2\n3\n4\n"
1350 a = "1\n2\n3\n4\n"
1351 b = "1\n2\n3\ninsert\n4\n"
1351 b = "1\n2\n3\ninsert\n4\n"
1352 fa = writetemp(a)
1352 fa = writetemp(a)
1353 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1353 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1354 os.path.basename(fa))
1354 os.path.basename(fa))
1355 fd = writetemp(d)
1355 fd = writetemp(d)
1356
1356
1357 files = {}
1357 files = {}
1358 try:
1358 try:
1359 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1359 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1360 except util.Abort, e:
1360 except util.Abort, e:
1361 ui.write(_(" patch call failed:\n"))
1361 ui.write(_(" patch call failed:\n"))
1362 ui.write(" " + str(e) + "\n")
1362 ui.write(" " + str(e) + "\n")
1363 patchproblems += 1
1363 patchproblems += 1
1364 else:
1364 else:
1365 if list(files) != [os.path.basename(fa)]:
1365 if list(files) != [os.path.basename(fa)]:
1366 ui.write(_(" unexpected patch output!\n"))
1366 ui.write(_(" unexpected patch output!\n"))
1367 patchproblems += 1
1367 patchproblems += 1
1368 a = open(fa).read()
1368 a = open(fa).read()
1369 if a != b:
1369 if a != b:
1370 ui.write(_(" patch test failed!\n"))
1370 ui.write(_(" patch test failed!\n"))
1371 patchproblems += 1
1371 patchproblems += 1
1372
1372
1373 if patchproblems:
1373 if patchproblems:
1374 if ui.config('ui', 'patch'):
1374 if ui.config('ui', 'patch'):
1375 ui.write(_(" (Current patch tool may be incompatible with patch,"
1375 ui.write(_(" (Current patch tool may be incompatible with patch,"
1376 " or misconfigured. Please check your configuration"
1376 " or misconfigured. Please check your configuration"
1377 " file)\n"))
1377 " file)\n"))
1378 else:
1378 else:
1379 ui.write(_(" Internal patcher failure, please report this error"
1379 ui.write(_(" Internal patcher failure, please report this error"
1380 " to http://mercurial.selenic.com/bts/\n"))
1380 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1381 problems += patchproblems
1381 problems += patchproblems
1382
1382
1383 os.unlink(fa)
1383 os.unlink(fa)
1384 os.unlink(fd)
1384 os.unlink(fd)
1385
1385
1386 # editor
1386 # editor
1387 ui.status(_("Checking commit editor...\n"))
1387 ui.status(_("Checking commit editor...\n"))
1388 editor = ui.geteditor()
1388 editor = ui.geteditor()
1389 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1389 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1390 if not cmdpath:
1390 if not cmdpath:
1391 if editor == 'vi':
1391 if editor == 'vi':
1392 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1392 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1393 ui.write(_(" (specify a commit editor in your configuration"
1393 ui.write(_(" (specify a commit editor in your configuration"
1394 " file)\n"))
1394 " file)\n"))
1395 else:
1395 else:
1396 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1396 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1397 ui.write(_(" (specify a commit editor in your configuration"
1397 ui.write(_(" (specify a commit editor in your configuration"
1398 " file)\n"))
1398 " file)\n"))
1399 problems += 1
1399 problems += 1
1400
1400
1401 # check username
1401 # check username
1402 ui.status(_("Checking username...\n"))
1402 ui.status(_("Checking username...\n"))
1403 try:
1403 try:
1404 ui.username()
1404 ui.username()
1405 except util.Abort, e:
1405 except util.Abort, e:
1406 ui.write(" %s\n" % e)
1406 ui.write(" %s\n" % e)
1407 ui.write(_(" (specify a username in your configuration file)\n"))
1407 ui.write(_(" (specify a username in your configuration file)\n"))
1408 problems += 1
1408 problems += 1
1409
1409
1410 if not problems:
1410 if not problems:
1411 ui.status(_("No problems detected\n"))
1411 ui.status(_("No problems detected\n"))
1412 else:
1412 else:
1413 ui.write(_("%s problems detected,"
1413 ui.write(_("%s problems detected,"
1414 " please check your install!\n") % problems)
1414 " please check your install!\n") % problems)
1415
1415
1416 return problems
1416 return problems
1417
1417
1418 def debugrename(ui, repo, file1, *pats, **opts):
1418 def debugrename(ui, repo, file1, *pats, **opts):
1419 """dump rename information"""
1419 """dump rename information"""
1420
1420
1421 ctx = repo[opts.get('rev')]
1421 ctx = repo[opts.get('rev')]
1422 m = cmdutil.match(repo, (file1,) + pats, opts)
1422 m = cmdutil.match(repo, (file1,) + pats, opts)
1423 for abs in ctx.walk(m):
1423 for abs in ctx.walk(m):
1424 fctx = ctx[abs]
1424 fctx = ctx[abs]
1425 o = fctx.filelog().renamed(fctx.filenode())
1425 o = fctx.filelog().renamed(fctx.filenode())
1426 rel = m.rel(abs)
1426 rel = m.rel(abs)
1427 if o:
1427 if o:
1428 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1428 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1429 else:
1429 else:
1430 ui.write(_("%s not renamed\n") % rel)
1430 ui.write(_("%s not renamed\n") % rel)
1431
1431
1432 def debugwalk(ui, repo, *pats, **opts):
1432 def debugwalk(ui, repo, *pats, **opts):
1433 """show how files match on given patterns"""
1433 """show how files match on given patterns"""
1434 m = cmdutil.match(repo, pats, opts)
1434 m = cmdutil.match(repo, pats, opts)
1435 items = list(repo.walk(m))
1435 items = list(repo.walk(m))
1436 if not items:
1436 if not items:
1437 return
1437 return
1438 fmt = 'f %%-%ds %%-%ds %%s' % (
1438 fmt = 'f %%-%ds %%-%ds %%s' % (
1439 max([len(abs) for abs in items]),
1439 max([len(abs) for abs in items]),
1440 max([len(m.rel(abs)) for abs in items]))
1440 max([len(m.rel(abs)) for abs in items]))
1441 for abs in items:
1441 for abs in items:
1442 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1442 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1443 ui.write("%s\n" % line.rstrip())
1443 ui.write("%s\n" % line.rstrip())
1444
1444
1445 def diff(ui, repo, *pats, **opts):
1445 def diff(ui, repo, *pats, **opts):
1446 """diff repository (or selected files)
1446 """diff repository (or selected files)
1447
1447
1448 Show differences between revisions for the specified files.
1448 Show differences between revisions for the specified files.
1449
1449
1450 Differences between files are shown using the unified diff format.
1450 Differences between files are shown using the unified diff format.
1451
1451
1452 .. note::
1452 .. note::
1453 diff may generate unexpected results for merges, as it will
1453 diff may generate unexpected results for merges, as it will
1454 default to comparing against the working directory's first
1454 default to comparing against the working directory's first
1455 parent changeset if no revisions are specified.
1455 parent changeset if no revisions are specified.
1456
1456
1457 When two revision arguments are given, then changes are shown
1457 When two revision arguments are given, then changes are shown
1458 between those revisions. If only one revision is specified then
1458 between those revisions. If only one revision is specified then
1459 that revision is compared to the working directory, and, when no
1459 that revision is compared to the working directory, and, when no
1460 revisions are specified, the working directory files are compared
1460 revisions are specified, the working directory files are compared
1461 to its parent.
1461 to its parent.
1462
1462
1463 Alternatively you can specify -c/--change with a revision to see
1463 Alternatively you can specify -c/--change with a revision to see
1464 the changes in that changeset relative to its first parent.
1464 the changes in that changeset relative to its first parent.
1465
1465
1466 Without the -a/--text option, diff will avoid generating diffs of
1466 Without the -a/--text option, diff will avoid generating diffs of
1467 files it detects as binary. With -a, diff will generate a diff
1467 files it detects as binary. With -a, diff will generate a diff
1468 anyway, probably with undesirable results.
1468 anyway, probably with undesirable results.
1469
1469
1470 Use the -g/--git option to generate diffs in the git extended diff
1470 Use the -g/--git option to generate diffs in the git extended diff
1471 format. For more information, read :hg:`help diffs`.
1471 format. For more information, read :hg:`help diffs`.
1472
1472
1473 Returns 0 on success.
1473 Returns 0 on success.
1474 """
1474 """
1475
1475
1476 revs = opts.get('rev')
1476 revs = opts.get('rev')
1477 change = opts.get('change')
1477 change = opts.get('change')
1478 stat = opts.get('stat')
1478 stat = opts.get('stat')
1479 reverse = opts.get('reverse')
1479 reverse = opts.get('reverse')
1480
1480
1481 if revs and change:
1481 if revs and change:
1482 msg = _('cannot specify --rev and --change at the same time')
1482 msg = _('cannot specify --rev and --change at the same time')
1483 raise util.Abort(msg)
1483 raise util.Abort(msg)
1484 elif change:
1484 elif change:
1485 node2 = repo.lookup(change)
1485 node2 = repo.lookup(change)
1486 node1 = repo[node2].parents()[0].node()
1486 node1 = repo[node2].parents()[0].node()
1487 else:
1487 else:
1488 node1, node2 = cmdutil.revpair(repo, revs)
1488 node1, node2 = cmdutil.revpair(repo, revs)
1489
1489
1490 if reverse:
1490 if reverse:
1491 node1, node2 = node2, node1
1491 node1, node2 = node2, node1
1492
1492
1493 diffopts = patch.diffopts(ui, opts)
1493 diffopts = patch.diffopts(ui, opts)
1494 m = cmdutil.match(repo, pats, opts)
1494 m = cmdutil.match(repo, pats, opts)
1495 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1495 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1496 listsubrepos=opts.get('subrepos'))
1496 listsubrepos=opts.get('subrepos'))
1497
1497
1498 def export(ui, repo, *changesets, **opts):
1498 def export(ui, repo, *changesets, **opts):
1499 """dump the header and diffs for one or more changesets
1499 """dump the header and diffs for one or more changesets
1500
1500
1501 Print the changeset header and diffs for one or more revisions.
1501 Print the changeset header and diffs for one or more revisions.
1502
1502
1503 The information shown in the changeset header is: author, date,
1503 The information shown in the changeset header is: author, date,
1504 branch name (if non-default), changeset hash, parent(s) and commit
1504 branch name (if non-default), changeset hash, parent(s) and commit
1505 comment.
1505 comment.
1506
1506
1507 .. note::
1507 .. note::
1508 export may generate unexpected diff output for merge
1508 export may generate unexpected diff output for merge
1509 changesets, as it will compare the merge changeset against its
1509 changesets, as it will compare the merge changeset against its
1510 first parent only.
1510 first parent only.
1511
1511
1512 Output may be to a file, in which case the name of the file is
1512 Output may be to a file, in which case the name of the file is
1513 given using a format string. The formatting rules are as follows:
1513 given using a format string. The formatting rules are as follows:
1514
1514
1515 :``%%``: literal "%" character
1515 :``%%``: literal "%" character
1516 :``%H``: changeset hash (40 hexadecimal digits)
1516 :``%H``: changeset hash (40 hexadecimal digits)
1517 :``%N``: number of patches being generated
1517 :``%N``: number of patches being generated
1518 :``%R``: changeset revision number
1518 :``%R``: changeset revision number
1519 :``%b``: basename of the exporting repository
1519 :``%b``: basename of the exporting repository
1520 :``%h``: short-form changeset hash (12 hexadecimal digits)
1520 :``%h``: short-form changeset hash (12 hexadecimal digits)
1521 :``%n``: zero-padded sequence number, starting at 1
1521 :``%n``: zero-padded sequence number, starting at 1
1522 :``%r``: zero-padded changeset revision number
1522 :``%r``: zero-padded changeset revision number
1523
1523
1524 Without the -a/--text option, export will avoid generating diffs
1524 Without the -a/--text option, export will avoid generating diffs
1525 of files it detects as binary. With -a, export will generate a
1525 of files it detects as binary. With -a, export will generate a
1526 diff anyway, probably with undesirable results.
1526 diff anyway, probably with undesirable results.
1527
1527
1528 Use the -g/--git option to generate diffs in the git extended diff
1528 Use the -g/--git option to generate diffs in the git extended diff
1529 format. See :hg:`help diffs` for more information.
1529 format. See :hg:`help diffs` for more information.
1530
1530
1531 With the --switch-parent option, the diff will be against the
1531 With the --switch-parent option, the diff will be against the
1532 second parent. It can be useful to review a merge.
1532 second parent. It can be useful to review a merge.
1533
1533
1534 Returns 0 on success.
1534 Returns 0 on success.
1535 """
1535 """
1536 changesets += tuple(opts.get('rev', []))
1536 changesets += tuple(opts.get('rev', []))
1537 if not changesets:
1537 if not changesets:
1538 raise util.Abort(_("export requires at least one changeset"))
1538 raise util.Abort(_("export requires at least one changeset"))
1539 revs = cmdutil.revrange(repo, changesets)
1539 revs = cmdutil.revrange(repo, changesets)
1540 if len(revs) > 1:
1540 if len(revs) > 1:
1541 ui.note(_('exporting patches:\n'))
1541 ui.note(_('exporting patches:\n'))
1542 else:
1542 else:
1543 ui.note(_('exporting patch:\n'))
1543 ui.note(_('exporting patch:\n'))
1544 cmdutil.export(repo, revs, template=opts.get('output'),
1544 cmdutil.export(repo, revs, template=opts.get('output'),
1545 switch_parent=opts.get('switch_parent'),
1545 switch_parent=opts.get('switch_parent'),
1546 opts=patch.diffopts(ui, opts))
1546 opts=patch.diffopts(ui, opts))
1547
1547
1548 def forget(ui, repo, *pats, **opts):
1548 def forget(ui, repo, *pats, **opts):
1549 """forget the specified files on the next commit
1549 """forget the specified files on the next commit
1550
1550
1551 Mark the specified files so they will no longer be tracked
1551 Mark the specified files so they will no longer be tracked
1552 after the next commit.
1552 after the next commit.
1553
1553
1554 This only removes files from the current branch, not from the
1554 This only removes files from the current branch, not from the
1555 entire project history, and it does not delete them from the
1555 entire project history, and it does not delete them from the
1556 working directory.
1556 working directory.
1557
1557
1558 To undo a forget before the next commit, see :hg:`add`.
1558 To undo a forget before the next commit, see :hg:`add`.
1559
1559
1560 Returns 0 on success.
1560 Returns 0 on success.
1561 """
1561 """
1562
1562
1563 if not pats:
1563 if not pats:
1564 raise util.Abort(_('no files specified'))
1564 raise util.Abort(_('no files specified'))
1565
1565
1566 m = cmdutil.match(repo, pats, opts)
1566 m = cmdutil.match(repo, pats, opts)
1567 s = repo.status(match=m, clean=True)
1567 s = repo.status(match=m, clean=True)
1568 forget = sorted(s[0] + s[1] + s[3] + s[6])
1568 forget = sorted(s[0] + s[1] + s[3] + s[6])
1569 errs = 0
1569 errs = 0
1570
1570
1571 for f in m.files():
1571 for f in m.files():
1572 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1572 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1573 ui.warn(_('not removing %s: file is already untracked\n')
1573 ui.warn(_('not removing %s: file is already untracked\n')
1574 % m.rel(f))
1574 % m.rel(f))
1575 errs = 1
1575 errs = 1
1576
1576
1577 for f in forget:
1577 for f in forget:
1578 if ui.verbose or not m.exact(f):
1578 if ui.verbose or not m.exact(f):
1579 ui.status(_('removing %s\n') % m.rel(f))
1579 ui.status(_('removing %s\n') % m.rel(f))
1580
1580
1581 repo[None].remove(forget, unlink=False)
1581 repo[None].remove(forget, unlink=False)
1582 return errs
1582 return errs
1583
1583
1584 def grep(ui, repo, pattern, *pats, **opts):
1584 def grep(ui, repo, pattern, *pats, **opts):
1585 """search for a pattern in specified files and revisions
1585 """search for a pattern in specified files and revisions
1586
1586
1587 Search revisions of files for a regular expression.
1587 Search revisions of files for a regular expression.
1588
1588
1589 This command behaves differently than Unix grep. It only accepts
1589 This command behaves differently than Unix grep. It only accepts
1590 Python/Perl regexps. It searches repository history, not the
1590 Python/Perl regexps. It searches repository history, not the
1591 working directory. It always prints the revision number in which a
1591 working directory. It always prints the revision number in which a
1592 match appears.
1592 match appears.
1593
1593
1594 By default, grep only prints output for the first revision of a
1594 By default, grep only prints output for the first revision of a
1595 file in which it finds a match. To get it to print every revision
1595 file in which it finds a match. To get it to print every revision
1596 that contains a change in match status ("-" for a match that
1596 that contains a change in match status ("-" for a match that
1597 becomes a non-match, or "+" for a non-match that becomes a match),
1597 becomes a non-match, or "+" for a non-match that becomes a match),
1598 use the --all flag.
1598 use the --all flag.
1599
1599
1600 Returns 0 if a match is found, 1 otherwise.
1600 Returns 0 if a match is found, 1 otherwise.
1601 """
1601 """
1602 reflags = 0
1602 reflags = 0
1603 if opts.get('ignore_case'):
1603 if opts.get('ignore_case'):
1604 reflags |= re.I
1604 reflags |= re.I
1605 try:
1605 try:
1606 regexp = re.compile(pattern, reflags)
1606 regexp = re.compile(pattern, reflags)
1607 except re.error, inst:
1607 except re.error, inst:
1608 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1608 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1609 return 1
1609 return 1
1610 sep, eol = ':', '\n'
1610 sep, eol = ':', '\n'
1611 if opts.get('print0'):
1611 if opts.get('print0'):
1612 sep = eol = '\0'
1612 sep = eol = '\0'
1613
1613
1614 getfile = util.lrucachefunc(repo.file)
1614 getfile = util.lrucachefunc(repo.file)
1615
1615
1616 def matchlines(body):
1616 def matchlines(body):
1617 begin = 0
1617 begin = 0
1618 linenum = 0
1618 linenum = 0
1619 while True:
1619 while True:
1620 match = regexp.search(body, begin)
1620 match = regexp.search(body, begin)
1621 if not match:
1621 if not match:
1622 break
1622 break
1623 mstart, mend = match.span()
1623 mstart, mend = match.span()
1624 linenum += body.count('\n', begin, mstart) + 1
1624 linenum += body.count('\n', begin, mstart) + 1
1625 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1625 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1626 begin = body.find('\n', mend) + 1 or len(body)
1626 begin = body.find('\n', mend) + 1 or len(body)
1627 lend = begin - 1
1627 lend = begin - 1
1628 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1628 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1629
1629
1630 class linestate(object):
1630 class linestate(object):
1631 def __init__(self, line, linenum, colstart, colend):
1631 def __init__(self, line, linenum, colstart, colend):
1632 self.line = line
1632 self.line = line
1633 self.linenum = linenum
1633 self.linenum = linenum
1634 self.colstart = colstart
1634 self.colstart = colstart
1635 self.colend = colend
1635 self.colend = colend
1636
1636
1637 def __hash__(self):
1637 def __hash__(self):
1638 return hash((self.linenum, self.line))
1638 return hash((self.linenum, self.line))
1639
1639
1640 def __eq__(self, other):
1640 def __eq__(self, other):
1641 return self.line == other.line
1641 return self.line == other.line
1642
1642
1643 matches = {}
1643 matches = {}
1644 copies = {}
1644 copies = {}
1645 def grepbody(fn, rev, body):
1645 def grepbody(fn, rev, body):
1646 matches[rev].setdefault(fn, [])
1646 matches[rev].setdefault(fn, [])
1647 m = matches[rev][fn]
1647 m = matches[rev][fn]
1648 for lnum, cstart, cend, line in matchlines(body):
1648 for lnum, cstart, cend, line in matchlines(body):
1649 s = linestate(line, lnum, cstart, cend)
1649 s = linestate(line, lnum, cstart, cend)
1650 m.append(s)
1650 m.append(s)
1651
1651
1652 def difflinestates(a, b):
1652 def difflinestates(a, b):
1653 sm = difflib.SequenceMatcher(None, a, b)
1653 sm = difflib.SequenceMatcher(None, a, b)
1654 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1654 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1655 if tag == 'insert':
1655 if tag == 'insert':
1656 for i in xrange(blo, bhi):
1656 for i in xrange(blo, bhi):
1657 yield ('+', b[i])
1657 yield ('+', b[i])
1658 elif tag == 'delete':
1658 elif tag == 'delete':
1659 for i in xrange(alo, ahi):
1659 for i in xrange(alo, ahi):
1660 yield ('-', a[i])
1660 yield ('-', a[i])
1661 elif tag == 'replace':
1661 elif tag == 'replace':
1662 for i in xrange(alo, ahi):
1662 for i in xrange(alo, ahi):
1663 yield ('-', a[i])
1663 yield ('-', a[i])
1664 for i in xrange(blo, bhi):
1664 for i in xrange(blo, bhi):
1665 yield ('+', b[i])
1665 yield ('+', b[i])
1666
1666
1667 def display(fn, ctx, pstates, states):
1667 def display(fn, ctx, pstates, states):
1668 rev = ctx.rev()
1668 rev = ctx.rev()
1669 datefunc = ui.quiet and util.shortdate or util.datestr
1669 datefunc = ui.quiet and util.shortdate or util.datestr
1670 found = False
1670 found = False
1671 filerevmatches = {}
1671 filerevmatches = {}
1672 if opts.get('all'):
1672 if opts.get('all'):
1673 iter = difflinestates(pstates, states)
1673 iter = difflinestates(pstates, states)
1674 else:
1674 else:
1675 iter = [('', l) for l in states]
1675 iter = [('', l) for l in states]
1676 for change, l in iter:
1676 for change, l in iter:
1677 cols = [fn, str(rev)]
1677 cols = [fn, str(rev)]
1678 before, match, after = None, None, None
1678 before, match, after = None, None, None
1679 if opts.get('line_number'):
1679 if opts.get('line_number'):
1680 cols.append(str(l.linenum))
1680 cols.append(str(l.linenum))
1681 if opts.get('all'):
1681 if opts.get('all'):
1682 cols.append(change)
1682 cols.append(change)
1683 if opts.get('user'):
1683 if opts.get('user'):
1684 cols.append(ui.shortuser(ctx.user()))
1684 cols.append(ui.shortuser(ctx.user()))
1685 if opts.get('date'):
1685 if opts.get('date'):
1686 cols.append(datefunc(ctx.date()))
1686 cols.append(datefunc(ctx.date()))
1687 if opts.get('files_with_matches'):
1687 if opts.get('files_with_matches'):
1688 c = (fn, rev)
1688 c = (fn, rev)
1689 if c in filerevmatches:
1689 if c in filerevmatches:
1690 continue
1690 continue
1691 filerevmatches[c] = 1
1691 filerevmatches[c] = 1
1692 else:
1692 else:
1693 before = l.line[:l.colstart]
1693 before = l.line[:l.colstart]
1694 match = l.line[l.colstart:l.colend]
1694 match = l.line[l.colstart:l.colend]
1695 after = l.line[l.colend:]
1695 after = l.line[l.colend:]
1696 ui.write(sep.join(cols))
1696 ui.write(sep.join(cols))
1697 if before is not None:
1697 if before is not None:
1698 ui.write(sep + before)
1698 ui.write(sep + before)
1699 ui.write(match, label='grep.match')
1699 ui.write(match, label='grep.match')
1700 ui.write(after)
1700 ui.write(after)
1701 ui.write(eol)
1701 ui.write(eol)
1702 found = True
1702 found = True
1703 return found
1703 return found
1704
1704
1705 skip = {}
1705 skip = {}
1706 revfiles = {}
1706 revfiles = {}
1707 matchfn = cmdutil.match(repo, pats, opts)
1707 matchfn = cmdutil.match(repo, pats, opts)
1708 found = False
1708 found = False
1709 follow = opts.get('follow')
1709 follow = opts.get('follow')
1710
1710
1711 def prep(ctx, fns):
1711 def prep(ctx, fns):
1712 rev = ctx.rev()
1712 rev = ctx.rev()
1713 pctx = ctx.parents()[0]
1713 pctx = ctx.parents()[0]
1714 parent = pctx.rev()
1714 parent = pctx.rev()
1715 matches.setdefault(rev, {})
1715 matches.setdefault(rev, {})
1716 matches.setdefault(parent, {})
1716 matches.setdefault(parent, {})
1717 files = revfiles.setdefault(rev, [])
1717 files = revfiles.setdefault(rev, [])
1718 for fn in fns:
1718 for fn in fns:
1719 flog = getfile(fn)
1719 flog = getfile(fn)
1720 try:
1720 try:
1721 fnode = ctx.filenode(fn)
1721 fnode = ctx.filenode(fn)
1722 except error.LookupError:
1722 except error.LookupError:
1723 continue
1723 continue
1724
1724
1725 copied = flog.renamed(fnode)
1725 copied = flog.renamed(fnode)
1726 copy = follow and copied and copied[0]
1726 copy = follow and copied and copied[0]
1727 if copy:
1727 if copy:
1728 copies.setdefault(rev, {})[fn] = copy
1728 copies.setdefault(rev, {})[fn] = copy
1729 if fn in skip:
1729 if fn in skip:
1730 if copy:
1730 if copy:
1731 skip[copy] = True
1731 skip[copy] = True
1732 continue
1732 continue
1733 files.append(fn)
1733 files.append(fn)
1734
1734
1735 if fn not in matches[rev]:
1735 if fn not in matches[rev]:
1736 grepbody(fn, rev, flog.read(fnode))
1736 grepbody(fn, rev, flog.read(fnode))
1737
1737
1738 pfn = copy or fn
1738 pfn = copy or fn
1739 if pfn not in matches[parent]:
1739 if pfn not in matches[parent]:
1740 try:
1740 try:
1741 fnode = pctx.filenode(pfn)
1741 fnode = pctx.filenode(pfn)
1742 grepbody(pfn, parent, flog.read(fnode))
1742 grepbody(pfn, parent, flog.read(fnode))
1743 except error.LookupError:
1743 except error.LookupError:
1744 pass
1744 pass
1745
1745
1746 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1746 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1747 rev = ctx.rev()
1747 rev = ctx.rev()
1748 parent = ctx.parents()[0].rev()
1748 parent = ctx.parents()[0].rev()
1749 for fn in sorted(revfiles.get(rev, [])):
1749 for fn in sorted(revfiles.get(rev, [])):
1750 states = matches[rev][fn]
1750 states = matches[rev][fn]
1751 copy = copies.get(rev, {}).get(fn)
1751 copy = copies.get(rev, {}).get(fn)
1752 if fn in skip:
1752 if fn in skip:
1753 if copy:
1753 if copy:
1754 skip[copy] = True
1754 skip[copy] = True
1755 continue
1755 continue
1756 pstates = matches.get(parent, {}).get(copy or fn, [])
1756 pstates = matches.get(parent, {}).get(copy or fn, [])
1757 if pstates or states:
1757 if pstates or states:
1758 r = display(fn, ctx, pstates, states)
1758 r = display(fn, ctx, pstates, states)
1759 found = found or r
1759 found = found or r
1760 if r and not opts.get('all'):
1760 if r and not opts.get('all'):
1761 skip[fn] = True
1761 skip[fn] = True
1762 if copy:
1762 if copy:
1763 skip[copy] = True
1763 skip[copy] = True
1764 del matches[rev]
1764 del matches[rev]
1765 del revfiles[rev]
1765 del revfiles[rev]
1766
1766
1767 return not found
1767 return not found
1768
1768
1769 def heads(ui, repo, *branchrevs, **opts):
1769 def heads(ui, repo, *branchrevs, **opts):
1770 """show current repository heads or show branch heads
1770 """show current repository heads or show branch heads
1771
1771
1772 With no arguments, show all repository branch heads.
1772 With no arguments, show all repository branch heads.
1773
1773
1774 Repository "heads" are changesets with no child changesets. They are
1774 Repository "heads" are changesets with no child changesets. They are
1775 where development generally takes place and are the usual targets
1775 where development generally takes place and are the usual targets
1776 for update and merge operations. Branch heads are changesets that have
1776 for update and merge operations. Branch heads are changesets that have
1777 no child changeset on the same branch.
1777 no child changeset on the same branch.
1778
1778
1779 If one or more REVs are given, only branch heads on the branches
1779 If one or more REVs are given, only branch heads on the branches
1780 associated with the specified changesets are shown.
1780 associated with the specified changesets are shown.
1781
1781
1782 If -c/--closed is specified, also show branch heads marked closed
1782 If -c/--closed is specified, also show branch heads marked closed
1783 (see :hg:`commit --close-branch`).
1783 (see :hg:`commit --close-branch`).
1784
1784
1785 If STARTREV is specified, only those heads that are descendants of
1785 If STARTREV is specified, only those heads that are descendants of
1786 STARTREV will be displayed.
1786 STARTREV will be displayed.
1787
1787
1788 If -t/--topo is specified, named branch mechanics will be ignored and only
1788 If -t/--topo is specified, named branch mechanics will be ignored and only
1789 changesets without children will be shown.
1789 changesets without children will be shown.
1790
1790
1791 Returns 0 if matching heads are found, 1 if not.
1791 Returns 0 if matching heads are found, 1 if not.
1792 """
1792 """
1793
1793
1794 if opts.get('rev'):
1794 if opts.get('rev'):
1795 start = repo.lookup(opts['rev'])
1795 start = repo.lookup(opts['rev'])
1796 else:
1796 else:
1797 start = None
1797 start = None
1798
1798
1799 if opts.get('topo'):
1799 if opts.get('topo'):
1800 heads = [repo[h] for h in repo.heads(start)]
1800 heads = [repo[h] for h in repo.heads(start)]
1801 else:
1801 else:
1802 heads = []
1802 heads = []
1803 for b, ls in repo.branchmap().iteritems():
1803 for b, ls in repo.branchmap().iteritems():
1804 if start is None:
1804 if start is None:
1805 heads += [repo[h] for h in ls]
1805 heads += [repo[h] for h in ls]
1806 continue
1806 continue
1807 startrev = repo.changelog.rev(start)
1807 startrev = repo.changelog.rev(start)
1808 descendants = set(repo.changelog.descendants(startrev))
1808 descendants = set(repo.changelog.descendants(startrev))
1809 descendants.add(startrev)
1809 descendants.add(startrev)
1810 rev = repo.changelog.rev
1810 rev = repo.changelog.rev
1811 heads += [repo[h] for h in ls if rev(h) in descendants]
1811 heads += [repo[h] for h in ls if rev(h) in descendants]
1812
1812
1813 if branchrevs:
1813 if branchrevs:
1814 decode, encode = encoding.fromlocal, encoding.tolocal
1814 decode, encode = encoding.fromlocal, encoding.tolocal
1815 branches = set(repo[decode(br)].branch() for br in branchrevs)
1815 branches = set(repo[decode(br)].branch() for br in branchrevs)
1816 heads = [h for h in heads if h.branch() in branches]
1816 heads = [h for h in heads if h.branch() in branches]
1817
1817
1818 if not opts.get('closed'):
1818 if not opts.get('closed'):
1819 heads = [h for h in heads if not h.extra().get('close')]
1819 heads = [h for h in heads if not h.extra().get('close')]
1820
1820
1821 if opts.get('active') and branchrevs:
1821 if opts.get('active') and branchrevs:
1822 dagheads = repo.heads(start)
1822 dagheads = repo.heads(start)
1823 heads = [h for h in heads if h.node() in dagheads]
1823 heads = [h for h in heads if h.node() in dagheads]
1824
1824
1825 if branchrevs:
1825 if branchrevs:
1826 haveheads = set(h.branch() for h in heads)
1826 haveheads = set(h.branch() for h in heads)
1827 if branches - haveheads:
1827 if branches - haveheads:
1828 headless = ', '.join(encode(b) for b in branches - haveheads)
1828 headless = ', '.join(encode(b) for b in branches - haveheads)
1829 msg = _('no open branch heads found on branches %s')
1829 msg = _('no open branch heads found on branches %s')
1830 if opts.get('rev'):
1830 if opts.get('rev'):
1831 msg += _(' (started at %s)' % opts['rev'])
1831 msg += _(' (started at %s)' % opts['rev'])
1832 ui.warn((msg + '\n') % headless)
1832 ui.warn((msg + '\n') % headless)
1833
1833
1834 if not heads:
1834 if not heads:
1835 return 1
1835 return 1
1836
1836
1837 heads = sorted(heads, key=lambda x: -x.rev())
1837 heads = sorted(heads, key=lambda x: -x.rev())
1838 displayer = cmdutil.show_changeset(ui, repo, opts)
1838 displayer = cmdutil.show_changeset(ui, repo, opts)
1839 for ctx in heads:
1839 for ctx in heads:
1840 displayer.show(ctx)
1840 displayer.show(ctx)
1841 displayer.close()
1841 displayer.close()
1842
1842
1843 def help_(ui, name=None, with_version=False, unknowncmd=False):
1843 def help_(ui, name=None, with_version=False, unknowncmd=False):
1844 """show help for a given topic or a help overview
1844 """show help for a given topic or a help overview
1845
1845
1846 With no arguments, print a list of commands with short help messages.
1846 With no arguments, print a list of commands with short help messages.
1847
1847
1848 Given a topic, extension, or command name, print help for that
1848 Given a topic, extension, or command name, print help for that
1849 topic.
1849 topic.
1850
1850
1851 Returns 0 if successful.
1851 Returns 0 if successful.
1852 """
1852 """
1853 option_lists = []
1853 option_lists = []
1854 textwidth = ui.termwidth() - 2
1854 textwidth = ui.termwidth() - 2
1855
1855
1856 def addglobalopts(aliases):
1856 def addglobalopts(aliases):
1857 if ui.verbose:
1857 if ui.verbose:
1858 option_lists.append((_("global options:"), globalopts))
1858 option_lists.append((_("global options:"), globalopts))
1859 if name == 'shortlist':
1859 if name == 'shortlist':
1860 option_lists.append((_('use "hg help" for the full list '
1860 option_lists.append((_('use "hg help" for the full list '
1861 'of commands'), ()))
1861 'of commands'), ()))
1862 else:
1862 else:
1863 if name == 'shortlist':
1863 if name == 'shortlist':
1864 msg = _('use "hg help" for the full list of commands '
1864 msg = _('use "hg help" for the full list of commands '
1865 'or "hg -v" for details')
1865 'or "hg -v" for details')
1866 elif aliases:
1866 elif aliases:
1867 msg = _('use "hg -v help%s" to show aliases and '
1867 msg = _('use "hg -v help%s" to show aliases and '
1868 'global options') % (name and " " + name or "")
1868 'global options') % (name and " " + name or "")
1869 else:
1869 else:
1870 msg = _('use "hg -v help %s" to show global options') % name
1870 msg = _('use "hg -v help %s" to show global options') % name
1871 option_lists.append((msg, ()))
1871 option_lists.append((msg, ()))
1872
1872
1873 def helpcmd(name):
1873 def helpcmd(name):
1874 if with_version:
1874 if with_version:
1875 version_(ui)
1875 version_(ui)
1876 ui.write('\n')
1876 ui.write('\n')
1877
1877
1878 try:
1878 try:
1879 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1879 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1880 except error.AmbiguousCommand, inst:
1880 except error.AmbiguousCommand, inst:
1881 # py3k fix: except vars can't be used outside the scope of the
1881 # py3k fix: except vars can't be used outside the scope of the
1882 # except block, nor can be used inside a lambda. python issue4617
1882 # except block, nor can be used inside a lambda. python issue4617
1883 prefix = inst.args[0]
1883 prefix = inst.args[0]
1884 select = lambda c: c.lstrip('^').startswith(prefix)
1884 select = lambda c: c.lstrip('^').startswith(prefix)
1885 helplist(_('list of commands:\n\n'), select)
1885 helplist(_('list of commands:\n\n'), select)
1886 return
1886 return
1887
1887
1888 # check if it's an invalid alias and display its error if it is
1888 # check if it's an invalid alias and display its error if it is
1889 if getattr(entry[0], 'badalias', False):
1889 if getattr(entry[0], 'badalias', False):
1890 if not unknowncmd:
1890 if not unknowncmd:
1891 entry[0](ui)
1891 entry[0](ui)
1892 return
1892 return
1893
1893
1894 # synopsis
1894 # synopsis
1895 if len(entry) > 2:
1895 if len(entry) > 2:
1896 if entry[2].startswith('hg'):
1896 if entry[2].startswith('hg'):
1897 ui.write("%s\n" % entry[2])
1897 ui.write("%s\n" % entry[2])
1898 else:
1898 else:
1899 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1899 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1900 else:
1900 else:
1901 ui.write('hg %s\n' % aliases[0])
1901 ui.write('hg %s\n' % aliases[0])
1902
1902
1903 # aliases
1903 # aliases
1904 if not ui.quiet and len(aliases) > 1:
1904 if not ui.quiet and len(aliases) > 1:
1905 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1905 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1906
1906
1907 # description
1907 # description
1908 doc = gettext(entry[0].__doc__)
1908 doc = gettext(entry[0].__doc__)
1909 if not doc:
1909 if not doc:
1910 doc = _("(no help text available)")
1910 doc = _("(no help text available)")
1911 if hasattr(entry[0], 'definition'): # aliased command
1911 if hasattr(entry[0], 'definition'): # aliased command
1912 if entry[0].definition.startswith('!'): # shell alias
1912 if entry[0].definition.startswith('!'): # shell alias
1913 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1913 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1914 else:
1914 else:
1915 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1915 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1916 if ui.quiet:
1916 if ui.quiet:
1917 doc = doc.splitlines()[0]
1917 doc = doc.splitlines()[0]
1918 keep = ui.verbose and ['verbose'] or []
1918 keep = ui.verbose and ['verbose'] or []
1919 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1919 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1920 ui.write("\n%s\n" % formatted)
1920 ui.write("\n%s\n" % formatted)
1921 if pruned:
1921 if pruned:
1922 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1922 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1923
1923
1924 if not ui.quiet:
1924 if not ui.quiet:
1925 # options
1925 # options
1926 if entry[1]:
1926 if entry[1]:
1927 option_lists.append((_("options:\n"), entry[1]))
1927 option_lists.append((_("options:\n"), entry[1]))
1928
1928
1929 addglobalopts(False)
1929 addglobalopts(False)
1930
1930
1931 def helplist(header, select=None):
1931 def helplist(header, select=None):
1932 h = {}
1932 h = {}
1933 cmds = {}
1933 cmds = {}
1934 for c, e in table.iteritems():
1934 for c, e in table.iteritems():
1935 f = c.split("|", 1)[0]
1935 f = c.split("|", 1)[0]
1936 if select and not select(f):
1936 if select and not select(f):
1937 continue
1937 continue
1938 if (not select and name != 'shortlist' and
1938 if (not select and name != 'shortlist' and
1939 e[0].__module__ != __name__):
1939 e[0].__module__ != __name__):
1940 continue
1940 continue
1941 if name == "shortlist" and not f.startswith("^"):
1941 if name == "shortlist" and not f.startswith("^"):
1942 continue
1942 continue
1943 f = f.lstrip("^")
1943 f = f.lstrip("^")
1944 if not ui.debugflag and f.startswith("debug"):
1944 if not ui.debugflag and f.startswith("debug"):
1945 continue
1945 continue
1946 doc = e[0].__doc__
1946 doc = e[0].__doc__
1947 if doc and 'DEPRECATED' in doc and not ui.verbose:
1947 if doc and 'DEPRECATED' in doc and not ui.verbose:
1948 continue
1948 continue
1949 doc = gettext(doc)
1949 doc = gettext(doc)
1950 if not doc:
1950 if not doc:
1951 doc = _("(no help text available)")
1951 doc = _("(no help text available)")
1952 h[f] = doc.splitlines()[0].rstrip()
1952 h[f] = doc.splitlines()[0].rstrip()
1953 cmds[f] = c.lstrip("^")
1953 cmds[f] = c.lstrip("^")
1954
1954
1955 if not h:
1955 if not h:
1956 ui.status(_('no commands defined\n'))
1956 ui.status(_('no commands defined\n'))
1957 return
1957 return
1958
1958
1959 ui.status(header)
1959 ui.status(header)
1960 fns = sorted(h)
1960 fns = sorted(h)
1961 m = max(map(len, fns))
1961 m = max(map(len, fns))
1962 for f in fns:
1962 for f in fns:
1963 if ui.verbose:
1963 if ui.verbose:
1964 commands = cmds[f].replace("|",", ")
1964 commands = cmds[f].replace("|",", ")
1965 ui.write(" %s:\n %s\n"%(commands, h[f]))
1965 ui.write(" %s:\n %s\n"%(commands, h[f]))
1966 else:
1966 else:
1967 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1967 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1968 initindent=' %-*s ' % (m, f),
1968 initindent=' %-*s ' % (m, f),
1969 hangindent=' ' * (m + 4))))
1969 hangindent=' ' * (m + 4))))
1970
1970
1971 if not ui.quiet:
1971 if not ui.quiet:
1972 addglobalopts(True)
1972 addglobalopts(True)
1973
1973
1974 def helptopic(name):
1974 def helptopic(name):
1975 for names, header, doc in help.helptable:
1975 for names, header, doc in help.helptable:
1976 if name in names:
1976 if name in names:
1977 break
1977 break
1978 else:
1978 else:
1979 raise error.UnknownCommand(name)
1979 raise error.UnknownCommand(name)
1980
1980
1981 # description
1981 # description
1982 if not doc:
1982 if not doc:
1983 doc = _("(no help text available)")
1983 doc = _("(no help text available)")
1984 if hasattr(doc, '__call__'):
1984 if hasattr(doc, '__call__'):
1985 doc = doc()
1985 doc = doc()
1986
1986
1987 ui.write("%s\n\n" % header)
1987 ui.write("%s\n\n" % header)
1988 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1988 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1989
1989
1990 def helpext(name):
1990 def helpext(name):
1991 try:
1991 try:
1992 mod = extensions.find(name)
1992 mod = extensions.find(name)
1993 doc = gettext(mod.__doc__) or _('no help text available')
1993 doc = gettext(mod.__doc__) or _('no help text available')
1994 except KeyError:
1994 except KeyError:
1995 mod = None
1995 mod = None
1996 doc = extensions.disabledext(name)
1996 doc = extensions.disabledext(name)
1997 if not doc:
1997 if not doc:
1998 raise error.UnknownCommand(name)
1998 raise error.UnknownCommand(name)
1999
1999
2000 if '\n' not in doc:
2000 if '\n' not in doc:
2001 head, tail = doc, ""
2001 head, tail = doc, ""
2002 else:
2002 else:
2003 head, tail = doc.split('\n', 1)
2003 head, tail = doc.split('\n', 1)
2004 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2004 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2005 if tail:
2005 if tail:
2006 ui.write(minirst.format(tail, textwidth))
2006 ui.write(minirst.format(tail, textwidth))
2007 ui.status('\n\n')
2007 ui.status('\n\n')
2008
2008
2009 if mod:
2009 if mod:
2010 try:
2010 try:
2011 ct = mod.cmdtable
2011 ct = mod.cmdtable
2012 except AttributeError:
2012 except AttributeError:
2013 ct = {}
2013 ct = {}
2014 modcmds = set([c.split('|', 1)[0] for c in ct])
2014 modcmds = set([c.split('|', 1)[0] for c in ct])
2015 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2015 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2016 else:
2016 else:
2017 ui.write(_('use "hg help extensions" for information on enabling '
2017 ui.write(_('use "hg help extensions" for information on enabling '
2018 'extensions\n'))
2018 'extensions\n'))
2019
2019
2020 def helpextcmd(name):
2020 def helpextcmd(name):
2021 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2021 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2022 doc = gettext(mod.__doc__).splitlines()[0]
2022 doc = gettext(mod.__doc__).splitlines()[0]
2023
2023
2024 msg = help.listexts(_("'%s' is provided by the following "
2024 msg = help.listexts(_("'%s' is provided by the following "
2025 "extension:") % cmd, {ext: doc}, len(ext),
2025 "extension:") % cmd, {ext: doc}, len(ext),
2026 indent=4)
2026 indent=4)
2027 ui.write(minirst.format(msg, textwidth))
2027 ui.write(minirst.format(msg, textwidth))
2028 ui.write('\n\n')
2028 ui.write('\n\n')
2029 ui.write(_('use "hg help extensions" for information on enabling '
2029 ui.write(_('use "hg help extensions" for information on enabling '
2030 'extensions\n'))
2030 'extensions\n'))
2031
2031
2032 help.addtopichook('revsets', revset.makedoc)
2032 help.addtopichook('revsets', revset.makedoc)
2033
2033
2034 if name and name != 'shortlist':
2034 if name and name != 'shortlist':
2035 i = None
2035 i = None
2036 if unknowncmd:
2036 if unknowncmd:
2037 queries = (helpextcmd,)
2037 queries = (helpextcmd,)
2038 else:
2038 else:
2039 queries = (helptopic, helpcmd, helpext, helpextcmd)
2039 queries = (helptopic, helpcmd, helpext, helpextcmd)
2040 for f in queries:
2040 for f in queries:
2041 try:
2041 try:
2042 f(name)
2042 f(name)
2043 i = None
2043 i = None
2044 break
2044 break
2045 except error.UnknownCommand, inst:
2045 except error.UnknownCommand, inst:
2046 i = inst
2046 i = inst
2047 if i:
2047 if i:
2048 raise i
2048 raise i
2049
2049
2050 else:
2050 else:
2051 # program name
2051 # program name
2052 if ui.verbose or with_version:
2052 if ui.verbose or with_version:
2053 version_(ui)
2053 version_(ui)
2054 else:
2054 else:
2055 ui.status(_("Mercurial Distributed SCM\n"))
2055 ui.status(_("Mercurial Distributed SCM\n"))
2056 ui.status('\n')
2056 ui.status('\n')
2057
2057
2058 # list of commands
2058 # list of commands
2059 if name == "shortlist":
2059 if name == "shortlist":
2060 header = _('basic commands:\n\n')
2060 header = _('basic commands:\n\n')
2061 else:
2061 else:
2062 header = _('list of commands:\n\n')
2062 header = _('list of commands:\n\n')
2063
2063
2064 helplist(header)
2064 helplist(header)
2065 if name != 'shortlist':
2065 if name != 'shortlist':
2066 exts, maxlength = extensions.enabled()
2066 exts, maxlength = extensions.enabled()
2067 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2067 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2068 if text:
2068 if text:
2069 ui.write("\n%s\n" % minirst.format(text, textwidth))
2069 ui.write("\n%s\n" % minirst.format(text, textwidth))
2070
2070
2071 # list all option lists
2071 # list all option lists
2072 opt_output = []
2072 opt_output = []
2073 multioccur = False
2073 multioccur = False
2074 for title, options in option_lists:
2074 for title, options in option_lists:
2075 opt_output.append(("\n%s" % title, None))
2075 opt_output.append(("\n%s" % title, None))
2076 for option in options:
2076 for option in options:
2077 if len(option) == 5:
2077 if len(option) == 5:
2078 shortopt, longopt, default, desc, optlabel = option
2078 shortopt, longopt, default, desc, optlabel = option
2079 else:
2079 else:
2080 shortopt, longopt, default, desc = option
2080 shortopt, longopt, default, desc = option
2081 optlabel = _("VALUE") # default label
2081 optlabel = _("VALUE") # default label
2082
2082
2083 if _("DEPRECATED") in desc and not ui.verbose:
2083 if _("DEPRECATED") in desc and not ui.verbose:
2084 continue
2084 continue
2085 if isinstance(default, list):
2085 if isinstance(default, list):
2086 numqualifier = " %s [+]" % optlabel
2086 numqualifier = " %s [+]" % optlabel
2087 multioccur = True
2087 multioccur = True
2088 elif (default is not None) and not isinstance(default, bool):
2088 elif (default is not None) and not isinstance(default, bool):
2089 numqualifier = " %s" % optlabel
2089 numqualifier = " %s" % optlabel
2090 else:
2090 else:
2091 numqualifier = ""
2091 numqualifier = ""
2092 opt_output.append(("%2s%s" %
2092 opt_output.append(("%2s%s" %
2093 (shortopt and "-%s" % shortopt,
2093 (shortopt and "-%s" % shortopt,
2094 longopt and " --%s%s" %
2094 longopt and " --%s%s" %
2095 (longopt, numqualifier)),
2095 (longopt, numqualifier)),
2096 "%s%s" % (desc,
2096 "%s%s" % (desc,
2097 default
2097 default
2098 and _(" (default: %s)") % default
2098 and _(" (default: %s)") % default
2099 or "")))
2099 or "")))
2100 if multioccur:
2100 if multioccur:
2101 msg = _("\n[+] marked option can be specified multiple times")
2101 msg = _("\n[+] marked option can be specified multiple times")
2102 if ui.verbose and name != 'shortlist':
2102 if ui.verbose and name != 'shortlist':
2103 opt_output.append((msg, None))
2103 opt_output.append((msg, None))
2104 else:
2104 else:
2105 opt_output.insert(-1, (msg, None))
2105 opt_output.insert(-1, (msg, None))
2106
2106
2107 if not name:
2107 if not name:
2108 ui.write(_("\nadditional help topics:\n\n"))
2108 ui.write(_("\nadditional help topics:\n\n"))
2109 topics = []
2109 topics = []
2110 for names, header, doc in help.helptable:
2110 for names, header, doc in help.helptable:
2111 topics.append((sorted(names, key=len, reverse=True)[0], header))
2111 topics.append((sorted(names, key=len, reverse=True)[0], header))
2112 topics_len = max([len(s[0]) for s in topics])
2112 topics_len = max([len(s[0]) for s in topics])
2113 for t, desc in topics:
2113 for t, desc in topics:
2114 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2114 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2115
2115
2116 if opt_output:
2116 if opt_output:
2117 colwidth = encoding.colwidth
2117 colwidth = encoding.colwidth
2118 # normalize: (opt or message, desc or None, width of opt)
2118 # normalize: (opt or message, desc or None, width of opt)
2119 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2119 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2120 for opt, desc in opt_output]
2120 for opt, desc in opt_output]
2121 hanging = max([e[2] for e in entries])
2121 hanging = max([e[2] for e in entries])
2122 for opt, desc, width in entries:
2122 for opt, desc, width in entries:
2123 if desc:
2123 if desc:
2124 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2124 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2125 hangindent = ' ' * (hanging + 3)
2125 hangindent = ' ' * (hanging + 3)
2126 ui.write('%s\n' % (util.wrap(desc, textwidth,
2126 ui.write('%s\n' % (util.wrap(desc, textwidth,
2127 initindent=initindent,
2127 initindent=initindent,
2128 hangindent=hangindent)))
2128 hangindent=hangindent)))
2129 else:
2129 else:
2130 ui.write("%s\n" % opt)
2130 ui.write("%s\n" % opt)
2131
2131
2132 def identify(ui, repo, source=None,
2132 def identify(ui, repo, source=None,
2133 rev=None, num=None, id=None, branch=None, tags=None):
2133 rev=None, num=None, id=None, branch=None, tags=None):
2134 """identify the working copy or specified revision
2134 """identify the working copy or specified revision
2135
2135
2136 With no revision, print a summary of the current state of the
2136 With no revision, print a summary of the current state of the
2137 repository.
2137 repository.
2138
2138
2139 Specifying a path to a repository root or Mercurial bundle will
2139 Specifying a path to a repository root or Mercurial bundle will
2140 cause lookup to operate on that repository/bundle.
2140 cause lookup to operate on that repository/bundle.
2141
2141
2142 This summary identifies the repository state using one or two
2142 This summary identifies the repository state using one or two
2143 parent hash identifiers, followed by a "+" if there are
2143 parent hash identifiers, followed by a "+" if there are
2144 uncommitted changes in the working directory, a list of tags for
2144 uncommitted changes in the working directory, a list of tags for
2145 this revision and a branch name for non-default branches.
2145 this revision and a branch name for non-default branches.
2146
2146
2147 Returns 0 if successful.
2147 Returns 0 if successful.
2148 """
2148 """
2149
2149
2150 if not repo and not source:
2150 if not repo and not source:
2151 raise util.Abort(_("there is no Mercurial repository here "
2151 raise util.Abort(_("there is no Mercurial repository here "
2152 "(.hg not found)"))
2152 "(.hg not found)"))
2153
2153
2154 hexfunc = ui.debugflag and hex or short
2154 hexfunc = ui.debugflag and hex or short
2155 default = not (num or id or branch or tags)
2155 default = not (num or id or branch or tags)
2156 output = []
2156 output = []
2157
2157
2158 revs = []
2158 revs = []
2159 if source:
2159 if source:
2160 source, branches = hg.parseurl(ui.expandpath(source))
2160 source, branches = hg.parseurl(ui.expandpath(source))
2161 repo = hg.repository(ui, source)
2161 repo = hg.repository(ui, source)
2162 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2162 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2163
2163
2164 if not repo.local():
2164 if not repo.local():
2165 if not rev and revs:
2165 if not rev and revs:
2166 rev = revs[0]
2166 rev = revs[0]
2167 if not rev:
2167 if not rev:
2168 rev = "tip"
2168 rev = "tip"
2169 if num or branch or tags:
2169 if num or branch or tags:
2170 raise util.Abort(
2170 raise util.Abort(
2171 "can't query remote revision number, branch, or tags")
2171 "can't query remote revision number, branch, or tags")
2172 output = [hexfunc(repo.lookup(rev))]
2172 output = [hexfunc(repo.lookup(rev))]
2173 elif not rev:
2173 elif not rev:
2174 ctx = repo[None]
2174 ctx = repo[None]
2175 parents = ctx.parents()
2175 parents = ctx.parents()
2176 changed = False
2176 changed = False
2177 if default or id or num:
2177 if default or id or num:
2178 changed = util.any(repo.status())
2178 changed = util.any(repo.status())
2179 if default or id:
2179 if default or id:
2180 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2180 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2181 (changed) and "+" or "")]
2181 (changed) and "+" or "")]
2182 if num:
2182 if num:
2183 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2183 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2184 (changed) and "+" or ""))
2184 (changed) and "+" or ""))
2185 else:
2185 else:
2186 ctx = repo[rev]
2186 ctx = repo[rev]
2187 if default or id:
2187 if default or id:
2188 output = [hexfunc(ctx.node())]
2188 output = [hexfunc(ctx.node())]
2189 if num:
2189 if num:
2190 output.append(str(ctx.rev()))
2190 output.append(str(ctx.rev()))
2191
2191
2192 if repo.local() and default and not ui.quiet:
2192 if repo.local() and default and not ui.quiet:
2193 b = encoding.tolocal(ctx.branch())
2193 b = encoding.tolocal(ctx.branch())
2194 if b != 'default':
2194 if b != 'default':
2195 output.append("(%s)" % b)
2195 output.append("(%s)" % b)
2196
2196
2197 # multiple tags for a single parent separated by '/'
2197 # multiple tags for a single parent separated by '/'
2198 t = "/".join(ctx.tags())
2198 t = "/".join(ctx.tags())
2199 if t:
2199 if t:
2200 output.append(t)
2200 output.append(t)
2201
2201
2202 if branch:
2202 if branch:
2203 output.append(encoding.tolocal(ctx.branch()))
2203 output.append(encoding.tolocal(ctx.branch()))
2204
2204
2205 if tags:
2205 if tags:
2206 output.extend(ctx.tags())
2206 output.extend(ctx.tags())
2207
2207
2208 ui.write("%s\n" % ' '.join(output))
2208 ui.write("%s\n" % ' '.join(output))
2209
2209
2210 def import_(ui, repo, patch1, *patches, **opts):
2210 def import_(ui, repo, patch1, *patches, **opts):
2211 """import an ordered set of patches
2211 """import an ordered set of patches
2212
2212
2213 Import a list of patches and commit them individually (unless
2213 Import a list of patches and commit them individually (unless
2214 --no-commit is specified).
2214 --no-commit is specified).
2215
2215
2216 If there are outstanding changes in the working directory, import
2216 If there are outstanding changes in the working directory, import
2217 will abort unless given the -f/--force flag.
2217 will abort unless given the -f/--force flag.
2218
2218
2219 You can import a patch straight from a mail message. Even patches
2219 You can import a patch straight from a mail message. Even patches
2220 as attachments work (to use the body part, it must have type
2220 as attachments work (to use the body part, it must have type
2221 text/plain or text/x-patch). From and Subject headers of email
2221 text/plain or text/x-patch). From and Subject headers of email
2222 message are used as default committer and commit message. All
2222 message are used as default committer and commit message. All
2223 text/plain body parts before first diff are added to commit
2223 text/plain body parts before first diff are added to commit
2224 message.
2224 message.
2225
2225
2226 If the imported patch was generated by :hg:`export`, user and
2226 If the imported patch was generated by :hg:`export`, user and
2227 description from patch override values from message headers and
2227 description from patch override values from message headers and
2228 body. Values given on command line with -m/--message and -u/--user
2228 body. Values given on command line with -m/--message and -u/--user
2229 override these.
2229 override these.
2230
2230
2231 If --exact is specified, import will set the working directory to
2231 If --exact is specified, import will set the working directory to
2232 the parent of each patch before applying it, and will abort if the
2232 the parent of each patch before applying it, and will abort if the
2233 resulting changeset has a different ID than the one recorded in
2233 resulting changeset has a different ID than the one recorded in
2234 the patch. This may happen due to character set problems or other
2234 the patch. This may happen due to character set problems or other
2235 deficiencies in the text patch format.
2235 deficiencies in the text patch format.
2236
2236
2237 With -s/--similarity, hg will attempt to discover renames and
2237 With -s/--similarity, hg will attempt to discover renames and
2238 copies in the patch in the same way as 'addremove'.
2238 copies in the patch in the same way as 'addremove'.
2239
2239
2240 To read a patch from standard input, use "-" as the patch name. If
2240 To read a patch from standard input, use "-" as the patch name. If
2241 a URL is specified, the patch will be downloaded from it.
2241 a URL is specified, the patch will be downloaded from it.
2242 See :hg:`help dates` for a list of formats valid for -d/--date.
2242 See :hg:`help dates` for a list of formats valid for -d/--date.
2243
2243
2244 Returns 0 on success.
2244 Returns 0 on success.
2245 """
2245 """
2246 patches = (patch1,) + patches
2246 patches = (patch1,) + patches
2247
2247
2248 date = opts.get('date')
2248 date = opts.get('date')
2249 if date:
2249 if date:
2250 opts['date'] = util.parsedate(date)
2250 opts['date'] = util.parsedate(date)
2251
2251
2252 try:
2252 try:
2253 sim = float(opts.get('similarity') or 0)
2253 sim = float(opts.get('similarity') or 0)
2254 except ValueError:
2254 except ValueError:
2255 raise util.Abort(_('similarity must be a number'))
2255 raise util.Abort(_('similarity must be a number'))
2256 if sim < 0 or sim > 100:
2256 if sim < 0 or sim > 100:
2257 raise util.Abort(_('similarity must be between 0 and 100'))
2257 raise util.Abort(_('similarity must be between 0 and 100'))
2258
2258
2259 if opts.get('exact') or not opts.get('force'):
2259 if opts.get('exact') or not opts.get('force'):
2260 cmdutil.bail_if_changed(repo)
2260 cmdutil.bail_if_changed(repo)
2261
2261
2262 d = opts["base"]
2262 d = opts["base"]
2263 strip = opts["strip"]
2263 strip = opts["strip"]
2264 wlock = lock = None
2264 wlock = lock = None
2265
2265
2266 def tryone(ui, hunk):
2266 def tryone(ui, hunk):
2267 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2267 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2268 patch.extract(ui, hunk)
2268 patch.extract(ui, hunk)
2269
2269
2270 if not tmpname:
2270 if not tmpname:
2271 return None
2271 return None
2272 commitid = _('to working directory')
2272 commitid = _('to working directory')
2273
2273
2274 try:
2274 try:
2275 cmdline_message = cmdutil.logmessage(opts)
2275 cmdline_message = cmdutil.logmessage(opts)
2276 if cmdline_message:
2276 if cmdline_message:
2277 # pickup the cmdline msg
2277 # pickup the cmdline msg
2278 message = cmdline_message
2278 message = cmdline_message
2279 elif message:
2279 elif message:
2280 # pickup the patch msg
2280 # pickup the patch msg
2281 message = message.strip()
2281 message = message.strip()
2282 else:
2282 else:
2283 # launch the editor
2283 # launch the editor
2284 message = None
2284 message = None
2285 ui.debug('message:\n%s\n' % message)
2285 ui.debug('message:\n%s\n' % message)
2286
2286
2287 wp = repo.parents()
2287 wp = repo.parents()
2288 if opts.get('exact'):
2288 if opts.get('exact'):
2289 if not nodeid or not p1:
2289 if not nodeid or not p1:
2290 raise util.Abort(_('not a Mercurial patch'))
2290 raise util.Abort(_('not a Mercurial patch'))
2291 p1 = repo.lookup(p1)
2291 p1 = repo.lookup(p1)
2292 p2 = repo.lookup(p2 or hex(nullid))
2292 p2 = repo.lookup(p2 or hex(nullid))
2293
2293
2294 if p1 != wp[0].node():
2294 if p1 != wp[0].node():
2295 hg.clean(repo, p1)
2295 hg.clean(repo, p1)
2296 repo.dirstate.setparents(p1, p2)
2296 repo.dirstate.setparents(p1, p2)
2297 elif p2:
2297 elif p2:
2298 try:
2298 try:
2299 p1 = repo.lookup(p1)
2299 p1 = repo.lookup(p1)
2300 p2 = repo.lookup(p2)
2300 p2 = repo.lookup(p2)
2301 if p1 == wp[0].node():
2301 if p1 == wp[0].node():
2302 repo.dirstate.setparents(p1, p2)
2302 repo.dirstate.setparents(p1, p2)
2303 except error.RepoError:
2303 except error.RepoError:
2304 pass
2304 pass
2305 if opts.get('exact') or opts.get('import_branch'):
2305 if opts.get('exact') or opts.get('import_branch'):
2306 repo.dirstate.setbranch(branch or 'default')
2306 repo.dirstate.setbranch(branch or 'default')
2307
2307
2308 files = {}
2308 files = {}
2309 try:
2309 try:
2310 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2310 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2311 files=files, eolmode=None)
2311 files=files, eolmode=None)
2312 finally:
2312 finally:
2313 files = cmdutil.updatedir(ui, repo, files,
2313 files = cmdutil.updatedir(ui, repo, files,
2314 similarity=sim / 100.0)
2314 similarity=sim / 100.0)
2315 if not opts.get('no_commit'):
2315 if not opts.get('no_commit'):
2316 if opts.get('exact'):
2316 if opts.get('exact'):
2317 m = None
2317 m = None
2318 else:
2318 else:
2319 m = cmdutil.matchfiles(repo, files or [])
2319 m = cmdutil.matchfiles(repo, files or [])
2320 n = repo.commit(message, opts.get('user') or user,
2320 n = repo.commit(message, opts.get('user') or user,
2321 opts.get('date') or date, match=m,
2321 opts.get('date') or date, match=m,
2322 editor=cmdutil.commiteditor)
2322 editor=cmdutil.commiteditor)
2323 if opts.get('exact'):
2323 if opts.get('exact'):
2324 if hex(n) != nodeid:
2324 if hex(n) != nodeid:
2325 repo.rollback()
2325 repo.rollback()
2326 raise util.Abort(_('patch is damaged'
2326 raise util.Abort(_('patch is damaged'
2327 ' or loses information'))
2327 ' or loses information'))
2328 # Force a dirstate write so that the next transaction
2328 # Force a dirstate write so that the next transaction
2329 # backups an up-do-date file.
2329 # backups an up-do-date file.
2330 repo.dirstate.write()
2330 repo.dirstate.write()
2331 if n:
2331 if n:
2332 commitid = short(n)
2332 commitid = short(n)
2333
2333
2334 return commitid
2334 return commitid
2335 finally:
2335 finally:
2336 os.unlink(tmpname)
2336 os.unlink(tmpname)
2337
2337
2338 try:
2338 try:
2339 wlock = repo.wlock()
2339 wlock = repo.wlock()
2340 lock = repo.lock()
2340 lock = repo.lock()
2341 lastcommit = None
2341 lastcommit = None
2342 for p in patches:
2342 for p in patches:
2343 pf = os.path.join(d, p)
2343 pf = os.path.join(d, p)
2344
2344
2345 if pf == '-':
2345 if pf == '-':
2346 ui.status(_("applying patch from stdin\n"))
2346 ui.status(_("applying patch from stdin\n"))
2347 pf = sys.stdin
2347 pf = sys.stdin
2348 else:
2348 else:
2349 ui.status(_("applying %s\n") % p)
2349 ui.status(_("applying %s\n") % p)
2350 pf = url.open(ui, pf)
2350 pf = url.open(ui, pf)
2351
2351
2352 haspatch = False
2352 haspatch = False
2353 for hunk in patch.split(pf):
2353 for hunk in patch.split(pf):
2354 commitid = tryone(ui, hunk)
2354 commitid = tryone(ui, hunk)
2355 if commitid:
2355 if commitid:
2356 haspatch = True
2356 haspatch = True
2357 if lastcommit:
2357 if lastcommit:
2358 ui.status(_('applied %s\n') % lastcommit)
2358 ui.status(_('applied %s\n') % lastcommit)
2359 lastcommit = commitid
2359 lastcommit = commitid
2360
2360
2361 if not haspatch:
2361 if not haspatch:
2362 raise util.Abort(_('no diffs found'))
2362 raise util.Abort(_('no diffs found'))
2363
2363
2364 finally:
2364 finally:
2365 release(lock, wlock)
2365 release(lock, wlock)
2366
2366
2367 def incoming(ui, repo, source="default", **opts):
2367 def incoming(ui, repo, source="default", **opts):
2368 """show new changesets found in source
2368 """show new changesets found in source
2369
2369
2370 Show new changesets found in the specified path/URL or the default
2370 Show new changesets found in the specified path/URL or the default
2371 pull location. These are the changesets that would have been pulled
2371 pull location. These are the changesets that would have been pulled
2372 if a pull at the time you issued this command.
2372 if a pull at the time you issued this command.
2373
2373
2374 For remote repository, using --bundle avoids downloading the
2374 For remote repository, using --bundle avoids downloading the
2375 changesets twice if the incoming is followed by a pull.
2375 changesets twice if the incoming is followed by a pull.
2376
2376
2377 See pull for valid source format details.
2377 See pull for valid source format details.
2378
2378
2379 Returns 0 if there are incoming changes, 1 otherwise.
2379 Returns 0 if there are incoming changes, 1 otherwise.
2380 """
2380 """
2381 if opts.get('bundle') and opts.get('subrepos'):
2381 if opts.get('bundle') and opts.get('subrepos'):
2382 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2382 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2383
2383
2384 ret = hg.incoming(ui, repo, source, opts)
2384 ret = hg.incoming(ui, repo, source, opts)
2385 return ret
2385 return ret
2386
2386
2387 def init(ui, dest=".", **opts):
2387 def init(ui, dest=".", **opts):
2388 """create a new repository in the given directory
2388 """create a new repository in the given directory
2389
2389
2390 Initialize a new repository in the given directory. If the given
2390 Initialize a new repository in the given directory. If the given
2391 directory does not exist, it will be created.
2391 directory does not exist, it will be created.
2392
2392
2393 If no directory is given, the current directory is used.
2393 If no directory is given, the current directory is used.
2394
2394
2395 It is possible to specify an ``ssh://`` URL as the destination.
2395 It is possible to specify an ``ssh://`` URL as the destination.
2396 See :hg:`help urls` for more information.
2396 See :hg:`help urls` for more information.
2397
2397
2398 Returns 0 on success.
2398 Returns 0 on success.
2399 """
2399 """
2400 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2400 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2401
2401
2402 def locate(ui, repo, *pats, **opts):
2402 def locate(ui, repo, *pats, **opts):
2403 """locate files matching specific patterns
2403 """locate files matching specific patterns
2404
2404
2405 Print files under Mercurial control in the working directory whose
2405 Print files under Mercurial control in the working directory whose
2406 names match the given patterns.
2406 names match the given patterns.
2407
2407
2408 By default, this command searches all directories in the working
2408 By default, this command searches all directories in the working
2409 directory. To search just the current directory and its
2409 directory. To search just the current directory and its
2410 subdirectories, use "--include .".
2410 subdirectories, use "--include .".
2411
2411
2412 If no patterns are given to match, this command prints the names
2412 If no patterns are given to match, this command prints the names
2413 of all files under Mercurial control in the working directory.
2413 of all files under Mercurial control in the working directory.
2414
2414
2415 If you want to feed the output of this command into the "xargs"
2415 If you want to feed the output of this command into the "xargs"
2416 command, use the -0 option to both this command and "xargs". This
2416 command, use the -0 option to both this command and "xargs". This
2417 will avoid the problem of "xargs" treating single filenames that
2417 will avoid the problem of "xargs" treating single filenames that
2418 contain whitespace as multiple filenames.
2418 contain whitespace as multiple filenames.
2419
2419
2420 Returns 0 if a match is found, 1 otherwise.
2420 Returns 0 if a match is found, 1 otherwise.
2421 """
2421 """
2422 end = opts.get('print0') and '\0' or '\n'
2422 end = opts.get('print0') and '\0' or '\n'
2423 rev = opts.get('rev') or None
2423 rev = opts.get('rev') or None
2424
2424
2425 ret = 1
2425 ret = 1
2426 m = cmdutil.match(repo, pats, opts, default='relglob')
2426 m = cmdutil.match(repo, pats, opts, default='relglob')
2427 m.bad = lambda x, y: False
2427 m.bad = lambda x, y: False
2428 for abs in repo[rev].walk(m):
2428 for abs in repo[rev].walk(m):
2429 if not rev and abs not in repo.dirstate:
2429 if not rev and abs not in repo.dirstate:
2430 continue
2430 continue
2431 if opts.get('fullpath'):
2431 if opts.get('fullpath'):
2432 ui.write(repo.wjoin(abs), end)
2432 ui.write(repo.wjoin(abs), end)
2433 else:
2433 else:
2434 ui.write(((pats and m.rel(abs)) or abs), end)
2434 ui.write(((pats and m.rel(abs)) or abs), end)
2435 ret = 0
2435 ret = 0
2436
2436
2437 return ret
2437 return ret
2438
2438
2439 def log(ui, repo, *pats, **opts):
2439 def log(ui, repo, *pats, **opts):
2440 """show revision history of entire repository or files
2440 """show revision history of entire repository or files
2441
2441
2442 Print the revision history of the specified files or the entire
2442 Print the revision history of the specified files or the entire
2443 project.
2443 project.
2444
2444
2445 File history is shown without following rename or copy history of
2445 File history is shown without following rename or copy history of
2446 files. Use -f/--follow with a filename to follow history across
2446 files. Use -f/--follow with a filename to follow history across
2447 renames and copies. --follow without a filename will only show
2447 renames and copies. --follow without a filename will only show
2448 ancestors or descendants of the starting revision. --follow-first
2448 ancestors or descendants of the starting revision. --follow-first
2449 only follows the first parent of merge revisions.
2449 only follows the first parent of merge revisions.
2450
2450
2451 If no revision range is specified, the default is ``tip:0`` unless
2451 If no revision range is specified, the default is ``tip:0`` unless
2452 --follow is set, in which case the working directory parent is
2452 --follow is set, in which case the working directory parent is
2453 used as the starting revision. You can specify a revision set for
2453 used as the starting revision. You can specify a revision set for
2454 log, see :hg:`help revsets` for more information.
2454 log, see :hg:`help revsets` for more information.
2455
2455
2456 See :hg:`help dates` for a list of formats valid for -d/--date.
2456 See :hg:`help dates` for a list of formats valid for -d/--date.
2457
2457
2458 By default this command prints revision number and changeset id,
2458 By default this command prints revision number and changeset id,
2459 tags, non-trivial parents, user, date and time, and a summary for
2459 tags, non-trivial parents, user, date and time, and a summary for
2460 each commit. When the -v/--verbose switch is used, the list of
2460 each commit. When the -v/--verbose switch is used, the list of
2461 changed files and full commit message are shown.
2461 changed files and full commit message are shown.
2462
2462
2463 .. note::
2463 .. note::
2464 log -p/--patch may generate unexpected diff output for merge
2464 log -p/--patch may generate unexpected diff output for merge
2465 changesets, as it will only compare the merge changeset against
2465 changesets, as it will only compare the merge changeset against
2466 its first parent. Also, only files different from BOTH parents
2466 its first parent. Also, only files different from BOTH parents
2467 will appear in files:.
2467 will appear in files:.
2468
2468
2469 Returns 0 on success.
2469 Returns 0 on success.
2470 """
2470 """
2471
2471
2472 matchfn = cmdutil.match(repo, pats, opts)
2472 matchfn = cmdutil.match(repo, pats, opts)
2473 limit = cmdutil.loglimit(opts)
2473 limit = cmdutil.loglimit(opts)
2474 count = 0
2474 count = 0
2475
2475
2476 endrev = None
2476 endrev = None
2477 if opts.get('copies') and opts.get('rev'):
2477 if opts.get('copies') and opts.get('rev'):
2478 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2478 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2479
2479
2480 df = False
2480 df = False
2481 if opts["date"]:
2481 if opts["date"]:
2482 df = util.matchdate(opts["date"])
2482 df = util.matchdate(opts["date"])
2483
2483
2484 branches = opts.get('branch', []) + opts.get('only_branch', [])
2484 branches = opts.get('branch', []) + opts.get('only_branch', [])
2485 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2485 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2486
2486
2487 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2487 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2488 def prep(ctx, fns):
2488 def prep(ctx, fns):
2489 rev = ctx.rev()
2489 rev = ctx.rev()
2490 parents = [p for p in repo.changelog.parentrevs(rev)
2490 parents = [p for p in repo.changelog.parentrevs(rev)
2491 if p != nullrev]
2491 if p != nullrev]
2492 if opts.get('no_merges') and len(parents) == 2:
2492 if opts.get('no_merges') and len(parents) == 2:
2493 return
2493 return
2494 if opts.get('only_merges') and len(parents) != 2:
2494 if opts.get('only_merges') and len(parents) != 2:
2495 return
2495 return
2496 if opts.get('branch') and ctx.branch() not in opts['branch']:
2496 if opts.get('branch') and ctx.branch() not in opts['branch']:
2497 return
2497 return
2498 if df and not df(ctx.date()[0]):
2498 if df and not df(ctx.date()[0]):
2499 return
2499 return
2500 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2500 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2501 return
2501 return
2502 if opts.get('keyword'):
2502 if opts.get('keyword'):
2503 for k in [kw.lower() for kw in opts['keyword']]:
2503 for k in [kw.lower() for kw in opts['keyword']]:
2504 if (k in ctx.user().lower() or
2504 if (k in ctx.user().lower() or
2505 k in ctx.description().lower() or
2505 k in ctx.description().lower() or
2506 k in " ".join(ctx.files()).lower()):
2506 k in " ".join(ctx.files()).lower()):
2507 break
2507 break
2508 else:
2508 else:
2509 return
2509 return
2510
2510
2511 copies = None
2511 copies = None
2512 if opts.get('copies') and rev:
2512 if opts.get('copies') and rev:
2513 copies = []
2513 copies = []
2514 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2514 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2515 for fn in ctx.files():
2515 for fn in ctx.files():
2516 rename = getrenamed(fn, rev)
2516 rename = getrenamed(fn, rev)
2517 if rename:
2517 if rename:
2518 copies.append((fn, rename[0]))
2518 copies.append((fn, rename[0]))
2519
2519
2520 revmatchfn = None
2520 revmatchfn = None
2521 if opts.get('patch') or opts.get('stat'):
2521 if opts.get('patch') or opts.get('stat'):
2522 if opts.get('follow') or opts.get('follow_first'):
2522 if opts.get('follow') or opts.get('follow_first'):
2523 # note: this might be wrong when following through merges
2523 # note: this might be wrong when following through merges
2524 revmatchfn = cmdutil.match(repo, fns, default='path')
2524 revmatchfn = cmdutil.match(repo, fns, default='path')
2525 else:
2525 else:
2526 revmatchfn = matchfn
2526 revmatchfn = matchfn
2527
2527
2528 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2528 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2529
2529
2530 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2530 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2531 if count == limit:
2531 if count == limit:
2532 break
2532 break
2533 if displayer.flush(ctx.rev()):
2533 if displayer.flush(ctx.rev()):
2534 count += 1
2534 count += 1
2535 displayer.close()
2535 displayer.close()
2536
2536
2537 def manifest(ui, repo, node=None, rev=None):
2537 def manifest(ui, repo, node=None, rev=None):
2538 """output the current or given revision of the project manifest
2538 """output the current or given revision of the project manifest
2539
2539
2540 Print a list of version controlled files for the given revision.
2540 Print a list of version controlled files for the given revision.
2541 If no revision is given, the first parent of the working directory
2541 If no revision is given, the first parent of the working directory
2542 is used, or the null revision if no revision is checked out.
2542 is used, or the null revision if no revision is checked out.
2543
2543
2544 With -v, print file permissions, symlink and executable bits.
2544 With -v, print file permissions, symlink and executable bits.
2545 With --debug, print file revision hashes.
2545 With --debug, print file revision hashes.
2546
2546
2547 Returns 0 on success.
2547 Returns 0 on success.
2548 """
2548 """
2549
2549
2550 if rev and node:
2550 if rev and node:
2551 raise util.Abort(_("please specify just one revision"))
2551 raise util.Abort(_("please specify just one revision"))
2552
2552
2553 if not node:
2553 if not node:
2554 node = rev
2554 node = rev
2555
2555
2556 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2556 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2557 ctx = repo[node]
2557 ctx = repo[node]
2558 for f in ctx:
2558 for f in ctx:
2559 if ui.debugflag:
2559 if ui.debugflag:
2560 ui.write("%40s " % hex(ctx.manifest()[f]))
2560 ui.write("%40s " % hex(ctx.manifest()[f]))
2561 if ui.verbose:
2561 if ui.verbose:
2562 ui.write(decor[ctx.flags(f)])
2562 ui.write(decor[ctx.flags(f)])
2563 ui.write("%s\n" % f)
2563 ui.write("%s\n" % f)
2564
2564
2565 def merge(ui, repo, node=None, **opts):
2565 def merge(ui, repo, node=None, **opts):
2566 """merge working directory with another revision
2566 """merge working directory with another revision
2567
2567
2568 The current working directory is updated with all changes made in
2568 The current working directory is updated with all changes made in
2569 the requested revision since the last common predecessor revision.
2569 the requested revision since the last common predecessor revision.
2570
2570
2571 Files that changed between either parent are marked as changed for
2571 Files that changed between either parent are marked as changed for
2572 the next commit and a commit must be performed before any further
2572 the next commit and a commit must be performed before any further
2573 updates to the repository are allowed. The next commit will have
2573 updates to the repository are allowed. The next commit will have
2574 two parents.
2574 two parents.
2575
2575
2576 ``--tool`` can be used to specify the merge tool used for file
2576 ``--tool`` can be used to specify the merge tool used for file
2577 merges. It overrides the HGMERGE environment variable and your
2577 merges. It overrides the HGMERGE environment variable and your
2578 configuration files.
2578 configuration files.
2579
2579
2580 If no revision is specified, the working directory's parent is a
2580 If no revision is specified, the working directory's parent is a
2581 head revision, and the current branch contains exactly one other
2581 head revision, and the current branch contains exactly one other
2582 head, the other head is merged with by default. Otherwise, an
2582 head, the other head is merged with by default. Otherwise, an
2583 explicit revision with which to merge with must be provided.
2583 explicit revision with which to merge with must be provided.
2584
2584
2585 :hg:`resolve` must be used to resolve unresolved files.
2585 :hg:`resolve` must be used to resolve unresolved files.
2586
2586
2587 To undo an uncommitted merge, use :hg:`update --clean .` which
2587 To undo an uncommitted merge, use :hg:`update --clean .` which
2588 will check out a clean copy of the original merge parent, losing
2588 will check out a clean copy of the original merge parent, losing
2589 all changes.
2589 all changes.
2590
2590
2591 Returns 0 on success, 1 if there are unresolved files.
2591 Returns 0 on success, 1 if there are unresolved files.
2592 """
2592 """
2593
2593
2594 if opts.get('rev') and node:
2594 if opts.get('rev') and node:
2595 raise util.Abort(_("please specify just one revision"))
2595 raise util.Abort(_("please specify just one revision"))
2596 if not node:
2596 if not node:
2597 node = opts.get('rev')
2597 node = opts.get('rev')
2598
2598
2599 if not node:
2599 if not node:
2600 branch = repo.changectx(None).branch()
2600 branch = repo.changectx(None).branch()
2601 bheads = repo.branchheads(branch)
2601 bheads = repo.branchheads(branch)
2602 if len(bheads) > 2:
2602 if len(bheads) > 2:
2603 raise util.Abort(_(
2603 raise util.Abort(_(
2604 'branch \'%s\' has %d heads - '
2604 'branch \'%s\' has %d heads - '
2605 'please merge with an explicit rev\n'
2605 'please merge with an explicit rev\n'
2606 '(run \'hg heads .\' to see heads)')
2606 '(run \'hg heads .\' to see heads)')
2607 % (branch, len(bheads)))
2607 % (branch, len(bheads)))
2608
2608
2609 parent = repo.dirstate.parents()[0]
2609 parent = repo.dirstate.parents()[0]
2610 if len(bheads) == 1:
2610 if len(bheads) == 1:
2611 if len(repo.heads()) > 1:
2611 if len(repo.heads()) > 1:
2612 raise util.Abort(_(
2612 raise util.Abort(_(
2613 'branch \'%s\' has one head - '
2613 'branch \'%s\' has one head - '
2614 'please merge with an explicit rev\n'
2614 'please merge with an explicit rev\n'
2615 '(run \'hg heads\' to see all heads)')
2615 '(run \'hg heads\' to see all heads)')
2616 % branch)
2616 % branch)
2617 msg = _('there is nothing to merge')
2617 msg = _('there is nothing to merge')
2618 if parent != repo.lookup(repo[None].branch()):
2618 if parent != repo.lookup(repo[None].branch()):
2619 msg = _('%s - use "hg update" instead') % msg
2619 msg = _('%s - use "hg update" instead') % msg
2620 raise util.Abort(msg)
2620 raise util.Abort(msg)
2621
2621
2622 if parent not in bheads:
2622 if parent not in bheads:
2623 raise util.Abort(_('working dir not at a head rev - '
2623 raise util.Abort(_('working dir not at a head rev - '
2624 'use "hg update" or merge with an explicit rev'))
2624 'use "hg update" or merge with an explicit rev'))
2625 node = parent == bheads[0] and bheads[-1] or bheads[0]
2625 node = parent == bheads[0] and bheads[-1] or bheads[0]
2626
2626
2627 if opts.get('preview'):
2627 if opts.get('preview'):
2628 # find nodes that are ancestors of p2 but not of p1
2628 # find nodes that are ancestors of p2 but not of p1
2629 p1 = repo.lookup('.')
2629 p1 = repo.lookup('.')
2630 p2 = repo.lookup(node)
2630 p2 = repo.lookup(node)
2631 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2631 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2632
2632
2633 displayer = cmdutil.show_changeset(ui, repo, opts)
2633 displayer = cmdutil.show_changeset(ui, repo, opts)
2634 for node in nodes:
2634 for node in nodes:
2635 displayer.show(repo[node])
2635 displayer.show(repo[node])
2636 displayer.close()
2636 displayer.close()
2637 return 0
2637 return 0
2638
2638
2639 try:
2639 try:
2640 # ui.forcemerge is an internal variable, do not document
2640 # ui.forcemerge is an internal variable, do not document
2641 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2641 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2642 return hg.merge(repo, node, force=opts.get('force'))
2642 return hg.merge(repo, node, force=opts.get('force'))
2643 finally:
2643 finally:
2644 ui.setconfig('ui', 'forcemerge', '')
2644 ui.setconfig('ui', 'forcemerge', '')
2645
2645
2646 def outgoing(ui, repo, dest=None, **opts):
2646 def outgoing(ui, repo, dest=None, **opts):
2647 """show changesets not found in the destination
2647 """show changesets not found in the destination
2648
2648
2649 Show changesets not found in the specified destination repository
2649 Show changesets not found in the specified destination repository
2650 or the default push location. These are the changesets that would
2650 or the default push location. These are the changesets that would
2651 be pushed if a push was requested.
2651 be pushed if a push was requested.
2652
2652
2653 See pull for details of valid destination formats.
2653 See pull for details of valid destination formats.
2654
2654
2655 Returns 0 if there are outgoing changes, 1 otherwise.
2655 Returns 0 if there are outgoing changes, 1 otherwise.
2656 """
2656 """
2657 ret = hg.outgoing(ui, repo, dest, opts)
2657 ret = hg.outgoing(ui, repo, dest, opts)
2658 return ret
2658 return ret
2659
2659
2660 def parents(ui, repo, file_=None, **opts):
2660 def parents(ui, repo, file_=None, **opts):
2661 """show the parents of the working directory or revision
2661 """show the parents of the working directory or revision
2662
2662
2663 Print the working directory's parent revisions. If a revision is
2663 Print the working directory's parent revisions. If a revision is
2664 given via -r/--rev, the parent of that revision will be printed.
2664 given via -r/--rev, the parent of that revision will be printed.
2665 If a file argument is given, the revision in which the file was
2665 If a file argument is given, the revision in which the file was
2666 last changed (before the working directory revision or the
2666 last changed (before the working directory revision or the
2667 argument to --rev if given) is printed.
2667 argument to --rev if given) is printed.
2668
2668
2669 Returns 0 on success.
2669 Returns 0 on success.
2670 """
2670 """
2671 rev = opts.get('rev')
2671 rev = opts.get('rev')
2672 if rev:
2672 if rev:
2673 ctx = repo[rev]
2673 ctx = repo[rev]
2674 else:
2674 else:
2675 ctx = repo[None]
2675 ctx = repo[None]
2676
2676
2677 if file_:
2677 if file_:
2678 m = cmdutil.match(repo, (file_,), opts)
2678 m = cmdutil.match(repo, (file_,), opts)
2679 if m.anypats() or len(m.files()) != 1:
2679 if m.anypats() or len(m.files()) != 1:
2680 raise util.Abort(_('can only specify an explicit filename'))
2680 raise util.Abort(_('can only specify an explicit filename'))
2681 file_ = m.files()[0]
2681 file_ = m.files()[0]
2682 filenodes = []
2682 filenodes = []
2683 for cp in ctx.parents():
2683 for cp in ctx.parents():
2684 if not cp:
2684 if not cp:
2685 continue
2685 continue
2686 try:
2686 try:
2687 filenodes.append(cp.filenode(file_))
2687 filenodes.append(cp.filenode(file_))
2688 except error.LookupError:
2688 except error.LookupError:
2689 pass
2689 pass
2690 if not filenodes:
2690 if not filenodes:
2691 raise util.Abort(_("'%s' not found in manifest!") % file_)
2691 raise util.Abort(_("'%s' not found in manifest!") % file_)
2692 fl = repo.file(file_)
2692 fl = repo.file(file_)
2693 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2693 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2694 else:
2694 else:
2695 p = [cp.node() for cp in ctx.parents()]
2695 p = [cp.node() for cp in ctx.parents()]
2696
2696
2697 displayer = cmdutil.show_changeset(ui, repo, opts)
2697 displayer = cmdutil.show_changeset(ui, repo, opts)
2698 for n in p:
2698 for n in p:
2699 if n != nullid:
2699 if n != nullid:
2700 displayer.show(repo[n])
2700 displayer.show(repo[n])
2701 displayer.close()
2701 displayer.close()
2702
2702
2703 def paths(ui, repo, search=None):
2703 def paths(ui, repo, search=None):
2704 """show aliases for remote repositories
2704 """show aliases for remote repositories
2705
2705
2706 Show definition of symbolic path name NAME. If no name is given,
2706 Show definition of symbolic path name NAME. If no name is given,
2707 show definition of all available names.
2707 show definition of all available names.
2708
2708
2709 Path names are defined in the [paths] section of your
2709 Path names are defined in the [paths] section of your
2710 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2710 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2711 repository, ``.hg/hgrc`` is used, too.
2711 repository, ``.hg/hgrc`` is used, too.
2712
2712
2713 The path names ``default`` and ``default-push`` have a special
2713 The path names ``default`` and ``default-push`` have a special
2714 meaning. When performing a push or pull operation, they are used
2714 meaning. When performing a push or pull operation, they are used
2715 as fallbacks if no location is specified on the command-line.
2715 as fallbacks if no location is specified on the command-line.
2716 When ``default-push`` is set, it will be used for push and
2716 When ``default-push`` is set, it will be used for push and
2717 ``default`` will be used for pull; otherwise ``default`` is used
2717 ``default`` will be used for pull; otherwise ``default`` is used
2718 as the fallback for both. When cloning a repository, the clone
2718 as the fallback for both. When cloning a repository, the clone
2719 source is written as ``default`` in ``.hg/hgrc``. Note that
2719 source is written as ``default`` in ``.hg/hgrc``. Note that
2720 ``default`` and ``default-push`` apply to all inbound (e.g.
2720 ``default`` and ``default-push`` apply to all inbound (e.g.
2721 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2721 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2722 :hg:`bundle`) operations.
2722 :hg:`bundle`) operations.
2723
2723
2724 See :hg:`help urls` for more information.
2724 See :hg:`help urls` for more information.
2725
2725
2726 Returns 0 on success.
2726 Returns 0 on success.
2727 """
2727 """
2728 if search:
2728 if search:
2729 for name, path in ui.configitems("paths"):
2729 for name, path in ui.configitems("paths"):
2730 if name == search:
2730 if name == search:
2731 ui.write("%s\n" % url.hidepassword(path))
2731 ui.write("%s\n" % url.hidepassword(path))
2732 return
2732 return
2733 ui.warn(_("not found!\n"))
2733 ui.warn(_("not found!\n"))
2734 return 1
2734 return 1
2735 else:
2735 else:
2736 for name, path in ui.configitems("paths"):
2736 for name, path in ui.configitems("paths"):
2737 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2737 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2738
2738
2739 def postincoming(ui, repo, modheads, optupdate, checkout):
2739 def postincoming(ui, repo, modheads, optupdate, checkout):
2740 if modheads == 0:
2740 if modheads == 0:
2741 return
2741 return
2742 if optupdate:
2742 if optupdate:
2743 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2743 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2744 return hg.update(repo, checkout)
2744 return hg.update(repo, checkout)
2745 else:
2745 else:
2746 ui.status(_("not updating, since new heads added\n"))
2746 ui.status(_("not updating, since new heads added\n"))
2747 if modheads > 1:
2747 if modheads > 1:
2748 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2748 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2749 else:
2749 else:
2750 ui.status(_("(run 'hg update' to get a working copy)\n"))
2750 ui.status(_("(run 'hg update' to get a working copy)\n"))
2751
2751
2752 def pull(ui, repo, source="default", **opts):
2752 def pull(ui, repo, source="default", **opts):
2753 """pull changes from the specified source
2753 """pull changes from the specified source
2754
2754
2755 Pull changes from a remote repository to a local one.
2755 Pull changes from a remote repository to a local one.
2756
2756
2757 This finds all changes from the repository at the specified path
2757 This finds all changes from the repository at the specified path
2758 or URL and adds them to a local repository (the current one unless
2758 or URL and adds them to a local repository (the current one unless
2759 -R is specified). By default, this does not update the copy of the
2759 -R is specified). By default, this does not update the copy of the
2760 project in the working directory.
2760 project in the working directory.
2761
2761
2762 Use :hg:`incoming` if you want to see what would have been added
2762 Use :hg:`incoming` if you want to see what would have been added
2763 by a pull at the time you issued this command. If you then decide
2763 by a pull at the time you issued this command. If you then decide
2764 to add those changes to the repository, you should use :hg:`pull
2764 to add those changes to the repository, you should use :hg:`pull
2765 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2765 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2766
2766
2767 If SOURCE is omitted, the 'default' path will be used.
2767 If SOURCE is omitted, the 'default' path will be used.
2768 See :hg:`help urls` for more information.
2768 See :hg:`help urls` for more information.
2769
2769
2770 Returns 0 on success, 1 if an update had unresolved files.
2770 Returns 0 on success, 1 if an update had unresolved files.
2771 """
2771 """
2772 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2772 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2773 other = hg.repository(hg.remoteui(repo, opts), source)
2773 other = hg.repository(hg.remoteui(repo, opts), source)
2774 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2774 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2775 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2775 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2776 if revs:
2776 if revs:
2777 try:
2777 try:
2778 revs = [other.lookup(rev) for rev in revs]
2778 revs = [other.lookup(rev) for rev in revs]
2779 except error.CapabilityError:
2779 except error.CapabilityError:
2780 err = _("other repository doesn't support revision lookup, "
2780 err = _("other repository doesn't support revision lookup, "
2781 "so a rev cannot be specified.")
2781 "so a rev cannot be specified.")
2782 raise util.Abort(err)
2782 raise util.Abort(err)
2783
2783
2784 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2784 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2785 if checkout:
2785 if checkout:
2786 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2786 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2787 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2787 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2788
2788
2789 def push(ui, repo, dest=None, **opts):
2789 def push(ui, repo, dest=None, **opts):
2790 """push changes to the specified destination
2790 """push changes to the specified destination
2791
2791
2792 Push changesets from the local repository to the specified
2792 Push changesets from the local repository to the specified
2793 destination.
2793 destination.
2794
2794
2795 This operation is symmetrical to pull: it is identical to a pull
2795 This operation is symmetrical to pull: it is identical to a pull
2796 in the destination repository from the current one.
2796 in the destination repository from the current one.
2797
2797
2798 By default, push will not allow creation of new heads at the
2798 By default, push will not allow creation of new heads at the
2799 destination, since multiple heads would make it unclear which head
2799 destination, since multiple heads would make it unclear which head
2800 to use. In this situation, it is recommended to pull and merge
2800 to use. In this situation, it is recommended to pull and merge
2801 before pushing.
2801 before pushing.
2802
2802
2803 Use --new-branch if you want to allow push to create a new named
2803 Use --new-branch if you want to allow push to create a new named
2804 branch that is not present at the destination. This allows you to
2804 branch that is not present at the destination. This allows you to
2805 only create a new branch without forcing other changes.
2805 only create a new branch without forcing other changes.
2806
2806
2807 Use -f/--force to override the default behavior and push all
2807 Use -f/--force to override the default behavior and push all
2808 changesets on all branches.
2808 changesets on all branches.
2809
2809
2810 If -r/--rev is used, the specified revision and all its ancestors
2810 If -r/--rev is used, the specified revision and all its ancestors
2811 will be pushed to the remote repository.
2811 will be pushed to the remote repository.
2812
2812
2813 Please see :hg:`help urls` for important details about ``ssh://``
2813 Please see :hg:`help urls` for important details about ``ssh://``
2814 URLs. If DESTINATION is omitted, a default path will be used.
2814 URLs. If DESTINATION is omitted, a default path will be used.
2815
2815
2816 Returns 0 if push was successful, 1 if nothing to push.
2816 Returns 0 if push was successful, 1 if nothing to push.
2817 """
2817 """
2818 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2818 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2819 dest, branches = hg.parseurl(dest, opts.get('branch'))
2819 dest, branches = hg.parseurl(dest, opts.get('branch'))
2820 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2820 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2821 other = hg.repository(hg.remoteui(repo, opts), dest)
2821 other = hg.repository(hg.remoteui(repo, opts), dest)
2822 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2822 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2823 if revs:
2823 if revs:
2824 revs = [repo.lookup(rev) for rev in revs]
2824 revs = [repo.lookup(rev) for rev in revs]
2825
2825
2826 # push subrepos depth-first for coherent ordering
2826 # push subrepos depth-first for coherent ordering
2827 c = repo['']
2827 c = repo['']
2828 subs = c.substate # only repos that are committed
2828 subs = c.substate # only repos that are committed
2829 for s in sorted(subs):
2829 for s in sorted(subs):
2830 if not c.sub(s).push(opts.get('force')):
2830 if not c.sub(s).push(opts.get('force')):
2831 return False
2831 return False
2832
2832
2833 r = repo.push(other, opts.get('force'), revs=revs,
2833 r = repo.push(other, opts.get('force'), revs=revs,
2834 newbranch=opts.get('new_branch'))
2834 newbranch=opts.get('new_branch'))
2835 return r == 0
2835 return r == 0
2836
2836
2837 def recover(ui, repo):
2837 def recover(ui, repo):
2838 """roll back an interrupted transaction
2838 """roll back an interrupted transaction
2839
2839
2840 Recover from an interrupted commit or pull.
2840 Recover from an interrupted commit or pull.
2841
2841
2842 This command tries to fix the repository status after an
2842 This command tries to fix the repository status after an
2843 interrupted operation. It should only be necessary when Mercurial
2843 interrupted operation. It should only be necessary when Mercurial
2844 suggests it.
2844 suggests it.
2845
2845
2846 Returns 0 if successful, 1 if nothing to recover or verify fails.
2846 Returns 0 if successful, 1 if nothing to recover or verify fails.
2847 """
2847 """
2848 if repo.recover():
2848 if repo.recover():
2849 return hg.verify(repo)
2849 return hg.verify(repo)
2850 return 1
2850 return 1
2851
2851
2852 def remove(ui, repo, *pats, **opts):
2852 def remove(ui, repo, *pats, **opts):
2853 """remove the specified files on the next commit
2853 """remove the specified files on the next commit
2854
2854
2855 Schedule the indicated files for removal from the repository.
2855 Schedule the indicated files for removal from the repository.
2856
2856
2857 This only removes files from the current branch, not from the
2857 This only removes files from the current branch, not from the
2858 entire project history. -A/--after can be used to remove only
2858 entire project history. -A/--after can be used to remove only
2859 files that have already been deleted, -f/--force can be used to
2859 files that have already been deleted, -f/--force can be used to
2860 force deletion, and -Af can be used to remove files from the next
2860 force deletion, and -Af can be used to remove files from the next
2861 revision without deleting them from the working directory.
2861 revision without deleting them from the working directory.
2862
2862
2863 The following table details the behavior of remove for different
2863 The following table details the behavior of remove for different
2864 file states (columns) and option combinations (rows). The file
2864 file states (columns) and option combinations (rows). The file
2865 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2865 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2866 reported by :hg:`status`). The actions are Warn, Remove (from
2866 reported by :hg:`status`). The actions are Warn, Remove (from
2867 branch) and Delete (from disk)::
2867 branch) and Delete (from disk)::
2868
2868
2869 A C M !
2869 A C M !
2870 none W RD W R
2870 none W RD W R
2871 -f R RD RD R
2871 -f R RD RD R
2872 -A W W W R
2872 -A W W W R
2873 -Af R R R R
2873 -Af R R R R
2874
2874
2875 This command schedules the files to be removed at the next commit.
2875 This command schedules the files to be removed at the next commit.
2876 To undo a remove before that, see :hg:`revert`.
2876 To undo a remove before that, see :hg:`revert`.
2877
2877
2878 Returns 0 on success, 1 if any warnings encountered.
2878 Returns 0 on success, 1 if any warnings encountered.
2879 """
2879 """
2880
2880
2881 ret = 0
2881 ret = 0
2882 after, force = opts.get('after'), opts.get('force')
2882 after, force = opts.get('after'), opts.get('force')
2883 if not pats and not after:
2883 if not pats and not after:
2884 raise util.Abort(_('no files specified'))
2884 raise util.Abort(_('no files specified'))
2885
2885
2886 m = cmdutil.match(repo, pats, opts)
2886 m = cmdutil.match(repo, pats, opts)
2887 s = repo.status(match=m, clean=True)
2887 s = repo.status(match=m, clean=True)
2888 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2888 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2889
2889
2890 for f in m.files():
2890 for f in m.files():
2891 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2891 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2892 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2892 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2893 ret = 1
2893 ret = 1
2894
2894
2895 if force:
2895 if force:
2896 remove, forget = modified + deleted + clean, added
2896 remove, forget = modified + deleted + clean, added
2897 elif after:
2897 elif after:
2898 remove, forget = deleted, []
2898 remove, forget = deleted, []
2899 for f in modified + added + clean:
2899 for f in modified + added + clean:
2900 ui.warn(_('not removing %s: file still exists (use -f'
2900 ui.warn(_('not removing %s: file still exists (use -f'
2901 ' to force removal)\n') % m.rel(f))
2901 ' to force removal)\n') % m.rel(f))
2902 ret = 1
2902 ret = 1
2903 else:
2903 else:
2904 remove, forget = deleted + clean, []
2904 remove, forget = deleted + clean, []
2905 for f in modified:
2905 for f in modified:
2906 ui.warn(_('not removing %s: file is modified (use -f'
2906 ui.warn(_('not removing %s: file is modified (use -f'
2907 ' to force removal)\n') % m.rel(f))
2907 ' to force removal)\n') % m.rel(f))
2908 ret = 1
2908 ret = 1
2909 for f in added:
2909 for f in added:
2910 ui.warn(_('not removing %s: file has been marked for add (use -f'
2910 ui.warn(_('not removing %s: file has been marked for add (use -f'
2911 ' to force removal)\n') % m.rel(f))
2911 ' to force removal)\n') % m.rel(f))
2912 ret = 1
2912 ret = 1
2913
2913
2914 for f in sorted(remove + forget):
2914 for f in sorted(remove + forget):
2915 if ui.verbose or not m.exact(f):
2915 if ui.verbose or not m.exact(f):
2916 ui.status(_('removing %s\n') % m.rel(f))
2916 ui.status(_('removing %s\n') % m.rel(f))
2917
2917
2918 repo[None].forget(forget)
2918 repo[None].forget(forget)
2919 repo[None].remove(remove, unlink=not after)
2919 repo[None].remove(remove, unlink=not after)
2920 return ret
2920 return ret
2921
2921
2922 def rename(ui, repo, *pats, **opts):
2922 def rename(ui, repo, *pats, **opts):
2923 """rename files; equivalent of copy + remove
2923 """rename files; equivalent of copy + remove
2924
2924
2925 Mark dest as copies of sources; mark sources for deletion. If dest
2925 Mark dest as copies of sources; mark sources for deletion. If dest
2926 is a directory, copies are put in that directory. If dest is a
2926 is a directory, copies are put in that directory. If dest is a
2927 file, there can only be one source.
2927 file, there can only be one source.
2928
2928
2929 By default, this command copies the contents of files as they
2929 By default, this command copies the contents of files as they
2930 exist in the working directory. If invoked with -A/--after, the
2930 exist in the working directory. If invoked with -A/--after, the
2931 operation is recorded, but no copying is performed.
2931 operation is recorded, but no copying is performed.
2932
2932
2933 This command takes effect at the next commit. To undo a rename
2933 This command takes effect at the next commit. To undo a rename
2934 before that, see :hg:`revert`.
2934 before that, see :hg:`revert`.
2935
2935
2936 Returns 0 on success, 1 if errors are encountered.
2936 Returns 0 on success, 1 if errors are encountered.
2937 """
2937 """
2938 wlock = repo.wlock(False)
2938 wlock = repo.wlock(False)
2939 try:
2939 try:
2940 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2940 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2941 finally:
2941 finally:
2942 wlock.release()
2942 wlock.release()
2943
2943
2944 def resolve(ui, repo, *pats, **opts):
2944 def resolve(ui, repo, *pats, **opts):
2945 """redo merges or set/view the merge status of files
2945 """redo merges or set/view the merge status of files
2946
2946
2947 Merges with unresolved conflicts are often the result of
2947 Merges with unresolved conflicts are often the result of
2948 non-interactive merging using the ``internal:merge`` configuration
2948 non-interactive merging using the ``internal:merge`` configuration
2949 setting, or a command-line merge tool like ``diff3``. The resolve
2949 setting, or a command-line merge tool like ``diff3``. The resolve
2950 command is used to manage the files involved in a merge, after
2950 command is used to manage the files involved in a merge, after
2951 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2951 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2952 working directory must have two parents).
2952 working directory must have two parents).
2953
2953
2954 The resolve command can be used in the following ways:
2954 The resolve command can be used in the following ways:
2955
2955
2956 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2956 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2957 files, discarding any previous merge attempts. Re-merging is not
2957 files, discarding any previous merge attempts. Re-merging is not
2958 performed for files already marked as resolved. Use ``--all/-a``
2958 performed for files already marked as resolved. Use ``--all/-a``
2959 to selects all unresolved files. ``--tool`` can be used to specify
2959 to selects all unresolved files. ``--tool`` can be used to specify
2960 the merge tool used for the given files. It overrides the HGMERGE
2960 the merge tool used for the given files. It overrides the HGMERGE
2961 environment variable and your configuration files.
2961 environment variable and your configuration files.
2962
2962
2963 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2963 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2964 (e.g. after having manually fixed-up the files). The default is
2964 (e.g. after having manually fixed-up the files). The default is
2965 to mark all unresolved files.
2965 to mark all unresolved files.
2966
2966
2967 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2967 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2968 default is to mark all resolved files.
2968 default is to mark all resolved files.
2969
2969
2970 - :hg:`resolve -l`: list files which had or still have conflicts.
2970 - :hg:`resolve -l`: list files which had or still have conflicts.
2971 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2971 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2972
2972
2973 Note that Mercurial will not let you commit files with unresolved
2973 Note that Mercurial will not let you commit files with unresolved
2974 merge conflicts. You must use :hg:`resolve -m ...` before you can
2974 merge conflicts. You must use :hg:`resolve -m ...` before you can
2975 commit after a conflicting merge.
2975 commit after a conflicting merge.
2976
2976
2977 Returns 0 on success, 1 if any files fail a resolve attempt.
2977 Returns 0 on success, 1 if any files fail a resolve attempt.
2978 """
2978 """
2979
2979
2980 all, mark, unmark, show, nostatus = \
2980 all, mark, unmark, show, nostatus = \
2981 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2981 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2982
2982
2983 if (show and (mark or unmark)) or (mark and unmark):
2983 if (show and (mark or unmark)) or (mark and unmark):
2984 raise util.Abort(_("too many options specified"))
2984 raise util.Abort(_("too many options specified"))
2985 if pats and all:
2985 if pats and all:
2986 raise util.Abort(_("can't specify --all and patterns"))
2986 raise util.Abort(_("can't specify --all and patterns"))
2987 if not (all or pats or show or mark or unmark):
2987 if not (all or pats or show or mark or unmark):
2988 raise util.Abort(_('no files or directories specified; '
2988 raise util.Abort(_('no files or directories specified; '
2989 'use --all to remerge all files'))
2989 'use --all to remerge all files'))
2990
2990
2991 ms = mergemod.mergestate(repo)
2991 ms = mergemod.mergestate(repo)
2992 m = cmdutil.match(repo, pats, opts)
2992 m = cmdutil.match(repo, pats, opts)
2993 ret = 0
2993 ret = 0
2994
2994
2995 for f in ms:
2995 for f in ms:
2996 if m(f):
2996 if m(f):
2997 if show:
2997 if show:
2998 if nostatus:
2998 if nostatus:
2999 ui.write("%s\n" % f)
2999 ui.write("%s\n" % f)
3000 else:
3000 else:
3001 ui.write("%s %s\n" % (ms[f].upper(), f),
3001 ui.write("%s %s\n" % (ms[f].upper(), f),
3002 label='resolve.' +
3002 label='resolve.' +
3003 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3003 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3004 elif mark:
3004 elif mark:
3005 ms.mark(f, "r")
3005 ms.mark(f, "r")
3006 elif unmark:
3006 elif unmark:
3007 ms.mark(f, "u")
3007 ms.mark(f, "u")
3008 else:
3008 else:
3009 wctx = repo[None]
3009 wctx = repo[None]
3010 mctx = wctx.parents()[-1]
3010 mctx = wctx.parents()[-1]
3011
3011
3012 # backup pre-resolve (merge uses .orig for its own purposes)
3012 # backup pre-resolve (merge uses .orig for its own purposes)
3013 a = repo.wjoin(f)
3013 a = repo.wjoin(f)
3014 util.copyfile(a, a + ".resolve")
3014 util.copyfile(a, a + ".resolve")
3015
3015
3016 try:
3016 try:
3017 # resolve file
3017 # resolve file
3018 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3018 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3019 if ms.resolve(f, wctx, mctx):
3019 if ms.resolve(f, wctx, mctx):
3020 ret = 1
3020 ret = 1
3021 finally:
3021 finally:
3022 ui.setconfig('ui', 'forcemerge', '')
3022 ui.setconfig('ui', 'forcemerge', '')
3023
3023
3024 # replace filemerge's .orig file with our resolve file
3024 # replace filemerge's .orig file with our resolve file
3025 util.rename(a + ".resolve", a + ".orig")
3025 util.rename(a + ".resolve", a + ".orig")
3026
3026
3027 ms.commit()
3027 ms.commit()
3028 return ret
3028 return ret
3029
3029
3030 def revert(ui, repo, *pats, **opts):
3030 def revert(ui, repo, *pats, **opts):
3031 """restore individual files or directories to an earlier state
3031 """restore individual files or directories to an earlier state
3032
3032
3033 .. note::
3033 .. note::
3034 This command is most likely not what you are looking for.
3034 This command is most likely not what you are looking for.
3035 Revert will partially overwrite content in the working
3035 Revert will partially overwrite content in the working
3036 directory without changing the working directory parents. Use
3036 directory without changing the working directory parents. Use
3037 :hg:`update -r rev` to check out earlier revisions, or
3037 :hg:`update -r rev` to check out earlier revisions, or
3038 :hg:`update --clean .` to undo a merge which has added another
3038 :hg:`update --clean .` to undo a merge which has added another
3039 parent.
3039 parent.
3040
3040
3041 With no revision specified, revert the named files or directories
3041 With no revision specified, revert the named files or directories
3042 to the contents they had in the parent of the working directory.
3042 to the contents they had in the parent of the working directory.
3043 This restores the contents of the affected files to an unmodified
3043 This restores the contents of the affected files to an unmodified
3044 state and unschedules adds, removes, copies, and renames. If the
3044 state and unschedules adds, removes, copies, and renames. If the
3045 working directory has two parents, you must explicitly specify a
3045 working directory has two parents, you must explicitly specify a
3046 revision.
3046 revision.
3047
3047
3048 Using the -r/--rev option, revert the given files or directories
3048 Using the -r/--rev option, revert the given files or directories
3049 to their contents as of a specific revision. This can be helpful
3049 to their contents as of a specific revision. This can be helpful
3050 to "roll back" some or all of an earlier change. See :hg:`help
3050 to "roll back" some or all of an earlier change. See :hg:`help
3051 dates` for a list of formats valid for -d/--date.
3051 dates` for a list of formats valid for -d/--date.
3052
3052
3053 Revert modifies the working directory. It does not commit any
3053 Revert modifies the working directory. It does not commit any
3054 changes, or change the parent of the working directory. If you
3054 changes, or change the parent of the working directory. If you
3055 revert to a revision other than the parent of the working
3055 revert to a revision other than the parent of the working
3056 directory, the reverted files will thus appear modified
3056 directory, the reverted files will thus appear modified
3057 afterwards.
3057 afterwards.
3058
3058
3059 If a file has been deleted, it is restored. If the executable mode
3059 If a file has been deleted, it is restored. If the executable mode
3060 of a file was changed, it is reset.
3060 of a file was changed, it is reset.
3061
3061
3062 If names are given, all files matching the names are reverted.
3062 If names are given, all files matching the names are reverted.
3063 If no arguments are given, no files are reverted.
3063 If no arguments are given, no files are reverted.
3064
3064
3065 Modified files are saved with a .orig suffix before reverting.
3065 Modified files are saved with a .orig suffix before reverting.
3066 To disable these backups, use --no-backup.
3066 To disable these backups, use --no-backup.
3067
3067
3068 Returns 0 on success.
3068 Returns 0 on success.
3069 """
3069 """
3070
3070
3071 if opts.get("date"):
3071 if opts.get("date"):
3072 if opts.get("rev"):
3072 if opts.get("rev"):
3073 raise util.Abort(_("you can't specify a revision and a date"))
3073 raise util.Abort(_("you can't specify a revision and a date"))
3074 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3074 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3075
3075
3076 if not pats and not opts.get('all'):
3076 if not pats and not opts.get('all'):
3077 raise util.Abort(_('no files or directories specified; '
3077 raise util.Abort(_('no files or directories specified; '
3078 'use --all to revert the whole repo'))
3078 'use --all to revert the whole repo'))
3079
3079
3080 parent, p2 = repo.dirstate.parents()
3080 parent, p2 = repo.dirstate.parents()
3081 if not opts.get('rev') and p2 != nullid:
3081 if not opts.get('rev') and p2 != nullid:
3082 raise util.Abort(_('uncommitted merge - please provide a '
3082 raise util.Abort(_('uncommitted merge - please provide a '
3083 'specific revision'))
3083 'specific revision'))
3084 ctx = repo[opts.get('rev')]
3084 ctx = repo[opts.get('rev')]
3085 node = ctx.node()
3085 node = ctx.node()
3086 mf = ctx.manifest()
3086 mf = ctx.manifest()
3087 if node == parent:
3087 if node == parent:
3088 pmf = mf
3088 pmf = mf
3089 else:
3089 else:
3090 pmf = None
3090 pmf = None
3091
3091
3092 # need all matching names in dirstate and manifest of target rev,
3092 # need all matching names in dirstate and manifest of target rev,
3093 # so have to walk both. do not print errors if files exist in one
3093 # so have to walk both. do not print errors if files exist in one
3094 # but not other.
3094 # but not other.
3095
3095
3096 names = {}
3096 names = {}
3097
3097
3098 wlock = repo.wlock()
3098 wlock = repo.wlock()
3099 try:
3099 try:
3100 # walk dirstate.
3100 # walk dirstate.
3101
3101
3102 m = cmdutil.match(repo, pats, opts)
3102 m = cmdutil.match(repo, pats, opts)
3103 m.bad = lambda x, y: False
3103 m.bad = lambda x, y: False
3104 for abs in repo.walk(m):
3104 for abs in repo.walk(m):
3105 names[abs] = m.rel(abs), m.exact(abs)
3105 names[abs] = m.rel(abs), m.exact(abs)
3106
3106
3107 # walk target manifest.
3107 # walk target manifest.
3108
3108
3109 def badfn(path, msg):
3109 def badfn(path, msg):
3110 if path in names:
3110 if path in names:
3111 return
3111 return
3112 path_ = path + '/'
3112 path_ = path + '/'
3113 for f in names:
3113 for f in names:
3114 if f.startswith(path_):
3114 if f.startswith(path_):
3115 return
3115 return
3116 ui.warn("%s: %s\n" % (m.rel(path), msg))
3116 ui.warn("%s: %s\n" % (m.rel(path), msg))
3117
3117
3118 m = cmdutil.match(repo, pats, opts)
3118 m = cmdutil.match(repo, pats, opts)
3119 m.bad = badfn
3119 m.bad = badfn
3120 for abs in repo[node].walk(m):
3120 for abs in repo[node].walk(m):
3121 if abs not in names:
3121 if abs not in names:
3122 names[abs] = m.rel(abs), m.exact(abs)
3122 names[abs] = m.rel(abs), m.exact(abs)
3123
3123
3124 m = cmdutil.matchfiles(repo, names)
3124 m = cmdutil.matchfiles(repo, names)
3125 changes = repo.status(match=m)[:4]
3125 changes = repo.status(match=m)[:4]
3126 modified, added, removed, deleted = map(set, changes)
3126 modified, added, removed, deleted = map(set, changes)
3127
3127
3128 # if f is a rename, also revert the source
3128 # if f is a rename, also revert the source
3129 cwd = repo.getcwd()
3129 cwd = repo.getcwd()
3130 for f in added:
3130 for f in added:
3131 src = repo.dirstate.copied(f)
3131 src = repo.dirstate.copied(f)
3132 if src and src not in names and repo.dirstate[src] == 'r':
3132 if src and src not in names and repo.dirstate[src] == 'r':
3133 removed.add(src)
3133 removed.add(src)
3134 names[src] = (repo.pathto(src, cwd), True)
3134 names[src] = (repo.pathto(src, cwd), True)
3135
3135
3136 def removeforget(abs):
3136 def removeforget(abs):
3137 if repo.dirstate[abs] == 'a':
3137 if repo.dirstate[abs] == 'a':
3138 return _('forgetting %s\n')
3138 return _('forgetting %s\n')
3139 return _('removing %s\n')
3139 return _('removing %s\n')
3140
3140
3141 revert = ([], _('reverting %s\n'))
3141 revert = ([], _('reverting %s\n'))
3142 add = ([], _('adding %s\n'))
3142 add = ([], _('adding %s\n'))
3143 remove = ([], removeforget)
3143 remove = ([], removeforget)
3144 undelete = ([], _('undeleting %s\n'))
3144 undelete = ([], _('undeleting %s\n'))
3145
3145
3146 disptable = (
3146 disptable = (
3147 # dispatch table:
3147 # dispatch table:
3148 # file state
3148 # file state
3149 # action if in target manifest
3149 # action if in target manifest
3150 # action if not in target manifest
3150 # action if not in target manifest
3151 # make backup if in target manifest
3151 # make backup if in target manifest
3152 # make backup if not in target manifest
3152 # make backup if not in target manifest
3153 (modified, revert, remove, True, True),
3153 (modified, revert, remove, True, True),
3154 (added, revert, remove, True, False),
3154 (added, revert, remove, True, False),
3155 (removed, undelete, None, False, False),
3155 (removed, undelete, None, False, False),
3156 (deleted, revert, remove, False, False),
3156 (deleted, revert, remove, False, False),
3157 )
3157 )
3158
3158
3159 for abs, (rel, exact) in sorted(names.items()):
3159 for abs, (rel, exact) in sorted(names.items()):
3160 mfentry = mf.get(abs)
3160 mfentry = mf.get(abs)
3161 target = repo.wjoin(abs)
3161 target = repo.wjoin(abs)
3162 def handle(xlist, dobackup):
3162 def handle(xlist, dobackup):
3163 xlist[0].append(abs)
3163 xlist[0].append(abs)
3164 if (dobackup and not opts.get('no_backup') and
3164 if (dobackup and not opts.get('no_backup') and
3165 os.path.lexists(target)):
3165 os.path.lexists(target)):
3166 bakname = "%s.orig" % rel
3166 bakname = "%s.orig" % rel
3167 ui.note(_('saving current version of %s as %s\n') %
3167 ui.note(_('saving current version of %s as %s\n') %
3168 (rel, bakname))
3168 (rel, bakname))
3169 if not opts.get('dry_run'):
3169 if not opts.get('dry_run'):
3170 util.rename(target, bakname)
3170 util.rename(target, bakname)
3171 if ui.verbose or not exact:
3171 if ui.verbose or not exact:
3172 msg = xlist[1]
3172 msg = xlist[1]
3173 if not isinstance(msg, basestring):
3173 if not isinstance(msg, basestring):
3174 msg = msg(abs)
3174 msg = msg(abs)
3175 ui.status(msg % rel)
3175 ui.status(msg % rel)
3176 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3176 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3177 if abs not in table:
3177 if abs not in table:
3178 continue
3178 continue
3179 # file has changed in dirstate
3179 # file has changed in dirstate
3180 if mfentry:
3180 if mfentry:
3181 handle(hitlist, backuphit)
3181 handle(hitlist, backuphit)
3182 elif misslist is not None:
3182 elif misslist is not None:
3183 handle(misslist, backupmiss)
3183 handle(misslist, backupmiss)
3184 break
3184 break
3185 else:
3185 else:
3186 if abs not in repo.dirstate:
3186 if abs not in repo.dirstate:
3187 if mfentry:
3187 if mfentry:
3188 handle(add, True)
3188 handle(add, True)
3189 elif exact:
3189 elif exact:
3190 ui.warn(_('file not managed: %s\n') % rel)
3190 ui.warn(_('file not managed: %s\n') % rel)
3191 continue
3191 continue
3192 # file has not changed in dirstate
3192 # file has not changed in dirstate
3193 if node == parent:
3193 if node == parent:
3194 if exact:
3194 if exact:
3195 ui.warn(_('no changes needed to %s\n') % rel)
3195 ui.warn(_('no changes needed to %s\n') % rel)
3196 continue
3196 continue
3197 if pmf is None:
3197 if pmf is None:
3198 # only need parent manifest in this unlikely case,
3198 # only need parent manifest in this unlikely case,
3199 # so do not read by default
3199 # so do not read by default
3200 pmf = repo[parent].manifest()
3200 pmf = repo[parent].manifest()
3201 if abs in pmf:
3201 if abs in pmf:
3202 if mfentry:
3202 if mfentry:
3203 # if version of file is same in parent and target
3203 # if version of file is same in parent and target
3204 # manifests, do nothing
3204 # manifests, do nothing
3205 if (pmf[abs] != mfentry or
3205 if (pmf[abs] != mfentry or
3206 pmf.flags(abs) != mf.flags(abs)):
3206 pmf.flags(abs) != mf.flags(abs)):
3207 handle(revert, False)
3207 handle(revert, False)
3208 else:
3208 else:
3209 handle(remove, False)
3209 handle(remove, False)
3210
3210
3211 if not opts.get('dry_run'):
3211 if not opts.get('dry_run'):
3212 def checkout(f):
3212 def checkout(f):
3213 fc = ctx[f]
3213 fc = ctx[f]
3214 repo.wwrite(f, fc.data(), fc.flags())
3214 repo.wwrite(f, fc.data(), fc.flags())
3215
3215
3216 audit_path = util.path_auditor(repo.root)
3216 audit_path = util.path_auditor(repo.root)
3217 for f in remove[0]:
3217 for f in remove[0]:
3218 if repo.dirstate[f] == 'a':
3218 if repo.dirstate[f] == 'a':
3219 repo.dirstate.forget(f)
3219 repo.dirstate.forget(f)
3220 continue
3220 continue
3221 audit_path(f)
3221 audit_path(f)
3222 try:
3222 try:
3223 util.unlink(repo.wjoin(f))
3223 util.unlink(repo.wjoin(f))
3224 except OSError:
3224 except OSError:
3225 pass
3225 pass
3226 repo.dirstate.remove(f)
3226 repo.dirstate.remove(f)
3227
3227
3228 normal = None
3228 normal = None
3229 if node == parent:
3229 if node == parent:
3230 # We're reverting to our parent. If possible, we'd like status
3230 # We're reverting to our parent. If possible, we'd like status
3231 # to report the file as clean. We have to use normallookup for
3231 # to report the file as clean. We have to use normallookup for
3232 # merges to avoid losing information about merged/dirty files.
3232 # merges to avoid losing information about merged/dirty files.
3233 if p2 != nullid:
3233 if p2 != nullid:
3234 normal = repo.dirstate.normallookup
3234 normal = repo.dirstate.normallookup
3235 else:
3235 else:
3236 normal = repo.dirstate.normal
3236 normal = repo.dirstate.normal
3237 for f in revert[0]:
3237 for f in revert[0]:
3238 checkout(f)
3238 checkout(f)
3239 if normal:
3239 if normal:
3240 normal(f)
3240 normal(f)
3241
3241
3242 for f in add[0]:
3242 for f in add[0]:
3243 checkout(f)
3243 checkout(f)
3244 repo.dirstate.add(f)
3244 repo.dirstate.add(f)
3245
3245
3246 normal = repo.dirstate.normallookup
3246 normal = repo.dirstate.normallookup
3247 if node == parent and p2 == nullid:
3247 if node == parent and p2 == nullid:
3248 normal = repo.dirstate.normal
3248 normal = repo.dirstate.normal
3249 for f in undelete[0]:
3249 for f in undelete[0]:
3250 checkout(f)
3250 checkout(f)
3251 normal(f)
3251 normal(f)
3252
3252
3253 finally:
3253 finally:
3254 wlock.release()
3254 wlock.release()
3255
3255
3256 def rollback(ui, repo, **opts):
3256 def rollback(ui, repo, **opts):
3257 """roll back the last transaction (dangerous)
3257 """roll back the last transaction (dangerous)
3258
3258
3259 This command should be used with care. There is only one level of
3259 This command should be used with care. There is only one level of
3260 rollback, and there is no way to undo a rollback. It will also
3260 rollback, and there is no way to undo a rollback. It will also
3261 restore the dirstate at the time of the last transaction, losing
3261 restore the dirstate at the time of the last transaction, losing
3262 any dirstate changes since that time. This command does not alter
3262 any dirstate changes since that time. This command does not alter
3263 the working directory.
3263 the working directory.
3264
3264
3265 Transactions are used to encapsulate the effects of all commands
3265 Transactions are used to encapsulate the effects of all commands
3266 that create new changesets or propagate existing changesets into a
3266 that create new changesets or propagate existing changesets into a
3267 repository. For example, the following commands are transactional,
3267 repository. For example, the following commands are transactional,
3268 and their effects can be rolled back:
3268 and their effects can be rolled back:
3269
3269
3270 - commit
3270 - commit
3271 - import
3271 - import
3272 - pull
3272 - pull
3273 - push (with this repository as the destination)
3273 - push (with this repository as the destination)
3274 - unbundle
3274 - unbundle
3275
3275
3276 This command is not intended for use on public repositories. Once
3276 This command is not intended for use on public repositories. Once
3277 changes are visible for pull by other users, rolling a transaction
3277 changes are visible for pull by other users, rolling a transaction
3278 back locally is ineffective (someone else may already have pulled
3278 back locally is ineffective (someone else may already have pulled
3279 the changes). Furthermore, a race is possible with readers of the
3279 the changes). Furthermore, a race is possible with readers of the
3280 repository; for example an in-progress pull from the repository
3280 repository; for example an in-progress pull from the repository
3281 may fail if a rollback is performed.
3281 may fail if a rollback is performed.
3282
3282
3283 Returns 0 on success, 1 if no rollback data is available.
3283 Returns 0 on success, 1 if no rollback data is available.
3284 """
3284 """
3285 return repo.rollback(opts.get('dry_run'))
3285 return repo.rollback(opts.get('dry_run'))
3286
3286
3287 def root(ui, repo):
3287 def root(ui, repo):
3288 """print the root (top) of the current working directory
3288 """print the root (top) of the current working directory
3289
3289
3290 Print the root directory of the current repository.
3290 Print the root directory of the current repository.
3291
3291
3292 Returns 0 on success.
3292 Returns 0 on success.
3293 """
3293 """
3294 ui.write(repo.root + "\n")
3294 ui.write(repo.root + "\n")
3295
3295
3296 def serve(ui, repo, **opts):
3296 def serve(ui, repo, **opts):
3297 """start stand-alone webserver
3297 """start stand-alone webserver
3298
3298
3299 Start a local HTTP repository browser and pull server. You can use
3299 Start a local HTTP repository browser and pull server. You can use
3300 this for ad-hoc sharing and browing of repositories. It is
3300 this for ad-hoc sharing and browing of repositories. It is
3301 recommended to use a real web server to serve a repository for
3301 recommended to use a real web server to serve a repository for
3302 longer periods of time.
3302 longer periods of time.
3303
3303
3304 Please note that the server does not implement access control.
3304 Please note that the server does not implement access control.
3305 This means that, by default, anybody can read from the server and
3305 This means that, by default, anybody can read from the server and
3306 nobody can write to it by default. Set the ``web.allow_push``
3306 nobody can write to it by default. Set the ``web.allow_push``
3307 option to ``*`` to allow everybody to push to the server. You
3307 option to ``*`` to allow everybody to push to the server. You
3308 should use a real web server if you need to authenticate users.
3308 should use a real web server if you need to authenticate users.
3309
3309
3310 By default, the server logs accesses to stdout and errors to
3310 By default, the server logs accesses to stdout and errors to
3311 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3311 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3312 files.
3312 files.
3313
3313
3314 To have the server choose a free port number to listen on, specify
3314 To have the server choose a free port number to listen on, specify
3315 a port number of 0; in this case, the server will print the port
3315 a port number of 0; in this case, the server will print the port
3316 number it uses.
3316 number it uses.
3317
3317
3318 Returns 0 on success.
3318 Returns 0 on success.
3319 """
3319 """
3320
3320
3321 if opts["stdio"]:
3321 if opts["stdio"]:
3322 if repo is None:
3322 if repo is None:
3323 raise error.RepoError(_("There is no Mercurial repository here"
3323 raise error.RepoError(_("There is no Mercurial repository here"
3324 " (.hg not found)"))
3324 " (.hg not found)"))
3325 s = sshserver.sshserver(ui, repo)
3325 s = sshserver.sshserver(ui, repo)
3326 s.serve_forever()
3326 s.serve_forever()
3327
3327
3328 # this way we can check if something was given in the command-line
3328 # this way we can check if something was given in the command-line
3329 if opts.get('port'):
3329 if opts.get('port'):
3330 opts['port'] = util.getport(opts.get('port'))
3330 opts['port'] = util.getport(opts.get('port'))
3331
3331
3332 baseui = repo and repo.baseui or ui
3332 baseui = repo and repo.baseui or ui
3333 optlist = ("name templates style address port prefix ipv6"
3333 optlist = ("name templates style address port prefix ipv6"
3334 " accesslog errorlog certificate encoding")
3334 " accesslog errorlog certificate encoding")
3335 for o in optlist.split():
3335 for o in optlist.split():
3336 val = opts.get(o, '')
3336 val = opts.get(o, '')
3337 if val in (None, ''): # should check against default options instead
3337 if val in (None, ''): # should check against default options instead
3338 continue
3338 continue
3339 baseui.setconfig("web", o, val)
3339 baseui.setconfig("web", o, val)
3340 if repo and repo.ui != baseui:
3340 if repo and repo.ui != baseui:
3341 repo.ui.setconfig("web", o, val)
3341 repo.ui.setconfig("web", o, val)
3342
3342
3343 o = opts.get('web_conf') or opts.get('webdir_conf')
3343 o = opts.get('web_conf') or opts.get('webdir_conf')
3344 if not o:
3344 if not o:
3345 if not repo:
3345 if not repo:
3346 raise error.RepoError(_("There is no Mercurial repository"
3346 raise error.RepoError(_("There is no Mercurial repository"
3347 " here (.hg not found)"))
3347 " here (.hg not found)"))
3348 o = repo.root
3348 o = repo.root
3349
3349
3350 app = hgweb.hgweb(o, baseui=ui)
3350 app = hgweb.hgweb(o, baseui=ui)
3351
3351
3352 class service(object):
3352 class service(object):
3353 def init(self):
3353 def init(self):
3354 util.set_signal_handler()
3354 util.set_signal_handler()
3355 self.httpd = hgweb.server.create_server(ui, app)
3355 self.httpd = hgweb.server.create_server(ui, app)
3356
3356
3357 if opts['port'] and not ui.verbose:
3357 if opts['port'] and not ui.verbose:
3358 return
3358 return
3359
3359
3360 if self.httpd.prefix:
3360 if self.httpd.prefix:
3361 prefix = self.httpd.prefix.strip('/') + '/'
3361 prefix = self.httpd.prefix.strip('/') + '/'
3362 else:
3362 else:
3363 prefix = ''
3363 prefix = ''
3364
3364
3365 port = ':%d' % self.httpd.port
3365 port = ':%d' % self.httpd.port
3366 if port == ':80':
3366 if port == ':80':
3367 port = ''
3367 port = ''
3368
3368
3369 bindaddr = self.httpd.addr
3369 bindaddr = self.httpd.addr
3370 if bindaddr == '0.0.0.0':
3370 if bindaddr == '0.0.0.0':
3371 bindaddr = '*'
3371 bindaddr = '*'
3372 elif ':' in bindaddr: # IPv6
3372 elif ':' in bindaddr: # IPv6
3373 bindaddr = '[%s]' % bindaddr
3373 bindaddr = '[%s]' % bindaddr
3374
3374
3375 fqaddr = self.httpd.fqaddr
3375 fqaddr = self.httpd.fqaddr
3376 if ':' in fqaddr:
3376 if ':' in fqaddr:
3377 fqaddr = '[%s]' % fqaddr
3377 fqaddr = '[%s]' % fqaddr
3378 if opts['port']:
3378 if opts['port']:
3379 write = ui.status
3379 write = ui.status
3380 else:
3380 else:
3381 write = ui.write
3381 write = ui.write
3382 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3382 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3383 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3383 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3384
3384
3385 def run(self):
3385 def run(self):
3386 self.httpd.serve_forever()
3386 self.httpd.serve_forever()
3387
3387
3388 service = service()
3388 service = service()
3389
3389
3390 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3390 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3391
3391
3392 def status(ui, repo, *pats, **opts):
3392 def status(ui, repo, *pats, **opts):
3393 """show changed files in the working directory
3393 """show changed files in the working directory
3394
3394
3395 Show status of files in the repository. If names are given, only
3395 Show status of files in the repository. If names are given, only
3396 files that match are shown. Files that are clean or ignored or
3396 files that match are shown. Files that are clean or ignored or
3397 the source of a copy/move operation, are not listed unless
3397 the source of a copy/move operation, are not listed unless
3398 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3398 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3399 Unless options described with "show only ..." are given, the
3399 Unless options described with "show only ..." are given, the
3400 options -mardu are used.
3400 options -mardu are used.
3401
3401
3402 Option -q/--quiet hides untracked (unknown and ignored) files
3402 Option -q/--quiet hides untracked (unknown and ignored) files
3403 unless explicitly requested with -u/--unknown or -i/--ignored.
3403 unless explicitly requested with -u/--unknown or -i/--ignored.
3404
3404
3405 .. note::
3405 .. note::
3406 status may appear to disagree with diff if permissions have
3406 status may appear to disagree with diff if permissions have
3407 changed or a merge has occurred. The standard diff format does
3407 changed or a merge has occurred. The standard diff format does
3408 not report permission changes and diff only reports changes
3408 not report permission changes and diff only reports changes
3409 relative to one merge parent.
3409 relative to one merge parent.
3410
3410
3411 If one revision is given, it is used as the base revision.
3411 If one revision is given, it is used as the base revision.
3412 If two revisions are given, the differences between them are
3412 If two revisions are given, the differences between them are
3413 shown. The --change option can also be used as a shortcut to list
3413 shown. The --change option can also be used as a shortcut to list
3414 the changed files of a revision from its first parent.
3414 the changed files of a revision from its first parent.
3415
3415
3416 The codes used to show the status of files are::
3416 The codes used to show the status of files are::
3417
3417
3418 M = modified
3418 M = modified
3419 A = added
3419 A = added
3420 R = removed
3420 R = removed
3421 C = clean
3421 C = clean
3422 ! = missing (deleted by non-hg command, but still tracked)
3422 ! = missing (deleted by non-hg command, but still tracked)
3423 ? = not tracked
3423 ? = not tracked
3424 I = ignored
3424 I = ignored
3425 = origin of the previous file listed as A (added)
3425 = origin of the previous file listed as A (added)
3426
3426
3427 Returns 0 on success.
3427 Returns 0 on success.
3428 """
3428 """
3429
3429
3430 revs = opts.get('rev')
3430 revs = opts.get('rev')
3431 change = opts.get('change')
3431 change = opts.get('change')
3432
3432
3433 if revs and change:
3433 if revs and change:
3434 msg = _('cannot specify --rev and --change at the same time')
3434 msg = _('cannot specify --rev and --change at the same time')
3435 raise util.Abort(msg)
3435 raise util.Abort(msg)
3436 elif change:
3436 elif change:
3437 node2 = repo.lookup(change)
3437 node2 = repo.lookup(change)
3438 node1 = repo[node2].parents()[0].node()
3438 node1 = repo[node2].parents()[0].node()
3439 else:
3439 else:
3440 node1, node2 = cmdutil.revpair(repo, revs)
3440 node1, node2 = cmdutil.revpair(repo, revs)
3441
3441
3442 cwd = (pats and repo.getcwd()) or ''
3442 cwd = (pats and repo.getcwd()) or ''
3443 end = opts.get('print0') and '\0' or '\n'
3443 end = opts.get('print0') and '\0' or '\n'
3444 copy = {}
3444 copy = {}
3445 states = 'modified added removed deleted unknown ignored clean'.split()
3445 states = 'modified added removed deleted unknown ignored clean'.split()
3446 show = [k for k in states if opts.get(k)]
3446 show = [k for k in states if opts.get(k)]
3447 if opts.get('all'):
3447 if opts.get('all'):
3448 show += ui.quiet and (states[:4] + ['clean']) or states
3448 show += ui.quiet and (states[:4] + ['clean']) or states
3449 if not show:
3449 if not show:
3450 show = ui.quiet and states[:4] or states[:5]
3450 show = ui.quiet and states[:4] or states[:5]
3451
3451
3452 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3452 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3453 'ignored' in show, 'clean' in show, 'unknown' in show,
3453 'ignored' in show, 'clean' in show, 'unknown' in show,
3454 opts.get('subrepos'))
3454 opts.get('subrepos'))
3455 changestates = zip(states, 'MAR!?IC', stat)
3455 changestates = zip(states, 'MAR!?IC', stat)
3456
3456
3457 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3457 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3458 ctxn = repo[nullid]
3458 ctxn = repo[nullid]
3459 ctx1 = repo[node1]
3459 ctx1 = repo[node1]
3460 ctx2 = repo[node2]
3460 ctx2 = repo[node2]
3461 added = stat[1]
3461 added = stat[1]
3462 if node2 is None:
3462 if node2 is None:
3463 added = stat[0] + stat[1] # merged?
3463 added = stat[0] + stat[1] # merged?
3464
3464
3465 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3465 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3466 if k in added:
3466 if k in added:
3467 copy[k] = v
3467 copy[k] = v
3468 elif v in added:
3468 elif v in added:
3469 copy[v] = k
3469 copy[v] = k
3470
3470
3471 for state, char, files in changestates:
3471 for state, char, files in changestates:
3472 if state in show:
3472 if state in show:
3473 format = "%s %%s%s" % (char, end)
3473 format = "%s %%s%s" % (char, end)
3474 if opts.get('no_status'):
3474 if opts.get('no_status'):
3475 format = "%%s%s" % end
3475 format = "%%s%s" % end
3476
3476
3477 for f in files:
3477 for f in files:
3478 ui.write(format % repo.pathto(f, cwd),
3478 ui.write(format % repo.pathto(f, cwd),
3479 label='status.' + state)
3479 label='status.' + state)
3480 if f in copy:
3480 if f in copy:
3481 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3481 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3482 label='status.copied')
3482 label='status.copied')
3483
3483
3484 def summary(ui, repo, **opts):
3484 def summary(ui, repo, **opts):
3485 """summarize working directory state
3485 """summarize working directory state
3486
3486
3487 This generates a brief summary of the working directory state,
3487 This generates a brief summary of the working directory state,
3488 including parents, branch, commit status, and available updates.
3488 including parents, branch, commit status, and available updates.
3489
3489
3490 With the --remote option, this will check the default paths for
3490 With the --remote option, this will check the default paths for
3491 incoming and outgoing changes. This can be time-consuming.
3491 incoming and outgoing changes. This can be time-consuming.
3492
3492
3493 Returns 0 on success.
3493 Returns 0 on success.
3494 """
3494 """
3495
3495
3496 ctx = repo[None]
3496 ctx = repo[None]
3497 parents = ctx.parents()
3497 parents = ctx.parents()
3498 pnode = parents[0].node()
3498 pnode = parents[0].node()
3499
3499
3500 for p in parents:
3500 for p in parents:
3501 # label with log.changeset (instead of log.parent) since this
3501 # label with log.changeset (instead of log.parent) since this
3502 # shows a working directory parent *changeset*:
3502 # shows a working directory parent *changeset*:
3503 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3503 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3504 label='log.changeset')
3504 label='log.changeset')
3505 ui.write(' '.join(p.tags()), label='log.tag')
3505 ui.write(' '.join(p.tags()), label='log.tag')
3506 if p.rev() == -1:
3506 if p.rev() == -1:
3507 if not len(repo):
3507 if not len(repo):
3508 ui.write(_(' (empty repository)'))
3508 ui.write(_(' (empty repository)'))
3509 else:
3509 else:
3510 ui.write(_(' (no revision checked out)'))
3510 ui.write(_(' (no revision checked out)'))
3511 ui.write('\n')
3511 ui.write('\n')
3512 if p.description():
3512 if p.description():
3513 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3513 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3514 label='log.summary')
3514 label='log.summary')
3515
3515
3516 branch = ctx.branch()
3516 branch = ctx.branch()
3517 bheads = repo.branchheads(branch)
3517 bheads = repo.branchheads(branch)
3518 m = _('branch: %s\n') % branch
3518 m = _('branch: %s\n') % branch
3519 if branch != 'default':
3519 if branch != 'default':
3520 ui.write(m, label='log.branch')
3520 ui.write(m, label='log.branch')
3521 else:
3521 else:
3522 ui.status(m, label='log.branch')
3522 ui.status(m, label='log.branch')
3523
3523
3524 st = list(repo.status(unknown=True))[:6]
3524 st = list(repo.status(unknown=True))[:6]
3525
3525
3526 c = repo.dirstate.copies()
3526 c = repo.dirstate.copies()
3527 copied, renamed = [], []
3527 copied, renamed = [], []
3528 for d, s in c.iteritems():
3528 for d, s in c.iteritems():
3529 if s in st[2]:
3529 if s in st[2]:
3530 st[2].remove(s)
3530 st[2].remove(s)
3531 renamed.append(d)
3531 renamed.append(d)
3532 else:
3532 else:
3533 copied.append(d)
3533 copied.append(d)
3534 if d in st[1]:
3534 if d in st[1]:
3535 st[1].remove(d)
3535 st[1].remove(d)
3536 st.insert(3, renamed)
3536 st.insert(3, renamed)
3537 st.insert(4, copied)
3537 st.insert(4, copied)
3538
3538
3539 ms = mergemod.mergestate(repo)
3539 ms = mergemod.mergestate(repo)
3540 st.append([f for f in ms if ms[f] == 'u'])
3540 st.append([f for f in ms if ms[f] == 'u'])
3541
3541
3542 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3542 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3543 st.append(subs)
3543 st.append(subs)
3544
3544
3545 labels = [ui.label(_('%d modified'), 'status.modified'),
3545 labels = [ui.label(_('%d modified'), 'status.modified'),
3546 ui.label(_('%d added'), 'status.added'),
3546 ui.label(_('%d added'), 'status.added'),
3547 ui.label(_('%d removed'), 'status.removed'),
3547 ui.label(_('%d removed'), 'status.removed'),
3548 ui.label(_('%d renamed'), 'status.copied'),
3548 ui.label(_('%d renamed'), 'status.copied'),
3549 ui.label(_('%d copied'), 'status.copied'),
3549 ui.label(_('%d copied'), 'status.copied'),
3550 ui.label(_('%d deleted'), 'status.deleted'),
3550 ui.label(_('%d deleted'), 'status.deleted'),
3551 ui.label(_('%d unknown'), 'status.unknown'),
3551 ui.label(_('%d unknown'), 'status.unknown'),
3552 ui.label(_('%d ignored'), 'status.ignored'),
3552 ui.label(_('%d ignored'), 'status.ignored'),
3553 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3553 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3554 ui.label(_('%d subrepos'), 'status.modified')]
3554 ui.label(_('%d subrepos'), 'status.modified')]
3555 t = []
3555 t = []
3556 for s, l in zip(st, labels):
3556 for s, l in zip(st, labels):
3557 if s:
3557 if s:
3558 t.append(l % len(s))
3558 t.append(l % len(s))
3559
3559
3560 t = ', '.join(t)
3560 t = ', '.join(t)
3561 cleanworkdir = False
3561 cleanworkdir = False
3562
3562
3563 if len(parents) > 1:
3563 if len(parents) > 1:
3564 t += _(' (merge)')
3564 t += _(' (merge)')
3565 elif branch != parents[0].branch():
3565 elif branch != parents[0].branch():
3566 t += _(' (new branch)')
3566 t += _(' (new branch)')
3567 elif (parents[0].extra().get('close') and
3567 elif (parents[0].extra().get('close') and
3568 pnode in repo.branchheads(branch, closed=True)):
3568 pnode in repo.branchheads(branch, closed=True)):
3569 t += _(' (head closed)')
3569 t += _(' (head closed)')
3570 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3570 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3571 t += _(' (clean)')
3571 t += _(' (clean)')
3572 cleanworkdir = True
3572 cleanworkdir = True
3573 elif pnode not in bheads:
3573 elif pnode not in bheads:
3574 t += _(' (new branch head)')
3574 t += _(' (new branch head)')
3575
3575
3576 if cleanworkdir:
3576 if cleanworkdir:
3577 ui.status(_('commit: %s\n') % t.strip())
3577 ui.status(_('commit: %s\n') % t.strip())
3578 else:
3578 else:
3579 ui.write(_('commit: %s\n') % t.strip())
3579 ui.write(_('commit: %s\n') % t.strip())
3580
3580
3581 # all ancestors of branch heads - all ancestors of parent = new csets
3581 # all ancestors of branch heads - all ancestors of parent = new csets
3582 new = [0] * len(repo)
3582 new = [0] * len(repo)
3583 cl = repo.changelog
3583 cl = repo.changelog
3584 for a in [cl.rev(n) for n in bheads]:
3584 for a in [cl.rev(n) for n in bheads]:
3585 new[a] = 1
3585 new[a] = 1
3586 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3586 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3587 new[a] = 1
3587 new[a] = 1
3588 for a in [p.rev() for p in parents]:
3588 for a in [p.rev() for p in parents]:
3589 if a >= 0:
3589 if a >= 0:
3590 new[a] = 0
3590 new[a] = 0
3591 for a in cl.ancestors(*[p.rev() for p in parents]):
3591 for a in cl.ancestors(*[p.rev() for p in parents]):
3592 new[a] = 0
3592 new[a] = 0
3593 new = sum(new)
3593 new = sum(new)
3594
3594
3595 if new == 0:
3595 if new == 0:
3596 ui.status(_('update: (current)\n'))
3596 ui.status(_('update: (current)\n'))
3597 elif pnode not in bheads:
3597 elif pnode not in bheads:
3598 ui.write(_('update: %d new changesets (update)\n') % new)
3598 ui.write(_('update: %d new changesets (update)\n') % new)
3599 else:
3599 else:
3600 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3600 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3601 (new, len(bheads)))
3601 (new, len(bheads)))
3602
3602
3603 if opts.get('remote'):
3603 if opts.get('remote'):
3604 t = []
3604 t = []
3605 source, branches = hg.parseurl(ui.expandpath('default'))
3605 source, branches = hg.parseurl(ui.expandpath('default'))
3606 other = hg.repository(hg.remoteui(repo, {}), source)
3606 other = hg.repository(hg.remoteui(repo, {}), source)
3607 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3607 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3608 ui.debug('comparing with %s\n' % url.hidepassword(source))
3608 ui.debug('comparing with %s\n' % url.hidepassword(source))
3609 repo.ui.pushbuffer()
3609 repo.ui.pushbuffer()
3610 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3610 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3611 repo.ui.popbuffer()
3611 repo.ui.popbuffer()
3612 if incoming:
3612 if incoming:
3613 t.append(_('1 or more incoming'))
3613 t.append(_('1 or more incoming'))
3614
3614
3615 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3615 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3616 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3616 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3617 other = hg.repository(hg.remoteui(repo, {}), dest)
3617 other = hg.repository(hg.remoteui(repo, {}), dest)
3618 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3618 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3619 repo.ui.pushbuffer()
3619 repo.ui.pushbuffer()
3620 o = discovery.findoutgoing(repo, other)
3620 o = discovery.findoutgoing(repo, other)
3621 repo.ui.popbuffer()
3621 repo.ui.popbuffer()
3622 o = repo.changelog.nodesbetween(o, None)[0]
3622 o = repo.changelog.nodesbetween(o, None)[0]
3623 if o:
3623 if o:
3624 t.append(_('%d outgoing') % len(o))
3624 t.append(_('%d outgoing') % len(o))
3625
3625
3626 if t:
3626 if t:
3627 ui.write(_('remote: %s\n') % (', '.join(t)))
3627 ui.write(_('remote: %s\n') % (', '.join(t)))
3628 else:
3628 else:
3629 ui.status(_('remote: (synced)\n'))
3629 ui.status(_('remote: (synced)\n'))
3630
3630
3631 def tag(ui, repo, name1, *names, **opts):
3631 def tag(ui, repo, name1, *names, **opts):
3632 """add one or more tags for the current or given revision
3632 """add one or more tags for the current or given revision
3633
3633
3634 Name a particular revision using <name>.
3634 Name a particular revision using <name>.
3635
3635
3636 Tags are used to name particular revisions of the repository and are
3636 Tags are used to name particular revisions of the repository and are
3637 very useful to compare different revisions, to go back to significant
3637 very useful to compare different revisions, to go back to significant
3638 earlier versions or to mark branch points as releases, etc.
3638 earlier versions or to mark branch points as releases, etc.
3639
3639
3640 If no revision is given, the parent of the working directory is
3640 If no revision is given, the parent of the working directory is
3641 used, or tip if no revision is checked out.
3641 used, or tip if no revision is checked out.
3642
3642
3643 To facilitate version control, distribution, and merging of tags,
3643 To facilitate version control, distribution, and merging of tags,
3644 they are stored as a file named ".hgtags" which is managed
3644 they are stored as a file named ".hgtags" which is managed
3645 similarly to other project files and can be hand-edited if
3645 similarly to other project files and can be hand-edited if
3646 necessary. The file '.hg/localtags' is used for local tags (not
3646 necessary. The file '.hg/localtags' is used for local tags (not
3647 shared among repositories).
3647 shared among repositories).
3648
3648
3649 See :hg:`help dates` for a list of formats valid for -d/--date.
3649 See :hg:`help dates` for a list of formats valid for -d/--date.
3650
3650
3651 Since tag names have priority over branch names during revision
3651 Since tag names have priority over branch names during revision
3652 lookup, using an existing branch name as a tag name is discouraged.
3652 lookup, using an existing branch name as a tag name is discouraged.
3653
3653
3654 Returns 0 on success.
3654 Returns 0 on success.
3655 """
3655 """
3656
3656
3657 rev_ = "."
3657 rev_ = "."
3658 names = [t.strip() for t in (name1,) + names]
3658 names = [t.strip() for t in (name1,) + names]
3659 if len(names) != len(set(names)):
3659 if len(names) != len(set(names)):
3660 raise util.Abort(_('tag names must be unique'))
3660 raise util.Abort(_('tag names must be unique'))
3661 for n in names:
3661 for n in names:
3662 if n in ['tip', '.', 'null']:
3662 if n in ['tip', '.', 'null']:
3663 raise util.Abort(_('the name \'%s\' is reserved') % n)
3663 raise util.Abort(_('the name \'%s\' is reserved') % n)
3664 if not n:
3664 if not n:
3665 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3665 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3666 if opts.get('rev') and opts.get('remove'):
3666 if opts.get('rev') and opts.get('remove'):
3667 raise util.Abort(_("--rev and --remove are incompatible"))
3667 raise util.Abort(_("--rev and --remove are incompatible"))
3668 if opts.get('rev'):
3668 if opts.get('rev'):
3669 rev_ = opts['rev']
3669 rev_ = opts['rev']
3670 message = opts.get('message')
3670 message = opts.get('message')
3671 if opts.get('remove'):
3671 if opts.get('remove'):
3672 expectedtype = opts.get('local') and 'local' or 'global'
3672 expectedtype = opts.get('local') and 'local' or 'global'
3673 for n in names:
3673 for n in names:
3674 if not repo.tagtype(n):
3674 if not repo.tagtype(n):
3675 raise util.Abort(_('tag \'%s\' does not exist') % n)
3675 raise util.Abort(_('tag \'%s\' does not exist') % n)
3676 if repo.tagtype(n) != expectedtype:
3676 if repo.tagtype(n) != expectedtype:
3677 if expectedtype == 'global':
3677 if expectedtype == 'global':
3678 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3678 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3679 else:
3679 else:
3680 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3680 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3681 rev_ = nullid
3681 rev_ = nullid
3682 if not message:
3682 if not message:
3683 # we don't translate commit messages
3683 # we don't translate commit messages
3684 message = 'Removed tag %s' % ', '.join(names)
3684 message = 'Removed tag %s' % ', '.join(names)
3685 elif not opts.get('force'):
3685 elif not opts.get('force'):
3686 for n in names:
3686 for n in names:
3687 if n in repo.tags():
3687 if n in repo.tags():
3688 raise util.Abort(_('tag \'%s\' already exists '
3688 raise util.Abort(_('tag \'%s\' already exists '
3689 '(use -f to force)') % n)
3689 '(use -f to force)') % n)
3690 if not rev_ and repo.dirstate.parents()[1] != nullid:
3690 if not rev_ and repo.dirstate.parents()[1] != nullid:
3691 raise util.Abort(_('uncommitted merge - please provide a '
3691 raise util.Abort(_('uncommitted merge - please provide a '
3692 'specific revision'))
3692 'specific revision'))
3693 r = repo[rev_].node()
3693 r = repo[rev_].node()
3694
3694
3695 if not message:
3695 if not message:
3696 # we don't translate commit messages
3696 # we don't translate commit messages
3697 message = ('Added tag %s for changeset %s' %
3697 message = ('Added tag %s for changeset %s' %
3698 (', '.join(names), short(r)))
3698 (', '.join(names), short(r)))
3699
3699
3700 date = opts.get('date')
3700 date = opts.get('date')
3701 if date:
3701 if date:
3702 date = util.parsedate(date)
3702 date = util.parsedate(date)
3703
3703
3704 if opts.get('edit'):
3704 if opts.get('edit'):
3705 message = ui.edit(message, ui.username())
3705 message = ui.edit(message, ui.username())
3706
3706
3707 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3707 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3708
3708
3709 def tags(ui, repo):
3709 def tags(ui, repo):
3710 """list repository tags
3710 """list repository tags
3711
3711
3712 This lists both regular and local tags. When the -v/--verbose
3712 This lists both regular and local tags. When the -v/--verbose
3713 switch is used, a third column "local" is printed for local tags.
3713 switch is used, a third column "local" is printed for local tags.
3714
3714
3715 Returns 0 on success.
3715 Returns 0 on success.
3716 """
3716 """
3717
3717
3718 hexfunc = ui.debugflag and hex or short
3718 hexfunc = ui.debugflag and hex or short
3719 tagtype = ""
3719 tagtype = ""
3720
3720
3721 for t, n in reversed(repo.tagslist()):
3721 for t, n in reversed(repo.tagslist()):
3722 if ui.quiet:
3722 if ui.quiet:
3723 ui.write("%s\n" % t)
3723 ui.write("%s\n" % t)
3724 continue
3724 continue
3725
3725
3726 try:
3726 try:
3727 hn = hexfunc(n)
3727 hn = hexfunc(n)
3728 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3728 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3729 except error.LookupError:
3729 except error.LookupError:
3730 r = " ?:%s" % hn
3730 r = " ?:%s" % hn
3731 else:
3731 else:
3732 spaces = " " * (30 - encoding.colwidth(t))
3732 spaces = " " * (30 - encoding.colwidth(t))
3733 if ui.verbose:
3733 if ui.verbose:
3734 if repo.tagtype(t) == 'local':
3734 if repo.tagtype(t) == 'local':
3735 tagtype = " local"
3735 tagtype = " local"
3736 else:
3736 else:
3737 tagtype = ""
3737 tagtype = ""
3738 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3738 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3739
3739
3740 def tip(ui, repo, **opts):
3740 def tip(ui, repo, **opts):
3741 """show the tip revision
3741 """show the tip revision
3742
3742
3743 The tip revision (usually just called the tip) is the changeset
3743 The tip revision (usually just called the tip) is the changeset
3744 most recently added to the repository (and therefore the most
3744 most recently added to the repository (and therefore the most
3745 recently changed head).
3745 recently changed head).
3746
3746
3747 If you have just made a commit, that commit will be the tip. If
3747 If you have just made a commit, that commit will be the tip. If
3748 you have just pulled changes from another repository, the tip of
3748 you have just pulled changes from another repository, the tip of
3749 that repository becomes the current tip. The "tip" tag is special
3749 that repository becomes the current tip. The "tip" tag is special
3750 and cannot be renamed or assigned to a different changeset.
3750 and cannot be renamed or assigned to a different changeset.
3751
3751
3752 Returns 0 on success.
3752 Returns 0 on success.
3753 """
3753 """
3754 displayer = cmdutil.show_changeset(ui, repo, opts)
3754 displayer = cmdutil.show_changeset(ui, repo, opts)
3755 displayer.show(repo[len(repo) - 1])
3755 displayer.show(repo[len(repo) - 1])
3756 displayer.close()
3756 displayer.close()
3757
3757
3758 def unbundle(ui, repo, fname1, *fnames, **opts):
3758 def unbundle(ui, repo, fname1, *fnames, **opts):
3759 """apply one or more changegroup files
3759 """apply one or more changegroup files
3760
3760
3761 Apply one or more compressed changegroup files generated by the
3761 Apply one or more compressed changegroup files generated by the
3762 bundle command.
3762 bundle command.
3763
3763
3764 Returns 0 on success, 1 if an update has unresolved files.
3764 Returns 0 on success, 1 if an update has unresolved files.
3765 """
3765 """
3766 fnames = (fname1,) + fnames
3766 fnames = (fname1,) + fnames
3767
3767
3768 lock = repo.lock()
3768 lock = repo.lock()
3769 try:
3769 try:
3770 for fname in fnames:
3770 for fname in fnames:
3771 f = url.open(ui, fname)
3771 f = url.open(ui, fname)
3772 gen = changegroup.readbundle(f, fname)
3772 gen = changegroup.readbundle(f, fname)
3773 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3773 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3774 lock=lock)
3774 lock=lock)
3775 finally:
3775 finally:
3776 lock.release()
3776 lock.release()
3777
3777
3778 return postincoming(ui, repo, modheads, opts.get('update'), None)
3778 return postincoming(ui, repo, modheads, opts.get('update'), None)
3779
3779
3780 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3780 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3781 """update working directory (or switch revisions)
3781 """update working directory (or switch revisions)
3782
3782
3783 Update the repository's working directory to the specified
3783 Update the repository's working directory to the specified
3784 changeset. If no changeset is specified, update to the tip of the
3784 changeset. If no changeset is specified, update to the tip of the
3785 current named branch.
3785 current named branch.
3786
3786
3787 If the changeset is not a descendant of the working directory's
3787 If the changeset is not a descendant of the working directory's
3788 parent, the update is aborted. With the -c/--check option, the
3788 parent, the update is aborted. With the -c/--check option, the
3789 working directory is checked for uncommitted changes; if none are
3789 working directory is checked for uncommitted changes; if none are
3790 found, the working directory is updated to the specified
3790 found, the working directory is updated to the specified
3791 changeset.
3791 changeset.
3792
3792
3793 The following rules apply when the working directory contains
3793 The following rules apply when the working directory contains
3794 uncommitted changes:
3794 uncommitted changes:
3795
3795
3796 1. If neither -c/--check nor -C/--clean is specified, and if
3796 1. If neither -c/--check nor -C/--clean is specified, and if
3797 the requested changeset is an ancestor or descendant of
3797 the requested changeset is an ancestor or descendant of
3798 the working directory's parent, the uncommitted changes
3798 the working directory's parent, the uncommitted changes
3799 are merged into the requested changeset and the merged
3799 are merged into the requested changeset and the merged
3800 result is left uncommitted. If the requested changeset is
3800 result is left uncommitted. If the requested changeset is
3801 not an ancestor or descendant (that is, it is on another
3801 not an ancestor or descendant (that is, it is on another
3802 branch), the update is aborted and the uncommitted changes
3802 branch), the update is aborted and the uncommitted changes
3803 are preserved.
3803 are preserved.
3804
3804
3805 2. With the -c/--check option, the update is aborted and the
3805 2. With the -c/--check option, the update is aborted and the
3806 uncommitted changes are preserved.
3806 uncommitted changes are preserved.
3807
3807
3808 3. With the -C/--clean option, uncommitted changes are discarded and
3808 3. With the -C/--clean option, uncommitted changes are discarded and
3809 the working directory is updated to the requested changeset.
3809 the working directory is updated to the requested changeset.
3810
3810
3811 Use null as the changeset to remove the working directory (like
3811 Use null as the changeset to remove the working directory (like
3812 :hg:`clone -U`).
3812 :hg:`clone -U`).
3813
3813
3814 If you want to update just one file to an older changeset, use
3814 If you want to update just one file to an older changeset, use
3815 :hg:`revert`.
3815 :hg:`revert`.
3816
3816
3817 See :hg:`help dates` for a list of formats valid for -d/--date.
3817 See :hg:`help dates` for a list of formats valid for -d/--date.
3818
3818
3819 Returns 0 on success, 1 if there are unresolved files.
3819 Returns 0 on success, 1 if there are unresolved files.
3820 """
3820 """
3821 if rev and node:
3821 if rev and node:
3822 raise util.Abort(_("please specify just one revision"))
3822 raise util.Abort(_("please specify just one revision"))
3823
3823
3824 if not rev:
3824 if not rev:
3825 rev = node
3825 rev = node
3826
3826
3827 rev = cmdutil.revsingle(repo, rev, rev).rev()
3827 rev = cmdutil.revsingle(repo, rev, rev).rev()
3828
3828
3829 if check and clean:
3829 if check and clean:
3830 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3830 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3831
3831
3832 if check:
3832 if check:
3833 # we could use dirty() but we can ignore merge and branch trivia
3833 # we could use dirty() but we can ignore merge and branch trivia
3834 c = repo[None]
3834 c = repo[None]
3835 if c.modified() or c.added() or c.removed():
3835 if c.modified() or c.added() or c.removed():
3836 raise util.Abort(_("uncommitted local changes"))
3836 raise util.Abort(_("uncommitted local changes"))
3837
3837
3838 if date:
3838 if date:
3839 if rev:
3839 if rev:
3840 raise util.Abort(_("you can't specify a revision and a date"))
3840 raise util.Abort(_("you can't specify a revision and a date"))
3841 rev = cmdutil.finddate(ui, repo, date)
3841 rev = cmdutil.finddate(ui, repo, date)
3842
3842
3843 if clean or check:
3843 if clean or check:
3844 return hg.clean(repo, rev)
3844 return hg.clean(repo, rev)
3845 else:
3845 else:
3846 return hg.update(repo, rev)
3846 return hg.update(repo, rev)
3847
3847
3848 def verify(ui, repo):
3848 def verify(ui, repo):
3849 """verify the integrity of the repository
3849 """verify the integrity of the repository
3850
3850
3851 Verify the integrity of the current repository.
3851 Verify the integrity of the current repository.
3852
3852
3853 This will perform an extensive check of the repository's
3853 This will perform an extensive check of the repository's
3854 integrity, validating the hashes and checksums of each entry in
3854 integrity, validating the hashes and checksums of each entry in
3855 the changelog, manifest, and tracked files, as well as the
3855 the changelog, manifest, and tracked files, as well as the
3856 integrity of their crosslinks and indices.
3856 integrity of their crosslinks and indices.
3857
3857
3858 Returns 0 on success, 1 if errors are encountered.
3858 Returns 0 on success, 1 if errors are encountered.
3859 """
3859 """
3860 return hg.verify(repo)
3860 return hg.verify(repo)
3861
3861
3862 def version_(ui):
3862 def version_(ui):
3863 """output version and copyright information"""
3863 """output version and copyright information"""
3864 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3864 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3865 % util.version())
3865 % util.version())
3866 ui.status(_(
3866 ui.status(_(
3867 "(see http://mercurial.selenic.com for more information)\n"
3867 "(see http://mercurial.selenic.com for more information)\n"
3868 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3868 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3869 "This is free software; see the source for copying conditions. "
3869 "This is free software; see the source for copying conditions. "
3870 "There is NO\nwarranty; "
3870 "There is NO\nwarranty; "
3871 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3871 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3872 ))
3872 ))
3873
3873
3874 # Command options and aliases are listed here, alphabetically
3874 # Command options and aliases are listed here, alphabetically
3875
3875
3876 globalopts = [
3876 globalopts = [
3877 ('R', 'repository', '',
3877 ('R', 'repository', '',
3878 _('repository root directory or name of overlay bundle file'),
3878 _('repository root directory or name of overlay bundle file'),
3879 _('REPO')),
3879 _('REPO')),
3880 ('', 'cwd', '',
3880 ('', 'cwd', '',
3881 _('change working directory'), _('DIR')),
3881 _('change working directory'), _('DIR')),
3882 ('y', 'noninteractive', None,
3882 ('y', 'noninteractive', None,
3883 _('do not prompt, assume \'yes\' for any required answers')),
3883 _('do not prompt, assume \'yes\' for any required answers')),
3884 ('q', 'quiet', None, _('suppress output')),
3884 ('q', 'quiet', None, _('suppress output')),
3885 ('v', 'verbose', None, _('enable additional output')),
3885 ('v', 'verbose', None, _('enable additional output')),
3886 ('', 'config', [],
3886 ('', 'config', [],
3887 _('set/override config option (use \'section.name=value\')'),
3887 _('set/override config option (use \'section.name=value\')'),
3888 _('CONFIG')),
3888 _('CONFIG')),
3889 ('', 'debug', None, _('enable debugging output')),
3889 ('', 'debug', None, _('enable debugging output')),
3890 ('', 'debugger', None, _('start debugger')),
3890 ('', 'debugger', None, _('start debugger')),
3891 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3891 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3892 _('ENCODE')),
3892 _('ENCODE')),
3893 ('', 'encodingmode', encoding.encodingmode,
3893 ('', 'encodingmode', encoding.encodingmode,
3894 _('set the charset encoding mode'), _('MODE')),
3894 _('set the charset encoding mode'), _('MODE')),
3895 ('', 'traceback', None, _('always print a traceback on exception')),
3895 ('', 'traceback', None, _('always print a traceback on exception')),
3896 ('', 'time', None, _('time how long the command takes')),
3896 ('', 'time', None, _('time how long the command takes')),
3897 ('', 'profile', None, _('print command execution profile')),
3897 ('', 'profile', None, _('print command execution profile')),
3898 ('', 'version', None, _('output version information and exit')),
3898 ('', 'version', None, _('output version information and exit')),
3899 ('h', 'help', None, _('display help and exit')),
3899 ('h', 'help', None, _('display help and exit')),
3900 ]
3900 ]
3901
3901
3902 dryrunopts = [('n', 'dry-run', None,
3902 dryrunopts = [('n', 'dry-run', None,
3903 _('do not perform actions, just print output'))]
3903 _('do not perform actions, just print output'))]
3904
3904
3905 remoteopts = [
3905 remoteopts = [
3906 ('e', 'ssh', '',
3906 ('e', 'ssh', '',
3907 _('specify ssh command to use'), _('CMD')),
3907 _('specify ssh command to use'), _('CMD')),
3908 ('', 'remotecmd', '',
3908 ('', 'remotecmd', '',
3909 _('specify hg command to run on the remote side'), _('CMD')),
3909 _('specify hg command to run on the remote side'), _('CMD')),
3910 ]
3910 ]
3911
3911
3912 walkopts = [
3912 walkopts = [
3913 ('I', 'include', [],
3913 ('I', 'include', [],
3914 _('include names matching the given patterns'), _('PATTERN')),
3914 _('include names matching the given patterns'), _('PATTERN')),
3915 ('X', 'exclude', [],
3915 ('X', 'exclude', [],
3916 _('exclude names matching the given patterns'), _('PATTERN')),
3916 _('exclude names matching the given patterns'), _('PATTERN')),
3917 ]
3917 ]
3918
3918
3919 commitopts = [
3919 commitopts = [
3920 ('m', 'message', '',
3920 ('m', 'message', '',
3921 _('use text as commit message'), _('TEXT')),
3921 _('use text as commit message'), _('TEXT')),
3922 ('l', 'logfile', '',
3922 ('l', 'logfile', '',
3923 _('read commit message from file'), _('FILE')),
3923 _('read commit message from file'), _('FILE')),
3924 ]
3924 ]
3925
3925
3926 commitopts2 = [
3926 commitopts2 = [
3927 ('d', 'date', '',
3927 ('d', 'date', '',
3928 _('record datecode as commit date'), _('DATE')),
3928 _('record datecode as commit date'), _('DATE')),
3929 ('u', 'user', '',
3929 ('u', 'user', '',
3930 _('record the specified user as committer'), _('USER')),
3930 _('record the specified user as committer'), _('USER')),
3931 ]
3931 ]
3932
3932
3933 templateopts = [
3933 templateopts = [
3934 ('', 'style', '',
3934 ('', 'style', '',
3935 _('display using template map file'), _('STYLE')),
3935 _('display using template map file'), _('STYLE')),
3936 ('', 'template', '',
3936 ('', 'template', '',
3937 _('display with template'), _('TEMPLATE')),
3937 _('display with template'), _('TEMPLATE')),
3938 ]
3938 ]
3939
3939
3940 logopts = [
3940 logopts = [
3941 ('p', 'patch', None, _('show patch')),
3941 ('p', 'patch', None, _('show patch')),
3942 ('g', 'git', None, _('use git extended diff format')),
3942 ('g', 'git', None, _('use git extended diff format')),
3943 ('l', 'limit', '',
3943 ('l', 'limit', '',
3944 _('limit number of changes displayed'), _('NUM')),
3944 _('limit number of changes displayed'), _('NUM')),
3945 ('M', 'no-merges', None, _('do not show merges')),
3945 ('M', 'no-merges', None, _('do not show merges')),
3946 ('', 'stat', None, _('output diffstat-style summary of changes')),
3946 ('', 'stat', None, _('output diffstat-style summary of changes')),
3947 ] + templateopts
3947 ] + templateopts
3948
3948
3949 diffopts = [
3949 diffopts = [
3950 ('a', 'text', None, _('treat all files as text')),
3950 ('a', 'text', None, _('treat all files as text')),
3951 ('g', 'git', None, _('use git extended diff format')),
3951 ('g', 'git', None, _('use git extended diff format')),
3952 ('', 'nodates', None, _('omit dates from diff headers'))
3952 ('', 'nodates', None, _('omit dates from diff headers'))
3953 ]
3953 ]
3954
3954
3955 diffopts2 = [
3955 diffopts2 = [
3956 ('p', 'show-function', None, _('show which function each change is in')),
3956 ('p', 'show-function', None, _('show which function each change is in')),
3957 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3957 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3958 ('w', 'ignore-all-space', None,
3958 ('w', 'ignore-all-space', None,
3959 _('ignore white space when comparing lines')),
3959 _('ignore white space when comparing lines')),
3960 ('b', 'ignore-space-change', None,
3960 ('b', 'ignore-space-change', None,
3961 _('ignore changes in the amount of white space')),
3961 _('ignore changes in the amount of white space')),
3962 ('B', 'ignore-blank-lines', None,
3962 ('B', 'ignore-blank-lines', None,
3963 _('ignore changes whose lines are all blank')),
3963 _('ignore changes whose lines are all blank')),
3964 ('U', 'unified', '',
3964 ('U', 'unified', '',
3965 _('number of lines of context to show'), _('NUM')),
3965 _('number of lines of context to show'), _('NUM')),
3966 ('', 'stat', None, _('output diffstat-style summary of changes')),
3966 ('', 'stat', None, _('output diffstat-style summary of changes')),
3967 ]
3967 ]
3968
3968
3969 similarityopts = [
3969 similarityopts = [
3970 ('s', 'similarity', '',
3970 ('s', 'similarity', '',
3971 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3971 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3972 ]
3972 ]
3973
3973
3974 subrepoopts = [
3974 subrepoopts = [
3975 ('S', 'subrepos', None,
3975 ('S', 'subrepos', None,
3976 _('recurse into subrepositories'))
3976 _('recurse into subrepositories'))
3977 ]
3977 ]
3978
3978
3979 table = {
3979 table = {
3980 "^add": (add, walkopts + subrepoopts + dryrunopts,
3980 "^add": (add, walkopts + subrepoopts + dryrunopts,
3981 _('[OPTION]... [FILE]...')),
3981 _('[OPTION]... [FILE]...')),
3982 "addremove":
3982 "addremove":
3983 (addremove, similarityopts + walkopts + dryrunopts,
3983 (addremove, similarityopts + walkopts + dryrunopts,
3984 _('[OPTION]... [FILE]...')),
3984 _('[OPTION]... [FILE]...')),
3985 "^annotate|blame":
3985 "^annotate|blame":
3986 (annotate,
3986 (annotate,
3987 [('r', 'rev', '',
3987 [('r', 'rev', '',
3988 _('annotate the specified revision'), _('REV')),
3988 _('annotate the specified revision'), _('REV')),
3989 ('', 'follow', None,
3989 ('', 'follow', None,
3990 _('follow copies/renames and list the filename (DEPRECATED)')),
3990 _('follow copies/renames and list the filename (DEPRECATED)')),
3991 ('', 'no-follow', None, _("don't follow copies and renames")),
3991 ('', 'no-follow', None, _("don't follow copies and renames")),
3992 ('a', 'text', None, _('treat all files as text')),
3992 ('a', 'text', None, _('treat all files as text')),
3993 ('u', 'user', None, _('list the author (long with -v)')),
3993 ('u', 'user', None, _('list the author (long with -v)')),
3994 ('f', 'file', None, _('list the filename')),
3994 ('f', 'file', None, _('list the filename')),
3995 ('d', 'date', None, _('list the date (short with -q)')),
3995 ('d', 'date', None, _('list the date (short with -q)')),
3996 ('n', 'number', None, _('list the revision number (default)')),
3996 ('n', 'number', None, _('list the revision number (default)')),
3997 ('c', 'changeset', None, _('list the changeset')),
3997 ('c', 'changeset', None, _('list the changeset')),
3998 ('l', 'line-number', None,
3998 ('l', 'line-number', None,
3999 _('show line number at the first appearance'))
3999 _('show line number at the first appearance'))
4000 ] + walkopts,
4000 ] + walkopts,
4001 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4001 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4002 "archive":
4002 "archive":
4003 (archive,
4003 (archive,
4004 [('', 'no-decode', None, _('do not pass files through decoders')),
4004 [('', 'no-decode', None, _('do not pass files through decoders')),
4005 ('p', 'prefix', '',
4005 ('p', 'prefix', '',
4006 _('directory prefix for files in archive'), _('PREFIX')),
4006 _('directory prefix for files in archive'), _('PREFIX')),
4007 ('r', 'rev', '',
4007 ('r', 'rev', '',
4008 _('revision to distribute'), _('REV')),
4008 _('revision to distribute'), _('REV')),
4009 ('t', 'type', '',
4009 ('t', 'type', '',
4010 _('type of distribution to create'), _('TYPE')),
4010 _('type of distribution to create'), _('TYPE')),
4011 ] + subrepoopts + walkopts,
4011 ] + subrepoopts + walkopts,
4012 _('[OPTION]... DEST')),
4012 _('[OPTION]... DEST')),
4013 "backout":
4013 "backout":
4014 (backout,
4014 (backout,
4015 [('', 'merge', None,
4015 [('', 'merge', None,
4016 _('merge with old dirstate parent after backout')),
4016 _('merge with old dirstate parent after backout')),
4017 ('', 'parent', '',
4017 ('', 'parent', '',
4018 _('parent to choose when backing out merge'), _('REV')),
4018 _('parent to choose when backing out merge'), _('REV')),
4019 ('t', 'tool', '',
4019 ('t', 'tool', '',
4020 _('specify merge tool')),
4020 _('specify merge tool')),
4021 ('r', 'rev', '',
4021 ('r', 'rev', '',
4022 _('revision to backout'), _('REV')),
4022 _('revision to backout'), _('REV')),
4023 ] + walkopts + commitopts + commitopts2,
4023 ] + walkopts + commitopts + commitopts2,
4024 _('[OPTION]... [-r] REV')),
4024 _('[OPTION]... [-r] REV')),
4025 "bisect":
4025 "bisect":
4026 (bisect,
4026 (bisect,
4027 [('r', 'reset', False, _('reset bisect state')),
4027 [('r', 'reset', False, _('reset bisect state')),
4028 ('g', 'good', False, _('mark changeset good')),
4028 ('g', 'good', False, _('mark changeset good')),
4029 ('b', 'bad', False, _('mark changeset bad')),
4029 ('b', 'bad', False, _('mark changeset bad')),
4030 ('s', 'skip', False, _('skip testing changeset')),
4030 ('s', 'skip', False, _('skip testing changeset')),
4031 ('c', 'command', '',
4031 ('c', 'command', '',
4032 _('use command to check changeset state'), _('CMD')),
4032 _('use command to check changeset state'), _('CMD')),
4033 ('U', 'noupdate', False, _('do not update to target'))],
4033 ('U', 'noupdate', False, _('do not update to target'))],
4034 _("[-gbsr] [-U] [-c CMD] [REV]")),
4034 _("[-gbsr] [-U] [-c CMD] [REV]")),
4035 "branch":
4035 "branch":
4036 (branch,
4036 (branch,
4037 [('f', 'force', None,
4037 [('f', 'force', None,
4038 _('set branch name even if it shadows an existing branch')),
4038 _('set branch name even if it shadows an existing branch')),
4039 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4039 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4040 _('[-fC] [NAME]')),
4040 _('[-fC] [NAME]')),
4041 "branches":
4041 "branches":
4042 (branches,
4042 (branches,
4043 [('a', 'active', False,
4043 [('a', 'active', False,
4044 _('show only branches that have unmerged heads')),
4044 _('show only branches that have unmerged heads')),
4045 ('c', 'closed', False,
4045 ('c', 'closed', False,
4046 _('show normal and closed branches'))],
4046 _('show normal and closed branches'))],
4047 _('[-ac]')),
4047 _('[-ac]')),
4048 "bundle":
4048 "bundle":
4049 (bundle,
4049 (bundle,
4050 [('f', 'force', None,
4050 [('f', 'force', None,
4051 _('run even when the destination is unrelated')),
4051 _('run even when the destination is unrelated')),
4052 ('r', 'rev', [],
4052 ('r', 'rev', [],
4053 _('a changeset intended to be added to the destination'),
4053 _('a changeset intended to be added to the destination'),
4054 _('REV')),
4054 _('REV')),
4055 ('b', 'branch', [],
4055 ('b', 'branch', [],
4056 _('a specific branch you would like to bundle'),
4056 _('a specific branch you would like to bundle'),
4057 _('BRANCH')),
4057 _('BRANCH')),
4058 ('', 'base', [],
4058 ('', 'base', [],
4059 _('a base changeset assumed to be available at the destination'),
4059 _('a base changeset assumed to be available at the destination'),
4060 _('REV')),
4060 _('REV')),
4061 ('a', 'all', None, _('bundle all changesets in the repository')),
4061 ('a', 'all', None, _('bundle all changesets in the repository')),
4062 ('t', 'type', 'bzip2',
4062 ('t', 'type', 'bzip2',
4063 _('bundle compression type to use'), _('TYPE')),
4063 _('bundle compression type to use'), _('TYPE')),
4064 ] + remoteopts,
4064 ] + remoteopts,
4065 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4065 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4066 "cat":
4066 "cat":
4067 (cat,
4067 (cat,
4068 [('o', 'output', '',
4068 [('o', 'output', '',
4069 _('print output to file with formatted name'), _('FORMAT')),
4069 _('print output to file with formatted name'), _('FORMAT')),
4070 ('r', 'rev', '',
4070 ('r', 'rev', '',
4071 _('print the given revision'), _('REV')),
4071 _('print the given revision'), _('REV')),
4072 ('', 'decode', None, _('apply any matching decode filter')),
4072 ('', 'decode', None, _('apply any matching decode filter')),
4073 ] + walkopts,
4073 ] + walkopts,
4074 _('[OPTION]... FILE...')),
4074 _('[OPTION]... FILE...')),
4075 "^clone":
4075 "^clone":
4076 (clone,
4076 (clone,
4077 [('U', 'noupdate', None,
4077 [('U', 'noupdate', None,
4078 _('the clone will include an empty working copy (only a repository)')),
4078 _('the clone will include an empty working copy (only a repository)')),
4079 ('u', 'updaterev', '',
4079 ('u', 'updaterev', '',
4080 _('revision, tag or branch to check out'), _('REV')),
4080 _('revision, tag or branch to check out'), _('REV')),
4081 ('r', 'rev', [],
4081 ('r', 'rev', [],
4082 _('include the specified changeset'), _('REV')),
4082 _('include the specified changeset'), _('REV')),
4083 ('b', 'branch', [],
4083 ('b', 'branch', [],
4084 _('clone only the specified branch'), _('BRANCH')),
4084 _('clone only the specified branch'), _('BRANCH')),
4085 ('', 'pull', None, _('use pull protocol to copy metadata')),
4085 ('', 'pull', None, _('use pull protocol to copy metadata')),
4086 ('', 'uncompressed', None,
4086 ('', 'uncompressed', None,
4087 _('use uncompressed transfer (fast over LAN)')),
4087 _('use uncompressed transfer (fast over LAN)')),
4088 ] + remoteopts,
4088 ] + remoteopts,
4089 _('[OPTION]... SOURCE [DEST]')),
4089 _('[OPTION]... SOURCE [DEST]')),
4090 "^commit|ci":
4090 "^commit|ci":
4091 (commit,
4091 (commit,
4092 [('A', 'addremove', None,
4092 [('A', 'addremove', None,
4093 _('mark new/missing files as added/removed before committing')),
4093 _('mark new/missing files as added/removed before committing')),
4094 ('', 'close-branch', None,
4094 ('', 'close-branch', None,
4095 _('mark a branch as closed, hiding it from the branch list')),
4095 _('mark a branch as closed, hiding it from the branch list')),
4096 ] + walkopts + commitopts + commitopts2,
4096 ] + walkopts + commitopts + commitopts2,
4097 _('[OPTION]... [FILE]...')),
4097 _('[OPTION]... [FILE]...')),
4098 "copy|cp":
4098 "copy|cp":
4099 (copy,
4099 (copy,
4100 [('A', 'after', None, _('record a copy that has already occurred')),
4100 [('A', 'after', None, _('record a copy that has already occurred')),
4101 ('f', 'force', None,
4101 ('f', 'force', None,
4102 _('forcibly copy over an existing managed file')),
4102 _('forcibly copy over an existing managed file')),
4103 ] + walkopts + dryrunopts,
4103 ] + walkopts + dryrunopts,
4104 _('[OPTION]... [SOURCE]... DEST')),
4104 _('[OPTION]... [SOURCE]... DEST')),
4105 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4105 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4106 "debugbuilddag":
4106 "debugbuilddag":
4107 (debugbuilddag,
4107 (debugbuilddag,
4108 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4108 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4109 ('a', 'appended-file', None, _('add single file all revs append to')),
4109 ('a', 'appended-file', None, _('add single file all revs append to')),
4110 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4110 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4111 ('n', 'new-file', None, _('add new file at each rev')),
4111 ('n', 'new-file', None, _('add new file at each rev')),
4112 ],
4112 ],
4113 _('[OPTION]... TEXT')),
4113 _('[OPTION]... TEXT')),
4114 "debugcheckstate": (debugcheckstate, [], ''),
4114 "debugcheckstate": (debugcheckstate, [], ''),
4115 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4115 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4116 "debugcomplete":
4116 "debugcomplete":
4117 (debugcomplete,
4117 (debugcomplete,
4118 [('o', 'options', None, _('show the command options'))],
4118 [('o', 'options', None, _('show the command options'))],
4119 _('[-o] CMD')),
4119 _('[-o] CMD')),
4120 "debugdag":
4120 "debugdag":
4121 (debugdag,
4121 (debugdag,
4122 [('t', 'tags', None, _('use tags as labels')),
4122 [('t', 'tags', None, _('use tags as labels')),
4123 ('b', 'branches', None, _('annotate with branch names')),
4123 ('b', 'branches', None, _('annotate with branch names')),
4124 ('', 'dots', None, _('use dots for runs')),
4124 ('', 'dots', None, _('use dots for runs')),
4125 ('s', 'spaces', None, _('separate elements by spaces')),
4125 ('s', 'spaces', None, _('separate elements by spaces')),
4126 ],
4126 ],
4127 _('[OPTION]... [FILE [REV]...]')),
4127 _('[OPTION]... [FILE [REV]...]')),
4128 "debugdate":
4128 "debugdate":
4129 (debugdate,
4129 (debugdate,
4130 [('e', 'extended', None, _('try extended date formats'))],
4130 [('e', 'extended', None, _('try extended date formats'))],
4131 _('[-e] DATE [RANGE]')),
4131 _('[-e] DATE [RANGE]')),
4132 "debugdata": (debugdata, [], _('FILE REV')),
4132 "debugdata": (debugdata, [], _('FILE REV')),
4133 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4133 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4134 "debugindex": (debugindex, [], _('FILE')),
4134 "debugindex": (debugindex, [], _('FILE')),
4135 "debugindexdot": (debugindexdot, [], _('FILE')),
4135 "debugindexdot": (debugindexdot, [], _('FILE')),
4136 "debuginstall": (debuginstall, [], ''),
4136 "debuginstall": (debuginstall, [], ''),
4137 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4137 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4138 "debugrebuildstate":
4138 "debugrebuildstate":
4139 (debugrebuildstate,
4139 (debugrebuildstate,
4140 [('r', 'rev', '',
4140 [('r', 'rev', '',
4141 _('revision to rebuild to'), _('REV'))],
4141 _('revision to rebuild to'), _('REV'))],
4142 _('[-r REV] [REV]')),
4142 _('[-r REV] [REV]')),
4143 "debugrename":
4143 "debugrename":
4144 (debugrename,
4144 (debugrename,
4145 [('r', 'rev', '',
4145 [('r', 'rev', '',
4146 _('revision to debug'), _('REV'))],
4146 _('revision to debug'), _('REV'))],
4147 _('[-r REV] FILE')),
4147 _('[-r REV] FILE')),
4148 "debugrevspec":
4148 "debugrevspec":
4149 (debugrevspec, [], ('REVSPEC')),
4149 (debugrevspec, [], ('REVSPEC')),
4150 "debugsetparents":
4150 "debugsetparents":
4151 (debugsetparents, [], _('REV1 [REV2]')),
4151 (debugsetparents, [], _('REV1 [REV2]')),
4152 "debugstate":
4152 "debugstate":
4153 (debugstate,
4153 (debugstate,
4154 [('', 'nodates', None, _('do not display the saved mtime'))],
4154 [('', 'nodates', None, _('do not display the saved mtime'))],
4155 _('[OPTION]...')),
4155 _('[OPTION]...')),
4156 "debugsub":
4156 "debugsub":
4157 (debugsub,
4157 (debugsub,
4158 [('r', 'rev', '',
4158 [('r', 'rev', '',
4159 _('revision to check'), _('REV'))],
4159 _('revision to check'), _('REV'))],
4160 _('[-r REV] [REV]')),
4160 _('[-r REV] [REV]')),
4161 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4161 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4162 "^diff":
4162 "^diff":
4163 (diff,
4163 (diff,
4164 [('r', 'rev', [],
4164 [('r', 'rev', [],
4165 _('revision'), _('REV')),
4165 _('revision'), _('REV')),
4166 ('c', 'change', '',
4166 ('c', 'change', '',
4167 _('change made by revision'), _('REV'))
4167 _('change made by revision'), _('REV'))
4168 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4168 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4169 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4169 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4170 "^export":
4170 "^export":
4171 (export,
4171 (export,
4172 [('o', 'output', '',
4172 [('o', 'output', '',
4173 _('print output to file with formatted name'), _('FORMAT')),
4173 _('print output to file with formatted name'), _('FORMAT')),
4174 ('', 'switch-parent', None, _('diff against the second parent')),
4174 ('', 'switch-parent', None, _('diff against the second parent')),
4175 ('r', 'rev', [],
4175 ('r', 'rev', [],
4176 _('revisions to export'), _('REV')),
4176 _('revisions to export'), _('REV')),
4177 ] + diffopts,
4177 ] + diffopts,
4178 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4178 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4179 "^forget":
4179 "^forget":
4180 (forget,
4180 (forget,
4181 [] + walkopts,
4181 [] + walkopts,
4182 _('[OPTION]... FILE...')),
4182 _('[OPTION]... FILE...')),
4183 "grep":
4183 "grep":
4184 (grep,
4184 (grep,
4185 [('0', 'print0', None, _('end fields with NUL')),
4185 [('0', 'print0', None, _('end fields with NUL')),
4186 ('', 'all', None, _('print all revisions that match')),
4186 ('', 'all', None, _('print all revisions that match')),
4187 ('f', 'follow', None,
4187 ('f', 'follow', None,
4188 _('follow changeset history,'
4188 _('follow changeset history,'
4189 ' or file history across copies and renames')),
4189 ' or file history across copies and renames')),
4190 ('i', 'ignore-case', None, _('ignore case when matching')),
4190 ('i', 'ignore-case', None, _('ignore case when matching')),
4191 ('l', 'files-with-matches', None,
4191 ('l', 'files-with-matches', None,
4192 _('print only filenames and revisions that match')),
4192 _('print only filenames and revisions that match')),
4193 ('n', 'line-number', None, _('print matching line numbers')),
4193 ('n', 'line-number', None, _('print matching line numbers')),
4194 ('r', 'rev', [],
4194 ('r', 'rev', [],
4195 _('only search files changed within revision range'), _('REV')),
4195 _('only search files changed within revision range'), _('REV')),
4196 ('u', 'user', None, _('list the author (long with -v)')),
4196 ('u', 'user', None, _('list the author (long with -v)')),
4197 ('d', 'date', None, _('list the date (short with -q)')),
4197 ('d', 'date', None, _('list the date (short with -q)')),
4198 ] + walkopts,
4198 ] + walkopts,
4199 _('[OPTION]... PATTERN [FILE]...')),
4199 _('[OPTION]... PATTERN [FILE]...')),
4200 "heads":
4200 "heads":
4201 (heads,
4201 (heads,
4202 [('r', 'rev', '',
4202 [('r', 'rev', '',
4203 _('show only heads which are descendants of STARTREV'),
4203 _('show only heads which are descendants of STARTREV'),
4204 _('STARTREV')),
4204 _('STARTREV')),
4205 ('t', 'topo', False, _('show topological heads only')),
4205 ('t', 'topo', False, _('show topological heads only')),
4206 ('a', 'active', False,
4206 ('a', 'active', False,
4207 _('show active branchheads only (DEPRECATED)')),
4207 _('show active branchheads only (DEPRECATED)')),
4208 ('c', 'closed', False,
4208 ('c', 'closed', False,
4209 _('show normal and closed branch heads')),
4209 _('show normal and closed branch heads')),
4210 ] + templateopts,
4210 ] + templateopts,
4211 _('[-ac] [-r STARTREV] [REV]...')),
4211 _('[-ac] [-r STARTREV] [REV]...')),
4212 "help": (help_, [], _('[TOPIC]')),
4212 "help": (help_, [], _('[TOPIC]')),
4213 "identify|id":
4213 "identify|id":
4214 (identify,
4214 (identify,
4215 [('r', 'rev', '',
4215 [('r', 'rev', '',
4216 _('identify the specified revision'), _('REV')),
4216 _('identify the specified revision'), _('REV')),
4217 ('n', 'num', None, _('show local revision number')),
4217 ('n', 'num', None, _('show local revision number')),
4218 ('i', 'id', None, _('show global revision id')),
4218 ('i', 'id', None, _('show global revision id')),
4219 ('b', 'branch', None, _('show branch')),
4219 ('b', 'branch', None, _('show branch')),
4220 ('t', 'tags', None, _('show tags'))],
4220 ('t', 'tags', None, _('show tags'))],
4221 _('[-nibt] [-r REV] [SOURCE]')),
4221 _('[-nibt] [-r REV] [SOURCE]')),
4222 "import|patch":
4222 "import|patch":
4223 (import_,
4223 (import_,
4224 [('p', 'strip', 1,
4224 [('p', 'strip', 1,
4225 _('directory strip option for patch. This has the same '
4225 _('directory strip option for patch. This has the same '
4226 'meaning as the corresponding patch option'),
4226 'meaning as the corresponding patch option'),
4227 _('NUM')),
4227 _('NUM')),
4228 ('b', 'base', '',
4228 ('b', 'base', '',
4229 _('base path'), _('PATH')),
4229 _('base path'), _('PATH')),
4230 ('f', 'force', None,
4230 ('f', 'force', None,
4231 _('skip check for outstanding uncommitted changes')),
4231 _('skip check for outstanding uncommitted changes')),
4232 ('', 'no-commit', None,
4232 ('', 'no-commit', None,
4233 _("don't commit, just update the working directory")),
4233 _("don't commit, just update the working directory")),
4234 ('', 'exact', None,
4234 ('', 'exact', None,
4235 _('apply patch to the nodes from which it was generated')),
4235 _('apply patch to the nodes from which it was generated')),
4236 ('', 'import-branch', None,
4236 ('', 'import-branch', None,
4237 _('use any branch information in patch (implied by --exact)'))] +
4237 _('use any branch information in patch (implied by --exact)'))] +
4238 commitopts + commitopts2 + similarityopts,
4238 commitopts + commitopts2 + similarityopts,
4239 _('[OPTION]... PATCH...')),
4239 _('[OPTION]... PATCH...')),
4240 "incoming|in":
4240 "incoming|in":
4241 (incoming,
4241 (incoming,
4242 [('f', 'force', None,
4242 [('f', 'force', None,
4243 _('run even if remote repository is unrelated')),
4243 _('run even if remote repository is unrelated')),
4244 ('n', 'newest-first', None, _('show newest record first')),
4244 ('n', 'newest-first', None, _('show newest record first')),
4245 ('', 'bundle', '',
4245 ('', 'bundle', '',
4246 _('file to store the bundles into'), _('FILE')),
4246 _('file to store the bundles into'), _('FILE')),
4247 ('r', 'rev', [],
4247 ('r', 'rev', [],
4248 _('a remote changeset intended to be added'), _('REV')),
4248 _('a remote changeset intended to be added'), _('REV')),
4249 ('b', 'branch', [],
4249 ('b', 'branch', [],
4250 _('a specific branch you would like to pull'), _('BRANCH')),
4250 _('a specific branch you would like to pull'), _('BRANCH')),
4251 ] + logopts + remoteopts + subrepoopts,
4251 ] + logopts + remoteopts + subrepoopts,
4252 _('[-p] [-n] [-M] [-f] [-r REV]...'
4252 _('[-p] [-n] [-M] [-f] [-r REV]...'
4253 ' [--bundle FILENAME] [SOURCE]')),
4253 ' [--bundle FILENAME] [SOURCE]')),
4254 "^init":
4254 "^init":
4255 (init,
4255 (init,
4256 remoteopts,
4256 remoteopts,
4257 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4257 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4258 "locate":
4258 "locate":
4259 (locate,
4259 (locate,
4260 [('r', 'rev', '',
4260 [('r', 'rev', '',
4261 _('search the repository as it is in REV'), _('REV')),
4261 _('search the repository as it is in REV'), _('REV')),
4262 ('0', 'print0', None,
4262 ('0', 'print0', None,
4263 _('end filenames with NUL, for use with xargs')),
4263 _('end filenames with NUL, for use with xargs')),
4264 ('f', 'fullpath', None,
4264 ('f', 'fullpath', None,
4265 _('print complete paths from the filesystem root')),
4265 _('print complete paths from the filesystem root')),
4266 ] + walkopts,
4266 ] + walkopts,
4267 _('[OPTION]... [PATTERN]...')),
4267 _('[OPTION]... [PATTERN]...')),
4268 "^log|history":
4268 "^log|history":
4269 (log,
4269 (log,
4270 [('f', 'follow', None,
4270 [('f', 'follow', None,
4271 _('follow changeset history,'
4271 _('follow changeset history,'
4272 ' or file history across copies and renames')),
4272 ' or file history across copies and renames')),
4273 ('', 'follow-first', None,
4273 ('', 'follow-first', None,
4274 _('only follow the first parent of merge changesets')),
4274 _('only follow the first parent of merge changesets')),
4275 ('d', 'date', '',
4275 ('d', 'date', '',
4276 _('show revisions matching date spec'), _('DATE')),
4276 _('show revisions matching date spec'), _('DATE')),
4277 ('C', 'copies', None, _('show copied files')),
4277 ('C', 'copies', None, _('show copied files')),
4278 ('k', 'keyword', [],
4278 ('k', 'keyword', [],
4279 _('do case-insensitive search for a given text'), _('TEXT')),
4279 _('do case-insensitive search for a given text'), _('TEXT')),
4280 ('r', 'rev', [],
4280 ('r', 'rev', [],
4281 _('show the specified revision or range'), _('REV')),
4281 _('show the specified revision or range'), _('REV')),
4282 ('', 'removed', None, _('include revisions where files were removed')),
4282 ('', 'removed', None, _('include revisions where files were removed')),
4283 ('m', 'only-merges', None, _('show only merges')),
4283 ('m', 'only-merges', None, _('show only merges')),
4284 ('u', 'user', [],
4284 ('u', 'user', [],
4285 _('revisions committed by user'), _('USER')),
4285 _('revisions committed by user'), _('USER')),
4286 ('', 'only-branch', [],
4286 ('', 'only-branch', [],
4287 _('show only changesets within the given named branch (DEPRECATED)'),
4287 _('show only changesets within the given named branch (DEPRECATED)'),
4288 _('BRANCH')),
4288 _('BRANCH')),
4289 ('b', 'branch', [],
4289 ('b', 'branch', [],
4290 _('show changesets within the given named branch'), _('BRANCH')),
4290 _('show changesets within the given named branch'), _('BRANCH')),
4291 ('P', 'prune', [],
4291 ('P', 'prune', [],
4292 _('do not display revision or any of its ancestors'), _('REV')),
4292 _('do not display revision or any of its ancestors'), _('REV')),
4293 ] + logopts + walkopts,
4293 ] + logopts + walkopts,
4294 _('[OPTION]... [FILE]')),
4294 _('[OPTION]... [FILE]')),
4295 "manifest":
4295 "manifest":
4296 (manifest,
4296 (manifest,
4297 [('r', 'rev', '',
4297 [('r', 'rev', '',
4298 _('revision to display'), _('REV'))],
4298 _('revision to display'), _('REV'))],
4299 _('[-r REV]')),
4299 _('[-r REV]')),
4300 "^merge":
4300 "^merge":
4301 (merge,
4301 (merge,
4302 [('f', 'force', None, _('force a merge with outstanding changes')),
4302 [('f', 'force', None, _('force a merge with outstanding changes')),
4303 ('t', 'tool', '', _('specify merge tool')),
4303 ('t', 'tool', '', _('specify merge tool')),
4304 ('r', 'rev', '',
4304 ('r', 'rev', '',
4305 _('revision to merge'), _('REV')),
4305 _('revision to merge'), _('REV')),
4306 ('P', 'preview', None,
4306 ('P', 'preview', None,
4307 _('review revisions to merge (no merge is performed)'))],
4307 _('review revisions to merge (no merge is performed)'))],
4308 _('[-P] [-f] [[-r] REV]')),
4308 _('[-P] [-f] [[-r] REV]')),
4309 "outgoing|out":
4309 "outgoing|out":
4310 (outgoing,
4310 (outgoing,
4311 [('f', 'force', None,
4311 [('f', 'force', None,
4312 _('run even when the destination is unrelated')),
4312 _('run even when the destination is unrelated')),
4313 ('r', 'rev', [],
4313 ('r', 'rev', [],
4314 _('a changeset intended to be included in the destination'),
4314 _('a changeset intended to be included in the destination'),
4315 _('REV')),
4315 _('REV')),
4316 ('n', 'newest-first', None, _('show newest record first')),
4316 ('n', 'newest-first', None, _('show newest record first')),
4317 ('b', 'branch', [],
4317 ('b', 'branch', [],
4318 _('a specific branch you would like to push'), _('BRANCH')),
4318 _('a specific branch you would like to push'), _('BRANCH')),
4319 ] + logopts + remoteopts + subrepoopts,
4319 ] + logopts + remoteopts + subrepoopts,
4320 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4320 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4321 "parents":
4321 "parents":
4322 (parents,
4322 (parents,
4323 [('r', 'rev', '',
4323 [('r', 'rev', '',
4324 _('show parents of the specified revision'), _('REV')),
4324 _('show parents of the specified revision'), _('REV')),
4325 ] + templateopts,
4325 ] + templateopts,
4326 _('[-r REV] [FILE]')),
4326 _('[-r REV] [FILE]')),
4327 "paths": (paths, [], _('[NAME]')),
4327 "paths": (paths, [], _('[NAME]')),
4328 "^pull":
4328 "^pull":
4329 (pull,
4329 (pull,
4330 [('u', 'update', None,
4330 [('u', 'update', None,
4331 _('update to new branch head if changesets were pulled')),
4331 _('update to new branch head if changesets were pulled')),
4332 ('f', 'force', None,
4332 ('f', 'force', None,
4333 _('run even when remote repository is unrelated')),
4333 _('run even when remote repository is unrelated')),
4334 ('r', 'rev', [],
4334 ('r', 'rev', [],
4335 _('a remote changeset intended to be added'), _('REV')),
4335 _('a remote changeset intended to be added'), _('REV')),
4336 ('b', 'branch', [],
4336 ('b', 'branch', [],
4337 _('a specific branch you would like to pull'), _('BRANCH')),
4337 _('a specific branch you would like to pull'), _('BRANCH')),
4338 ] + remoteopts,
4338 ] + remoteopts,
4339 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4339 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4340 "^push":
4340 "^push":
4341 (push,
4341 (push,
4342 [('f', 'force', None, _('force push')),
4342 [('f', 'force', None, _('force push')),
4343 ('r', 'rev', [],
4343 ('r', 'rev', [],
4344 _('a changeset intended to be included in the destination'),
4344 _('a changeset intended to be included in the destination'),
4345 _('REV')),
4345 _('REV')),
4346 ('b', 'branch', [],
4346 ('b', 'branch', [],
4347 _('a specific branch you would like to push'), _('BRANCH')),
4347 _('a specific branch you would like to push'), _('BRANCH')),
4348 ('', 'new-branch', False, _('allow pushing a new branch')),
4348 ('', 'new-branch', False, _('allow pushing a new branch')),
4349 ] + remoteopts,
4349 ] + remoteopts,
4350 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4350 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4351 "recover": (recover, []),
4351 "recover": (recover, []),
4352 "^remove|rm":
4352 "^remove|rm":
4353 (remove,
4353 (remove,
4354 [('A', 'after', None, _('record delete for missing files')),
4354 [('A', 'after', None, _('record delete for missing files')),
4355 ('f', 'force', None,
4355 ('f', 'force', None,
4356 _('remove (and delete) file even if added or modified')),
4356 _('remove (and delete) file even if added or modified')),
4357 ] + walkopts,
4357 ] + walkopts,
4358 _('[OPTION]... FILE...')),
4358 _('[OPTION]... FILE...')),
4359 "rename|move|mv":
4359 "rename|move|mv":
4360 (rename,
4360 (rename,
4361 [('A', 'after', None, _('record a rename that has already occurred')),
4361 [('A', 'after', None, _('record a rename that has already occurred')),
4362 ('f', 'force', None,
4362 ('f', 'force', None,
4363 _('forcibly copy over an existing managed file')),
4363 _('forcibly copy over an existing managed file')),
4364 ] + walkopts + dryrunopts,
4364 ] + walkopts + dryrunopts,
4365 _('[OPTION]... SOURCE... DEST')),
4365 _('[OPTION]... SOURCE... DEST')),
4366 "resolve":
4366 "resolve":
4367 (resolve,
4367 (resolve,
4368 [('a', 'all', None, _('select all unresolved files')),
4368 [('a', 'all', None, _('select all unresolved files')),
4369 ('l', 'list', None, _('list state of files needing merge')),
4369 ('l', 'list', None, _('list state of files needing merge')),
4370 ('m', 'mark', None, _('mark files as resolved')),
4370 ('m', 'mark', None, _('mark files as resolved')),
4371 ('u', 'unmark', None, _('mark files as unresolved')),
4371 ('u', 'unmark', None, _('mark files as unresolved')),
4372 ('t', 'tool', '', _('specify merge tool')),
4372 ('t', 'tool', '', _('specify merge tool')),
4373 ('n', 'no-status', None, _('hide status prefix'))]
4373 ('n', 'no-status', None, _('hide status prefix'))]
4374 + walkopts,
4374 + walkopts,
4375 _('[OPTION]... [FILE]...')),
4375 _('[OPTION]... [FILE]...')),
4376 "revert":
4376 "revert":
4377 (revert,
4377 (revert,
4378 [('a', 'all', None, _('revert all changes when no arguments given')),
4378 [('a', 'all', None, _('revert all changes when no arguments given')),
4379 ('d', 'date', '',
4379 ('d', 'date', '',
4380 _('tipmost revision matching date'), _('DATE')),
4380 _('tipmost revision matching date'), _('DATE')),
4381 ('r', 'rev', '',
4381 ('r', 'rev', '',
4382 _('revert to the specified revision'), _('REV')),
4382 _('revert to the specified revision'), _('REV')),
4383 ('', 'no-backup', None, _('do not save backup copies of files')),
4383 ('', 'no-backup', None, _('do not save backup copies of files')),
4384 ] + walkopts + dryrunopts,
4384 ] + walkopts + dryrunopts,
4385 _('[OPTION]... [-r REV] [NAME]...')),
4385 _('[OPTION]... [-r REV] [NAME]...')),
4386 "rollback": (rollback, dryrunopts),
4386 "rollback": (rollback, dryrunopts),
4387 "root": (root, []),
4387 "root": (root, []),
4388 "^serve":
4388 "^serve":
4389 (serve,
4389 (serve,
4390 [('A', 'accesslog', '',
4390 [('A', 'accesslog', '',
4391 _('name of access log file to write to'), _('FILE')),
4391 _('name of access log file to write to'), _('FILE')),
4392 ('d', 'daemon', None, _('run server in background')),
4392 ('d', 'daemon', None, _('run server in background')),
4393 ('', 'daemon-pipefds', '',
4393 ('', 'daemon-pipefds', '',
4394 _('used internally by daemon mode'), _('NUM')),
4394 _('used internally by daemon mode'), _('NUM')),
4395 ('E', 'errorlog', '',
4395 ('E', 'errorlog', '',
4396 _('name of error log file to write to'), _('FILE')),
4396 _('name of error log file to write to'), _('FILE')),
4397 # use string type, then we can check if something was passed
4397 # use string type, then we can check if something was passed
4398 ('p', 'port', '',
4398 ('p', 'port', '',
4399 _('port to listen on (default: 8000)'), _('PORT')),
4399 _('port to listen on (default: 8000)'), _('PORT')),
4400 ('a', 'address', '',
4400 ('a', 'address', '',
4401 _('address to listen on (default: all interfaces)'), _('ADDR')),
4401 _('address to listen on (default: all interfaces)'), _('ADDR')),
4402 ('', 'prefix', '',
4402 ('', 'prefix', '',
4403 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4403 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4404 ('n', 'name', '',
4404 ('n', 'name', '',
4405 _('name to show in web pages (default: working directory)'),
4405 _('name to show in web pages (default: working directory)'),
4406 _('NAME')),
4406 _('NAME')),
4407 ('', 'web-conf', '',
4407 ('', 'web-conf', '',
4408 _('name of the hgweb config file (see "hg help hgweb")'),
4408 _('name of the hgweb config file (see "hg help hgweb")'),
4409 _('FILE')),
4409 _('FILE')),
4410 ('', 'webdir-conf', '',
4410 ('', 'webdir-conf', '',
4411 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4411 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4412 ('', 'pid-file', '',
4412 ('', 'pid-file', '',
4413 _('name of file to write process ID to'), _('FILE')),
4413 _('name of file to write process ID to'), _('FILE')),
4414 ('', 'stdio', None, _('for remote clients')),
4414 ('', 'stdio', None, _('for remote clients')),
4415 ('t', 'templates', '',
4415 ('t', 'templates', '',
4416 _('web templates to use'), _('TEMPLATE')),
4416 _('web templates to use'), _('TEMPLATE')),
4417 ('', 'style', '',
4417 ('', 'style', '',
4418 _('template style to use'), _('STYLE')),
4418 _('template style to use'), _('STYLE')),
4419 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4419 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4420 ('', 'certificate', '',
4420 ('', 'certificate', '',
4421 _('SSL certificate file'), _('FILE'))],
4421 _('SSL certificate file'), _('FILE'))],
4422 _('[OPTION]...')),
4422 _('[OPTION]...')),
4423 "showconfig|debugconfig":
4423 "showconfig|debugconfig":
4424 (showconfig,
4424 (showconfig,
4425 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4425 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4426 _('[-u] [NAME]...')),
4426 _('[-u] [NAME]...')),
4427 "^summary|sum":
4427 "^summary|sum":
4428 (summary,
4428 (summary,
4429 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4429 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4430 "^status|st":
4430 "^status|st":
4431 (status,
4431 (status,
4432 [('A', 'all', None, _('show status of all files')),
4432 [('A', 'all', None, _('show status of all files')),
4433 ('m', 'modified', None, _('show only modified files')),
4433 ('m', 'modified', None, _('show only modified files')),
4434 ('a', 'added', None, _('show only added files')),
4434 ('a', 'added', None, _('show only added files')),
4435 ('r', 'removed', None, _('show only removed files')),
4435 ('r', 'removed', None, _('show only removed files')),
4436 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4436 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4437 ('c', 'clean', None, _('show only files without changes')),
4437 ('c', 'clean', None, _('show only files without changes')),
4438 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4438 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4439 ('i', 'ignored', None, _('show only ignored files')),
4439 ('i', 'ignored', None, _('show only ignored files')),
4440 ('n', 'no-status', None, _('hide status prefix')),
4440 ('n', 'no-status', None, _('hide status prefix')),
4441 ('C', 'copies', None, _('show source of copied files')),
4441 ('C', 'copies', None, _('show source of copied files')),
4442 ('0', 'print0', None,
4442 ('0', 'print0', None,
4443 _('end filenames with NUL, for use with xargs')),
4443 _('end filenames with NUL, for use with xargs')),
4444 ('', 'rev', [],
4444 ('', 'rev', [],
4445 _('show difference from revision'), _('REV')),
4445 _('show difference from revision'), _('REV')),
4446 ('', 'change', '',
4446 ('', 'change', '',
4447 _('list the changed files of a revision'), _('REV')),
4447 _('list the changed files of a revision'), _('REV')),
4448 ] + walkopts + subrepoopts,
4448 ] + walkopts + subrepoopts,
4449 _('[OPTION]... [FILE]...')),
4449 _('[OPTION]... [FILE]...')),
4450 "tag":
4450 "tag":
4451 (tag,
4451 (tag,
4452 [('f', 'force', None, _('replace existing tag')),
4452 [('f', 'force', None, _('replace existing tag')),
4453 ('l', 'local', None, _('make the tag local')),
4453 ('l', 'local', None, _('make the tag local')),
4454 ('r', 'rev', '',
4454 ('r', 'rev', '',
4455 _('revision to tag'), _('REV')),
4455 _('revision to tag'), _('REV')),
4456 ('', 'remove', None, _('remove a tag')),
4456 ('', 'remove', None, _('remove a tag')),
4457 # -l/--local is already there, commitopts cannot be used
4457 # -l/--local is already there, commitopts cannot be used
4458 ('e', 'edit', None, _('edit commit message')),
4458 ('e', 'edit', None, _('edit commit message')),
4459 ('m', 'message', '',
4459 ('m', 'message', '',
4460 _('use <text> as commit message'), _('TEXT')),
4460 _('use <text> as commit message'), _('TEXT')),
4461 ] + commitopts2,
4461 ] + commitopts2,
4462 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4462 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4463 "tags": (tags, [], ''),
4463 "tags": (tags, [], ''),
4464 "tip":
4464 "tip":
4465 (tip,
4465 (tip,
4466 [('p', 'patch', None, _('show patch')),
4466 [('p', 'patch', None, _('show patch')),
4467 ('g', 'git', None, _('use git extended diff format')),
4467 ('g', 'git', None, _('use git extended diff format')),
4468 ] + templateopts,
4468 ] + templateopts,
4469 _('[-p] [-g]')),
4469 _('[-p] [-g]')),
4470 "unbundle":
4470 "unbundle":
4471 (unbundle,
4471 (unbundle,
4472 [('u', 'update', None,
4472 [('u', 'update', None,
4473 _('update to new branch head if changesets were unbundled'))],
4473 _('update to new branch head if changesets were unbundled'))],
4474 _('[-u] FILE...')),
4474 _('[-u] FILE...')),
4475 "^update|up|checkout|co":
4475 "^update|up|checkout|co":
4476 (update,
4476 (update,
4477 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4477 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4478 ('c', 'check', None,
4478 ('c', 'check', None,
4479 _('update across branches if no uncommitted changes')),
4479 _('update across branches if no uncommitted changes')),
4480 ('d', 'date', '',
4480 ('d', 'date', '',
4481 _('tipmost revision matching date'), _('DATE')),
4481 _('tipmost revision matching date'), _('DATE')),
4482 ('r', 'rev', '',
4482 ('r', 'rev', '',
4483 _('revision'), _('REV'))],
4483 _('revision'), _('REV'))],
4484 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4484 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4485 "verify": (verify, []),
4485 "verify": (verify, []),
4486 "version": (version_, []),
4486 "version": (version_, []),
4487 }
4487 }
4488
4488
4489 norepo = ("clone init version help debugcommands debugcomplete"
4489 norepo = ("clone init version help debugcommands debugcomplete"
4490 " debugdate debuginstall debugfsinfo debugpushkey")
4490 " debugdate debuginstall debugfsinfo debugpushkey")
4491 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4491 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4492 " debugdata debugindex debugindexdot")
4492 " debugdata debugindex debugindexdot")
@@ -1,642 +1,641
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 of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback, re
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback, re
10 import util, commands, hg, fancyopts, extensions, hook, error
10 import util, commands, hg, fancyopts, extensions, hook, error
11 import cmdutil, encoding
11 import cmdutil, encoding
12 import ui as uimod
12 import ui as uimod
13
13
14 def run():
14 def run():
15 "run the command in sys.argv"
15 "run the command in sys.argv"
16 sys.exit(dispatch(sys.argv[1:]))
16 sys.exit(dispatch(sys.argv[1:]))
17
17
18 def dispatch(args):
18 def dispatch(args):
19 "run the command specified in args"
19 "run the command specified in args"
20 try:
20 try:
21 u = uimod.ui()
21 u = uimod.ui()
22 if '--traceback' in args:
22 if '--traceback' in args:
23 u.setconfig('ui', 'traceback', 'on')
23 u.setconfig('ui', 'traceback', 'on')
24 except util.Abort, inst:
24 except util.Abort, inst:
25 sys.stderr.write(_("abort: %s\n") % inst)
25 sys.stderr.write(_("abort: %s\n") % inst)
26 if inst.hint:
26 if inst.hint:
27 sys.stderr.write(_("(%s)\n") % inst.hint)
27 sys.stderr.write(_("(%s)\n") % inst.hint)
28 return -1
28 return -1
29 except error.ParseError, inst:
29 except error.ParseError, inst:
30 if len(inst.args) > 1:
30 if len(inst.args) > 1:
31 sys.stderr.write(_("hg: parse error at %s: %s\n") %
31 sys.stderr.write(_("hg: parse error at %s: %s\n") %
32 (inst.args[1], inst.args[0]))
32 (inst.args[1], inst.args[0]))
33 else:
33 else:
34 sys.stderr.write(_("hg: parse error: %s\n") % inst.args[0])
34 sys.stderr.write(_("hg: parse error: %s\n") % inst.args[0])
35 return -1
35 return -1
36 return _runcatch(u, args)
36 return _runcatch(u, args)
37
37
38 def _runcatch(ui, args):
38 def _runcatch(ui, args):
39 def catchterm(*args):
39 def catchterm(*args):
40 raise error.SignalInterrupt
40 raise error.SignalInterrupt
41
41
42 try:
42 try:
43 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
43 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
44 num = getattr(signal, name, None)
44 num = getattr(signal, name, None)
45 if num:
45 if num:
46 signal.signal(num, catchterm)
46 signal.signal(num, catchterm)
47 except ValueError:
47 except ValueError:
48 pass # happens if called in a thread
48 pass # happens if called in a thread
49
49
50 try:
50 try:
51 try:
51 try:
52 # enter the debugger before command execution
52 # enter the debugger before command execution
53 if '--debugger' in args:
53 if '--debugger' in args:
54 ui.warn(_("entering debugger - "
54 ui.warn(_("entering debugger - "
55 "type c to continue starting hg or h for help\n"))
55 "type c to continue starting hg or h for help\n"))
56 pdb.set_trace()
56 pdb.set_trace()
57 try:
57 try:
58 return _dispatch(ui, args)
58 return _dispatch(ui, args)
59 finally:
59 finally:
60 ui.flush()
60 ui.flush()
61 except:
61 except:
62 # enter the debugger when we hit an exception
62 # enter the debugger when we hit an exception
63 if '--debugger' in args:
63 if '--debugger' in args:
64 traceback.print_exc()
64 traceback.print_exc()
65 pdb.post_mortem(sys.exc_info()[2])
65 pdb.post_mortem(sys.exc_info()[2])
66 ui.traceback()
66 ui.traceback()
67 raise
67 raise
68
68
69 # Global exception handling, alphabetically
69 # Global exception handling, alphabetically
70 # Mercurial-specific first, followed by built-in and library exceptions
70 # Mercurial-specific first, followed by built-in and library exceptions
71 except error.AmbiguousCommand, inst:
71 except error.AmbiguousCommand, inst:
72 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
72 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
73 (inst.args[0], " ".join(inst.args[1])))
73 (inst.args[0], " ".join(inst.args[1])))
74 except error.ParseError, inst:
74 except error.ParseError, inst:
75 if len(inst.args) > 1:
75 if len(inst.args) > 1:
76 ui.warn(_("hg: parse error at %s: %s\n") %
76 ui.warn(_("hg: parse error at %s: %s\n") %
77 (inst.args[1], inst.args[0]))
77 (inst.args[1], inst.args[0]))
78 else:
78 else:
79 ui.warn(_("hg: parse error: %s\n") % inst.args[0])
79 ui.warn(_("hg: parse error: %s\n") % inst.args[0])
80 return -1
80 return -1
81 except error.LockHeld, inst:
81 except error.LockHeld, inst:
82 if inst.errno == errno.ETIMEDOUT:
82 if inst.errno == errno.ETIMEDOUT:
83 reason = _('timed out waiting for lock held by %s') % inst.locker
83 reason = _('timed out waiting for lock held by %s') % inst.locker
84 else:
84 else:
85 reason = _('lock held by %s') % inst.locker
85 reason = _('lock held by %s') % inst.locker
86 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
86 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
87 except error.LockUnavailable, inst:
87 except error.LockUnavailable, inst:
88 ui.warn(_("abort: could not lock %s: %s\n") %
88 ui.warn(_("abort: could not lock %s: %s\n") %
89 (inst.desc or inst.filename, inst.strerror))
89 (inst.desc or inst.filename, inst.strerror))
90 except error.CommandError, inst:
90 except error.CommandError, inst:
91 if inst.args[0]:
91 if inst.args[0]:
92 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
92 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
93 commands.help_(ui, inst.args[0])
93 commands.help_(ui, inst.args[0])
94 else:
94 else:
95 ui.warn(_("hg: %s\n") % inst.args[1])
95 ui.warn(_("hg: %s\n") % inst.args[1])
96 commands.help_(ui, 'shortlist')
96 commands.help_(ui, 'shortlist')
97 except error.RepoError, inst:
97 except error.RepoError, inst:
98 ui.warn(_("abort: %s!\n") % inst)
98 ui.warn(_("abort: %s!\n") % inst)
99 except error.ResponseError, inst:
99 except error.ResponseError, inst:
100 ui.warn(_("abort: %s") % inst.args[0])
100 ui.warn(_("abort: %s") % inst.args[0])
101 if not isinstance(inst.args[1], basestring):
101 if not isinstance(inst.args[1], basestring):
102 ui.warn(" %r\n" % (inst.args[1],))
102 ui.warn(" %r\n" % (inst.args[1],))
103 elif not inst.args[1]:
103 elif not inst.args[1]:
104 ui.warn(_(" empty string\n"))
104 ui.warn(_(" empty string\n"))
105 else:
105 else:
106 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
106 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
107 except error.RevlogError, inst:
107 except error.RevlogError, inst:
108 ui.warn(_("abort: %s!\n") % inst)
108 ui.warn(_("abort: %s!\n") % inst)
109 except error.SignalInterrupt:
109 except error.SignalInterrupt:
110 ui.warn(_("killed!\n"))
110 ui.warn(_("killed!\n"))
111 except error.UnknownCommand, inst:
111 except error.UnknownCommand, inst:
112 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
112 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
113 try:
113 try:
114 # check if the command is in a disabled extension
114 # check if the command is in a disabled extension
115 # (but don't check for extensions themselves)
115 # (but don't check for extensions themselves)
116 commands.help_(ui, inst.args[0], unknowncmd=True)
116 commands.help_(ui, inst.args[0], unknowncmd=True)
117 except error.UnknownCommand:
117 except error.UnknownCommand:
118 commands.help_(ui, 'shortlist')
118 commands.help_(ui, 'shortlist')
119 except util.Abort, inst:
119 except util.Abort, inst:
120 ui.warn(_("abort: %s\n") % inst)
120 ui.warn(_("abort: %s\n") % inst)
121 if inst.hint:
121 if inst.hint:
122 ui.warn(_("(%s)\n") % inst.hint)
122 ui.warn(_("(%s)\n") % inst.hint)
123 except ImportError, inst:
123 except ImportError, inst:
124 ui.warn(_("abort: %s!\n") % inst)
124 ui.warn(_("abort: %s!\n") % inst)
125 m = str(inst).split()[-1]
125 m = str(inst).split()[-1]
126 if m in "mpatch bdiff".split():
126 if m in "mpatch bdiff".split():
127 ui.warn(_("(did you forget to compile extensions?)\n"))
127 ui.warn(_("(did you forget to compile extensions?)\n"))
128 elif m in "zlib".split():
128 elif m in "zlib".split():
129 ui.warn(_("(is your Python install correct?)\n"))
129 ui.warn(_("(is your Python install correct?)\n"))
130 except IOError, inst:
130 except IOError, inst:
131 if hasattr(inst, "code"):
131 if hasattr(inst, "code"):
132 ui.warn(_("abort: %s\n") % inst)
132 ui.warn(_("abort: %s\n") % inst)
133 elif hasattr(inst, "reason"):
133 elif hasattr(inst, "reason"):
134 try: # usually it is in the form (errno, strerror)
134 try: # usually it is in the form (errno, strerror)
135 reason = inst.reason.args[1]
135 reason = inst.reason.args[1]
136 except: # it might be anything, for example a string
136 except: # it might be anything, for example a string
137 reason = inst.reason
137 reason = inst.reason
138 ui.warn(_("abort: error: %s\n") % reason)
138 ui.warn(_("abort: error: %s\n") % reason)
139 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
139 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
140 if ui.debugflag:
140 if ui.debugflag:
141 ui.warn(_("broken pipe\n"))
141 ui.warn(_("broken pipe\n"))
142 elif getattr(inst, "strerror", None):
142 elif getattr(inst, "strerror", None):
143 if getattr(inst, "filename", None):
143 if getattr(inst, "filename", None):
144 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
144 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
145 else:
145 else:
146 ui.warn(_("abort: %s\n") % inst.strerror)
146 ui.warn(_("abort: %s\n") % inst.strerror)
147 else:
147 else:
148 raise
148 raise
149 except OSError, inst:
149 except OSError, inst:
150 if getattr(inst, "filename", None):
150 if getattr(inst, "filename", None):
151 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
151 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
152 else:
152 else:
153 ui.warn(_("abort: %s\n") % inst.strerror)
153 ui.warn(_("abort: %s\n") % inst.strerror)
154 except KeyboardInterrupt:
154 except KeyboardInterrupt:
155 try:
155 try:
156 ui.warn(_("interrupted!\n"))
156 ui.warn(_("interrupted!\n"))
157 except IOError, inst:
157 except IOError, inst:
158 if inst.errno == errno.EPIPE:
158 if inst.errno == errno.EPIPE:
159 if ui.debugflag:
159 if ui.debugflag:
160 ui.warn(_("\nbroken pipe\n"))
160 ui.warn(_("\nbroken pipe\n"))
161 else:
161 else:
162 raise
162 raise
163 except MemoryError:
163 except MemoryError:
164 ui.warn(_("abort: out of memory\n"))
164 ui.warn(_("abort: out of memory\n"))
165 except SystemExit, inst:
165 except SystemExit, inst:
166 # Commands shouldn't sys.exit directly, but give a return code.
166 # Commands shouldn't sys.exit directly, but give a return code.
167 # Just in case catch this and and pass exit code to caller.
167 # Just in case catch this and and pass exit code to caller.
168 return inst.code
168 return inst.code
169 except socket.error, inst:
169 except socket.error, inst:
170 ui.warn(_("abort: %s\n") % inst.args[-1])
170 ui.warn(_("abort: %s\n") % inst.args[-1])
171 except:
171 except:
172 ui.warn(_("** unknown exception encountered, details follow\n"))
172 ui.warn(_("** unknown exception encountered,"
173 ui.warn(_("** report bug details to "
173 " please report by visiting\n"))
174 "http://mercurial.selenic.com/bts/\n"))
174 ui.warn(_("** http://mercurial.selenic.com/wiki/BugTracker\n"))
175 ui.warn(_("** or mercurial@selenic.com\n"))
176 ui.warn(_("** Python %s\n") % sys.version.replace('\n', ''))
175 ui.warn(_("** Python %s\n") % sys.version.replace('\n', ''))
177 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
176 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
178 % util.version())
177 % util.version())
179 ui.warn(_("** Extensions loaded: %s\n")
178 ui.warn(_("** Extensions loaded: %s\n")
180 % ", ".join([x[0] for x in extensions.extensions()]))
179 % ", ".join([x[0] for x in extensions.extensions()]))
181 raise
180 raise
182
181
183 return -1
182 return -1
184
183
185 def aliasargs(fn):
184 def aliasargs(fn):
186 if hasattr(fn, 'args'):
185 if hasattr(fn, 'args'):
187 return fn.args
186 return fn.args
188 return []
187 return []
189
188
190 class cmdalias(object):
189 class cmdalias(object):
191 def __init__(self, name, definition, cmdtable):
190 def __init__(self, name, definition, cmdtable):
192 self.name = self.cmd = name
191 self.name = self.cmd = name
193 self.cmdname = ''
192 self.cmdname = ''
194 self.definition = definition
193 self.definition = definition
195 self.args = []
194 self.args = []
196 self.opts = []
195 self.opts = []
197 self.help = ''
196 self.help = ''
198 self.norepo = True
197 self.norepo = True
199 self.badalias = False
198 self.badalias = False
200
199
201 try:
200 try:
202 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
201 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
203 for alias, e in cmdtable.iteritems():
202 for alias, e in cmdtable.iteritems():
204 if e is entry:
203 if e is entry:
205 self.cmd = alias
204 self.cmd = alias
206 break
205 break
207 self.shadows = True
206 self.shadows = True
208 except error.UnknownCommand:
207 except error.UnknownCommand:
209 self.shadows = False
208 self.shadows = False
210
209
211 if not self.definition:
210 if not self.definition:
212 def fn(ui, *args):
211 def fn(ui, *args):
213 ui.warn(_("no definition for alias '%s'\n") % self.name)
212 ui.warn(_("no definition for alias '%s'\n") % self.name)
214 return 1
213 return 1
215 self.fn = fn
214 self.fn = fn
216 self.badalias = True
215 self.badalias = True
217
216
218 return
217 return
219
218
220 if self.definition.startswith('!'):
219 if self.definition.startswith('!'):
221 self.shell = True
220 self.shell = True
222 def fn(ui, *args):
221 def fn(ui, *args):
223 env = {'HG_ARGS': ' '.join((self.name,) + args)}
222 env = {'HG_ARGS': ' '.join((self.name,) + args)}
224 def _checkvar(m):
223 def _checkvar(m):
225 if int(m.groups()[0]) <= len(args):
224 if int(m.groups()[0]) <= len(args):
226 return m.group()
225 return m.group()
227 else:
226 else:
228 return ''
227 return ''
229 cmd = re.sub(r'\$(\d+)', _checkvar, self.definition[1:])
228 cmd = re.sub(r'\$(\d+)', _checkvar, self.definition[1:])
230 replace = dict((str(i + 1), arg) for i, arg in enumerate(args))
229 replace = dict((str(i + 1), arg) for i, arg in enumerate(args))
231 replace['0'] = self.name
230 replace['0'] = self.name
232 replace['@'] = ' '.join(args)
231 replace['@'] = ' '.join(args)
233 cmd = util.interpolate(r'\$', replace, cmd)
232 cmd = util.interpolate(r'\$', replace, cmd)
234 return util.system(cmd, environ=env)
233 return util.system(cmd, environ=env)
235 self.fn = fn
234 self.fn = fn
236 return
235 return
237
236
238 args = shlex.split(self.definition)
237 args = shlex.split(self.definition)
239 self.cmdname = cmd = args.pop(0)
238 self.cmdname = cmd = args.pop(0)
240 args = map(util.expandpath, args)
239 args = map(util.expandpath, args)
241
240
242 for invalidarg in ("--cwd", "-R", "--repository", "--repo"):
241 for invalidarg in ("--cwd", "-R", "--repository", "--repo"):
243 if _earlygetopt([invalidarg], args):
242 if _earlygetopt([invalidarg], args):
244 def fn(ui, *args):
243 def fn(ui, *args):
245 ui.warn(_("error in definition for alias '%s': %s may only "
244 ui.warn(_("error in definition for alias '%s': %s may only "
246 "be given on the command line\n")
245 "be given on the command line\n")
247 % (self.name, invalidarg))
246 % (self.name, invalidarg))
248 return 1
247 return 1
249
248
250 self.fn = fn
249 self.fn = fn
251 self.badalias = True
250 self.badalias = True
252 return
251 return
253
252
254 try:
253 try:
255 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
254 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
256 if len(tableentry) > 2:
255 if len(tableentry) > 2:
257 self.fn, self.opts, self.help = tableentry
256 self.fn, self.opts, self.help = tableentry
258 else:
257 else:
259 self.fn, self.opts = tableentry
258 self.fn, self.opts = tableentry
260
259
261 self.args = aliasargs(self.fn) + args
260 self.args = aliasargs(self.fn) + args
262 if cmd not in commands.norepo.split(' '):
261 if cmd not in commands.norepo.split(' '):
263 self.norepo = False
262 self.norepo = False
264 if self.help.startswith("hg " + cmd):
263 if self.help.startswith("hg " + cmd):
265 # drop prefix in old-style help lines so hg shows the alias
264 # drop prefix in old-style help lines so hg shows the alias
266 self.help = self.help[4 + len(cmd):]
265 self.help = self.help[4 + len(cmd):]
267 self.__doc__ = self.fn.__doc__
266 self.__doc__ = self.fn.__doc__
268
267
269 except error.UnknownCommand:
268 except error.UnknownCommand:
270 def fn(ui, *args):
269 def fn(ui, *args):
271 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
270 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
272 % (self.name, cmd))
271 % (self.name, cmd))
273 try:
272 try:
274 # check if the command is in a disabled extension
273 # check if the command is in a disabled extension
275 commands.help_(ui, cmd, unknowncmd=True)
274 commands.help_(ui, cmd, unknowncmd=True)
276 except error.UnknownCommand:
275 except error.UnknownCommand:
277 pass
276 pass
278 return 1
277 return 1
279 self.fn = fn
278 self.fn = fn
280 self.badalias = True
279 self.badalias = True
281 except error.AmbiguousCommand:
280 except error.AmbiguousCommand:
282 def fn(ui, *args):
281 def fn(ui, *args):
283 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
282 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
284 % (self.name, cmd))
283 % (self.name, cmd))
285 return 1
284 return 1
286 self.fn = fn
285 self.fn = fn
287 self.badalias = True
286 self.badalias = True
288
287
289 def __call__(self, ui, *args, **opts):
288 def __call__(self, ui, *args, **opts):
290 if self.shadows:
289 if self.shadows:
291 ui.debug("alias '%s' shadows command '%s'\n" %
290 ui.debug("alias '%s' shadows command '%s'\n" %
292 (self.name, self.cmdname))
291 (self.name, self.cmdname))
293
292
294 if self.definition.startswith('!'):
293 if self.definition.startswith('!'):
295 return self.fn(ui, *args, **opts)
294 return self.fn(ui, *args, **opts)
296 else:
295 else:
297 try:
296 try:
298 util.checksignature(self.fn)(ui, *args, **opts)
297 util.checksignature(self.fn)(ui, *args, **opts)
299 except error.SignatureError:
298 except error.SignatureError:
300 args = ' '.join([self.cmdname] + self.args)
299 args = ' '.join([self.cmdname] + self.args)
301 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
300 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
302 raise
301 raise
303
302
304 def addaliases(ui, cmdtable):
303 def addaliases(ui, cmdtable):
305 # aliases are processed after extensions have been loaded, so they
304 # aliases are processed after extensions have been loaded, so they
306 # may use extension commands. Aliases can also use other alias definitions,
305 # may use extension commands. Aliases can also use other alias definitions,
307 # but only if they have been defined prior to the current definition.
306 # but only if they have been defined prior to the current definition.
308 for alias, definition in ui.configitems('alias'):
307 for alias, definition in ui.configitems('alias'):
309 aliasdef = cmdalias(alias, definition, cmdtable)
308 aliasdef = cmdalias(alias, definition, cmdtable)
310 cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help)
309 cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help)
311 if aliasdef.norepo:
310 if aliasdef.norepo:
312 commands.norepo += ' %s' % alias
311 commands.norepo += ' %s' % alias
313
312
314 def _parse(ui, args):
313 def _parse(ui, args):
315 options = {}
314 options = {}
316 cmdoptions = {}
315 cmdoptions = {}
317
316
318 try:
317 try:
319 args = fancyopts.fancyopts(args, commands.globalopts, options)
318 args = fancyopts.fancyopts(args, commands.globalopts, options)
320 except fancyopts.getopt.GetoptError, inst:
319 except fancyopts.getopt.GetoptError, inst:
321 raise error.CommandError(None, inst)
320 raise error.CommandError(None, inst)
322
321
323 if args:
322 if args:
324 cmd, args = args[0], args[1:]
323 cmd, args = args[0], args[1:]
325 aliases, entry = cmdutil.findcmd(cmd, commands.table,
324 aliases, entry = cmdutil.findcmd(cmd, commands.table,
326 ui.config("ui", "strict"))
325 ui.config("ui", "strict"))
327 cmd = aliases[0]
326 cmd = aliases[0]
328 args = aliasargs(entry[0]) + args
327 args = aliasargs(entry[0]) + args
329 defaults = ui.config("defaults", cmd)
328 defaults = ui.config("defaults", cmd)
330 if defaults:
329 if defaults:
331 args = map(util.expandpath, shlex.split(defaults)) + args
330 args = map(util.expandpath, shlex.split(defaults)) + args
332 c = list(entry[1])
331 c = list(entry[1])
333 else:
332 else:
334 cmd = None
333 cmd = None
335 c = []
334 c = []
336
335
337 # combine global options into local
336 # combine global options into local
338 for o in commands.globalopts:
337 for o in commands.globalopts:
339 c.append((o[0], o[1], options[o[1]], o[3]))
338 c.append((o[0], o[1], options[o[1]], o[3]))
340
339
341 try:
340 try:
342 args = fancyopts.fancyopts(args, c, cmdoptions, True)
341 args = fancyopts.fancyopts(args, c, cmdoptions, True)
343 except fancyopts.getopt.GetoptError, inst:
342 except fancyopts.getopt.GetoptError, inst:
344 raise error.CommandError(cmd, inst)
343 raise error.CommandError(cmd, inst)
345
344
346 # separate global options back out
345 # separate global options back out
347 for o in commands.globalopts:
346 for o in commands.globalopts:
348 n = o[1]
347 n = o[1]
349 options[n] = cmdoptions[n]
348 options[n] = cmdoptions[n]
350 del cmdoptions[n]
349 del cmdoptions[n]
351
350
352 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
351 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
353
352
354 def _parseconfig(ui, config):
353 def _parseconfig(ui, config):
355 """parse the --config options from the command line"""
354 """parse the --config options from the command line"""
356 for cfg in config:
355 for cfg in config:
357 try:
356 try:
358 name, value = cfg.split('=', 1)
357 name, value = cfg.split('=', 1)
359 section, name = name.split('.', 1)
358 section, name = name.split('.', 1)
360 if not section or not name:
359 if not section or not name:
361 raise IndexError
360 raise IndexError
362 ui.setconfig(section, name, value)
361 ui.setconfig(section, name, value)
363 except (IndexError, ValueError):
362 except (IndexError, ValueError):
364 raise util.Abort(_('malformed --config option: %r '
363 raise util.Abort(_('malformed --config option: %r '
365 '(use --config section.name=value)') % cfg)
364 '(use --config section.name=value)') % cfg)
366
365
367 def _earlygetopt(aliases, args):
366 def _earlygetopt(aliases, args):
368 """Return list of values for an option (or aliases).
367 """Return list of values for an option (or aliases).
369
368
370 The values are listed in the order they appear in args.
369 The values are listed in the order they appear in args.
371 The options and values are removed from args.
370 The options and values are removed from args.
372 """
371 """
373 try:
372 try:
374 argcount = args.index("--")
373 argcount = args.index("--")
375 except ValueError:
374 except ValueError:
376 argcount = len(args)
375 argcount = len(args)
377 shortopts = [opt for opt in aliases if len(opt) == 2]
376 shortopts = [opt for opt in aliases if len(opt) == 2]
378 values = []
377 values = []
379 pos = 0
378 pos = 0
380 while pos < argcount:
379 while pos < argcount:
381 if args[pos] in aliases:
380 if args[pos] in aliases:
382 if pos + 1 >= argcount:
381 if pos + 1 >= argcount:
383 # ignore and let getopt report an error if there is no value
382 # ignore and let getopt report an error if there is no value
384 break
383 break
385 del args[pos]
384 del args[pos]
386 values.append(args.pop(pos))
385 values.append(args.pop(pos))
387 argcount -= 2
386 argcount -= 2
388 elif args[pos][:2] in shortopts:
387 elif args[pos][:2] in shortopts:
389 # short option can have no following space, e.g. hg log -Rfoo
388 # short option can have no following space, e.g. hg log -Rfoo
390 values.append(args.pop(pos)[2:])
389 values.append(args.pop(pos)[2:])
391 argcount -= 1
390 argcount -= 1
392 else:
391 else:
393 pos += 1
392 pos += 1
394 return values
393 return values
395
394
396 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
395 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
397 # run pre-hook, and abort if it fails
396 # run pre-hook, and abort if it fails
398 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
397 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
399 pats=cmdpats, opts=cmdoptions)
398 pats=cmdpats, opts=cmdoptions)
400 if ret:
399 if ret:
401 return ret
400 return ret
402 ret = _runcommand(ui, options, cmd, d)
401 ret = _runcommand(ui, options, cmd, d)
403 # run post-hook, passing command result
402 # run post-hook, passing command result
404 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
403 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
405 result=ret, pats=cmdpats, opts=cmdoptions)
404 result=ret, pats=cmdpats, opts=cmdoptions)
406 return ret
405 return ret
407
406
408 def _getlocal(ui, rpath):
407 def _getlocal(ui, rpath):
409 """Return (path, local ui object) for the given target path.
408 """Return (path, local ui object) for the given target path.
410
409
411 Takes paths in [cwd]/.hg/hgrc into account."
410 Takes paths in [cwd]/.hg/hgrc into account."
412 """
411 """
413 try:
412 try:
414 wd = os.getcwd()
413 wd = os.getcwd()
415 except OSError, e:
414 except OSError, e:
416 raise util.Abort(_("error getting current working directory: %s") %
415 raise util.Abort(_("error getting current working directory: %s") %
417 e.strerror)
416 e.strerror)
418 path = cmdutil.findrepo(wd) or ""
417 path = cmdutil.findrepo(wd) or ""
419 if not path:
418 if not path:
420 lui = ui
419 lui = ui
421 else:
420 else:
422 lui = ui.copy()
421 lui = ui.copy()
423 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
422 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
424
423
425 if rpath:
424 if rpath:
426 path = lui.expandpath(rpath[-1])
425 path = lui.expandpath(rpath[-1])
427 lui = ui.copy()
426 lui = ui.copy()
428 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
427 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
429
428
430 return path, lui
429 return path, lui
431
430
432 def _checkshellalias(ui, args):
431 def _checkshellalias(ui, args):
433 cwd = os.getcwd()
432 cwd = os.getcwd()
434 norepo = commands.norepo
433 norepo = commands.norepo
435 options = {}
434 options = {}
436
435
437 try:
436 try:
438 args = fancyopts.fancyopts(args, commands.globalopts, options)
437 args = fancyopts.fancyopts(args, commands.globalopts, options)
439 except fancyopts.getopt.GetoptError:
438 except fancyopts.getopt.GetoptError:
440 return
439 return
441
440
442 if not args:
441 if not args:
443 return
442 return
444
443
445 _parseconfig(ui, options['config'])
444 _parseconfig(ui, options['config'])
446 if options['cwd']:
445 if options['cwd']:
447 os.chdir(options['cwd'])
446 os.chdir(options['cwd'])
448
447
449 path, lui = _getlocal(ui, [options['repository']])
448 path, lui = _getlocal(ui, [options['repository']])
450
449
451 cmdtable = commands.table.copy()
450 cmdtable = commands.table.copy()
452 addaliases(lui, cmdtable)
451 addaliases(lui, cmdtable)
453
452
454 cmd = args[0]
453 cmd = args[0]
455 try:
454 try:
456 aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
455 aliases, entry = cmdutil.findcmd(cmd, cmdtable, lui.config("ui", "strict"))
457 except error.UnknownCommand:
456 except error.UnknownCommand:
458 commands.norepo = norepo
457 commands.norepo = norepo
459 os.chdir(cwd)
458 os.chdir(cwd)
460 return
459 return
461
460
462 cmd = aliases[0]
461 cmd = aliases[0]
463 fn = entry[0]
462 fn = entry[0]
464
463
465 if cmd and hasattr(fn, 'shell'):
464 if cmd and hasattr(fn, 'shell'):
466 d = lambda: fn(ui, *args[1:])
465 d = lambda: fn(ui, *args[1:])
467 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
466 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
468
467
469 commands.norepo = norepo
468 commands.norepo = norepo
470 os.chdir(cwd)
469 os.chdir(cwd)
471
470
472 _loaded = set()
471 _loaded = set()
473 def _dispatch(ui, args):
472 def _dispatch(ui, args):
474 shellaliasfn = _checkshellalias(ui, args)
473 shellaliasfn = _checkshellalias(ui, args)
475 if shellaliasfn:
474 if shellaliasfn:
476 return shellaliasfn()
475 return shellaliasfn()
477
476
478 # read --config before doing anything else
477 # read --config before doing anything else
479 # (e.g. to change trust settings for reading .hg/hgrc)
478 # (e.g. to change trust settings for reading .hg/hgrc)
480 _parseconfig(ui, _earlygetopt(['--config'], args))
479 _parseconfig(ui, _earlygetopt(['--config'], args))
481
480
482 # check for cwd
481 # check for cwd
483 cwd = _earlygetopt(['--cwd'], args)
482 cwd = _earlygetopt(['--cwd'], args)
484 if cwd:
483 if cwd:
485 os.chdir(cwd[-1])
484 os.chdir(cwd[-1])
486
485
487 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
486 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
488 path, lui = _getlocal(ui, rpath)
487 path, lui = _getlocal(ui, rpath)
489
488
490 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
489 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
491 # reposetup. Programs like TortoiseHg will call _dispatch several
490 # reposetup. Programs like TortoiseHg will call _dispatch several
492 # times so we keep track of configured extensions in _loaded.
491 # times so we keep track of configured extensions in _loaded.
493 extensions.loadall(lui)
492 extensions.loadall(lui)
494 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
493 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
495 # Propagate any changes to lui.__class__ by extensions
494 # Propagate any changes to lui.__class__ by extensions
496 ui.__class__ = lui.__class__
495 ui.__class__ = lui.__class__
497
496
498 # (uisetup and extsetup are handled in extensions.loadall)
497 # (uisetup and extsetup are handled in extensions.loadall)
499
498
500 for name, module in exts:
499 for name, module in exts:
501 cmdtable = getattr(module, 'cmdtable', {})
500 cmdtable = getattr(module, 'cmdtable', {})
502 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
501 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
503 if overrides:
502 if overrides:
504 ui.warn(_("extension '%s' overrides commands: %s\n")
503 ui.warn(_("extension '%s' overrides commands: %s\n")
505 % (name, " ".join(overrides)))
504 % (name, " ".join(overrides)))
506 commands.table.update(cmdtable)
505 commands.table.update(cmdtable)
507 _loaded.add(name)
506 _loaded.add(name)
508
507
509 # (reposetup is handled in hg.repository)
508 # (reposetup is handled in hg.repository)
510
509
511 addaliases(lui, commands.table)
510 addaliases(lui, commands.table)
512
511
513 # check for fallback encoding
512 # check for fallback encoding
514 fallback = lui.config('ui', 'fallbackencoding')
513 fallback = lui.config('ui', 'fallbackencoding')
515 if fallback:
514 if fallback:
516 encoding.fallbackencoding = fallback
515 encoding.fallbackencoding = fallback
517
516
518 fullargs = args
517 fullargs = args
519 cmd, func, args, options, cmdoptions = _parse(lui, args)
518 cmd, func, args, options, cmdoptions = _parse(lui, args)
520
519
521 if options["config"]:
520 if options["config"]:
522 raise util.Abort(_("option --config may not be abbreviated!"))
521 raise util.Abort(_("option --config may not be abbreviated!"))
523 if options["cwd"]:
522 if options["cwd"]:
524 raise util.Abort(_("option --cwd may not be abbreviated!"))
523 raise util.Abort(_("option --cwd may not be abbreviated!"))
525 if options["repository"]:
524 if options["repository"]:
526 raise util.Abort(_(
525 raise util.Abort(_(
527 "Option -R has to be separated from other options (e.g. not -qR) "
526 "Option -R has to be separated from other options (e.g. not -qR) "
528 "and --repository may only be abbreviated as --repo!"))
527 "and --repository may only be abbreviated as --repo!"))
529
528
530 if options["encoding"]:
529 if options["encoding"]:
531 encoding.encoding = options["encoding"]
530 encoding.encoding = options["encoding"]
532 if options["encodingmode"]:
531 if options["encodingmode"]:
533 encoding.encodingmode = options["encodingmode"]
532 encoding.encodingmode = options["encodingmode"]
534 if options["time"]:
533 if options["time"]:
535 def get_times():
534 def get_times():
536 t = os.times()
535 t = os.times()
537 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
536 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
538 t = (t[0], t[1], t[2], t[3], time.clock())
537 t = (t[0], t[1], t[2], t[3], time.clock())
539 return t
538 return t
540 s = get_times()
539 s = get_times()
541 def print_time():
540 def print_time():
542 t = get_times()
541 t = get_times()
543 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
542 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
544 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
543 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
545 atexit.register(print_time)
544 atexit.register(print_time)
546
545
547 if options['verbose'] or options['debug'] or options['quiet']:
546 if options['verbose'] or options['debug'] or options['quiet']:
548 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
547 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
549 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
548 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
550 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
549 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
551 if options['traceback']:
550 if options['traceback']:
552 ui.setconfig('ui', 'traceback', 'on')
551 ui.setconfig('ui', 'traceback', 'on')
553 if options['noninteractive']:
552 if options['noninteractive']:
554 ui.setconfig('ui', 'interactive', 'off')
553 ui.setconfig('ui', 'interactive', 'off')
555
554
556 if options['help']:
555 if options['help']:
557 return commands.help_(ui, cmd, options['version'])
556 return commands.help_(ui, cmd, options['version'])
558 elif options['version']:
557 elif options['version']:
559 return commands.version_(ui)
558 return commands.version_(ui)
560 elif not cmd:
559 elif not cmd:
561 return commands.help_(ui, 'shortlist')
560 return commands.help_(ui, 'shortlist')
562
561
563 repo = None
562 repo = None
564 cmdpats = args[:]
563 cmdpats = args[:]
565 if cmd not in commands.norepo.split():
564 if cmd not in commands.norepo.split():
566 try:
565 try:
567 repo = hg.repository(ui, path=path)
566 repo = hg.repository(ui, path=path)
568 ui = repo.ui
567 ui = repo.ui
569 if not repo.local():
568 if not repo.local():
570 raise util.Abort(_("repository '%s' is not local") % path)
569 raise util.Abort(_("repository '%s' is not local") % path)
571 ui.setconfig("bundle", "mainreporoot", repo.root)
570 ui.setconfig("bundle", "mainreporoot", repo.root)
572 except error.RepoError:
571 except error.RepoError:
573 if cmd not in commands.optionalrepo.split():
572 if cmd not in commands.optionalrepo.split():
574 if args and not path: # try to infer -R from command args
573 if args and not path: # try to infer -R from command args
575 repos = map(cmdutil.findrepo, args)
574 repos = map(cmdutil.findrepo, args)
576 guess = repos[0]
575 guess = repos[0]
577 if guess and repos.count(guess) == len(repos):
576 if guess and repos.count(guess) == len(repos):
578 return _dispatch(ui, ['--repository', guess] + fullargs)
577 return _dispatch(ui, ['--repository', guess] + fullargs)
579 if not path:
578 if not path:
580 raise error.RepoError(_("There is no Mercurial repository"
579 raise error.RepoError(_("There is no Mercurial repository"
581 " here (.hg not found)"))
580 " here (.hg not found)"))
582 raise
581 raise
583 args.insert(0, repo)
582 args.insert(0, repo)
584 elif rpath:
583 elif rpath:
585 ui.warn(_("warning: --repository ignored\n"))
584 ui.warn(_("warning: --repository ignored\n"))
586
585
587 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
586 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
588 ui.log("command", msg + "\n")
587 ui.log("command", msg + "\n")
589 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
588 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
590 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
589 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
591 cmdpats, cmdoptions)
590 cmdpats, cmdoptions)
592
591
593 def _runcommand(ui, options, cmd, cmdfunc):
592 def _runcommand(ui, options, cmd, cmdfunc):
594 def checkargs():
593 def checkargs():
595 try:
594 try:
596 return cmdfunc()
595 return cmdfunc()
597 except error.SignatureError:
596 except error.SignatureError:
598 raise error.CommandError(cmd, _("invalid arguments"))
597 raise error.CommandError(cmd, _("invalid arguments"))
599
598
600 if options['profile']:
599 if options['profile']:
601 format = ui.config('profiling', 'format', default='text')
600 format = ui.config('profiling', 'format', default='text')
602
601
603 if not format in ['text', 'kcachegrind']:
602 if not format in ['text', 'kcachegrind']:
604 ui.warn(_("unrecognized profiling format '%s'"
603 ui.warn(_("unrecognized profiling format '%s'"
605 " - Ignored\n") % format)
604 " - Ignored\n") % format)
606 format = 'text'
605 format = 'text'
607
606
608 output = ui.config('profiling', 'output')
607 output = ui.config('profiling', 'output')
609
608
610 if output:
609 if output:
611 path = ui.expandpath(output)
610 path = ui.expandpath(output)
612 ostream = open(path, 'wb')
611 ostream = open(path, 'wb')
613 else:
612 else:
614 ostream = sys.stderr
613 ostream = sys.stderr
615
614
616 try:
615 try:
617 from mercurial import lsprof
616 from mercurial import lsprof
618 except ImportError:
617 except ImportError:
619 raise util.Abort(_(
618 raise util.Abort(_(
620 'lsprof not available - install from '
619 'lsprof not available - install from '
621 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
620 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
622 p = lsprof.Profiler()
621 p = lsprof.Profiler()
623 p.enable(subcalls=True)
622 p.enable(subcalls=True)
624 try:
623 try:
625 return checkargs()
624 return checkargs()
626 finally:
625 finally:
627 p.disable()
626 p.disable()
628
627
629 if format == 'kcachegrind':
628 if format == 'kcachegrind':
630 import lsprofcalltree
629 import lsprofcalltree
631 calltree = lsprofcalltree.KCacheGrind(p)
630 calltree = lsprofcalltree.KCacheGrind(p)
632 calltree.output(ostream)
631 calltree.output(ostream)
633 else:
632 else:
634 # format == 'text'
633 # format == 'text'
635 stats = lsprof.Stats(p.getstats())
634 stats = lsprof.Stats(p.getstats())
636 stats.sort()
635 stats.sort()
637 stats.pprint(top=10, file=ostream, climit=5)
636 stats.pprint(top=10, file=ostream, climit=5)
638
637
639 if output:
638 if output:
640 ostream.close()
639 ostream.close()
641 else:
640 else:
642 return checkargs()
641 return checkargs()
General Comments 0
You need to be logged in to leave comments. Login now