##// END OF EJS Templates
ui: yield unchanged values in walkconfig...
Martin Geisler -
r13576:edd06611 default
parent child Browse files
Show More
@@ -1,4748 +1,4749 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms 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, bookmarks
12 import hg, util, revlog, extensions, copies, error, bookmarks
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 = cmdutil.revsingle(repo, opts.get('rev'))
129 ctx = cmdutil.revsingle(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 = cmdutil.revsingle(repo, opts.get('rev'))
181 ctx = cmdutil.revsingle(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 Prepare a new changeset with the effect of REV undone in the
207 Prepare a new changeset with the effect of REV undone in the
208 current working directory.
208 current working directory.
209
209
210 If REV is the parent of the working directory, then this new changeset
210 If REV is the parent of the working directory, then this new changeset
211 is committed automatically. Otherwise, hg needs to merge the
211 is committed automatically. Otherwise, hg needs to merge the
212 changes and the merged result is left uncommitted.
212 changes and the merged result is left uncommitted.
213
213
214 By default, the pending changeset will have one parent,
214 By default, the pending changeset will have one parent,
215 maintaining a linear history. With --merge, the pending changeset
215 maintaining a linear history. With --merge, the pending changeset
216 will instead have two parents: the old parent of the working
216 will instead have two parents: the old parent of the working
217 directory and a new child of REV that simply undoes REV.
217 directory and a new child of REV that simply undoes REV.
218
218
219 Before version 1.7, the behavior without --merge was equivalent to
219 Before version 1.7, the behavior without --merge was equivalent to
220 specifying --merge followed by :hg:`update --clean .` to cancel
220 specifying --merge followed by :hg:`update --clean .` to cancel
221 the merge and leave the child of REV as a head to be merged
221 the merge and leave the child of REV as a head to be merged
222 separately.
222 separately.
223
223
224 See :hg:`help dates` for a list of formats valid for -d/--date.
224 See :hg:`help dates` for a list of formats valid for -d/--date.
225
225
226 Returns 0 on success.
226 Returns 0 on success.
227 '''
227 '''
228 if rev and node:
228 if rev and node:
229 raise util.Abort(_("please specify just one revision"))
229 raise util.Abort(_("please specify just one revision"))
230
230
231 if not rev:
231 if not rev:
232 rev = node
232 rev = node
233
233
234 if not rev:
234 if not rev:
235 raise util.Abort(_("please specify a revision to backout"))
235 raise util.Abort(_("please specify a revision to backout"))
236
236
237 date = opts.get('date')
237 date = opts.get('date')
238 if date:
238 if date:
239 opts['date'] = util.parsedate(date)
239 opts['date'] = util.parsedate(date)
240
240
241 cmdutil.bail_if_changed(repo)
241 cmdutil.bail_if_changed(repo)
242 node = cmdutil.revsingle(repo, rev).node()
242 node = cmdutil.revsingle(repo, rev).node()
243
243
244 op1, op2 = repo.dirstate.parents()
244 op1, op2 = repo.dirstate.parents()
245 a = repo.changelog.ancestor(op1, node)
245 a = repo.changelog.ancestor(op1, node)
246 if a != node:
246 if a != node:
247 raise util.Abort(_('cannot backout change on a different branch'))
247 raise util.Abort(_('cannot backout change on a different branch'))
248
248
249 p1, p2 = repo.changelog.parents(node)
249 p1, p2 = repo.changelog.parents(node)
250 if p1 == nullid:
250 if p1 == nullid:
251 raise util.Abort(_('cannot backout a change with no parents'))
251 raise util.Abort(_('cannot backout a change with no parents'))
252 if p2 != nullid:
252 if p2 != nullid:
253 if not opts.get('parent'):
253 if not opts.get('parent'):
254 raise util.Abort(_('cannot backout a merge changeset without '
254 raise util.Abort(_('cannot backout a merge changeset without '
255 '--parent'))
255 '--parent'))
256 p = repo.lookup(opts['parent'])
256 p = repo.lookup(opts['parent'])
257 if p not in (p1, p2):
257 if p not in (p1, p2):
258 raise util.Abort(_('%s is not a parent of %s') %
258 raise util.Abort(_('%s is not a parent of %s') %
259 (short(p), short(node)))
259 (short(p), short(node)))
260 parent = p
260 parent = p
261 else:
261 else:
262 if opts.get('parent'):
262 if opts.get('parent'):
263 raise util.Abort(_('cannot use --parent on non-merge changeset'))
263 raise util.Abort(_('cannot use --parent on non-merge changeset'))
264 parent = p1
264 parent = p1
265
265
266 # the backout should appear on the same branch
266 # the backout should appear on the same branch
267 branch = repo.dirstate.branch()
267 branch = repo.dirstate.branch()
268 hg.clean(repo, node, show_stats=False)
268 hg.clean(repo, node, show_stats=False)
269 repo.dirstate.setbranch(branch)
269 repo.dirstate.setbranch(branch)
270 revert_opts = opts.copy()
270 revert_opts = opts.copy()
271 revert_opts['date'] = None
271 revert_opts['date'] = None
272 revert_opts['all'] = True
272 revert_opts['all'] = True
273 revert_opts['rev'] = hex(parent)
273 revert_opts['rev'] = hex(parent)
274 revert_opts['no_backup'] = None
274 revert_opts['no_backup'] = None
275 revert(ui, repo, **revert_opts)
275 revert(ui, repo, **revert_opts)
276 if not opts.get('merge') and op1 != node:
276 if not opts.get('merge') and op1 != node:
277 try:
277 try:
278 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
278 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
279 return hg.update(repo, op1)
279 return hg.update(repo, op1)
280 finally:
280 finally:
281 ui.setconfig('ui', 'forcemerge', '')
281 ui.setconfig('ui', 'forcemerge', '')
282
282
283 commit_opts = opts.copy()
283 commit_opts = opts.copy()
284 commit_opts['addremove'] = False
284 commit_opts['addremove'] = False
285 if not commit_opts['message'] and not commit_opts['logfile']:
285 if not commit_opts['message'] and not commit_opts['logfile']:
286 # we don't translate commit messages
286 # we don't translate commit messages
287 commit_opts['message'] = "Backed out changeset %s" % short(node)
287 commit_opts['message'] = "Backed out changeset %s" % short(node)
288 commit_opts['force_editor'] = True
288 commit_opts['force_editor'] = True
289 commit(ui, repo, **commit_opts)
289 commit(ui, repo, **commit_opts)
290 def nice(node):
290 def nice(node):
291 return '%d:%s' % (repo.changelog.rev(node), short(node))
291 return '%d:%s' % (repo.changelog.rev(node), short(node))
292 ui.status(_('changeset %s backs out changeset %s\n') %
292 ui.status(_('changeset %s backs out changeset %s\n') %
293 (nice(repo.changelog.tip()), nice(node)))
293 (nice(repo.changelog.tip()), nice(node)))
294 if opts.get('merge') and op1 != node:
294 if opts.get('merge') and op1 != node:
295 hg.clean(repo, op1, show_stats=False)
295 hg.clean(repo, op1, show_stats=False)
296 ui.status(_('merging with changeset %s\n')
296 ui.status(_('merging with changeset %s\n')
297 % nice(repo.changelog.tip()))
297 % nice(repo.changelog.tip()))
298 try:
298 try:
299 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
299 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
300 return hg.merge(repo, hex(repo.changelog.tip()))
300 return hg.merge(repo, hex(repo.changelog.tip()))
301 finally:
301 finally:
302 ui.setconfig('ui', 'forcemerge', '')
302 ui.setconfig('ui', 'forcemerge', '')
303 return 0
303 return 0
304
304
305 def bisect(ui, repo, rev=None, extra=None, command=None,
305 def bisect(ui, repo, rev=None, extra=None, command=None,
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
307 """subdivision search of changesets
307 """subdivision search of changesets
308
308
309 This command helps to find changesets which introduce problems. To
309 This command helps to find changesets which introduce problems. To
310 use, mark the earliest changeset you know exhibits the problem as
310 use, mark the earliest changeset you know exhibits the problem as
311 bad, then mark the latest changeset which is free from the problem
311 bad, then mark the latest changeset which is free from the problem
312 as good. Bisect will update your working directory to a revision
312 as good. Bisect will update your working directory to a revision
313 for testing (unless the -U/--noupdate option is specified). Once
313 for testing (unless the -U/--noupdate option is specified). Once
314 you have performed tests, mark the working directory as good or
314 you have performed tests, mark the working directory as good or
315 bad, and bisect will either update to another candidate changeset
315 bad, and bisect will either update to another candidate changeset
316 or announce that it has found the bad revision.
316 or announce that it has found the bad revision.
317
317
318 As a shortcut, you can also use the revision argument to mark a
318 As a shortcut, you can also use the revision argument to mark a
319 revision as good or bad without checking it out first.
319 revision as good or bad without checking it out first.
320
320
321 If you supply a command, it will be used for automatic bisection.
321 If you supply a command, it will be used for automatic bisection.
322 Its exit status will be used to mark revisions as good or bad:
322 Its exit status will be used to mark revisions as good or bad:
323 status 0 means good, 125 means to skip the revision, 127
323 status 0 means good, 125 means to skip the revision, 127
324 (command not found) will abort the bisection, and any other
324 (command not found) will abort the bisection, and any other
325 non-zero exit status means the revision is bad.
325 non-zero exit status means the revision is bad.
326
326
327 Returns 0 on success.
327 Returns 0 on success.
328 """
328 """
329 def print_result(nodes, good):
329 def print_result(nodes, good):
330 displayer = cmdutil.show_changeset(ui, repo, {})
330 displayer = cmdutil.show_changeset(ui, repo, {})
331 if len(nodes) == 1:
331 if len(nodes) == 1:
332 # narrowed it down to a single revision
332 # narrowed it down to a single revision
333 if good:
333 if good:
334 ui.write(_("The first good revision is:\n"))
334 ui.write(_("The first good revision is:\n"))
335 else:
335 else:
336 ui.write(_("The first bad revision is:\n"))
336 ui.write(_("The first bad revision is:\n"))
337 displayer.show(repo[nodes[0]])
337 displayer.show(repo[nodes[0]])
338 parents = repo[nodes[0]].parents()
338 parents = repo[nodes[0]].parents()
339 if len(parents) > 1:
339 if len(parents) > 1:
340 side = good and state['bad'] or state['good']
340 side = good and state['bad'] or state['good']
341 num = len(set(i.node() for i in parents) & set(side))
341 num = len(set(i.node() for i in parents) & set(side))
342 if num == 1:
342 if num == 1:
343 common = parents[0].ancestor(parents[1])
343 common = parents[0].ancestor(parents[1])
344 ui.write(_('Not all ancestors of this changeset have been'
344 ui.write(_('Not all ancestors of this changeset have been'
345 ' checked.\nTo check the other ancestors, start'
345 ' checked.\nTo check the other ancestors, start'
346 ' from the common ancestor, %s.\n' % common))
346 ' from the common ancestor, %s.\n' % common))
347 else:
347 else:
348 # multiple possible revisions
348 # multiple possible revisions
349 if good:
349 if good:
350 ui.write(_("Due to skipped revisions, the first "
350 ui.write(_("Due to skipped revisions, the first "
351 "good revision could be any of:\n"))
351 "good revision could be any of:\n"))
352 else:
352 else:
353 ui.write(_("Due to skipped revisions, the first "
353 ui.write(_("Due to skipped revisions, the first "
354 "bad revision could be any of:\n"))
354 "bad revision could be any of:\n"))
355 for n in nodes:
355 for n in nodes:
356 displayer.show(repo[n])
356 displayer.show(repo[n])
357 displayer.close()
357 displayer.close()
358
358
359 def check_state(state, interactive=True):
359 def check_state(state, interactive=True):
360 if not state['good'] or not state['bad']:
360 if not state['good'] or not state['bad']:
361 if (good or bad or skip or reset) and interactive:
361 if (good or bad or skip or reset) and interactive:
362 return
362 return
363 if not state['good']:
363 if not state['good']:
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
365 else:
365 else:
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
367 return True
367 return True
368
368
369 # backward compatibility
369 # backward compatibility
370 if rev in "good bad reset init".split():
370 if rev in "good bad reset init".split():
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
372 cmd, rev, extra = rev, extra, None
372 cmd, rev, extra = rev, extra, None
373 if cmd == "good":
373 if cmd == "good":
374 good = True
374 good = True
375 elif cmd == "bad":
375 elif cmd == "bad":
376 bad = True
376 bad = True
377 else:
377 else:
378 reset = True
378 reset = True
379 elif extra or good + bad + skip + reset + bool(command) > 1:
379 elif extra or good + bad + skip + reset + bool(command) > 1:
380 raise util.Abort(_('incompatible arguments'))
380 raise util.Abort(_('incompatible arguments'))
381
381
382 if reset:
382 if reset:
383 p = repo.join("bisect.state")
383 p = repo.join("bisect.state")
384 if os.path.exists(p):
384 if os.path.exists(p):
385 os.unlink(p)
385 os.unlink(p)
386 return
386 return
387
387
388 state = hbisect.load_state(repo)
388 state = hbisect.load_state(repo)
389
389
390 if command:
390 if command:
391 changesets = 1
391 changesets = 1
392 try:
392 try:
393 while changesets:
393 while changesets:
394 # update state
394 # update state
395 status = util.system(command)
395 status = util.system(command)
396 if status == 125:
396 if status == 125:
397 transition = "skip"
397 transition = "skip"
398 elif status == 0:
398 elif status == 0:
399 transition = "good"
399 transition = "good"
400 # status < 0 means process was killed
400 # status < 0 means process was killed
401 elif status == 127:
401 elif status == 127:
402 raise util.Abort(_("failed to execute %s") % command)
402 raise util.Abort(_("failed to execute %s") % command)
403 elif status < 0:
403 elif status < 0:
404 raise util.Abort(_("%s killed") % command)
404 raise util.Abort(_("%s killed") % command)
405 else:
405 else:
406 transition = "bad"
406 transition = "bad"
407 ctx = cmdutil.revsingle(repo, rev)
407 ctx = cmdutil.revsingle(repo, rev)
408 rev = None # clear for future iterations
408 rev = None # clear for future iterations
409 state[transition].append(ctx.node())
409 state[transition].append(ctx.node())
410 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
410 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
411 check_state(state, interactive=False)
411 check_state(state, interactive=False)
412 # bisect
412 # bisect
413 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
413 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
414 # update to next check
414 # update to next check
415 cmdutil.bail_if_changed(repo)
415 cmdutil.bail_if_changed(repo)
416 hg.clean(repo, nodes[0], show_stats=False)
416 hg.clean(repo, nodes[0], show_stats=False)
417 finally:
417 finally:
418 hbisect.save_state(repo, state)
418 hbisect.save_state(repo, state)
419 print_result(nodes, good)
419 print_result(nodes, good)
420 return
420 return
421
421
422 # update state
422 # update state
423
423
424 if rev:
424 if rev:
425 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
425 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
426 else:
426 else:
427 nodes = [repo.lookup('.')]
427 nodes = [repo.lookup('.')]
428
428
429 if good or bad or skip:
429 if good or bad or skip:
430 if good:
430 if good:
431 state['good'] += nodes
431 state['good'] += nodes
432 elif bad:
432 elif bad:
433 state['bad'] += nodes
433 state['bad'] += nodes
434 elif skip:
434 elif skip:
435 state['skip'] += nodes
435 state['skip'] += nodes
436 hbisect.save_state(repo, state)
436 hbisect.save_state(repo, state)
437
437
438 if not check_state(state):
438 if not check_state(state):
439 return
439 return
440
440
441 # actually bisect
441 # actually bisect
442 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
442 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
443 if changesets == 0:
443 if changesets == 0:
444 print_result(nodes, good)
444 print_result(nodes, good)
445 else:
445 else:
446 assert len(nodes) == 1 # only a single node can be tested next
446 assert len(nodes) == 1 # only a single node can be tested next
447 node = nodes[0]
447 node = nodes[0]
448 # compute the approximate number of remaining tests
448 # compute the approximate number of remaining tests
449 tests, size = 0, 2
449 tests, size = 0, 2
450 while size <= changesets:
450 while size <= changesets:
451 tests, size = tests + 1, size * 2
451 tests, size = tests + 1, size * 2
452 rev = repo.changelog.rev(node)
452 rev = repo.changelog.rev(node)
453 ui.write(_("Testing changeset %d:%s "
453 ui.write(_("Testing changeset %d:%s "
454 "(%d changesets remaining, ~%d tests)\n")
454 "(%d changesets remaining, ~%d tests)\n")
455 % (rev, short(node), changesets, tests))
455 % (rev, short(node), changesets, tests))
456 if not noupdate:
456 if not noupdate:
457 cmdutil.bail_if_changed(repo)
457 cmdutil.bail_if_changed(repo)
458 return hg.clean(repo, node)
458 return hg.clean(repo, node)
459
459
460 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
460 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
461 '''track a line of development with movable markers
461 '''track a line of development with movable markers
462
462
463 Bookmarks are pointers to certain commits that move when
463 Bookmarks are pointers to certain commits that move when
464 committing. Bookmarks are local. They can be renamed, copied and
464 committing. Bookmarks are local. They can be renamed, copied and
465 deleted. It is possible to use bookmark names in :hg:`merge` and
465 deleted. It is possible to use bookmark names in :hg:`merge` and
466 :hg:`update` to merge and update respectively to a given bookmark.
466 :hg:`update` to merge and update respectively to a given bookmark.
467
467
468 You can use :hg:`bookmark NAME` to set a bookmark on the working
468 You can use :hg:`bookmark NAME` to set a bookmark on the working
469 directory's parent revision with the given name. If you specify
469 directory's parent revision with the given name. If you specify
470 a revision using -r REV (where REV may be an existing bookmark),
470 a revision using -r REV (where REV may be an existing bookmark),
471 the bookmark is assigned to that revision.
471 the bookmark is assigned to that revision.
472
472
473 Bookmarks can be pushed and pulled between repositories (see :hg:`help
473 Bookmarks can be pushed and pulled between repositories (see :hg:`help
474 push` and :hg:`help pull`). This requires both the local and remote
474 push` and :hg:`help pull`). This requires both the local and remote
475 repositories to support bookmarks. For versions prior to 1.8, this means
475 repositories to support bookmarks. For versions prior to 1.8, this means
476 the bookmarks extension must be enabled.
476 the bookmarks extension must be enabled.
477 '''
477 '''
478 hexfn = ui.debugflag and hex or short
478 hexfn = ui.debugflag and hex or short
479 marks = repo._bookmarks
479 marks = repo._bookmarks
480 cur = repo.changectx('.').node()
480 cur = repo.changectx('.').node()
481
481
482 if rename:
482 if rename:
483 if rename not in marks:
483 if rename not in marks:
484 raise util.Abort(_("a bookmark of this name does not exist"))
484 raise util.Abort(_("a bookmark of this name does not exist"))
485 if mark in marks and not force:
485 if mark in marks and not force:
486 raise util.Abort(_("a bookmark of the same name already exists"))
486 raise util.Abort(_("a bookmark of the same name already exists"))
487 if mark is None:
487 if mark is None:
488 raise util.Abort(_("new bookmark name required"))
488 raise util.Abort(_("new bookmark name required"))
489 marks[mark] = marks[rename]
489 marks[mark] = marks[rename]
490 del marks[rename]
490 del marks[rename]
491 if repo._bookmarkcurrent == rename:
491 if repo._bookmarkcurrent == rename:
492 bookmarks.setcurrent(repo, mark)
492 bookmarks.setcurrent(repo, mark)
493 bookmarks.write(repo)
493 bookmarks.write(repo)
494 return
494 return
495
495
496 if delete:
496 if delete:
497 if mark is None:
497 if mark is None:
498 raise util.Abort(_("bookmark name required"))
498 raise util.Abort(_("bookmark name required"))
499 if mark not in marks:
499 if mark not in marks:
500 raise util.Abort(_("a bookmark of this name does not exist"))
500 raise util.Abort(_("a bookmark of this name does not exist"))
501 if mark == repo._bookmarkcurrent:
501 if mark == repo._bookmarkcurrent:
502 bookmarks.setcurrent(repo, None)
502 bookmarks.setcurrent(repo, None)
503 del marks[mark]
503 del marks[mark]
504 bookmarks.write(repo)
504 bookmarks.write(repo)
505 return
505 return
506
506
507 if mark is not None:
507 if mark is not None:
508 if "\n" in mark:
508 if "\n" in mark:
509 raise util.Abort(_("bookmark name cannot contain newlines"))
509 raise util.Abort(_("bookmark name cannot contain newlines"))
510 mark = mark.strip()
510 mark = mark.strip()
511 if not mark:
511 if not mark:
512 raise util.Abort(_("bookmark names cannot consist entirely of "
512 raise util.Abort(_("bookmark names cannot consist entirely of "
513 "whitespace"))
513 "whitespace"))
514 if mark in marks and not force:
514 if mark in marks and not force:
515 raise util.Abort(_("a bookmark of the same name already exists"))
515 raise util.Abort(_("a bookmark of the same name already exists"))
516 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
516 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
517 and not force):
517 and not force):
518 raise util.Abort(
518 raise util.Abort(
519 _("a bookmark cannot have the name of an existing branch"))
519 _("a bookmark cannot have the name of an existing branch"))
520 if rev:
520 if rev:
521 marks[mark] = repo.lookup(rev)
521 marks[mark] = repo.lookup(rev)
522 else:
522 else:
523 marks[mark] = repo.changectx('.').node()
523 marks[mark] = repo.changectx('.').node()
524 if repo.changectx('.').node() == marks[mark]:
524 if repo.changectx('.').node() == marks[mark]:
525 bookmarks.setcurrent(repo, mark)
525 bookmarks.setcurrent(repo, mark)
526 bookmarks.write(repo)
526 bookmarks.write(repo)
527 return
527 return
528
528
529 if mark is None:
529 if mark is None:
530 if rev:
530 if rev:
531 raise util.Abort(_("bookmark name required"))
531 raise util.Abort(_("bookmark name required"))
532 if len(marks) == 0:
532 if len(marks) == 0:
533 ui.status(_("no bookmarks set\n"))
533 ui.status(_("no bookmarks set\n"))
534 else:
534 else:
535 for bmark, n in sorted(marks.iteritems()):
535 for bmark, n in sorted(marks.iteritems()):
536 current = repo._bookmarkcurrent
536 current = repo._bookmarkcurrent
537 if bmark == current and n == cur:
537 if bmark == current and n == cur:
538 prefix, label = '*', 'bookmarks.current'
538 prefix, label = '*', 'bookmarks.current'
539 else:
539 else:
540 prefix, label = ' ', ''
540 prefix, label = ' ', ''
541
541
542 if ui.quiet:
542 if ui.quiet:
543 ui.write("%s\n" % bmark, label=label)
543 ui.write("%s\n" % bmark, label=label)
544 else:
544 else:
545 ui.write(" %s %-25s %d:%s\n" % (
545 ui.write(" %s %-25s %d:%s\n" % (
546 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
546 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
547 label=label)
547 label=label)
548 return
548 return
549
549
550 def branch(ui, repo, label=None, **opts):
550 def branch(ui, repo, label=None, **opts):
551 """set or show the current branch name
551 """set or show the current branch name
552
552
553 With no argument, show the current branch name. With one argument,
553 With no argument, show the current branch name. With one argument,
554 set the working directory branch name (the branch will not exist
554 set the working directory branch name (the branch will not exist
555 in the repository until the next commit). Standard practice
555 in the repository until the next commit). Standard practice
556 recommends that primary development take place on the 'default'
556 recommends that primary development take place on the 'default'
557 branch.
557 branch.
558
558
559 Unless -f/--force is specified, branch will not let you set a
559 Unless -f/--force is specified, branch will not let you set a
560 branch name that already exists, even if it's inactive.
560 branch name that already exists, even if it's inactive.
561
561
562 Use -C/--clean to reset the working directory branch to that of
562 Use -C/--clean to reset the working directory branch to that of
563 the parent of the working directory, negating a previous branch
563 the parent of the working directory, negating a previous branch
564 change.
564 change.
565
565
566 Use the command :hg:`update` to switch to an existing branch. Use
566 Use the command :hg:`update` to switch to an existing branch. Use
567 :hg:`commit --close-branch` to mark this branch as closed.
567 :hg:`commit --close-branch` to mark this branch as closed.
568
568
569 Returns 0 on success.
569 Returns 0 on success.
570 """
570 """
571
571
572 if opts.get('clean'):
572 if opts.get('clean'):
573 label = repo[None].parents()[0].branch()
573 label = repo[None].parents()[0].branch()
574 repo.dirstate.setbranch(label)
574 repo.dirstate.setbranch(label)
575 ui.status(_('reset working directory to branch %s\n') % label)
575 ui.status(_('reset working directory to branch %s\n') % label)
576 elif label:
576 elif label:
577 if not opts.get('force') and label in repo.branchtags():
577 if not opts.get('force') and label in repo.branchtags():
578 if label not in [p.branch() for p in repo.parents()]:
578 if label not in [p.branch() for p in repo.parents()]:
579 raise util.Abort(_('a branch of the same name already exists'
579 raise util.Abort(_('a branch of the same name already exists'
580 " (use 'hg update' to switch to it)"))
580 " (use 'hg update' to switch to it)"))
581 repo.dirstate.setbranch(label)
581 repo.dirstate.setbranch(label)
582 ui.status(_('marked working directory as branch %s\n') % label)
582 ui.status(_('marked working directory as branch %s\n') % label)
583 else:
583 else:
584 ui.write("%s\n" % repo.dirstate.branch())
584 ui.write("%s\n" % repo.dirstate.branch())
585
585
586 def branches(ui, repo, active=False, closed=False):
586 def branches(ui, repo, active=False, closed=False):
587 """list repository named branches
587 """list repository named branches
588
588
589 List the repository's named branches, indicating which ones are
589 List the repository's named branches, indicating which ones are
590 inactive. If -c/--closed is specified, also list branches which have
590 inactive. If -c/--closed is specified, also list branches which have
591 been marked closed (see :hg:`commit --close-branch`).
591 been marked closed (see :hg:`commit --close-branch`).
592
592
593 If -a/--active is specified, only show active branches. A branch
593 If -a/--active is specified, only show active branches. A branch
594 is considered active if it contains repository heads.
594 is considered active if it contains repository heads.
595
595
596 Use the command :hg:`update` to switch to an existing branch.
596 Use the command :hg:`update` to switch to an existing branch.
597
597
598 Returns 0.
598 Returns 0.
599 """
599 """
600
600
601 hexfunc = ui.debugflag and hex or short
601 hexfunc = ui.debugflag and hex or short
602 activebranches = [repo[n].branch() for n in repo.heads()]
602 activebranches = [repo[n].branch() for n in repo.heads()]
603 def testactive(tag, node):
603 def testactive(tag, node):
604 realhead = tag in activebranches
604 realhead = tag in activebranches
605 open = node in repo.branchheads(tag, closed=False)
605 open = node in repo.branchheads(tag, closed=False)
606 return realhead and open
606 return realhead and open
607 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
607 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
608 for tag, node in repo.branchtags().items()],
608 for tag, node in repo.branchtags().items()],
609 reverse=True)
609 reverse=True)
610
610
611 for isactive, node, tag in branches:
611 for isactive, node, tag in branches:
612 if (not active) or isactive:
612 if (not active) or isactive:
613 if ui.quiet:
613 if ui.quiet:
614 ui.write("%s\n" % tag)
614 ui.write("%s\n" % tag)
615 else:
615 else:
616 hn = repo.lookup(node)
616 hn = repo.lookup(node)
617 if isactive:
617 if isactive:
618 label = 'branches.active'
618 label = 'branches.active'
619 notice = ''
619 notice = ''
620 elif hn not in repo.branchheads(tag, closed=False):
620 elif hn not in repo.branchheads(tag, closed=False):
621 if not closed:
621 if not closed:
622 continue
622 continue
623 label = 'branches.closed'
623 label = 'branches.closed'
624 notice = _(' (closed)')
624 notice = _(' (closed)')
625 else:
625 else:
626 label = 'branches.inactive'
626 label = 'branches.inactive'
627 notice = _(' (inactive)')
627 notice = _(' (inactive)')
628 if tag == repo.dirstate.branch():
628 if tag == repo.dirstate.branch():
629 label = 'branches.current'
629 label = 'branches.current'
630 rev = str(node).rjust(31 - encoding.colwidth(tag))
630 rev = str(node).rjust(31 - encoding.colwidth(tag))
631 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
631 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
632 tag = ui.label(tag, label)
632 tag = ui.label(tag, label)
633 ui.write("%s %s%s\n" % (tag, rev, notice))
633 ui.write("%s %s%s\n" % (tag, rev, notice))
634
634
635 def bundle(ui, repo, fname, dest=None, **opts):
635 def bundle(ui, repo, fname, dest=None, **opts):
636 """create a changegroup file
636 """create a changegroup file
637
637
638 Generate a compressed changegroup file collecting changesets not
638 Generate a compressed changegroup file collecting changesets not
639 known to be in another repository.
639 known to be in another repository.
640
640
641 If you omit the destination repository, then hg assumes the
641 If you omit the destination repository, then hg assumes the
642 destination will have all the nodes you specify with --base
642 destination will have all the nodes you specify with --base
643 parameters. To create a bundle containing all changesets, use
643 parameters. To create a bundle containing all changesets, use
644 -a/--all (or --base null).
644 -a/--all (or --base null).
645
645
646 You can change compression method with the -t/--type option.
646 You can change compression method with the -t/--type option.
647 The available compression methods are: none, bzip2, and
647 The available compression methods are: none, bzip2, and
648 gzip (by default, bundles are compressed using bzip2).
648 gzip (by default, bundles are compressed using bzip2).
649
649
650 The bundle file can then be transferred using conventional means
650 The bundle file can then be transferred using conventional means
651 and applied to another repository with the unbundle or pull
651 and applied to another repository with the unbundle or pull
652 command. This is useful when direct push and pull are not
652 command. This is useful when direct push and pull are not
653 available or when exporting an entire repository is undesirable.
653 available or when exporting an entire repository is undesirable.
654
654
655 Applying bundles preserves all changeset contents including
655 Applying bundles preserves all changeset contents including
656 permissions, copy/rename information, and revision history.
656 permissions, copy/rename information, and revision history.
657
657
658 Returns 0 on success, 1 if no changes found.
658 Returns 0 on success, 1 if no changes found.
659 """
659 """
660 revs = None
660 revs = None
661 if 'rev' in opts:
661 if 'rev' in opts:
662 revs = cmdutil.revrange(repo, opts['rev'])
662 revs = cmdutil.revrange(repo, opts['rev'])
663
663
664 if opts.get('all'):
664 if opts.get('all'):
665 base = ['null']
665 base = ['null']
666 else:
666 else:
667 base = cmdutil.revrange(repo, opts.get('base'))
667 base = cmdutil.revrange(repo, opts.get('base'))
668 if base:
668 if base:
669 if dest:
669 if dest:
670 raise util.Abort(_("--base is incompatible with specifying "
670 raise util.Abort(_("--base is incompatible with specifying "
671 "a destination"))
671 "a destination"))
672 base = [repo.lookup(rev) for rev in base]
672 base = [repo.lookup(rev) for rev in base]
673 # create the right base
673 # create the right base
674 # XXX: nodesbetween / changegroup* should be "fixed" instead
674 # XXX: nodesbetween / changegroup* should be "fixed" instead
675 o = []
675 o = []
676 has = set((nullid,))
676 has = set((nullid,))
677 for n in base:
677 for n in base:
678 has.update(repo.changelog.reachable(n))
678 has.update(repo.changelog.reachable(n))
679 if revs:
679 if revs:
680 revs = [repo.lookup(rev) for rev in revs]
680 revs = [repo.lookup(rev) for rev in revs]
681 visit = revs[:]
681 visit = revs[:]
682 has.difference_update(visit)
682 has.difference_update(visit)
683 else:
683 else:
684 visit = repo.changelog.heads()
684 visit = repo.changelog.heads()
685 seen = {}
685 seen = {}
686 while visit:
686 while visit:
687 n = visit.pop(0)
687 n = visit.pop(0)
688 parents = [p for p in repo.changelog.parents(n) if p not in has]
688 parents = [p for p in repo.changelog.parents(n) if p not in has]
689 if len(parents) == 0:
689 if len(parents) == 0:
690 if n not in has:
690 if n not in has:
691 o.append(n)
691 o.append(n)
692 else:
692 else:
693 for p in parents:
693 for p in parents:
694 if p not in seen:
694 if p not in seen:
695 seen[p] = 1
695 seen[p] = 1
696 visit.append(p)
696 visit.append(p)
697 else:
697 else:
698 dest = ui.expandpath(dest or 'default-push', dest or 'default')
698 dest = ui.expandpath(dest or 'default-push', dest or 'default')
699 dest, branches = hg.parseurl(dest, opts.get('branch'))
699 dest, branches = hg.parseurl(dest, opts.get('branch'))
700 other = hg.repository(hg.remoteui(repo, opts), dest)
700 other = hg.repository(hg.remoteui(repo, opts), dest)
701 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
701 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
702 if revs:
702 if revs:
703 revs = [repo.lookup(rev) for rev in revs]
703 revs = [repo.lookup(rev) for rev in revs]
704 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
704 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
705
705
706 if not o:
706 if not o:
707 ui.status(_("no changes found\n"))
707 ui.status(_("no changes found\n"))
708 return 1
708 return 1
709
709
710 if revs:
710 if revs:
711 cg = repo.changegroupsubset(o, revs, 'bundle')
711 cg = repo.changegroupsubset(o, revs, 'bundle')
712 else:
712 else:
713 cg = repo.changegroup(o, 'bundle')
713 cg = repo.changegroup(o, 'bundle')
714
714
715 bundletype = opts.get('type', 'bzip2').lower()
715 bundletype = opts.get('type', 'bzip2').lower()
716 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
716 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
717 bundletype = btypes.get(bundletype)
717 bundletype = btypes.get(bundletype)
718 if bundletype not in changegroup.bundletypes:
718 if bundletype not in changegroup.bundletypes:
719 raise util.Abort(_('unknown bundle type specified with --type'))
719 raise util.Abort(_('unknown bundle type specified with --type'))
720
720
721 changegroup.writebundle(cg, fname, bundletype)
721 changegroup.writebundle(cg, fname, bundletype)
722
722
723 def cat(ui, repo, file1, *pats, **opts):
723 def cat(ui, repo, file1, *pats, **opts):
724 """output the current or given revision of files
724 """output the current or given revision of files
725
725
726 Print the specified files as they were at the given revision. If
726 Print the specified files as they were at the given revision. If
727 no revision is given, the parent of the working directory is used,
727 no revision is given, the parent of the working directory is used,
728 or tip if no revision is checked out.
728 or tip if no revision is checked out.
729
729
730 Output may be to a file, in which case the name of the file is
730 Output may be to a file, in which case the name of the file is
731 given using a format string. The formatting rules are the same as
731 given using a format string. The formatting rules are the same as
732 for the export command, with the following additions:
732 for the export command, with the following additions:
733
733
734 :``%s``: basename of file being printed
734 :``%s``: basename of file being printed
735 :``%d``: dirname of file being printed, or '.' if in repository root
735 :``%d``: dirname of file being printed, or '.' if in repository root
736 :``%p``: root-relative path name of file being printed
736 :``%p``: root-relative path name of file being printed
737
737
738 Returns 0 on success.
738 Returns 0 on success.
739 """
739 """
740 ctx = cmdutil.revsingle(repo, opts.get('rev'))
740 ctx = cmdutil.revsingle(repo, opts.get('rev'))
741 err = 1
741 err = 1
742 m = cmdutil.match(repo, (file1,) + pats, opts)
742 m = cmdutil.match(repo, (file1,) + pats, opts)
743 for abs in ctx.walk(m):
743 for abs in ctx.walk(m):
744 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
744 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
745 data = ctx[abs].data()
745 data = ctx[abs].data()
746 if opts.get('decode'):
746 if opts.get('decode'):
747 data = repo.wwritedata(abs, data)
747 data = repo.wwritedata(abs, data)
748 fp.write(data)
748 fp.write(data)
749 fp.close()
749 fp.close()
750 err = 0
750 err = 0
751 return err
751 return err
752
752
753 def clone(ui, source, dest=None, **opts):
753 def clone(ui, source, dest=None, **opts):
754 """make a copy of an existing repository
754 """make a copy of an existing repository
755
755
756 Create a copy of an existing repository in a new directory.
756 Create a copy of an existing repository in a new directory.
757
757
758 If no destination directory name is specified, it defaults to the
758 If no destination directory name is specified, it defaults to the
759 basename of the source.
759 basename of the source.
760
760
761 The location of the source is added to the new repository's
761 The location of the source is added to the new repository's
762 ``.hg/hgrc`` file, as the default to be used for future pulls.
762 ``.hg/hgrc`` file, as the default to be used for future pulls.
763
763
764 See :hg:`help urls` for valid source format details.
764 See :hg:`help urls` for valid source format details.
765
765
766 It is possible to specify an ``ssh://`` URL as the destination, but no
766 It is possible to specify an ``ssh://`` URL as the destination, but no
767 ``.hg/hgrc`` and working directory will be created on the remote side.
767 ``.hg/hgrc`` and working directory will be created on the remote side.
768 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
768 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
769
769
770 A set of changesets (tags, or branch names) to pull may be specified
770 A set of changesets (tags, or branch names) to pull may be specified
771 by listing each changeset (tag, or branch name) with -r/--rev.
771 by listing each changeset (tag, or branch name) with -r/--rev.
772 If -r/--rev is used, the cloned repository will contain only a subset
772 If -r/--rev is used, the cloned repository will contain only a subset
773 of the changesets of the source repository. Only the set of changesets
773 of the changesets of the source repository. Only the set of changesets
774 defined by all -r/--rev options (including all their ancestors)
774 defined by all -r/--rev options (including all their ancestors)
775 will be pulled into the destination repository.
775 will be pulled into the destination repository.
776 No subsequent changesets (including subsequent tags) will be present
776 No subsequent changesets (including subsequent tags) will be present
777 in the destination.
777 in the destination.
778
778
779 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
779 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
780 local source repositories.
780 local source repositories.
781
781
782 For efficiency, hardlinks are used for cloning whenever the source
782 For efficiency, hardlinks are used for cloning whenever the source
783 and destination are on the same filesystem (note this applies only
783 and destination are on the same filesystem (note this applies only
784 to the repository data, not to the working directory). Some
784 to the repository data, not to the working directory). Some
785 filesystems, such as AFS, implement hardlinking incorrectly, but
785 filesystems, such as AFS, implement hardlinking incorrectly, but
786 do not report errors. In these cases, use the --pull option to
786 do not report errors. In these cases, use the --pull option to
787 avoid hardlinking.
787 avoid hardlinking.
788
788
789 In some cases, you can clone repositories and the working directory
789 In some cases, you can clone repositories and the working directory
790 using full hardlinks with ::
790 using full hardlinks with ::
791
791
792 $ cp -al REPO REPOCLONE
792 $ cp -al REPO REPOCLONE
793
793
794 This is the fastest way to clone, but it is not always safe. The
794 This is the fastest way to clone, but it is not always safe. The
795 operation is not atomic (making sure REPO is not modified during
795 operation is not atomic (making sure REPO is not modified during
796 the operation is up to you) and you have to make sure your editor
796 the operation is up to you) and you have to make sure your editor
797 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
797 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
798 this is not compatible with certain extensions that place their
798 this is not compatible with certain extensions that place their
799 metadata under the .hg directory, such as mq.
799 metadata under the .hg directory, such as mq.
800
800
801 Mercurial will update the working directory to the first applicable
801 Mercurial will update the working directory to the first applicable
802 revision from this list:
802 revision from this list:
803
803
804 a) null if -U or the source repository has no changesets
804 a) null if -U or the source repository has no changesets
805 b) if -u . and the source repository is local, the first parent of
805 b) if -u . and the source repository is local, the first parent of
806 the source repository's working directory
806 the source repository's working directory
807 c) the changeset specified with -u (if a branch name, this means the
807 c) the changeset specified with -u (if a branch name, this means the
808 latest head of that branch)
808 latest head of that branch)
809 d) the changeset specified with -r
809 d) the changeset specified with -r
810 e) the tipmost head specified with -b
810 e) the tipmost head specified with -b
811 f) the tipmost head specified with the url#branch source syntax
811 f) the tipmost head specified with the url#branch source syntax
812 g) the tipmost head of the default branch
812 g) the tipmost head of the default branch
813 h) tip
813 h) tip
814
814
815 Returns 0 on success.
815 Returns 0 on success.
816 """
816 """
817 if opts.get('noupdate') and opts.get('updaterev'):
817 if opts.get('noupdate') and opts.get('updaterev'):
818 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
818 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
819
819
820 r = hg.clone(hg.remoteui(ui, opts), source, dest,
820 r = hg.clone(hg.remoteui(ui, opts), source, dest,
821 pull=opts.get('pull'),
821 pull=opts.get('pull'),
822 stream=opts.get('uncompressed'),
822 stream=opts.get('uncompressed'),
823 rev=opts.get('rev'),
823 rev=opts.get('rev'),
824 update=opts.get('updaterev') or not opts.get('noupdate'),
824 update=opts.get('updaterev') or not opts.get('noupdate'),
825 branch=opts.get('branch'))
825 branch=opts.get('branch'))
826
826
827 return r is None
827 return r is None
828
828
829 def commit(ui, repo, *pats, **opts):
829 def commit(ui, repo, *pats, **opts):
830 """commit the specified files or all outstanding changes
830 """commit the specified files or all outstanding changes
831
831
832 Commit changes to the given files into the repository. Unlike a
832 Commit changes to the given files into the repository. Unlike a
833 centralized SCM, this operation is a local operation. See
833 centralized SCM, this operation is a local operation. See
834 :hg:`push` for a way to actively distribute your changes.
834 :hg:`push` for a way to actively distribute your changes.
835
835
836 If a list of files is omitted, all changes reported by :hg:`status`
836 If a list of files is omitted, all changes reported by :hg:`status`
837 will be committed.
837 will be committed.
838
838
839 If you are committing the result of a merge, do not provide any
839 If you are committing the result of a merge, do not provide any
840 filenames or -I/-X filters.
840 filenames or -I/-X filters.
841
841
842 If no commit message is specified, Mercurial starts your
842 If no commit message is specified, Mercurial starts your
843 configured editor where you can enter a message. In case your
843 configured editor where you can enter a message. In case your
844 commit fails, you will find a backup of your message in
844 commit fails, you will find a backup of your message in
845 ``.hg/last-message.txt``.
845 ``.hg/last-message.txt``.
846
846
847 See :hg:`help dates` for a list of formats valid for -d/--date.
847 See :hg:`help dates` for a list of formats valid for -d/--date.
848
848
849 Returns 0 on success, 1 if nothing changed.
849 Returns 0 on success, 1 if nothing changed.
850 """
850 """
851 extra = {}
851 extra = {}
852 if opts.get('close_branch'):
852 if opts.get('close_branch'):
853 if repo['.'].node() not in repo.branchheads():
853 if repo['.'].node() not in repo.branchheads():
854 # The topo heads set is included in the branch heads set of the
854 # The topo heads set is included in the branch heads set of the
855 # current branch, so it's sufficient to test branchheads
855 # current branch, so it's sufficient to test branchheads
856 raise util.Abort(_('can only close branch heads'))
856 raise util.Abort(_('can only close branch heads'))
857 extra['close'] = 1
857 extra['close'] = 1
858 e = cmdutil.commiteditor
858 e = cmdutil.commiteditor
859 if opts.get('force_editor'):
859 if opts.get('force_editor'):
860 e = cmdutil.commitforceeditor
860 e = cmdutil.commitforceeditor
861
861
862 def commitfunc(ui, repo, message, match, opts):
862 def commitfunc(ui, repo, message, match, opts):
863 return repo.commit(message, opts.get('user'), opts.get('date'), match,
863 return repo.commit(message, opts.get('user'), opts.get('date'), match,
864 editor=e, extra=extra)
864 editor=e, extra=extra)
865
865
866 branch = repo[None].branch()
866 branch = repo[None].branch()
867 bheads = repo.branchheads(branch)
867 bheads = repo.branchheads(branch)
868
868
869 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
869 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
870 if not node:
870 if not node:
871 ui.status(_("nothing changed\n"))
871 ui.status(_("nothing changed\n"))
872 return 1
872 return 1
873
873
874 ctx = repo[node]
874 ctx = repo[node]
875 parents = ctx.parents()
875 parents = ctx.parents()
876
876
877 if bheads and not [x for x in parents
877 if bheads and not [x for x in parents
878 if x.node() in bheads and x.branch() == branch]:
878 if x.node() in bheads and x.branch() == branch]:
879 ui.status(_('created new head\n'))
879 ui.status(_('created new head\n'))
880 # The message is not printed for initial roots. For the other
880 # The message is not printed for initial roots. For the other
881 # changesets, it is printed in the following situations:
881 # changesets, it is printed in the following situations:
882 #
882 #
883 # Par column: for the 2 parents with ...
883 # Par column: for the 2 parents with ...
884 # N: null or no parent
884 # N: null or no parent
885 # B: parent is on another named branch
885 # B: parent is on another named branch
886 # C: parent is a regular non head changeset
886 # C: parent is a regular non head changeset
887 # H: parent was a branch head of the current branch
887 # H: parent was a branch head of the current branch
888 # Msg column: whether we print "created new head" message
888 # Msg column: whether we print "created new head" message
889 # In the following, it is assumed that there already exists some
889 # In the following, it is assumed that there already exists some
890 # initial branch heads of the current branch, otherwise nothing is
890 # initial branch heads of the current branch, otherwise nothing is
891 # printed anyway.
891 # printed anyway.
892 #
892 #
893 # Par Msg Comment
893 # Par Msg Comment
894 # NN y additional topo root
894 # NN y additional topo root
895 #
895 #
896 # BN y additional branch root
896 # BN y additional branch root
897 # CN y additional topo head
897 # CN y additional topo head
898 # HN n usual case
898 # HN n usual case
899 #
899 #
900 # BB y weird additional branch root
900 # BB y weird additional branch root
901 # CB y branch merge
901 # CB y branch merge
902 # HB n merge with named branch
902 # HB n merge with named branch
903 #
903 #
904 # CC y additional head from merge
904 # CC y additional head from merge
905 # CH n merge with a head
905 # CH n merge with a head
906 #
906 #
907 # HH n head merge: head count decreases
907 # HH n head merge: head count decreases
908
908
909 if not opts.get('close_branch'):
909 if not opts.get('close_branch'):
910 for r in parents:
910 for r in parents:
911 if r.extra().get('close') and r.branch() == branch:
911 if r.extra().get('close') and r.branch() == branch:
912 ui.status(_('reopening closed branch head %d\n') % r)
912 ui.status(_('reopening closed branch head %d\n') % r)
913
913
914 if ui.debugflag:
914 if ui.debugflag:
915 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
915 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
916 elif ui.verbose:
916 elif ui.verbose:
917 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
917 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
918
918
919 def copy(ui, repo, *pats, **opts):
919 def copy(ui, repo, *pats, **opts):
920 """mark files as copied for the next commit
920 """mark files as copied for the next commit
921
921
922 Mark dest as having copies of source files. If dest is a
922 Mark dest as having copies of source files. If dest is a
923 directory, copies are put in that directory. If dest is a file,
923 directory, copies are put in that directory. If dest is a file,
924 the source must be a single file.
924 the source must be a single file.
925
925
926 By default, this command copies the contents of files as they
926 By default, this command copies the contents of files as they
927 exist in the working directory. If invoked with -A/--after, the
927 exist in the working directory. If invoked with -A/--after, the
928 operation is recorded, but no copying is performed.
928 operation is recorded, but no copying is performed.
929
929
930 This command takes effect with the next commit. To undo a copy
930 This command takes effect with the next commit. To undo a copy
931 before that, see :hg:`revert`.
931 before that, see :hg:`revert`.
932
932
933 Returns 0 on success, 1 if errors are encountered.
933 Returns 0 on success, 1 if errors are encountered.
934 """
934 """
935 wlock = repo.wlock(False)
935 wlock = repo.wlock(False)
936 try:
936 try:
937 return cmdutil.copy(ui, repo, pats, opts)
937 return cmdutil.copy(ui, repo, pats, opts)
938 finally:
938 finally:
939 wlock.release()
939 wlock.release()
940
940
941 def debugancestor(ui, repo, *args):
941 def debugancestor(ui, repo, *args):
942 """find the ancestor revision of two revisions in a given index"""
942 """find the ancestor revision of two revisions in a given index"""
943 if len(args) == 3:
943 if len(args) == 3:
944 index, rev1, rev2 = args
944 index, rev1, rev2 = args
945 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
945 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
946 lookup = r.lookup
946 lookup = r.lookup
947 elif len(args) == 2:
947 elif len(args) == 2:
948 if not repo:
948 if not repo:
949 raise util.Abort(_("there is no Mercurial repository here "
949 raise util.Abort(_("there is no Mercurial repository here "
950 "(.hg not found)"))
950 "(.hg not found)"))
951 rev1, rev2 = args
951 rev1, rev2 = args
952 r = repo.changelog
952 r = repo.changelog
953 lookup = repo.lookup
953 lookup = repo.lookup
954 else:
954 else:
955 raise util.Abort(_('either two or three arguments required'))
955 raise util.Abort(_('either two or three arguments required'))
956 a = r.ancestor(lookup(rev1), lookup(rev2))
956 a = r.ancestor(lookup(rev1), lookup(rev2))
957 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
957 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
958
958
959 def debugbuilddag(ui, repo, text,
959 def debugbuilddag(ui, repo, text,
960 mergeable_file=False,
960 mergeable_file=False,
961 appended_file=False,
961 appended_file=False,
962 overwritten_file=False,
962 overwritten_file=False,
963 new_file=False):
963 new_file=False):
964 """builds a repo with a given dag from scratch in the current empty repo
964 """builds a repo with a given dag from scratch in the current empty repo
965
965
966 Elements:
966 Elements:
967
967
968 - "+n" is a linear run of n nodes based on the current default parent
968 - "+n" is a linear run of n nodes based on the current default parent
969 - "." is a single node based on the current default parent
969 - "." is a single node based on the current default parent
970 - "$" resets the default parent to null (implied at the start);
970 - "$" resets the default parent to null (implied at the start);
971 otherwise the default parent is always the last node created
971 otherwise the default parent is always the last node created
972 - "<p" sets the default parent to the backref p
972 - "<p" sets the default parent to the backref p
973 - "*p" is a fork at parent p, which is a backref
973 - "*p" is a fork at parent p, which is a backref
974 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
974 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
975 - "/p2" is a merge of the preceding node and p2
975 - "/p2" is a merge of the preceding node and p2
976 - ":tag" defines a local tag for the preceding node
976 - ":tag" defines a local tag for the preceding node
977 - "@branch" sets the named branch for subsequent nodes
977 - "@branch" sets the named branch for subsequent nodes
978 - "!command" runs the command using your shell
978 - "!command" runs the command using your shell
979 - "!!my command\\n" is like "!", but to the end of the line
979 - "!!my command\\n" is like "!", but to the end of the line
980 - "#...\\n" is a comment up to the end of the line
980 - "#...\\n" is a comment up to the end of the line
981
981
982 Whitespace between the above elements is ignored.
982 Whitespace between the above elements is ignored.
983
983
984 A backref is either
984 A backref is either
985
985
986 - a number n, which references the node curr-n, where curr is the current
986 - a number n, which references the node curr-n, where curr is the current
987 node, or
987 node, or
988 - the name of a local tag you placed earlier using ":tag", or
988 - the name of a local tag you placed earlier using ":tag", or
989 - empty to denote the default parent.
989 - empty to denote the default parent.
990
990
991 All string valued-elements are either strictly alphanumeric, or must
991 All string valued-elements are either strictly alphanumeric, or must
992 be enclosed in double quotes ("..."), with "\\" as escape character.
992 be enclosed in double quotes ("..."), with "\\" as escape character.
993
993
994 Note that the --overwritten-file and --appended-file options imply the
994 Note that the --overwritten-file and --appended-file options imply the
995 use of "HGMERGE=internal:local" during DAG buildup.
995 use of "HGMERGE=internal:local" during DAG buildup.
996 """
996 """
997
997
998 if not (mergeable_file or appended_file or overwritten_file or new_file):
998 if not (mergeable_file or appended_file or overwritten_file or new_file):
999 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
999 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
1000
1000
1001 if len(repo.changelog) > 0:
1001 if len(repo.changelog) > 0:
1002 raise util.Abort(_('repository is not empty'))
1002 raise util.Abort(_('repository is not empty'))
1003
1003
1004 if overwritten_file or appended_file:
1004 if overwritten_file or appended_file:
1005 # we don't want to fail in merges during buildup
1005 # we don't want to fail in merges during buildup
1006 os.environ['HGMERGE'] = 'internal:local'
1006 os.environ['HGMERGE'] = 'internal:local'
1007
1007
1008 def writefile(fname, text, fmode="wb"):
1008 def writefile(fname, text, fmode="wb"):
1009 f = open(fname, fmode)
1009 f = open(fname, fmode)
1010 try:
1010 try:
1011 f.write(text)
1011 f.write(text)
1012 finally:
1012 finally:
1013 f.close()
1013 f.close()
1014
1014
1015 if mergeable_file:
1015 if mergeable_file:
1016 linesperrev = 2
1016 linesperrev = 2
1017 # determine number of revs in DAG
1017 # determine number of revs in DAG
1018 n = 0
1018 n = 0
1019 for type, data in dagparser.parsedag(text):
1019 for type, data in dagparser.parsedag(text):
1020 if type == 'n':
1020 if type == 'n':
1021 n += 1
1021 n += 1
1022 # make a file with k lines per rev
1022 # make a file with k lines per rev
1023 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
1023 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
1024 + "\n")
1024 + "\n")
1025
1025
1026 at = -1
1026 at = -1
1027 atbranch = 'default'
1027 atbranch = 'default'
1028 for type, data in dagparser.parsedag(text):
1028 for type, data in dagparser.parsedag(text):
1029 if type == 'n':
1029 if type == 'n':
1030 ui.status('node %s\n' % str(data))
1030 ui.status('node %s\n' % str(data))
1031 id, ps = data
1031 id, ps = data
1032 p1 = ps[0]
1032 p1 = ps[0]
1033 if p1 != at:
1033 if p1 != at:
1034 update(ui, repo, node=str(p1), clean=True)
1034 update(ui, repo, node=str(p1), clean=True)
1035 at = p1
1035 at = p1
1036 if repo.dirstate.branch() != atbranch:
1036 if repo.dirstate.branch() != atbranch:
1037 branch(ui, repo, atbranch, force=True)
1037 branch(ui, repo, atbranch, force=True)
1038 if len(ps) > 1:
1038 if len(ps) > 1:
1039 p2 = ps[1]
1039 p2 = ps[1]
1040 merge(ui, repo, node=p2)
1040 merge(ui, repo, node=p2)
1041
1041
1042 if mergeable_file:
1042 if mergeable_file:
1043 f = open("mf", "rb+")
1043 f = open("mf", "rb+")
1044 try:
1044 try:
1045 lines = f.read().split("\n")
1045 lines = f.read().split("\n")
1046 lines[id * linesperrev] += " r%i" % id
1046 lines[id * linesperrev] += " r%i" % id
1047 f.seek(0)
1047 f.seek(0)
1048 f.write("\n".join(lines))
1048 f.write("\n".join(lines))
1049 finally:
1049 finally:
1050 f.close()
1050 f.close()
1051
1051
1052 if appended_file:
1052 if appended_file:
1053 writefile("af", "r%i\n" % id, "ab")
1053 writefile("af", "r%i\n" % id, "ab")
1054
1054
1055 if overwritten_file:
1055 if overwritten_file:
1056 writefile("of", "r%i\n" % id)
1056 writefile("of", "r%i\n" % id)
1057
1057
1058 if new_file:
1058 if new_file:
1059 writefile("nf%i" % id, "r%i\n" % id)
1059 writefile("nf%i" % id, "r%i\n" % id)
1060
1060
1061 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
1061 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
1062 at = id
1062 at = id
1063 elif type == 'l':
1063 elif type == 'l':
1064 id, name = data
1064 id, name = data
1065 ui.status('tag %s\n' % name)
1065 ui.status('tag %s\n' % name)
1066 tag(ui, repo, name, local=True)
1066 tag(ui, repo, name, local=True)
1067 elif type == 'a':
1067 elif type == 'a':
1068 ui.status('branch %s\n' % data)
1068 ui.status('branch %s\n' % data)
1069 atbranch = data
1069 atbranch = data
1070 elif type in 'cC':
1070 elif type in 'cC':
1071 r = util.system(data, cwd=repo.root)
1071 r = util.system(data, cwd=repo.root)
1072 if r:
1072 if r:
1073 desc, r = util.explain_exit(r)
1073 desc, r = util.explain_exit(r)
1074 raise util.Abort(_('%s command %s') % (data, desc))
1074 raise util.Abort(_('%s command %s') % (data, desc))
1075
1075
1076 def debugcommands(ui, cmd='', *args):
1076 def debugcommands(ui, cmd='', *args):
1077 """list all available commands and options"""
1077 """list all available commands and options"""
1078 for cmd, vals in sorted(table.iteritems()):
1078 for cmd, vals in sorted(table.iteritems()):
1079 cmd = cmd.split('|')[0].strip('^')
1079 cmd = cmd.split('|')[0].strip('^')
1080 opts = ', '.join([i[1] for i in vals[1]])
1080 opts = ', '.join([i[1] for i in vals[1]])
1081 ui.write('%s: %s\n' % (cmd, opts))
1081 ui.write('%s: %s\n' % (cmd, opts))
1082
1082
1083 def debugcomplete(ui, cmd='', **opts):
1083 def debugcomplete(ui, cmd='', **opts):
1084 """returns the completion list associated with the given command"""
1084 """returns the completion list associated with the given command"""
1085
1085
1086 if opts.get('options'):
1086 if opts.get('options'):
1087 options = []
1087 options = []
1088 otables = [globalopts]
1088 otables = [globalopts]
1089 if cmd:
1089 if cmd:
1090 aliases, entry = cmdutil.findcmd(cmd, table, False)
1090 aliases, entry = cmdutil.findcmd(cmd, table, False)
1091 otables.append(entry[1])
1091 otables.append(entry[1])
1092 for t in otables:
1092 for t in otables:
1093 for o in t:
1093 for o in t:
1094 if "(DEPRECATED)" in o[3]:
1094 if "(DEPRECATED)" in o[3]:
1095 continue
1095 continue
1096 if o[0]:
1096 if o[0]:
1097 options.append('-%s' % o[0])
1097 options.append('-%s' % o[0])
1098 options.append('--%s' % o[1])
1098 options.append('--%s' % o[1])
1099 ui.write("%s\n" % "\n".join(options))
1099 ui.write("%s\n" % "\n".join(options))
1100 return
1100 return
1101
1101
1102 cmdlist = cmdutil.findpossible(cmd, table)
1102 cmdlist = cmdutil.findpossible(cmd, table)
1103 if ui.verbose:
1103 if ui.verbose:
1104 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1104 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1105 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1105 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1106
1106
1107 def debugfsinfo(ui, path = "."):
1107 def debugfsinfo(ui, path = "."):
1108 """show information detected about current filesystem"""
1108 """show information detected about current filesystem"""
1109 open('.debugfsinfo', 'w').write('')
1109 open('.debugfsinfo', 'w').write('')
1110 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1110 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1111 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1111 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1112 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1112 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1113 and 'yes' or 'no'))
1113 and 'yes' or 'no'))
1114 os.unlink('.debugfsinfo')
1114 os.unlink('.debugfsinfo')
1115
1115
1116 def debugrebuildstate(ui, repo, rev="tip"):
1116 def debugrebuildstate(ui, repo, rev="tip"):
1117 """rebuild the dirstate as it would look like for the given revision"""
1117 """rebuild the dirstate as it would look like for the given revision"""
1118 ctx = cmdutil.revsingle(repo, rev)
1118 ctx = cmdutil.revsingle(repo, rev)
1119 wlock = repo.wlock()
1119 wlock = repo.wlock()
1120 try:
1120 try:
1121 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1121 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1122 finally:
1122 finally:
1123 wlock.release()
1123 wlock.release()
1124
1124
1125 def debugcheckstate(ui, repo):
1125 def debugcheckstate(ui, repo):
1126 """validate the correctness of the current dirstate"""
1126 """validate the correctness of the current dirstate"""
1127 parent1, parent2 = repo.dirstate.parents()
1127 parent1, parent2 = repo.dirstate.parents()
1128 m1 = repo[parent1].manifest()
1128 m1 = repo[parent1].manifest()
1129 m2 = repo[parent2].manifest()
1129 m2 = repo[parent2].manifest()
1130 errors = 0
1130 errors = 0
1131 for f in repo.dirstate:
1131 for f in repo.dirstate:
1132 state = repo.dirstate[f]
1132 state = repo.dirstate[f]
1133 if state in "nr" and f not in m1:
1133 if state in "nr" and f not in m1:
1134 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1134 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1135 errors += 1
1135 errors += 1
1136 if state in "a" and f in m1:
1136 if state in "a" and f in m1:
1137 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1137 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1138 errors += 1
1138 errors += 1
1139 if state in "m" and f not in m1 and f not in m2:
1139 if state in "m" and f not in m1 and f not in m2:
1140 ui.warn(_("%s in state %s, but not in either manifest\n") %
1140 ui.warn(_("%s in state %s, but not in either manifest\n") %
1141 (f, state))
1141 (f, state))
1142 errors += 1
1142 errors += 1
1143 for f in m1:
1143 for f in m1:
1144 state = repo.dirstate[f]
1144 state = repo.dirstate[f]
1145 if state not in "nrm":
1145 if state not in "nrm":
1146 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1146 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1147 errors += 1
1147 errors += 1
1148 if errors:
1148 if errors:
1149 error = _(".hg/dirstate inconsistent with current parent's manifest")
1149 error = _(".hg/dirstate inconsistent with current parent's manifest")
1150 raise util.Abort(error)
1150 raise util.Abort(error)
1151
1151
1152 def showconfig(ui, repo, *values, **opts):
1152 def showconfig(ui, repo, *values, **opts):
1153 """show combined config settings from all hgrc files
1153 """show combined config settings from all hgrc files
1154
1154
1155 With no arguments, print names and values of all config items.
1155 With no arguments, print names and values of all config items.
1156
1156
1157 With one argument of the form section.name, print just the value
1157 With one argument of the form section.name, print just the value
1158 of that config item.
1158 of that config item.
1159
1159
1160 With multiple arguments, print names and values of all config
1160 With multiple arguments, print names and values of all config
1161 items with matching section names.
1161 items with matching section names.
1162
1162
1163 With --debug, the source (filename and line number) is printed
1163 With --debug, the source (filename and line number) is printed
1164 for each config item.
1164 for each config item.
1165
1165
1166 Returns 0 on success.
1166 Returns 0 on success.
1167 """
1167 """
1168
1168
1169 for f in util.rcpath():
1169 for f in util.rcpath():
1170 ui.debug(_('read config from: %s\n') % f)
1170 ui.debug(_('read config from: %s\n') % f)
1171 untrusted = bool(opts.get('untrusted'))
1171 untrusted = bool(opts.get('untrusted'))
1172 if values:
1172 if values:
1173 sections = [v for v in values if '.' not in v]
1173 sections = [v for v in values if '.' not in v]
1174 items = [v for v in values if '.' in v]
1174 items = [v for v in values if '.' in v]
1175 if len(items) > 1 or items and sections:
1175 if len(items) > 1 or items and sections:
1176 raise util.Abort(_('only one config item permitted'))
1176 raise util.Abort(_('only one config item permitted'))
1177 for section, name, value in ui.walkconfig(untrusted=untrusted):
1177 for section, name, value in ui.walkconfig(untrusted=untrusted):
1178 value = str(value).replace('\n', '\\n')
1178 sectname = section + '.' + name
1179 sectname = section + '.' + name
1179 if values:
1180 if values:
1180 for v in values:
1181 for v in values:
1181 if v == section:
1182 if v == section:
1182 ui.debug('%s: ' %
1183 ui.debug('%s: ' %
1183 ui.configsource(section, name, untrusted))
1184 ui.configsource(section, name, untrusted))
1184 ui.write('%s=%s\n' % (sectname, value))
1185 ui.write('%s=%s\n' % (sectname, value))
1185 elif v == sectname:
1186 elif v == sectname:
1186 ui.debug('%s: ' %
1187 ui.debug('%s: ' %
1187 ui.configsource(section, name, untrusted))
1188 ui.configsource(section, name, untrusted))
1188 ui.write(value, '\n')
1189 ui.write(value, '\n')
1189 else:
1190 else:
1190 ui.debug('%s: ' %
1191 ui.debug('%s: ' %
1191 ui.configsource(section, name, untrusted))
1192 ui.configsource(section, name, untrusted))
1192 ui.write('%s=%s\n' % (sectname, value))
1193 ui.write('%s=%s\n' % (sectname, value))
1193
1194
1194 def debugpushkey(ui, repopath, namespace, *keyinfo):
1195 def debugpushkey(ui, repopath, namespace, *keyinfo):
1195 '''access the pushkey key/value protocol
1196 '''access the pushkey key/value protocol
1196
1197
1197 With two args, list the keys in the given namespace.
1198 With two args, list the keys in the given namespace.
1198
1199
1199 With five args, set a key to new if it currently is set to old.
1200 With five args, set a key to new if it currently is set to old.
1200 Reports success or failure.
1201 Reports success or failure.
1201 '''
1202 '''
1202
1203
1203 target = hg.repository(ui, repopath)
1204 target = hg.repository(ui, repopath)
1204 if keyinfo:
1205 if keyinfo:
1205 key, old, new = keyinfo
1206 key, old, new = keyinfo
1206 r = target.pushkey(namespace, key, old, new)
1207 r = target.pushkey(namespace, key, old, new)
1207 ui.status(str(r) + '\n')
1208 ui.status(str(r) + '\n')
1208 return not r
1209 return not r
1209 else:
1210 else:
1210 for k, v in target.listkeys(namespace).iteritems():
1211 for k, v in target.listkeys(namespace).iteritems():
1211 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1212 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1212 v.encode('string-escape')))
1213 v.encode('string-escape')))
1213
1214
1214 def debugrevspec(ui, repo, expr):
1215 def debugrevspec(ui, repo, expr):
1215 '''parse and apply a revision specification'''
1216 '''parse and apply a revision specification'''
1216 if ui.verbose:
1217 if ui.verbose:
1217 tree = revset.parse(expr)
1218 tree = revset.parse(expr)
1218 ui.note(tree, "\n")
1219 ui.note(tree, "\n")
1219 func = revset.match(expr)
1220 func = revset.match(expr)
1220 for c in func(repo, range(len(repo))):
1221 for c in func(repo, range(len(repo))):
1221 ui.write("%s\n" % c)
1222 ui.write("%s\n" % c)
1222
1223
1223 def debugsetparents(ui, repo, rev1, rev2=None):
1224 def debugsetparents(ui, repo, rev1, rev2=None):
1224 """manually set the parents of the current working directory
1225 """manually set the parents of the current working directory
1225
1226
1226 This is useful for writing repository conversion tools, but should
1227 This is useful for writing repository conversion tools, but should
1227 be used with care.
1228 be used with care.
1228
1229
1229 Returns 0 on success.
1230 Returns 0 on success.
1230 """
1231 """
1231
1232
1232 r1 = cmdutil.revsingle(repo, rev1).node()
1233 r1 = cmdutil.revsingle(repo, rev1).node()
1233 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1234 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1234
1235
1235 wlock = repo.wlock()
1236 wlock = repo.wlock()
1236 try:
1237 try:
1237 repo.dirstate.setparents(r1, r2)
1238 repo.dirstate.setparents(r1, r2)
1238 finally:
1239 finally:
1239 wlock.release()
1240 wlock.release()
1240
1241
1241 def debugstate(ui, repo, nodates=None):
1242 def debugstate(ui, repo, nodates=None):
1242 """show the contents of the current dirstate"""
1243 """show the contents of the current dirstate"""
1243 timestr = ""
1244 timestr = ""
1244 showdate = not nodates
1245 showdate = not nodates
1245 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1246 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1246 if showdate:
1247 if showdate:
1247 if ent[3] == -1:
1248 if ent[3] == -1:
1248 # Pad or slice to locale representation
1249 # Pad or slice to locale representation
1249 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1250 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1250 time.localtime(0)))
1251 time.localtime(0)))
1251 timestr = 'unset'
1252 timestr = 'unset'
1252 timestr = (timestr[:locale_len] +
1253 timestr = (timestr[:locale_len] +
1253 ' ' * (locale_len - len(timestr)))
1254 ' ' * (locale_len - len(timestr)))
1254 else:
1255 else:
1255 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1256 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1256 time.localtime(ent[3]))
1257 time.localtime(ent[3]))
1257 if ent[1] & 020000:
1258 if ent[1] & 020000:
1258 mode = 'lnk'
1259 mode = 'lnk'
1259 else:
1260 else:
1260 mode = '%3o' % (ent[1] & 0777)
1261 mode = '%3o' % (ent[1] & 0777)
1261 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1262 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1262 for f in repo.dirstate.copies():
1263 for f in repo.dirstate.copies():
1263 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1264 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1264
1265
1265 def debugsub(ui, repo, rev=None):
1266 def debugsub(ui, repo, rev=None):
1266 ctx = cmdutil.revsingle(repo, rev, None)
1267 ctx = cmdutil.revsingle(repo, rev, None)
1267 for k, v in sorted(ctx.substate.items()):
1268 for k, v in sorted(ctx.substate.items()):
1268 ui.write('path %s\n' % k)
1269 ui.write('path %s\n' % k)
1269 ui.write(' source %s\n' % v[0])
1270 ui.write(' source %s\n' % v[0])
1270 ui.write(' revision %s\n' % v[1])
1271 ui.write(' revision %s\n' % v[1])
1271
1272
1272 def debugdag(ui, repo, file_=None, *revs, **opts):
1273 def debugdag(ui, repo, file_=None, *revs, **opts):
1273 """format the changelog or an index DAG as a concise textual description
1274 """format the changelog or an index DAG as a concise textual description
1274
1275
1275 If you pass a revlog index, the revlog's DAG is emitted. If you list
1276 If you pass a revlog index, the revlog's DAG is emitted. If you list
1276 revision numbers, they get labelled in the output as rN.
1277 revision numbers, they get labelled in the output as rN.
1277
1278
1278 Otherwise, the changelog DAG of the current repo is emitted.
1279 Otherwise, the changelog DAG of the current repo is emitted.
1279 """
1280 """
1280 spaces = opts.get('spaces')
1281 spaces = opts.get('spaces')
1281 dots = opts.get('dots')
1282 dots = opts.get('dots')
1282 if file_:
1283 if file_:
1283 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1284 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1284 revs = set((int(r) for r in revs))
1285 revs = set((int(r) for r in revs))
1285 def events():
1286 def events():
1286 for r in rlog:
1287 for r in rlog:
1287 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1288 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1288 if r in revs:
1289 if r in revs:
1289 yield 'l', (r, "r%i" % r)
1290 yield 'l', (r, "r%i" % r)
1290 elif repo:
1291 elif repo:
1291 cl = repo.changelog
1292 cl = repo.changelog
1292 tags = opts.get('tags')
1293 tags = opts.get('tags')
1293 branches = opts.get('branches')
1294 branches = opts.get('branches')
1294 if tags:
1295 if tags:
1295 labels = {}
1296 labels = {}
1296 for l, n in repo.tags().items():
1297 for l, n in repo.tags().items():
1297 labels.setdefault(cl.rev(n), []).append(l)
1298 labels.setdefault(cl.rev(n), []).append(l)
1298 def events():
1299 def events():
1299 b = "default"
1300 b = "default"
1300 for r in cl:
1301 for r in cl:
1301 if branches:
1302 if branches:
1302 newb = cl.read(cl.node(r))[5]['branch']
1303 newb = cl.read(cl.node(r))[5]['branch']
1303 if newb != b:
1304 if newb != b:
1304 yield 'a', newb
1305 yield 'a', newb
1305 b = newb
1306 b = newb
1306 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1307 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1307 if tags:
1308 if tags:
1308 ls = labels.get(r)
1309 ls = labels.get(r)
1309 if ls:
1310 if ls:
1310 for l in ls:
1311 for l in ls:
1311 yield 'l', (r, l)
1312 yield 'l', (r, l)
1312 else:
1313 else:
1313 raise util.Abort(_('need repo for changelog dag'))
1314 raise util.Abort(_('need repo for changelog dag'))
1314
1315
1315 for line in dagparser.dagtextlines(events(),
1316 for line in dagparser.dagtextlines(events(),
1316 addspaces=spaces,
1317 addspaces=spaces,
1317 wraplabels=True,
1318 wraplabels=True,
1318 wrapannotations=True,
1319 wrapannotations=True,
1319 wrapnonlinear=dots,
1320 wrapnonlinear=dots,
1320 usedots=dots,
1321 usedots=dots,
1321 maxlinewidth=70):
1322 maxlinewidth=70):
1322 ui.write(line)
1323 ui.write(line)
1323 ui.write("\n")
1324 ui.write("\n")
1324
1325
1325 def debugdata(ui, repo, file_, rev):
1326 def debugdata(ui, repo, file_, rev):
1326 """dump the contents of a data file revision"""
1327 """dump the contents of a data file revision"""
1327 r = None
1328 r = None
1328 if repo:
1329 if repo:
1329 filelog = repo.file(file_)
1330 filelog = repo.file(file_)
1330 if len(filelog):
1331 if len(filelog):
1331 r = filelog
1332 r = filelog
1332 if not r:
1333 if not r:
1333 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1334 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1334 try:
1335 try:
1335 ui.write(r.revision(r.lookup(rev)))
1336 ui.write(r.revision(r.lookup(rev)))
1336 except KeyError:
1337 except KeyError:
1337 raise util.Abort(_('invalid revision identifier %s') % rev)
1338 raise util.Abort(_('invalid revision identifier %s') % rev)
1338
1339
1339 def debugdate(ui, date, range=None, **opts):
1340 def debugdate(ui, date, range=None, **opts):
1340 """parse and display a date"""
1341 """parse and display a date"""
1341 if opts["extended"]:
1342 if opts["extended"]:
1342 d = util.parsedate(date, util.extendeddateformats)
1343 d = util.parsedate(date, util.extendeddateformats)
1343 else:
1344 else:
1344 d = util.parsedate(date)
1345 d = util.parsedate(date)
1345 ui.write("internal: %s %s\n" % d)
1346 ui.write("internal: %s %s\n" % d)
1346 ui.write("standard: %s\n" % util.datestr(d))
1347 ui.write("standard: %s\n" % util.datestr(d))
1347 if range:
1348 if range:
1348 m = util.matchdate(range)
1349 m = util.matchdate(range)
1349 ui.write("match: %s\n" % m(d[0]))
1350 ui.write("match: %s\n" % m(d[0]))
1350
1351
1351 def debugignore(ui, repo, *values, **opts):
1352 def debugignore(ui, repo, *values, **opts):
1352 """display the combined ignore pattern"""
1353 """display the combined ignore pattern"""
1353 ignore = repo.dirstate._ignore
1354 ignore = repo.dirstate._ignore
1354 if hasattr(ignore, 'includepat'):
1355 if hasattr(ignore, 'includepat'):
1355 ui.write("%s\n" % ignore.includepat)
1356 ui.write("%s\n" % ignore.includepat)
1356 else:
1357 else:
1357 raise util.Abort(_("no ignore patterns found"))
1358 raise util.Abort(_("no ignore patterns found"))
1358
1359
1359 def debugindex(ui, repo, file_, **opts):
1360 def debugindex(ui, repo, file_, **opts):
1360 """dump the contents of an index file"""
1361 """dump the contents of an index file"""
1361 r = None
1362 r = None
1362 if repo:
1363 if repo:
1363 filelog = repo.file(file_)
1364 filelog = repo.file(file_)
1364 if len(filelog):
1365 if len(filelog):
1365 r = filelog
1366 r = filelog
1366
1367
1367 format = opts.get('format', 0)
1368 format = opts.get('format', 0)
1368 if format not in (0, 1):
1369 if format not in (0, 1):
1369 raise util.Abort(_("unknown format %d") % format)
1370 raise util.Abort(_("unknown format %d") % format)
1370
1371
1371 if not r:
1372 if not r:
1372 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1373 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1373
1374
1374 if format == 0:
1375 if format == 0:
1375 ui.write(" rev offset length base linkrev"
1376 ui.write(" rev offset length base linkrev"
1376 " nodeid p1 p2\n")
1377 " nodeid p1 p2\n")
1377 elif format == 1:
1378 elif format == 1:
1378 ui.write(" rev flag offset length"
1379 ui.write(" rev flag offset length"
1379 " size base link p1 p2 nodeid\n")
1380 " size base link p1 p2 nodeid\n")
1380
1381
1381 for i in r:
1382 for i in r:
1382 node = r.node(i)
1383 node = r.node(i)
1383 if format == 0:
1384 if format == 0:
1384 try:
1385 try:
1385 pp = r.parents(node)
1386 pp = r.parents(node)
1386 except:
1387 except:
1387 pp = [nullid, nullid]
1388 pp = [nullid, nullid]
1388 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1389 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1389 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1390 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1390 short(node), short(pp[0]), short(pp[1])))
1391 short(node), short(pp[0]), short(pp[1])))
1391 elif format == 1:
1392 elif format == 1:
1392 pr = r.parentrevs(i)
1393 pr = r.parentrevs(i)
1393 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1394 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1394 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1395 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1395 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1396 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1396
1397
1397 def debugindexdot(ui, repo, file_):
1398 def debugindexdot(ui, repo, file_):
1398 """dump an index DAG as a graphviz dot file"""
1399 """dump an index DAG as a graphviz dot file"""
1399 r = None
1400 r = None
1400 if repo:
1401 if repo:
1401 filelog = repo.file(file_)
1402 filelog = repo.file(file_)
1402 if len(filelog):
1403 if len(filelog):
1403 r = filelog
1404 r = filelog
1404 if not r:
1405 if not r:
1405 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1406 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1406 ui.write("digraph G {\n")
1407 ui.write("digraph G {\n")
1407 for i in r:
1408 for i in r:
1408 node = r.node(i)
1409 node = r.node(i)
1409 pp = r.parents(node)
1410 pp = r.parents(node)
1410 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1411 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1411 if pp[1] != nullid:
1412 if pp[1] != nullid:
1412 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1413 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1413 ui.write("}\n")
1414 ui.write("}\n")
1414
1415
1415 def debuginstall(ui):
1416 def debuginstall(ui):
1416 '''test Mercurial installation
1417 '''test Mercurial installation
1417
1418
1418 Returns 0 on success.
1419 Returns 0 on success.
1419 '''
1420 '''
1420
1421
1421 def writetemp(contents):
1422 def writetemp(contents):
1422 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1423 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1423 f = os.fdopen(fd, "wb")
1424 f = os.fdopen(fd, "wb")
1424 f.write(contents)
1425 f.write(contents)
1425 f.close()
1426 f.close()
1426 return name
1427 return name
1427
1428
1428 problems = 0
1429 problems = 0
1429
1430
1430 # encoding
1431 # encoding
1431 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1432 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1432 try:
1433 try:
1433 encoding.fromlocal("test")
1434 encoding.fromlocal("test")
1434 except util.Abort, inst:
1435 except util.Abort, inst:
1435 ui.write(" %s\n" % inst)
1436 ui.write(" %s\n" % inst)
1436 ui.write(_(" (check that your locale is properly set)\n"))
1437 ui.write(_(" (check that your locale is properly set)\n"))
1437 problems += 1
1438 problems += 1
1438
1439
1439 # compiled modules
1440 # compiled modules
1440 ui.status(_("Checking installed modules (%s)...\n")
1441 ui.status(_("Checking installed modules (%s)...\n")
1441 % os.path.dirname(__file__))
1442 % os.path.dirname(__file__))
1442 try:
1443 try:
1443 import bdiff, mpatch, base85, osutil
1444 import bdiff, mpatch, base85, osutil
1444 except Exception, inst:
1445 except Exception, inst:
1445 ui.write(" %s\n" % inst)
1446 ui.write(" %s\n" % inst)
1446 ui.write(_(" One or more extensions could not be found"))
1447 ui.write(_(" One or more extensions could not be found"))
1447 ui.write(_(" (check that you compiled the extensions)\n"))
1448 ui.write(_(" (check that you compiled the extensions)\n"))
1448 problems += 1
1449 problems += 1
1449
1450
1450 # templates
1451 # templates
1451 ui.status(_("Checking templates...\n"))
1452 ui.status(_("Checking templates...\n"))
1452 try:
1453 try:
1453 import templater
1454 import templater
1454 templater.templater(templater.templatepath("map-cmdline.default"))
1455 templater.templater(templater.templatepath("map-cmdline.default"))
1455 except Exception, inst:
1456 except Exception, inst:
1456 ui.write(" %s\n" % inst)
1457 ui.write(" %s\n" % inst)
1457 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1458 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1458 problems += 1
1459 problems += 1
1459
1460
1460 # patch
1461 # patch
1461 ui.status(_("Checking patch...\n"))
1462 ui.status(_("Checking patch...\n"))
1462 patchproblems = 0
1463 patchproblems = 0
1463 a = "1\n2\n3\n4\n"
1464 a = "1\n2\n3\n4\n"
1464 b = "1\n2\n3\ninsert\n4\n"
1465 b = "1\n2\n3\ninsert\n4\n"
1465 fa = writetemp(a)
1466 fa = writetemp(a)
1466 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1467 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1467 os.path.basename(fa))
1468 os.path.basename(fa))
1468 fd = writetemp(d)
1469 fd = writetemp(d)
1469
1470
1470 files = {}
1471 files = {}
1471 try:
1472 try:
1472 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1473 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1473 except util.Abort, e:
1474 except util.Abort, e:
1474 ui.write(_(" patch call failed:\n"))
1475 ui.write(_(" patch call failed:\n"))
1475 ui.write(" " + str(e) + "\n")
1476 ui.write(" " + str(e) + "\n")
1476 patchproblems += 1
1477 patchproblems += 1
1477 else:
1478 else:
1478 if list(files) != [os.path.basename(fa)]:
1479 if list(files) != [os.path.basename(fa)]:
1479 ui.write(_(" unexpected patch output!\n"))
1480 ui.write(_(" unexpected patch output!\n"))
1480 patchproblems += 1
1481 patchproblems += 1
1481 a = open(fa).read()
1482 a = open(fa).read()
1482 if a != b:
1483 if a != b:
1483 ui.write(_(" patch test failed!\n"))
1484 ui.write(_(" patch test failed!\n"))
1484 patchproblems += 1
1485 patchproblems += 1
1485
1486
1486 if patchproblems:
1487 if patchproblems:
1487 if ui.config('ui', 'patch'):
1488 if ui.config('ui', 'patch'):
1488 ui.write(_(" (Current patch tool may be incompatible with patch,"
1489 ui.write(_(" (Current patch tool may be incompatible with patch,"
1489 " or misconfigured. Please check your configuration"
1490 " or misconfigured. Please check your configuration"
1490 " file)\n"))
1491 " file)\n"))
1491 else:
1492 else:
1492 ui.write(_(" Internal patcher failure, please report this error"
1493 ui.write(_(" Internal patcher failure, please report this error"
1493 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1494 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1494 problems += patchproblems
1495 problems += patchproblems
1495
1496
1496 os.unlink(fa)
1497 os.unlink(fa)
1497 os.unlink(fd)
1498 os.unlink(fd)
1498
1499
1499 # editor
1500 # editor
1500 ui.status(_("Checking commit editor...\n"))
1501 ui.status(_("Checking commit editor...\n"))
1501 editor = ui.geteditor()
1502 editor = ui.geteditor()
1502 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1503 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1503 if not cmdpath:
1504 if not cmdpath:
1504 if editor == 'vi':
1505 if editor == 'vi':
1505 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1506 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1506 ui.write(_(" (specify a commit editor in your configuration"
1507 ui.write(_(" (specify a commit editor in your configuration"
1507 " file)\n"))
1508 " file)\n"))
1508 else:
1509 else:
1509 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1510 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1510 ui.write(_(" (specify a commit editor in your configuration"
1511 ui.write(_(" (specify a commit editor in your configuration"
1511 " file)\n"))
1512 " file)\n"))
1512 problems += 1
1513 problems += 1
1513
1514
1514 # check username
1515 # check username
1515 ui.status(_("Checking username...\n"))
1516 ui.status(_("Checking username...\n"))
1516 try:
1517 try:
1517 ui.username()
1518 ui.username()
1518 except util.Abort, e:
1519 except util.Abort, e:
1519 ui.write(" %s\n" % e)
1520 ui.write(" %s\n" % e)
1520 ui.write(_(" (specify a username in your configuration file)\n"))
1521 ui.write(_(" (specify a username in your configuration file)\n"))
1521 problems += 1
1522 problems += 1
1522
1523
1523 if not problems:
1524 if not problems:
1524 ui.status(_("No problems detected\n"))
1525 ui.status(_("No problems detected\n"))
1525 else:
1526 else:
1526 ui.write(_("%s problems detected,"
1527 ui.write(_("%s problems detected,"
1527 " please check your install!\n") % problems)
1528 " please check your install!\n") % problems)
1528
1529
1529 return problems
1530 return problems
1530
1531
1531 def debugrename(ui, repo, file1, *pats, **opts):
1532 def debugrename(ui, repo, file1, *pats, **opts):
1532 """dump rename information"""
1533 """dump rename information"""
1533
1534
1534 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1535 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1535 m = cmdutil.match(repo, (file1,) + pats, opts)
1536 m = cmdutil.match(repo, (file1,) + pats, opts)
1536 for abs in ctx.walk(m):
1537 for abs in ctx.walk(m):
1537 fctx = ctx[abs]
1538 fctx = ctx[abs]
1538 o = fctx.filelog().renamed(fctx.filenode())
1539 o = fctx.filelog().renamed(fctx.filenode())
1539 rel = m.rel(abs)
1540 rel = m.rel(abs)
1540 if o:
1541 if o:
1541 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1542 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1542 else:
1543 else:
1543 ui.write(_("%s not renamed\n") % rel)
1544 ui.write(_("%s not renamed\n") % rel)
1544
1545
1545 def debugwalk(ui, repo, *pats, **opts):
1546 def debugwalk(ui, repo, *pats, **opts):
1546 """show how files match on given patterns"""
1547 """show how files match on given patterns"""
1547 m = cmdutil.match(repo, pats, opts)
1548 m = cmdutil.match(repo, pats, opts)
1548 items = list(repo.walk(m))
1549 items = list(repo.walk(m))
1549 if not items:
1550 if not items:
1550 return
1551 return
1551 fmt = 'f %%-%ds %%-%ds %%s' % (
1552 fmt = 'f %%-%ds %%-%ds %%s' % (
1552 max([len(abs) for abs in items]),
1553 max([len(abs) for abs in items]),
1553 max([len(m.rel(abs)) for abs in items]))
1554 max([len(m.rel(abs)) for abs in items]))
1554 for abs in items:
1555 for abs in items:
1555 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1556 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1556 ui.write("%s\n" % line.rstrip())
1557 ui.write("%s\n" % line.rstrip())
1557
1558
1558 def diff(ui, repo, *pats, **opts):
1559 def diff(ui, repo, *pats, **opts):
1559 """diff repository (or selected files)
1560 """diff repository (or selected files)
1560
1561
1561 Show differences between revisions for the specified files.
1562 Show differences between revisions for the specified files.
1562
1563
1563 Differences between files are shown using the unified diff format.
1564 Differences between files are shown using the unified diff format.
1564
1565
1565 .. note::
1566 .. note::
1566 diff may generate unexpected results for merges, as it will
1567 diff may generate unexpected results for merges, as it will
1567 default to comparing against the working directory's first
1568 default to comparing against the working directory's first
1568 parent changeset if no revisions are specified.
1569 parent changeset if no revisions are specified.
1569
1570
1570 When two revision arguments are given, then changes are shown
1571 When two revision arguments are given, then changes are shown
1571 between those revisions. If only one revision is specified then
1572 between those revisions. If only one revision is specified then
1572 that revision is compared to the working directory, and, when no
1573 that revision is compared to the working directory, and, when no
1573 revisions are specified, the working directory files are compared
1574 revisions are specified, the working directory files are compared
1574 to its parent.
1575 to its parent.
1575
1576
1576 Alternatively you can specify -c/--change with a revision to see
1577 Alternatively you can specify -c/--change with a revision to see
1577 the changes in that changeset relative to its first parent.
1578 the changes in that changeset relative to its first parent.
1578
1579
1579 Without the -a/--text option, diff will avoid generating diffs of
1580 Without the -a/--text option, diff will avoid generating diffs of
1580 files it detects as binary. With -a, diff will generate a diff
1581 files it detects as binary. With -a, diff will generate a diff
1581 anyway, probably with undesirable results.
1582 anyway, probably with undesirable results.
1582
1583
1583 Use the -g/--git option to generate diffs in the git extended diff
1584 Use the -g/--git option to generate diffs in the git extended diff
1584 format. For more information, read :hg:`help diffs`.
1585 format. For more information, read :hg:`help diffs`.
1585
1586
1586 Returns 0 on success.
1587 Returns 0 on success.
1587 """
1588 """
1588
1589
1589 revs = opts.get('rev')
1590 revs = opts.get('rev')
1590 change = opts.get('change')
1591 change = opts.get('change')
1591 stat = opts.get('stat')
1592 stat = opts.get('stat')
1592 reverse = opts.get('reverse')
1593 reverse = opts.get('reverse')
1593
1594
1594 if revs and change:
1595 if revs and change:
1595 msg = _('cannot specify --rev and --change at the same time')
1596 msg = _('cannot specify --rev and --change at the same time')
1596 raise util.Abort(msg)
1597 raise util.Abort(msg)
1597 elif change:
1598 elif change:
1598 node2 = repo.lookup(change)
1599 node2 = repo.lookup(change)
1599 node1 = repo[node2].parents()[0].node()
1600 node1 = repo[node2].parents()[0].node()
1600 else:
1601 else:
1601 node1, node2 = cmdutil.revpair(repo, revs)
1602 node1, node2 = cmdutil.revpair(repo, revs)
1602
1603
1603 if reverse:
1604 if reverse:
1604 node1, node2 = node2, node1
1605 node1, node2 = node2, node1
1605
1606
1606 diffopts = patch.diffopts(ui, opts)
1607 diffopts = patch.diffopts(ui, opts)
1607 m = cmdutil.match(repo, pats, opts)
1608 m = cmdutil.match(repo, pats, opts)
1608 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1609 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1609 listsubrepos=opts.get('subrepos'))
1610 listsubrepos=opts.get('subrepos'))
1610
1611
1611 def export(ui, repo, *changesets, **opts):
1612 def export(ui, repo, *changesets, **opts):
1612 """dump the header and diffs for one or more changesets
1613 """dump the header and diffs for one or more changesets
1613
1614
1614 Print the changeset header and diffs for one or more revisions.
1615 Print the changeset header and diffs for one or more revisions.
1615
1616
1616 The information shown in the changeset header is: author, date,
1617 The information shown in the changeset header is: author, date,
1617 branch name (if non-default), changeset hash, parent(s) and commit
1618 branch name (if non-default), changeset hash, parent(s) and commit
1618 comment.
1619 comment.
1619
1620
1620 .. note::
1621 .. note::
1621 export may generate unexpected diff output for merge
1622 export may generate unexpected diff output for merge
1622 changesets, as it will compare the merge changeset against its
1623 changesets, as it will compare the merge changeset against its
1623 first parent only.
1624 first parent only.
1624
1625
1625 Output may be to a file, in which case the name of the file is
1626 Output may be to a file, in which case the name of the file is
1626 given using a format string. The formatting rules are as follows:
1627 given using a format string. The formatting rules are as follows:
1627
1628
1628 :``%%``: literal "%" character
1629 :``%%``: literal "%" character
1629 :``%H``: changeset hash (40 hexadecimal digits)
1630 :``%H``: changeset hash (40 hexadecimal digits)
1630 :``%N``: number of patches being generated
1631 :``%N``: number of patches being generated
1631 :``%R``: changeset revision number
1632 :``%R``: changeset revision number
1632 :``%b``: basename of the exporting repository
1633 :``%b``: basename of the exporting repository
1633 :``%h``: short-form changeset hash (12 hexadecimal digits)
1634 :``%h``: short-form changeset hash (12 hexadecimal digits)
1634 :``%n``: zero-padded sequence number, starting at 1
1635 :``%n``: zero-padded sequence number, starting at 1
1635 :``%r``: zero-padded changeset revision number
1636 :``%r``: zero-padded changeset revision number
1636
1637
1637 Without the -a/--text option, export will avoid generating diffs
1638 Without the -a/--text option, export will avoid generating diffs
1638 of files it detects as binary. With -a, export will generate a
1639 of files it detects as binary. With -a, export will generate a
1639 diff anyway, probably with undesirable results.
1640 diff anyway, probably with undesirable results.
1640
1641
1641 Use the -g/--git option to generate diffs in the git extended diff
1642 Use the -g/--git option to generate diffs in the git extended diff
1642 format. See :hg:`help diffs` for more information.
1643 format. See :hg:`help diffs` for more information.
1643
1644
1644 With the --switch-parent option, the diff will be against the
1645 With the --switch-parent option, the diff will be against the
1645 second parent. It can be useful to review a merge.
1646 second parent. It can be useful to review a merge.
1646
1647
1647 Returns 0 on success.
1648 Returns 0 on success.
1648 """
1649 """
1649 changesets += tuple(opts.get('rev', []))
1650 changesets += tuple(opts.get('rev', []))
1650 if not changesets:
1651 if not changesets:
1651 raise util.Abort(_("export requires at least one changeset"))
1652 raise util.Abort(_("export requires at least one changeset"))
1652 revs = cmdutil.revrange(repo, changesets)
1653 revs = cmdutil.revrange(repo, changesets)
1653 if len(revs) > 1:
1654 if len(revs) > 1:
1654 ui.note(_('exporting patches:\n'))
1655 ui.note(_('exporting patches:\n'))
1655 else:
1656 else:
1656 ui.note(_('exporting patch:\n'))
1657 ui.note(_('exporting patch:\n'))
1657 cmdutil.export(repo, revs, template=opts.get('output'),
1658 cmdutil.export(repo, revs, template=opts.get('output'),
1658 switch_parent=opts.get('switch_parent'),
1659 switch_parent=opts.get('switch_parent'),
1659 opts=patch.diffopts(ui, opts))
1660 opts=patch.diffopts(ui, opts))
1660
1661
1661 def forget(ui, repo, *pats, **opts):
1662 def forget(ui, repo, *pats, **opts):
1662 """forget the specified files on the next commit
1663 """forget the specified files on the next commit
1663
1664
1664 Mark the specified files so they will no longer be tracked
1665 Mark the specified files so they will no longer be tracked
1665 after the next commit.
1666 after the next commit.
1666
1667
1667 This only removes files from the current branch, not from the
1668 This only removes files from the current branch, not from the
1668 entire project history, and it does not delete them from the
1669 entire project history, and it does not delete them from the
1669 working directory.
1670 working directory.
1670
1671
1671 To undo a forget before the next commit, see :hg:`add`.
1672 To undo a forget before the next commit, see :hg:`add`.
1672
1673
1673 Returns 0 on success.
1674 Returns 0 on success.
1674 """
1675 """
1675
1676
1676 if not pats:
1677 if not pats:
1677 raise util.Abort(_('no files specified'))
1678 raise util.Abort(_('no files specified'))
1678
1679
1679 m = cmdutil.match(repo, pats, opts)
1680 m = cmdutil.match(repo, pats, opts)
1680 s = repo.status(match=m, clean=True)
1681 s = repo.status(match=m, clean=True)
1681 forget = sorted(s[0] + s[1] + s[3] + s[6])
1682 forget = sorted(s[0] + s[1] + s[3] + s[6])
1682 errs = 0
1683 errs = 0
1683
1684
1684 for f in m.files():
1685 for f in m.files():
1685 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1686 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1686 ui.warn(_('not removing %s: file is already untracked\n')
1687 ui.warn(_('not removing %s: file is already untracked\n')
1687 % m.rel(f))
1688 % m.rel(f))
1688 errs = 1
1689 errs = 1
1689
1690
1690 for f in forget:
1691 for f in forget:
1691 if ui.verbose or not m.exact(f):
1692 if ui.verbose or not m.exact(f):
1692 ui.status(_('removing %s\n') % m.rel(f))
1693 ui.status(_('removing %s\n') % m.rel(f))
1693
1694
1694 repo[None].remove(forget, unlink=False)
1695 repo[None].remove(forget, unlink=False)
1695 return errs
1696 return errs
1696
1697
1697 def grep(ui, repo, pattern, *pats, **opts):
1698 def grep(ui, repo, pattern, *pats, **opts):
1698 """search for a pattern in specified files and revisions
1699 """search for a pattern in specified files and revisions
1699
1700
1700 Search revisions of files for a regular expression.
1701 Search revisions of files for a regular expression.
1701
1702
1702 This command behaves differently than Unix grep. It only accepts
1703 This command behaves differently than Unix grep. It only accepts
1703 Python/Perl regexps. It searches repository history, not the
1704 Python/Perl regexps. It searches repository history, not the
1704 working directory. It always prints the revision number in which a
1705 working directory. It always prints the revision number in which a
1705 match appears.
1706 match appears.
1706
1707
1707 By default, grep only prints output for the first revision of a
1708 By default, grep only prints output for the first revision of a
1708 file in which it finds a match. To get it to print every revision
1709 file in which it finds a match. To get it to print every revision
1709 that contains a change in match status ("-" for a match that
1710 that contains a change in match status ("-" for a match that
1710 becomes a non-match, or "+" for a non-match that becomes a match),
1711 becomes a non-match, or "+" for a non-match that becomes a match),
1711 use the --all flag.
1712 use the --all flag.
1712
1713
1713 Returns 0 if a match is found, 1 otherwise.
1714 Returns 0 if a match is found, 1 otherwise.
1714 """
1715 """
1715 reflags = 0
1716 reflags = 0
1716 if opts.get('ignore_case'):
1717 if opts.get('ignore_case'):
1717 reflags |= re.I
1718 reflags |= re.I
1718 try:
1719 try:
1719 regexp = re.compile(pattern, reflags)
1720 regexp = re.compile(pattern, reflags)
1720 except re.error, inst:
1721 except re.error, inst:
1721 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1722 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1722 return 1
1723 return 1
1723 sep, eol = ':', '\n'
1724 sep, eol = ':', '\n'
1724 if opts.get('print0'):
1725 if opts.get('print0'):
1725 sep = eol = '\0'
1726 sep = eol = '\0'
1726
1727
1727 getfile = util.lrucachefunc(repo.file)
1728 getfile = util.lrucachefunc(repo.file)
1728
1729
1729 def matchlines(body):
1730 def matchlines(body):
1730 begin = 0
1731 begin = 0
1731 linenum = 0
1732 linenum = 0
1732 while True:
1733 while True:
1733 match = regexp.search(body, begin)
1734 match = regexp.search(body, begin)
1734 if not match:
1735 if not match:
1735 break
1736 break
1736 mstart, mend = match.span()
1737 mstart, mend = match.span()
1737 linenum += body.count('\n', begin, mstart) + 1
1738 linenum += body.count('\n', begin, mstart) + 1
1738 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1739 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1739 begin = body.find('\n', mend) + 1 or len(body)
1740 begin = body.find('\n', mend) + 1 or len(body)
1740 lend = begin - 1
1741 lend = begin - 1
1741 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1742 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1742
1743
1743 class linestate(object):
1744 class linestate(object):
1744 def __init__(self, line, linenum, colstart, colend):
1745 def __init__(self, line, linenum, colstart, colend):
1745 self.line = line
1746 self.line = line
1746 self.linenum = linenum
1747 self.linenum = linenum
1747 self.colstart = colstart
1748 self.colstart = colstart
1748 self.colend = colend
1749 self.colend = colend
1749
1750
1750 def __hash__(self):
1751 def __hash__(self):
1751 return hash((self.linenum, self.line))
1752 return hash((self.linenum, self.line))
1752
1753
1753 def __eq__(self, other):
1754 def __eq__(self, other):
1754 return self.line == other.line
1755 return self.line == other.line
1755
1756
1756 matches = {}
1757 matches = {}
1757 copies = {}
1758 copies = {}
1758 def grepbody(fn, rev, body):
1759 def grepbody(fn, rev, body):
1759 matches[rev].setdefault(fn, [])
1760 matches[rev].setdefault(fn, [])
1760 m = matches[rev][fn]
1761 m = matches[rev][fn]
1761 for lnum, cstart, cend, line in matchlines(body):
1762 for lnum, cstart, cend, line in matchlines(body):
1762 s = linestate(line, lnum, cstart, cend)
1763 s = linestate(line, lnum, cstart, cend)
1763 m.append(s)
1764 m.append(s)
1764
1765
1765 def difflinestates(a, b):
1766 def difflinestates(a, b):
1766 sm = difflib.SequenceMatcher(None, a, b)
1767 sm = difflib.SequenceMatcher(None, a, b)
1767 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1768 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1768 if tag == 'insert':
1769 if tag == 'insert':
1769 for i in xrange(blo, bhi):
1770 for i in xrange(blo, bhi):
1770 yield ('+', b[i])
1771 yield ('+', b[i])
1771 elif tag == 'delete':
1772 elif tag == 'delete':
1772 for i in xrange(alo, ahi):
1773 for i in xrange(alo, ahi):
1773 yield ('-', a[i])
1774 yield ('-', a[i])
1774 elif tag == 'replace':
1775 elif tag == 'replace':
1775 for i in xrange(alo, ahi):
1776 for i in xrange(alo, ahi):
1776 yield ('-', a[i])
1777 yield ('-', a[i])
1777 for i in xrange(blo, bhi):
1778 for i in xrange(blo, bhi):
1778 yield ('+', b[i])
1779 yield ('+', b[i])
1779
1780
1780 def display(fn, ctx, pstates, states):
1781 def display(fn, ctx, pstates, states):
1781 rev = ctx.rev()
1782 rev = ctx.rev()
1782 datefunc = ui.quiet and util.shortdate or util.datestr
1783 datefunc = ui.quiet and util.shortdate or util.datestr
1783 found = False
1784 found = False
1784 filerevmatches = {}
1785 filerevmatches = {}
1785 if opts.get('all'):
1786 if opts.get('all'):
1786 iter = difflinestates(pstates, states)
1787 iter = difflinestates(pstates, states)
1787 else:
1788 else:
1788 iter = [('', l) for l in states]
1789 iter = [('', l) for l in states]
1789 for change, l in iter:
1790 for change, l in iter:
1790 cols = [fn, str(rev)]
1791 cols = [fn, str(rev)]
1791 before, match, after = None, None, None
1792 before, match, after = None, None, None
1792 if opts.get('line_number'):
1793 if opts.get('line_number'):
1793 cols.append(str(l.linenum))
1794 cols.append(str(l.linenum))
1794 if opts.get('all'):
1795 if opts.get('all'):
1795 cols.append(change)
1796 cols.append(change)
1796 if opts.get('user'):
1797 if opts.get('user'):
1797 cols.append(ui.shortuser(ctx.user()))
1798 cols.append(ui.shortuser(ctx.user()))
1798 if opts.get('date'):
1799 if opts.get('date'):
1799 cols.append(datefunc(ctx.date()))
1800 cols.append(datefunc(ctx.date()))
1800 if opts.get('files_with_matches'):
1801 if opts.get('files_with_matches'):
1801 c = (fn, rev)
1802 c = (fn, rev)
1802 if c in filerevmatches:
1803 if c in filerevmatches:
1803 continue
1804 continue
1804 filerevmatches[c] = 1
1805 filerevmatches[c] = 1
1805 else:
1806 else:
1806 before = l.line[:l.colstart]
1807 before = l.line[:l.colstart]
1807 match = l.line[l.colstart:l.colend]
1808 match = l.line[l.colstart:l.colend]
1808 after = l.line[l.colend:]
1809 after = l.line[l.colend:]
1809 ui.write(sep.join(cols))
1810 ui.write(sep.join(cols))
1810 if before is not None:
1811 if before is not None:
1811 ui.write(sep + before)
1812 ui.write(sep + before)
1812 ui.write(match, label='grep.match')
1813 ui.write(match, label='grep.match')
1813 ui.write(after)
1814 ui.write(after)
1814 ui.write(eol)
1815 ui.write(eol)
1815 found = True
1816 found = True
1816 return found
1817 return found
1817
1818
1818 skip = {}
1819 skip = {}
1819 revfiles = {}
1820 revfiles = {}
1820 matchfn = cmdutil.match(repo, pats, opts)
1821 matchfn = cmdutil.match(repo, pats, opts)
1821 found = False
1822 found = False
1822 follow = opts.get('follow')
1823 follow = opts.get('follow')
1823
1824
1824 def prep(ctx, fns):
1825 def prep(ctx, fns):
1825 rev = ctx.rev()
1826 rev = ctx.rev()
1826 pctx = ctx.parents()[0]
1827 pctx = ctx.parents()[0]
1827 parent = pctx.rev()
1828 parent = pctx.rev()
1828 matches.setdefault(rev, {})
1829 matches.setdefault(rev, {})
1829 matches.setdefault(parent, {})
1830 matches.setdefault(parent, {})
1830 files = revfiles.setdefault(rev, [])
1831 files = revfiles.setdefault(rev, [])
1831 for fn in fns:
1832 for fn in fns:
1832 flog = getfile(fn)
1833 flog = getfile(fn)
1833 try:
1834 try:
1834 fnode = ctx.filenode(fn)
1835 fnode = ctx.filenode(fn)
1835 except error.LookupError:
1836 except error.LookupError:
1836 continue
1837 continue
1837
1838
1838 copied = flog.renamed(fnode)
1839 copied = flog.renamed(fnode)
1839 copy = follow and copied and copied[0]
1840 copy = follow and copied and copied[0]
1840 if copy:
1841 if copy:
1841 copies.setdefault(rev, {})[fn] = copy
1842 copies.setdefault(rev, {})[fn] = copy
1842 if fn in skip:
1843 if fn in skip:
1843 if copy:
1844 if copy:
1844 skip[copy] = True
1845 skip[copy] = True
1845 continue
1846 continue
1846 files.append(fn)
1847 files.append(fn)
1847
1848
1848 if fn not in matches[rev]:
1849 if fn not in matches[rev]:
1849 grepbody(fn, rev, flog.read(fnode))
1850 grepbody(fn, rev, flog.read(fnode))
1850
1851
1851 pfn = copy or fn
1852 pfn = copy or fn
1852 if pfn not in matches[parent]:
1853 if pfn not in matches[parent]:
1853 try:
1854 try:
1854 fnode = pctx.filenode(pfn)
1855 fnode = pctx.filenode(pfn)
1855 grepbody(pfn, parent, flog.read(fnode))
1856 grepbody(pfn, parent, flog.read(fnode))
1856 except error.LookupError:
1857 except error.LookupError:
1857 pass
1858 pass
1858
1859
1859 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1860 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1860 rev = ctx.rev()
1861 rev = ctx.rev()
1861 parent = ctx.parents()[0].rev()
1862 parent = ctx.parents()[0].rev()
1862 for fn in sorted(revfiles.get(rev, [])):
1863 for fn in sorted(revfiles.get(rev, [])):
1863 states = matches[rev][fn]
1864 states = matches[rev][fn]
1864 copy = copies.get(rev, {}).get(fn)
1865 copy = copies.get(rev, {}).get(fn)
1865 if fn in skip:
1866 if fn in skip:
1866 if copy:
1867 if copy:
1867 skip[copy] = True
1868 skip[copy] = True
1868 continue
1869 continue
1869 pstates = matches.get(parent, {}).get(copy or fn, [])
1870 pstates = matches.get(parent, {}).get(copy or fn, [])
1870 if pstates or states:
1871 if pstates or states:
1871 r = display(fn, ctx, pstates, states)
1872 r = display(fn, ctx, pstates, states)
1872 found = found or r
1873 found = found or r
1873 if r and not opts.get('all'):
1874 if r and not opts.get('all'):
1874 skip[fn] = True
1875 skip[fn] = True
1875 if copy:
1876 if copy:
1876 skip[copy] = True
1877 skip[copy] = True
1877 del matches[rev]
1878 del matches[rev]
1878 del revfiles[rev]
1879 del revfiles[rev]
1879
1880
1880 return not found
1881 return not found
1881
1882
1882 def heads(ui, repo, *branchrevs, **opts):
1883 def heads(ui, repo, *branchrevs, **opts):
1883 """show current repository heads or show branch heads
1884 """show current repository heads or show branch heads
1884
1885
1885 With no arguments, show all repository branch heads.
1886 With no arguments, show all repository branch heads.
1886
1887
1887 Repository "heads" are changesets with no child changesets. They are
1888 Repository "heads" are changesets with no child changesets. They are
1888 where development generally takes place and are the usual targets
1889 where development generally takes place and are the usual targets
1889 for update and merge operations. Branch heads are changesets that have
1890 for update and merge operations. Branch heads are changesets that have
1890 no child changeset on the same branch.
1891 no child changeset on the same branch.
1891
1892
1892 If one or more REVs are given, only branch heads on the branches
1893 If one or more REVs are given, only branch heads on the branches
1893 associated with the specified changesets are shown.
1894 associated with the specified changesets are shown.
1894
1895
1895 If -c/--closed is specified, also show branch heads marked closed
1896 If -c/--closed is specified, also show branch heads marked closed
1896 (see :hg:`commit --close-branch`).
1897 (see :hg:`commit --close-branch`).
1897
1898
1898 If STARTREV is specified, only those heads that are descendants of
1899 If STARTREV is specified, only those heads that are descendants of
1899 STARTREV will be displayed.
1900 STARTREV will be displayed.
1900
1901
1901 If -t/--topo is specified, named branch mechanics will be ignored and only
1902 If -t/--topo is specified, named branch mechanics will be ignored and only
1902 changesets without children will be shown.
1903 changesets without children will be shown.
1903
1904
1904 Returns 0 if matching heads are found, 1 if not.
1905 Returns 0 if matching heads are found, 1 if not.
1905 """
1906 """
1906
1907
1907 start = None
1908 start = None
1908 if 'rev' in opts:
1909 if 'rev' in opts:
1909 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1910 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1910
1911
1911 if opts.get('topo'):
1912 if opts.get('topo'):
1912 heads = [repo[h] for h in repo.heads(start)]
1913 heads = [repo[h] for h in repo.heads(start)]
1913 else:
1914 else:
1914 heads = []
1915 heads = []
1915 for b, ls in repo.branchmap().iteritems():
1916 for b, ls in repo.branchmap().iteritems():
1916 if start is None:
1917 if start is None:
1917 heads += [repo[h] for h in ls]
1918 heads += [repo[h] for h in ls]
1918 continue
1919 continue
1919 startrev = repo.changelog.rev(start)
1920 startrev = repo.changelog.rev(start)
1920 descendants = set(repo.changelog.descendants(startrev))
1921 descendants = set(repo.changelog.descendants(startrev))
1921 descendants.add(startrev)
1922 descendants.add(startrev)
1922 rev = repo.changelog.rev
1923 rev = repo.changelog.rev
1923 heads += [repo[h] for h in ls if rev(h) in descendants]
1924 heads += [repo[h] for h in ls if rev(h) in descendants]
1924
1925
1925 if branchrevs:
1926 if branchrevs:
1926 branches = set(repo[br].branch() for br in branchrevs)
1927 branches = set(repo[br].branch() for br in branchrevs)
1927 heads = [h for h in heads if h.branch() in branches]
1928 heads = [h for h in heads if h.branch() in branches]
1928
1929
1929 if not opts.get('closed'):
1930 if not opts.get('closed'):
1930 heads = [h for h in heads if not h.extra().get('close')]
1931 heads = [h for h in heads if not h.extra().get('close')]
1931
1932
1932 if opts.get('active') and branchrevs:
1933 if opts.get('active') and branchrevs:
1933 dagheads = repo.heads(start)
1934 dagheads = repo.heads(start)
1934 heads = [h for h in heads if h.node() in dagheads]
1935 heads = [h for h in heads if h.node() in dagheads]
1935
1936
1936 if branchrevs:
1937 if branchrevs:
1937 haveheads = set(h.branch() for h in heads)
1938 haveheads = set(h.branch() for h in heads)
1938 if branches - haveheads:
1939 if branches - haveheads:
1939 headless = ', '.join(b for b in branches - haveheads)
1940 headless = ', '.join(b for b in branches - haveheads)
1940 msg = _('no open branch heads found on branches %s')
1941 msg = _('no open branch heads found on branches %s')
1941 if opts.get('rev'):
1942 if opts.get('rev'):
1942 msg += _(' (started at %s)' % opts['rev'])
1943 msg += _(' (started at %s)' % opts['rev'])
1943 ui.warn((msg + '\n') % headless)
1944 ui.warn((msg + '\n') % headless)
1944
1945
1945 if not heads:
1946 if not heads:
1946 return 1
1947 return 1
1947
1948
1948 heads = sorted(heads, key=lambda x: -x.rev())
1949 heads = sorted(heads, key=lambda x: -x.rev())
1949 displayer = cmdutil.show_changeset(ui, repo, opts)
1950 displayer = cmdutil.show_changeset(ui, repo, opts)
1950 for ctx in heads:
1951 for ctx in heads:
1951 displayer.show(ctx)
1952 displayer.show(ctx)
1952 displayer.close()
1953 displayer.close()
1953
1954
1954 def help_(ui, name=None, with_version=False, unknowncmd=False):
1955 def help_(ui, name=None, with_version=False, unknowncmd=False):
1955 """show help for a given topic or a help overview
1956 """show help for a given topic or a help overview
1956
1957
1957 With no arguments, print a list of commands with short help messages.
1958 With no arguments, print a list of commands with short help messages.
1958
1959
1959 Given a topic, extension, or command name, print help for that
1960 Given a topic, extension, or command name, print help for that
1960 topic.
1961 topic.
1961
1962
1962 Returns 0 if successful.
1963 Returns 0 if successful.
1963 """
1964 """
1964 option_lists = []
1965 option_lists = []
1965 textwidth = ui.termwidth() - 2
1966 textwidth = ui.termwidth() - 2
1966
1967
1967 def addglobalopts(aliases):
1968 def addglobalopts(aliases):
1968 if ui.verbose:
1969 if ui.verbose:
1969 option_lists.append((_("global options:"), globalopts))
1970 option_lists.append((_("global options:"), globalopts))
1970 if name == 'shortlist':
1971 if name == 'shortlist':
1971 option_lists.append((_('use "hg help" for the full list '
1972 option_lists.append((_('use "hg help" for the full list '
1972 'of commands'), ()))
1973 'of commands'), ()))
1973 else:
1974 else:
1974 if name == 'shortlist':
1975 if name == 'shortlist':
1975 msg = _('use "hg help" for the full list of commands '
1976 msg = _('use "hg help" for the full list of commands '
1976 'or "hg -v" for details')
1977 'or "hg -v" for details')
1977 elif aliases:
1978 elif aliases:
1978 msg = _('use "hg -v help%s" to show builtin aliases and '
1979 msg = _('use "hg -v help%s" to show builtin aliases and '
1979 'global options') % (name and " " + name or "")
1980 'global options') % (name and " " + name or "")
1980 else:
1981 else:
1981 msg = _('use "hg -v help %s" to show global options') % name
1982 msg = _('use "hg -v help %s" to show global options') % name
1982 option_lists.append((msg, ()))
1983 option_lists.append((msg, ()))
1983
1984
1984 def helpcmd(name):
1985 def helpcmd(name):
1985 if with_version:
1986 if with_version:
1986 version_(ui)
1987 version_(ui)
1987 ui.write('\n')
1988 ui.write('\n')
1988
1989
1989 try:
1990 try:
1990 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1991 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1991 except error.AmbiguousCommand, inst:
1992 except error.AmbiguousCommand, inst:
1992 # py3k fix: except vars can't be used outside the scope of the
1993 # py3k fix: except vars can't be used outside the scope of the
1993 # except block, nor can be used inside a lambda. python issue4617
1994 # except block, nor can be used inside a lambda. python issue4617
1994 prefix = inst.args[0]
1995 prefix = inst.args[0]
1995 select = lambda c: c.lstrip('^').startswith(prefix)
1996 select = lambda c: c.lstrip('^').startswith(prefix)
1996 helplist(_('list of commands:\n\n'), select)
1997 helplist(_('list of commands:\n\n'), select)
1997 return
1998 return
1998
1999
1999 # check if it's an invalid alias and display its error if it is
2000 # check if it's an invalid alias and display its error if it is
2000 if getattr(entry[0], 'badalias', False):
2001 if getattr(entry[0], 'badalias', False):
2001 if not unknowncmd:
2002 if not unknowncmd:
2002 entry[0](ui)
2003 entry[0](ui)
2003 return
2004 return
2004
2005
2005 # synopsis
2006 # synopsis
2006 if len(entry) > 2:
2007 if len(entry) > 2:
2007 if entry[2].startswith('hg'):
2008 if entry[2].startswith('hg'):
2008 ui.write("%s\n" % entry[2])
2009 ui.write("%s\n" % entry[2])
2009 else:
2010 else:
2010 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2011 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2011 else:
2012 else:
2012 ui.write('hg %s\n' % aliases[0])
2013 ui.write('hg %s\n' % aliases[0])
2013
2014
2014 # aliases
2015 # aliases
2015 if not ui.quiet and len(aliases) > 1:
2016 if not ui.quiet and len(aliases) > 1:
2016 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2017 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2017
2018
2018 # description
2019 # description
2019 doc = gettext(entry[0].__doc__)
2020 doc = gettext(entry[0].__doc__)
2020 if not doc:
2021 if not doc:
2021 doc = _("(no help text available)")
2022 doc = _("(no help text available)")
2022 if hasattr(entry[0], 'definition'): # aliased command
2023 if hasattr(entry[0], 'definition'): # aliased command
2023 if entry[0].definition.startswith('!'): # shell alias
2024 if entry[0].definition.startswith('!'): # shell alias
2024 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2025 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2025 else:
2026 else:
2026 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2027 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2027 if ui.quiet:
2028 if ui.quiet:
2028 doc = doc.splitlines()[0]
2029 doc = doc.splitlines()[0]
2029 keep = ui.verbose and ['verbose'] or []
2030 keep = ui.verbose and ['verbose'] or []
2030 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2031 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2031 ui.write("\n%s\n" % formatted)
2032 ui.write("\n%s\n" % formatted)
2032 if pruned:
2033 if pruned:
2033 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2034 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2034
2035
2035 if not ui.quiet:
2036 if not ui.quiet:
2036 # options
2037 # options
2037 if entry[1]:
2038 if entry[1]:
2038 option_lists.append((_("options:\n"), entry[1]))
2039 option_lists.append((_("options:\n"), entry[1]))
2039
2040
2040 addglobalopts(False)
2041 addglobalopts(False)
2041
2042
2042 def helplist(header, select=None):
2043 def helplist(header, select=None):
2043 h = {}
2044 h = {}
2044 cmds = {}
2045 cmds = {}
2045 for c, e in table.iteritems():
2046 for c, e in table.iteritems():
2046 f = c.split("|", 1)[0]
2047 f = c.split("|", 1)[0]
2047 if select and not select(f):
2048 if select and not select(f):
2048 continue
2049 continue
2049 if (not select and name != 'shortlist' and
2050 if (not select and name != 'shortlist' and
2050 e[0].__module__ != __name__):
2051 e[0].__module__ != __name__):
2051 continue
2052 continue
2052 if name == "shortlist" and not f.startswith("^"):
2053 if name == "shortlist" and not f.startswith("^"):
2053 continue
2054 continue
2054 f = f.lstrip("^")
2055 f = f.lstrip("^")
2055 if not ui.debugflag and f.startswith("debug"):
2056 if not ui.debugflag and f.startswith("debug"):
2056 continue
2057 continue
2057 doc = e[0].__doc__
2058 doc = e[0].__doc__
2058 if doc and 'DEPRECATED' in doc and not ui.verbose:
2059 if doc and 'DEPRECATED' in doc and not ui.verbose:
2059 continue
2060 continue
2060 doc = gettext(doc)
2061 doc = gettext(doc)
2061 if not doc:
2062 if not doc:
2062 doc = _("(no help text available)")
2063 doc = _("(no help text available)")
2063 h[f] = doc.splitlines()[0].rstrip()
2064 h[f] = doc.splitlines()[0].rstrip()
2064 cmds[f] = c.lstrip("^")
2065 cmds[f] = c.lstrip("^")
2065
2066
2066 if not h:
2067 if not h:
2067 ui.status(_('no commands defined\n'))
2068 ui.status(_('no commands defined\n'))
2068 return
2069 return
2069
2070
2070 ui.status(header)
2071 ui.status(header)
2071 fns = sorted(h)
2072 fns = sorted(h)
2072 m = max(map(len, fns))
2073 m = max(map(len, fns))
2073 for f in fns:
2074 for f in fns:
2074 if ui.verbose:
2075 if ui.verbose:
2075 commands = cmds[f].replace("|",", ")
2076 commands = cmds[f].replace("|",", ")
2076 ui.write(" %s:\n %s\n"%(commands, h[f]))
2077 ui.write(" %s:\n %s\n"%(commands, h[f]))
2077 else:
2078 else:
2078 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2079 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2079 initindent=' %-*s ' % (m, f),
2080 initindent=' %-*s ' % (m, f),
2080 hangindent=' ' * (m + 4))))
2081 hangindent=' ' * (m + 4))))
2081
2082
2082 if not ui.quiet:
2083 if not ui.quiet:
2083 addglobalopts(True)
2084 addglobalopts(True)
2084
2085
2085 def helptopic(name):
2086 def helptopic(name):
2086 for names, header, doc in help.helptable:
2087 for names, header, doc in help.helptable:
2087 if name in names:
2088 if name in names:
2088 break
2089 break
2089 else:
2090 else:
2090 raise error.UnknownCommand(name)
2091 raise error.UnknownCommand(name)
2091
2092
2092 # description
2093 # description
2093 if not doc:
2094 if not doc:
2094 doc = _("(no help text available)")
2095 doc = _("(no help text available)")
2095 if hasattr(doc, '__call__'):
2096 if hasattr(doc, '__call__'):
2096 doc = doc()
2097 doc = doc()
2097
2098
2098 ui.write("%s\n\n" % header)
2099 ui.write("%s\n\n" % header)
2099 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2100 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2100
2101
2101 def helpext(name):
2102 def helpext(name):
2102 try:
2103 try:
2103 mod = extensions.find(name)
2104 mod = extensions.find(name)
2104 doc = gettext(mod.__doc__) or _('no help text available')
2105 doc = gettext(mod.__doc__) or _('no help text available')
2105 except KeyError:
2106 except KeyError:
2106 mod = None
2107 mod = None
2107 doc = extensions.disabledext(name)
2108 doc = extensions.disabledext(name)
2108 if not doc:
2109 if not doc:
2109 raise error.UnknownCommand(name)
2110 raise error.UnknownCommand(name)
2110
2111
2111 if '\n' not in doc:
2112 if '\n' not in doc:
2112 head, tail = doc, ""
2113 head, tail = doc, ""
2113 else:
2114 else:
2114 head, tail = doc.split('\n', 1)
2115 head, tail = doc.split('\n', 1)
2115 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2116 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2116 if tail:
2117 if tail:
2117 ui.write(minirst.format(tail, textwidth))
2118 ui.write(minirst.format(tail, textwidth))
2118 ui.status('\n\n')
2119 ui.status('\n\n')
2119
2120
2120 if mod:
2121 if mod:
2121 try:
2122 try:
2122 ct = mod.cmdtable
2123 ct = mod.cmdtable
2123 except AttributeError:
2124 except AttributeError:
2124 ct = {}
2125 ct = {}
2125 modcmds = set([c.split('|', 1)[0] for c in ct])
2126 modcmds = set([c.split('|', 1)[0] for c in ct])
2126 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2127 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2127 else:
2128 else:
2128 ui.write(_('use "hg help extensions" for information on enabling '
2129 ui.write(_('use "hg help extensions" for information on enabling '
2129 'extensions\n'))
2130 'extensions\n'))
2130
2131
2131 def helpextcmd(name):
2132 def helpextcmd(name):
2132 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2133 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2133 doc = gettext(mod.__doc__).splitlines()[0]
2134 doc = gettext(mod.__doc__).splitlines()[0]
2134
2135
2135 msg = help.listexts(_("'%s' is provided by the following "
2136 msg = help.listexts(_("'%s' is provided by the following "
2136 "extension:") % cmd, {ext: doc}, len(ext),
2137 "extension:") % cmd, {ext: doc}, len(ext),
2137 indent=4)
2138 indent=4)
2138 ui.write(minirst.format(msg, textwidth))
2139 ui.write(minirst.format(msg, textwidth))
2139 ui.write('\n\n')
2140 ui.write('\n\n')
2140 ui.write(_('use "hg help extensions" for information on enabling '
2141 ui.write(_('use "hg help extensions" for information on enabling '
2141 'extensions\n'))
2142 'extensions\n'))
2142
2143
2143 help.addtopichook('revsets', revset.makedoc)
2144 help.addtopichook('revsets', revset.makedoc)
2144
2145
2145 if name and name != 'shortlist':
2146 if name and name != 'shortlist':
2146 i = None
2147 i = None
2147 if unknowncmd:
2148 if unknowncmd:
2148 queries = (helpextcmd,)
2149 queries = (helpextcmd,)
2149 else:
2150 else:
2150 queries = (helptopic, helpcmd, helpext, helpextcmd)
2151 queries = (helptopic, helpcmd, helpext, helpextcmd)
2151 for f in queries:
2152 for f in queries:
2152 try:
2153 try:
2153 f(name)
2154 f(name)
2154 i = None
2155 i = None
2155 break
2156 break
2156 except error.UnknownCommand, inst:
2157 except error.UnknownCommand, inst:
2157 i = inst
2158 i = inst
2158 if i:
2159 if i:
2159 raise i
2160 raise i
2160
2161
2161 else:
2162 else:
2162 # program name
2163 # program name
2163 if ui.verbose or with_version:
2164 if ui.verbose or with_version:
2164 version_(ui)
2165 version_(ui)
2165 else:
2166 else:
2166 ui.status(_("Mercurial Distributed SCM\n"))
2167 ui.status(_("Mercurial Distributed SCM\n"))
2167 ui.status('\n')
2168 ui.status('\n')
2168
2169
2169 # list of commands
2170 # list of commands
2170 if name == "shortlist":
2171 if name == "shortlist":
2171 header = _('basic commands:\n\n')
2172 header = _('basic commands:\n\n')
2172 else:
2173 else:
2173 header = _('list of commands:\n\n')
2174 header = _('list of commands:\n\n')
2174
2175
2175 helplist(header)
2176 helplist(header)
2176 if name != 'shortlist':
2177 if name != 'shortlist':
2177 exts, maxlength = extensions.enabled()
2178 exts, maxlength = extensions.enabled()
2178 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2179 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2179 if text:
2180 if text:
2180 ui.write("\n%s\n" % minirst.format(text, textwidth))
2181 ui.write("\n%s\n" % minirst.format(text, textwidth))
2181
2182
2182 # list all option lists
2183 # list all option lists
2183 opt_output = []
2184 opt_output = []
2184 multioccur = False
2185 multioccur = False
2185 for title, options in option_lists:
2186 for title, options in option_lists:
2186 opt_output.append(("\n%s" % title, None))
2187 opt_output.append(("\n%s" % title, None))
2187 for option in options:
2188 for option in options:
2188 if len(option) == 5:
2189 if len(option) == 5:
2189 shortopt, longopt, default, desc, optlabel = option
2190 shortopt, longopt, default, desc, optlabel = option
2190 else:
2191 else:
2191 shortopt, longopt, default, desc = option
2192 shortopt, longopt, default, desc = option
2192 optlabel = _("VALUE") # default label
2193 optlabel = _("VALUE") # default label
2193
2194
2194 if _("DEPRECATED") in desc and not ui.verbose:
2195 if _("DEPRECATED") in desc and not ui.verbose:
2195 continue
2196 continue
2196 if isinstance(default, list):
2197 if isinstance(default, list):
2197 numqualifier = " %s [+]" % optlabel
2198 numqualifier = " %s [+]" % optlabel
2198 multioccur = True
2199 multioccur = True
2199 elif (default is not None) and not isinstance(default, bool):
2200 elif (default is not None) and not isinstance(default, bool):
2200 numqualifier = " %s" % optlabel
2201 numqualifier = " %s" % optlabel
2201 else:
2202 else:
2202 numqualifier = ""
2203 numqualifier = ""
2203 opt_output.append(("%2s%s" %
2204 opt_output.append(("%2s%s" %
2204 (shortopt and "-%s" % shortopt,
2205 (shortopt and "-%s" % shortopt,
2205 longopt and " --%s%s" %
2206 longopt and " --%s%s" %
2206 (longopt, numqualifier)),
2207 (longopt, numqualifier)),
2207 "%s%s" % (desc,
2208 "%s%s" % (desc,
2208 default
2209 default
2209 and _(" (default: %s)") % default
2210 and _(" (default: %s)") % default
2210 or "")))
2211 or "")))
2211 if multioccur:
2212 if multioccur:
2212 msg = _("\n[+] marked option can be specified multiple times")
2213 msg = _("\n[+] marked option can be specified multiple times")
2213 if ui.verbose and name != 'shortlist':
2214 if ui.verbose and name != 'shortlist':
2214 opt_output.append((msg, None))
2215 opt_output.append((msg, None))
2215 else:
2216 else:
2216 opt_output.insert(-1, (msg, None))
2217 opt_output.insert(-1, (msg, None))
2217
2218
2218 if not name:
2219 if not name:
2219 ui.write(_("\nadditional help topics:\n\n"))
2220 ui.write(_("\nadditional help topics:\n\n"))
2220 topics = []
2221 topics = []
2221 for names, header, doc in help.helptable:
2222 for names, header, doc in help.helptable:
2222 topics.append((sorted(names, key=len, reverse=True)[0], header))
2223 topics.append((sorted(names, key=len, reverse=True)[0], header))
2223 topics_len = max([len(s[0]) for s in topics])
2224 topics_len = max([len(s[0]) for s in topics])
2224 for t, desc in topics:
2225 for t, desc in topics:
2225 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2226 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2226
2227
2227 if opt_output:
2228 if opt_output:
2228 colwidth = encoding.colwidth
2229 colwidth = encoding.colwidth
2229 # normalize: (opt or message, desc or None, width of opt)
2230 # normalize: (opt or message, desc or None, width of opt)
2230 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2231 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2231 for opt, desc in opt_output]
2232 for opt, desc in opt_output]
2232 hanging = max([e[2] for e in entries])
2233 hanging = max([e[2] for e in entries])
2233 for opt, desc, width in entries:
2234 for opt, desc, width in entries:
2234 if desc:
2235 if desc:
2235 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2236 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2236 hangindent = ' ' * (hanging + 3)
2237 hangindent = ' ' * (hanging + 3)
2237 ui.write('%s\n' % (util.wrap(desc, textwidth,
2238 ui.write('%s\n' % (util.wrap(desc, textwidth,
2238 initindent=initindent,
2239 initindent=initindent,
2239 hangindent=hangindent)))
2240 hangindent=hangindent)))
2240 else:
2241 else:
2241 ui.write("%s\n" % opt)
2242 ui.write("%s\n" % opt)
2242
2243
2243 def identify(ui, repo, source=None, rev=None,
2244 def identify(ui, repo, source=None, rev=None,
2244 num=None, id=None, branch=None, tags=None, bookmarks=None):
2245 num=None, id=None, branch=None, tags=None, bookmarks=None):
2245 """identify the working copy or specified revision
2246 """identify the working copy or specified revision
2246
2247
2247 With no revision, print a summary of the current state of the
2248 With no revision, print a summary of the current state of the
2248 repository.
2249 repository.
2249
2250
2250 Specifying a path to a repository root or Mercurial bundle will
2251 Specifying a path to a repository root or Mercurial bundle will
2251 cause lookup to operate on that repository/bundle.
2252 cause lookup to operate on that repository/bundle.
2252
2253
2253 This summary identifies the repository state using one or two
2254 This summary identifies the repository state using one or two
2254 parent hash identifiers, followed by a "+" if there are
2255 parent hash identifiers, followed by a "+" if there are
2255 uncommitted changes in the working directory, a list of tags for
2256 uncommitted changes in the working directory, a list of tags for
2256 this revision and a branch name for non-default branches.
2257 this revision and a branch name for non-default branches.
2257
2258
2258 Returns 0 if successful.
2259 Returns 0 if successful.
2259 """
2260 """
2260
2261
2261 if not repo and not source:
2262 if not repo and not source:
2262 raise util.Abort(_("there is no Mercurial repository here "
2263 raise util.Abort(_("there is no Mercurial repository here "
2263 "(.hg not found)"))
2264 "(.hg not found)"))
2264
2265
2265 hexfunc = ui.debugflag and hex or short
2266 hexfunc = ui.debugflag and hex or short
2266 default = not (num or id or branch or tags or bookmarks)
2267 default = not (num or id or branch or tags or bookmarks)
2267 output = []
2268 output = []
2268
2269
2269 revs = []
2270 revs = []
2270 if source:
2271 if source:
2271 source, branches = hg.parseurl(ui.expandpath(source))
2272 source, branches = hg.parseurl(ui.expandpath(source))
2272 repo = hg.repository(ui, source)
2273 repo = hg.repository(ui, source)
2273 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2274 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2274
2275
2275 if not repo.local():
2276 if not repo.local():
2276 if not rev and revs:
2277 if not rev and revs:
2277 rev = revs[0]
2278 rev = revs[0]
2278 if not rev:
2279 if not rev:
2279 rev = "tip"
2280 rev = "tip"
2280 if num or branch or tags or bookmarks:
2281 if num or branch or tags or bookmarks:
2281 raise util.Abort(_("can't query remote revision number,"
2282 raise util.Abort(_("can't query remote revision number,"
2282 " branch, tags, or bookmarks"))
2283 " branch, tags, or bookmarks"))
2283 output = [hexfunc(repo.lookup(rev))]
2284 output = [hexfunc(repo.lookup(rev))]
2284 elif not rev:
2285 elif not rev:
2285 ctx = repo[None]
2286 ctx = repo[None]
2286 parents = ctx.parents()
2287 parents = ctx.parents()
2287 changed = False
2288 changed = False
2288 if default or id or num:
2289 if default or id or num:
2289 changed = util.any(repo.status())
2290 changed = util.any(repo.status())
2290 if default or id:
2291 if default or id:
2291 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2292 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2292 (changed) and "+" or "")]
2293 (changed) and "+" or "")]
2293 if num:
2294 if num:
2294 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2295 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2295 (changed) and "+" or ""))
2296 (changed) and "+" or ""))
2296 else:
2297 else:
2297 ctx = cmdutil.revsingle(repo, rev)
2298 ctx = cmdutil.revsingle(repo, rev)
2298 if default or id:
2299 if default or id:
2299 output = [hexfunc(ctx.node())]
2300 output = [hexfunc(ctx.node())]
2300 if num:
2301 if num:
2301 output.append(str(ctx.rev()))
2302 output.append(str(ctx.rev()))
2302
2303
2303 if repo.local() and default and not ui.quiet:
2304 if repo.local() and default and not ui.quiet:
2304 b = ctx.branch()
2305 b = ctx.branch()
2305 if b != 'default':
2306 if b != 'default':
2306 output.append("(%s)" % b)
2307 output.append("(%s)" % b)
2307
2308
2308 # multiple tags for a single parent separated by '/'
2309 # multiple tags for a single parent separated by '/'
2309 t = "/".join(ctx.tags())
2310 t = "/".join(ctx.tags())
2310 if t:
2311 if t:
2311 output.append(t)
2312 output.append(t)
2312
2313
2313 # multiple bookmarks for a single parent separated by '/'
2314 # multiple bookmarks for a single parent separated by '/'
2314 bm = '/'.join(ctx.bookmarks())
2315 bm = '/'.join(ctx.bookmarks())
2315 if bm:
2316 if bm:
2316 output.append(bm)
2317 output.append(bm)
2317
2318
2318 if branch:
2319 if branch:
2319 output.append(ctx.branch())
2320 output.append(ctx.branch())
2320
2321
2321 if tags:
2322 if tags:
2322 output.extend(ctx.tags())
2323 output.extend(ctx.tags())
2323
2324
2324 if bookmarks:
2325 if bookmarks:
2325 output.extend(ctx.bookmarks())
2326 output.extend(ctx.bookmarks())
2326
2327
2327 ui.write("%s\n" % ' '.join(output))
2328 ui.write("%s\n" % ' '.join(output))
2328
2329
2329 def import_(ui, repo, patch1, *patches, **opts):
2330 def import_(ui, repo, patch1, *patches, **opts):
2330 """import an ordered set of patches
2331 """import an ordered set of patches
2331
2332
2332 Import a list of patches and commit them individually (unless
2333 Import a list of patches and commit them individually (unless
2333 --no-commit is specified).
2334 --no-commit is specified).
2334
2335
2335 If there are outstanding changes in the working directory, import
2336 If there are outstanding changes in the working directory, import
2336 will abort unless given the -f/--force flag.
2337 will abort unless given the -f/--force flag.
2337
2338
2338 You can import a patch straight from a mail message. Even patches
2339 You can import a patch straight from a mail message. Even patches
2339 as attachments work (to use the body part, it must have type
2340 as attachments work (to use the body part, it must have type
2340 text/plain or text/x-patch). From and Subject headers of email
2341 text/plain or text/x-patch). From and Subject headers of email
2341 message are used as default committer and commit message. All
2342 message are used as default committer and commit message. All
2342 text/plain body parts before first diff are added to commit
2343 text/plain body parts before first diff are added to commit
2343 message.
2344 message.
2344
2345
2345 If the imported patch was generated by :hg:`export`, user and
2346 If the imported patch was generated by :hg:`export`, user and
2346 description from patch override values from message headers and
2347 description from patch override values from message headers and
2347 body. Values given on command line with -m/--message and -u/--user
2348 body. Values given on command line with -m/--message and -u/--user
2348 override these.
2349 override these.
2349
2350
2350 If --exact is specified, import will set the working directory to
2351 If --exact is specified, import will set the working directory to
2351 the parent of each patch before applying it, and will abort if the
2352 the parent of each patch before applying it, and will abort if the
2352 resulting changeset has a different ID than the one recorded in
2353 resulting changeset has a different ID than the one recorded in
2353 the patch. This may happen due to character set problems or other
2354 the patch. This may happen due to character set problems or other
2354 deficiencies in the text patch format.
2355 deficiencies in the text patch format.
2355
2356
2356 With -s/--similarity, hg will attempt to discover renames and
2357 With -s/--similarity, hg will attempt to discover renames and
2357 copies in the patch in the same way as 'addremove'.
2358 copies in the patch in the same way as 'addremove'.
2358
2359
2359 To read a patch from standard input, use "-" as the patch name. If
2360 To read a patch from standard input, use "-" as the patch name. If
2360 a URL is specified, the patch will be downloaded from it.
2361 a URL is specified, the patch will be downloaded from it.
2361 See :hg:`help dates` for a list of formats valid for -d/--date.
2362 See :hg:`help dates` for a list of formats valid for -d/--date.
2362
2363
2363 Returns 0 on success.
2364 Returns 0 on success.
2364 """
2365 """
2365 patches = (patch1,) + patches
2366 patches = (patch1,) + patches
2366
2367
2367 date = opts.get('date')
2368 date = opts.get('date')
2368 if date:
2369 if date:
2369 opts['date'] = util.parsedate(date)
2370 opts['date'] = util.parsedate(date)
2370
2371
2371 try:
2372 try:
2372 sim = float(opts.get('similarity') or 0)
2373 sim = float(opts.get('similarity') or 0)
2373 except ValueError:
2374 except ValueError:
2374 raise util.Abort(_('similarity must be a number'))
2375 raise util.Abort(_('similarity must be a number'))
2375 if sim < 0 or sim > 100:
2376 if sim < 0 or sim > 100:
2376 raise util.Abort(_('similarity must be between 0 and 100'))
2377 raise util.Abort(_('similarity must be between 0 and 100'))
2377
2378
2378 if opts.get('exact') or not opts.get('force'):
2379 if opts.get('exact') or not opts.get('force'):
2379 cmdutil.bail_if_changed(repo)
2380 cmdutil.bail_if_changed(repo)
2380
2381
2381 d = opts["base"]
2382 d = opts["base"]
2382 strip = opts["strip"]
2383 strip = opts["strip"]
2383 wlock = lock = None
2384 wlock = lock = None
2384 msgs = []
2385 msgs = []
2385
2386
2386 def tryone(ui, hunk):
2387 def tryone(ui, hunk):
2387 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2388 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2388 patch.extract(ui, hunk)
2389 patch.extract(ui, hunk)
2389
2390
2390 if not tmpname:
2391 if not tmpname:
2391 return None
2392 return None
2392 commitid = _('to working directory')
2393 commitid = _('to working directory')
2393
2394
2394 try:
2395 try:
2395 cmdline_message = cmdutil.logmessage(opts)
2396 cmdline_message = cmdutil.logmessage(opts)
2396 if cmdline_message:
2397 if cmdline_message:
2397 # pickup the cmdline msg
2398 # pickup the cmdline msg
2398 message = cmdline_message
2399 message = cmdline_message
2399 elif message:
2400 elif message:
2400 # pickup the patch msg
2401 # pickup the patch msg
2401 message = message.strip()
2402 message = message.strip()
2402 else:
2403 else:
2403 # launch the editor
2404 # launch the editor
2404 message = None
2405 message = None
2405 ui.debug('message:\n%s\n' % message)
2406 ui.debug('message:\n%s\n' % message)
2406
2407
2407 wp = repo.parents()
2408 wp = repo.parents()
2408 if opts.get('exact'):
2409 if opts.get('exact'):
2409 if not nodeid or not p1:
2410 if not nodeid or not p1:
2410 raise util.Abort(_('not a Mercurial patch'))
2411 raise util.Abort(_('not a Mercurial patch'))
2411 p1 = repo.lookup(p1)
2412 p1 = repo.lookup(p1)
2412 p2 = repo.lookup(p2 or hex(nullid))
2413 p2 = repo.lookup(p2 or hex(nullid))
2413
2414
2414 if p1 != wp[0].node():
2415 if p1 != wp[0].node():
2415 hg.clean(repo, p1)
2416 hg.clean(repo, p1)
2416 repo.dirstate.setparents(p1, p2)
2417 repo.dirstate.setparents(p1, p2)
2417 elif p2:
2418 elif p2:
2418 try:
2419 try:
2419 p1 = repo.lookup(p1)
2420 p1 = repo.lookup(p1)
2420 p2 = repo.lookup(p2)
2421 p2 = repo.lookup(p2)
2421 if p1 == wp[0].node():
2422 if p1 == wp[0].node():
2422 repo.dirstate.setparents(p1, p2)
2423 repo.dirstate.setparents(p1, p2)
2423 except error.RepoError:
2424 except error.RepoError:
2424 pass
2425 pass
2425 if opts.get('exact') or opts.get('import_branch'):
2426 if opts.get('exact') or opts.get('import_branch'):
2426 repo.dirstate.setbranch(branch or 'default')
2427 repo.dirstate.setbranch(branch or 'default')
2427
2428
2428 files = {}
2429 files = {}
2429 try:
2430 try:
2430 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2431 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2431 files=files, eolmode=None)
2432 files=files, eolmode=None)
2432 finally:
2433 finally:
2433 files = cmdutil.updatedir(ui, repo, files,
2434 files = cmdutil.updatedir(ui, repo, files,
2434 similarity=sim / 100.0)
2435 similarity=sim / 100.0)
2435 if opts.get('no_commit'):
2436 if opts.get('no_commit'):
2436 if message:
2437 if message:
2437 msgs.append(message)
2438 msgs.append(message)
2438 else:
2439 else:
2439 if opts.get('exact'):
2440 if opts.get('exact'):
2440 m = None
2441 m = None
2441 else:
2442 else:
2442 m = cmdutil.matchfiles(repo, files or [])
2443 m = cmdutil.matchfiles(repo, files or [])
2443 n = repo.commit(message, opts.get('user') or user,
2444 n = repo.commit(message, opts.get('user') or user,
2444 opts.get('date') or date, match=m,
2445 opts.get('date') or date, match=m,
2445 editor=cmdutil.commiteditor)
2446 editor=cmdutil.commiteditor)
2446 if opts.get('exact'):
2447 if opts.get('exact'):
2447 if hex(n) != nodeid:
2448 if hex(n) != nodeid:
2448 repo.rollback()
2449 repo.rollback()
2449 raise util.Abort(_('patch is damaged'
2450 raise util.Abort(_('patch is damaged'
2450 ' or loses information'))
2451 ' or loses information'))
2451 # Force a dirstate write so that the next transaction
2452 # Force a dirstate write so that the next transaction
2452 # backups an up-do-date file.
2453 # backups an up-do-date file.
2453 repo.dirstate.write()
2454 repo.dirstate.write()
2454 if n:
2455 if n:
2455 commitid = short(n)
2456 commitid = short(n)
2456
2457
2457 return commitid
2458 return commitid
2458 finally:
2459 finally:
2459 os.unlink(tmpname)
2460 os.unlink(tmpname)
2460
2461
2461 try:
2462 try:
2462 wlock = repo.wlock()
2463 wlock = repo.wlock()
2463 lock = repo.lock()
2464 lock = repo.lock()
2464 lastcommit = None
2465 lastcommit = None
2465 for p in patches:
2466 for p in patches:
2466 pf = os.path.join(d, p)
2467 pf = os.path.join(d, p)
2467
2468
2468 if pf == '-':
2469 if pf == '-':
2469 ui.status(_("applying patch from stdin\n"))
2470 ui.status(_("applying patch from stdin\n"))
2470 pf = sys.stdin
2471 pf = sys.stdin
2471 else:
2472 else:
2472 ui.status(_("applying %s\n") % p)
2473 ui.status(_("applying %s\n") % p)
2473 pf = url.open(ui, pf)
2474 pf = url.open(ui, pf)
2474
2475
2475 haspatch = False
2476 haspatch = False
2476 for hunk in patch.split(pf):
2477 for hunk in patch.split(pf):
2477 commitid = tryone(ui, hunk)
2478 commitid = tryone(ui, hunk)
2478 if commitid:
2479 if commitid:
2479 haspatch = True
2480 haspatch = True
2480 if lastcommit:
2481 if lastcommit:
2481 ui.status(_('applied %s\n') % lastcommit)
2482 ui.status(_('applied %s\n') % lastcommit)
2482 lastcommit = commitid
2483 lastcommit = commitid
2483
2484
2484 if not haspatch:
2485 if not haspatch:
2485 raise util.Abort(_('no diffs found'))
2486 raise util.Abort(_('no diffs found'))
2486
2487
2487 if msgs:
2488 if msgs:
2488 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2489 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2489 finally:
2490 finally:
2490 release(lock, wlock)
2491 release(lock, wlock)
2491
2492
2492 def incoming(ui, repo, source="default", **opts):
2493 def incoming(ui, repo, source="default", **opts):
2493 """show new changesets found in source
2494 """show new changesets found in source
2494
2495
2495 Show new changesets found in the specified path/URL or the default
2496 Show new changesets found in the specified path/URL or the default
2496 pull location. These are the changesets that would have been pulled
2497 pull location. These are the changesets that would have been pulled
2497 if a pull at the time you issued this command.
2498 if a pull at the time you issued this command.
2498
2499
2499 For remote repository, using --bundle avoids downloading the
2500 For remote repository, using --bundle avoids downloading the
2500 changesets twice if the incoming is followed by a pull.
2501 changesets twice if the incoming is followed by a pull.
2501
2502
2502 See pull for valid source format details.
2503 See pull for valid source format details.
2503
2504
2504 Returns 0 if there are incoming changes, 1 otherwise.
2505 Returns 0 if there are incoming changes, 1 otherwise.
2505 """
2506 """
2506 if opts.get('bundle') and opts.get('subrepos'):
2507 if opts.get('bundle') and opts.get('subrepos'):
2507 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2508 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2508
2509
2509 if opts.get('bookmarks'):
2510 if opts.get('bookmarks'):
2510 source, branches = hg.parseurl(ui.expandpath(source),
2511 source, branches = hg.parseurl(ui.expandpath(source),
2511 opts.get('branch'))
2512 opts.get('branch'))
2512 other = hg.repository(hg.remoteui(repo, opts), source)
2513 other = hg.repository(hg.remoteui(repo, opts), source)
2513 if 'bookmarks' not in other.listkeys('namespaces'):
2514 if 'bookmarks' not in other.listkeys('namespaces'):
2514 ui.warn(_("remote doesn't support bookmarks\n"))
2515 ui.warn(_("remote doesn't support bookmarks\n"))
2515 return 0
2516 return 0
2516 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2517 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2517 return bookmarks.diff(ui, repo, other)
2518 return bookmarks.diff(ui, repo, other)
2518
2519
2519 ret = hg.incoming(ui, repo, source, opts)
2520 ret = hg.incoming(ui, repo, source, opts)
2520 return ret
2521 return ret
2521
2522
2522 def init(ui, dest=".", **opts):
2523 def init(ui, dest=".", **opts):
2523 """create a new repository in the given directory
2524 """create a new repository in the given directory
2524
2525
2525 Initialize a new repository in the given directory. If the given
2526 Initialize a new repository in the given directory. If the given
2526 directory does not exist, it will be created.
2527 directory does not exist, it will be created.
2527
2528
2528 If no directory is given, the current directory is used.
2529 If no directory is given, the current directory is used.
2529
2530
2530 It is possible to specify an ``ssh://`` URL as the destination.
2531 It is possible to specify an ``ssh://`` URL as the destination.
2531 See :hg:`help urls` for more information.
2532 See :hg:`help urls` for more information.
2532
2533
2533 Returns 0 on success.
2534 Returns 0 on success.
2534 """
2535 """
2535 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2536 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2536
2537
2537 def locate(ui, repo, *pats, **opts):
2538 def locate(ui, repo, *pats, **opts):
2538 """locate files matching specific patterns
2539 """locate files matching specific patterns
2539
2540
2540 Print files under Mercurial control in the working directory whose
2541 Print files under Mercurial control in the working directory whose
2541 names match the given patterns.
2542 names match the given patterns.
2542
2543
2543 By default, this command searches all directories in the working
2544 By default, this command searches all directories in the working
2544 directory. To search just the current directory and its
2545 directory. To search just the current directory and its
2545 subdirectories, use "--include .".
2546 subdirectories, use "--include .".
2546
2547
2547 If no patterns are given to match, this command prints the names
2548 If no patterns are given to match, this command prints the names
2548 of all files under Mercurial control in the working directory.
2549 of all files under Mercurial control in the working directory.
2549
2550
2550 If you want to feed the output of this command into the "xargs"
2551 If you want to feed the output of this command into the "xargs"
2551 command, use the -0 option to both this command and "xargs". This
2552 command, use the -0 option to both this command and "xargs". This
2552 will avoid the problem of "xargs" treating single filenames that
2553 will avoid the problem of "xargs" treating single filenames that
2553 contain whitespace as multiple filenames.
2554 contain whitespace as multiple filenames.
2554
2555
2555 Returns 0 if a match is found, 1 otherwise.
2556 Returns 0 if a match is found, 1 otherwise.
2556 """
2557 """
2557 end = opts.get('print0') and '\0' or '\n'
2558 end = opts.get('print0') and '\0' or '\n'
2558 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2559 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2559
2560
2560 ret = 1
2561 ret = 1
2561 m = cmdutil.match(repo, pats, opts, default='relglob')
2562 m = cmdutil.match(repo, pats, opts, default='relglob')
2562 m.bad = lambda x, y: False
2563 m.bad = lambda x, y: False
2563 for abs in repo[rev].walk(m):
2564 for abs in repo[rev].walk(m):
2564 if not rev and abs not in repo.dirstate:
2565 if not rev and abs not in repo.dirstate:
2565 continue
2566 continue
2566 if opts.get('fullpath'):
2567 if opts.get('fullpath'):
2567 ui.write(repo.wjoin(abs), end)
2568 ui.write(repo.wjoin(abs), end)
2568 else:
2569 else:
2569 ui.write(((pats and m.rel(abs)) or abs), end)
2570 ui.write(((pats and m.rel(abs)) or abs), end)
2570 ret = 0
2571 ret = 0
2571
2572
2572 return ret
2573 return ret
2573
2574
2574 def log(ui, repo, *pats, **opts):
2575 def log(ui, repo, *pats, **opts):
2575 """show revision history of entire repository or files
2576 """show revision history of entire repository or files
2576
2577
2577 Print the revision history of the specified files or the entire
2578 Print the revision history of the specified files or the entire
2578 project.
2579 project.
2579
2580
2580 File history is shown without following rename or copy history of
2581 File history is shown without following rename or copy history of
2581 files. Use -f/--follow with a filename to follow history across
2582 files. Use -f/--follow with a filename to follow history across
2582 renames and copies. --follow without a filename will only show
2583 renames and copies. --follow without a filename will only show
2583 ancestors or descendants of the starting revision. --follow-first
2584 ancestors or descendants of the starting revision. --follow-first
2584 only follows the first parent of merge revisions.
2585 only follows the first parent of merge revisions.
2585
2586
2586 If no revision range is specified, the default is ``tip:0`` unless
2587 If no revision range is specified, the default is ``tip:0`` unless
2587 --follow is set, in which case the working directory parent is
2588 --follow is set, in which case the working directory parent is
2588 used as the starting revision. You can specify a revision set for
2589 used as the starting revision. You can specify a revision set for
2589 log, see :hg:`help revsets` for more information.
2590 log, see :hg:`help revsets` for more information.
2590
2591
2591 See :hg:`help dates` for a list of formats valid for -d/--date.
2592 See :hg:`help dates` for a list of formats valid for -d/--date.
2592
2593
2593 By default this command prints revision number and changeset id,
2594 By default this command prints revision number and changeset id,
2594 tags, non-trivial parents, user, date and time, and a summary for
2595 tags, non-trivial parents, user, date and time, and a summary for
2595 each commit. When the -v/--verbose switch is used, the list of
2596 each commit. When the -v/--verbose switch is used, the list of
2596 changed files and full commit message are shown.
2597 changed files and full commit message are shown.
2597
2598
2598 .. note::
2599 .. note::
2599 log -p/--patch may generate unexpected diff output for merge
2600 log -p/--patch may generate unexpected diff output for merge
2600 changesets, as it will only compare the merge changeset against
2601 changesets, as it will only compare the merge changeset against
2601 its first parent. Also, only files different from BOTH parents
2602 its first parent. Also, only files different from BOTH parents
2602 will appear in files:.
2603 will appear in files:.
2603
2604
2604 Returns 0 on success.
2605 Returns 0 on success.
2605 """
2606 """
2606
2607
2607 matchfn = cmdutil.match(repo, pats, opts)
2608 matchfn = cmdutil.match(repo, pats, opts)
2608 limit = cmdutil.loglimit(opts)
2609 limit = cmdutil.loglimit(opts)
2609 count = 0
2610 count = 0
2610
2611
2611 endrev = None
2612 endrev = None
2612 if opts.get('copies') and opts.get('rev'):
2613 if opts.get('copies') and opts.get('rev'):
2613 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2614 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2614
2615
2615 df = False
2616 df = False
2616 if opts["date"]:
2617 if opts["date"]:
2617 df = util.matchdate(opts["date"])
2618 df = util.matchdate(opts["date"])
2618
2619
2619 branches = opts.get('branch', []) + opts.get('only_branch', [])
2620 branches = opts.get('branch', []) + opts.get('only_branch', [])
2620 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2621 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2621
2622
2622 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2623 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2623 def prep(ctx, fns):
2624 def prep(ctx, fns):
2624 rev = ctx.rev()
2625 rev = ctx.rev()
2625 parents = [p for p in repo.changelog.parentrevs(rev)
2626 parents = [p for p in repo.changelog.parentrevs(rev)
2626 if p != nullrev]
2627 if p != nullrev]
2627 if opts.get('no_merges') and len(parents) == 2:
2628 if opts.get('no_merges') and len(parents) == 2:
2628 return
2629 return
2629 if opts.get('only_merges') and len(parents) != 2:
2630 if opts.get('only_merges') and len(parents) != 2:
2630 return
2631 return
2631 if opts.get('branch') and ctx.branch() not in opts['branch']:
2632 if opts.get('branch') and ctx.branch() not in opts['branch']:
2632 return
2633 return
2633 if df and not df(ctx.date()[0]):
2634 if df and not df(ctx.date()[0]):
2634 return
2635 return
2635 if opts['user'] and not [k for k in opts['user']
2636 if opts['user'] and not [k for k in opts['user']
2636 if k.lower() in ctx.user().lower()]:
2637 if k.lower() in ctx.user().lower()]:
2637 return
2638 return
2638 if opts.get('keyword'):
2639 if opts.get('keyword'):
2639 for k in [kw.lower() for kw in opts['keyword']]:
2640 for k in [kw.lower() for kw in opts['keyword']]:
2640 if (k in ctx.user().lower() or
2641 if (k in ctx.user().lower() or
2641 k in ctx.description().lower() or
2642 k in ctx.description().lower() or
2642 k in " ".join(ctx.files()).lower()):
2643 k in " ".join(ctx.files()).lower()):
2643 break
2644 break
2644 else:
2645 else:
2645 return
2646 return
2646
2647
2647 copies = None
2648 copies = None
2648 if opts.get('copies') and rev:
2649 if opts.get('copies') and rev:
2649 copies = []
2650 copies = []
2650 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2651 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2651 for fn in ctx.files():
2652 for fn in ctx.files():
2652 rename = getrenamed(fn, rev)
2653 rename = getrenamed(fn, rev)
2653 if rename:
2654 if rename:
2654 copies.append((fn, rename[0]))
2655 copies.append((fn, rename[0]))
2655
2656
2656 revmatchfn = None
2657 revmatchfn = None
2657 if opts.get('patch') or opts.get('stat'):
2658 if opts.get('patch') or opts.get('stat'):
2658 if opts.get('follow') or opts.get('follow_first'):
2659 if opts.get('follow') or opts.get('follow_first'):
2659 # note: this might be wrong when following through merges
2660 # note: this might be wrong when following through merges
2660 revmatchfn = cmdutil.match(repo, fns, default='path')
2661 revmatchfn = cmdutil.match(repo, fns, default='path')
2661 else:
2662 else:
2662 revmatchfn = matchfn
2663 revmatchfn = matchfn
2663
2664
2664 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2665 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2665
2666
2666 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2667 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2667 if count == limit:
2668 if count == limit:
2668 break
2669 break
2669 if displayer.flush(ctx.rev()):
2670 if displayer.flush(ctx.rev()):
2670 count += 1
2671 count += 1
2671 displayer.close()
2672 displayer.close()
2672
2673
2673 def manifest(ui, repo, node=None, rev=None):
2674 def manifest(ui, repo, node=None, rev=None):
2674 """output the current or given revision of the project manifest
2675 """output the current or given revision of the project manifest
2675
2676
2676 Print a list of version controlled files for the given revision.
2677 Print a list of version controlled files for the given revision.
2677 If no revision is given, the first parent of the working directory
2678 If no revision is given, the first parent of the working directory
2678 is used, or the null revision if no revision is checked out.
2679 is used, or the null revision if no revision is checked out.
2679
2680
2680 With -v, print file permissions, symlink and executable bits.
2681 With -v, print file permissions, symlink and executable bits.
2681 With --debug, print file revision hashes.
2682 With --debug, print file revision hashes.
2682
2683
2683 Returns 0 on success.
2684 Returns 0 on success.
2684 """
2685 """
2685
2686
2686 if rev and node:
2687 if rev and node:
2687 raise util.Abort(_("please specify just one revision"))
2688 raise util.Abort(_("please specify just one revision"))
2688
2689
2689 if not node:
2690 if not node:
2690 node = rev
2691 node = rev
2691
2692
2692 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2693 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2693 ctx = cmdutil.revsingle(repo, node)
2694 ctx = cmdutil.revsingle(repo, node)
2694 for f in ctx:
2695 for f in ctx:
2695 if ui.debugflag:
2696 if ui.debugflag:
2696 ui.write("%40s " % hex(ctx.manifest()[f]))
2697 ui.write("%40s " % hex(ctx.manifest()[f]))
2697 if ui.verbose:
2698 if ui.verbose:
2698 ui.write(decor[ctx.flags(f)])
2699 ui.write(decor[ctx.flags(f)])
2699 ui.write("%s\n" % f)
2700 ui.write("%s\n" % f)
2700
2701
2701 def merge(ui, repo, node=None, **opts):
2702 def merge(ui, repo, node=None, **opts):
2702 """merge working directory with another revision
2703 """merge working directory with another revision
2703
2704
2704 The current working directory is updated with all changes made in
2705 The current working directory is updated with all changes made in
2705 the requested revision since the last common predecessor revision.
2706 the requested revision since the last common predecessor revision.
2706
2707
2707 Files that changed between either parent are marked as changed for
2708 Files that changed between either parent are marked as changed for
2708 the next commit and a commit must be performed before any further
2709 the next commit and a commit must be performed before any further
2709 updates to the repository are allowed. The next commit will have
2710 updates to the repository are allowed. The next commit will have
2710 two parents.
2711 two parents.
2711
2712
2712 ``--tool`` can be used to specify the merge tool used for file
2713 ``--tool`` can be used to specify the merge tool used for file
2713 merges. It overrides the HGMERGE environment variable and your
2714 merges. It overrides the HGMERGE environment variable and your
2714 configuration files.
2715 configuration files.
2715
2716
2716 If no revision is specified, the working directory's parent is a
2717 If no revision is specified, the working directory's parent is a
2717 head revision, and the current branch contains exactly one other
2718 head revision, and the current branch contains exactly one other
2718 head, the other head is merged with by default. Otherwise, an
2719 head, the other head is merged with by default. Otherwise, an
2719 explicit revision with which to merge with must be provided.
2720 explicit revision with which to merge with must be provided.
2720
2721
2721 :hg:`resolve` must be used to resolve unresolved files.
2722 :hg:`resolve` must be used to resolve unresolved files.
2722
2723
2723 To undo an uncommitted merge, use :hg:`update --clean .` which
2724 To undo an uncommitted merge, use :hg:`update --clean .` which
2724 will check out a clean copy of the original merge parent, losing
2725 will check out a clean copy of the original merge parent, losing
2725 all changes.
2726 all changes.
2726
2727
2727 Returns 0 on success, 1 if there are unresolved files.
2728 Returns 0 on success, 1 if there are unresolved files.
2728 """
2729 """
2729
2730
2730 if opts.get('rev') and node:
2731 if opts.get('rev') and node:
2731 raise util.Abort(_("please specify just one revision"))
2732 raise util.Abort(_("please specify just one revision"))
2732 if not node:
2733 if not node:
2733 node = opts.get('rev')
2734 node = opts.get('rev')
2734
2735
2735 if not node:
2736 if not node:
2736 branch = repo[None].branch()
2737 branch = repo[None].branch()
2737 bheads = repo.branchheads(branch)
2738 bheads = repo.branchheads(branch)
2738 if len(bheads) > 2:
2739 if len(bheads) > 2:
2739 raise util.Abort(_(
2740 raise util.Abort(_(
2740 'branch \'%s\' has %d heads - '
2741 'branch \'%s\' has %d heads - '
2741 'please merge with an explicit rev\n'
2742 'please merge with an explicit rev\n'
2742 '(run \'hg heads .\' to see heads)')
2743 '(run \'hg heads .\' to see heads)')
2743 % (branch, len(bheads)))
2744 % (branch, len(bheads)))
2744
2745
2745 parent = repo.dirstate.parents()[0]
2746 parent = repo.dirstate.parents()[0]
2746 if len(bheads) == 1:
2747 if len(bheads) == 1:
2747 if len(repo.heads()) > 1:
2748 if len(repo.heads()) > 1:
2748 raise util.Abort(_(
2749 raise util.Abort(_(
2749 'branch \'%s\' has one head - '
2750 'branch \'%s\' has one head - '
2750 'please merge with an explicit rev\n'
2751 'please merge with an explicit rev\n'
2751 '(run \'hg heads\' to see all heads)')
2752 '(run \'hg heads\' to see all heads)')
2752 % branch)
2753 % branch)
2753 msg = _('there is nothing to merge')
2754 msg = _('there is nothing to merge')
2754 if parent != repo.lookup(repo[None].branch()):
2755 if parent != repo.lookup(repo[None].branch()):
2755 msg = _('%s - use "hg update" instead') % msg
2756 msg = _('%s - use "hg update" instead') % msg
2756 raise util.Abort(msg)
2757 raise util.Abort(msg)
2757
2758
2758 if parent not in bheads:
2759 if parent not in bheads:
2759 raise util.Abort(_('working dir not at a head rev - '
2760 raise util.Abort(_('working dir not at a head rev - '
2760 'use "hg update" or merge with an explicit rev'))
2761 'use "hg update" or merge with an explicit rev'))
2761 node = parent == bheads[0] and bheads[-1] or bheads[0]
2762 node = parent == bheads[0] and bheads[-1] or bheads[0]
2762 else:
2763 else:
2763 node = cmdutil.revsingle(repo, node).node()
2764 node = cmdutil.revsingle(repo, node).node()
2764
2765
2765 if opts.get('preview'):
2766 if opts.get('preview'):
2766 # find nodes that are ancestors of p2 but not of p1
2767 # find nodes that are ancestors of p2 but not of p1
2767 p1 = repo.lookup('.')
2768 p1 = repo.lookup('.')
2768 p2 = repo.lookup(node)
2769 p2 = repo.lookup(node)
2769 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2770 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2770
2771
2771 displayer = cmdutil.show_changeset(ui, repo, opts)
2772 displayer = cmdutil.show_changeset(ui, repo, opts)
2772 for node in nodes:
2773 for node in nodes:
2773 displayer.show(repo[node])
2774 displayer.show(repo[node])
2774 displayer.close()
2775 displayer.close()
2775 return 0
2776 return 0
2776
2777
2777 try:
2778 try:
2778 # ui.forcemerge is an internal variable, do not document
2779 # ui.forcemerge is an internal variable, do not document
2779 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2780 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2780 return hg.merge(repo, node, force=opts.get('force'))
2781 return hg.merge(repo, node, force=opts.get('force'))
2781 finally:
2782 finally:
2782 ui.setconfig('ui', 'forcemerge', '')
2783 ui.setconfig('ui', 'forcemerge', '')
2783
2784
2784 def outgoing(ui, repo, dest=None, **opts):
2785 def outgoing(ui, repo, dest=None, **opts):
2785 """show changesets not found in the destination
2786 """show changesets not found in the destination
2786
2787
2787 Show changesets not found in the specified destination repository
2788 Show changesets not found in the specified destination repository
2788 or the default push location. These are the changesets that would
2789 or the default push location. These are the changesets that would
2789 be pushed if a push was requested.
2790 be pushed if a push was requested.
2790
2791
2791 See pull for details of valid destination formats.
2792 See pull for details of valid destination formats.
2792
2793
2793 Returns 0 if there are outgoing changes, 1 otherwise.
2794 Returns 0 if there are outgoing changes, 1 otherwise.
2794 """
2795 """
2795
2796
2796 if opts.get('bookmarks'):
2797 if opts.get('bookmarks'):
2797 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2798 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2798 dest, branches = hg.parseurl(dest, opts.get('branch'))
2799 dest, branches = hg.parseurl(dest, opts.get('branch'))
2799 other = hg.repository(hg.remoteui(repo, opts), dest)
2800 other = hg.repository(hg.remoteui(repo, opts), dest)
2800 if 'bookmarks' not in other.listkeys('namespaces'):
2801 if 'bookmarks' not in other.listkeys('namespaces'):
2801 ui.warn(_("remote doesn't support bookmarks\n"))
2802 ui.warn(_("remote doesn't support bookmarks\n"))
2802 return 0
2803 return 0
2803 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2804 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2804 return bookmarks.diff(ui, other, repo)
2805 return bookmarks.diff(ui, other, repo)
2805
2806
2806 ret = hg.outgoing(ui, repo, dest, opts)
2807 ret = hg.outgoing(ui, repo, dest, opts)
2807 return ret
2808 return ret
2808
2809
2809 def parents(ui, repo, file_=None, **opts):
2810 def parents(ui, repo, file_=None, **opts):
2810 """show the parents of the working directory or revision
2811 """show the parents of the working directory or revision
2811
2812
2812 Print the working directory's parent revisions. If a revision is
2813 Print the working directory's parent revisions. If a revision is
2813 given via -r/--rev, the parent of that revision will be printed.
2814 given via -r/--rev, the parent of that revision will be printed.
2814 If a file argument is given, the revision in which the file was
2815 If a file argument is given, the revision in which the file was
2815 last changed (before the working directory revision or the
2816 last changed (before the working directory revision or the
2816 argument to --rev if given) is printed.
2817 argument to --rev if given) is printed.
2817
2818
2818 Returns 0 on success.
2819 Returns 0 on success.
2819 """
2820 """
2820
2821
2821 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2822 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2822
2823
2823 if file_:
2824 if file_:
2824 m = cmdutil.match(repo, (file_,), opts)
2825 m = cmdutil.match(repo, (file_,), opts)
2825 if m.anypats() or len(m.files()) != 1:
2826 if m.anypats() or len(m.files()) != 1:
2826 raise util.Abort(_('can only specify an explicit filename'))
2827 raise util.Abort(_('can only specify an explicit filename'))
2827 file_ = m.files()[0]
2828 file_ = m.files()[0]
2828 filenodes = []
2829 filenodes = []
2829 for cp in ctx.parents():
2830 for cp in ctx.parents():
2830 if not cp:
2831 if not cp:
2831 continue
2832 continue
2832 try:
2833 try:
2833 filenodes.append(cp.filenode(file_))
2834 filenodes.append(cp.filenode(file_))
2834 except error.LookupError:
2835 except error.LookupError:
2835 pass
2836 pass
2836 if not filenodes:
2837 if not filenodes:
2837 raise util.Abort(_("'%s' not found in manifest!") % file_)
2838 raise util.Abort(_("'%s' not found in manifest!") % file_)
2838 fl = repo.file(file_)
2839 fl = repo.file(file_)
2839 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2840 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2840 else:
2841 else:
2841 p = [cp.node() for cp in ctx.parents()]
2842 p = [cp.node() for cp in ctx.parents()]
2842
2843
2843 displayer = cmdutil.show_changeset(ui, repo, opts)
2844 displayer = cmdutil.show_changeset(ui, repo, opts)
2844 for n in p:
2845 for n in p:
2845 if n != nullid:
2846 if n != nullid:
2846 displayer.show(repo[n])
2847 displayer.show(repo[n])
2847 displayer.close()
2848 displayer.close()
2848
2849
2849 def paths(ui, repo, search=None):
2850 def paths(ui, repo, search=None):
2850 """show aliases for remote repositories
2851 """show aliases for remote repositories
2851
2852
2852 Show definition of symbolic path name NAME. If no name is given,
2853 Show definition of symbolic path name NAME. If no name is given,
2853 show definition of all available names.
2854 show definition of all available names.
2854
2855
2855 Path names are defined in the [paths] section of your
2856 Path names are defined in the [paths] section of your
2856 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2857 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2857 repository, ``.hg/hgrc`` is used, too.
2858 repository, ``.hg/hgrc`` is used, too.
2858
2859
2859 The path names ``default`` and ``default-push`` have a special
2860 The path names ``default`` and ``default-push`` have a special
2860 meaning. When performing a push or pull operation, they are used
2861 meaning. When performing a push or pull operation, they are used
2861 as fallbacks if no location is specified on the command-line.
2862 as fallbacks if no location is specified on the command-line.
2862 When ``default-push`` is set, it will be used for push and
2863 When ``default-push`` is set, it will be used for push and
2863 ``default`` will be used for pull; otherwise ``default`` is used
2864 ``default`` will be used for pull; otherwise ``default`` is used
2864 as the fallback for both. When cloning a repository, the clone
2865 as the fallback for both. When cloning a repository, the clone
2865 source is written as ``default`` in ``.hg/hgrc``. Note that
2866 source is written as ``default`` in ``.hg/hgrc``. Note that
2866 ``default`` and ``default-push`` apply to all inbound (e.g.
2867 ``default`` and ``default-push`` apply to all inbound (e.g.
2867 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2868 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2868 :hg:`bundle`) operations.
2869 :hg:`bundle`) operations.
2869
2870
2870 See :hg:`help urls` for more information.
2871 See :hg:`help urls` for more information.
2871
2872
2872 Returns 0 on success.
2873 Returns 0 on success.
2873 """
2874 """
2874 if search:
2875 if search:
2875 for name, path in ui.configitems("paths"):
2876 for name, path in ui.configitems("paths"):
2876 if name == search:
2877 if name == search:
2877 ui.write("%s\n" % url.hidepassword(path))
2878 ui.write("%s\n" % url.hidepassword(path))
2878 return
2879 return
2879 ui.warn(_("not found!\n"))
2880 ui.warn(_("not found!\n"))
2880 return 1
2881 return 1
2881 else:
2882 else:
2882 for name, path in ui.configitems("paths"):
2883 for name, path in ui.configitems("paths"):
2883 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2884 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2884
2885
2885 def postincoming(ui, repo, modheads, optupdate, checkout):
2886 def postincoming(ui, repo, modheads, optupdate, checkout):
2886 if modheads == 0:
2887 if modheads == 0:
2887 return
2888 return
2888 if optupdate:
2889 if optupdate:
2889 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2890 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2890 return hg.update(repo, checkout)
2891 return hg.update(repo, checkout)
2891 else:
2892 else:
2892 ui.status(_("not updating, since new heads added\n"))
2893 ui.status(_("not updating, since new heads added\n"))
2893 if modheads > 1:
2894 if modheads > 1:
2894 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2895 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2895 else:
2896 else:
2896 ui.status(_("(run 'hg update' to get a working copy)\n"))
2897 ui.status(_("(run 'hg update' to get a working copy)\n"))
2897
2898
2898 def pull(ui, repo, source="default", **opts):
2899 def pull(ui, repo, source="default", **opts):
2899 """pull changes from the specified source
2900 """pull changes from the specified source
2900
2901
2901 Pull changes from a remote repository to a local one.
2902 Pull changes from a remote repository to a local one.
2902
2903
2903 This finds all changes from the repository at the specified path
2904 This finds all changes from the repository at the specified path
2904 or URL and adds them to a local repository (the current one unless
2905 or URL and adds them to a local repository (the current one unless
2905 -R is specified). By default, this does not update the copy of the
2906 -R is specified). By default, this does not update the copy of the
2906 project in the working directory.
2907 project in the working directory.
2907
2908
2908 Use :hg:`incoming` if you want to see what would have been added
2909 Use :hg:`incoming` if you want to see what would have been added
2909 by a pull at the time you issued this command. If you then decide
2910 by a pull at the time you issued this command. If you then decide
2910 to add those changes to the repository, you should use :hg:`pull
2911 to add those changes to the repository, you should use :hg:`pull
2911 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2912 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2912
2913
2913 If SOURCE is omitted, the 'default' path will be used.
2914 If SOURCE is omitted, the 'default' path will be used.
2914 See :hg:`help urls` for more information.
2915 See :hg:`help urls` for more information.
2915
2916
2916 Returns 0 on success, 1 if an update had unresolved files.
2917 Returns 0 on success, 1 if an update had unresolved files.
2917 """
2918 """
2918 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2919 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2919 other = hg.repository(hg.remoteui(repo, opts), source)
2920 other = hg.repository(hg.remoteui(repo, opts), source)
2920 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2921 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2921 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2922 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2922
2923
2923 if opts.get('bookmark'):
2924 if opts.get('bookmark'):
2924 if not revs:
2925 if not revs:
2925 revs = []
2926 revs = []
2926 rb = other.listkeys('bookmarks')
2927 rb = other.listkeys('bookmarks')
2927 for b in opts['bookmark']:
2928 for b in opts['bookmark']:
2928 if b not in rb:
2929 if b not in rb:
2929 raise util.Abort(_('remote bookmark %s not found!') % b)
2930 raise util.Abort(_('remote bookmark %s not found!') % b)
2930 revs.append(rb[b])
2931 revs.append(rb[b])
2931
2932
2932 if revs:
2933 if revs:
2933 try:
2934 try:
2934 revs = [other.lookup(rev) for rev in revs]
2935 revs = [other.lookup(rev) for rev in revs]
2935 except error.CapabilityError:
2936 except error.CapabilityError:
2936 err = _("other repository doesn't support revision lookup, "
2937 err = _("other repository doesn't support revision lookup, "
2937 "so a rev cannot be specified.")
2938 "so a rev cannot be specified.")
2938 raise util.Abort(err)
2939 raise util.Abort(err)
2939
2940
2940 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2941 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2941 if checkout:
2942 if checkout:
2942 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2943 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2943 repo._subtoppath = source
2944 repo._subtoppath = source
2944 try:
2945 try:
2945 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
2946 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
2946
2947
2947 finally:
2948 finally:
2948 del repo._subtoppath
2949 del repo._subtoppath
2949
2950
2950 # update specified bookmarks
2951 # update specified bookmarks
2951 if opts.get('bookmark'):
2952 if opts.get('bookmark'):
2952 for b in opts['bookmark']:
2953 for b in opts['bookmark']:
2953 # explicit pull overrides local bookmark if any
2954 # explicit pull overrides local bookmark if any
2954 ui.status(_("importing bookmark %s\n") % b)
2955 ui.status(_("importing bookmark %s\n") % b)
2955 repo._bookmarks[b] = repo[rb[b]].node()
2956 repo._bookmarks[b] = repo[rb[b]].node()
2956 bookmarks.write(repo)
2957 bookmarks.write(repo)
2957
2958
2958 return ret
2959 return ret
2959
2960
2960 def push(ui, repo, dest=None, **opts):
2961 def push(ui, repo, dest=None, **opts):
2961 """push changes to the specified destination
2962 """push changes to the specified destination
2962
2963
2963 Push changesets from the local repository to the specified
2964 Push changesets from the local repository to the specified
2964 destination.
2965 destination.
2965
2966
2966 This operation is symmetrical to pull: it is identical to a pull
2967 This operation is symmetrical to pull: it is identical to a pull
2967 in the destination repository from the current one.
2968 in the destination repository from the current one.
2968
2969
2969 By default, push will not allow creation of new heads at the
2970 By default, push will not allow creation of new heads at the
2970 destination, since multiple heads would make it unclear which head
2971 destination, since multiple heads would make it unclear which head
2971 to use. In this situation, it is recommended to pull and merge
2972 to use. In this situation, it is recommended to pull and merge
2972 before pushing.
2973 before pushing.
2973
2974
2974 Use --new-branch if you want to allow push to create a new named
2975 Use --new-branch if you want to allow push to create a new named
2975 branch that is not present at the destination. This allows you to
2976 branch that is not present at the destination. This allows you to
2976 only create a new branch without forcing other changes.
2977 only create a new branch without forcing other changes.
2977
2978
2978 Use -f/--force to override the default behavior and push all
2979 Use -f/--force to override the default behavior and push all
2979 changesets on all branches.
2980 changesets on all branches.
2980
2981
2981 If -r/--rev is used, the specified revision and all its ancestors
2982 If -r/--rev is used, the specified revision and all its ancestors
2982 will be pushed to the remote repository.
2983 will be pushed to the remote repository.
2983
2984
2984 Please see :hg:`help urls` for important details about ``ssh://``
2985 Please see :hg:`help urls` for important details about ``ssh://``
2985 URLs. If DESTINATION is omitted, a default path will be used.
2986 URLs. If DESTINATION is omitted, a default path will be used.
2986
2987
2987 Returns 0 if push was successful, 1 if nothing to push.
2988 Returns 0 if push was successful, 1 if nothing to push.
2988 """
2989 """
2989
2990
2990 if opts.get('bookmark'):
2991 if opts.get('bookmark'):
2991 for b in opts['bookmark']:
2992 for b in opts['bookmark']:
2992 # translate -B options to -r so changesets get pushed
2993 # translate -B options to -r so changesets get pushed
2993 if b in repo._bookmarks:
2994 if b in repo._bookmarks:
2994 opts.setdefault('rev', []).append(b)
2995 opts.setdefault('rev', []).append(b)
2995 else:
2996 else:
2996 # if we try to push a deleted bookmark, translate it to null
2997 # if we try to push a deleted bookmark, translate it to null
2997 # this lets simultaneous -r, -b options continue working
2998 # this lets simultaneous -r, -b options continue working
2998 opts.setdefault('rev', []).append("null")
2999 opts.setdefault('rev', []).append("null")
2999
3000
3000 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3001 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3001 dest, branches = hg.parseurl(dest, opts.get('branch'))
3002 dest, branches = hg.parseurl(dest, opts.get('branch'))
3002 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3003 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3003 other = hg.repository(hg.remoteui(repo, opts), dest)
3004 other = hg.repository(hg.remoteui(repo, opts), dest)
3004 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
3005 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
3005 if revs:
3006 if revs:
3006 revs = [repo.lookup(rev) for rev in revs]
3007 revs = [repo.lookup(rev) for rev in revs]
3007
3008
3008 repo._subtoppath = dest
3009 repo._subtoppath = dest
3009 try:
3010 try:
3010 # push subrepos depth-first for coherent ordering
3011 # push subrepos depth-first for coherent ordering
3011 c = repo['']
3012 c = repo['']
3012 subs = c.substate # only repos that are committed
3013 subs = c.substate # only repos that are committed
3013 for s in sorted(subs):
3014 for s in sorted(subs):
3014 if not c.sub(s).push(opts.get('force')):
3015 if not c.sub(s).push(opts.get('force')):
3015 return False
3016 return False
3016 finally:
3017 finally:
3017 del repo._subtoppath
3018 del repo._subtoppath
3018 result = repo.push(other, opts.get('force'), revs=revs,
3019 result = repo.push(other, opts.get('force'), revs=revs,
3019 newbranch=opts.get('new_branch'))
3020 newbranch=opts.get('new_branch'))
3020
3021
3021 result = (result == 0)
3022 result = (result == 0)
3022
3023
3023 if opts.get('bookmark'):
3024 if opts.get('bookmark'):
3024 rb = other.listkeys('bookmarks')
3025 rb = other.listkeys('bookmarks')
3025 for b in opts['bookmark']:
3026 for b in opts['bookmark']:
3026 # explicit push overrides remote bookmark if any
3027 # explicit push overrides remote bookmark if any
3027 if b in repo._bookmarks:
3028 if b in repo._bookmarks:
3028 ui.status(_("exporting bookmark %s\n") % b)
3029 ui.status(_("exporting bookmark %s\n") % b)
3029 new = repo[b].hex()
3030 new = repo[b].hex()
3030 elif b in rb:
3031 elif b in rb:
3031 ui.status(_("deleting remote bookmark %s\n") % b)
3032 ui.status(_("deleting remote bookmark %s\n") % b)
3032 new = '' # delete
3033 new = '' # delete
3033 else:
3034 else:
3034 ui.warn(_('bookmark %s does not exist on the local '
3035 ui.warn(_('bookmark %s does not exist on the local '
3035 'or remote repository!\n') % b)
3036 'or remote repository!\n') % b)
3036 return 2
3037 return 2
3037 old = rb.get(b, '')
3038 old = rb.get(b, '')
3038 r = other.pushkey('bookmarks', b, old, new)
3039 r = other.pushkey('bookmarks', b, old, new)
3039 if not r:
3040 if not r:
3040 ui.warn(_('updating bookmark %s failed!\n') % b)
3041 ui.warn(_('updating bookmark %s failed!\n') % b)
3041 if not result:
3042 if not result:
3042 result = 2
3043 result = 2
3043
3044
3044 return result
3045 return result
3045
3046
3046 def recover(ui, repo):
3047 def recover(ui, repo):
3047 """roll back an interrupted transaction
3048 """roll back an interrupted transaction
3048
3049
3049 Recover from an interrupted commit or pull.
3050 Recover from an interrupted commit or pull.
3050
3051
3051 This command tries to fix the repository status after an
3052 This command tries to fix the repository status after an
3052 interrupted operation. It should only be necessary when Mercurial
3053 interrupted operation. It should only be necessary when Mercurial
3053 suggests it.
3054 suggests it.
3054
3055
3055 Returns 0 if successful, 1 if nothing to recover or verify fails.
3056 Returns 0 if successful, 1 if nothing to recover or verify fails.
3056 """
3057 """
3057 if repo.recover():
3058 if repo.recover():
3058 return hg.verify(repo)
3059 return hg.verify(repo)
3059 return 1
3060 return 1
3060
3061
3061 def remove(ui, repo, *pats, **opts):
3062 def remove(ui, repo, *pats, **opts):
3062 """remove the specified files on the next commit
3063 """remove the specified files on the next commit
3063
3064
3064 Schedule the indicated files for removal from the repository.
3065 Schedule the indicated files for removal from the repository.
3065
3066
3066 This only removes files from the current branch, not from the
3067 This only removes files from the current branch, not from the
3067 entire project history. -A/--after can be used to remove only
3068 entire project history. -A/--after can be used to remove only
3068 files that have already been deleted, -f/--force can be used to
3069 files that have already been deleted, -f/--force can be used to
3069 force deletion, and -Af can be used to remove files from the next
3070 force deletion, and -Af can be used to remove files from the next
3070 revision without deleting them from the working directory.
3071 revision without deleting them from the working directory.
3071
3072
3072 The following table details the behavior of remove for different
3073 The following table details the behavior of remove for different
3073 file states (columns) and option combinations (rows). The file
3074 file states (columns) and option combinations (rows). The file
3074 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3075 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3075 reported by :hg:`status`). The actions are Warn, Remove (from
3076 reported by :hg:`status`). The actions are Warn, Remove (from
3076 branch) and Delete (from disk)::
3077 branch) and Delete (from disk)::
3077
3078
3078 A C M !
3079 A C M !
3079 none W RD W R
3080 none W RD W R
3080 -f R RD RD R
3081 -f R RD RD R
3081 -A W W W R
3082 -A W W W R
3082 -Af R R R R
3083 -Af R R R R
3083
3084
3084 This command schedules the files to be removed at the next commit.
3085 This command schedules the files to be removed at the next commit.
3085 To undo a remove before that, see :hg:`revert`.
3086 To undo a remove before that, see :hg:`revert`.
3086
3087
3087 Returns 0 on success, 1 if any warnings encountered.
3088 Returns 0 on success, 1 if any warnings encountered.
3088 """
3089 """
3089
3090
3090 ret = 0
3091 ret = 0
3091 after, force = opts.get('after'), opts.get('force')
3092 after, force = opts.get('after'), opts.get('force')
3092 if not pats and not after:
3093 if not pats and not after:
3093 raise util.Abort(_('no files specified'))
3094 raise util.Abort(_('no files specified'))
3094
3095
3095 m = cmdutil.match(repo, pats, opts)
3096 m = cmdutil.match(repo, pats, opts)
3096 s = repo.status(match=m, clean=True)
3097 s = repo.status(match=m, clean=True)
3097 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3098 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3098
3099
3099 for f in m.files():
3100 for f in m.files():
3100 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3101 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3101 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3102 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3102 ret = 1
3103 ret = 1
3103
3104
3104 if force:
3105 if force:
3105 remove, forget = modified + deleted + clean, added
3106 remove, forget = modified + deleted + clean, added
3106 elif after:
3107 elif after:
3107 remove, forget = deleted, []
3108 remove, forget = deleted, []
3108 for f in modified + added + clean:
3109 for f in modified + added + clean:
3109 ui.warn(_('not removing %s: file still exists (use -f'
3110 ui.warn(_('not removing %s: file still exists (use -f'
3110 ' to force removal)\n') % m.rel(f))
3111 ' to force removal)\n') % m.rel(f))
3111 ret = 1
3112 ret = 1
3112 else:
3113 else:
3113 remove, forget = deleted + clean, []
3114 remove, forget = deleted + clean, []
3114 for f in modified:
3115 for f in modified:
3115 ui.warn(_('not removing %s: file is modified (use -f'
3116 ui.warn(_('not removing %s: file is modified (use -f'
3116 ' to force removal)\n') % m.rel(f))
3117 ' to force removal)\n') % m.rel(f))
3117 ret = 1
3118 ret = 1
3118 for f in added:
3119 for f in added:
3119 ui.warn(_('not removing %s: file has been marked for add (use -f'
3120 ui.warn(_('not removing %s: file has been marked for add (use -f'
3120 ' to force removal)\n') % m.rel(f))
3121 ' to force removal)\n') % m.rel(f))
3121 ret = 1
3122 ret = 1
3122
3123
3123 for f in sorted(remove + forget):
3124 for f in sorted(remove + forget):
3124 if ui.verbose or not m.exact(f):
3125 if ui.verbose or not m.exact(f):
3125 ui.status(_('removing %s\n') % m.rel(f))
3126 ui.status(_('removing %s\n') % m.rel(f))
3126
3127
3127 repo[None].forget(forget)
3128 repo[None].forget(forget)
3128 repo[None].remove(remove, unlink=not after)
3129 repo[None].remove(remove, unlink=not after)
3129 return ret
3130 return ret
3130
3131
3131 def rename(ui, repo, *pats, **opts):
3132 def rename(ui, repo, *pats, **opts):
3132 """rename files; equivalent of copy + remove
3133 """rename files; equivalent of copy + remove
3133
3134
3134 Mark dest as copies of sources; mark sources for deletion. If dest
3135 Mark dest as copies of sources; mark sources for deletion. If dest
3135 is a directory, copies are put in that directory. If dest is a
3136 is a directory, copies are put in that directory. If dest is a
3136 file, there can only be one source.
3137 file, there can only be one source.
3137
3138
3138 By default, this command copies the contents of files as they
3139 By default, this command copies the contents of files as they
3139 exist in the working directory. If invoked with -A/--after, the
3140 exist in the working directory. If invoked with -A/--after, the
3140 operation is recorded, but no copying is performed.
3141 operation is recorded, but no copying is performed.
3141
3142
3142 This command takes effect at the next commit. To undo a rename
3143 This command takes effect at the next commit. To undo a rename
3143 before that, see :hg:`revert`.
3144 before that, see :hg:`revert`.
3144
3145
3145 Returns 0 on success, 1 if errors are encountered.
3146 Returns 0 on success, 1 if errors are encountered.
3146 """
3147 """
3147 wlock = repo.wlock(False)
3148 wlock = repo.wlock(False)
3148 try:
3149 try:
3149 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3150 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3150 finally:
3151 finally:
3151 wlock.release()
3152 wlock.release()
3152
3153
3153 def resolve(ui, repo, *pats, **opts):
3154 def resolve(ui, repo, *pats, **opts):
3154 """redo merges or set/view the merge status of files
3155 """redo merges or set/view the merge status of files
3155
3156
3156 Merges with unresolved conflicts are often the result of
3157 Merges with unresolved conflicts are often the result of
3157 non-interactive merging using the ``internal:merge`` configuration
3158 non-interactive merging using the ``internal:merge`` configuration
3158 setting, or a command-line merge tool like ``diff3``. The resolve
3159 setting, or a command-line merge tool like ``diff3``. The resolve
3159 command is used to manage the files involved in a merge, after
3160 command is used to manage the files involved in a merge, after
3160 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3161 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3161 working directory must have two parents).
3162 working directory must have two parents).
3162
3163
3163 The resolve command can be used in the following ways:
3164 The resolve command can be used in the following ways:
3164
3165
3165 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3166 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3166 files, discarding any previous merge attempts. Re-merging is not
3167 files, discarding any previous merge attempts. Re-merging is not
3167 performed for files already marked as resolved. Use ``--all/-a``
3168 performed for files already marked as resolved. Use ``--all/-a``
3168 to selects all unresolved files. ``--tool`` can be used to specify
3169 to selects all unresolved files. ``--tool`` can be used to specify
3169 the merge tool used for the given files. It overrides the HGMERGE
3170 the merge tool used for the given files. It overrides the HGMERGE
3170 environment variable and your configuration files.
3171 environment variable and your configuration files.
3171
3172
3172 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3173 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3173 (e.g. after having manually fixed-up the files). The default is
3174 (e.g. after having manually fixed-up the files). The default is
3174 to mark all unresolved files.
3175 to mark all unresolved files.
3175
3176
3176 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3177 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3177 default is to mark all resolved files.
3178 default is to mark all resolved files.
3178
3179
3179 - :hg:`resolve -l`: list files which had or still have conflicts.
3180 - :hg:`resolve -l`: list files which had or still have conflicts.
3180 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3181 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3181
3182
3182 Note that Mercurial will not let you commit files with unresolved
3183 Note that Mercurial will not let you commit files with unresolved
3183 merge conflicts. You must use :hg:`resolve -m ...` before you can
3184 merge conflicts. You must use :hg:`resolve -m ...` before you can
3184 commit after a conflicting merge.
3185 commit after a conflicting merge.
3185
3186
3186 Returns 0 on success, 1 if any files fail a resolve attempt.
3187 Returns 0 on success, 1 if any files fail a resolve attempt.
3187 """
3188 """
3188
3189
3189 all, mark, unmark, show, nostatus = \
3190 all, mark, unmark, show, nostatus = \
3190 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3191 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3191
3192
3192 if (show and (mark or unmark)) or (mark and unmark):
3193 if (show and (mark or unmark)) or (mark and unmark):
3193 raise util.Abort(_("too many options specified"))
3194 raise util.Abort(_("too many options specified"))
3194 if pats and all:
3195 if pats and all:
3195 raise util.Abort(_("can't specify --all and patterns"))
3196 raise util.Abort(_("can't specify --all and patterns"))
3196 if not (all or pats or show or mark or unmark):
3197 if not (all or pats or show or mark or unmark):
3197 raise util.Abort(_('no files or directories specified; '
3198 raise util.Abort(_('no files or directories specified; '
3198 'use --all to remerge all files'))
3199 'use --all to remerge all files'))
3199
3200
3200 ms = mergemod.mergestate(repo)
3201 ms = mergemod.mergestate(repo)
3201 m = cmdutil.match(repo, pats, opts)
3202 m = cmdutil.match(repo, pats, opts)
3202 ret = 0
3203 ret = 0
3203
3204
3204 for f in ms:
3205 for f in ms:
3205 if m(f):
3206 if m(f):
3206 if show:
3207 if show:
3207 if nostatus:
3208 if nostatus:
3208 ui.write("%s\n" % f)
3209 ui.write("%s\n" % f)
3209 else:
3210 else:
3210 ui.write("%s %s\n" % (ms[f].upper(), f),
3211 ui.write("%s %s\n" % (ms[f].upper(), f),
3211 label='resolve.' +
3212 label='resolve.' +
3212 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3213 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3213 elif mark:
3214 elif mark:
3214 ms.mark(f, "r")
3215 ms.mark(f, "r")
3215 elif unmark:
3216 elif unmark:
3216 ms.mark(f, "u")
3217 ms.mark(f, "u")
3217 else:
3218 else:
3218 wctx = repo[None]
3219 wctx = repo[None]
3219 mctx = wctx.parents()[-1]
3220 mctx = wctx.parents()[-1]
3220
3221
3221 # backup pre-resolve (merge uses .orig for its own purposes)
3222 # backup pre-resolve (merge uses .orig for its own purposes)
3222 a = repo.wjoin(f)
3223 a = repo.wjoin(f)
3223 util.copyfile(a, a + ".resolve")
3224 util.copyfile(a, a + ".resolve")
3224
3225
3225 try:
3226 try:
3226 # resolve file
3227 # resolve file
3227 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3228 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3228 if ms.resolve(f, wctx, mctx):
3229 if ms.resolve(f, wctx, mctx):
3229 ret = 1
3230 ret = 1
3230 finally:
3231 finally:
3231 ui.setconfig('ui', 'forcemerge', '')
3232 ui.setconfig('ui', 'forcemerge', '')
3232
3233
3233 # replace filemerge's .orig file with our resolve file
3234 # replace filemerge's .orig file with our resolve file
3234 util.rename(a + ".resolve", a + ".orig")
3235 util.rename(a + ".resolve", a + ".orig")
3235
3236
3236 ms.commit()
3237 ms.commit()
3237 return ret
3238 return ret
3238
3239
3239 def revert(ui, repo, *pats, **opts):
3240 def revert(ui, repo, *pats, **opts):
3240 """restore individual files or directories to an earlier state
3241 """restore individual files or directories to an earlier state
3241
3242
3242 .. note::
3243 .. note::
3243 This command is most likely not what you are looking for.
3244 This command is most likely not what you are looking for.
3244 Revert will partially overwrite content in the working
3245 Revert will partially overwrite content in the working
3245 directory without changing the working directory parents. Use
3246 directory without changing the working directory parents. Use
3246 :hg:`update -r rev` to check out earlier revisions, or
3247 :hg:`update -r rev` to check out earlier revisions, or
3247 :hg:`update --clean .` to undo a merge which has added another
3248 :hg:`update --clean .` to undo a merge which has added another
3248 parent.
3249 parent.
3249
3250
3250 With no revision specified, revert the named files or directories
3251 With no revision specified, revert the named files or directories
3251 to the contents they had in the parent of the working directory.
3252 to the contents they had in the parent of the working directory.
3252 This restores the contents of the affected files to an unmodified
3253 This restores the contents of the affected files to an unmodified
3253 state and unschedules adds, removes, copies, and renames. If the
3254 state and unschedules adds, removes, copies, and renames. If the
3254 working directory has two parents, you must explicitly specify a
3255 working directory has two parents, you must explicitly specify a
3255 revision.
3256 revision.
3256
3257
3257 Using the -r/--rev option, revert the given files or directories
3258 Using the -r/--rev option, revert the given files or directories
3258 to their contents as of a specific revision. This can be helpful
3259 to their contents as of a specific revision. This can be helpful
3259 to "roll back" some or all of an earlier change. See :hg:`help
3260 to "roll back" some or all of an earlier change. See :hg:`help
3260 dates` for a list of formats valid for -d/--date.
3261 dates` for a list of formats valid for -d/--date.
3261
3262
3262 Revert modifies the working directory. It does not commit any
3263 Revert modifies the working directory. It does not commit any
3263 changes, or change the parent of the working directory. If you
3264 changes, or change the parent of the working directory. If you
3264 revert to a revision other than the parent of the working
3265 revert to a revision other than the parent of the working
3265 directory, the reverted files will thus appear modified
3266 directory, the reverted files will thus appear modified
3266 afterwards.
3267 afterwards.
3267
3268
3268 If a file has been deleted, it is restored. If the executable mode
3269 If a file has been deleted, it is restored. If the executable mode
3269 of a file was changed, it is reset.
3270 of a file was changed, it is reset.
3270
3271
3271 If names are given, all files matching the names are reverted.
3272 If names are given, all files matching the names are reverted.
3272 If no arguments are given, no files are reverted.
3273 If no arguments are given, no files are reverted.
3273
3274
3274 Modified files are saved with a .orig suffix before reverting.
3275 Modified files are saved with a .orig suffix before reverting.
3275 To disable these backups, use --no-backup.
3276 To disable these backups, use --no-backup.
3276
3277
3277 Returns 0 on success.
3278 Returns 0 on success.
3278 """
3279 """
3279
3280
3280 if opts.get("date"):
3281 if opts.get("date"):
3281 if opts.get("rev"):
3282 if opts.get("rev"):
3282 raise util.Abort(_("you can't specify a revision and a date"))
3283 raise util.Abort(_("you can't specify a revision and a date"))
3283 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3284 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3284
3285
3285 parent, p2 = repo.dirstate.parents()
3286 parent, p2 = repo.dirstate.parents()
3286 if not opts.get('rev') and p2 != nullid:
3287 if not opts.get('rev') and p2 != nullid:
3287 raise util.Abort(_('uncommitted merge - '
3288 raise util.Abort(_('uncommitted merge - '
3288 'use "hg update", see "hg help revert"'))
3289 'use "hg update", see "hg help revert"'))
3289
3290
3290 if not pats and not opts.get('all'):
3291 if not pats and not opts.get('all'):
3291 raise util.Abort(_('no files or directories specified; '
3292 raise util.Abort(_('no files or directories specified; '
3292 'use --all to revert the whole repo'))
3293 'use --all to revert the whole repo'))
3293
3294
3294 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3295 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3295 node = ctx.node()
3296 node = ctx.node()
3296 mf = ctx.manifest()
3297 mf = ctx.manifest()
3297 if node == parent:
3298 if node == parent:
3298 pmf = mf
3299 pmf = mf
3299 else:
3300 else:
3300 pmf = None
3301 pmf = None
3301
3302
3302 # need all matching names in dirstate and manifest of target rev,
3303 # need all matching names in dirstate and manifest of target rev,
3303 # so have to walk both. do not print errors if files exist in one
3304 # so have to walk both. do not print errors if files exist in one
3304 # but not other.
3305 # but not other.
3305
3306
3306 names = {}
3307 names = {}
3307
3308
3308 wlock = repo.wlock()
3309 wlock = repo.wlock()
3309 try:
3310 try:
3310 # walk dirstate.
3311 # walk dirstate.
3311
3312
3312 m = cmdutil.match(repo, pats, opts)
3313 m = cmdutil.match(repo, pats, opts)
3313 m.bad = lambda x, y: False
3314 m.bad = lambda x, y: False
3314 for abs in repo.walk(m):
3315 for abs in repo.walk(m):
3315 names[abs] = m.rel(abs), m.exact(abs)
3316 names[abs] = m.rel(abs), m.exact(abs)
3316
3317
3317 # walk target manifest.
3318 # walk target manifest.
3318
3319
3319 def badfn(path, msg):
3320 def badfn(path, msg):
3320 if path in names:
3321 if path in names:
3321 return
3322 return
3322 path_ = path + '/'
3323 path_ = path + '/'
3323 for f in names:
3324 for f in names:
3324 if f.startswith(path_):
3325 if f.startswith(path_):
3325 return
3326 return
3326 ui.warn("%s: %s\n" % (m.rel(path), msg))
3327 ui.warn("%s: %s\n" % (m.rel(path), msg))
3327
3328
3328 m = cmdutil.match(repo, pats, opts)
3329 m = cmdutil.match(repo, pats, opts)
3329 m.bad = badfn
3330 m.bad = badfn
3330 for abs in repo[node].walk(m):
3331 for abs in repo[node].walk(m):
3331 if abs not in names:
3332 if abs not in names:
3332 names[abs] = m.rel(abs), m.exact(abs)
3333 names[abs] = m.rel(abs), m.exact(abs)
3333
3334
3334 m = cmdutil.matchfiles(repo, names)
3335 m = cmdutil.matchfiles(repo, names)
3335 changes = repo.status(match=m)[:4]
3336 changes = repo.status(match=m)[:4]
3336 modified, added, removed, deleted = map(set, changes)
3337 modified, added, removed, deleted = map(set, changes)
3337
3338
3338 # if f is a rename, also revert the source
3339 # if f is a rename, also revert the source
3339 cwd = repo.getcwd()
3340 cwd = repo.getcwd()
3340 for f in added:
3341 for f in added:
3341 src = repo.dirstate.copied(f)
3342 src = repo.dirstate.copied(f)
3342 if src and src not in names and repo.dirstate[src] == 'r':
3343 if src and src not in names and repo.dirstate[src] == 'r':
3343 removed.add(src)
3344 removed.add(src)
3344 names[src] = (repo.pathto(src, cwd), True)
3345 names[src] = (repo.pathto(src, cwd), True)
3345
3346
3346 def removeforget(abs):
3347 def removeforget(abs):
3347 if repo.dirstate[abs] == 'a':
3348 if repo.dirstate[abs] == 'a':
3348 return _('forgetting %s\n')
3349 return _('forgetting %s\n')
3349 return _('removing %s\n')
3350 return _('removing %s\n')
3350
3351
3351 revert = ([], _('reverting %s\n'))
3352 revert = ([], _('reverting %s\n'))
3352 add = ([], _('adding %s\n'))
3353 add = ([], _('adding %s\n'))
3353 remove = ([], removeforget)
3354 remove = ([], removeforget)
3354 undelete = ([], _('undeleting %s\n'))
3355 undelete = ([], _('undeleting %s\n'))
3355
3356
3356 disptable = (
3357 disptable = (
3357 # dispatch table:
3358 # dispatch table:
3358 # file state
3359 # file state
3359 # action if in target manifest
3360 # action if in target manifest
3360 # action if not in target manifest
3361 # action if not in target manifest
3361 # make backup if in target manifest
3362 # make backup if in target manifest
3362 # make backup if not in target manifest
3363 # make backup if not in target manifest
3363 (modified, revert, remove, True, True),
3364 (modified, revert, remove, True, True),
3364 (added, revert, remove, True, False),
3365 (added, revert, remove, True, False),
3365 (removed, undelete, None, False, False),
3366 (removed, undelete, None, False, False),
3366 (deleted, revert, remove, False, False),
3367 (deleted, revert, remove, False, False),
3367 )
3368 )
3368
3369
3369 for abs, (rel, exact) in sorted(names.items()):
3370 for abs, (rel, exact) in sorted(names.items()):
3370 mfentry = mf.get(abs)
3371 mfentry = mf.get(abs)
3371 target = repo.wjoin(abs)
3372 target = repo.wjoin(abs)
3372 def handle(xlist, dobackup):
3373 def handle(xlist, dobackup):
3373 xlist[0].append(abs)
3374 xlist[0].append(abs)
3374 if (dobackup and not opts.get('no_backup') and
3375 if (dobackup and not opts.get('no_backup') and
3375 os.path.lexists(target)):
3376 os.path.lexists(target)):
3376 bakname = "%s.orig" % rel
3377 bakname = "%s.orig" % rel
3377 ui.note(_('saving current version of %s as %s\n') %
3378 ui.note(_('saving current version of %s as %s\n') %
3378 (rel, bakname))
3379 (rel, bakname))
3379 if not opts.get('dry_run'):
3380 if not opts.get('dry_run'):
3380 util.rename(target, bakname)
3381 util.rename(target, bakname)
3381 if ui.verbose or not exact:
3382 if ui.verbose or not exact:
3382 msg = xlist[1]
3383 msg = xlist[1]
3383 if not isinstance(msg, basestring):
3384 if not isinstance(msg, basestring):
3384 msg = msg(abs)
3385 msg = msg(abs)
3385 ui.status(msg % rel)
3386 ui.status(msg % rel)
3386 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3387 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3387 if abs not in table:
3388 if abs not in table:
3388 continue
3389 continue
3389 # file has changed in dirstate
3390 # file has changed in dirstate
3390 if mfentry:
3391 if mfentry:
3391 handle(hitlist, backuphit)
3392 handle(hitlist, backuphit)
3392 elif misslist is not None:
3393 elif misslist is not None:
3393 handle(misslist, backupmiss)
3394 handle(misslist, backupmiss)
3394 break
3395 break
3395 else:
3396 else:
3396 if abs not in repo.dirstate:
3397 if abs not in repo.dirstate:
3397 if mfentry:
3398 if mfentry:
3398 handle(add, True)
3399 handle(add, True)
3399 elif exact:
3400 elif exact:
3400 ui.warn(_('file not managed: %s\n') % rel)
3401 ui.warn(_('file not managed: %s\n') % rel)
3401 continue
3402 continue
3402 # file has not changed in dirstate
3403 # file has not changed in dirstate
3403 if node == parent:
3404 if node == parent:
3404 if exact:
3405 if exact:
3405 ui.warn(_('no changes needed to %s\n') % rel)
3406 ui.warn(_('no changes needed to %s\n') % rel)
3406 continue
3407 continue
3407 if pmf is None:
3408 if pmf is None:
3408 # only need parent manifest in this unlikely case,
3409 # only need parent manifest in this unlikely case,
3409 # so do not read by default
3410 # so do not read by default
3410 pmf = repo[parent].manifest()
3411 pmf = repo[parent].manifest()
3411 if abs in pmf:
3412 if abs in pmf:
3412 if mfentry:
3413 if mfentry:
3413 # if version of file is same in parent and target
3414 # if version of file is same in parent and target
3414 # manifests, do nothing
3415 # manifests, do nothing
3415 if (pmf[abs] != mfentry or
3416 if (pmf[abs] != mfentry or
3416 pmf.flags(abs) != mf.flags(abs)):
3417 pmf.flags(abs) != mf.flags(abs)):
3417 handle(revert, False)
3418 handle(revert, False)
3418 else:
3419 else:
3419 handle(remove, False)
3420 handle(remove, False)
3420
3421
3421 if not opts.get('dry_run'):
3422 if not opts.get('dry_run'):
3422 def checkout(f):
3423 def checkout(f):
3423 fc = ctx[f]
3424 fc = ctx[f]
3424 repo.wwrite(f, fc.data(), fc.flags())
3425 repo.wwrite(f, fc.data(), fc.flags())
3425
3426
3426 audit_path = util.path_auditor(repo.root)
3427 audit_path = util.path_auditor(repo.root)
3427 for f in remove[0]:
3428 for f in remove[0]:
3428 if repo.dirstate[f] == 'a':
3429 if repo.dirstate[f] == 'a':
3429 repo.dirstate.forget(f)
3430 repo.dirstate.forget(f)
3430 continue
3431 continue
3431 audit_path(f)
3432 audit_path(f)
3432 try:
3433 try:
3433 util.unlinkpath(repo.wjoin(f))
3434 util.unlinkpath(repo.wjoin(f))
3434 except OSError:
3435 except OSError:
3435 pass
3436 pass
3436 repo.dirstate.remove(f)
3437 repo.dirstate.remove(f)
3437
3438
3438 normal = None
3439 normal = None
3439 if node == parent:
3440 if node == parent:
3440 # We're reverting to our parent. If possible, we'd like status
3441 # We're reverting to our parent. If possible, we'd like status
3441 # to report the file as clean. We have to use normallookup for
3442 # to report the file as clean. We have to use normallookup for
3442 # merges to avoid losing information about merged/dirty files.
3443 # merges to avoid losing information about merged/dirty files.
3443 if p2 != nullid:
3444 if p2 != nullid:
3444 normal = repo.dirstate.normallookup
3445 normal = repo.dirstate.normallookup
3445 else:
3446 else:
3446 normal = repo.dirstate.normal
3447 normal = repo.dirstate.normal
3447 for f in revert[0]:
3448 for f in revert[0]:
3448 checkout(f)
3449 checkout(f)
3449 if normal:
3450 if normal:
3450 normal(f)
3451 normal(f)
3451
3452
3452 for f in add[0]:
3453 for f in add[0]:
3453 checkout(f)
3454 checkout(f)
3454 repo.dirstate.add(f)
3455 repo.dirstate.add(f)
3455
3456
3456 normal = repo.dirstate.normallookup
3457 normal = repo.dirstate.normallookup
3457 if node == parent and p2 == nullid:
3458 if node == parent and p2 == nullid:
3458 normal = repo.dirstate.normal
3459 normal = repo.dirstate.normal
3459 for f in undelete[0]:
3460 for f in undelete[0]:
3460 checkout(f)
3461 checkout(f)
3461 normal(f)
3462 normal(f)
3462
3463
3463 finally:
3464 finally:
3464 wlock.release()
3465 wlock.release()
3465
3466
3466 def rollback(ui, repo, **opts):
3467 def rollback(ui, repo, **opts):
3467 """roll back the last transaction (dangerous)
3468 """roll back the last transaction (dangerous)
3468
3469
3469 This command should be used with care. There is only one level of
3470 This command should be used with care. There is only one level of
3470 rollback, and there is no way to undo a rollback. It will also
3471 rollback, and there is no way to undo a rollback. It will also
3471 restore the dirstate at the time of the last transaction, losing
3472 restore the dirstate at the time of the last transaction, losing
3472 any dirstate changes since that time. This command does not alter
3473 any dirstate changes since that time. This command does not alter
3473 the working directory.
3474 the working directory.
3474
3475
3475 Transactions are used to encapsulate the effects of all commands
3476 Transactions are used to encapsulate the effects of all commands
3476 that create new changesets or propagate existing changesets into a
3477 that create new changesets or propagate existing changesets into a
3477 repository. For example, the following commands are transactional,
3478 repository. For example, the following commands are transactional,
3478 and their effects can be rolled back:
3479 and their effects can be rolled back:
3479
3480
3480 - commit
3481 - commit
3481 - import
3482 - import
3482 - pull
3483 - pull
3483 - push (with this repository as the destination)
3484 - push (with this repository as the destination)
3484 - unbundle
3485 - unbundle
3485
3486
3486 This command is not intended for use on public repositories. Once
3487 This command is not intended for use on public repositories. Once
3487 changes are visible for pull by other users, rolling a transaction
3488 changes are visible for pull by other users, rolling a transaction
3488 back locally is ineffective (someone else may already have pulled
3489 back locally is ineffective (someone else may already have pulled
3489 the changes). Furthermore, a race is possible with readers of the
3490 the changes). Furthermore, a race is possible with readers of the
3490 repository; for example an in-progress pull from the repository
3491 repository; for example an in-progress pull from the repository
3491 may fail if a rollback is performed.
3492 may fail if a rollback is performed.
3492
3493
3493 Returns 0 on success, 1 if no rollback data is available.
3494 Returns 0 on success, 1 if no rollback data is available.
3494 """
3495 """
3495 return repo.rollback(opts.get('dry_run'))
3496 return repo.rollback(opts.get('dry_run'))
3496
3497
3497 def root(ui, repo):
3498 def root(ui, repo):
3498 """print the root (top) of the current working directory
3499 """print the root (top) of the current working directory
3499
3500
3500 Print the root directory of the current repository.
3501 Print the root directory of the current repository.
3501
3502
3502 Returns 0 on success.
3503 Returns 0 on success.
3503 """
3504 """
3504 ui.write(repo.root + "\n")
3505 ui.write(repo.root + "\n")
3505
3506
3506 def serve(ui, repo, **opts):
3507 def serve(ui, repo, **opts):
3507 """start stand-alone webserver
3508 """start stand-alone webserver
3508
3509
3509 Start a local HTTP repository browser and pull server. You can use
3510 Start a local HTTP repository browser and pull server. You can use
3510 this for ad-hoc sharing and browsing of repositories. It is
3511 this for ad-hoc sharing and browsing of repositories. It is
3511 recommended to use a real web server to serve a repository for
3512 recommended to use a real web server to serve a repository for
3512 longer periods of time.
3513 longer periods of time.
3513
3514
3514 Please note that the server does not implement access control.
3515 Please note that the server does not implement access control.
3515 This means that, by default, anybody can read from the server and
3516 This means that, by default, anybody can read from the server and
3516 nobody can write to it by default. Set the ``web.allow_push``
3517 nobody can write to it by default. Set the ``web.allow_push``
3517 option to ``*`` to allow everybody to push to the server. You
3518 option to ``*`` to allow everybody to push to the server. You
3518 should use a real web server if you need to authenticate users.
3519 should use a real web server if you need to authenticate users.
3519
3520
3520 By default, the server logs accesses to stdout and errors to
3521 By default, the server logs accesses to stdout and errors to
3521 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3522 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3522 files.
3523 files.
3523
3524
3524 To have the server choose a free port number to listen on, specify
3525 To have the server choose a free port number to listen on, specify
3525 a port number of 0; in this case, the server will print the port
3526 a port number of 0; in this case, the server will print the port
3526 number it uses.
3527 number it uses.
3527
3528
3528 Returns 0 on success.
3529 Returns 0 on success.
3529 """
3530 """
3530
3531
3531 if opts["stdio"]:
3532 if opts["stdio"]:
3532 if repo is None:
3533 if repo is None:
3533 raise error.RepoError(_("There is no Mercurial repository here"
3534 raise error.RepoError(_("There is no Mercurial repository here"
3534 " (.hg not found)"))
3535 " (.hg not found)"))
3535 s = sshserver.sshserver(ui, repo)
3536 s = sshserver.sshserver(ui, repo)
3536 s.serve_forever()
3537 s.serve_forever()
3537
3538
3538 # this way we can check if something was given in the command-line
3539 # this way we can check if something was given in the command-line
3539 if opts.get('port'):
3540 if opts.get('port'):
3540 opts['port'] = util.getport(opts.get('port'))
3541 opts['port'] = util.getport(opts.get('port'))
3541
3542
3542 baseui = repo and repo.baseui or ui
3543 baseui = repo and repo.baseui or ui
3543 optlist = ("name templates style address port prefix ipv6"
3544 optlist = ("name templates style address port prefix ipv6"
3544 " accesslog errorlog certificate encoding")
3545 " accesslog errorlog certificate encoding")
3545 for o in optlist.split():
3546 for o in optlist.split():
3546 val = opts.get(o, '')
3547 val = opts.get(o, '')
3547 if val in (None, ''): # should check against default options instead
3548 if val in (None, ''): # should check against default options instead
3548 continue
3549 continue
3549 baseui.setconfig("web", o, val)
3550 baseui.setconfig("web", o, val)
3550 if repo and repo.ui != baseui:
3551 if repo and repo.ui != baseui:
3551 repo.ui.setconfig("web", o, val)
3552 repo.ui.setconfig("web", o, val)
3552
3553
3553 o = opts.get('web_conf') or opts.get('webdir_conf')
3554 o = opts.get('web_conf') or opts.get('webdir_conf')
3554 if not o:
3555 if not o:
3555 if not repo:
3556 if not repo:
3556 raise error.RepoError(_("There is no Mercurial repository"
3557 raise error.RepoError(_("There is no Mercurial repository"
3557 " here (.hg not found)"))
3558 " here (.hg not found)"))
3558 o = repo.root
3559 o = repo.root
3559
3560
3560 app = hgweb.hgweb(o, baseui=ui)
3561 app = hgweb.hgweb(o, baseui=ui)
3561
3562
3562 class service(object):
3563 class service(object):
3563 def init(self):
3564 def init(self):
3564 util.set_signal_handler()
3565 util.set_signal_handler()
3565 self.httpd = hgweb.server.create_server(ui, app)
3566 self.httpd = hgweb.server.create_server(ui, app)
3566
3567
3567 if opts['port'] and not ui.verbose:
3568 if opts['port'] and not ui.verbose:
3568 return
3569 return
3569
3570
3570 if self.httpd.prefix:
3571 if self.httpd.prefix:
3571 prefix = self.httpd.prefix.strip('/') + '/'
3572 prefix = self.httpd.prefix.strip('/') + '/'
3572 else:
3573 else:
3573 prefix = ''
3574 prefix = ''
3574
3575
3575 port = ':%d' % self.httpd.port
3576 port = ':%d' % self.httpd.port
3576 if port == ':80':
3577 if port == ':80':
3577 port = ''
3578 port = ''
3578
3579
3579 bindaddr = self.httpd.addr
3580 bindaddr = self.httpd.addr
3580 if bindaddr == '0.0.0.0':
3581 if bindaddr == '0.0.0.0':
3581 bindaddr = '*'
3582 bindaddr = '*'
3582 elif ':' in bindaddr: # IPv6
3583 elif ':' in bindaddr: # IPv6
3583 bindaddr = '[%s]' % bindaddr
3584 bindaddr = '[%s]' % bindaddr
3584
3585
3585 fqaddr = self.httpd.fqaddr
3586 fqaddr = self.httpd.fqaddr
3586 if ':' in fqaddr:
3587 if ':' in fqaddr:
3587 fqaddr = '[%s]' % fqaddr
3588 fqaddr = '[%s]' % fqaddr
3588 if opts['port']:
3589 if opts['port']:
3589 write = ui.status
3590 write = ui.status
3590 else:
3591 else:
3591 write = ui.write
3592 write = ui.write
3592 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3593 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3593 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3594 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3594
3595
3595 def run(self):
3596 def run(self):
3596 self.httpd.serve_forever()
3597 self.httpd.serve_forever()
3597
3598
3598 service = service()
3599 service = service()
3599
3600
3600 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3601 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3601
3602
3602 def status(ui, repo, *pats, **opts):
3603 def status(ui, repo, *pats, **opts):
3603 """show changed files in the working directory
3604 """show changed files in the working directory
3604
3605
3605 Show status of files in the repository. If names are given, only
3606 Show status of files in the repository. If names are given, only
3606 files that match are shown. Files that are clean or ignored or
3607 files that match are shown. Files that are clean or ignored or
3607 the source of a copy/move operation, are not listed unless
3608 the source of a copy/move operation, are not listed unless
3608 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3609 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3609 Unless options described with "show only ..." are given, the
3610 Unless options described with "show only ..." are given, the
3610 options -mardu are used.
3611 options -mardu are used.
3611
3612
3612 Option -q/--quiet hides untracked (unknown and ignored) files
3613 Option -q/--quiet hides untracked (unknown and ignored) files
3613 unless explicitly requested with -u/--unknown or -i/--ignored.
3614 unless explicitly requested with -u/--unknown or -i/--ignored.
3614
3615
3615 .. note::
3616 .. note::
3616 status may appear to disagree with diff if permissions have
3617 status may appear to disagree with diff if permissions have
3617 changed or a merge has occurred. The standard diff format does
3618 changed or a merge has occurred. The standard diff format does
3618 not report permission changes and diff only reports changes
3619 not report permission changes and diff only reports changes
3619 relative to one merge parent.
3620 relative to one merge parent.
3620
3621
3621 If one revision is given, it is used as the base revision.
3622 If one revision is given, it is used as the base revision.
3622 If two revisions are given, the differences between them are
3623 If two revisions are given, the differences between them are
3623 shown. The --change option can also be used as a shortcut to list
3624 shown. The --change option can also be used as a shortcut to list
3624 the changed files of a revision from its first parent.
3625 the changed files of a revision from its first parent.
3625
3626
3626 The codes used to show the status of files are::
3627 The codes used to show the status of files are::
3627
3628
3628 M = modified
3629 M = modified
3629 A = added
3630 A = added
3630 R = removed
3631 R = removed
3631 C = clean
3632 C = clean
3632 ! = missing (deleted by non-hg command, but still tracked)
3633 ! = missing (deleted by non-hg command, but still tracked)
3633 ? = not tracked
3634 ? = not tracked
3634 I = ignored
3635 I = ignored
3635 = origin of the previous file listed as A (added)
3636 = origin of the previous file listed as A (added)
3636
3637
3637 Returns 0 on success.
3638 Returns 0 on success.
3638 """
3639 """
3639
3640
3640 revs = opts.get('rev')
3641 revs = opts.get('rev')
3641 change = opts.get('change')
3642 change = opts.get('change')
3642
3643
3643 if revs and change:
3644 if revs and change:
3644 msg = _('cannot specify --rev and --change at the same time')
3645 msg = _('cannot specify --rev and --change at the same time')
3645 raise util.Abort(msg)
3646 raise util.Abort(msg)
3646 elif change:
3647 elif change:
3647 node2 = repo.lookup(change)
3648 node2 = repo.lookup(change)
3648 node1 = repo[node2].parents()[0].node()
3649 node1 = repo[node2].parents()[0].node()
3649 else:
3650 else:
3650 node1, node2 = cmdutil.revpair(repo, revs)
3651 node1, node2 = cmdutil.revpair(repo, revs)
3651
3652
3652 cwd = (pats and repo.getcwd()) or ''
3653 cwd = (pats and repo.getcwd()) or ''
3653 end = opts.get('print0') and '\0' or '\n'
3654 end = opts.get('print0') and '\0' or '\n'
3654 copy = {}
3655 copy = {}
3655 states = 'modified added removed deleted unknown ignored clean'.split()
3656 states = 'modified added removed deleted unknown ignored clean'.split()
3656 show = [k for k in states if opts.get(k)]
3657 show = [k for k in states if opts.get(k)]
3657 if opts.get('all'):
3658 if opts.get('all'):
3658 show += ui.quiet and (states[:4] + ['clean']) or states
3659 show += ui.quiet and (states[:4] + ['clean']) or states
3659 if not show:
3660 if not show:
3660 show = ui.quiet and states[:4] or states[:5]
3661 show = ui.quiet and states[:4] or states[:5]
3661
3662
3662 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3663 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3663 'ignored' in show, 'clean' in show, 'unknown' in show,
3664 'ignored' in show, 'clean' in show, 'unknown' in show,
3664 opts.get('subrepos'))
3665 opts.get('subrepos'))
3665 changestates = zip(states, 'MAR!?IC', stat)
3666 changestates = zip(states, 'MAR!?IC', stat)
3666
3667
3667 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3668 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3668 ctxn = repo[nullid]
3669 ctxn = repo[nullid]
3669 ctx1 = repo[node1]
3670 ctx1 = repo[node1]
3670 ctx2 = repo[node2]
3671 ctx2 = repo[node2]
3671 added = stat[1]
3672 added = stat[1]
3672 if node2 is None:
3673 if node2 is None:
3673 added = stat[0] + stat[1] # merged?
3674 added = stat[0] + stat[1] # merged?
3674
3675
3675 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3676 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3676 if k in added:
3677 if k in added:
3677 copy[k] = v
3678 copy[k] = v
3678 elif v in added:
3679 elif v in added:
3679 copy[v] = k
3680 copy[v] = k
3680
3681
3681 for state, char, files in changestates:
3682 for state, char, files in changestates:
3682 if state in show:
3683 if state in show:
3683 format = "%s %%s%s" % (char, end)
3684 format = "%s %%s%s" % (char, end)
3684 if opts.get('no_status'):
3685 if opts.get('no_status'):
3685 format = "%%s%s" % end
3686 format = "%%s%s" % end
3686
3687
3687 for f in files:
3688 for f in files:
3688 ui.write(format % repo.pathto(f, cwd),
3689 ui.write(format % repo.pathto(f, cwd),
3689 label='status.' + state)
3690 label='status.' + state)
3690 if f in copy:
3691 if f in copy:
3691 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3692 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3692 label='status.copied')
3693 label='status.copied')
3693
3694
3694 def summary(ui, repo, **opts):
3695 def summary(ui, repo, **opts):
3695 """summarize working directory state
3696 """summarize working directory state
3696
3697
3697 This generates a brief summary of the working directory state,
3698 This generates a brief summary of the working directory state,
3698 including parents, branch, commit status, and available updates.
3699 including parents, branch, commit status, and available updates.
3699
3700
3700 With the --remote option, this will check the default paths for
3701 With the --remote option, this will check the default paths for
3701 incoming and outgoing changes. This can be time-consuming.
3702 incoming and outgoing changes. This can be time-consuming.
3702
3703
3703 Returns 0 on success.
3704 Returns 0 on success.
3704 """
3705 """
3705
3706
3706 ctx = repo[None]
3707 ctx = repo[None]
3707 parents = ctx.parents()
3708 parents = ctx.parents()
3708 pnode = parents[0].node()
3709 pnode = parents[0].node()
3709
3710
3710 for p in parents:
3711 for p in parents:
3711 # label with log.changeset (instead of log.parent) since this
3712 # label with log.changeset (instead of log.parent) since this
3712 # shows a working directory parent *changeset*:
3713 # shows a working directory parent *changeset*:
3713 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3714 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3714 label='log.changeset')
3715 label='log.changeset')
3715 ui.write(' '.join(p.tags()), label='log.tag')
3716 ui.write(' '.join(p.tags()), label='log.tag')
3716 if p.bookmarks():
3717 if p.bookmarks():
3717 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
3718 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
3718 if p.rev() == -1:
3719 if p.rev() == -1:
3719 if not len(repo):
3720 if not len(repo):
3720 ui.write(_(' (empty repository)'))
3721 ui.write(_(' (empty repository)'))
3721 else:
3722 else:
3722 ui.write(_(' (no revision checked out)'))
3723 ui.write(_(' (no revision checked out)'))
3723 ui.write('\n')
3724 ui.write('\n')
3724 if p.description():
3725 if p.description():
3725 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3726 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3726 label='log.summary')
3727 label='log.summary')
3727
3728
3728 branch = ctx.branch()
3729 branch = ctx.branch()
3729 bheads = repo.branchheads(branch)
3730 bheads = repo.branchheads(branch)
3730 m = _('branch: %s\n') % branch
3731 m = _('branch: %s\n') % branch
3731 if branch != 'default':
3732 if branch != 'default':
3732 ui.write(m, label='log.branch')
3733 ui.write(m, label='log.branch')
3733 else:
3734 else:
3734 ui.status(m, label='log.branch')
3735 ui.status(m, label='log.branch')
3735
3736
3736 st = list(repo.status(unknown=True))[:6]
3737 st = list(repo.status(unknown=True))[:6]
3737
3738
3738 c = repo.dirstate.copies()
3739 c = repo.dirstate.copies()
3739 copied, renamed = [], []
3740 copied, renamed = [], []
3740 for d, s in c.iteritems():
3741 for d, s in c.iteritems():
3741 if s in st[2]:
3742 if s in st[2]:
3742 st[2].remove(s)
3743 st[2].remove(s)
3743 renamed.append(d)
3744 renamed.append(d)
3744 else:
3745 else:
3745 copied.append(d)
3746 copied.append(d)
3746 if d in st[1]:
3747 if d in st[1]:
3747 st[1].remove(d)
3748 st[1].remove(d)
3748 st.insert(3, renamed)
3749 st.insert(3, renamed)
3749 st.insert(4, copied)
3750 st.insert(4, copied)
3750
3751
3751 ms = mergemod.mergestate(repo)
3752 ms = mergemod.mergestate(repo)
3752 st.append([f for f in ms if ms[f] == 'u'])
3753 st.append([f for f in ms if ms[f] == 'u'])
3753
3754
3754 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3755 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3755 st.append(subs)
3756 st.append(subs)
3756
3757
3757 labels = [ui.label(_('%d modified'), 'status.modified'),
3758 labels = [ui.label(_('%d modified'), 'status.modified'),
3758 ui.label(_('%d added'), 'status.added'),
3759 ui.label(_('%d added'), 'status.added'),
3759 ui.label(_('%d removed'), 'status.removed'),
3760 ui.label(_('%d removed'), 'status.removed'),
3760 ui.label(_('%d renamed'), 'status.copied'),
3761 ui.label(_('%d renamed'), 'status.copied'),
3761 ui.label(_('%d copied'), 'status.copied'),
3762 ui.label(_('%d copied'), 'status.copied'),
3762 ui.label(_('%d deleted'), 'status.deleted'),
3763 ui.label(_('%d deleted'), 'status.deleted'),
3763 ui.label(_('%d unknown'), 'status.unknown'),
3764 ui.label(_('%d unknown'), 'status.unknown'),
3764 ui.label(_('%d ignored'), 'status.ignored'),
3765 ui.label(_('%d ignored'), 'status.ignored'),
3765 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3766 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3766 ui.label(_('%d subrepos'), 'status.modified')]
3767 ui.label(_('%d subrepos'), 'status.modified')]
3767 t = []
3768 t = []
3768 for s, l in zip(st, labels):
3769 for s, l in zip(st, labels):
3769 if s:
3770 if s:
3770 t.append(l % len(s))
3771 t.append(l % len(s))
3771
3772
3772 t = ', '.join(t)
3773 t = ', '.join(t)
3773 cleanworkdir = False
3774 cleanworkdir = False
3774
3775
3775 if len(parents) > 1:
3776 if len(parents) > 1:
3776 t += _(' (merge)')
3777 t += _(' (merge)')
3777 elif branch != parents[0].branch():
3778 elif branch != parents[0].branch():
3778 t += _(' (new branch)')
3779 t += _(' (new branch)')
3779 elif (parents[0].extra().get('close') and
3780 elif (parents[0].extra().get('close') and
3780 pnode in repo.branchheads(branch, closed=True)):
3781 pnode in repo.branchheads(branch, closed=True)):
3781 t += _(' (head closed)')
3782 t += _(' (head closed)')
3782 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3783 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3783 t += _(' (clean)')
3784 t += _(' (clean)')
3784 cleanworkdir = True
3785 cleanworkdir = True
3785 elif pnode not in bheads:
3786 elif pnode not in bheads:
3786 t += _(' (new branch head)')
3787 t += _(' (new branch head)')
3787
3788
3788 if cleanworkdir:
3789 if cleanworkdir:
3789 ui.status(_('commit: %s\n') % t.strip())
3790 ui.status(_('commit: %s\n') % t.strip())
3790 else:
3791 else:
3791 ui.write(_('commit: %s\n') % t.strip())
3792 ui.write(_('commit: %s\n') % t.strip())
3792
3793
3793 # all ancestors of branch heads - all ancestors of parent = new csets
3794 # all ancestors of branch heads - all ancestors of parent = new csets
3794 new = [0] * len(repo)
3795 new = [0] * len(repo)
3795 cl = repo.changelog
3796 cl = repo.changelog
3796 for a in [cl.rev(n) for n in bheads]:
3797 for a in [cl.rev(n) for n in bheads]:
3797 new[a] = 1
3798 new[a] = 1
3798 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3799 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3799 new[a] = 1
3800 new[a] = 1
3800 for a in [p.rev() for p in parents]:
3801 for a in [p.rev() for p in parents]:
3801 if a >= 0:
3802 if a >= 0:
3802 new[a] = 0
3803 new[a] = 0
3803 for a in cl.ancestors(*[p.rev() for p in parents]):
3804 for a in cl.ancestors(*[p.rev() for p in parents]):
3804 new[a] = 0
3805 new[a] = 0
3805 new = sum(new)
3806 new = sum(new)
3806
3807
3807 if new == 0:
3808 if new == 0:
3808 ui.status(_('update: (current)\n'))
3809 ui.status(_('update: (current)\n'))
3809 elif pnode not in bheads:
3810 elif pnode not in bheads:
3810 ui.write(_('update: %d new changesets (update)\n') % new)
3811 ui.write(_('update: %d new changesets (update)\n') % new)
3811 else:
3812 else:
3812 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3813 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3813 (new, len(bheads)))
3814 (new, len(bheads)))
3814
3815
3815 if opts.get('remote'):
3816 if opts.get('remote'):
3816 t = []
3817 t = []
3817 source, branches = hg.parseurl(ui.expandpath('default'))
3818 source, branches = hg.parseurl(ui.expandpath('default'))
3818 other = hg.repository(hg.remoteui(repo, {}), source)
3819 other = hg.repository(hg.remoteui(repo, {}), source)
3819 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3820 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3820 ui.debug('comparing with %s\n' % url.hidepassword(source))
3821 ui.debug('comparing with %s\n' % url.hidepassword(source))
3821 repo.ui.pushbuffer()
3822 repo.ui.pushbuffer()
3822 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3823 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3823 repo.ui.popbuffer()
3824 repo.ui.popbuffer()
3824 if incoming:
3825 if incoming:
3825 t.append(_('1 or more incoming'))
3826 t.append(_('1 or more incoming'))
3826
3827
3827 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3828 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3828 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3829 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3829 other = hg.repository(hg.remoteui(repo, {}), dest)
3830 other = hg.repository(hg.remoteui(repo, {}), dest)
3830 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3831 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3831 repo.ui.pushbuffer()
3832 repo.ui.pushbuffer()
3832 o = discovery.findoutgoing(repo, other)
3833 o = discovery.findoutgoing(repo, other)
3833 repo.ui.popbuffer()
3834 repo.ui.popbuffer()
3834 o = repo.changelog.nodesbetween(o, None)[0]
3835 o = repo.changelog.nodesbetween(o, None)[0]
3835 if o:
3836 if o:
3836 t.append(_('%d outgoing') % len(o))
3837 t.append(_('%d outgoing') % len(o))
3837 if 'bookmarks' in other.listkeys('namespaces'):
3838 if 'bookmarks' in other.listkeys('namespaces'):
3838 lmarks = repo.listkeys('bookmarks')
3839 lmarks = repo.listkeys('bookmarks')
3839 rmarks = other.listkeys('bookmarks')
3840 rmarks = other.listkeys('bookmarks')
3840 diff = set(rmarks) - set(lmarks)
3841 diff = set(rmarks) - set(lmarks)
3841 if len(diff) > 0:
3842 if len(diff) > 0:
3842 t.append(_('%d incoming bookmarks') % len(diff))
3843 t.append(_('%d incoming bookmarks') % len(diff))
3843 diff = set(lmarks) - set(rmarks)
3844 diff = set(lmarks) - set(rmarks)
3844 if len(diff) > 0:
3845 if len(diff) > 0:
3845 t.append(_('%d outgoing bookmarks') % len(diff))
3846 t.append(_('%d outgoing bookmarks') % len(diff))
3846
3847
3847 if t:
3848 if t:
3848 ui.write(_('remote: %s\n') % (', '.join(t)))
3849 ui.write(_('remote: %s\n') % (', '.join(t)))
3849 else:
3850 else:
3850 ui.status(_('remote: (synced)\n'))
3851 ui.status(_('remote: (synced)\n'))
3851
3852
3852 def tag(ui, repo, name1, *names, **opts):
3853 def tag(ui, repo, name1, *names, **opts):
3853 """add one or more tags for the current or given revision
3854 """add one or more tags for the current or given revision
3854
3855
3855 Name a particular revision using <name>.
3856 Name a particular revision using <name>.
3856
3857
3857 Tags are used to name particular revisions of the repository and are
3858 Tags are used to name particular revisions of the repository and are
3858 very useful to compare different revisions, to go back to significant
3859 very useful to compare different revisions, to go back to significant
3859 earlier versions or to mark branch points as releases, etc. Changing
3860 earlier versions or to mark branch points as releases, etc. Changing
3860 an existing tag is normally disallowed; use -f/--force to override.
3861 an existing tag is normally disallowed; use -f/--force to override.
3861
3862
3862 If no revision is given, the parent of the working directory is
3863 If no revision is given, the parent of the working directory is
3863 used, or tip if no revision is checked out.
3864 used, or tip if no revision is checked out.
3864
3865
3865 To facilitate version control, distribution, and merging of tags,
3866 To facilitate version control, distribution, and merging of tags,
3866 they are stored as a file named ".hgtags" which is managed similarly
3867 they are stored as a file named ".hgtags" which is managed similarly
3867 to other project files and can be hand-edited if necessary. This
3868 to other project files and can be hand-edited if necessary. This
3868 also means that tagging creates a new commit. The file
3869 also means that tagging creates a new commit. The file
3869 ".hg/localtags" is used for local tags (not shared among
3870 ".hg/localtags" is used for local tags (not shared among
3870 repositories).
3871 repositories).
3871
3872
3872 Tag commits are usually made at the head of a branch. If the parent
3873 Tag commits are usually made at the head of a branch. If the parent
3873 of the working directory is not a branch head, :hg:`tag` aborts; use
3874 of the working directory is not a branch head, :hg:`tag` aborts; use
3874 -f/--force to force the tag commit to be based on a non-head
3875 -f/--force to force the tag commit to be based on a non-head
3875 changeset.
3876 changeset.
3876
3877
3877 See :hg:`help dates` for a list of formats valid for -d/--date.
3878 See :hg:`help dates` for a list of formats valid for -d/--date.
3878
3879
3879 Since tag names have priority over branch names during revision
3880 Since tag names have priority over branch names during revision
3880 lookup, using an existing branch name as a tag name is discouraged.
3881 lookup, using an existing branch name as a tag name is discouraged.
3881
3882
3882 Returns 0 on success.
3883 Returns 0 on success.
3883 """
3884 """
3884
3885
3885 rev_ = "."
3886 rev_ = "."
3886 names = [t.strip() for t in (name1,) + names]
3887 names = [t.strip() for t in (name1,) + names]
3887 if len(names) != len(set(names)):
3888 if len(names) != len(set(names)):
3888 raise util.Abort(_('tag names must be unique'))
3889 raise util.Abort(_('tag names must be unique'))
3889 for n in names:
3890 for n in names:
3890 if n in ['tip', '.', 'null']:
3891 if n in ['tip', '.', 'null']:
3891 raise util.Abort(_('the name \'%s\' is reserved') % n)
3892 raise util.Abort(_('the name \'%s\' is reserved') % n)
3892 if not n:
3893 if not n:
3893 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3894 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3894 if opts.get('rev') and opts.get('remove'):
3895 if opts.get('rev') and opts.get('remove'):
3895 raise util.Abort(_("--rev and --remove are incompatible"))
3896 raise util.Abort(_("--rev and --remove are incompatible"))
3896 if opts.get('rev'):
3897 if opts.get('rev'):
3897 rev_ = opts['rev']
3898 rev_ = opts['rev']
3898 message = opts.get('message')
3899 message = opts.get('message')
3899 if opts.get('remove'):
3900 if opts.get('remove'):
3900 expectedtype = opts.get('local') and 'local' or 'global'
3901 expectedtype = opts.get('local') and 'local' or 'global'
3901 for n in names:
3902 for n in names:
3902 if not repo.tagtype(n):
3903 if not repo.tagtype(n):
3903 raise util.Abort(_('tag \'%s\' does not exist') % n)
3904 raise util.Abort(_('tag \'%s\' does not exist') % n)
3904 if repo.tagtype(n) != expectedtype:
3905 if repo.tagtype(n) != expectedtype:
3905 if expectedtype == 'global':
3906 if expectedtype == 'global':
3906 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3907 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3907 else:
3908 else:
3908 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3909 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3909 rev_ = nullid
3910 rev_ = nullid
3910 if not message:
3911 if not message:
3911 # we don't translate commit messages
3912 # we don't translate commit messages
3912 message = 'Removed tag %s' % ', '.join(names)
3913 message = 'Removed tag %s' % ', '.join(names)
3913 elif not opts.get('force'):
3914 elif not opts.get('force'):
3914 for n in names:
3915 for n in names:
3915 if n in repo.tags():
3916 if n in repo.tags():
3916 raise util.Abort(_('tag \'%s\' already exists '
3917 raise util.Abort(_('tag \'%s\' already exists '
3917 '(use -f to force)') % n)
3918 '(use -f to force)') % n)
3918 if not opts.get('local'):
3919 if not opts.get('local'):
3919 p1, p2 = repo.dirstate.parents()
3920 p1, p2 = repo.dirstate.parents()
3920 if p2 != nullid:
3921 if p2 != nullid:
3921 raise util.Abort(_('uncommitted merge'))
3922 raise util.Abort(_('uncommitted merge'))
3922 bheads = repo.branchheads()
3923 bheads = repo.branchheads()
3923 if not opts.get('force') and bheads and p1 not in bheads:
3924 if not opts.get('force') and bheads and p1 not in bheads:
3924 raise util.Abort(_('not at a branch head (use -f to force)'))
3925 raise util.Abort(_('not at a branch head (use -f to force)'))
3925 r = cmdutil.revsingle(repo, rev_).node()
3926 r = cmdutil.revsingle(repo, rev_).node()
3926
3927
3927 if not message:
3928 if not message:
3928 # we don't translate commit messages
3929 # we don't translate commit messages
3929 message = ('Added tag %s for changeset %s' %
3930 message = ('Added tag %s for changeset %s' %
3930 (', '.join(names), short(r)))
3931 (', '.join(names), short(r)))
3931
3932
3932 date = opts.get('date')
3933 date = opts.get('date')
3933 if date:
3934 if date:
3934 date = util.parsedate(date)
3935 date = util.parsedate(date)
3935
3936
3936 if opts.get('edit'):
3937 if opts.get('edit'):
3937 message = ui.edit(message, ui.username())
3938 message = ui.edit(message, ui.username())
3938
3939
3939 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3940 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3940
3941
3941 def tags(ui, repo):
3942 def tags(ui, repo):
3942 """list repository tags
3943 """list repository tags
3943
3944
3944 This lists both regular and local tags. When the -v/--verbose
3945 This lists both regular and local tags. When the -v/--verbose
3945 switch is used, a third column "local" is printed for local tags.
3946 switch is used, a third column "local" is printed for local tags.
3946
3947
3947 Returns 0 on success.
3948 Returns 0 on success.
3948 """
3949 """
3949
3950
3950 hexfunc = ui.debugflag and hex or short
3951 hexfunc = ui.debugflag and hex or short
3951 tagtype = ""
3952 tagtype = ""
3952
3953
3953 for t, n in reversed(repo.tagslist()):
3954 for t, n in reversed(repo.tagslist()):
3954 if ui.quiet:
3955 if ui.quiet:
3955 ui.write("%s\n" % t)
3956 ui.write("%s\n" % t)
3956 continue
3957 continue
3957
3958
3958 try:
3959 try:
3959 hn = hexfunc(n)
3960 hn = hexfunc(n)
3960 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3961 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3961 except error.LookupError:
3962 except error.LookupError:
3962 r = " ?:%s" % hn
3963 r = " ?:%s" % hn
3963 else:
3964 else:
3964 spaces = " " * (30 - encoding.colwidth(t))
3965 spaces = " " * (30 - encoding.colwidth(t))
3965 if ui.verbose:
3966 if ui.verbose:
3966 if repo.tagtype(t) == 'local':
3967 if repo.tagtype(t) == 'local':
3967 tagtype = " local"
3968 tagtype = " local"
3968 else:
3969 else:
3969 tagtype = ""
3970 tagtype = ""
3970 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3971 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3971
3972
3972 def tip(ui, repo, **opts):
3973 def tip(ui, repo, **opts):
3973 """show the tip revision
3974 """show the tip revision
3974
3975
3975 The tip revision (usually just called the tip) is the changeset
3976 The tip revision (usually just called the tip) is the changeset
3976 most recently added to the repository (and therefore the most
3977 most recently added to the repository (and therefore the most
3977 recently changed head).
3978 recently changed head).
3978
3979
3979 If you have just made a commit, that commit will be the tip. If
3980 If you have just made a commit, that commit will be the tip. If
3980 you have just pulled changes from another repository, the tip of
3981 you have just pulled changes from another repository, the tip of
3981 that repository becomes the current tip. The "tip" tag is special
3982 that repository becomes the current tip. The "tip" tag is special
3982 and cannot be renamed or assigned to a different changeset.
3983 and cannot be renamed or assigned to a different changeset.
3983
3984
3984 Returns 0 on success.
3985 Returns 0 on success.
3985 """
3986 """
3986 displayer = cmdutil.show_changeset(ui, repo, opts)
3987 displayer = cmdutil.show_changeset(ui, repo, opts)
3987 displayer.show(repo[len(repo) - 1])
3988 displayer.show(repo[len(repo) - 1])
3988 displayer.close()
3989 displayer.close()
3989
3990
3990 def unbundle(ui, repo, fname1, *fnames, **opts):
3991 def unbundle(ui, repo, fname1, *fnames, **opts):
3991 """apply one or more changegroup files
3992 """apply one or more changegroup files
3992
3993
3993 Apply one or more compressed changegroup files generated by the
3994 Apply one or more compressed changegroup files generated by the
3994 bundle command.
3995 bundle command.
3995
3996
3996 Returns 0 on success, 1 if an update has unresolved files.
3997 Returns 0 on success, 1 if an update has unresolved files.
3997 """
3998 """
3998 fnames = (fname1,) + fnames
3999 fnames = (fname1,) + fnames
3999
4000
4000 lock = repo.lock()
4001 lock = repo.lock()
4001 try:
4002 try:
4002 for fname in fnames:
4003 for fname in fnames:
4003 f = url.open(ui, fname)
4004 f = url.open(ui, fname)
4004 gen = changegroup.readbundle(f, fname)
4005 gen = changegroup.readbundle(f, fname)
4005 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
4006 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
4006 lock=lock)
4007 lock=lock)
4007 finally:
4008 finally:
4008 lock.release()
4009 lock.release()
4009
4010
4010 return postincoming(ui, repo, modheads, opts.get('update'), None)
4011 return postincoming(ui, repo, modheads, opts.get('update'), None)
4011
4012
4012 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
4013 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
4013 """update working directory (or switch revisions)
4014 """update working directory (or switch revisions)
4014
4015
4015 Update the repository's working directory to the specified
4016 Update the repository's working directory to the specified
4016 changeset. If no changeset is specified, update to the tip of the
4017 changeset. If no changeset is specified, update to the tip of the
4017 current named branch.
4018 current named branch.
4018
4019
4019 If the changeset is not a descendant of the working directory's
4020 If the changeset is not a descendant of the working directory's
4020 parent, the update is aborted. With the -c/--check option, the
4021 parent, the update is aborted. With the -c/--check option, the
4021 working directory is checked for uncommitted changes; if none are
4022 working directory is checked for uncommitted changes; if none are
4022 found, the working directory is updated to the specified
4023 found, the working directory is updated to the specified
4023 changeset.
4024 changeset.
4024
4025
4025 The following rules apply when the working directory contains
4026 The following rules apply when the working directory contains
4026 uncommitted changes:
4027 uncommitted changes:
4027
4028
4028 1. If neither -c/--check nor -C/--clean is specified, and if
4029 1. If neither -c/--check nor -C/--clean is specified, and if
4029 the requested changeset is an ancestor or descendant of
4030 the requested changeset is an ancestor or descendant of
4030 the working directory's parent, the uncommitted changes
4031 the working directory's parent, the uncommitted changes
4031 are merged into the requested changeset and the merged
4032 are merged into the requested changeset and the merged
4032 result is left uncommitted. If the requested changeset is
4033 result is left uncommitted. If the requested changeset is
4033 not an ancestor or descendant (that is, it is on another
4034 not an ancestor or descendant (that is, it is on another
4034 branch), the update is aborted and the uncommitted changes
4035 branch), the update is aborted and the uncommitted changes
4035 are preserved.
4036 are preserved.
4036
4037
4037 2. With the -c/--check option, the update is aborted and the
4038 2. With the -c/--check option, the update is aborted and the
4038 uncommitted changes are preserved.
4039 uncommitted changes are preserved.
4039
4040
4040 3. With the -C/--clean option, uncommitted changes are discarded and
4041 3. With the -C/--clean option, uncommitted changes are discarded and
4041 the working directory is updated to the requested changeset.
4042 the working directory is updated to the requested changeset.
4042
4043
4043 Use null as the changeset to remove the working directory (like
4044 Use null as the changeset to remove the working directory (like
4044 :hg:`clone -U`).
4045 :hg:`clone -U`).
4045
4046
4046 If you want to update just one file to an older changeset, use
4047 If you want to update just one file to an older changeset, use
4047 :hg:`revert`.
4048 :hg:`revert`.
4048
4049
4049 See :hg:`help dates` for a list of formats valid for -d/--date.
4050 See :hg:`help dates` for a list of formats valid for -d/--date.
4050
4051
4051 Returns 0 on success, 1 if there are unresolved files.
4052 Returns 0 on success, 1 if there are unresolved files.
4052 """
4053 """
4053 if rev and node:
4054 if rev and node:
4054 raise util.Abort(_("please specify just one revision"))
4055 raise util.Abort(_("please specify just one revision"))
4055
4056
4056 if rev is None or rev == '':
4057 if rev is None or rev == '':
4057 rev = node
4058 rev = node
4058
4059
4059 # if we defined a bookmark, we have to remember the original bookmark name
4060 # if we defined a bookmark, we have to remember the original bookmark name
4060 brev = rev
4061 brev = rev
4061 rev = cmdutil.revsingle(repo, rev, rev).rev()
4062 rev = cmdutil.revsingle(repo, rev, rev).rev()
4062
4063
4063 if check and clean:
4064 if check and clean:
4064 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4065 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4065
4066
4066 if check:
4067 if check:
4067 # we could use dirty() but we can ignore merge and branch trivia
4068 # we could use dirty() but we can ignore merge and branch trivia
4068 c = repo[None]
4069 c = repo[None]
4069 if c.modified() or c.added() or c.removed():
4070 if c.modified() or c.added() or c.removed():
4070 raise util.Abort(_("uncommitted local changes"))
4071 raise util.Abort(_("uncommitted local changes"))
4071
4072
4072 if date:
4073 if date:
4073 if rev:
4074 if rev:
4074 raise util.Abort(_("you can't specify a revision and a date"))
4075 raise util.Abort(_("you can't specify a revision and a date"))
4075 rev = cmdutil.finddate(ui, repo, date)
4076 rev = cmdutil.finddate(ui, repo, date)
4076
4077
4077 if clean or check:
4078 if clean or check:
4078 ret = hg.clean(repo, rev)
4079 ret = hg.clean(repo, rev)
4079 else:
4080 else:
4080 ret = hg.update(repo, rev)
4081 ret = hg.update(repo, rev)
4081
4082
4082 if brev in repo._bookmarks:
4083 if brev in repo._bookmarks:
4083 bookmarks.setcurrent(repo, brev)
4084 bookmarks.setcurrent(repo, brev)
4084
4085
4085 return ret
4086 return ret
4086
4087
4087 def verify(ui, repo):
4088 def verify(ui, repo):
4088 """verify the integrity of the repository
4089 """verify the integrity of the repository
4089
4090
4090 Verify the integrity of the current repository.
4091 Verify the integrity of the current repository.
4091
4092
4092 This will perform an extensive check of the repository's
4093 This will perform an extensive check of the repository's
4093 integrity, validating the hashes and checksums of each entry in
4094 integrity, validating the hashes and checksums of each entry in
4094 the changelog, manifest, and tracked files, as well as the
4095 the changelog, manifest, and tracked files, as well as the
4095 integrity of their crosslinks and indices.
4096 integrity of their crosslinks and indices.
4096
4097
4097 Returns 0 on success, 1 if errors are encountered.
4098 Returns 0 on success, 1 if errors are encountered.
4098 """
4099 """
4099 return hg.verify(repo)
4100 return hg.verify(repo)
4100
4101
4101 def version_(ui):
4102 def version_(ui):
4102 """output version and copyright information"""
4103 """output version and copyright information"""
4103 ui.write(_("Mercurial Distributed SCM (version %s)\n")
4104 ui.write(_("Mercurial Distributed SCM (version %s)\n")
4104 % util.version())
4105 % util.version())
4105 ui.status(_(
4106 ui.status(_(
4106 "(see http://mercurial.selenic.com for more information)\n"
4107 "(see http://mercurial.selenic.com for more information)\n"
4107 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
4108 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
4108 "This is free software; see the source for copying conditions. "
4109 "This is free software; see the source for copying conditions. "
4109 "There is NO\nwarranty; "
4110 "There is NO\nwarranty; "
4110 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
4111 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
4111 ))
4112 ))
4112
4113
4113 # Command options and aliases are listed here, alphabetically
4114 # Command options and aliases are listed here, alphabetically
4114
4115
4115 globalopts = [
4116 globalopts = [
4116 ('R', 'repository', '',
4117 ('R', 'repository', '',
4117 _('repository root directory or name of overlay bundle file'),
4118 _('repository root directory or name of overlay bundle file'),
4118 _('REPO')),
4119 _('REPO')),
4119 ('', 'cwd', '',
4120 ('', 'cwd', '',
4120 _('change working directory'), _('DIR')),
4121 _('change working directory'), _('DIR')),
4121 ('y', 'noninteractive', None,
4122 ('y', 'noninteractive', None,
4122 _('do not prompt, assume \'yes\' for any required answers')),
4123 _('do not prompt, assume \'yes\' for any required answers')),
4123 ('q', 'quiet', None, _('suppress output')),
4124 ('q', 'quiet', None, _('suppress output')),
4124 ('v', 'verbose', None, _('enable additional output')),
4125 ('v', 'verbose', None, _('enable additional output')),
4125 ('', 'config', [],
4126 ('', 'config', [],
4126 _('set/override config option (use \'section.name=value\')'),
4127 _('set/override config option (use \'section.name=value\')'),
4127 _('CONFIG')),
4128 _('CONFIG')),
4128 ('', 'debug', None, _('enable debugging output')),
4129 ('', 'debug', None, _('enable debugging output')),
4129 ('', 'debugger', None, _('start debugger')),
4130 ('', 'debugger', None, _('start debugger')),
4130 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
4131 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
4131 _('ENCODE')),
4132 _('ENCODE')),
4132 ('', 'encodingmode', encoding.encodingmode,
4133 ('', 'encodingmode', encoding.encodingmode,
4133 _('set the charset encoding mode'), _('MODE')),
4134 _('set the charset encoding mode'), _('MODE')),
4134 ('', 'traceback', None, _('always print a traceback on exception')),
4135 ('', 'traceback', None, _('always print a traceback on exception')),
4135 ('', 'time', None, _('time how long the command takes')),
4136 ('', 'time', None, _('time how long the command takes')),
4136 ('', 'profile', None, _('print command execution profile')),
4137 ('', 'profile', None, _('print command execution profile')),
4137 ('', 'version', None, _('output version information and exit')),
4138 ('', 'version', None, _('output version information and exit')),
4138 ('h', 'help', None, _('display help and exit')),
4139 ('h', 'help', None, _('display help and exit')),
4139 ]
4140 ]
4140
4141
4141 dryrunopts = [('n', 'dry-run', None,
4142 dryrunopts = [('n', 'dry-run', None,
4142 _('do not perform actions, just print output'))]
4143 _('do not perform actions, just print output'))]
4143
4144
4144 remoteopts = [
4145 remoteopts = [
4145 ('e', 'ssh', '',
4146 ('e', 'ssh', '',
4146 _('specify ssh command to use'), _('CMD')),
4147 _('specify ssh command to use'), _('CMD')),
4147 ('', 'remotecmd', '',
4148 ('', 'remotecmd', '',
4148 _('specify hg command to run on the remote side'), _('CMD')),
4149 _('specify hg command to run on the remote side'), _('CMD')),
4149 ('', 'insecure', None,
4150 ('', 'insecure', None,
4150 _('do not verify server certificate (ignoring web.cacerts config)')),
4151 _('do not verify server certificate (ignoring web.cacerts config)')),
4151 ]
4152 ]
4152
4153
4153 walkopts = [
4154 walkopts = [
4154 ('I', 'include', [],
4155 ('I', 'include', [],
4155 _('include names matching the given patterns'), _('PATTERN')),
4156 _('include names matching the given patterns'), _('PATTERN')),
4156 ('X', 'exclude', [],
4157 ('X', 'exclude', [],
4157 _('exclude names matching the given patterns'), _('PATTERN')),
4158 _('exclude names matching the given patterns'), _('PATTERN')),
4158 ]
4159 ]
4159
4160
4160 commitopts = [
4161 commitopts = [
4161 ('m', 'message', '',
4162 ('m', 'message', '',
4162 _('use text as commit message'), _('TEXT')),
4163 _('use text as commit message'), _('TEXT')),
4163 ('l', 'logfile', '',
4164 ('l', 'logfile', '',
4164 _('read commit message from file'), _('FILE')),
4165 _('read commit message from file'), _('FILE')),
4165 ]
4166 ]
4166
4167
4167 commitopts2 = [
4168 commitopts2 = [
4168 ('d', 'date', '',
4169 ('d', 'date', '',
4169 _('record datecode as commit date'), _('DATE')),
4170 _('record datecode as commit date'), _('DATE')),
4170 ('u', 'user', '',
4171 ('u', 'user', '',
4171 _('record the specified user as committer'), _('USER')),
4172 _('record the specified user as committer'), _('USER')),
4172 ]
4173 ]
4173
4174
4174 templateopts = [
4175 templateopts = [
4175 ('', 'style', '',
4176 ('', 'style', '',
4176 _('display using template map file'), _('STYLE')),
4177 _('display using template map file'), _('STYLE')),
4177 ('', 'template', '',
4178 ('', 'template', '',
4178 _('display with template'), _('TEMPLATE')),
4179 _('display with template'), _('TEMPLATE')),
4179 ]
4180 ]
4180
4181
4181 logopts = [
4182 logopts = [
4182 ('p', 'patch', None, _('show patch')),
4183 ('p', 'patch', None, _('show patch')),
4183 ('g', 'git', None, _('use git extended diff format')),
4184 ('g', 'git', None, _('use git extended diff format')),
4184 ('l', 'limit', '',
4185 ('l', 'limit', '',
4185 _('limit number of changes displayed'), _('NUM')),
4186 _('limit number of changes displayed'), _('NUM')),
4186 ('M', 'no-merges', None, _('do not show merges')),
4187 ('M', 'no-merges', None, _('do not show merges')),
4187 ('', 'stat', None, _('output diffstat-style summary of changes')),
4188 ('', 'stat', None, _('output diffstat-style summary of changes')),
4188 ] + templateopts
4189 ] + templateopts
4189
4190
4190 diffopts = [
4191 diffopts = [
4191 ('a', 'text', None, _('treat all files as text')),
4192 ('a', 'text', None, _('treat all files as text')),
4192 ('g', 'git', None, _('use git extended diff format')),
4193 ('g', 'git', None, _('use git extended diff format')),
4193 ('', 'nodates', None, _('omit dates from diff headers'))
4194 ('', 'nodates', None, _('omit dates from diff headers'))
4194 ]
4195 ]
4195
4196
4196 diffopts2 = [
4197 diffopts2 = [
4197 ('p', 'show-function', None, _('show which function each change is in')),
4198 ('p', 'show-function', None, _('show which function each change is in')),
4198 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4199 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4199 ('w', 'ignore-all-space', None,
4200 ('w', 'ignore-all-space', None,
4200 _('ignore white space when comparing lines')),
4201 _('ignore white space when comparing lines')),
4201 ('b', 'ignore-space-change', None,
4202 ('b', 'ignore-space-change', None,
4202 _('ignore changes in the amount of white space')),
4203 _('ignore changes in the amount of white space')),
4203 ('B', 'ignore-blank-lines', None,
4204 ('B', 'ignore-blank-lines', None,
4204 _('ignore changes whose lines are all blank')),
4205 _('ignore changes whose lines are all blank')),
4205 ('U', 'unified', '',
4206 ('U', 'unified', '',
4206 _('number of lines of context to show'), _('NUM')),
4207 _('number of lines of context to show'), _('NUM')),
4207 ('', 'stat', None, _('output diffstat-style summary of changes')),
4208 ('', 'stat', None, _('output diffstat-style summary of changes')),
4208 ]
4209 ]
4209
4210
4210 similarityopts = [
4211 similarityopts = [
4211 ('s', 'similarity', '',
4212 ('s', 'similarity', '',
4212 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4213 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4213 ]
4214 ]
4214
4215
4215 subrepoopts = [
4216 subrepoopts = [
4216 ('S', 'subrepos', None,
4217 ('S', 'subrepos', None,
4217 _('recurse into subrepositories'))
4218 _('recurse into subrepositories'))
4218 ]
4219 ]
4219
4220
4220 table = {
4221 table = {
4221 "^add": (add, walkopts + subrepoopts + dryrunopts,
4222 "^add": (add, walkopts + subrepoopts + dryrunopts,
4222 _('[OPTION]... [FILE]...')),
4223 _('[OPTION]... [FILE]...')),
4223 "addremove":
4224 "addremove":
4224 (addremove, similarityopts + walkopts + dryrunopts,
4225 (addremove, similarityopts + walkopts + dryrunopts,
4225 _('[OPTION]... [FILE]...')),
4226 _('[OPTION]... [FILE]...')),
4226 "^annotate|blame":
4227 "^annotate|blame":
4227 (annotate,
4228 (annotate,
4228 [('r', 'rev', '',
4229 [('r', 'rev', '',
4229 _('annotate the specified revision'), _('REV')),
4230 _('annotate the specified revision'), _('REV')),
4230 ('', 'follow', None,
4231 ('', 'follow', None,
4231 _('follow copies/renames and list the filename (DEPRECATED)')),
4232 _('follow copies/renames and list the filename (DEPRECATED)')),
4232 ('', 'no-follow', None, _("don't follow copies and renames")),
4233 ('', 'no-follow', None, _("don't follow copies and renames")),
4233 ('a', 'text', None, _('treat all files as text')),
4234 ('a', 'text', None, _('treat all files as text')),
4234 ('u', 'user', None, _('list the author (long with -v)')),
4235 ('u', 'user', None, _('list the author (long with -v)')),
4235 ('f', 'file', None, _('list the filename')),
4236 ('f', 'file', None, _('list the filename')),
4236 ('d', 'date', None, _('list the date (short with -q)')),
4237 ('d', 'date', None, _('list the date (short with -q)')),
4237 ('n', 'number', None, _('list the revision number (default)')),
4238 ('n', 'number', None, _('list the revision number (default)')),
4238 ('c', 'changeset', None, _('list the changeset')),
4239 ('c', 'changeset', None, _('list the changeset')),
4239 ('l', 'line-number', None,
4240 ('l', 'line-number', None,
4240 _('show line number at the first appearance'))
4241 _('show line number at the first appearance'))
4241 ] + walkopts,
4242 ] + walkopts,
4242 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4243 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4243 "archive":
4244 "archive":
4244 (archive,
4245 (archive,
4245 [('', 'no-decode', None, _('do not pass files through decoders')),
4246 [('', 'no-decode', None, _('do not pass files through decoders')),
4246 ('p', 'prefix', '',
4247 ('p', 'prefix', '',
4247 _('directory prefix for files in archive'), _('PREFIX')),
4248 _('directory prefix for files in archive'), _('PREFIX')),
4248 ('r', 'rev', '',
4249 ('r', 'rev', '',
4249 _('revision to distribute'), _('REV')),
4250 _('revision to distribute'), _('REV')),
4250 ('t', 'type', '',
4251 ('t', 'type', '',
4251 _('type of distribution to create'), _('TYPE')),
4252 _('type of distribution to create'), _('TYPE')),
4252 ] + subrepoopts + walkopts,
4253 ] + subrepoopts + walkopts,
4253 _('[OPTION]... DEST')),
4254 _('[OPTION]... DEST')),
4254 "backout":
4255 "backout":
4255 (backout,
4256 (backout,
4256 [('', 'merge', None,
4257 [('', 'merge', None,
4257 _('merge with old dirstate parent after backout')),
4258 _('merge with old dirstate parent after backout')),
4258 ('', 'parent', '',
4259 ('', 'parent', '',
4259 _('parent to choose when backing out merge'), _('REV')),
4260 _('parent to choose when backing out merge'), _('REV')),
4260 ('t', 'tool', '',
4261 ('t', 'tool', '',
4261 _('specify merge tool')),
4262 _('specify merge tool')),
4262 ('r', 'rev', '',
4263 ('r', 'rev', '',
4263 _('revision to backout'), _('REV')),
4264 _('revision to backout'), _('REV')),
4264 ] + walkopts + commitopts + commitopts2,
4265 ] + walkopts + commitopts + commitopts2,
4265 _('[OPTION]... [-r] REV')),
4266 _('[OPTION]... [-r] REV')),
4266 "bisect":
4267 "bisect":
4267 (bisect,
4268 (bisect,
4268 [('r', 'reset', False, _('reset bisect state')),
4269 [('r', 'reset', False, _('reset bisect state')),
4269 ('g', 'good', False, _('mark changeset good')),
4270 ('g', 'good', False, _('mark changeset good')),
4270 ('b', 'bad', False, _('mark changeset bad')),
4271 ('b', 'bad', False, _('mark changeset bad')),
4271 ('s', 'skip', False, _('skip testing changeset')),
4272 ('s', 'skip', False, _('skip testing changeset')),
4272 ('c', 'command', '',
4273 ('c', 'command', '',
4273 _('use command to check changeset state'), _('CMD')),
4274 _('use command to check changeset state'), _('CMD')),
4274 ('U', 'noupdate', False, _('do not update to target'))],
4275 ('U', 'noupdate', False, _('do not update to target'))],
4275 _("[-gbsr] [-U] [-c CMD] [REV]")),
4276 _("[-gbsr] [-U] [-c CMD] [REV]")),
4276 "bookmarks":
4277 "bookmarks":
4277 (bookmark,
4278 (bookmark,
4278 [('f', 'force', False, _('force')),
4279 [('f', 'force', False, _('force')),
4279 ('r', 'rev', '', _('revision'), _('REV')),
4280 ('r', 'rev', '', _('revision'), _('REV')),
4280 ('d', 'delete', False, _('delete a given bookmark')),
4281 ('d', 'delete', False, _('delete a given bookmark')),
4281 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
4282 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
4282 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
4283 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
4283 "branch":
4284 "branch":
4284 (branch,
4285 (branch,
4285 [('f', 'force', None,
4286 [('f', 'force', None,
4286 _('set branch name even if it shadows an existing branch')),
4287 _('set branch name even if it shadows an existing branch')),
4287 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4288 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4288 _('[-fC] [NAME]')),
4289 _('[-fC] [NAME]')),
4289 "branches":
4290 "branches":
4290 (branches,
4291 (branches,
4291 [('a', 'active', False,
4292 [('a', 'active', False,
4292 _('show only branches that have unmerged heads')),
4293 _('show only branches that have unmerged heads')),
4293 ('c', 'closed', False,
4294 ('c', 'closed', False,
4294 _('show normal and closed branches'))],
4295 _('show normal and closed branches'))],
4295 _('[-ac]')),
4296 _('[-ac]')),
4296 "bundle":
4297 "bundle":
4297 (bundle,
4298 (bundle,
4298 [('f', 'force', None,
4299 [('f', 'force', None,
4299 _('run even when the destination is unrelated')),
4300 _('run even when the destination is unrelated')),
4300 ('r', 'rev', [],
4301 ('r', 'rev', [],
4301 _('a changeset intended to be added to the destination'),
4302 _('a changeset intended to be added to the destination'),
4302 _('REV')),
4303 _('REV')),
4303 ('b', 'branch', [],
4304 ('b', 'branch', [],
4304 _('a specific branch you would like to bundle'),
4305 _('a specific branch you would like to bundle'),
4305 _('BRANCH')),
4306 _('BRANCH')),
4306 ('', 'base', [],
4307 ('', 'base', [],
4307 _('a base changeset assumed to be available at the destination'),
4308 _('a base changeset assumed to be available at the destination'),
4308 _('REV')),
4309 _('REV')),
4309 ('a', 'all', None, _('bundle all changesets in the repository')),
4310 ('a', 'all', None, _('bundle all changesets in the repository')),
4310 ('t', 'type', 'bzip2',
4311 ('t', 'type', 'bzip2',
4311 _('bundle compression type to use'), _('TYPE')),
4312 _('bundle compression type to use'), _('TYPE')),
4312 ] + remoteopts,
4313 ] + remoteopts,
4313 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4314 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4314 "cat":
4315 "cat":
4315 (cat,
4316 (cat,
4316 [('o', 'output', '',
4317 [('o', 'output', '',
4317 _('print output to file with formatted name'), _('FORMAT')),
4318 _('print output to file with formatted name'), _('FORMAT')),
4318 ('r', 'rev', '',
4319 ('r', 'rev', '',
4319 _('print the given revision'), _('REV')),
4320 _('print the given revision'), _('REV')),
4320 ('', 'decode', None, _('apply any matching decode filter')),
4321 ('', 'decode', None, _('apply any matching decode filter')),
4321 ] + walkopts,
4322 ] + walkopts,
4322 _('[OPTION]... FILE...')),
4323 _('[OPTION]... FILE...')),
4323 "^clone":
4324 "^clone":
4324 (clone,
4325 (clone,
4325 [('U', 'noupdate', None,
4326 [('U', 'noupdate', None,
4326 _('the clone will include an empty working copy (only a repository)')),
4327 _('the clone will include an empty working copy (only a repository)')),
4327 ('u', 'updaterev', '',
4328 ('u', 'updaterev', '',
4328 _('revision, tag or branch to check out'), _('REV')),
4329 _('revision, tag or branch to check out'), _('REV')),
4329 ('r', 'rev', [],
4330 ('r', 'rev', [],
4330 _('include the specified changeset'), _('REV')),
4331 _('include the specified changeset'), _('REV')),
4331 ('b', 'branch', [],
4332 ('b', 'branch', [],
4332 _('clone only the specified branch'), _('BRANCH')),
4333 _('clone only the specified branch'), _('BRANCH')),
4333 ('', 'pull', None, _('use pull protocol to copy metadata')),
4334 ('', 'pull', None, _('use pull protocol to copy metadata')),
4334 ('', 'uncompressed', None,
4335 ('', 'uncompressed', None,
4335 _('use uncompressed transfer (fast over LAN)')),
4336 _('use uncompressed transfer (fast over LAN)')),
4336 ] + remoteopts,
4337 ] + remoteopts,
4337 _('[OPTION]... SOURCE [DEST]')),
4338 _('[OPTION]... SOURCE [DEST]')),
4338 "^commit|ci":
4339 "^commit|ci":
4339 (commit,
4340 (commit,
4340 [('A', 'addremove', None,
4341 [('A', 'addremove', None,
4341 _('mark new/missing files as added/removed before committing')),
4342 _('mark new/missing files as added/removed before committing')),
4342 ('', 'close-branch', None,
4343 ('', 'close-branch', None,
4343 _('mark a branch as closed, hiding it from the branch list')),
4344 _('mark a branch as closed, hiding it from the branch list')),
4344 ] + walkopts + commitopts + commitopts2,
4345 ] + walkopts + commitopts + commitopts2,
4345 _('[OPTION]... [FILE]...')),
4346 _('[OPTION]... [FILE]...')),
4346 "copy|cp":
4347 "copy|cp":
4347 (copy,
4348 (copy,
4348 [('A', 'after', None, _('record a copy that has already occurred')),
4349 [('A', 'after', None, _('record a copy that has already occurred')),
4349 ('f', 'force', None,
4350 ('f', 'force', None,
4350 _('forcibly copy over an existing managed file')),
4351 _('forcibly copy over an existing managed file')),
4351 ] + walkopts + dryrunopts,
4352 ] + walkopts + dryrunopts,
4352 _('[OPTION]... [SOURCE]... DEST')),
4353 _('[OPTION]... [SOURCE]... DEST')),
4353 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4354 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4354 "debugbuilddag":
4355 "debugbuilddag":
4355 (debugbuilddag,
4356 (debugbuilddag,
4356 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4357 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4357 ('a', 'appended-file', None, _('add single file all revs append to')),
4358 ('a', 'appended-file', None, _('add single file all revs append to')),
4358 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4359 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4359 ('n', 'new-file', None, _('add new file at each rev')),
4360 ('n', 'new-file', None, _('add new file at each rev')),
4360 ],
4361 ],
4361 _('[OPTION]... TEXT')),
4362 _('[OPTION]... TEXT')),
4362 "debugcheckstate": (debugcheckstate, [], ''),
4363 "debugcheckstate": (debugcheckstate, [], ''),
4363 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4364 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4364 "debugcomplete":
4365 "debugcomplete":
4365 (debugcomplete,
4366 (debugcomplete,
4366 [('o', 'options', None, _('show the command options'))],
4367 [('o', 'options', None, _('show the command options'))],
4367 _('[-o] CMD')),
4368 _('[-o] CMD')),
4368 "debugdag":
4369 "debugdag":
4369 (debugdag,
4370 (debugdag,
4370 [('t', 'tags', None, _('use tags as labels')),
4371 [('t', 'tags', None, _('use tags as labels')),
4371 ('b', 'branches', None, _('annotate with branch names')),
4372 ('b', 'branches', None, _('annotate with branch names')),
4372 ('', 'dots', None, _('use dots for runs')),
4373 ('', 'dots', None, _('use dots for runs')),
4373 ('s', 'spaces', None, _('separate elements by spaces')),
4374 ('s', 'spaces', None, _('separate elements by spaces')),
4374 ],
4375 ],
4375 _('[OPTION]... [FILE [REV]...]')),
4376 _('[OPTION]... [FILE [REV]...]')),
4376 "debugdate":
4377 "debugdate":
4377 (debugdate,
4378 (debugdate,
4378 [('e', 'extended', None, _('try extended date formats'))],
4379 [('e', 'extended', None, _('try extended date formats'))],
4379 _('[-e] DATE [RANGE]')),
4380 _('[-e] DATE [RANGE]')),
4380 "debugdata": (debugdata, [], _('FILE REV')),
4381 "debugdata": (debugdata, [], _('FILE REV')),
4381 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4382 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4382 "debugignore": (debugignore, [], ''),
4383 "debugignore": (debugignore, [], ''),
4383 "debugindex": (debugindex,
4384 "debugindex": (debugindex,
4384 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4385 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4385 _('FILE')),
4386 _('FILE')),
4386 "debugindexdot": (debugindexdot, [], _('FILE')),
4387 "debugindexdot": (debugindexdot, [], _('FILE')),
4387 "debuginstall": (debuginstall, [], ''),
4388 "debuginstall": (debuginstall, [], ''),
4388 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4389 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4389 "debugrebuildstate":
4390 "debugrebuildstate":
4390 (debugrebuildstate,
4391 (debugrebuildstate,
4391 [('r', 'rev', '',
4392 [('r', 'rev', '',
4392 _('revision to rebuild to'), _('REV'))],
4393 _('revision to rebuild to'), _('REV'))],
4393 _('[-r REV] [REV]')),
4394 _('[-r REV] [REV]')),
4394 "debugrename":
4395 "debugrename":
4395 (debugrename,
4396 (debugrename,
4396 [('r', 'rev', '',
4397 [('r', 'rev', '',
4397 _('revision to debug'), _('REV'))],
4398 _('revision to debug'), _('REV'))],
4398 _('[-r REV] FILE')),
4399 _('[-r REV] FILE')),
4399 "debugrevspec":
4400 "debugrevspec":
4400 (debugrevspec, [], ('REVSPEC')),
4401 (debugrevspec, [], ('REVSPEC')),
4401 "debugsetparents":
4402 "debugsetparents":
4402 (debugsetparents, [], _('REV1 [REV2]')),
4403 (debugsetparents, [], _('REV1 [REV2]')),
4403 "debugstate":
4404 "debugstate":
4404 (debugstate,
4405 (debugstate,
4405 [('', 'nodates', None, _('do not display the saved mtime'))],
4406 [('', 'nodates', None, _('do not display the saved mtime'))],
4406 _('[OPTION]...')),
4407 _('[OPTION]...')),
4407 "debugsub":
4408 "debugsub":
4408 (debugsub,
4409 (debugsub,
4409 [('r', 'rev', '',
4410 [('r', 'rev', '',
4410 _('revision to check'), _('REV'))],
4411 _('revision to check'), _('REV'))],
4411 _('[-r REV] [REV]')),
4412 _('[-r REV] [REV]')),
4412 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4413 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4413 "^diff":
4414 "^diff":
4414 (diff,
4415 (diff,
4415 [('r', 'rev', [],
4416 [('r', 'rev', [],
4416 _('revision'), _('REV')),
4417 _('revision'), _('REV')),
4417 ('c', 'change', '',
4418 ('c', 'change', '',
4418 _('change made by revision'), _('REV'))
4419 _('change made by revision'), _('REV'))
4419 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4420 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4420 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4421 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4421 "^export":
4422 "^export":
4422 (export,
4423 (export,
4423 [('o', 'output', '',
4424 [('o', 'output', '',
4424 _('print output to file with formatted name'), _('FORMAT')),
4425 _('print output to file with formatted name'), _('FORMAT')),
4425 ('', 'switch-parent', None, _('diff against the second parent')),
4426 ('', 'switch-parent', None, _('diff against the second parent')),
4426 ('r', 'rev', [],
4427 ('r', 'rev', [],
4427 _('revisions to export'), _('REV')),
4428 _('revisions to export'), _('REV')),
4428 ] + diffopts,
4429 ] + diffopts,
4429 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4430 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4430 "^forget":
4431 "^forget":
4431 (forget,
4432 (forget,
4432 [] + walkopts,
4433 [] + walkopts,
4433 _('[OPTION]... FILE...')),
4434 _('[OPTION]... FILE...')),
4434 "grep":
4435 "grep":
4435 (grep,
4436 (grep,
4436 [('0', 'print0', None, _('end fields with NUL')),
4437 [('0', 'print0', None, _('end fields with NUL')),
4437 ('', 'all', None, _('print all revisions that match')),
4438 ('', 'all', None, _('print all revisions that match')),
4438 ('f', 'follow', None,
4439 ('f', 'follow', None,
4439 _('follow changeset history,'
4440 _('follow changeset history,'
4440 ' or file history across copies and renames')),
4441 ' or file history across copies and renames')),
4441 ('i', 'ignore-case', None, _('ignore case when matching')),
4442 ('i', 'ignore-case', None, _('ignore case when matching')),
4442 ('l', 'files-with-matches', None,
4443 ('l', 'files-with-matches', None,
4443 _('print only filenames and revisions that match')),
4444 _('print only filenames and revisions that match')),
4444 ('n', 'line-number', None, _('print matching line numbers')),
4445 ('n', 'line-number', None, _('print matching line numbers')),
4445 ('r', 'rev', [],
4446 ('r', 'rev', [],
4446 _('only search files changed within revision range'), _('REV')),
4447 _('only search files changed within revision range'), _('REV')),
4447 ('u', 'user', None, _('list the author (long with -v)')),
4448 ('u', 'user', None, _('list the author (long with -v)')),
4448 ('d', 'date', None, _('list the date (short with -q)')),
4449 ('d', 'date', None, _('list the date (short with -q)')),
4449 ] + walkopts,
4450 ] + walkopts,
4450 _('[OPTION]... PATTERN [FILE]...')),
4451 _('[OPTION]... PATTERN [FILE]...')),
4451 "heads":
4452 "heads":
4452 (heads,
4453 (heads,
4453 [('r', 'rev', '',
4454 [('r', 'rev', '',
4454 _('show only heads which are descendants of STARTREV'),
4455 _('show only heads which are descendants of STARTREV'),
4455 _('STARTREV')),
4456 _('STARTREV')),
4456 ('t', 'topo', False, _('show topological heads only')),
4457 ('t', 'topo', False, _('show topological heads only')),
4457 ('a', 'active', False,
4458 ('a', 'active', False,
4458 _('show active branchheads only (DEPRECATED)')),
4459 _('show active branchheads only (DEPRECATED)')),
4459 ('c', 'closed', False,
4460 ('c', 'closed', False,
4460 _('show normal and closed branch heads')),
4461 _('show normal and closed branch heads')),
4461 ] + templateopts,
4462 ] + templateopts,
4462 _('[-ac] [-r STARTREV] [REV]...')),
4463 _('[-ac] [-r STARTREV] [REV]...')),
4463 "help": (help_, [], _('[TOPIC]')),
4464 "help": (help_, [], _('[TOPIC]')),
4464 "identify|id":
4465 "identify|id":
4465 (identify,
4466 (identify,
4466 [('r', 'rev', '',
4467 [('r', 'rev', '',
4467 _('identify the specified revision'), _('REV')),
4468 _('identify the specified revision'), _('REV')),
4468 ('n', 'num', None, _('show local revision number')),
4469 ('n', 'num', None, _('show local revision number')),
4469 ('i', 'id', None, _('show global revision id')),
4470 ('i', 'id', None, _('show global revision id')),
4470 ('b', 'branch', None, _('show branch')),
4471 ('b', 'branch', None, _('show branch')),
4471 ('t', 'tags', None, _('show tags')),
4472 ('t', 'tags', None, _('show tags')),
4472 ('B', 'bookmarks', None, _('show bookmarks'))],
4473 ('B', 'bookmarks', None, _('show bookmarks'))],
4473 _('[-nibtB] [-r REV] [SOURCE]')),
4474 _('[-nibtB] [-r REV] [SOURCE]')),
4474 "import|patch":
4475 "import|patch":
4475 (import_,
4476 (import_,
4476 [('p', 'strip', 1,
4477 [('p', 'strip', 1,
4477 _('directory strip option for patch. This has the same '
4478 _('directory strip option for patch. This has the same '
4478 'meaning as the corresponding patch option'),
4479 'meaning as the corresponding patch option'),
4479 _('NUM')),
4480 _('NUM')),
4480 ('b', 'base', '',
4481 ('b', 'base', '',
4481 _('base path'), _('PATH')),
4482 _('base path'), _('PATH')),
4482 ('f', 'force', None,
4483 ('f', 'force', None,
4483 _('skip check for outstanding uncommitted changes')),
4484 _('skip check for outstanding uncommitted changes')),
4484 ('', 'no-commit', None,
4485 ('', 'no-commit', None,
4485 _("don't commit, just update the working directory")),
4486 _("don't commit, just update the working directory")),
4486 ('', 'exact', None,
4487 ('', 'exact', None,
4487 _('apply patch to the nodes from which it was generated')),
4488 _('apply patch to the nodes from which it was generated')),
4488 ('', 'import-branch', None,
4489 ('', 'import-branch', None,
4489 _('use any branch information in patch (implied by --exact)'))] +
4490 _('use any branch information in patch (implied by --exact)'))] +
4490 commitopts + commitopts2 + similarityopts,
4491 commitopts + commitopts2 + similarityopts,
4491 _('[OPTION]... PATCH...')),
4492 _('[OPTION]... PATCH...')),
4492 "incoming|in":
4493 "incoming|in":
4493 (incoming,
4494 (incoming,
4494 [('f', 'force', None,
4495 [('f', 'force', None,
4495 _('run even if remote repository is unrelated')),
4496 _('run even if remote repository is unrelated')),
4496 ('n', 'newest-first', None, _('show newest record first')),
4497 ('n', 'newest-first', None, _('show newest record first')),
4497 ('', 'bundle', '',
4498 ('', 'bundle', '',
4498 _('file to store the bundles into'), _('FILE')),
4499 _('file to store the bundles into'), _('FILE')),
4499 ('r', 'rev', [],
4500 ('r', 'rev', [],
4500 _('a remote changeset intended to be added'), _('REV')),
4501 _('a remote changeset intended to be added'), _('REV')),
4501 ('B', 'bookmarks', False, _("compare bookmarks")),
4502 ('B', 'bookmarks', False, _("compare bookmarks")),
4502 ('b', 'branch', [],
4503 ('b', 'branch', [],
4503 _('a specific branch you would like to pull'), _('BRANCH')),
4504 _('a specific branch you would like to pull'), _('BRANCH')),
4504 ] + logopts + remoteopts + subrepoopts,
4505 ] + logopts + remoteopts + subrepoopts,
4505 _('[-p] [-n] [-M] [-f] [-r REV]...'
4506 _('[-p] [-n] [-M] [-f] [-r REV]...'
4506 ' [--bundle FILENAME] [SOURCE]')),
4507 ' [--bundle FILENAME] [SOURCE]')),
4507 "^init":
4508 "^init":
4508 (init,
4509 (init,
4509 remoteopts,
4510 remoteopts,
4510 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4511 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4511 "locate":
4512 "locate":
4512 (locate,
4513 (locate,
4513 [('r', 'rev', '',
4514 [('r', 'rev', '',
4514 _('search the repository as it is in REV'), _('REV')),
4515 _('search the repository as it is in REV'), _('REV')),
4515 ('0', 'print0', None,
4516 ('0', 'print0', None,
4516 _('end filenames with NUL, for use with xargs')),
4517 _('end filenames with NUL, for use with xargs')),
4517 ('f', 'fullpath', None,
4518 ('f', 'fullpath', None,
4518 _('print complete paths from the filesystem root')),
4519 _('print complete paths from the filesystem root')),
4519 ] + walkopts,
4520 ] + walkopts,
4520 _('[OPTION]... [PATTERN]...')),
4521 _('[OPTION]... [PATTERN]...')),
4521 "^log|history":
4522 "^log|history":
4522 (log,
4523 (log,
4523 [('f', 'follow', None,
4524 [('f', 'follow', None,
4524 _('follow changeset history,'
4525 _('follow changeset history,'
4525 ' or file history across copies and renames')),
4526 ' or file history across copies and renames')),
4526 ('', 'follow-first', None,
4527 ('', 'follow-first', None,
4527 _('only follow the first parent of merge changesets')),
4528 _('only follow the first parent of merge changesets')),
4528 ('d', 'date', '',
4529 ('d', 'date', '',
4529 _('show revisions matching date spec'), _('DATE')),
4530 _('show revisions matching date spec'), _('DATE')),
4530 ('C', 'copies', None, _('show copied files')),
4531 ('C', 'copies', None, _('show copied files')),
4531 ('k', 'keyword', [],
4532 ('k', 'keyword', [],
4532 _('do case-insensitive search for a given text'), _('TEXT')),
4533 _('do case-insensitive search for a given text'), _('TEXT')),
4533 ('r', 'rev', [],
4534 ('r', 'rev', [],
4534 _('show the specified revision or range'), _('REV')),
4535 _('show the specified revision or range'), _('REV')),
4535 ('', 'removed', None, _('include revisions where files were removed')),
4536 ('', 'removed', None, _('include revisions where files were removed')),
4536 ('m', 'only-merges', None, _('show only merges')),
4537 ('m', 'only-merges', None, _('show only merges')),
4537 ('u', 'user', [],
4538 ('u', 'user', [],
4538 _('revisions committed by user'), _('USER')),
4539 _('revisions committed by user'), _('USER')),
4539 ('', 'only-branch', [],
4540 ('', 'only-branch', [],
4540 _('show only changesets within the given named branch (DEPRECATED)'),
4541 _('show only changesets within the given named branch (DEPRECATED)'),
4541 _('BRANCH')),
4542 _('BRANCH')),
4542 ('b', 'branch', [],
4543 ('b', 'branch', [],
4543 _('show changesets within the given named branch'), _('BRANCH')),
4544 _('show changesets within the given named branch'), _('BRANCH')),
4544 ('P', 'prune', [],
4545 ('P', 'prune', [],
4545 _('do not display revision or any of its ancestors'), _('REV')),
4546 _('do not display revision or any of its ancestors'), _('REV')),
4546 ] + logopts + walkopts,
4547 ] + logopts + walkopts,
4547 _('[OPTION]... [FILE]')),
4548 _('[OPTION]... [FILE]')),
4548 "manifest":
4549 "manifest":
4549 (manifest,
4550 (manifest,
4550 [('r', 'rev', '',
4551 [('r', 'rev', '',
4551 _('revision to display'), _('REV'))],
4552 _('revision to display'), _('REV'))],
4552 _('[-r REV]')),
4553 _('[-r REV]')),
4553 "^merge":
4554 "^merge":
4554 (merge,
4555 (merge,
4555 [('f', 'force', None, _('force a merge with outstanding changes')),
4556 [('f', 'force', None, _('force a merge with outstanding changes')),
4556 ('t', 'tool', '', _('specify merge tool')),
4557 ('t', 'tool', '', _('specify merge tool')),
4557 ('r', 'rev', '',
4558 ('r', 'rev', '',
4558 _('revision to merge'), _('REV')),
4559 _('revision to merge'), _('REV')),
4559 ('P', 'preview', None,
4560 ('P', 'preview', None,
4560 _('review revisions to merge (no merge is performed)'))],
4561 _('review revisions to merge (no merge is performed)'))],
4561 _('[-P] [-f] [[-r] REV]')),
4562 _('[-P] [-f] [[-r] REV]')),
4562 "outgoing|out":
4563 "outgoing|out":
4563 (outgoing,
4564 (outgoing,
4564 [('f', 'force', None,
4565 [('f', 'force', None,
4565 _('run even when the destination is unrelated')),
4566 _('run even when the destination is unrelated')),
4566 ('r', 'rev', [],
4567 ('r', 'rev', [],
4567 _('a changeset intended to be included in the destination'),
4568 _('a changeset intended to be included in the destination'),
4568 _('REV')),
4569 _('REV')),
4569 ('n', 'newest-first', None, _('show newest record first')),
4570 ('n', 'newest-first', None, _('show newest record first')),
4570 ('B', 'bookmarks', False, _("compare bookmarks")),
4571 ('B', 'bookmarks', False, _("compare bookmarks")),
4571 ('b', 'branch', [],
4572 ('b', 'branch', [],
4572 _('a specific branch you would like to push'), _('BRANCH')),
4573 _('a specific branch you would like to push'), _('BRANCH')),
4573 ] + logopts + remoteopts + subrepoopts,
4574 ] + logopts + remoteopts + subrepoopts,
4574 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4575 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4575 "parents":
4576 "parents":
4576 (parents,
4577 (parents,
4577 [('r', 'rev', '',
4578 [('r', 'rev', '',
4578 _('show parents of the specified revision'), _('REV')),
4579 _('show parents of the specified revision'), _('REV')),
4579 ] + templateopts,
4580 ] + templateopts,
4580 _('[-r REV] [FILE]')),
4581 _('[-r REV] [FILE]')),
4581 "paths": (paths, [], _('[NAME]')),
4582 "paths": (paths, [], _('[NAME]')),
4582 "^pull":
4583 "^pull":
4583 (pull,
4584 (pull,
4584 [('u', 'update', None,
4585 [('u', 'update', None,
4585 _('update to new branch head if changesets were pulled')),
4586 _('update to new branch head if changesets were pulled')),
4586 ('f', 'force', None,
4587 ('f', 'force', None,
4587 _('run even when remote repository is unrelated')),
4588 _('run even when remote repository is unrelated')),
4588 ('r', 'rev', [],
4589 ('r', 'rev', [],
4589 _('a remote changeset intended to be added'), _('REV')),
4590 _('a remote changeset intended to be added'), _('REV')),
4590 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4591 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4591 ('b', 'branch', [],
4592 ('b', 'branch', [],
4592 _('a specific branch you would like to pull'), _('BRANCH')),
4593 _('a specific branch you would like to pull'), _('BRANCH')),
4593 ] + remoteopts,
4594 ] + remoteopts,
4594 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4595 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4595 "^push":
4596 "^push":
4596 (push,
4597 (push,
4597 [('f', 'force', None, _('force push')),
4598 [('f', 'force', None, _('force push')),
4598 ('r', 'rev', [],
4599 ('r', 'rev', [],
4599 _('a changeset intended to be included in the destination'),
4600 _('a changeset intended to be included in the destination'),
4600 _('REV')),
4601 _('REV')),
4601 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4602 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4602 ('b', 'branch', [],
4603 ('b', 'branch', [],
4603 _('a specific branch you would like to push'), _('BRANCH')),
4604 _('a specific branch you would like to push'), _('BRANCH')),
4604 ('', 'new-branch', False, _('allow pushing a new branch')),
4605 ('', 'new-branch', False, _('allow pushing a new branch')),
4605 ] + remoteopts,
4606 ] + remoteopts,
4606 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4607 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4607 "recover": (recover, []),
4608 "recover": (recover, []),
4608 "^remove|rm":
4609 "^remove|rm":
4609 (remove,
4610 (remove,
4610 [('A', 'after', None, _('record delete for missing files')),
4611 [('A', 'after', None, _('record delete for missing files')),
4611 ('f', 'force', None,
4612 ('f', 'force', None,
4612 _('remove (and delete) file even if added or modified')),
4613 _('remove (and delete) file even if added or modified')),
4613 ] + walkopts,
4614 ] + walkopts,
4614 _('[OPTION]... FILE...')),
4615 _('[OPTION]... FILE...')),
4615 "rename|move|mv":
4616 "rename|move|mv":
4616 (rename,
4617 (rename,
4617 [('A', 'after', None, _('record a rename that has already occurred')),
4618 [('A', 'after', None, _('record a rename that has already occurred')),
4618 ('f', 'force', None,
4619 ('f', 'force', None,
4619 _('forcibly copy over an existing managed file')),
4620 _('forcibly copy over an existing managed file')),
4620 ] + walkopts + dryrunopts,
4621 ] + walkopts + dryrunopts,
4621 _('[OPTION]... SOURCE... DEST')),
4622 _('[OPTION]... SOURCE... DEST')),
4622 "resolve":
4623 "resolve":
4623 (resolve,
4624 (resolve,
4624 [('a', 'all', None, _('select all unresolved files')),
4625 [('a', 'all', None, _('select all unresolved files')),
4625 ('l', 'list', None, _('list state of files needing merge')),
4626 ('l', 'list', None, _('list state of files needing merge')),
4626 ('m', 'mark', None, _('mark files as resolved')),
4627 ('m', 'mark', None, _('mark files as resolved')),
4627 ('u', 'unmark', None, _('mark files as unresolved')),
4628 ('u', 'unmark', None, _('mark files as unresolved')),
4628 ('t', 'tool', '', _('specify merge tool')),
4629 ('t', 'tool', '', _('specify merge tool')),
4629 ('n', 'no-status', None, _('hide status prefix'))]
4630 ('n', 'no-status', None, _('hide status prefix'))]
4630 + walkopts,
4631 + walkopts,
4631 _('[OPTION]... [FILE]...')),
4632 _('[OPTION]... [FILE]...')),
4632 "revert":
4633 "revert":
4633 (revert,
4634 (revert,
4634 [('a', 'all', None, _('revert all changes when no arguments given')),
4635 [('a', 'all', None, _('revert all changes when no arguments given')),
4635 ('d', 'date', '',
4636 ('d', 'date', '',
4636 _('tipmost revision matching date'), _('DATE')),
4637 _('tipmost revision matching date'), _('DATE')),
4637 ('r', 'rev', '',
4638 ('r', 'rev', '',
4638 _('revert to the specified revision'), _('REV')),
4639 _('revert to the specified revision'), _('REV')),
4639 ('', 'no-backup', None, _('do not save backup copies of files')),
4640 ('', 'no-backup', None, _('do not save backup copies of files')),
4640 ] + walkopts + dryrunopts,
4641 ] + walkopts + dryrunopts,
4641 _('[OPTION]... [-r REV] [NAME]...')),
4642 _('[OPTION]... [-r REV] [NAME]...')),
4642 "rollback": (rollback, dryrunopts),
4643 "rollback": (rollback, dryrunopts),
4643 "root": (root, []),
4644 "root": (root, []),
4644 "^serve":
4645 "^serve":
4645 (serve,
4646 (serve,
4646 [('A', 'accesslog', '',
4647 [('A', 'accesslog', '',
4647 _('name of access log file to write to'), _('FILE')),
4648 _('name of access log file to write to'), _('FILE')),
4648 ('d', 'daemon', None, _('run server in background')),
4649 ('d', 'daemon', None, _('run server in background')),
4649 ('', 'daemon-pipefds', '',
4650 ('', 'daemon-pipefds', '',
4650 _('used internally by daemon mode'), _('NUM')),
4651 _('used internally by daemon mode'), _('NUM')),
4651 ('E', 'errorlog', '',
4652 ('E', 'errorlog', '',
4652 _('name of error log file to write to'), _('FILE')),
4653 _('name of error log file to write to'), _('FILE')),
4653 # use string type, then we can check if something was passed
4654 # use string type, then we can check if something was passed
4654 ('p', 'port', '',
4655 ('p', 'port', '',
4655 _('port to listen on (default: 8000)'), _('PORT')),
4656 _('port to listen on (default: 8000)'), _('PORT')),
4656 ('a', 'address', '',
4657 ('a', 'address', '',
4657 _('address to listen on (default: all interfaces)'), _('ADDR')),
4658 _('address to listen on (default: all interfaces)'), _('ADDR')),
4658 ('', 'prefix', '',
4659 ('', 'prefix', '',
4659 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4660 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4660 ('n', 'name', '',
4661 ('n', 'name', '',
4661 _('name to show in web pages (default: working directory)'),
4662 _('name to show in web pages (default: working directory)'),
4662 _('NAME')),
4663 _('NAME')),
4663 ('', 'web-conf', '',
4664 ('', 'web-conf', '',
4664 _('name of the hgweb config file (see "hg help hgweb")'),
4665 _('name of the hgweb config file (see "hg help hgweb")'),
4665 _('FILE')),
4666 _('FILE')),
4666 ('', 'webdir-conf', '',
4667 ('', 'webdir-conf', '',
4667 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4668 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4668 ('', 'pid-file', '',
4669 ('', 'pid-file', '',
4669 _('name of file to write process ID to'), _('FILE')),
4670 _('name of file to write process ID to'), _('FILE')),
4670 ('', 'stdio', None, _('for remote clients')),
4671 ('', 'stdio', None, _('for remote clients')),
4671 ('t', 'templates', '',
4672 ('t', 'templates', '',
4672 _('web templates to use'), _('TEMPLATE')),
4673 _('web templates to use'), _('TEMPLATE')),
4673 ('', 'style', '',
4674 ('', 'style', '',
4674 _('template style to use'), _('STYLE')),
4675 _('template style to use'), _('STYLE')),
4675 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4676 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4676 ('', 'certificate', '',
4677 ('', 'certificate', '',
4677 _('SSL certificate file'), _('FILE'))],
4678 _('SSL certificate file'), _('FILE'))],
4678 _('[OPTION]...')),
4679 _('[OPTION]...')),
4679 "showconfig|debugconfig":
4680 "showconfig|debugconfig":
4680 (showconfig,
4681 (showconfig,
4681 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4682 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4682 _('[-u] [NAME]...')),
4683 _('[-u] [NAME]...')),
4683 "^summary|sum":
4684 "^summary|sum":
4684 (summary,
4685 (summary,
4685 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4686 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4686 "^status|st":
4687 "^status|st":
4687 (status,
4688 (status,
4688 [('A', 'all', None, _('show status of all files')),
4689 [('A', 'all', None, _('show status of all files')),
4689 ('m', 'modified', None, _('show only modified files')),
4690 ('m', 'modified', None, _('show only modified files')),
4690 ('a', 'added', None, _('show only added files')),
4691 ('a', 'added', None, _('show only added files')),
4691 ('r', 'removed', None, _('show only removed files')),
4692 ('r', 'removed', None, _('show only removed files')),
4692 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4693 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4693 ('c', 'clean', None, _('show only files without changes')),
4694 ('c', 'clean', None, _('show only files without changes')),
4694 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4695 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4695 ('i', 'ignored', None, _('show only ignored files')),
4696 ('i', 'ignored', None, _('show only ignored files')),
4696 ('n', 'no-status', None, _('hide status prefix')),
4697 ('n', 'no-status', None, _('hide status prefix')),
4697 ('C', 'copies', None, _('show source of copied files')),
4698 ('C', 'copies', None, _('show source of copied files')),
4698 ('0', 'print0', None,
4699 ('0', 'print0', None,
4699 _('end filenames with NUL, for use with xargs')),
4700 _('end filenames with NUL, for use with xargs')),
4700 ('', 'rev', [],
4701 ('', 'rev', [],
4701 _('show difference from revision'), _('REV')),
4702 _('show difference from revision'), _('REV')),
4702 ('', 'change', '',
4703 ('', 'change', '',
4703 _('list the changed files of a revision'), _('REV')),
4704 _('list the changed files of a revision'), _('REV')),
4704 ] + walkopts + subrepoopts,
4705 ] + walkopts + subrepoopts,
4705 _('[OPTION]... [FILE]...')),
4706 _('[OPTION]... [FILE]...')),
4706 "tag":
4707 "tag":
4707 (tag,
4708 (tag,
4708 [('f', 'force', None, _('force tag')),
4709 [('f', 'force', None, _('force tag')),
4709 ('l', 'local', None, _('make the tag local')),
4710 ('l', 'local', None, _('make the tag local')),
4710 ('r', 'rev', '',
4711 ('r', 'rev', '',
4711 _('revision to tag'), _('REV')),
4712 _('revision to tag'), _('REV')),
4712 ('', 'remove', None, _('remove a tag')),
4713 ('', 'remove', None, _('remove a tag')),
4713 # -l/--local is already there, commitopts cannot be used
4714 # -l/--local is already there, commitopts cannot be used
4714 ('e', 'edit', None, _('edit commit message')),
4715 ('e', 'edit', None, _('edit commit message')),
4715 ('m', 'message', '',
4716 ('m', 'message', '',
4716 _('use <text> as commit message'), _('TEXT')),
4717 _('use <text> as commit message'), _('TEXT')),
4717 ] + commitopts2,
4718 ] + commitopts2,
4718 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4719 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4719 "tags": (tags, [], ''),
4720 "tags": (tags, [], ''),
4720 "tip":
4721 "tip":
4721 (tip,
4722 (tip,
4722 [('p', 'patch', None, _('show patch')),
4723 [('p', 'patch', None, _('show patch')),
4723 ('g', 'git', None, _('use git extended diff format')),
4724 ('g', 'git', None, _('use git extended diff format')),
4724 ] + templateopts,
4725 ] + templateopts,
4725 _('[-p] [-g]')),
4726 _('[-p] [-g]')),
4726 "unbundle":
4727 "unbundle":
4727 (unbundle,
4728 (unbundle,
4728 [('u', 'update', None,
4729 [('u', 'update', None,
4729 _('update to new branch head if changesets were unbundled'))],
4730 _('update to new branch head if changesets were unbundled'))],
4730 _('[-u] FILE...')),
4731 _('[-u] FILE...')),
4731 "^update|up|checkout|co":
4732 "^update|up|checkout|co":
4732 (update,
4733 (update,
4733 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4734 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4734 ('c', 'check', None,
4735 ('c', 'check', None,
4735 _('update across branches if no uncommitted changes')),
4736 _('update across branches if no uncommitted changes')),
4736 ('d', 'date', '',
4737 ('d', 'date', '',
4737 _('tipmost revision matching date'), _('DATE')),
4738 _('tipmost revision matching date'), _('DATE')),
4738 ('r', 'rev', '',
4739 ('r', 'rev', '',
4739 _('revision'), _('REV'))],
4740 _('revision'), _('REV'))],
4740 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4741 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4741 "verify": (verify, []),
4742 "verify": (verify, []),
4742 "version": (version_, []),
4743 "version": (version_, []),
4743 }
4744 }
4744
4745
4745 norepo = ("clone init version help debugcommands debugcomplete"
4746 norepo = ("clone init version help debugcommands debugcomplete"
4746 " debugdate debuginstall debugfsinfo debugpushkey")
4747 " debugdate debuginstall debugfsinfo debugpushkey")
4747 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4748 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4748 " debugdata debugindex debugindexdot")
4749 " debugdata debugindex debugindexdot")
@@ -1,636 +1,636 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits 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 errno, getpass, os, socket, sys, tempfile, traceback
9 import errno, getpass, os, socket, sys, tempfile, traceback
10 import config, util, error
10 import config, util, error
11
11
12 class ui(object):
12 class ui(object):
13 def __init__(self, src=None):
13 def __init__(self, src=None):
14 self._buffers = []
14 self._buffers = []
15 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
15 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
16 self._reportuntrusted = True
16 self._reportuntrusted = True
17 self._ocfg = config.config() # overlay
17 self._ocfg = config.config() # overlay
18 self._tcfg = config.config() # trusted
18 self._tcfg = config.config() # trusted
19 self._ucfg = config.config() # untrusted
19 self._ucfg = config.config() # untrusted
20 self._trustusers = set()
20 self._trustusers = set()
21 self._trustgroups = set()
21 self._trustgroups = set()
22
22
23 if src:
23 if src:
24 self._tcfg = src._tcfg.copy()
24 self._tcfg = src._tcfg.copy()
25 self._ucfg = src._ucfg.copy()
25 self._ucfg = src._ucfg.copy()
26 self._ocfg = src._ocfg.copy()
26 self._ocfg = src._ocfg.copy()
27 self._trustusers = src._trustusers.copy()
27 self._trustusers = src._trustusers.copy()
28 self._trustgroups = src._trustgroups.copy()
28 self._trustgroups = src._trustgroups.copy()
29 self.environ = src.environ
29 self.environ = src.environ
30 self.fixconfig()
30 self.fixconfig()
31 else:
31 else:
32 # shared read-only environment
32 # shared read-only environment
33 self.environ = os.environ
33 self.environ = os.environ
34 # we always trust global config files
34 # we always trust global config files
35 for f in util.rcpath():
35 for f in util.rcpath():
36 self.readconfig(f, trust=True)
36 self.readconfig(f, trust=True)
37
37
38 def copy(self):
38 def copy(self):
39 return self.__class__(self)
39 return self.__class__(self)
40
40
41 def _is_trusted(self, fp, f):
41 def _is_trusted(self, fp, f):
42 st = util.fstat(fp)
42 st = util.fstat(fp)
43 if util.isowner(st):
43 if util.isowner(st):
44 return True
44 return True
45
45
46 tusers, tgroups = self._trustusers, self._trustgroups
46 tusers, tgroups = self._trustusers, self._trustgroups
47 if '*' in tusers or '*' in tgroups:
47 if '*' in tusers or '*' in tgroups:
48 return True
48 return True
49
49
50 user = util.username(st.st_uid)
50 user = util.username(st.st_uid)
51 group = util.groupname(st.st_gid)
51 group = util.groupname(st.st_gid)
52 if user in tusers or group in tgroups or user == util.username():
52 if user in tusers or group in tgroups or user == util.username():
53 return True
53 return True
54
54
55 if self._reportuntrusted:
55 if self._reportuntrusted:
56 self.warn(_('Not trusting file %s from untrusted '
56 self.warn(_('Not trusting file %s from untrusted '
57 'user %s, group %s\n') % (f, user, group))
57 'user %s, group %s\n') % (f, user, group))
58 return False
58 return False
59
59
60 def readconfig(self, filename, root=None, trust=False,
60 def readconfig(self, filename, root=None, trust=False,
61 sections=None, remap=None):
61 sections=None, remap=None):
62 try:
62 try:
63 fp = open(filename)
63 fp = open(filename)
64 except IOError:
64 except IOError:
65 if not sections: # ignore unless we were looking for something
65 if not sections: # ignore unless we were looking for something
66 return
66 return
67 raise
67 raise
68
68
69 cfg = config.config()
69 cfg = config.config()
70 trusted = sections or trust or self._is_trusted(fp, filename)
70 trusted = sections or trust or self._is_trusted(fp, filename)
71
71
72 try:
72 try:
73 cfg.read(filename, fp, sections=sections, remap=remap)
73 cfg.read(filename, fp, sections=sections, remap=remap)
74 except error.ConfigError, inst:
74 except error.ConfigError, inst:
75 if trusted:
75 if trusted:
76 raise
76 raise
77 self.warn(_("Ignored: %s\n") % str(inst))
77 self.warn(_("Ignored: %s\n") % str(inst))
78
78
79 if self.plain():
79 if self.plain():
80 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
80 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
81 'logtemplate', 'style',
81 'logtemplate', 'style',
82 'traceback', 'verbose'):
82 'traceback', 'verbose'):
83 if k in cfg['ui']:
83 if k in cfg['ui']:
84 del cfg['ui'][k]
84 del cfg['ui'][k]
85 for k, v in cfg.items('alias'):
85 for k, v in cfg.items('alias'):
86 del cfg['alias'][k]
86 del cfg['alias'][k]
87 for k, v in cfg.items('defaults'):
87 for k, v in cfg.items('defaults'):
88 del cfg['defaults'][k]
88 del cfg['defaults'][k]
89
89
90 if trusted:
90 if trusted:
91 self._tcfg.update(cfg)
91 self._tcfg.update(cfg)
92 self._tcfg.update(self._ocfg)
92 self._tcfg.update(self._ocfg)
93 self._ucfg.update(cfg)
93 self._ucfg.update(cfg)
94 self._ucfg.update(self._ocfg)
94 self._ucfg.update(self._ocfg)
95
95
96 if root is None:
96 if root is None:
97 root = os.path.expanduser('~')
97 root = os.path.expanduser('~')
98 self.fixconfig(root=root)
98 self.fixconfig(root=root)
99
99
100 def fixconfig(self, root=None, section=None):
100 def fixconfig(self, root=None, section=None):
101 if section in (None, 'paths'):
101 if section in (None, 'paths'):
102 # expand vars and ~
102 # expand vars and ~
103 # translate paths relative to root (or home) into absolute paths
103 # translate paths relative to root (or home) into absolute paths
104 root = root or os.getcwd()
104 root = root or os.getcwd()
105 for c in self._tcfg, self._ucfg, self._ocfg:
105 for c in self._tcfg, self._ucfg, self._ocfg:
106 for n, p in c.items('paths'):
106 for n, p in c.items('paths'):
107 if not p:
107 if not p:
108 continue
108 continue
109 if '%%' in p:
109 if '%%' in p:
110 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
110 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
111 % (n, p, self.configsource('paths', n)))
111 % (n, p, self.configsource('paths', n)))
112 p = p.replace('%%', '%')
112 p = p.replace('%%', '%')
113 p = util.expandpath(p)
113 p = util.expandpath(p)
114 if '://' not in p and not os.path.isabs(p):
114 if '://' not in p and not os.path.isabs(p):
115 p = os.path.normpath(os.path.join(root, p))
115 p = os.path.normpath(os.path.join(root, p))
116 c.set("paths", n, p)
116 c.set("paths", n, p)
117
117
118 if section in (None, 'ui'):
118 if section in (None, 'ui'):
119 # update ui options
119 # update ui options
120 self.debugflag = self.configbool('ui', 'debug')
120 self.debugflag = self.configbool('ui', 'debug')
121 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
121 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
122 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
122 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
123 if self.verbose and self.quiet:
123 if self.verbose and self.quiet:
124 self.quiet = self.verbose = False
124 self.quiet = self.verbose = False
125 self._reportuntrusted = self.debugflag or self.configbool("ui",
125 self._reportuntrusted = self.debugflag or self.configbool("ui",
126 "report_untrusted", True)
126 "report_untrusted", True)
127 self.tracebackflag = self.configbool('ui', 'traceback', False)
127 self.tracebackflag = self.configbool('ui', 'traceback', False)
128
128
129 if section in (None, 'trusted'):
129 if section in (None, 'trusted'):
130 # update trust information
130 # update trust information
131 self._trustusers.update(self.configlist('trusted', 'users'))
131 self._trustusers.update(self.configlist('trusted', 'users'))
132 self._trustgroups.update(self.configlist('trusted', 'groups'))
132 self._trustgroups.update(self.configlist('trusted', 'groups'))
133
133
134 def setconfig(self, section, name, value, overlay=True):
134 def setconfig(self, section, name, value, overlay=True):
135 if overlay:
135 if overlay:
136 self._ocfg.set(section, name, value)
136 self._ocfg.set(section, name, value)
137 self._tcfg.set(section, name, value)
137 self._tcfg.set(section, name, value)
138 self._ucfg.set(section, name, value)
138 self._ucfg.set(section, name, value)
139 self.fixconfig(section=section)
139 self.fixconfig(section=section)
140
140
141 def _data(self, untrusted):
141 def _data(self, untrusted):
142 return untrusted and self._ucfg or self._tcfg
142 return untrusted and self._ucfg or self._tcfg
143
143
144 def configsource(self, section, name, untrusted=False):
144 def configsource(self, section, name, untrusted=False):
145 return self._data(untrusted).source(section, name) or 'none'
145 return self._data(untrusted).source(section, name) or 'none'
146
146
147 def config(self, section, name, default=None, untrusted=False):
147 def config(self, section, name, default=None, untrusted=False):
148 value = self._data(untrusted).get(section, name, default)
148 value = self._data(untrusted).get(section, name, default)
149 if self.debugflag and not untrusted and self._reportuntrusted:
149 if self.debugflag and not untrusted and self._reportuntrusted:
150 uvalue = self._ucfg.get(section, name)
150 uvalue = self._ucfg.get(section, name)
151 if uvalue is not None and uvalue != value:
151 if uvalue is not None and uvalue != value:
152 self.debug(_("ignoring untrusted configuration option "
152 self.debug(_("ignoring untrusted configuration option "
153 "%s.%s = %s\n") % (section, name, uvalue))
153 "%s.%s = %s\n") % (section, name, uvalue))
154 return value
154 return value
155
155
156 def configpath(self, section, name, default=None, untrusted=False):
156 def configpath(self, section, name, default=None, untrusted=False):
157 'get a path config item, expanded relative to config file'
157 'get a path config item, expanded relative to config file'
158 v = self.config(section, name, default, untrusted)
158 v = self.config(section, name, default, untrusted)
159 if not os.path.isabs(v) or "://" not in v:
159 if not os.path.isabs(v) or "://" not in v:
160 src = self.configsource(section, name, untrusted)
160 src = self.configsource(section, name, untrusted)
161 if ':' in src:
161 if ':' in src:
162 base = os.path.dirname(src.rsplit(':'))
162 base = os.path.dirname(src.rsplit(':'))
163 v = os.path.join(base, os.path.expanduser(v))
163 v = os.path.join(base, os.path.expanduser(v))
164 return v
164 return v
165
165
166 def configbool(self, section, name, default=False, untrusted=False):
166 def configbool(self, section, name, default=False, untrusted=False):
167 v = self.config(section, name, None, untrusted)
167 v = self.config(section, name, None, untrusted)
168 if v is None:
168 if v is None:
169 return default
169 return default
170 if isinstance(v, bool):
170 if isinstance(v, bool):
171 return v
171 return v
172 b = util.parsebool(v)
172 b = util.parsebool(v)
173 if b is None:
173 if b is None:
174 raise error.ConfigError(_("%s.%s not a boolean ('%s')")
174 raise error.ConfigError(_("%s.%s not a boolean ('%s')")
175 % (section, name, v))
175 % (section, name, v))
176 return b
176 return b
177
177
178 def configlist(self, section, name, default=None, untrusted=False):
178 def configlist(self, section, name, default=None, untrusted=False):
179 """Return a list of comma/space separated strings"""
179 """Return a list of comma/space separated strings"""
180
180
181 def _parse_plain(parts, s, offset):
181 def _parse_plain(parts, s, offset):
182 whitespace = False
182 whitespace = False
183 while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
183 while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
184 whitespace = True
184 whitespace = True
185 offset += 1
185 offset += 1
186 if offset >= len(s):
186 if offset >= len(s):
187 return None, parts, offset
187 return None, parts, offset
188 if whitespace:
188 if whitespace:
189 parts.append('')
189 parts.append('')
190 if s[offset] == '"' and not parts[-1]:
190 if s[offset] == '"' and not parts[-1]:
191 return _parse_quote, parts, offset + 1
191 return _parse_quote, parts, offset + 1
192 elif s[offset] == '"' and parts[-1][-1] == '\\':
192 elif s[offset] == '"' and parts[-1][-1] == '\\':
193 parts[-1] = parts[-1][:-1] + s[offset]
193 parts[-1] = parts[-1][:-1] + s[offset]
194 return _parse_plain, parts, offset + 1
194 return _parse_plain, parts, offset + 1
195 parts[-1] += s[offset]
195 parts[-1] += s[offset]
196 return _parse_plain, parts, offset + 1
196 return _parse_plain, parts, offset + 1
197
197
198 def _parse_quote(parts, s, offset):
198 def _parse_quote(parts, s, offset):
199 if offset < len(s) and s[offset] == '"': # ""
199 if offset < len(s) and s[offset] == '"': # ""
200 parts.append('')
200 parts.append('')
201 offset += 1
201 offset += 1
202 while offset < len(s) and (s[offset].isspace() or
202 while offset < len(s) and (s[offset].isspace() or
203 s[offset] == ','):
203 s[offset] == ','):
204 offset += 1
204 offset += 1
205 return _parse_plain, parts, offset
205 return _parse_plain, parts, offset
206
206
207 while offset < len(s) and s[offset] != '"':
207 while offset < len(s) and s[offset] != '"':
208 if (s[offset] == '\\' and offset + 1 < len(s)
208 if (s[offset] == '\\' and offset + 1 < len(s)
209 and s[offset + 1] == '"'):
209 and s[offset + 1] == '"'):
210 offset += 1
210 offset += 1
211 parts[-1] += '"'
211 parts[-1] += '"'
212 else:
212 else:
213 parts[-1] += s[offset]
213 parts[-1] += s[offset]
214 offset += 1
214 offset += 1
215
215
216 if offset >= len(s):
216 if offset >= len(s):
217 real_parts = _configlist(parts[-1])
217 real_parts = _configlist(parts[-1])
218 if not real_parts:
218 if not real_parts:
219 parts[-1] = '"'
219 parts[-1] = '"'
220 else:
220 else:
221 real_parts[0] = '"' + real_parts[0]
221 real_parts[0] = '"' + real_parts[0]
222 parts = parts[:-1]
222 parts = parts[:-1]
223 parts.extend(real_parts)
223 parts.extend(real_parts)
224 return None, parts, offset
224 return None, parts, offset
225
225
226 offset += 1
226 offset += 1
227 while offset < len(s) and s[offset] in [' ', ',']:
227 while offset < len(s) and s[offset] in [' ', ',']:
228 offset += 1
228 offset += 1
229
229
230 if offset < len(s):
230 if offset < len(s):
231 if offset + 1 == len(s) and s[offset] == '"':
231 if offset + 1 == len(s) and s[offset] == '"':
232 parts[-1] += '"'
232 parts[-1] += '"'
233 offset += 1
233 offset += 1
234 else:
234 else:
235 parts.append('')
235 parts.append('')
236 else:
236 else:
237 return None, parts, offset
237 return None, parts, offset
238
238
239 return _parse_plain, parts, offset
239 return _parse_plain, parts, offset
240
240
241 def _configlist(s):
241 def _configlist(s):
242 s = s.rstrip(' ,')
242 s = s.rstrip(' ,')
243 if not s:
243 if not s:
244 return []
244 return []
245 parser, parts, offset = _parse_plain, [''], 0
245 parser, parts, offset = _parse_plain, [''], 0
246 while parser:
246 while parser:
247 parser, parts, offset = parser(parts, s, offset)
247 parser, parts, offset = parser(parts, s, offset)
248 return parts
248 return parts
249
249
250 result = self.config(section, name, untrusted=untrusted)
250 result = self.config(section, name, untrusted=untrusted)
251 if result is None:
251 if result is None:
252 result = default or []
252 result = default or []
253 if isinstance(result, basestring):
253 if isinstance(result, basestring):
254 result = _configlist(result.lstrip(' ,\n'))
254 result = _configlist(result.lstrip(' ,\n'))
255 if result is None:
255 if result is None:
256 result = default or []
256 result = default or []
257 return result
257 return result
258
258
259 def has_section(self, section, untrusted=False):
259 def has_section(self, section, untrusted=False):
260 '''tell whether section exists in config.'''
260 '''tell whether section exists in config.'''
261 return section in self._data(untrusted)
261 return section in self._data(untrusted)
262
262
263 def configitems(self, section, untrusted=False):
263 def configitems(self, section, untrusted=False):
264 items = self._data(untrusted).items(section)
264 items = self._data(untrusted).items(section)
265 if self.debugflag and not untrusted and self._reportuntrusted:
265 if self.debugflag and not untrusted and self._reportuntrusted:
266 for k, v in self._ucfg.items(section):
266 for k, v in self._ucfg.items(section):
267 if self._tcfg.get(section, k) != v:
267 if self._tcfg.get(section, k) != v:
268 self.debug(_("ignoring untrusted configuration option "
268 self.debug(_("ignoring untrusted configuration option "
269 "%s.%s = %s\n") % (section, k, v))
269 "%s.%s = %s\n") % (section, k, v))
270 return items
270 return items
271
271
272 def walkconfig(self, untrusted=False):
272 def walkconfig(self, untrusted=False):
273 cfg = self._data(untrusted)
273 cfg = self._data(untrusted)
274 for section in cfg.sections():
274 for section in cfg.sections():
275 for name, value in self.configitems(section, untrusted):
275 for name, value in self.configitems(section, untrusted):
276 yield section, name, str(value).replace('\n', '\\n')
276 yield section, name, value
277
277
278 def plain(self):
278 def plain(self):
279 '''is plain mode active?
279 '''is plain mode active?
280
280
281 Plain mode means that all configuration variables which affect the
281 Plain mode means that all configuration variables which affect the
282 behavior and output of Mercurial should be ignored. Additionally, the
282 behavior and output of Mercurial should be ignored. Additionally, the
283 output should be stable, reproducible and suitable for use in scripts or
283 output should be stable, reproducible and suitable for use in scripts or
284 applications.
284 applications.
285
285
286 The only way to trigger plain mode is by setting the `HGPLAIN'
286 The only way to trigger plain mode is by setting the `HGPLAIN'
287 environment variable.
287 environment variable.
288 '''
288 '''
289 return 'HGPLAIN' in os.environ
289 return 'HGPLAIN' in os.environ
290
290
291 def username(self):
291 def username(self):
292 """Return default username to be used in commits.
292 """Return default username to be used in commits.
293
293
294 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
294 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
295 and stop searching if one of these is set.
295 and stop searching if one of these is set.
296 If not found and ui.askusername is True, ask the user, else use
296 If not found and ui.askusername is True, ask the user, else use
297 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
297 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
298 """
298 """
299 user = os.environ.get("HGUSER")
299 user = os.environ.get("HGUSER")
300 if user is None:
300 if user is None:
301 user = self.config("ui", "username")
301 user = self.config("ui", "username")
302 if user is not None:
302 if user is not None:
303 user = os.path.expandvars(user)
303 user = os.path.expandvars(user)
304 if user is None:
304 if user is None:
305 user = os.environ.get("EMAIL")
305 user = os.environ.get("EMAIL")
306 if user is None and self.configbool("ui", "askusername"):
306 if user is None and self.configbool("ui", "askusername"):
307 user = self.prompt(_("enter a commit username:"), default=None)
307 user = self.prompt(_("enter a commit username:"), default=None)
308 if user is None and not self.interactive():
308 if user is None and not self.interactive():
309 try:
309 try:
310 user = '%s@%s' % (util.getuser(), socket.getfqdn())
310 user = '%s@%s' % (util.getuser(), socket.getfqdn())
311 self.warn(_("No username found, using '%s' instead\n") % user)
311 self.warn(_("No username found, using '%s' instead\n") % user)
312 except KeyError:
312 except KeyError:
313 pass
313 pass
314 if not user:
314 if not user:
315 raise util.Abort(_('no username supplied (see "hg help config")'))
315 raise util.Abort(_('no username supplied (see "hg help config")'))
316 if "\n" in user:
316 if "\n" in user:
317 raise util.Abort(_("username %s contains a newline\n") % repr(user))
317 raise util.Abort(_("username %s contains a newline\n") % repr(user))
318 return user
318 return user
319
319
320 def shortuser(self, user):
320 def shortuser(self, user):
321 """Return a short representation of a user name or email address."""
321 """Return a short representation of a user name or email address."""
322 if not self.verbose:
322 if not self.verbose:
323 user = util.shortuser(user)
323 user = util.shortuser(user)
324 return user
324 return user
325
325
326 def expandpath(self, loc, default=None):
326 def expandpath(self, loc, default=None):
327 """Return repository location relative to cwd or from [paths]"""
327 """Return repository location relative to cwd or from [paths]"""
328 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
328 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
329 return loc
329 return loc
330
330
331 path = self.config('paths', loc)
331 path = self.config('paths', loc)
332 if not path and default is not None:
332 if not path and default is not None:
333 path = self.config('paths', default)
333 path = self.config('paths', default)
334 return path or loc
334 return path or loc
335
335
336 def pushbuffer(self):
336 def pushbuffer(self):
337 self._buffers.append([])
337 self._buffers.append([])
338
338
339 def popbuffer(self, labeled=False):
339 def popbuffer(self, labeled=False):
340 '''pop the last buffer and return the buffered output
340 '''pop the last buffer and return the buffered output
341
341
342 If labeled is True, any labels associated with buffered
342 If labeled is True, any labels associated with buffered
343 output will be handled. By default, this has no effect
343 output will be handled. By default, this has no effect
344 on the output returned, but extensions and GUI tools may
344 on the output returned, but extensions and GUI tools may
345 handle this argument and returned styled output. If output
345 handle this argument and returned styled output. If output
346 is being buffered so it can be captured and parsed or
346 is being buffered so it can be captured and parsed or
347 processed, labeled should not be set to True.
347 processed, labeled should not be set to True.
348 '''
348 '''
349 return "".join(self._buffers.pop())
349 return "".join(self._buffers.pop())
350
350
351 def write(self, *args, **opts):
351 def write(self, *args, **opts):
352 '''write args to output
352 '''write args to output
353
353
354 By default, this method simply writes to the buffer or stdout,
354 By default, this method simply writes to the buffer or stdout,
355 but extensions or GUI tools may override this method,
355 but extensions or GUI tools may override this method,
356 write_err(), popbuffer(), and label() to style output from
356 write_err(), popbuffer(), and label() to style output from
357 various parts of hg.
357 various parts of hg.
358
358
359 An optional keyword argument, "label", can be passed in.
359 An optional keyword argument, "label", can be passed in.
360 This should be a string containing label names separated by
360 This should be a string containing label names separated by
361 space. Label names take the form of "topic.type". For example,
361 space. Label names take the form of "topic.type". For example,
362 ui.debug() issues a label of "ui.debug".
362 ui.debug() issues a label of "ui.debug".
363
363
364 When labeling output for a specific command, a label of
364 When labeling output for a specific command, a label of
365 "cmdname.type" is recommended. For example, status issues
365 "cmdname.type" is recommended. For example, status issues
366 a label of "status.modified" for modified files.
366 a label of "status.modified" for modified files.
367 '''
367 '''
368 if self._buffers:
368 if self._buffers:
369 self._buffers[-1].extend([str(a) for a in args])
369 self._buffers[-1].extend([str(a) for a in args])
370 else:
370 else:
371 for a in args:
371 for a in args:
372 sys.stdout.write(str(a))
372 sys.stdout.write(str(a))
373
373
374 def write_err(self, *args, **opts):
374 def write_err(self, *args, **opts):
375 try:
375 try:
376 if not getattr(sys.stdout, 'closed', False):
376 if not getattr(sys.stdout, 'closed', False):
377 sys.stdout.flush()
377 sys.stdout.flush()
378 for a in args:
378 for a in args:
379 sys.stderr.write(str(a))
379 sys.stderr.write(str(a))
380 # stderr may be buffered under win32 when redirected to files,
380 # stderr may be buffered under win32 when redirected to files,
381 # including stdout.
381 # including stdout.
382 if not getattr(sys.stderr, 'closed', False):
382 if not getattr(sys.stderr, 'closed', False):
383 sys.stderr.flush()
383 sys.stderr.flush()
384 except IOError, inst:
384 except IOError, inst:
385 if inst.errno not in (errno.EPIPE, errno.EIO):
385 if inst.errno not in (errno.EPIPE, errno.EIO):
386 raise
386 raise
387
387
388 def flush(self):
388 def flush(self):
389 try: sys.stdout.flush()
389 try: sys.stdout.flush()
390 except: pass
390 except: pass
391 try: sys.stderr.flush()
391 try: sys.stderr.flush()
392 except: pass
392 except: pass
393
393
394 def interactive(self):
394 def interactive(self):
395 '''is interactive input allowed?
395 '''is interactive input allowed?
396
396
397 An interactive session is a session where input can be reasonably read
397 An interactive session is a session where input can be reasonably read
398 from `sys.stdin'. If this function returns false, any attempt to read
398 from `sys.stdin'. If this function returns false, any attempt to read
399 from stdin should fail with an error, unless a sensible default has been
399 from stdin should fail with an error, unless a sensible default has been
400 specified.
400 specified.
401
401
402 Interactiveness is triggered by the value of the `ui.interactive'
402 Interactiveness is triggered by the value of the `ui.interactive'
403 configuration variable or - if it is unset - when `sys.stdin' points
403 configuration variable or - if it is unset - when `sys.stdin' points
404 to a terminal device.
404 to a terminal device.
405
405
406 This function refers to input only; for output, see `ui.formatted()'.
406 This function refers to input only; for output, see `ui.formatted()'.
407 '''
407 '''
408 i = self.configbool("ui", "interactive", None)
408 i = self.configbool("ui", "interactive", None)
409 if i is None:
409 if i is None:
410 try:
410 try:
411 return sys.stdin.isatty()
411 return sys.stdin.isatty()
412 except AttributeError:
412 except AttributeError:
413 # some environments replace stdin without implementing isatty
413 # some environments replace stdin without implementing isatty
414 # usually those are non-interactive
414 # usually those are non-interactive
415 return False
415 return False
416
416
417 return i
417 return i
418
418
419 def termwidth(self):
419 def termwidth(self):
420 '''how wide is the terminal in columns?
420 '''how wide is the terminal in columns?
421 '''
421 '''
422 if 'COLUMNS' in os.environ:
422 if 'COLUMNS' in os.environ:
423 try:
423 try:
424 return int(os.environ['COLUMNS'])
424 return int(os.environ['COLUMNS'])
425 except ValueError:
425 except ValueError:
426 pass
426 pass
427 return util.termwidth()
427 return util.termwidth()
428
428
429 def formatted(self):
429 def formatted(self):
430 '''should formatted output be used?
430 '''should formatted output be used?
431
431
432 It is often desirable to format the output to suite the output medium.
432 It is often desirable to format the output to suite the output medium.
433 Examples of this are truncating long lines or colorizing messages.
433 Examples of this are truncating long lines or colorizing messages.
434 However, this is not often not desirable when piping output into other
434 However, this is not often not desirable when piping output into other
435 utilities, e.g. `grep'.
435 utilities, e.g. `grep'.
436
436
437 Formatted output is triggered by the value of the `ui.formatted'
437 Formatted output is triggered by the value of the `ui.formatted'
438 configuration variable or - if it is unset - when `sys.stdout' points
438 configuration variable or - if it is unset - when `sys.stdout' points
439 to a terminal device. Please note that `ui.formatted' should be
439 to a terminal device. Please note that `ui.formatted' should be
440 considered an implementation detail; it is not intended for use outside
440 considered an implementation detail; it is not intended for use outside
441 Mercurial or its extensions.
441 Mercurial or its extensions.
442
442
443 This function refers to output only; for input, see `ui.interactive()'.
443 This function refers to output only; for input, see `ui.interactive()'.
444 This function always returns false when in plain mode, see `ui.plain()'.
444 This function always returns false when in plain mode, see `ui.plain()'.
445 '''
445 '''
446 if self.plain():
446 if self.plain():
447 return False
447 return False
448
448
449 i = self.configbool("ui", "formatted", None)
449 i = self.configbool("ui", "formatted", None)
450 if i is None:
450 if i is None:
451 try:
451 try:
452 return sys.stdout.isatty()
452 return sys.stdout.isatty()
453 except AttributeError:
453 except AttributeError:
454 # some environments replace stdout without implementing isatty
454 # some environments replace stdout without implementing isatty
455 # usually those are non-interactive
455 # usually those are non-interactive
456 return False
456 return False
457
457
458 return i
458 return i
459
459
460 def _readline(self, prompt=''):
460 def _readline(self, prompt=''):
461 if sys.stdin.isatty():
461 if sys.stdin.isatty():
462 try:
462 try:
463 # magically add command line editing support, where
463 # magically add command line editing support, where
464 # available
464 # available
465 import readline
465 import readline
466 # force demandimport to really load the module
466 # force demandimport to really load the module
467 readline.read_history_file
467 readline.read_history_file
468 # windows sometimes raises something other than ImportError
468 # windows sometimes raises something other than ImportError
469 except Exception:
469 except Exception:
470 pass
470 pass
471 line = raw_input(prompt)
471 line = raw_input(prompt)
472 # When stdin is in binary mode on Windows, it can cause
472 # When stdin is in binary mode on Windows, it can cause
473 # raw_input() to emit an extra trailing carriage return
473 # raw_input() to emit an extra trailing carriage return
474 if os.linesep == '\r\n' and line and line[-1] == '\r':
474 if os.linesep == '\r\n' and line and line[-1] == '\r':
475 line = line[:-1]
475 line = line[:-1]
476 return line
476 return line
477
477
478 def prompt(self, msg, default="y"):
478 def prompt(self, msg, default="y"):
479 """Prompt user with msg, read response.
479 """Prompt user with msg, read response.
480 If ui is not interactive, the default is returned.
480 If ui is not interactive, the default is returned.
481 """
481 """
482 if not self.interactive():
482 if not self.interactive():
483 self.write(msg, ' ', default, "\n")
483 self.write(msg, ' ', default, "\n")
484 return default
484 return default
485 try:
485 try:
486 r = self._readline(msg + ' ')
486 r = self._readline(msg + ' ')
487 if not r:
487 if not r:
488 return default
488 return default
489 return r
489 return r
490 except EOFError:
490 except EOFError:
491 raise util.Abort(_('response expected'))
491 raise util.Abort(_('response expected'))
492
492
493 def promptchoice(self, msg, choices, default=0):
493 def promptchoice(self, msg, choices, default=0):
494 """Prompt user with msg, read response, and ensure it matches
494 """Prompt user with msg, read response, and ensure it matches
495 one of the provided choices. The index of the choice is returned.
495 one of the provided choices. The index of the choice is returned.
496 choices is a sequence of acceptable responses with the format:
496 choices is a sequence of acceptable responses with the format:
497 ('&None', 'E&xec', 'Sym&link') Responses are case insensitive.
497 ('&None', 'E&xec', 'Sym&link') Responses are case insensitive.
498 If ui is not interactive, the default is returned.
498 If ui is not interactive, the default is returned.
499 """
499 """
500 resps = [s[s.index('&')+1].lower() for s in choices]
500 resps = [s[s.index('&')+1].lower() for s in choices]
501 while True:
501 while True:
502 r = self.prompt(msg, resps[default])
502 r = self.prompt(msg, resps[default])
503 if r.lower() in resps:
503 if r.lower() in resps:
504 return resps.index(r.lower())
504 return resps.index(r.lower())
505 self.write(_("unrecognized response\n"))
505 self.write(_("unrecognized response\n"))
506
506
507 def getpass(self, prompt=None, default=None):
507 def getpass(self, prompt=None, default=None):
508 if not self.interactive():
508 if not self.interactive():
509 return default
509 return default
510 try:
510 try:
511 return getpass.getpass(prompt or _('password: '))
511 return getpass.getpass(prompt or _('password: '))
512 except EOFError:
512 except EOFError:
513 raise util.Abort(_('response expected'))
513 raise util.Abort(_('response expected'))
514 def status(self, *msg, **opts):
514 def status(self, *msg, **opts):
515 '''write status message to output (if ui.quiet is False)
515 '''write status message to output (if ui.quiet is False)
516
516
517 This adds an output label of "ui.status".
517 This adds an output label of "ui.status".
518 '''
518 '''
519 if not self.quiet:
519 if not self.quiet:
520 opts['label'] = opts.get('label', '') + ' ui.status'
520 opts['label'] = opts.get('label', '') + ' ui.status'
521 self.write(*msg, **opts)
521 self.write(*msg, **opts)
522 def warn(self, *msg, **opts):
522 def warn(self, *msg, **opts):
523 '''write warning message to output (stderr)
523 '''write warning message to output (stderr)
524
524
525 This adds an output label of "ui.warning".
525 This adds an output label of "ui.warning".
526 '''
526 '''
527 opts['label'] = opts.get('label', '') + ' ui.warning'
527 opts['label'] = opts.get('label', '') + ' ui.warning'
528 self.write_err(*msg, **opts)
528 self.write_err(*msg, **opts)
529 def note(self, *msg, **opts):
529 def note(self, *msg, **opts):
530 '''write note to output (if ui.verbose is True)
530 '''write note to output (if ui.verbose is True)
531
531
532 This adds an output label of "ui.note".
532 This adds an output label of "ui.note".
533 '''
533 '''
534 if self.verbose:
534 if self.verbose:
535 opts['label'] = opts.get('label', '') + ' ui.note'
535 opts['label'] = opts.get('label', '') + ' ui.note'
536 self.write(*msg, **opts)
536 self.write(*msg, **opts)
537 def debug(self, *msg, **opts):
537 def debug(self, *msg, **opts):
538 '''write debug message to output (if ui.debugflag is True)
538 '''write debug message to output (if ui.debugflag is True)
539
539
540 This adds an output label of "ui.debug".
540 This adds an output label of "ui.debug".
541 '''
541 '''
542 if self.debugflag:
542 if self.debugflag:
543 opts['label'] = opts.get('label', '') + ' ui.debug'
543 opts['label'] = opts.get('label', '') + ' ui.debug'
544 self.write(*msg, **opts)
544 self.write(*msg, **opts)
545 def edit(self, text, user):
545 def edit(self, text, user):
546 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
546 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
547 text=True)
547 text=True)
548 try:
548 try:
549 f = os.fdopen(fd, "w")
549 f = os.fdopen(fd, "w")
550 f.write(text)
550 f.write(text)
551 f.close()
551 f.close()
552
552
553 editor = self.geteditor()
553 editor = self.geteditor()
554
554
555 util.system("%s \"%s\"" % (editor, name),
555 util.system("%s \"%s\"" % (editor, name),
556 environ={'HGUSER': user},
556 environ={'HGUSER': user},
557 onerr=util.Abort, errprefix=_("edit failed"))
557 onerr=util.Abort, errprefix=_("edit failed"))
558
558
559 f = open(name)
559 f = open(name)
560 t = f.read()
560 t = f.read()
561 f.close()
561 f.close()
562 finally:
562 finally:
563 os.unlink(name)
563 os.unlink(name)
564
564
565 return t
565 return t
566
566
567 def traceback(self, exc=None):
567 def traceback(self, exc=None):
568 '''print exception traceback if traceback printing enabled.
568 '''print exception traceback if traceback printing enabled.
569 only to call in exception handler. returns true if traceback
569 only to call in exception handler. returns true if traceback
570 printed.'''
570 printed.'''
571 if self.tracebackflag:
571 if self.tracebackflag:
572 if exc:
572 if exc:
573 traceback.print_exception(exc[0], exc[1], exc[2])
573 traceback.print_exception(exc[0], exc[1], exc[2])
574 else:
574 else:
575 traceback.print_exc()
575 traceback.print_exc()
576 return self.tracebackflag
576 return self.tracebackflag
577
577
578 def geteditor(self):
578 def geteditor(self):
579 '''return editor to use'''
579 '''return editor to use'''
580 return (os.environ.get("HGEDITOR") or
580 return (os.environ.get("HGEDITOR") or
581 self.config("ui", "editor") or
581 self.config("ui", "editor") or
582 os.environ.get("VISUAL") or
582 os.environ.get("VISUAL") or
583 os.environ.get("EDITOR", "vi"))
583 os.environ.get("EDITOR", "vi"))
584
584
585 def progress(self, topic, pos, item="", unit="", total=None):
585 def progress(self, topic, pos, item="", unit="", total=None):
586 '''show a progress message
586 '''show a progress message
587
587
588 With stock hg, this is simply a debug message that is hidden
588 With stock hg, this is simply a debug message that is hidden
589 by default, but with extensions or GUI tools it may be
589 by default, but with extensions or GUI tools it may be
590 visible. 'topic' is the current operation, 'item' is a
590 visible. 'topic' is the current operation, 'item' is a
591 non-numeric marker of the current position (ie the currently
591 non-numeric marker of the current position (ie the currently
592 in-process file), 'pos' is the current numeric position (ie
592 in-process file), 'pos' is the current numeric position (ie
593 revision, bytes, etc.), unit is a corresponding unit label,
593 revision, bytes, etc.), unit is a corresponding unit label,
594 and total is the highest expected pos.
594 and total is the highest expected pos.
595
595
596 Multiple nested topics may be active at a time.
596 Multiple nested topics may be active at a time.
597
597
598 All topics should be marked closed by setting pos to None at
598 All topics should be marked closed by setting pos to None at
599 termination.
599 termination.
600 '''
600 '''
601
601
602 if pos is None or not self.debugflag:
602 if pos is None or not self.debugflag:
603 return
603 return
604
604
605 if unit:
605 if unit:
606 unit = ' ' + unit
606 unit = ' ' + unit
607 if item:
607 if item:
608 item = ' ' + item
608 item = ' ' + item
609
609
610 if total:
610 if total:
611 pct = 100.0 * pos / total
611 pct = 100.0 * pos / total
612 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
612 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
613 % (topic, item, pos, total, unit, pct))
613 % (topic, item, pos, total, unit, pct))
614 else:
614 else:
615 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
615 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
616
616
617 def log(self, service, message):
617 def log(self, service, message):
618 '''hook for logging facility extensions
618 '''hook for logging facility extensions
619
619
620 service should be a readily-identifiable subsystem, which will
620 service should be a readily-identifiable subsystem, which will
621 allow filtering.
621 allow filtering.
622 message should be a newline-terminated string to log.
622 message should be a newline-terminated string to log.
623 '''
623 '''
624 pass
624 pass
625
625
626 def label(self, msg, label):
626 def label(self, msg, label):
627 '''style msg based on supplied label
627 '''style msg based on supplied label
628
628
629 Like ui.write(), this just returns msg unchanged, but extensions
629 Like ui.write(), this just returns msg unchanged, but extensions
630 and GUI tools can override it to allow styling output without
630 and GUI tools can override it to allow styling output without
631 writing it.
631 writing it.
632
632
633 ui.write(s, 'label') is equivalent to
633 ui.write(s, 'label') is equivalent to
634 ui.write(ui.label(s, 'label')).
634 ui.write(ui.label(s, 'label')).
635 '''
635 '''
636 return msg
636 return msg
General Comments 0
You need to be logged in to leave comments. Login now