##// END OF EJS Templates
bookmarks: change error messages to match those given by 'hg tag' commands
Idan Kamara -
r13911:6bc34094 default
parent child Browse files
Show More
@@ -1,4879 +1,4881 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, bin, nullid, nullrev, short
8 from node import hex, bin, 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, templatefilters
16 import minirst, revset, templatefilters
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 def bad(x, y):
129 def bad(x, y):
130 raise util.Abort("%s: %s" % (x, y))
130 raise util.Abort("%s: %s" % (x, y))
131
131
132 ctx = cmdutil.revsingle(repo, opts.get('rev'))
132 ctx = cmdutil.revsingle(repo, opts.get('rev'))
133 m = cmdutil.match(repo, pats, opts)
133 m = cmdutil.match(repo, pats, opts)
134 m.bad = bad
134 m.bad = bad
135 follow = not opts.get('no_follow')
135 follow = not opts.get('no_follow')
136 for abs in ctx.walk(m):
136 for abs in ctx.walk(m):
137 fctx = ctx[abs]
137 fctx = ctx[abs]
138 if not opts.get('text') and util.binary(fctx.data()):
138 if not opts.get('text') and util.binary(fctx.data()):
139 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
139 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
140 continue
140 continue
141
141
142 lines = fctx.annotate(follow=follow, linenumber=linenumber)
142 lines = fctx.annotate(follow=follow, linenumber=linenumber)
143 pieces = []
143 pieces = []
144
144
145 for f in funcmap:
145 for f in funcmap:
146 l = [f(n) for n, dummy in lines]
146 l = [f(n) for n, dummy in lines]
147 if l:
147 if l:
148 sized = [(x, encoding.colwidth(x)) for x in l]
148 sized = [(x, encoding.colwidth(x)) for x in l]
149 ml = max([w for x, w in sized])
149 ml = max([w for x, w in sized])
150 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
150 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
151
151
152 if pieces:
152 if pieces:
153 for p, l in zip(zip(*pieces), lines):
153 for p, l in zip(zip(*pieces), lines):
154 ui.write("%s: %s" % (" ".join(p), l[1]))
154 ui.write("%s: %s" % (" ".join(p), l[1]))
155
155
156 def archive(ui, repo, dest, **opts):
156 def archive(ui, repo, dest, **opts):
157 '''create an unversioned archive of a repository revision
157 '''create an unversioned archive of a repository revision
158
158
159 By default, the revision used is the parent of the working
159 By default, the revision used is the parent of the working
160 directory; use -r/--rev to specify a different revision.
160 directory; use -r/--rev to specify a different revision.
161
161
162 The archive type is automatically detected based on file
162 The archive type is automatically detected based on file
163 extension (or override using -t/--type).
163 extension (or override using -t/--type).
164
164
165 Valid types are:
165 Valid types are:
166
166
167 :``files``: a directory full of files (default)
167 :``files``: a directory full of files (default)
168 :``tar``: tar archive, uncompressed
168 :``tar``: tar archive, uncompressed
169 :``tbz2``: tar archive, compressed using bzip2
169 :``tbz2``: tar archive, compressed using bzip2
170 :``tgz``: tar archive, compressed using gzip
170 :``tgz``: tar archive, compressed using gzip
171 :``uzip``: zip archive, uncompressed
171 :``uzip``: zip archive, uncompressed
172 :``zip``: zip archive, compressed using deflate
172 :``zip``: zip archive, compressed using deflate
173
173
174 The exact name of the destination archive or directory is given
174 The exact name of the destination archive or directory is given
175 using a format string; see :hg:`help export` for details.
175 using a format string; see :hg:`help export` for details.
176
176
177 Each member added to an archive file has a directory prefix
177 Each member added to an archive file has a directory prefix
178 prepended. Use -p/--prefix to specify a format string for the
178 prepended. Use -p/--prefix to specify a format string for the
179 prefix. The default is the basename of the archive, with suffixes
179 prefix. The default is the basename of the archive, with suffixes
180 removed.
180 removed.
181
181
182 Returns 0 on success.
182 Returns 0 on success.
183 '''
183 '''
184
184
185 ctx = cmdutil.revsingle(repo, opts.get('rev'))
185 ctx = cmdutil.revsingle(repo, opts.get('rev'))
186 if not ctx:
186 if not ctx:
187 raise util.Abort(_('no working directory: please specify a revision'))
187 raise util.Abort(_('no working directory: please specify a revision'))
188 node = ctx.node()
188 node = ctx.node()
189 dest = cmdutil.make_filename(repo, dest, node)
189 dest = cmdutil.make_filename(repo, dest, node)
190 if os.path.realpath(dest) == repo.root:
190 if os.path.realpath(dest) == repo.root:
191 raise util.Abort(_('repository root cannot be destination'))
191 raise util.Abort(_('repository root cannot be destination'))
192
192
193 kind = opts.get('type') or archival.guesskind(dest) or 'files'
193 kind = opts.get('type') or archival.guesskind(dest) or 'files'
194 prefix = opts.get('prefix')
194 prefix = opts.get('prefix')
195
195
196 if dest == '-':
196 if dest == '-':
197 if kind == 'files':
197 if kind == 'files':
198 raise util.Abort(_('cannot archive plain files to stdout'))
198 raise util.Abort(_('cannot archive plain files to stdout'))
199 dest = sys.stdout
199 dest = sys.stdout
200 if not prefix:
200 if not prefix:
201 prefix = os.path.basename(repo.root) + '-%h'
201 prefix = os.path.basename(repo.root) + '-%h'
202
202
203 prefix = cmdutil.make_filename(repo, prefix, node)
203 prefix = cmdutil.make_filename(repo, prefix, node)
204 matchfn = cmdutil.match(repo, [], opts)
204 matchfn = cmdutil.match(repo, [], opts)
205 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
205 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
206 matchfn, prefix, subrepos=opts.get('subrepos'))
206 matchfn, prefix, subrepos=opts.get('subrepos'))
207
207
208 def backout(ui, repo, node=None, rev=None, **opts):
208 def backout(ui, repo, node=None, rev=None, **opts):
209 '''reverse effect of earlier changeset
209 '''reverse effect of earlier changeset
210
210
211 Prepare a new changeset with the effect of REV undone in the
211 Prepare a new changeset with the effect of REV undone in the
212 current working directory.
212 current working directory.
213
213
214 If REV is the parent of the working directory, then this new changeset
214 If REV is the parent of the working directory, then this new changeset
215 is committed automatically. Otherwise, hg needs to merge the
215 is committed automatically. Otherwise, hg needs to merge the
216 changes and the merged result is left uncommitted.
216 changes and the merged result is left uncommitted.
217
217
218 By default, the pending changeset will have one parent,
218 By default, the pending changeset will have one parent,
219 maintaining a linear history. With --merge, the pending changeset
219 maintaining a linear history. With --merge, the pending changeset
220 will instead have two parents: the old parent of the working
220 will instead have two parents: the old parent of the working
221 directory and a new child of REV that simply undoes REV.
221 directory and a new child of REV that simply undoes REV.
222
222
223 Before version 1.7, the behavior without --merge was equivalent to
223 Before version 1.7, the behavior without --merge was equivalent to
224 specifying --merge followed by :hg:`update --clean .` to cancel
224 specifying --merge followed by :hg:`update --clean .` to cancel
225 the merge and leave the child of REV as a head to be merged
225 the merge and leave the child of REV as a head to be merged
226 separately.
226 separately.
227
227
228 See :hg:`help dates` for a list of formats valid for -d/--date.
228 See :hg:`help dates` for a list of formats valid for -d/--date.
229
229
230 Returns 0 on success.
230 Returns 0 on success.
231 '''
231 '''
232 if rev and node:
232 if rev and node:
233 raise util.Abort(_("please specify just one revision"))
233 raise util.Abort(_("please specify just one revision"))
234
234
235 if not rev:
235 if not rev:
236 rev = node
236 rev = node
237
237
238 if not rev:
238 if not rev:
239 raise util.Abort(_("please specify a revision to backout"))
239 raise util.Abort(_("please specify a revision to backout"))
240
240
241 date = opts.get('date')
241 date = opts.get('date')
242 if date:
242 if date:
243 opts['date'] = util.parsedate(date)
243 opts['date'] = util.parsedate(date)
244
244
245 cmdutil.bail_if_changed(repo)
245 cmdutil.bail_if_changed(repo)
246 node = cmdutil.revsingle(repo, rev).node()
246 node = cmdutil.revsingle(repo, rev).node()
247
247
248 op1, op2 = repo.dirstate.parents()
248 op1, op2 = repo.dirstate.parents()
249 a = repo.changelog.ancestor(op1, node)
249 a = repo.changelog.ancestor(op1, node)
250 if a != node:
250 if a != node:
251 raise util.Abort(_('cannot backout change on a different branch'))
251 raise util.Abort(_('cannot backout change on a different branch'))
252
252
253 p1, p2 = repo.changelog.parents(node)
253 p1, p2 = repo.changelog.parents(node)
254 if p1 == nullid:
254 if p1 == nullid:
255 raise util.Abort(_('cannot backout a change with no parents'))
255 raise util.Abort(_('cannot backout a change with no parents'))
256 if p2 != nullid:
256 if p2 != nullid:
257 if not opts.get('parent'):
257 if not opts.get('parent'):
258 raise util.Abort(_('cannot backout a merge changeset without '
258 raise util.Abort(_('cannot backout a merge changeset without '
259 '--parent'))
259 '--parent'))
260 p = repo.lookup(opts['parent'])
260 p = repo.lookup(opts['parent'])
261 if p not in (p1, p2):
261 if p not in (p1, p2):
262 raise util.Abort(_('%s is not a parent of %s') %
262 raise util.Abort(_('%s is not a parent of %s') %
263 (short(p), short(node)))
263 (short(p), short(node)))
264 parent = p
264 parent = p
265 else:
265 else:
266 if opts.get('parent'):
266 if opts.get('parent'):
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
268 parent = p1
268 parent = p1
269
269
270 # the backout should appear on the same branch
270 # the backout should appear on the same branch
271 branch = repo.dirstate.branch()
271 branch = repo.dirstate.branch()
272 hg.clean(repo, node, show_stats=False)
272 hg.clean(repo, node, show_stats=False)
273 repo.dirstate.setbranch(branch)
273 repo.dirstate.setbranch(branch)
274 revert_opts = opts.copy()
274 revert_opts = opts.copy()
275 revert_opts['date'] = None
275 revert_opts['date'] = None
276 revert_opts['all'] = True
276 revert_opts['all'] = True
277 revert_opts['rev'] = hex(parent)
277 revert_opts['rev'] = hex(parent)
278 revert_opts['no_backup'] = None
278 revert_opts['no_backup'] = None
279 revert(ui, repo, **revert_opts)
279 revert(ui, repo, **revert_opts)
280 if not opts.get('merge') and op1 != node:
280 if not opts.get('merge') and op1 != node:
281 try:
281 try:
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
283 return hg.update(repo, op1)
283 return hg.update(repo, op1)
284 finally:
284 finally:
285 ui.setconfig('ui', 'forcemerge', '')
285 ui.setconfig('ui', 'forcemerge', '')
286
286
287 commit_opts = opts.copy()
287 commit_opts = opts.copy()
288 commit_opts['addremove'] = False
288 commit_opts['addremove'] = False
289 if not commit_opts['message'] and not commit_opts['logfile']:
289 if not commit_opts['message'] and not commit_opts['logfile']:
290 # we don't translate commit messages
290 # we don't translate commit messages
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
292 commit_opts['force_editor'] = True
292 commit_opts['force_editor'] = True
293 commit(ui, repo, **commit_opts)
293 commit(ui, repo, **commit_opts)
294 def nice(node):
294 def nice(node):
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
296 ui.status(_('changeset %s backs out changeset %s\n') %
296 ui.status(_('changeset %s backs out changeset %s\n') %
297 (nice(repo.changelog.tip()), nice(node)))
297 (nice(repo.changelog.tip()), nice(node)))
298 if opts.get('merge') and op1 != node:
298 if opts.get('merge') and op1 != node:
299 hg.clean(repo, op1, show_stats=False)
299 hg.clean(repo, op1, show_stats=False)
300 ui.status(_('merging with changeset %s\n')
300 ui.status(_('merging with changeset %s\n')
301 % nice(repo.changelog.tip()))
301 % nice(repo.changelog.tip()))
302 try:
302 try:
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
304 return hg.merge(repo, hex(repo.changelog.tip()))
304 return hg.merge(repo, hex(repo.changelog.tip()))
305 finally:
305 finally:
306 ui.setconfig('ui', 'forcemerge', '')
306 ui.setconfig('ui', 'forcemerge', '')
307 return 0
307 return 0
308
308
309 def bisect(ui, repo, rev=None, extra=None, command=None,
309 def bisect(ui, repo, rev=None, extra=None, command=None,
310 reset=None, good=None, bad=None, skip=None, extend=None,
310 reset=None, good=None, bad=None, skip=None, extend=None,
311 noupdate=None):
311 noupdate=None):
312 """subdivision search of changesets
312 """subdivision search of changesets
313
313
314 This command helps to find changesets which introduce problems. To
314 This command helps to find changesets which introduce problems. To
315 use, mark the earliest changeset you know exhibits the problem as
315 use, mark the earliest changeset you know exhibits the problem as
316 bad, then mark the latest changeset which is free from the problem
316 bad, then mark the latest changeset which is free from the problem
317 as good. Bisect will update your working directory to a revision
317 as good. Bisect will update your working directory to a revision
318 for testing (unless the -U/--noupdate option is specified). Once
318 for testing (unless the -U/--noupdate option is specified). Once
319 you have performed tests, mark the working directory as good or
319 you have performed tests, mark the working directory as good or
320 bad, and bisect will either update to another candidate changeset
320 bad, and bisect will either update to another candidate changeset
321 or announce that it has found the bad revision.
321 or announce that it has found the bad revision.
322
322
323 As a shortcut, you can also use the revision argument to mark a
323 As a shortcut, you can also use the revision argument to mark a
324 revision as good or bad without checking it out first.
324 revision as good or bad without checking it out first.
325
325
326 If you supply a command, it will be used for automatic bisection.
326 If you supply a command, it will be used for automatic bisection.
327 Its exit status will be used to mark revisions as good or bad:
327 Its exit status will be used to mark revisions as good or bad:
328 status 0 means good, 125 means to skip the revision, 127
328 status 0 means good, 125 means to skip the revision, 127
329 (command not found) will abort the bisection, and any other
329 (command not found) will abort the bisection, and any other
330 non-zero exit status means the revision is bad.
330 non-zero exit status means the revision is bad.
331
331
332 Returns 0 on success.
332 Returns 0 on success.
333 """
333 """
334 def extendbisectrange(nodes, good):
334 def extendbisectrange(nodes, good):
335 # bisect is incomplete when it ends on a merge node and
335 # bisect is incomplete when it ends on a merge node and
336 # one of the parent was not checked.
336 # one of the parent was not checked.
337 parents = repo[nodes[0]].parents()
337 parents = repo[nodes[0]].parents()
338 if len(parents) > 1:
338 if len(parents) > 1:
339 side = good and state['bad'] or state['good']
339 side = good and state['bad'] or state['good']
340 num = len(set(i.node() for i in parents) & set(side))
340 num = len(set(i.node() for i in parents) & set(side))
341 if num == 1:
341 if num == 1:
342 return parents[0].ancestor(parents[1])
342 return parents[0].ancestor(parents[1])
343 return None
343 return None
344
344
345 def print_result(nodes, good):
345 def print_result(nodes, good):
346 displayer = cmdutil.show_changeset(ui, repo, {})
346 displayer = cmdutil.show_changeset(ui, repo, {})
347 if len(nodes) == 1:
347 if len(nodes) == 1:
348 # narrowed it down to a single revision
348 # narrowed it down to a single revision
349 if good:
349 if good:
350 ui.write(_("The first good revision is:\n"))
350 ui.write(_("The first good revision is:\n"))
351 else:
351 else:
352 ui.write(_("The first bad revision is:\n"))
352 ui.write(_("The first bad revision is:\n"))
353 displayer.show(repo[nodes[0]])
353 displayer.show(repo[nodes[0]])
354 parents = repo[nodes[0]].parents()
354 parents = repo[nodes[0]].parents()
355 extendnode = extendbisectrange(nodes, good)
355 extendnode = extendbisectrange(nodes, good)
356 if extendnode is not None:
356 if extendnode is not None:
357 ui.write(_('Not all ancestors of this changeset have been'
357 ui.write(_('Not all ancestors of this changeset have been'
358 ' checked.\nUse bisect --extend to continue the '
358 ' checked.\nUse bisect --extend to continue the '
359 'bisection from\nthe common ancestor, %s.\n')
359 'bisection from\nthe common ancestor, %s.\n')
360 % short(extendnode.node()))
360 % short(extendnode.node()))
361 else:
361 else:
362 # multiple possible revisions
362 # multiple possible revisions
363 if good:
363 if good:
364 ui.write(_("Due to skipped revisions, the first "
364 ui.write(_("Due to skipped revisions, the first "
365 "good revision could be any of:\n"))
365 "good revision could be any of:\n"))
366 else:
366 else:
367 ui.write(_("Due to skipped revisions, the first "
367 ui.write(_("Due to skipped revisions, the first "
368 "bad revision could be any of:\n"))
368 "bad revision could be any of:\n"))
369 for n in nodes:
369 for n in nodes:
370 displayer.show(repo[n])
370 displayer.show(repo[n])
371 displayer.close()
371 displayer.close()
372
372
373 def check_state(state, interactive=True):
373 def check_state(state, interactive=True):
374 if not state['good'] or not state['bad']:
374 if not state['good'] or not state['bad']:
375 if (good or bad or skip or reset) and interactive:
375 if (good or bad or skip or reset) and interactive:
376 return
376 return
377 if not state['good']:
377 if not state['good']:
378 raise util.Abort(_('cannot bisect (no known good revisions)'))
378 raise util.Abort(_('cannot bisect (no known good revisions)'))
379 else:
379 else:
380 raise util.Abort(_('cannot bisect (no known bad revisions)'))
380 raise util.Abort(_('cannot bisect (no known bad revisions)'))
381 return True
381 return True
382
382
383 # backward compatibility
383 # backward compatibility
384 if rev in "good bad reset init".split():
384 if rev in "good bad reset init".split():
385 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
385 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
386 cmd, rev, extra = rev, extra, None
386 cmd, rev, extra = rev, extra, None
387 if cmd == "good":
387 if cmd == "good":
388 good = True
388 good = True
389 elif cmd == "bad":
389 elif cmd == "bad":
390 bad = True
390 bad = True
391 else:
391 else:
392 reset = True
392 reset = True
393 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
393 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
394 raise util.Abort(_('incompatible arguments'))
394 raise util.Abort(_('incompatible arguments'))
395
395
396 if reset:
396 if reset:
397 p = repo.join("bisect.state")
397 p = repo.join("bisect.state")
398 if os.path.exists(p):
398 if os.path.exists(p):
399 os.unlink(p)
399 os.unlink(p)
400 return
400 return
401
401
402 state = hbisect.load_state(repo)
402 state = hbisect.load_state(repo)
403
403
404 if command:
404 if command:
405 changesets = 1
405 changesets = 1
406 try:
406 try:
407 while changesets:
407 while changesets:
408 # update state
408 # update state
409 status = util.system(command)
409 status = util.system(command)
410 if status == 125:
410 if status == 125:
411 transition = "skip"
411 transition = "skip"
412 elif status == 0:
412 elif status == 0:
413 transition = "good"
413 transition = "good"
414 # status < 0 means process was killed
414 # status < 0 means process was killed
415 elif status == 127:
415 elif status == 127:
416 raise util.Abort(_("failed to execute %s") % command)
416 raise util.Abort(_("failed to execute %s") % command)
417 elif status < 0:
417 elif status < 0:
418 raise util.Abort(_("%s killed") % command)
418 raise util.Abort(_("%s killed") % command)
419 else:
419 else:
420 transition = "bad"
420 transition = "bad"
421 ctx = cmdutil.revsingle(repo, rev)
421 ctx = cmdutil.revsingle(repo, rev)
422 rev = None # clear for future iterations
422 rev = None # clear for future iterations
423 state[transition].append(ctx.node())
423 state[transition].append(ctx.node())
424 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
424 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
425 check_state(state, interactive=False)
425 check_state(state, interactive=False)
426 # bisect
426 # bisect
427 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
427 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
428 # update to next check
428 # update to next check
429 cmdutil.bail_if_changed(repo)
429 cmdutil.bail_if_changed(repo)
430 hg.clean(repo, nodes[0], show_stats=False)
430 hg.clean(repo, nodes[0], show_stats=False)
431 finally:
431 finally:
432 hbisect.save_state(repo, state)
432 hbisect.save_state(repo, state)
433 print_result(nodes, good)
433 print_result(nodes, good)
434 return
434 return
435
435
436 # update state
436 # update state
437
437
438 if rev:
438 if rev:
439 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
439 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
440 else:
440 else:
441 nodes = [repo.lookup('.')]
441 nodes = [repo.lookup('.')]
442
442
443 if good or bad or skip:
443 if good or bad or skip:
444 if good:
444 if good:
445 state['good'] += nodes
445 state['good'] += nodes
446 elif bad:
446 elif bad:
447 state['bad'] += nodes
447 state['bad'] += nodes
448 elif skip:
448 elif skip:
449 state['skip'] += nodes
449 state['skip'] += nodes
450 hbisect.save_state(repo, state)
450 hbisect.save_state(repo, state)
451
451
452 if not check_state(state):
452 if not check_state(state):
453 return
453 return
454
454
455 # actually bisect
455 # actually bisect
456 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
456 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
457 if extend:
457 if extend:
458 if not changesets:
458 if not changesets:
459 extendnode = extendbisectrange(nodes, good)
459 extendnode = extendbisectrange(nodes, good)
460 if extendnode is not None:
460 if extendnode is not None:
461 ui.write(_("Extending search to changeset %d:%s\n"
461 ui.write(_("Extending search to changeset %d:%s\n"
462 % (extendnode.rev(), short(extendnode.node()))))
462 % (extendnode.rev(), short(extendnode.node()))))
463 if noupdate:
463 if noupdate:
464 return
464 return
465 cmdutil.bail_if_changed(repo)
465 cmdutil.bail_if_changed(repo)
466 return hg.clean(repo, extendnode.node())
466 return hg.clean(repo, extendnode.node())
467 raise util.Abort(_("nothing to extend"))
467 raise util.Abort(_("nothing to extend"))
468
468
469 if changesets == 0:
469 if changesets == 0:
470 print_result(nodes, good)
470 print_result(nodes, good)
471 else:
471 else:
472 assert len(nodes) == 1 # only a single node can be tested next
472 assert len(nodes) == 1 # only a single node can be tested next
473 node = nodes[0]
473 node = nodes[0]
474 # compute the approximate number of remaining tests
474 # compute the approximate number of remaining tests
475 tests, size = 0, 2
475 tests, size = 0, 2
476 while size <= changesets:
476 while size <= changesets:
477 tests, size = tests + 1, size * 2
477 tests, size = tests + 1, size * 2
478 rev = repo.changelog.rev(node)
478 rev = repo.changelog.rev(node)
479 ui.write(_("Testing changeset %d:%s "
479 ui.write(_("Testing changeset %d:%s "
480 "(%d changesets remaining, ~%d tests)\n")
480 "(%d changesets remaining, ~%d tests)\n")
481 % (rev, short(node), changesets, tests))
481 % (rev, short(node), changesets, tests))
482 if not noupdate:
482 if not noupdate:
483 cmdutil.bail_if_changed(repo)
483 cmdutil.bail_if_changed(repo)
484 return hg.clean(repo, node)
484 return hg.clean(repo, node)
485
485
486 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
486 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
487 '''track a line of development with movable markers
487 '''track a line of development with movable markers
488
488
489 Bookmarks are pointers to certain commits that move when
489 Bookmarks are pointers to certain commits that move when
490 committing. Bookmarks are local. They can be renamed, copied and
490 committing. Bookmarks are local. They can be renamed, copied and
491 deleted. It is possible to use bookmark names in :hg:`merge` and
491 deleted. It is possible to use bookmark names in :hg:`merge` and
492 :hg:`update` to merge and update respectively to a given bookmark.
492 :hg:`update` to merge and update respectively to a given bookmark.
493
493
494 You can use :hg:`bookmark NAME` to set a bookmark on the working
494 You can use :hg:`bookmark NAME` to set a bookmark on the working
495 directory's parent revision with the given name. If you specify
495 directory's parent revision with the given name. If you specify
496 a revision using -r REV (where REV may be an existing bookmark),
496 a revision using -r REV (where REV may be an existing bookmark),
497 the bookmark is assigned to that revision.
497 the bookmark is assigned to that revision.
498
498
499 Bookmarks can be pushed and pulled between repositories (see :hg:`help
499 Bookmarks can be pushed and pulled between repositories (see :hg:`help
500 push` and :hg:`help pull`). This requires both the local and remote
500 push` and :hg:`help pull`). This requires both the local and remote
501 repositories to support bookmarks. For versions prior to 1.8, this means
501 repositories to support bookmarks. For versions prior to 1.8, this means
502 the bookmarks extension must be enabled.
502 the bookmarks extension must be enabled.
503 '''
503 '''
504 hexfn = ui.debugflag and hex or short
504 hexfn = ui.debugflag and hex or short
505 marks = repo._bookmarks
505 marks = repo._bookmarks
506 cur = repo.changectx('.').node()
506 cur = repo.changectx('.').node()
507
507
508 if rename:
508 if rename:
509 if rename not in marks:
509 if rename not in marks:
510 raise util.Abort(_("a bookmark of this name does not exist"))
510 raise util.Abort(_("bookmark '%s' does not exist") % rename)
511 if mark in marks and not force:
511 if mark in marks and not force:
512 raise util.Abort(_("a bookmark of the same name already exists"))
512 raise util.Abort(_("bookmark '%s' already exists "
513 "(use -f to force)") % mark)
513 if mark is None:
514 if mark is None:
514 raise util.Abort(_("new bookmark name required"))
515 raise util.Abort(_("new bookmark name required"))
515 marks[mark] = marks[rename]
516 marks[mark] = marks[rename]
516 if repo._bookmarkcurrent == rename:
517 if repo._bookmarkcurrent == rename:
517 bookmarks.setcurrent(repo, mark)
518 bookmarks.setcurrent(repo, mark)
518 del marks[rename]
519 del marks[rename]
519 bookmarks.write(repo)
520 bookmarks.write(repo)
520 return
521 return
521
522
522 if delete:
523 if delete:
523 if mark is None:
524 if mark is None:
524 raise util.Abort(_("bookmark name required"))
525 raise util.Abort(_("bookmark name required"))
525 if mark not in marks:
526 if mark not in marks:
526 raise util.Abort(_("a bookmark of this name does not exist"))
527 raise util.Abort(_("bookmark '%s' does not exist") % mark)
527 if mark == repo._bookmarkcurrent:
528 if mark == repo._bookmarkcurrent:
528 bookmarks.setcurrent(repo, None)
529 bookmarks.setcurrent(repo, None)
529 del marks[mark]
530 del marks[mark]
530 bookmarks.write(repo)
531 bookmarks.write(repo)
531 return
532 return
532
533
533 if mark is not None:
534 if mark is not None:
534 if "\n" in mark:
535 if "\n" in mark:
535 raise util.Abort(_("bookmark name cannot contain newlines"))
536 raise util.Abort(_("bookmark name cannot contain newlines"))
536 mark = mark.strip()
537 mark = mark.strip()
537 if not mark:
538 if not mark:
538 raise util.Abort(_("bookmark names cannot consist entirely of "
539 raise util.Abort(_("bookmark names cannot consist entirely of "
539 "whitespace"))
540 "whitespace"))
540 if mark in marks and not force:
541 if mark in marks and not force:
541 raise util.Abort(_("a bookmark of the same name already exists"))
542 raise util.Abort(_("bookmark '%s' already exists "
543 "(use -f to force)") % mark)
542 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
544 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
543 and not force):
545 and not force):
544 raise util.Abort(
546 raise util.Abort(
545 _("a bookmark cannot have the name of an existing branch"))
547 _("a bookmark cannot have the name of an existing branch"))
546 if rev:
548 if rev:
547 marks[mark] = repo.lookup(rev)
549 marks[mark] = repo.lookup(rev)
548 else:
550 else:
549 marks[mark] = repo.changectx('.').node()
551 marks[mark] = repo.changectx('.').node()
550 if repo.changectx('.').node() == marks[mark]:
552 if repo.changectx('.').node() == marks[mark]:
551 bookmarks.setcurrent(repo, mark)
553 bookmarks.setcurrent(repo, mark)
552 bookmarks.write(repo)
554 bookmarks.write(repo)
553 return
555 return
554
556
555 if mark is None:
557 if mark is None:
556 if rev:
558 if rev:
557 raise util.Abort(_("bookmark name required"))
559 raise util.Abort(_("bookmark name required"))
558 if len(marks) == 0:
560 if len(marks) == 0:
559 ui.status(_("no bookmarks set\n"))
561 ui.status(_("no bookmarks set\n"))
560 else:
562 else:
561 for bmark, n in sorted(marks.iteritems()):
563 for bmark, n in sorted(marks.iteritems()):
562 current = repo._bookmarkcurrent
564 current = repo._bookmarkcurrent
563 if bmark == current and n == cur:
565 if bmark == current and n == cur:
564 prefix, label = '*', 'bookmarks.current'
566 prefix, label = '*', 'bookmarks.current'
565 else:
567 else:
566 prefix, label = ' ', ''
568 prefix, label = ' ', ''
567
569
568 if ui.quiet:
570 if ui.quiet:
569 ui.write("%s\n" % bmark, label=label)
571 ui.write("%s\n" % bmark, label=label)
570 else:
572 else:
571 ui.write(" %s %-25s %d:%s\n" % (
573 ui.write(" %s %-25s %d:%s\n" % (
572 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
574 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
573 label=label)
575 label=label)
574 return
576 return
575
577
576 def branch(ui, repo, label=None, **opts):
578 def branch(ui, repo, label=None, **opts):
577 """set or show the current branch name
579 """set or show the current branch name
578
580
579 With no argument, show the current branch name. With one argument,
581 With no argument, show the current branch name. With one argument,
580 set the working directory branch name (the branch will not exist
582 set the working directory branch name (the branch will not exist
581 in the repository until the next commit). Standard practice
583 in the repository until the next commit). Standard practice
582 recommends that primary development take place on the 'default'
584 recommends that primary development take place on the 'default'
583 branch.
585 branch.
584
586
585 Unless -f/--force is specified, branch will not let you set a
587 Unless -f/--force is specified, branch will not let you set a
586 branch name that already exists, even if it's inactive.
588 branch name that already exists, even if it's inactive.
587
589
588 Use -C/--clean to reset the working directory branch to that of
590 Use -C/--clean to reset the working directory branch to that of
589 the parent of the working directory, negating a previous branch
591 the parent of the working directory, negating a previous branch
590 change.
592 change.
591
593
592 Use the command :hg:`update` to switch to an existing branch. Use
594 Use the command :hg:`update` to switch to an existing branch. Use
593 :hg:`commit --close-branch` to mark this branch as closed.
595 :hg:`commit --close-branch` to mark this branch as closed.
594
596
595 Returns 0 on success.
597 Returns 0 on success.
596 """
598 """
597
599
598 if opts.get('clean'):
600 if opts.get('clean'):
599 label = repo[None].p1().branch()
601 label = repo[None].p1().branch()
600 repo.dirstate.setbranch(label)
602 repo.dirstate.setbranch(label)
601 ui.status(_('reset working directory to branch %s\n') % label)
603 ui.status(_('reset working directory to branch %s\n') % label)
602 elif label:
604 elif label:
603 if not opts.get('force') and label in repo.branchtags():
605 if not opts.get('force') and label in repo.branchtags():
604 if label not in [p.branch() for p in repo.parents()]:
606 if label not in [p.branch() for p in repo.parents()]:
605 raise util.Abort(_('a branch of the same name already exists'
607 raise util.Abort(_('a branch of the same name already exists'
606 " (use 'hg update' to switch to it)"))
608 " (use 'hg update' to switch to it)"))
607 repo.dirstate.setbranch(label)
609 repo.dirstate.setbranch(label)
608 ui.status(_('marked working directory as branch %s\n') % label)
610 ui.status(_('marked working directory as branch %s\n') % label)
609 else:
611 else:
610 ui.write("%s\n" % repo.dirstate.branch())
612 ui.write("%s\n" % repo.dirstate.branch())
611
613
612 def branches(ui, repo, active=False, closed=False):
614 def branches(ui, repo, active=False, closed=False):
613 """list repository named branches
615 """list repository named branches
614
616
615 List the repository's named branches, indicating which ones are
617 List the repository's named branches, indicating which ones are
616 inactive. If -c/--closed is specified, also list branches which have
618 inactive. If -c/--closed is specified, also list branches which have
617 been marked closed (see :hg:`commit --close-branch`).
619 been marked closed (see :hg:`commit --close-branch`).
618
620
619 If -a/--active is specified, only show active branches. A branch
621 If -a/--active is specified, only show active branches. A branch
620 is considered active if it contains repository heads.
622 is considered active if it contains repository heads.
621
623
622 Use the command :hg:`update` to switch to an existing branch.
624 Use the command :hg:`update` to switch to an existing branch.
623
625
624 Returns 0.
626 Returns 0.
625 """
627 """
626
628
627 hexfunc = ui.debugflag and hex or short
629 hexfunc = ui.debugflag and hex or short
628 activebranches = [repo[n].branch() for n in repo.heads()]
630 activebranches = [repo[n].branch() for n in repo.heads()]
629 def testactive(tag, node):
631 def testactive(tag, node):
630 realhead = tag in activebranches
632 realhead = tag in activebranches
631 open = node in repo.branchheads(tag, closed=False)
633 open = node in repo.branchheads(tag, closed=False)
632 return realhead and open
634 return realhead and open
633 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
635 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
634 for tag, node in repo.branchtags().items()],
636 for tag, node in repo.branchtags().items()],
635 reverse=True)
637 reverse=True)
636
638
637 for isactive, node, tag in branches:
639 for isactive, node, tag in branches:
638 if (not active) or isactive:
640 if (not active) or isactive:
639 if ui.quiet:
641 if ui.quiet:
640 ui.write("%s\n" % tag)
642 ui.write("%s\n" % tag)
641 else:
643 else:
642 hn = repo.lookup(node)
644 hn = repo.lookup(node)
643 if isactive:
645 if isactive:
644 label = 'branches.active'
646 label = 'branches.active'
645 notice = ''
647 notice = ''
646 elif hn not in repo.branchheads(tag, closed=False):
648 elif hn not in repo.branchheads(tag, closed=False):
647 if not closed:
649 if not closed:
648 continue
650 continue
649 label = 'branches.closed'
651 label = 'branches.closed'
650 notice = _(' (closed)')
652 notice = _(' (closed)')
651 else:
653 else:
652 label = 'branches.inactive'
654 label = 'branches.inactive'
653 notice = _(' (inactive)')
655 notice = _(' (inactive)')
654 if tag == repo.dirstate.branch():
656 if tag == repo.dirstate.branch():
655 label = 'branches.current'
657 label = 'branches.current'
656 rev = str(node).rjust(31 - encoding.colwidth(tag))
658 rev = str(node).rjust(31 - encoding.colwidth(tag))
657 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
659 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
658 tag = ui.label(tag, label)
660 tag = ui.label(tag, label)
659 ui.write("%s %s%s\n" % (tag, rev, notice))
661 ui.write("%s %s%s\n" % (tag, rev, notice))
660
662
661 def bundle(ui, repo, fname, dest=None, **opts):
663 def bundle(ui, repo, fname, dest=None, **opts):
662 """create a changegroup file
664 """create a changegroup file
663
665
664 Generate a compressed changegroup file collecting changesets not
666 Generate a compressed changegroup file collecting changesets not
665 known to be in another repository.
667 known to be in another repository.
666
668
667 If you omit the destination repository, then hg assumes the
669 If you omit the destination repository, then hg assumes the
668 destination will have all the nodes you specify with --base
670 destination will have all the nodes you specify with --base
669 parameters. To create a bundle containing all changesets, use
671 parameters. To create a bundle containing all changesets, use
670 -a/--all (or --base null).
672 -a/--all (or --base null).
671
673
672 You can change compression method with the -t/--type option.
674 You can change compression method with the -t/--type option.
673 The available compression methods are: none, bzip2, and
675 The available compression methods are: none, bzip2, and
674 gzip (by default, bundles are compressed using bzip2).
676 gzip (by default, bundles are compressed using bzip2).
675
677
676 The bundle file can then be transferred using conventional means
678 The bundle file can then be transferred using conventional means
677 and applied to another repository with the unbundle or pull
679 and applied to another repository with the unbundle or pull
678 command. This is useful when direct push and pull are not
680 command. This is useful when direct push and pull are not
679 available or when exporting an entire repository is undesirable.
681 available or when exporting an entire repository is undesirable.
680
682
681 Applying bundles preserves all changeset contents including
683 Applying bundles preserves all changeset contents including
682 permissions, copy/rename information, and revision history.
684 permissions, copy/rename information, and revision history.
683
685
684 Returns 0 on success, 1 if no changes found.
686 Returns 0 on success, 1 if no changes found.
685 """
687 """
686 revs = None
688 revs = None
687 if 'rev' in opts:
689 if 'rev' in opts:
688 revs = cmdutil.revrange(repo, opts['rev'])
690 revs = cmdutil.revrange(repo, opts['rev'])
689
691
690 if opts.get('all'):
692 if opts.get('all'):
691 base = ['null']
693 base = ['null']
692 else:
694 else:
693 base = cmdutil.revrange(repo, opts.get('base'))
695 base = cmdutil.revrange(repo, opts.get('base'))
694 if base:
696 if base:
695 if dest:
697 if dest:
696 raise util.Abort(_("--base is incompatible with specifying "
698 raise util.Abort(_("--base is incompatible with specifying "
697 "a destination"))
699 "a destination"))
698 base = [repo.lookup(rev) for rev in base]
700 base = [repo.lookup(rev) for rev in base]
699 # create the right base
701 # create the right base
700 # XXX: nodesbetween / changegroup* should be "fixed" instead
702 # XXX: nodesbetween / changegroup* should be "fixed" instead
701 o = []
703 o = []
702 has = set((nullid,))
704 has = set((nullid,))
703 for n in base:
705 for n in base:
704 has.update(repo.changelog.reachable(n))
706 has.update(repo.changelog.reachable(n))
705 if revs:
707 if revs:
706 revs = [repo.lookup(rev) for rev in revs]
708 revs = [repo.lookup(rev) for rev in revs]
707 visit = revs[:]
709 visit = revs[:]
708 has.difference_update(visit)
710 has.difference_update(visit)
709 else:
711 else:
710 visit = repo.changelog.heads()
712 visit = repo.changelog.heads()
711 seen = {}
713 seen = {}
712 while visit:
714 while visit:
713 n = visit.pop(0)
715 n = visit.pop(0)
714 parents = [p for p in repo.changelog.parents(n) if p not in has]
716 parents = [p for p in repo.changelog.parents(n) if p not in has]
715 if len(parents) == 0:
717 if len(parents) == 0:
716 if n not in has:
718 if n not in has:
717 o.append(n)
719 o.append(n)
718 else:
720 else:
719 for p in parents:
721 for p in parents:
720 if p not in seen:
722 if p not in seen:
721 seen[p] = 1
723 seen[p] = 1
722 visit.append(p)
724 visit.append(p)
723 else:
725 else:
724 dest = ui.expandpath(dest or 'default-push', dest or 'default')
726 dest = ui.expandpath(dest or 'default-push', dest or 'default')
725 dest, branches = hg.parseurl(dest, opts.get('branch'))
727 dest, branches = hg.parseurl(dest, opts.get('branch'))
726 other = hg.repository(hg.remoteui(repo, opts), dest)
728 other = hg.repository(hg.remoteui(repo, opts), dest)
727 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
729 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
728 if revs:
730 if revs:
729 revs = [repo.lookup(rev) for rev in revs]
731 revs = [repo.lookup(rev) for rev in revs]
730 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
732 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
731
733
732 if not o:
734 if not o:
733 ui.status(_("no changes found\n"))
735 ui.status(_("no changes found\n"))
734 return 1
736 return 1
735
737
736 if revs:
738 if revs:
737 cg = repo.changegroupsubset(o, revs, 'bundle')
739 cg = repo.changegroupsubset(o, revs, 'bundle')
738 else:
740 else:
739 cg = repo.changegroup(o, 'bundle')
741 cg = repo.changegroup(o, 'bundle')
740
742
741 bundletype = opts.get('type', 'bzip2').lower()
743 bundletype = opts.get('type', 'bzip2').lower()
742 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
744 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
743 bundletype = btypes.get(bundletype)
745 bundletype = btypes.get(bundletype)
744 if bundletype not in changegroup.bundletypes:
746 if bundletype not in changegroup.bundletypes:
745 raise util.Abort(_('unknown bundle type specified with --type'))
747 raise util.Abort(_('unknown bundle type specified with --type'))
746
748
747 changegroup.writebundle(cg, fname, bundletype)
749 changegroup.writebundle(cg, fname, bundletype)
748
750
749 def cat(ui, repo, file1, *pats, **opts):
751 def cat(ui, repo, file1, *pats, **opts):
750 """output the current or given revision of files
752 """output the current or given revision of files
751
753
752 Print the specified files as they were at the given revision. If
754 Print the specified files as they were at the given revision. If
753 no revision is given, the parent of the working directory is used,
755 no revision is given, the parent of the working directory is used,
754 or tip if no revision is checked out.
756 or tip if no revision is checked out.
755
757
756 Output may be to a file, in which case the name of the file is
758 Output may be to a file, in which case the name of the file is
757 given using a format string. The formatting rules are the same as
759 given using a format string. The formatting rules are the same as
758 for the export command, with the following additions:
760 for the export command, with the following additions:
759
761
760 :``%s``: basename of file being printed
762 :``%s``: basename of file being printed
761 :``%d``: dirname of file being printed, or '.' if in repository root
763 :``%d``: dirname of file being printed, or '.' if in repository root
762 :``%p``: root-relative path name of file being printed
764 :``%p``: root-relative path name of file being printed
763
765
764 Returns 0 on success.
766 Returns 0 on success.
765 """
767 """
766 ctx = cmdutil.revsingle(repo, opts.get('rev'))
768 ctx = cmdutil.revsingle(repo, opts.get('rev'))
767 err = 1
769 err = 1
768 m = cmdutil.match(repo, (file1,) + pats, opts)
770 m = cmdutil.match(repo, (file1,) + pats, opts)
769 for abs in ctx.walk(m):
771 for abs in ctx.walk(m):
770 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
772 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
771 data = ctx[abs].data()
773 data = ctx[abs].data()
772 if opts.get('decode'):
774 if opts.get('decode'):
773 data = repo.wwritedata(abs, data)
775 data = repo.wwritedata(abs, data)
774 fp.write(data)
776 fp.write(data)
775 fp.close()
777 fp.close()
776 err = 0
778 err = 0
777 return err
779 return err
778
780
779 def clone(ui, source, dest=None, **opts):
781 def clone(ui, source, dest=None, **opts):
780 """make a copy of an existing repository
782 """make a copy of an existing repository
781
783
782 Create a copy of an existing repository in a new directory.
784 Create a copy of an existing repository in a new directory.
783
785
784 If no destination directory name is specified, it defaults to the
786 If no destination directory name is specified, it defaults to the
785 basename of the source.
787 basename of the source.
786
788
787 The location of the source is added to the new repository's
789 The location of the source is added to the new repository's
788 ``.hg/hgrc`` file, as the default to be used for future pulls.
790 ``.hg/hgrc`` file, as the default to be used for future pulls.
789
791
790 See :hg:`help urls` for valid source format details.
792 See :hg:`help urls` for valid source format details.
791
793
792 It is possible to specify an ``ssh://`` URL as the destination, but no
794 It is possible to specify an ``ssh://`` URL as the destination, but no
793 ``.hg/hgrc`` and working directory will be created on the remote side.
795 ``.hg/hgrc`` and working directory will be created on the remote side.
794 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
796 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
795
797
796 A set of changesets (tags, or branch names) to pull may be specified
798 A set of changesets (tags, or branch names) to pull may be specified
797 by listing each changeset (tag, or branch name) with -r/--rev.
799 by listing each changeset (tag, or branch name) with -r/--rev.
798 If -r/--rev is used, the cloned repository will contain only a subset
800 If -r/--rev is used, the cloned repository will contain only a subset
799 of the changesets of the source repository. Only the set of changesets
801 of the changesets of the source repository. Only the set of changesets
800 defined by all -r/--rev options (including all their ancestors)
802 defined by all -r/--rev options (including all their ancestors)
801 will be pulled into the destination repository.
803 will be pulled into the destination repository.
802 No subsequent changesets (including subsequent tags) will be present
804 No subsequent changesets (including subsequent tags) will be present
803 in the destination.
805 in the destination.
804
806
805 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
807 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
806 local source repositories.
808 local source repositories.
807
809
808 For efficiency, hardlinks are used for cloning whenever the source
810 For efficiency, hardlinks are used for cloning whenever the source
809 and destination are on the same filesystem (note this applies only
811 and destination are on the same filesystem (note this applies only
810 to the repository data, not to the working directory). Some
812 to the repository data, not to the working directory). Some
811 filesystems, such as AFS, implement hardlinking incorrectly, but
813 filesystems, such as AFS, implement hardlinking incorrectly, but
812 do not report errors. In these cases, use the --pull option to
814 do not report errors. In these cases, use the --pull option to
813 avoid hardlinking.
815 avoid hardlinking.
814
816
815 In some cases, you can clone repositories and the working directory
817 In some cases, you can clone repositories and the working directory
816 using full hardlinks with ::
818 using full hardlinks with ::
817
819
818 $ cp -al REPO REPOCLONE
820 $ cp -al REPO REPOCLONE
819
821
820 This is the fastest way to clone, but it is not always safe. The
822 This is the fastest way to clone, but it is not always safe. The
821 operation is not atomic (making sure REPO is not modified during
823 operation is not atomic (making sure REPO is not modified during
822 the operation is up to you) and you have to make sure your editor
824 the operation is up to you) and you have to make sure your editor
823 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
825 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
824 this is not compatible with certain extensions that place their
826 this is not compatible with certain extensions that place their
825 metadata under the .hg directory, such as mq.
827 metadata under the .hg directory, such as mq.
826
828
827 Mercurial will update the working directory to the first applicable
829 Mercurial will update the working directory to the first applicable
828 revision from this list:
830 revision from this list:
829
831
830 a) null if -U or the source repository has no changesets
832 a) null if -U or the source repository has no changesets
831 b) if -u . and the source repository is local, the first parent of
833 b) if -u . and the source repository is local, the first parent of
832 the source repository's working directory
834 the source repository's working directory
833 c) the changeset specified with -u (if a branch name, this means the
835 c) the changeset specified with -u (if a branch name, this means the
834 latest head of that branch)
836 latest head of that branch)
835 d) the changeset specified with -r
837 d) the changeset specified with -r
836 e) the tipmost head specified with -b
838 e) the tipmost head specified with -b
837 f) the tipmost head specified with the url#branch source syntax
839 f) the tipmost head specified with the url#branch source syntax
838 g) the tipmost head of the default branch
840 g) the tipmost head of the default branch
839 h) tip
841 h) tip
840
842
841 Returns 0 on success.
843 Returns 0 on success.
842 """
844 """
843 if opts.get('noupdate') and opts.get('updaterev'):
845 if opts.get('noupdate') and opts.get('updaterev'):
844 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
846 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
845
847
846 r = hg.clone(hg.remoteui(ui, opts), source, dest,
848 r = hg.clone(hg.remoteui(ui, opts), source, dest,
847 pull=opts.get('pull'),
849 pull=opts.get('pull'),
848 stream=opts.get('uncompressed'),
850 stream=opts.get('uncompressed'),
849 rev=opts.get('rev'),
851 rev=opts.get('rev'),
850 update=opts.get('updaterev') or not opts.get('noupdate'),
852 update=opts.get('updaterev') or not opts.get('noupdate'),
851 branch=opts.get('branch'))
853 branch=opts.get('branch'))
852
854
853 return r is None
855 return r is None
854
856
855 def commit(ui, repo, *pats, **opts):
857 def commit(ui, repo, *pats, **opts):
856 """commit the specified files or all outstanding changes
858 """commit the specified files or all outstanding changes
857
859
858 Commit changes to the given files into the repository. Unlike a
860 Commit changes to the given files into the repository. Unlike a
859 centralized SCM, this operation is a local operation. See
861 centralized SCM, this operation is a local operation. See
860 :hg:`push` for a way to actively distribute your changes.
862 :hg:`push` for a way to actively distribute your changes.
861
863
862 If a list of files is omitted, all changes reported by :hg:`status`
864 If a list of files is omitted, all changes reported by :hg:`status`
863 will be committed.
865 will be committed.
864
866
865 If you are committing the result of a merge, do not provide any
867 If you are committing the result of a merge, do not provide any
866 filenames or -I/-X filters.
868 filenames or -I/-X filters.
867
869
868 If no commit message is specified, Mercurial starts your
870 If no commit message is specified, Mercurial starts your
869 configured editor where you can enter a message. In case your
871 configured editor where you can enter a message. In case your
870 commit fails, you will find a backup of your message in
872 commit fails, you will find a backup of your message in
871 ``.hg/last-message.txt``.
873 ``.hg/last-message.txt``.
872
874
873 See :hg:`help dates` for a list of formats valid for -d/--date.
875 See :hg:`help dates` for a list of formats valid for -d/--date.
874
876
875 Returns 0 on success, 1 if nothing changed.
877 Returns 0 on success, 1 if nothing changed.
876 """
878 """
877 extra = {}
879 extra = {}
878 if opts.get('close_branch'):
880 if opts.get('close_branch'):
879 if repo['.'].node() not in repo.branchheads():
881 if repo['.'].node() not in repo.branchheads():
880 # The topo heads set is included in the branch heads set of the
882 # The topo heads set is included in the branch heads set of the
881 # current branch, so it's sufficient to test branchheads
883 # current branch, so it's sufficient to test branchheads
882 raise util.Abort(_('can only close branch heads'))
884 raise util.Abort(_('can only close branch heads'))
883 extra['close'] = 1
885 extra['close'] = 1
884 e = cmdutil.commiteditor
886 e = cmdutil.commiteditor
885 if opts.get('force_editor'):
887 if opts.get('force_editor'):
886 e = cmdutil.commitforceeditor
888 e = cmdutil.commitforceeditor
887
889
888 def commitfunc(ui, repo, message, match, opts):
890 def commitfunc(ui, repo, message, match, opts):
889 return repo.commit(message, opts.get('user'), opts.get('date'), match,
891 return repo.commit(message, opts.get('user'), opts.get('date'), match,
890 editor=e, extra=extra)
892 editor=e, extra=extra)
891
893
892 branch = repo[None].branch()
894 branch = repo[None].branch()
893 bheads = repo.branchheads(branch)
895 bheads = repo.branchheads(branch)
894
896
895 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
897 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
896 if not node:
898 if not node:
897 stat = repo.status(match=cmdutil.match(repo, pats, opts))
899 stat = repo.status(match=cmdutil.match(repo, pats, opts))
898 if stat[3]:
900 if stat[3]:
899 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
901 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
900 % len(stat[3]))
902 % len(stat[3]))
901 else:
903 else:
902 ui.status(_("nothing changed\n"))
904 ui.status(_("nothing changed\n"))
903 return 1
905 return 1
904
906
905 ctx = repo[node]
907 ctx = repo[node]
906 parents = ctx.parents()
908 parents = ctx.parents()
907
909
908 if bheads and not [x for x in parents
910 if bheads and not [x for x in parents
909 if x.node() in bheads and x.branch() == branch]:
911 if x.node() in bheads and x.branch() == branch]:
910 ui.status(_('created new head\n'))
912 ui.status(_('created new head\n'))
911 # The message is not printed for initial roots. For the other
913 # The message is not printed for initial roots. For the other
912 # changesets, it is printed in the following situations:
914 # changesets, it is printed in the following situations:
913 #
915 #
914 # Par column: for the 2 parents with ...
916 # Par column: for the 2 parents with ...
915 # N: null or no parent
917 # N: null or no parent
916 # B: parent is on another named branch
918 # B: parent is on another named branch
917 # C: parent is a regular non head changeset
919 # C: parent is a regular non head changeset
918 # H: parent was a branch head of the current branch
920 # H: parent was a branch head of the current branch
919 # Msg column: whether we print "created new head" message
921 # Msg column: whether we print "created new head" message
920 # In the following, it is assumed that there already exists some
922 # In the following, it is assumed that there already exists some
921 # initial branch heads of the current branch, otherwise nothing is
923 # initial branch heads of the current branch, otherwise nothing is
922 # printed anyway.
924 # printed anyway.
923 #
925 #
924 # Par Msg Comment
926 # Par Msg Comment
925 # NN y additional topo root
927 # NN y additional topo root
926 #
928 #
927 # BN y additional branch root
929 # BN y additional branch root
928 # CN y additional topo head
930 # CN y additional topo head
929 # HN n usual case
931 # HN n usual case
930 #
932 #
931 # BB y weird additional branch root
933 # BB y weird additional branch root
932 # CB y branch merge
934 # CB y branch merge
933 # HB n merge with named branch
935 # HB n merge with named branch
934 #
936 #
935 # CC y additional head from merge
937 # CC y additional head from merge
936 # CH n merge with a head
938 # CH n merge with a head
937 #
939 #
938 # HH n head merge: head count decreases
940 # HH n head merge: head count decreases
939
941
940 if not opts.get('close_branch'):
942 if not opts.get('close_branch'):
941 for r in parents:
943 for r in parents:
942 if r.extra().get('close') and r.branch() == branch:
944 if r.extra().get('close') and r.branch() == branch:
943 ui.status(_('reopening closed branch head %d\n') % r)
945 ui.status(_('reopening closed branch head %d\n') % r)
944
946
945 if ui.debugflag:
947 if ui.debugflag:
946 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
948 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
947 elif ui.verbose:
949 elif ui.verbose:
948 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
950 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
949
951
950 def copy(ui, repo, *pats, **opts):
952 def copy(ui, repo, *pats, **opts):
951 """mark files as copied for the next commit
953 """mark files as copied for the next commit
952
954
953 Mark dest as having copies of source files. If dest is a
955 Mark dest as having copies of source files. If dest is a
954 directory, copies are put in that directory. If dest is a file,
956 directory, copies are put in that directory. If dest is a file,
955 the source must be a single file.
957 the source must be a single file.
956
958
957 By default, this command copies the contents of files as they
959 By default, this command copies the contents of files as they
958 exist in the working directory. If invoked with -A/--after, the
960 exist in the working directory. If invoked with -A/--after, the
959 operation is recorded, but no copying is performed.
961 operation is recorded, but no copying is performed.
960
962
961 This command takes effect with the next commit. To undo a copy
963 This command takes effect with the next commit. To undo a copy
962 before that, see :hg:`revert`.
964 before that, see :hg:`revert`.
963
965
964 Returns 0 on success, 1 if errors are encountered.
966 Returns 0 on success, 1 if errors are encountered.
965 """
967 """
966 wlock = repo.wlock(False)
968 wlock = repo.wlock(False)
967 try:
969 try:
968 return cmdutil.copy(ui, repo, pats, opts)
970 return cmdutil.copy(ui, repo, pats, opts)
969 finally:
971 finally:
970 wlock.release()
972 wlock.release()
971
973
972 def debugancestor(ui, repo, *args):
974 def debugancestor(ui, repo, *args):
973 """find the ancestor revision of two revisions in a given index"""
975 """find the ancestor revision of two revisions in a given index"""
974 if len(args) == 3:
976 if len(args) == 3:
975 index, rev1, rev2 = args
977 index, rev1, rev2 = args
976 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
978 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
977 lookup = r.lookup
979 lookup = r.lookup
978 elif len(args) == 2:
980 elif len(args) == 2:
979 if not repo:
981 if not repo:
980 raise util.Abort(_("there is no Mercurial repository here "
982 raise util.Abort(_("there is no Mercurial repository here "
981 "(.hg not found)"))
983 "(.hg not found)"))
982 rev1, rev2 = args
984 rev1, rev2 = args
983 r = repo.changelog
985 r = repo.changelog
984 lookup = repo.lookup
986 lookup = repo.lookup
985 else:
987 else:
986 raise util.Abort(_('either two or three arguments required'))
988 raise util.Abort(_('either two or three arguments required'))
987 a = r.ancestor(lookup(rev1), lookup(rev2))
989 a = r.ancestor(lookup(rev1), lookup(rev2))
988 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
990 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
989
991
990 def debugbuilddag(ui, repo, text,
992 def debugbuilddag(ui, repo, text,
991 mergeable_file=False,
993 mergeable_file=False,
992 appended_file=False,
994 appended_file=False,
993 overwritten_file=False,
995 overwritten_file=False,
994 new_file=False):
996 new_file=False):
995 """builds a repo with a given dag from scratch in the current empty repo
997 """builds a repo with a given dag from scratch in the current empty repo
996
998
997 Elements:
999 Elements:
998
1000
999 - "+n" is a linear run of n nodes based on the current default parent
1001 - "+n" is a linear run of n nodes based on the current default parent
1000 - "." is a single node based on the current default parent
1002 - "." is a single node based on the current default parent
1001 - "$" resets the default parent to null (implied at the start);
1003 - "$" resets the default parent to null (implied at the start);
1002 otherwise the default parent is always the last node created
1004 otherwise the default parent is always the last node created
1003 - "<p" sets the default parent to the backref p
1005 - "<p" sets the default parent to the backref p
1004 - "*p" is a fork at parent p, which is a backref
1006 - "*p" is a fork at parent p, which is a backref
1005 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1007 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1006 - "/p2" is a merge of the preceding node and p2
1008 - "/p2" is a merge of the preceding node and p2
1007 - ":tag" defines a local tag for the preceding node
1009 - ":tag" defines a local tag for the preceding node
1008 - "@branch" sets the named branch for subsequent nodes
1010 - "@branch" sets the named branch for subsequent nodes
1009 - "!command" runs the command using your shell
1011 - "!command" runs the command using your shell
1010 - "!!my command\\n" is like "!", but to the end of the line
1012 - "!!my command\\n" is like "!", but to the end of the line
1011 - "#...\\n" is a comment up to the end of the line
1013 - "#...\\n" is a comment up to the end of the line
1012
1014
1013 Whitespace between the above elements is ignored.
1015 Whitespace between the above elements is ignored.
1014
1016
1015 A backref is either
1017 A backref is either
1016
1018
1017 - a number n, which references the node curr-n, where curr is the current
1019 - a number n, which references the node curr-n, where curr is the current
1018 node, or
1020 node, or
1019 - the name of a local tag you placed earlier using ":tag", or
1021 - the name of a local tag you placed earlier using ":tag", or
1020 - empty to denote the default parent.
1022 - empty to denote the default parent.
1021
1023
1022 All string valued-elements are either strictly alphanumeric, or must
1024 All string valued-elements are either strictly alphanumeric, or must
1023 be enclosed in double quotes ("..."), with "\\" as escape character.
1025 be enclosed in double quotes ("..."), with "\\" as escape character.
1024
1026
1025 Note that the --overwritten-file and --appended-file options imply the
1027 Note that the --overwritten-file and --appended-file options imply the
1026 use of "HGMERGE=internal:local" during DAG buildup.
1028 use of "HGMERGE=internal:local" during DAG buildup.
1027 """
1029 """
1028
1030
1029 if not (mergeable_file or appended_file or overwritten_file or new_file):
1031 if not (mergeable_file or appended_file or overwritten_file or new_file):
1030 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
1032 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
1031
1033
1032 if len(repo.changelog) > 0:
1034 if len(repo.changelog) > 0:
1033 raise util.Abort(_('repository is not empty'))
1035 raise util.Abort(_('repository is not empty'))
1034
1036
1035 if overwritten_file or appended_file:
1037 if overwritten_file or appended_file:
1036 # we don't want to fail in merges during buildup
1038 # we don't want to fail in merges during buildup
1037 os.environ['HGMERGE'] = 'internal:local'
1039 os.environ['HGMERGE'] = 'internal:local'
1038
1040
1039 def writefile(fname, text, fmode="wb"):
1041 def writefile(fname, text, fmode="wb"):
1040 f = open(fname, fmode)
1042 f = open(fname, fmode)
1041 try:
1043 try:
1042 f.write(text)
1044 f.write(text)
1043 finally:
1045 finally:
1044 f.close()
1046 f.close()
1045
1047
1046 if mergeable_file:
1048 if mergeable_file:
1047 linesperrev = 2
1049 linesperrev = 2
1048 # determine number of revs in DAG
1050 # determine number of revs in DAG
1049 n = 0
1051 n = 0
1050 for type, data in dagparser.parsedag(text):
1052 for type, data in dagparser.parsedag(text):
1051 if type == 'n':
1053 if type == 'n':
1052 n += 1
1054 n += 1
1053 # make a file with k lines per rev
1055 # make a file with k lines per rev
1054 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
1056 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
1055 + "\n")
1057 + "\n")
1056
1058
1057 at = -1
1059 at = -1
1058 atbranch = 'default'
1060 atbranch = 'default'
1059 for type, data in dagparser.parsedag(text):
1061 for type, data in dagparser.parsedag(text):
1060 if type == 'n':
1062 if type == 'n':
1061 ui.status('node %s\n' % str(data))
1063 ui.status('node %s\n' % str(data))
1062 id, ps = data
1064 id, ps = data
1063 p1 = ps[0]
1065 p1 = ps[0]
1064 if p1 != at:
1066 if p1 != at:
1065 update(ui, repo, node=str(p1), clean=True)
1067 update(ui, repo, node=str(p1), clean=True)
1066 at = p1
1068 at = p1
1067 if repo.dirstate.branch() != atbranch:
1069 if repo.dirstate.branch() != atbranch:
1068 branch(ui, repo, atbranch, force=True)
1070 branch(ui, repo, atbranch, force=True)
1069 if len(ps) > 1:
1071 if len(ps) > 1:
1070 p2 = ps[1]
1072 p2 = ps[1]
1071 merge(ui, repo, node=p2)
1073 merge(ui, repo, node=p2)
1072
1074
1073 if mergeable_file:
1075 if mergeable_file:
1074 f = open("mf", "rb+")
1076 f = open("mf", "rb+")
1075 try:
1077 try:
1076 lines = f.read().split("\n")
1078 lines = f.read().split("\n")
1077 lines[id * linesperrev] += " r%i" % id
1079 lines[id * linesperrev] += " r%i" % id
1078 f.seek(0)
1080 f.seek(0)
1079 f.write("\n".join(lines))
1081 f.write("\n".join(lines))
1080 finally:
1082 finally:
1081 f.close()
1083 f.close()
1082
1084
1083 if appended_file:
1085 if appended_file:
1084 writefile("af", "r%i\n" % id, "ab")
1086 writefile("af", "r%i\n" % id, "ab")
1085
1087
1086 if overwritten_file:
1088 if overwritten_file:
1087 writefile("of", "r%i\n" % id)
1089 writefile("of", "r%i\n" % id)
1088
1090
1089 if new_file:
1091 if new_file:
1090 writefile("nf%i" % id, "r%i\n" % id)
1092 writefile("nf%i" % id, "r%i\n" % id)
1091
1093
1092 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
1094 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
1093 at = id
1095 at = id
1094 elif type == 'l':
1096 elif type == 'l':
1095 id, name = data
1097 id, name = data
1096 ui.status('tag %s\n' % name)
1098 ui.status('tag %s\n' % name)
1097 tag(ui, repo, name, local=True)
1099 tag(ui, repo, name, local=True)
1098 elif type == 'a':
1100 elif type == 'a':
1099 ui.status('branch %s\n' % data)
1101 ui.status('branch %s\n' % data)
1100 atbranch = data
1102 atbranch = data
1101 elif type in 'cC':
1103 elif type in 'cC':
1102 r = util.system(data, cwd=repo.root)
1104 r = util.system(data, cwd=repo.root)
1103 if r:
1105 if r:
1104 desc, r = util.explain_exit(r)
1106 desc, r = util.explain_exit(r)
1105 raise util.Abort(_('%s command %s') % (data, desc))
1107 raise util.Abort(_('%s command %s') % (data, desc))
1106
1108
1107 def debugcommands(ui, cmd='', *args):
1109 def debugcommands(ui, cmd='', *args):
1108 """list all available commands and options"""
1110 """list all available commands and options"""
1109 for cmd, vals in sorted(table.iteritems()):
1111 for cmd, vals in sorted(table.iteritems()):
1110 cmd = cmd.split('|')[0].strip('^')
1112 cmd = cmd.split('|')[0].strip('^')
1111 opts = ', '.join([i[1] for i in vals[1]])
1113 opts = ', '.join([i[1] for i in vals[1]])
1112 ui.write('%s: %s\n' % (cmd, opts))
1114 ui.write('%s: %s\n' % (cmd, opts))
1113
1115
1114 def debugcomplete(ui, cmd='', **opts):
1116 def debugcomplete(ui, cmd='', **opts):
1115 """returns the completion list associated with the given command"""
1117 """returns the completion list associated with the given command"""
1116
1118
1117 if opts.get('options'):
1119 if opts.get('options'):
1118 options = []
1120 options = []
1119 otables = [globalopts]
1121 otables = [globalopts]
1120 if cmd:
1122 if cmd:
1121 aliases, entry = cmdutil.findcmd(cmd, table, False)
1123 aliases, entry = cmdutil.findcmd(cmd, table, False)
1122 otables.append(entry[1])
1124 otables.append(entry[1])
1123 for t in otables:
1125 for t in otables:
1124 for o in t:
1126 for o in t:
1125 if "(DEPRECATED)" in o[3]:
1127 if "(DEPRECATED)" in o[3]:
1126 continue
1128 continue
1127 if o[0]:
1129 if o[0]:
1128 options.append('-%s' % o[0])
1130 options.append('-%s' % o[0])
1129 options.append('--%s' % o[1])
1131 options.append('--%s' % o[1])
1130 ui.write("%s\n" % "\n".join(options))
1132 ui.write("%s\n" % "\n".join(options))
1131 return
1133 return
1132
1134
1133 cmdlist = cmdutil.findpossible(cmd, table)
1135 cmdlist = cmdutil.findpossible(cmd, table)
1134 if ui.verbose:
1136 if ui.verbose:
1135 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1137 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1136 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1138 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1137
1139
1138 def debugfsinfo(ui, path = "."):
1140 def debugfsinfo(ui, path = "."):
1139 """show information detected about current filesystem"""
1141 """show information detected about current filesystem"""
1140 open('.debugfsinfo', 'w').write('')
1142 open('.debugfsinfo', 'w').write('')
1141 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1143 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1142 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1144 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1143 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1145 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1144 and 'yes' or 'no'))
1146 and 'yes' or 'no'))
1145 os.unlink('.debugfsinfo')
1147 os.unlink('.debugfsinfo')
1146
1148
1147 def debugrebuildstate(ui, repo, rev="tip"):
1149 def debugrebuildstate(ui, repo, rev="tip"):
1148 """rebuild the dirstate as it would look like for the given revision"""
1150 """rebuild the dirstate as it would look like for the given revision"""
1149 ctx = cmdutil.revsingle(repo, rev)
1151 ctx = cmdutil.revsingle(repo, rev)
1150 wlock = repo.wlock()
1152 wlock = repo.wlock()
1151 try:
1153 try:
1152 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1154 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1153 finally:
1155 finally:
1154 wlock.release()
1156 wlock.release()
1155
1157
1156 def debugcheckstate(ui, repo):
1158 def debugcheckstate(ui, repo):
1157 """validate the correctness of the current dirstate"""
1159 """validate the correctness of the current dirstate"""
1158 parent1, parent2 = repo.dirstate.parents()
1160 parent1, parent2 = repo.dirstate.parents()
1159 m1 = repo[parent1].manifest()
1161 m1 = repo[parent1].manifest()
1160 m2 = repo[parent2].manifest()
1162 m2 = repo[parent2].manifest()
1161 errors = 0
1163 errors = 0
1162 for f in repo.dirstate:
1164 for f in repo.dirstate:
1163 state = repo.dirstate[f]
1165 state = repo.dirstate[f]
1164 if state in "nr" and f not in m1:
1166 if state in "nr" and f not in m1:
1165 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1167 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1166 errors += 1
1168 errors += 1
1167 if state in "a" and f in m1:
1169 if state in "a" and f in m1:
1168 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1170 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1169 errors += 1
1171 errors += 1
1170 if state in "m" and f not in m1 and f not in m2:
1172 if state in "m" and f not in m1 and f not in m2:
1171 ui.warn(_("%s in state %s, but not in either manifest\n") %
1173 ui.warn(_("%s in state %s, but not in either manifest\n") %
1172 (f, state))
1174 (f, state))
1173 errors += 1
1175 errors += 1
1174 for f in m1:
1176 for f in m1:
1175 state = repo.dirstate[f]
1177 state = repo.dirstate[f]
1176 if state not in "nrm":
1178 if state not in "nrm":
1177 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1179 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1178 errors += 1
1180 errors += 1
1179 if errors:
1181 if errors:
1180 error = _(".hg/dirstate inconsistent with current parent's manifest")
1182 error = _(".hg/dirstate inconsistent with current parent's manifest")
1181 raise util.Abort(error)
1183 raise util.Abort(error)
1182
1184
1183 def showconfig(ui, repo, *values, **opts):
1185 def showconfig(ui, repo, *values, **opts):
1184 """show combined config settings from all hgrc files
1186 """show combined config settings from all hgrc files
1185
1187
1186 With no arguments, print names and values of all config items.
1188 With no arguments, print names and values of all config items.
1187
1189
1188 With one argument of the form section.name, print just the value
1190 With one argument of the form section.name, print just the value
1189 of that config item.
1191 of that config item.
1190
1192
1191 With multiple arguments, print names and values of all config
1193 With multiple arguments, print names and values of all config
1192 items with matching section names.
1194 items with matching section names.
1193
1195
1194 With --debug, the source (filename and line number) is printed
1196 With --debug, the source (filename and line number) is printed
1195 for each config item.
1197 for each config item.
1196
1198
1197 Returns 0 on success.
1199 Returns 0 on success.
1198 """
1200 """
1199
1201
1200 for f in util.rcpath():
1202 for f in util.rcpath():
1201 ui.debug(_('read config from: %s\n') % f)
1203 ui.debug(_('read config from: %s\n') % f)
1202 untrusted = bool(opts.get('untrusted'))
1204 untrusted = bool(opts.get('untrusted'))
1203 if values:
1205 if values:
1204 sections = [v for v in values if '.' not in v]
1206 sections = [v for v in values if '.' not in v]
1205 items = [v for v in values if '.' in v]
1207 items = [v for v in values if '.' in v]
1206 if len(items) > 1 or items and sections:
1208 if len(items) > 1 or items and sections:
1207 raise util.Abort(_('only one config item permitted'))
1209 raise util.Abort(_('only one config item permitted'))
1208 for section, name, value in ui.walkconfig(untrusted=untrusted):
1210 for section, name, value in ui.walkconfig(untrusted=untrusted):
1209 value = str(value).replace('\n', '\\n')
1211 value = str(value).replace('\n', '\\n')
1210 sectname = section + '.' + name
1212 sectname = section + '.' + name
1211 if values:
1213 if values:
1212 for v in values:
1214 for v in values:
1213 if v == section:
1215 if v == section:
1214 ui.debug('%s: ' %
1216 ui.debug('%s: ' %
1215 ui.configsource(section, name, untrusted))
1217 ui.configsource(section, name, untrusted))
1216 ui.write('%s=%s\n' % (sectname, value))
1218 ui.write('%s=%s\n' % (sectname, value))
1217 elif v == sectname:
1219 elif v == sectname:
1218 ui.debug('%s: ' %
1220 ui.debug('%s: ' %
1219 ui.configsource(section, name, untrusted))
1221 ui.configsource(section, name, untrusted))
1220 ui.write(value, '\n')
1222 ui.write(value, '\n')
1221 else:
1223 else:
1222 ui.debug('%s: ' %
1224 ui.debug('%s: ' %
1223 ui.configsource(section, name, untrusted))
1225 ui.configsource(section, name, untrusted))
1224 ui.write('%s=%s\n' % (sectname, value))
1226 ui.write('%s=%s\n' % (sectname, value))
1225
1227
1226 def debugknown(ui, repopath, *ids, **opts):
1228 def debugknown(ui, repopath, *ids, **opts):
1227 """test whether node ids are known to a repo
1229 """test whether node ids are known to a repo
1228
1230
1229 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1231 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1230 indicating unknown/known.
1232 indicating unknown/known.
1231 """
1233 """
1232 repo = hg.repository(ui, repopath)
1234 repo = hg.repository(ui, repopath)
1233 if not repo.capable('known'):
1235 if not repo.capable('known'):
1234 raise util.Abort("known() not supported by target repository")
1236 raise util.Abort("known() not supported by target repository")
1235 flags = repo.known([bin(s) for s in ids])
1237 flags = repo.known([bin(s) for s in ids])
1236 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1238 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1237
1239
1238 def debugbundle(ui, bundlepath, all=None, **opts):
1240 def debugbundle(ui, bundlepath, all=None, **opts):
1239 """lists the contents of a bundle"""
1241 """lists the contents of a bundle"""
1240 f = url.open(ui, bundlepath)
1242 f = url.open(ui, bundlepath)
1241 try:
1243 try:
1242 gen = changegroup.readbundle(f, bundlepath)
1244 gen = changegroup.readbundle(f, bundlepath)
1243 if all:
1245 if all:
1244 ui.write("format: id, p1, p2, cset, len(delta)\n")
1246 ui.write("format: id, p1, p2, cset, len(delta)\n")
1245
1247
1246 def showchunks(named):
1248 def showchunks(named):
1247 ui.write("\n%s\n" % named)
1249 ui.write("\n%s\n" % named)
1248 while 1:
1250 while 1:
1249 chunkdata = gen.parsechunk()
1251 chunkdata = gen.parsechunk()
1250 if not chunkdata:
1252 if not chunkdata:
1251 break
1253 break
1252 node = chunkdata['node']
1254 node = chunkdata['node']
1253 p1 = chunkdata['p1']
1255 p1 = chunkdata['p1']
1254 p2 = chunkdata['p2']
1256 p2 = chunkdata['p2']
1255 cs = chunkdata['cs']
1257 cs = chunkdata['cs']
1256 delta = chunkdata['data']
1258 delta = chunkdata['data']
1257 ui.write("%s %s %s %s %s\n" %
1259 ui.write("%s %s %s %s %s\n" %
1258 (hex(node), hex(p1), hex(p2),
1260 (hex(node), hex(p1), hex(p2),
1259 hex(cs), len(delta)))
1261 hex(cs), len(delta)))
1260
1262
1261 showchunks("changelog")
1263 showchunks("changelog")
1262 showchunks("manifest")
1264 showchunks("manifest")
1263 while 1:
1265 while 1:
1264 fname = gen.chunk()
1266 fname = gen.chunk()
1265 if not fname:
1267 if not fname:
1266 break
1268 break
1267 showchunks(fname)
1269 showchunks(fname)
1268 else:
1270 else:
1269 while 1:
1271 while 1:
1270 chunkdata = gen.parsechunk()
1272 chunkdata = gen.parsechunk()
1271 if not chunkdata:
1273 if not chunkdata:
1272 break
1274 break
1273 node = chunkdata['node']
1275 node = chunkdata['node']
1274 ui.write("%s\n" % hex(node))
1276 ui.write("%s\n" % hex(node))
1275 finally:
1277 finally:
1276 f.close()
1278 f.close()
1277
1279
1278 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1280 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1279 """retrieves a bundle from a repo
1281 """retrieves a bundle from a repo
1280
1282
1281 Every ID must be a full-length hex node id string. Saves the bundle to the
1283 Every ID must be a full-length hex node id string. Saves the bundle to the
1282 given file.
1284 given file.
1283 """
1285 """
1284 repo = hg.repository(ui, repopath)
1286 repo = hg.repository(ui, repopath)
1285 if not repo.capable('getbundle'):
1287 if not repo.capable('getbundle'):
1286 raise util.Abort("getbundle() not supported by target repository")
1288 raise util.Abort("getbundle() not supported by target repository")
1287 args = {}
1289 args = {}
1288 if common:
1290 if common:
1289 args['common'] = [bin(s) for s in common]
1291 args['common'] = [bin(s) for s in common]
1290 if head:
1292 if head:
1291 args['heads'] = [bin(s) for s in head]
1293 args['heads'] = [bin(s) for s in head]
1292 bundle = repo.getbundle('debug', **args)
1294 bundle = repo.getbundle('debug', **args)
1293
1295
1294 bundletype = opts.get('type', 'bzip2').lower()
1296 bundletype = opts.get('type', 'bzip2').lower()
1295 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1297 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1296 bundletype = btypes.get(bundletype)
1298 bundletype = btypes.get(bundletype)
1297 if bundletype not in changegroup.bundletypes:
1299 if bundletype not in changegroup.bundletypes:
1298 raise util.Abort(_('unknown bundle type specified with --type'))
1300 raise util.Abort(_('unknown bundle type specified with --type'))
1299 changegroup.writebundle(bundle, bundlepath, bundletype)
1301 changegroup.writebundle(bundle, bundlepath, bundletype)
1300
1302
1301 def debugpushkey(ui, repopath, namespace, *keyinfo):
1303 def debugpushkey(ui, repopath, namespace, *keyinfo):
1302 '''access the pushkey key/value protocol
1304 '''access the pushkey key/value protocol
1303
1305
1304 With two args, list the keys in the given namespace.
1306 With two args, list the keys in the given namespace.
1305
1307
1306 With five args, set a key to new if it currently is set to old.
1308 With five args, set a key to new if it currently is set to old.
1307 Reports success or failure.
1309 Reports success or failure.
1308 '''
1310 '''
1309
1311
1310 target = hg.repository(ui, repopath)
1312 target = hg.repository(ui, repopath)
1311 if keyinfo:
1313 if keyinfo:
1312 key, old, new = keyinfo
1314 key, old, new = keyinfo
1313 r = target.pushkey(namespace, key, old, new)
1315 r = target.pushkey(namespace, key, old, new)
1314 ui.status(str(r) + '\n')
1316 ui.status(str(r) + '\n')
1315 return not r
1317 return not r
1316 else:
1318 else:
1317 for k, v in target.listkeys(namespace).iteritems():
1319 for k, v in target.listkeys(namespace).iteritems():
1318 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1320 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1319 v.encode('string-escape')))
1321 v.encode('string-escape')))
1320
1322
1321 def debugrevspec(ui, repo, expr):
1323 def debugrevspec(ui, repo, expr):
1322 '''parse and apply a revision specification'''
1324 '''parse and apply a revision specification'''
1323 if ui.verbose:
1325 if ui.verbose:
1324 tree = revset.parse(expr)[0]
1326 tree = revset.parse(expr)[0]
1325 ui.note(tree, "\n")
1327 ui.note(tree, "\n")
1326 func = revset.match(expr)
1328 func = revset.match(expr)
1327 for c in func(repo, range(len(repo))):
1329 for c in func(repo, range(len(repo))):
1328 ui.write("%s\n" % c)
1330 ui.write("%s\n" % c)
1329
1331
1330 def debugsetparents(ui, repo, rev1, rev2=None):
1332 def debugsetparents(ui, repo, rev1, rev2=None):
1331 """manually set the parents of the current working directory
1333 """manually set the parents of the current working directory
1332
1334
1333 This is useful for writing repository conversion tools, but should
1335 This is useful for writing repository conversion tools, but should
1334 be used with care.
1336 be used with care.
1335
1337
1336 Returns 0 on success.
1338 Returns 0 on success.
1337 """
1339 """
1338
1340
1339 r1 = cmdutil.revsingle(repo, rev1).node()
1341 r1 = cmdutil.revsingle(repo, rev1).node()
1340 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1342 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1341
1343
1342 wlock = repo.wlock()
1344 wlock = repo.wlock()
1343 try:
1345 try:
1344 repo.dirstate.setparents(r1, r2)
1346 repo.dirstate.setparents(r1, r2)
1345 finally:
1347 finally:
1346 wlock.release()
1348 wlock.release()
1347
1349
1348 def debugstate(ui, repo, nodates=None, datesort=None):
1350 def debugstate(ui, repo, nodates=None, datesort=None):
1349 """show the contents of the current dirstate"""
1351 """show the contents of the current dirstate"""
1350 timestr = ""
1352 timestr = ""
1351 showdate = not nodates
1353 showdate = not nodates
1352 if datesort:
1354 if datesort:
1353 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
1355 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
1354 else:
1356 else:
1355 keyfunc = None # sort by filename
1357 keyfunc = None # sort by filename
1356 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
1358 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
1357 if showdate:
1359 if showdate:
1358 if ent[3] == -1:
1360 if ent[3] == -1:
1359 # Pad or slice to locale representation
1361 # Pad or slice to locale representation
1360 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1362 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1361 time.localtime(0)))
1363 time.localtime(0)))
1362 timestr = 'unset'
1364 timestr = 'unset'
1363 timestr = (timestr[:locale_len] +
1365 timestr = (timestr[:locale_len] +
1364 ' ' * (locale_len - len(timestr)))
1366 ' ' * (locale_len - len(timestr)))
1365 else:
1367 else:
1366 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1368 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1367 time.localtime(ent[3]))
1369 time.localtime(ent[3]))
1368 if ent[1] & 020000:
1370 if ent[1] & 020000:
1369 mode = 'lnk'
1371 mode = 'lnk'
1370 else:
1372 else:
1371 mode = '%3o' % (ent[1] & 0777)
1373 mode = '%3o' % (ent[1] & 0777)
1372 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1374 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1373 for f in repo.dirstate.copies():
1375 for f in repo.dirstate.copies():
1374 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1376 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1375
1377
1376 def debugsub(ui, repo, rev=None):
1378 def debugsub(ui, repo, rev=None):
1377 ctx = cmdutil.revsingle(repo, rev, None)
1379 ctx = cmdutil.revsingle(repo, rev, None)
1378 for k, v in sorted(ctx.substate.items()):
1380 for k, v in sorted(ctx.substate.items()):
1379 ui.write('path %s\n' % k)
1381 ui.write('path %s\n' % k)
1380 ui.write(' source %s\n' % v[0])
1382 ui.write(' source %s\n' % v[0])
1381 ui.write(' revision %s\n' % v[1])
1383 ui.write(' revision %s\n' % v[1])
1382
1384
1383 def debugdag(ui, repo, file_=None, *revs, **opts):
1385 def debugdag(ui, repo, file_=None, *revs, **opts):
1384 """format the changelog or an index DAG as a concise textual description
1386 """format the changelog or an index DAG as a concise textual description
1385
1387
1386 If you pass a revlog index, the revlog's DAG is emitted. If you list
1388 If you pass a revlog index, the revlog's DAG is emitted. If you list
1387 revision numbers, they get labelled in the output as rN.
1389 revision numbers, they get labelled in the output as rN.
1388
1390
1389 Otherwise, the changelog DAG of the current repo is emitted.
1391 Otherwise, the changelog DAG of the current repo is emitted.
1390 """
1392 """
1391 spaces = opts.get('spaces')
1393 spaces = opts.get('spaces')
1392 dots = opts.get('dots')
1394 dots = opts.get('dots')
1393 if file_:
1395 if file_:
1394 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1396 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1395 revs = set((int(r) for r in revs))
1397 revs = set((int(r) for r in revs))
1396 def events():
1398 def events():
1397 for r in rlog:
1399 for r in rlog:
1398 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1400 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1399 if r in revs:
1401 if r in revs:
1400 yield 'l', (r, "r%i" % r)
1402 yield 'l', (r, "r%i" % r)
1401 elif repo:
1403 elif repo:
1402 cl = repo.changelog
1404 cl = repo.changelog
1403 tags = opts.get('tags')
1405 tags = opts.get('tags')
1404 branches = opts.get('branches')
1406 branches = opts.get('branches')
1405 if tags:
1407 if tags:
1406 labels = {}
1408 labels = {}
1407 for l, n in repo.tags().items():
1409 for l, n in repo.tags().items():
1408 labels.setdefault(cl.rev(n), []).append(l)
1410 labels.setdefault(cl.rev(n), []).append(l)
1409 def events():
1411 def events():
1410 b = "default"
1412 b = "default"
1411 for r in cl:
1413 for r in cl:
1412 if branches:
1414 if branches:
1413 newb = cl.read(cl.node(r))[5]['branch']
1415 newb = cl.read(cl.node(r))[5]['branch']
1414 if newb != b:
1416 if newb != b:
1415 yield 'a', newb
1417 yield 'a', newb
1416 b = newb
1418 b = newb
1417 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1419 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1418 if tags:
1420 if tags:
1419 ls = labels.get(r)
1421 ls = labels.get(r)
1420 if ls:
1422 if ls:
1421 for l in ls:
1423 for l in ls:
1422 yield 'l', (r, l)
1424 yield 'l', (r, l)
1423 else:
1425 else:
1424 raise util.Abort(_('need repo for changelog dag'))
1426 raise util.Abort(_('need repo for changelog dag'))
1425
1427
1426 for line in dagparser.dagtextlines(events(),
1428 for line in dagparser.dagtextlines(events(),
1427 addspaces=spaces,
1429 addspaces=spaces,
1428 wraplabels=True,
1430 wraplabels=True,
1429 wrapannotations=True,
1431 wrapannotations=True,
1430 wrapnonlinear=dots,
1432 wrapnonlinear=dots,
1431 usedots=dots,
1433 usedots=dots,
1432 maxlinewidth=70):
1434 maxlinewidth=70):
1433 ui.write(line)
1435 ui.write(line)
1434 ui.write("\n")
1436 ui.write("\n")
1435
1437
1436 def debugdata(ui, repo, file_, rev):
1438 def debugdata(ui, repo, file_, rev):
1437 """dump the contents of a data file revision"""
1439 """dump the contents of a data file revision"""
1438 r = None
1440 r = None
1439 if repo:
1441 if repo:
1440 filelog = repo.file(file_)
1442 filelog = repo.file(file_)
1441 if len(filelog):
1443 if len(filelog):
1442 r = filelog
1444 r = filelog
1443 if not r:
1445 if not r:
1444 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1446 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1445 try:
1447 try:
1446 ui.write(r.revision(r.lookup(rev)))
1448 ui.write(r.revision(r.lookup(rev)))
1447 except KeyError:
1449 except KeyError:
1448 raise util.Abort(_('invalid revision identifier %s') % rev)
1450 raise util.Abort(_('invalid revision identifier %s') % rev)
1449
1451
1450 def debugdate(ui, date, range=None, **opts):
1452 def debugdate(ui, date, range=None, **opts):
1451 """parse and display a date"""
1453 """parse and display a date"""
1452 if opts["extended"]:
1454 if opts["extended"]:
1453 d = util.parsedate(date, util.extendeddateformats)
1455 d = util.parsedate(date, util.extendeddateformats)
1454 else:
1456 else:
1455 d = util.parsedate(date)
1457 d = util.parsedate(date)
1456 ui.write("internal: %s %s\n" % d)
1458 ui.write("internal: %s %s\n" % d)
1457 ui.write("standard: %s\n" % util.datestr(d))
1459 ui.write("standard: %s\n" % util.datestr(d))
1458 if range:
1460 if range:
1459 m = util.matchdate(range)
1461 m = util.matchdate(range)
1460 ui.write("match: %s\n" % m(d[0]))
1462 ui.write("match: %s\n" % m(d[0]))
1461
1463
1462 def debugignore(ui, repo, *values, **opts):
1464 def debugignore(ui, repo, *values, **opts):
1463 """display the combined ignore pattern"""
1465 """display the combined ignore pattern"""
1464 ignore = repo.dirstate._ignore
1466 ignore = repo.dirstate._ignore
1465 if hasattr(ignore, 'includepat'):
1467 if hasattr(ignore, 'includepat'):
1466 ui.write("%s\n" % ignore.includepat)
1468 ui.write("%s\n" % ignore.includepat)
1467 else:
1469 else:
1468 raise util.Abort(_("no ignore patterns found"))
1470 raise util.Abort(_("no ignore patterns found"))
1469
1471
1470 def debugindex(ui, repo, file_, **opts):
1472 def debugindex(ui, repo, file_, **opts):
1471 """dump the contents of an index file"""
1473 """dump the contents of an index file"""
1472 r = None
1474 r = None
1473 if repo:
1475 if repo:
1474 filelog = repo.file(file_)
1476 filelog = repo.file(file_)
1475 if len(filelog):
1477 if len(filelog):
1476 r = filelog
1478 r = filelog
1477
1479
1478 format = opts.get('format', 0)
1480 format = opts.get('format', 0)
1479 if format not in (0, 1):
1481 if format not in (0, 1):
1480 raise util.Abort(_("unknown format %d") % format)
1482 raise util.Abort(_("unknown format %d") % format)
1481
1483
1482 if not r:
1484 if not r:
1483 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1485 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1484
1486
1485 if format == 0:
1487 if format == 0:
1486 ui.write(" rev offset length base linkrev"
1488 ui.write(" rev offset length base linkrev"
1487 " nodeid p1 p2\n")
1489 " nodeid p1 p2\n")
1488 elif format == 1:
1490 elif format == 1:
1489 ui.write(" rev flag offset length"
1491 ui.write(" rev flag offset length"
1490 " size base link p1 p2 nodeid\n")
1492 " size base link p1 p2 nodeid\n")
1491
1493
1492 for i in r:
1494 for i in r:
1493 node = r.node(i)
1495 node = r.node(i)
1494 if format == 0:
1496 if format == 0:
1495 try:
1497 try:
1496 pp = r.parents(node)
1498 pp = r.parents(node)
1497 except:
1499 except:
1498 pp = [nullid, nullid]
1500 pp = [nullid, nullid]
1499 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1501 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1500 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1502 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1501 short(node), short(pp[0]), short(pp[1])))
1503 short(node), short(pp[0]), short(pp[1])))
1502 elif format == 1:
1504 elif format == 1:
1503 pr = r.parentrevs(i)
1505 pr = r.parentrevs(i)
1504 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1506 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1505 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1507 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1506 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1508 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1507
1509
1508 def debugindexdot(ui, repo, file_):
1510 def debugindexdot(ui, repo, file_):
1509 """dump an index DAG as a graphviz dot file"""
1511 """dump an index DAG as a graphviz dot file"""
1510 r = None
1512 r = None
1511 if repo:
1513 if repo:
1512 filelog = repo.file(file_)
1514 filelog = repo.file(file_)
1513 if len(filelog):
1515 if len(filelog):
1514 r = filelog
1516 r = filelog
1515 if not r:
1517 if not r:
1516 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1518 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1517 ui.write("digraph G {\n")
1519 ui.write("digraph G {\n")
1518 for i in r:
1520 for i in r:
1519 node = r.node(i)
1521 node = r.node(i)
1520 pp = r.parents(node)
1522 pp = r.parents(node)
1521 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1523 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1522 if pp[1] != nullid:
1524 if pp[1] != nullid:
1523 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1525 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1524 ui.write("}\n")
1526 ui.write("}\n")
1525
1527
1526 def debuginstall(ui):
1528 def debuginstall(ui):
1527 '''test Mercurial installation
1529 '''test Mercurial installation
1528
1530
1529 Returns 0 on success.
1531 Returns 0 on success.
1530 '''
1532 '''
1531
1533
1532 def writetemp(contents):
1534 def writetemp(contents):
1533 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1535 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1534 f = os.fdopen(fd, "wb")
1536 f = os.fdopen(fd, "wb")
1535 f.write(contents)
1537 f.write(contents)
1536 f.close()
1538 f.close()
1537 return name
1539 return name
1538
1540
1539 problems = 0
1541 problems = 0
1540
1542
1541 # encoding
1543 # encoding
1542 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1544 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1543 try:
1545 try:
1544 encoding.fromlocal("test")
1546 encoding.fromlocal("test")
1545 except util.Abort, inst:
1547 except util.Abort, inst:
1546 ui.write(" %s\n" % inst)
1548 ui.write(" %s\n" % inst)
1547 ui.write(_(" (check that your locale is properly set)\n"))
1549 ui.write(_(" (check that your locale is properly set)\n"))
1548 problems += 1
1550 problems += 1
1549
1551
1550 # compiled modules
1552 # compiled modules
1551 ui.status(_("Checking installed modules (%s)...\n")
1553 ui.status(_("Checking installed modules (%s)...\n")
1552 % os.path.dirname(__file__))
1554 % os.path.dirname(__file__))
1553 try:
1555 try:
1554 import bdiff, mpatch, base85, osutil
1556 import bdiff, mpatch, base85, osutil
1555 except Exception, inst:
1557 except Exception, inst:
1556 ui.write(" %s\n" % inst)
1558 ui.write(" %s\n" % inst)
1557 ui.write(_(" One or more extensions could not be found"))
1559 ui.write(_(" One or more extensions could not be found"))
1558 ui.write(_(" (check that you compiled the extensions)\n"))
1560 ui.write(_(" (check that you compiled the extensions)\n"))
1559 problems += 1
1561 problems += 1
1560
1562
1561 # templates
1563 # templates
1562 ui.status(_("Checking templates...\n"))
1564 ui.status(_("Checking templates...\n"))
1563 try:
1565 try:
1564 import templater
1566 import templater
1565 templater.templater(templater.templatepath("map-cmdline.default"))
1567 templater.templater(templater.templatepath("map-cmdline.default"))
1566 except Exception, inst:
1568 except Exception, inst:
1567 ui.write(" %s\n" % inst)
1569 ui.write(" %s\n" % inst)
1568 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1570 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1569 problems += 1
1571 problems += 1
1570
1572
1571 # editor
1573 # editor
1572 ui.status(_("Checking commit editor...\n"))
1574 ui.status(_("Checking commit editor...\n"))
1573 editor = ui.geteditor()
1575 editor = ui.geteditor()
1574 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1576 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1575 if not cmdpath:
1577 if not cmdpath:
1576 if editor == 'vi':
1578 if editor == 'vi':
1577 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1579 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1578 ui.write(_(" (specify a commit editor in your configuration"
1580 ui.write(_(" (specify a commit editor in your configuration"
1579 " file)\n"))
1581 " file)\n"))
1580 else:
1582 else:
1581 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1583 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1582 ui.write(_(" (specify a commit editor in your configuration"
1584 ui.write(_(" (specify a commit editor in your configuration"
1583 " file)\n"))
1585 " file)\n"))
1584 problems += 1
1586 problems += 1
1585
1587
1586 # check username
1588 # check username
1587 ui.status(_("Checking username...\n"))
1589 ui.status(_("Checking username...\n"))
1588 try:
1590 try:
1589 ui.username()
1591 ui.username()
1590 except util.Abort, e:
1592 except util.Abort, e:
1591 ui.write(" %s\n" % e)
1593 ui.write(" %s\n" % e)
1592 ui.write(_(" (specify a username in your configuration file)\n"))
1594 ui.write(_(" (specify a username in your configuration file)\n"))
1593 problems += 1
1595 problems += 1
1594
1596
1595 if not problems:
1597 if not problems:
1596 ui.status(_("No problems detected\n"))
1598 ui.status(_("No problems detected\n"))
1597 else:
1599 else:
1598 ui.write(_("%s problems detected,"
1600 ui.write(_("%s problems detected,"
1599 " please check your install!\n") % problems)
1601 " please check your install!\n") % problems)
1600
1602
1601 return problems
1603 return problems
1602
1604
1603 def debugrename(ui, repo, file1, *pats, **opts):
1605 def debugrename(ui, repo, file1, *pats, **opts):
1604 """dump rename information"""
1606 """dump rename information"""
1605
1607
1606 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1608 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1607 m = cmdutil.match(repo, (file1,) + pats, opts)
1609 m = cmdutil.match(repo, (file1,) + pats, opts)
1608 for abs in ctx.walk(m):
1610 for abs in ctx.walk(m):
1609 fctx = ctx[abs]
1611 fctx = ctx[abs]
1610 o = fctx.filelog().renamed(fctx.filenode())
1612 o = fctx.filelog().renamed(fctx.filenode())
1611 rel = m.rel(abs)
1613 rel = m.rel(abs)
1612 if o:
1614 if o:
1613 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1615 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1614 else:
1616 else:
1615 ui.write(_("%s not renamed\n") % rel)
1617 ui.write(_("%s not renamed\n") % rel)
1616
1618
1617 def debugwalk(ui, repo, *pats, **opts):
1619 def debugwalk(ui, repo, *pats, **opts):
1618 """show how files match on given patterns"""
1620 """show how files match on given patterns"""
1619 m = cmdutil.match(repo, pats, opts)
1621 m = cmdutil.match(repo, pats, opts)
1620 items = list(repo.walk(m))
1622 items = list(repo.walk(m))
1621 if not items:
1623 if not items:
1622 return
1624 return
1623 fmt = 'f %%-%ds %%-%ds %%s' % (
1625 fmt = 'f %%-%ds %%-%ds %%s' % (
1624 max([len(abs) for abs in items]),
1626 max([len(abs) for abs in items]),
1625 max([len(m.rel(abs)) for abs in items]))
1627 max([len(m.rel(abs)) for abs in items]))
1626 for abs in items:
1628 for abs in items:
1627 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1629 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1628 ui.write("%s\n" % line.rstrip())
1630 ui.write("%s\n" % line.rstrip())
1629
1631
1630 def debugwireargs(ui, repopath, *vals, **opts):
1632 def debugwireargs(ui, repopath, *vals, **opts):
1631 repo = hg.repository(hg.remoteui(ui, opts), repopath)
1633 repo = hg.repository(hg.remoteui(ui, opts), repopath)
1632 for opt in remoteopts:
1634 for opt in remoteopts:
1633 del opts[opt[1]]
1635 del opts[opt[1]]
1634 args = {}
1636 args = {}
1635 for k, v in opts.iteritems():
1637 for k, v in opts.iteritems():
1636 if v:
1638 if v:
1637 args[k] = v
1639 args[k] = v
1638 # run twice to check that we don't mess up the stream for the next command
1640 # run twice to check that we don't mess up the stream for the next command
1639 res1 = repo.debugwireargs(*vals, **args)
1641 res1 = repo.debugwireargs(*vals, **args)
1640 res2 = repo.debugwireargs(*vals, **args)
1642 res2 = repo.debugwireargs(*vals, **args)
1641 ui.write("%s\n" % res1)
1643 ui.write("%s\n" % res1)
1642 if res1 != res2:
1644 if res1 != res2:
1643 ui.warn("%s\n" % res2)
1645 ui.warn("%s\n" % res2)
1644
1646
1645 def diff(ui, repo, *pats, **opts):
1647 def diff(ui, repo, *pats, **opts):
1646 """diff repository (or selected files)
1648 """diff repository (or selected files)
1647
1649
1648 Show differences between revisions for the specified files.
1650 Show differences between revisions for the specified files.
1649
1651
1650 Differences between files are shown using the unified diff format.
1652 Differences between files are shown using the unified diff format.
1651
1653
1652 .. note::
1654 .. note::
1653 diff may generate unexpected results for merges, as it will
1655 diff may generate unexpected results for merges, as it will
1654 default to comparing against the working directory's first
1656 default to comparing against the working directory's first
1655 parent changeset if no revisions are specified.
1657 parent changeset if no revisions are specified.
1656
1658
1657 When two revision arguments are given, then changes are shown
1659 When two revision arguments are given, then changes are shown
1658 between those revisions. If only one revision is specified then
1660 between those revisions. If only one revision is specified then
1659 that revision is compared to the working directory, and, when no
1661 that revision is compared to the working directory, and, when no
1660 revisions are specified, the working directory files are compared
1662 revisions are specified, the working directory files are compared
1661 to its parent.
1663 to its parent.
1662
1664
1663 Alternatively you can specify -c/--change with a revision to see
1665 Alternatively you can specify -c/--change with a revision to see
1664 the changes in that changeset relative to its first parent.
1666 the changes in that changeset relative to its first parent.
1665
1667
1666 Without the -a/--text option, diff will avoid generating diffs of
1668 Without the -a/--text option, diff will avoid generating diffs of
1667 files it detects as binary. With -a, diff will generate a diff
1669 files it detects as binary. With -a, diff will generate a diff
1668 anyway, probably with undesirable results.
1670 anyway, probably with undesirable results.
1669
1671
1670 Use the -g/--git option to generate diffs in the git extended diff
1672 Use the -g/--git option to generate diffs in the git extended diff
1671 format. For more information, read :hg:`help diffs`.
1673 format. For more information, read :hg:`help diffs`.
1672
1674
1673 Returns 0 on success.
1675 Returns 0 on success.
1674 """
1676 """
1675
1677
1676 revs = opts.get('rev')
1678 revs = opts.get('rev')
1677 change = opts.get('change')
1679 change = opts.get('change')
1678 stat = opts.get('stat')
1680 stat = opts.get('stat')
1679 reverse = opts.get('reverse')
1681 reverse = opts.get('reverse')
1680
1682
1681 if revs and change:
1683 if revs and change:
1682 msg = _('cannot specify --rev and --change at the same time')
1684 msg = _('cannot specify --rev and --change at the same time')
1683 raise util.Abort(msg)
1685 raise util.Abort(msg)
1684 elif change:
1686 elif change:
1685 node2 = cmdutil.revsingle(repo, change, None).node()
1687 node2 = cmdutil.revsingle(repo, change, None).node()
1686 node1 = repo[node2].p1().node()
1688 node1 = repo[node2].p1().node()
1687 else:
1689 else:
1688 node1, node2 = cmdutil.revpair(repo, revs)
1690 node1, node2 = cmdutil.revpair(repo, revs)
1689
1691
1690 if reverse:
1692 if reverse:
1691 node1, node2 = node2, node1
1693 node1, node2 = node2, node1
1692
1694
1693 diffopts = patch.diffopts(ui, opts)
1695 diffopts = patch.diffopts(ui, opts)
1694 m = cmdutil.match(repo, pats, opts)
1696 m = cmdutil.match(repo, pats, opts)
1695 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1697 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1696 listsubrepos=opts.get('subrepos'))
1698 listsubrepos=opts.get('subrepos'))
1697
1699
1698 def export(ui, repo, *changesets, **opts):
1700 def export(ui, repo, *changesets, **opts):
1699 """dump the header and diffs for one or more changesets
1701 """dump the header and diffs for one or more changesets
1700
1702
1701 Print the changeset header and diffs for one or more revisions.
1703 Print the changeset header and diffs for one or more revisions.
1702
1704
1703 The information shown in the changeset header is: author, date,
1705 The information shown in the changeset header is: author, date,
1704 branch name (if non-default), changeset hash, parent(s) and commit
1706 branch name (if non-default), changeset hash, parent(s) and commit
1705 comment.
1707 comment.
1706
1708
1707 .. note::
1709 .. note::
1708 export may generate unexpected diff output for merge
1710 export may generate unexpected diff output for merge
1709 changesets, as it will compare the merge changeset against its
1711 changesets, as it will compare the merge changeset against its
1710 first parent only.
1712 first parent only.
1711
1713
1712 Output may be to a file, in which case the name of the file is
1714 Output may be to a file, in which case the name of the file is
1713 given using a format string. The formatting rules are as follows:
1715 given using a format string. The formatting rules are as follows:
1714
1716
1715 :``%%``: literal "%" character
1717 :``%%``: literal "%" character
1716 :``%H``: changeset hash (40 hexadecimal digits)
1718 :``%H``: changeset hash (40 hexadecimal digits)
1717 :``%N``: number of patches being generated
1719 :``%N``: number of patches being generated
1718 :``%R``: changeset revision number
1720 :``%R``: changeset revision number
1719 :``%b``: basename of the exporting repository
1721 :``%b``: basename of the exporting repository
1720 :``%h``: short-form changeset hash (12 hexadecimal digits)
1722 :``%h``: short-form changeset hash (12 hexadecimal digits)
1721 :``%n``: zero-padded sequence number, starting at 1
1723 :``%n``: zero-padded sequence number, starting at 1
1722 :``%r``: zero-padded changeset revision number
1724 :``%r``: zero-padded changeset revision number
1723
1725
1724 Without the -a/--text option, export will avoid generating diffs
1726 Without the -a/--text option, export will avoid generating diffs
1725 of files it detects as binary. With -a, export will generate a
1727 of files it detects as binary. With -a, export will generate a
1726 diff anyway, probably with undesirable results.
1728 diff anyway, probably with undesirable results.
1727
1729
1728 Use the -g/--git option to generate diffs in the git extended diff
1730 Use the -g/--git option to generate diffs in the git extended diff
1729 format. See :hg:`help diffs` for more information.
1731 format. See :hg:`help diffs` for more information.
1730
1732
1731 With the --switch-parent option, the diff will be against the
1733 With the --switch-parent option, the diff will be against the
1732 second parent. It can be useful to review a merge.
1734 second parent. It can be useful to review a merge.
1733
1735
1734 Returns 0 on success.
1736 Returns 0 on success.
1735 """
1737 """
1736 changesets += tuple(opts.get('rev', []))
1738 changesets += tuple(opts.get('rev', []))
1737 if not changesets:
1739 if not changesets:
1738 raise util.Abort(_("export requires at least one changeset"))
1740 raise util.Abort(_("export requires at least one changeset"))
1739 revs = cmdutil.revrange(repo, changesets)
1741 revs = cmdutil.revrange(repo, changesets)
1740 if len(revs) > 1:
1742 if len(revs) > 1:
1741 ui.note(_('exporting patches:\n'))
1743 ui.note(_('exporting patches:\n'))
1742 else:
1744 else:
1743 ui.note(_('exporting patch:\n'))
1745 ui.note(_('exporting patch:\n'))
1744 cmdutil.export(repo, revs, template=opts.get('output'),
1746 cmdutil.export(repo, revs, template=opts.get('output'),
1745 switch_parent=opts.get('switch_parent'),
1747 switch_parent=opts.get('switch_parent'),
1746 opts=patch.diffopts(ui, opts))
1748 opts=patch.diffopts(ui, opts))
1747
1749
1748 def forget(ui, repo, *pats, **opts):
1750 def forget(ui, repo, *pats, **opts):
1749 """forget the specified files on the next commit
1751 """forget the specified files on the next commit
1750
1752
1751 Mark the specified files so they will no longer be tracked
1753 Mark the specified files so they will no longer be tracked
1752 after the next commit.
1754 after the next commit.
1753
1755
1754 This only removes files from the current branch, not from the
1756 This only removes files from the current branch, not from the
1755 entire project history, and it does not delete them from the
1757 entire project history, and it does not delete them from the
1756 working directory.
1758 working directory.
1757
1759
1758 To undo a forget before the next commit, see :hg:`add`.
1760 To undo a forget before the next commit, see :hg:`add`.
1759
1761
1760 Returns 0 on success.
1762 Returns 0 on success.
1761 """
1763 """
1762
1764
1763 if not pats:
1765 if not pats:
1764 raise util.Abort(_('no files specified'))
1766 raise util.Abort(_('no files specified'))
1765
1767
1766 m = cmdutil.match(repo, pats, opts)
1768 m = cmdutil.match(repo, pats, opts)
1767 s = repo.status(match=m, clean=True)
1769 s = repo.status(match=m, clean=True)
1768 forget = sorted(s[0] + s[1] + s[3] + s[6])
1770 forget = sorted(s[0] + s[1] + s[3] + s[6])
1769 errs = 0
1771 errs = 0
1770
1772
1771 for f in m.files():
1773 for f in m.files():
1772 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1774 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1773 ui.warn(_('not removing %s: file is already untracked\n')
1775 ui.warn(_('not removing %s: file is already untracked\n')
1774 % m.rel(f))
1776 % m.rel(f))
1775 errs = 1
1777 errs = 1
1776
1778
1777 for f in forget:
1779 for f in forget:
1778 if ui.verbose or not m.exact(f):
1780 if ui.verbose or not m.exact(f):
1779 ui.status(_('removing %s\n') % m.rel(f))
1781 ui.status(_('removing %s\n') % m.rel(f))
1780
1782
1781 repo[None].remove(forget, unlink=False)
1783 repo[None].remove(forget, unlink=False)
1782 return errs
1784 return errs
1783
1785
1784 def grep(ui, repo, pattern, *pats, **opts):
1786 def grep(ui, repo, pattern, *pats, **opts):
1785 """search for a pattern in specified files and revisions
1787 """search for a pattern in specified files and revisions
1786
1788
1787 Search revisions of files for a regular expression.
1789 Search revisions of files for a regular expression.
1788
1790
1789 This command behaves differently than Unix grep. It only accepts
1791 This command behaves differently than Unix grep. It only accepts
1790 Python/Perl regexps. It searches repository history, not the
1792 Python/Perl regexps. It searches repository history, not the
1791 working directory. It always prints the revision number in which a
1793 working directory. It always prints the revision number in which a
1792 match appears.
1794 match appears.
1793
1795
1794 By default, grep only prints output for the first revision of a
1796 By default, grep only prints output for the first revision of a
1795 file in which it finds a match. To get it to print every revision
1797 file in which it finds a match. To get it to print every revision
1796 that contains a change in match status ("-" for a match that
1798 that contains a change in match status ("-" for a match that
1797 becomes a non-match, or "+" for a non-match that becomes a match),
1799 becomes a non-match, or "+" for a non-match that becomes a match),
1798 use the --all flag.
1800 use the --all flag.
1799
1801
1800 Returns 0 if a match is found, 1 otherwise.
1802 Returns 0 if a match is found, 1 otherwise.
1801 """
1803 """
1802 reflags = 0
1804 reflags = 0
1803 if opts.get('ignore_case'):
1805 if opts.get('ignore_case'):
1804 reflags |= re.I
1806 reflags |= re.I
1805 try:
1807 try:
1806 regexp = re.compile(pattern, reflags)
1808 regexp = re.compile(pattern, reflags)
1807 except re.error, inst:
1809 except re.error, inst:
1808 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1810 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1809 return 1
1811 return 1
1810 sep, eol = ':', '\n'
1812 sep, eol = ':', '\n'
1811 if opts.get('print0'):
1813 if opts.get('print0'):
1812 sep = eol = '\0'
1814 sep = eol = '\0'
1813
1815
1814 getfile = util.lrucachefunc(repo.file)
1816 getfile = util.lrucachefunc(repo.file)
1815
1817
1816 def matchlines(body):
1818 def matchlines(body):
1817 begin = 0
1819 begin = 0
1818 linenum = 0
1820 linenum = 0
1819 while True:
1821 while True:
1820 match = regexp.search(body, begin)
1822 match = regexp.search(body, begin)
1821 if not match:
1823 if not match:
1822 break
1824 break
1823 mstart, mend = match.span()
1825 mstart, mend = match.span()
1824 linenum += body.count('\n', begin, mstart) + 1
1826 linenum += body.count('\n', begin, mstart) + 1
1825 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1827 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1826 begin = body.find('\n', mend) + 1 or len(body)
1828 begin = body.find('\n', mend) + 1 or len(body)
1827 lend = begin - 1
1829 lend = begin - 1
1828 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1830 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1829
1831
1830 class linestate(object):
1832 class linestate(object):
1831 def __init__(self, line, linenum, colstart, colend):
1833 def __init__(self, line, linenum, colstart, colend):
1832 self.line = line
1834 self.line = line
1833 self.linenum = linenum
1835 self.linenum = linenum
1834 self.colstart = colstart
1836 self.colstart = colstart
1835 self.colend = colend
1837 self.colend = colend
1836
1838
1837 def __hash__(self):
1839 def __hash__(self):
1838 return hash((self.linenum, self.line))
1840 return hash((self.linenum, self.line))
1839
1841
1840 def __eq__(self, other):
1842 def __eq__(self, other):
1841 return self.line == other.line
1843 return self.line == other.line
1842
1844
1843 matches = {}
1845 matches = {}
1844 copies = {}
1846 copies = {}
1845 def grepbody(fn, rev, body):
1847 def grepbody(fn, rev, body):
1846 matches[rev].setdefault(fn, [])
1848 matches[rev].setdefault(fn, [])
1847 m = matches[rev][fn]
1849 m = matches[rev][fn]
1848 for lnum, cstart, cend, line in matchlines(body):
1850 for lnum, cstart, cend, line in matchlines(body):
1849 s = linestate(line, lnum, cstart, cend)
1851 s = linestate(line, lnum, cstart, cend)
1850 m.append(s)
1852 m.append(s)
1851
1853
1852 def difflinestates(a, b):
1854 def difflinestates(a, b):
1853 sm = difflib.SequenceMatcher(None, a, b)
1855 sm = difflib.SequenceMatcher(None, a, b)
1854 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1856 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1855 if tag == 'insert':
1857 if tag == 'insert':
1856 for i in xrange(blo, bhi):
1858 for i in xrange(blo, bhi):
1857 yield ('+', b[i])
1859 yield ('+', b[i])
1858 elif tag == 'delete':
1860 elif tag == 'delete':
1859 for i in xrange(alo, ahi):
1861 for i in xrange(alo, ahi):
1860 yield ('-', a[i])
1862 yield ('-', a[i])
1861 elif tag == 'replace':
1863 elif tag == 'replace':
1862 for i in xrange(alo, ahi):
1864 for i in xrange(alo, ahi):
1863 yield ('-', a[i])
1865 yield ('-', a[i])
1864 for i in xrange(blo, bhi):
1866 for i in xrange(blo, bhi):
1865 yield ('+', b[i])
1867 yield ('+', b[i])
1866
1868
1867 def display(fn, ctx, pstates, states):
1869 def display(fn, ctx, pstates, states):
1868 rev = ctx.rev()
1870 rev = ctx.rev()
1869 datefunc = ui.quiet and util.shortdate or util.datestr
1871 datefunc = ui.quiet and util.shortdate or util.datestr
1870 found = False
1872 found = False
1871 filerevmatches = {}
1873 filerevmatches = {}
1872 if opts.get('all'):
1874 if opts.get('all'):
1873 iter = difflinestates(pstates, states)
1875 iter = difflinestates(pstates, states)
1874 else:
1876 else:
1875 iter = [('', l) for l in states]
1877 iter = [('', l) for l in states]
1876 for change, l in iter:
1878 for change, l in iter:
1877 cols = [fn, str(rev)]
1879 cols = [fn, str(rev)]
1878 before, match, after = None, None, None
1880 before, match, after = None, None, None
1879 if opts.get('line_number'):
1881 if opts.get('line_number'):
1880 cols.append(str(l.linenum))
1882 cols.append(str(l.linenum))
1881 if opts.get('all'):
1883 if opts.get('all'):
1882 cols.append(change)
1884 cols.append(change)
1883 if opts.get('user'):
1885 if opts.get('user'):
1884 cols.append(ui.shortuser(ctx.user()))
1886 cols.append(ui.shortuser(ctx.user()))
1885 if opts.get('date'):
1887 if opts.get('date'):
1886 cols.append(datefunc(ctx.date()))
1888 cols.append(datefunc(ctx.date()))
1887 if opts.get('files_with_matches'):
1889 if opts.get('files_with_matches'):
1888 c = (fn, rev)
1890 c = (fn, rev)
1889 if c in filerevmatches:
1891 if c in filerevmatches:
1890 continue
1892 continue
1891 filerevmatches[c] = 1
1893 filerevmatches[c] = 1
1892 else:
1894 else:
1893 before = l.line[:l.colstart]
1895 before = l.line[:l.colstart]
1894 match = l.line[l.colstart:l.colend]
1896 match = l.line[l.colstart:l.colend]
1895 after = l.line[l.colend:]
1897 after = l.line[l.colend:]
1896 ui.write(sep.join(cols))
1898 ui.write(sep.join(cols))
1897 if before is not None:
1899 if before is not None:
1898 ui.write(sep + before)
1900 ui.write(sep + before)
1899 ui.write(match, label='grep.match')
1901 ui.write(match, label='grep.match')
1900 ui.write(after)
1902 ui.write(after)
1901 ui.write(eol)
1903 ui.write(eol)
1902 found = True
1904 found = True
1903 return found
1905 return found
1904
1906
1905 skip = {}
1907 skip = {}
1906 revfiles = {}
1908 revfiles = {}
1907 matchfn = cmdutil.match(repo, pats, opts)
1909 matchfn = cmdutil.match(repo, pats, opts)
1908 found = False
1910 found = False
1909 follow = opts.get('follow')
1911 follow = opts.get('follow')
1910
1912
1911 def prep(ctx, fns):
1913 def prep(ctx, fns):
1912 rev = ctx.rev()
1914 rev = ctx.rev()
1913 pctx = ctx.p1()
1915 pctx = ctx.p1()
1914 parent = pctx.rev()
1916 parent = pctx.rev()
1915 matches.setdefault(rev, {})
1917 matches.setdefault(rev, {})
1916 matches.setdefault(parent, {})
1918 matches.setdefault(parent, {})
1917 files = revfiles.setdefault(rev, [])
1919 files = revfiles.setdefault(rev, [])
1918 for fn in fns:
1920 for fn in fns:
1919 flog = getfile(fn)
1921 flog = getfile(fn)
1920 try:
1922 try:
1921 fnode = ctx.filenode(fn)
1923 fnode = ctx.filenode(fn)
1922 except error.LookupError:
1924 except error.LookupError:
1923 continue
1925 continue
1924
1926
1925 copied = flog.renamed(fnode)
1927 copied = flog.renamed(fnode)
1926 copy = follow and copied and copied[0]
1928 copy = follow and copied and copied[0]
1927 if copy:
1929 if copy:
1928 copies.setdefault(rev, {})[fn] = copy
1930 copies.setdefault(rev, {})[fn] = copy
1929 if fn in skip:
1931 if fn in skip:
1930 if copy:
1932 if copy:
1931 skip[copy] = True
1933 skip[copy] = True
1932 continue
1934 continue
1933 files.append(fn)
1935 files.append(fn)
1934
1936
1935 if fn not in matches[rev]:
1937 if fn not in matches[rev]:
1936 grepbody(fn, rev, flog.read(fnode))
1938 grepbody(fn, rev, flog.read(fnode))
1937
1939
1938 pfn = copy or fn
1940 pfn = copy or fn
1939 if pfn not in matches[parent]:
1941 if pfn not in matches[parent]:
1940 try:
1942 try:
1941 fnode = pctx.filenode(pfn)
1943 fnode = pctx.filenode(pfn)
1942 grepbody(pfn, parent, flog.read(fnode))
1944 grepbody(pfn, parent, flog.read(fnode))
1943 except error.LookupError:
1945 except error.LookupError:
1944 pass
1946 pass
1945
1947
1946 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1948 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1947 rev = ctx.rev()
1949 rev = ctx.rev()
1948 parent = ctx.p1().rev()
1950 parent = ctx.p1().rev()
1949 for fn in sorted(revfiles.get(rev, [])):
1951 for fn in sorted(revfiles.get(rev, [])):
1950 states = matches[rev][fn]
1952 states = matches[rev][fn]
1951 copy = copies.get(rev, {}).get(fn)
1953 copy = copies.get(rev, {}).get(fn)
1952 if fn in skip:
1954 if fn in skip:
1953 if copy:
1955 if copy:
1954 skip[copy] = True
1956 skip[copy] = True
1955 continue
1957 continue
1956 pstates = matches.get(parent, {}).get(copy or fn, [])
1958 pstates = matches.get(parent, {}).get(copy or fn, [])
1957 if pstates or states:
1959 if pstates or states:
1958 r = display(fn, ctx, pstates, states)
1960 r = display(fn, ctx, pstates, states)
1959 found = found or r
1961 found = found or r
1960 if r and not opts.get('all'):
1962 if r and not opts.get('all'):
1961 skip[fn] = True
1963 skip[fn] = True
1962 if copy:
1964 if copy:
1963 skip[copy] = True
1965 skip[copy] = True
1964 del matches[rev]
1966 del matches[rev]
1965 del revfiles[rev]
1967 del revfiles[rev]
1966
1968
1967 return not found
1969 return not found
1968
1970
1969 def heads(ui, repo, *branchrevs, **opts):
1971 def heads(ui, repo, *branchrevs, **opts):
1970 """show current repository heads or show branch heads
1972 """show current repository heads or show branch heads
1971
1973
1972 With no arguments, show all repository branch heads.
1974 With no arguments, show all repository branch heads.
1973
1975
1974 Repository "heads" are changesets with no child changesets. They are
1976 Repository "heads" are changesets with no child changesets. They are
1975 where development generally takes place and are the usual targets
1977 where development generally takes place and are the usual targets
1976 for update and merge operations. Branch heads are changesets that have
1978 for update and merge operations. Branch heads are changesets that have
1977 no child changeset on the same branch.
1979 no child changeset on the same branch.
1978
1980
1979 If one or more REVs are given, only branch heads on the branches
1981 If one or more REVs are given, only branch heads on the branches
1980 associated with the specified changesets are shown.
1982 associated with the specified changesets are shown.
1981
1983
1982 If -c/--closed is specified, also show branch heads marked closed
1984 If -c/--closed is specified, also show branch heads marked closed
1983 (see :hg:`commit --close-branch`).
1985 (see :hg:`commit --close-branch`).
1984
1986
1985 If STARTREV is specified, only those heads that are descendants of
1987 If STARTREV is specified, only those heads that are descendants of
1986 STARTREV will be displayed.
1988 STARTREV will be displayed.
1987
1989
1988 If -t/--topo is specified, named branch mechanics will be ignored and only
1990 If -t/--topo is specified, named branch mechanics will be ignored and only
1989 changesets without children will be shown.
1991 changesets without children will be shown.
1990
1992
1991 Returns 0 if matching heads are found, 1 if not.
1993 Returns 0 if matching heads are found, 1 if not.
1992 """
1994 """
1993
1995
1994 start = None
1996 start = None
1995 if 'rev' in opts:
1997 if 'rev' in opts:
1996 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1998 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1997
1999
1998 if opts.get('topo'):
2000 if opts.get('topo'):
1999 heads = [repo[h] for h in repo.heads(start)]
2001 heads = [repo[h] for h in repo.heads(start)]
2000 else:
2002 else:
2001 heads = []
2003 heads = []
2002 for b, ls in repo.branchmap().iteritems():
2004 for b, ls in repo.branchmap().iteritems():
2003 if start is None:
2005 if start is None:
2004 heads += [repo[h] for h in ls]
2006 heads += [repo[h] for h in ls]
2005 continue
2007 continue
2006 startrev = repo.changelog.rev(start)
2008 startrev = repo.changelog.rev(start)
2007 descendants = set(repo.changelog.descendants(startrev))
2009 descendants = set(repo.changelog.descendants(startrev))
2008 descendants.add(startrev)
2010 descendants.add(startrev)
2009 rev = repo.changelog.rev
2011 rev = repo.changelog.rev
2010 heads += [repo[h] for h in ls if rev(h) in descendants]
2012 heads += [repo[h] for h in ls if rev(h) in descendants]
2011
2013
2012 if branchrevs:
2014 if branchrevs:
2013 branches = set(repo[br].branch() for br in branchrevs)
2015 branches = set(repo[br].branch() for br in branchrevs)
2014 heads = [h for h in heads if h.branch() in branches]
2016 heads = [h for h in heads if h.branch() in branches]
2015
2017
2016 if not opts.get('closed'):
2018 if not opts.get('closed'):
2017 heads = [h for h in heads if not h.extra().get('close')]
2019 heads = [h for h in heads if not h.extra().get('close')]
2018
2020
2019 if opts.get('active') and branchrevs:
2021 if opts.get('active') and branchrevs:
2020 dagheads = repo.heads(start)
2022 dagheads = repo.heads(start)
2021 heads = [h for h in heads if h.node() in dagheads]
2023 heads = [h for h in heads if h.node() in dagheads]
2022
2024
2023 if branchrevs:
2025 if branchrevs:
2024 haveheads = set(h.branch() for h in heads)
2026 haveheads = set(h.branch() for h in heads)
2025 if branches - haveheads:
2027 if branches - haveheads:
2026 headless = ', '.join(b for b in branches - haveheads)
2028 headless = ', '.join(b for b in branches - haveheads)
2027 msg = _('no open branch heads found on branches %s')
2029 msg = _('no open branch heads found on branches %s')
2028 if opts.get('rev'):
2030 if opts.get('rev'):
2029 msg += _(' (started at %s)' % opts['rev'])
2031 msg += _(' (started at %s)' % opts['rev'])
2030 ui.warn((msg + '\n') % headless)
2032 ui.warn((msg + '\n') % headless)
2031
2033
2032 if not heads:
2034 if not heads:
2033 return 1
2035 return 1
2034
2036
2035 heads = sorted(heads, key=lambda x: -x.rev())
2037 heads = sorted(heads, key=lambda x: -x.rev())
2036 displayer = cmdutil.show_changeset(ui, repo, opts)
2038 displayer = cmdutil.show_changeset(ui, repo, opts)
2037 for ctx in heads:
2039 for ctx in heads:
2038 displayer.show(ctx)
2040 displayer.show(ctx)
2039 displayer.close()
2041 displayer.close()
2040
2042
2041 def help_(ui, name=None, with_version=False, unknowncmd=False):
2043 def help_(ui, name=None, with_version=False, unknowncmd=False):
2042 """show help for a given topic or a help overview
2044 """show help for a given topic or a help overview
2043
2045
2044 With no arguments, print a list of commands with short help messages.
2046 With no arguments, print a list of commands with short help messages.
2045
2047
2046 Given a topic, extension, or command name, print help for that
2048 Given a topic, extension, or command name, print help for that
2047 topic.
2049 topic.
2048
2050
2049 Returns 0 if successful.
2051 Returns 0 if successful.
2050 """
2052 """
2051 option_lists = []
2053 option_lists = []
2052 textwidth = min(ui.termwidth(), 80) - 2
2054 textwidth = min(ui.termwidth(), 80) - 2
2053
2055
2054 def addglobalopts(aliases):
2056 def addglobalopts(aliases):
2055 if ui.verbose:
2057 if ui.verbose:
2056 option_lists.append((_("global options:"), globalopts))
2058 option_lists.append((_("global options:"), globalopts))
2057 if name == 'shortlist':
2059 if name == 'shortlist':
2058 option_lists.append((_('use "hg help" for the full list '
2060 option_lists.append((_('use "hg help" for the full list '
2059 'of commands'), ()))
2061 'of commands'), ()))
2060 else:
2062 else:
2061 if name == 'shortlist':
2063 if name == 'shortlist':
2062 msg = _('use "hg help" for the full list of commands '
2064 msg = _('use "hg help" for the full list of commands '
2063 'or "hg -v" for details')
2065 'or "hg -v" for details')
2064 elif aliases:
2066 elif aliases:
2065 msg = _('use "hg -v help%s" to show builtin aliases and '
2067 msg = _('use "hg -v help%s" to show builtin aliases and '
2066 'global options') % (name and " " + name or "")
2068 'global options') % (name and " " + name or "")
2067 else:
2069 else:
2068 msg = _('use "hg -v help %s" to show global options') % name
2070 msg = _('use "hg -v help %s" to show global options') % name
2069 option_lists.append((msg, ()))
2071 option_lists.append((msg, ()))
2070
2072
2071 def helpcmd(name):
2073 def helpcmd(name):
2072 if with_version:
2074 if with_version:
2073 version_(ui)
2075 version_(ui)
2074 ui.write('\n')
2076 ui.write('\n')
2075
2077
2076 try:
2078 try:
2077 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2079 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2078 except error.AmbiguousCommand, inst:
2080 except error.AmbiguousCommand, inst:
2079 # py3k fix: except vars can't be used outside the scope of the
2081 # py3k fix: except vars can't be used outside the scope of the
2080 # except block, nor can be used inside a lambda. python issue4617
2082 # except block, nor can be used inside a lambda. python issue4617
2081 prefix = inst.args[0]
2083 prefix = inst.args[0]
2082 select = lambda c: c.lstrip('^').startswith(prefix)
2084 select = lambda c: c.lstrip('^').startswith(prefix)
2083 helplist(_('list of commands:\n\n'), select)
2085 helplist(_('list of commands:\n\n'), select)
2084 return
2086 return
2085
2087
2086 # check if it's an invalid alias and display its error if it is
2088 # check if it's an invalid alias and display its error if it is
2087 if getattr(entry[0], 'badalias', False):
2089 if getattr(entry[0], 'badalias', False):
2088 if not unknowncmd:
2090 if not unknowncmd:
2089 entry[0](ui)
2091 entry[0](ui)
2090 return
2092 return
2091
2093
2092 # synopsis
2094 # synopsis
2093 if len(entry) > 2:
2095 if len(entry) > 2:
2094 if entry[2].startswith('hg'):
2096 if entry[2].startswith('hg'):
2095 ui.write("%s\n" % entry[2])
2097 ui.write("%s\n" % entry[2])
2096 else:
2098 else:
2097 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2099 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2098 else:
2100 else:
2099 ui.write('hg %s\n' % aliases[0])
2101 ui.write('hg %s\n' % aliases[0])
2100
2102
2101 # aliases
2103 # aliases
2102 if not ui.quiet and len(aliases) > 1:
2104 if not ui.quiet and len(aliases) > 1:
2103 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2105 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2104
2106
2105 # description
2107 # description
2106 doc = gettext(entry[0].__doc__)
2108 doc = gettext(entry[0].__doc__)
2107 if not doc:
2109 if not doc:
2108 doc = _("(no help text available)")
2110 doc = _("(no help text available)")
2109 if hasattr(entry[0], 'definition'): # aliased command
2111 if hasattr(entry[0], 'definition'): # aliased command
2110 if entry[0].definition.startswith('!'): # shell alias
2112 if entry[0].definition.startswith('!'): # shell alias
2111 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2113 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2112 else:
2114 else:
2113 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2115 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2114 if ui.quiet:
2116 if ui.quiet:
2115 doc = doc.splitlines()[0]
2117 doc = doc.splitlines()[0]
2116 keep = ui.verbose and ['verbose'] or []
2118 keep = ui.verbose and ['verbose'] or []
2117 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2119 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2118 ui.write("\n%s\n" % formatted)
2120 ui.write("\n%s\n" % formatted)
2119 if pruned:
2121 if pruned:
2120 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2122 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2121
2123
2122 if not ui.quiet:
2124 if not ui.quiet:
2123 # options
2125 # options
2124 if entry[1]:
2126 if entry[1]:
2125 option_lists.append((_("options:\n"), entry[1]))
2127 option_lists.append((_("options:\n"), entry[1]))
2126
2128
2127 addglobalopts(False)
2129 addglobalopts(False)
2128
2130
2129 def helplist(header, select=None):
2131 def helplist(header, select=None):
2130 h = {}
2132 h = {}
2131 cmds = {}
2133 cmds = {}
2132 for c, e in table.iteritems():
2134 for c, e in table.iteritems():
2133 f = c.split("|", 1)[0]
2135 f = c.split("|", 1)[0]
2134 if select and not select(f):
2136 if select and not select(f):
2135 continue
2137 continue
2136 if (not select and name != 'shortlist' and
2138 if (not select and name != 'shortlist' and
2137 e[0].__module__ != __name__):
2139 e[0].__module__ != __name__):
2138 continue
2140 continue
2139 if name == "shortlist" and not f.startswith("^"):
2141 if name == "shortlist" and not f.startswith("^"):
2140 continue
2142 continue
2141 f = f.lstrip("^")
2143 f = f.lstrip("^")
2142 if not ui.debugflag and f.startswith("debug"):
2144 if not ui.debugflag and f.startswith("debug"):
2143 continue
2145 continue
2144 doc = e[0].__doc__
2146 doc = e[0].__doc__
2145 if doc and 'DEPRECATED' in doc and not ui.verbose:
2147 if doc and 'DEPRECATED' in doc and not ui.verbose:
2146 continue
2148 continue
2147 doc = gettext(doc)
2149 doc = gettext(doc)
2148 if not doc:
2150 if not doc:
2149 doc = _("(no help text available)")
2151 doc = _("(no help text available)")
2150 h[f] = doc.splitlines()[0].rstrip()
2152 h[f] = doc.splitlines()[0].rstrip()
2151 cmds[f] = c.lstrip("^")
2153 cmds[f] = c.lstrip("^")
2152
2154
2153 if not h:
2155 if not h:
2154 ui.status(_('no commands defined\n'))
2156 ui.status(_('no commands defined\n'))
2155 return
2157 return
2156
2158
2157 ui.status(header)
2159 ui.status(header)
2158 fns = sorted(h)
2160 fns = sorted(h)
2159 m = max(map(len, fns))
2161 m = max(map(len, fns))
2160 for f in fns:
2162 for f in fns:
2161 if ui.verbose:
2163 if ui.verbose:
2162 commands = cmds[f].replace("|",", ")
2164 commands = cmds[f].replace("|",", ")
2163 ui.write(" %s:\n %s\n"%(commands, h[f]))
2165 ui.write(" %s:\n %s\n"%(commands, h[f]))
2164 else:
2166 else:
2165 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2167 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2166 initindent=' %-*s ' % (m, f),
2168 initindent=' %-*s ' % (m, f),
2167 hangindent=' ' * (m + 4))))
2169 hangindent=' ' * (m + 4))))
2168
2170
2169 if not ui.quiet:
2171 if not ui.quiet:
2170 addglobalopts(True)
2172 addglobalopts(True)
2171
2173
2172 def helptopic(name):
2174 def helptopic(name):
2173 for names, header, doc in help.helptable:
2175 for names, header, doc in help.helptable:
2174 if name in names:
2176 if name in names:
2175 break
2177 break
2176 else:
2178 else:
2177 raise error.UnknownCommand(name)
2179 raise error.UnknownCommand(name)
2178
2180
2179 # description
2181 # description
2180 if not doc:
2182 if not doc:
2181 doc = _("(no help text available)")
2183 doc = _("(no help text available)")
2182 if hasattr(doc, '__call__'):
2184 if hasattr(doc, '__call__'):
2183 doc = doc()
2185 doc = doc()
2184
2186
2185 ui.write("%s\n\n" % header)
2187 ui.write("%s\n\n" % header)
2186 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2188 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2187
2189
2188 def helpext(name):
2190 def helpext(name):
2189 try:
2191 try:
2190 mod = extensions.find(name)
2192 mod = extensions.find(name)
2191 doc = gettext(mod.__doc__) or _('no help text available')
2193 doc = gettext(mod.__doc__) or _('no help text available')
2192 except KeyError:
2194 except KeyError:
2193 mod = None
2195 mod = None
2194 doc = extensions.disabledext(name)
2196 doc = extensions.disabledext(name)
2195 if not doc:
2197 if not doc:
2196 raise error.UnknownCommand(name)
2198 raise error.UnknownCommand(name)
2197
2199
2198 if '\n' not in doc:
2200 if '\n' not in doc:
2199 head, tail = doc, ""
2201 head, tail = doc, ""
2200 else:
2202 else:
2201 head, tail = doc.split('\n', 1)
2203 head, tail = doc.split('\n', 1)
2202 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2204 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2203 if tail:
2205 if tail:
2204 ui.write(minirst.format(tail, textwidth))
2206 ui.write(minirst.format(tail, textwidth))
2205 ui.status('\n\n')
2207 ui.status('\n\n')
2206
2208
2207 if mod:
2209 if mod:
2208 try:
2210 try:
2209 ct = mod.cmdtable
2211 ct = mod.cmdtable
2210 except AttributeError:
2212 except AttributeError:
2211 ct = {}
2213 ct = {}
2212 modcmds = set([c.split('|', 1)[0] for c in ct])
2214 modcmds = set([c.split('|', 1)[0] for c in ct])
2213 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2215 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2214 else:
2216 else:
2215 ui.write(_('use "hg help extensions" for information on enabling '
2217 ui.write(_('use "hg help extensions" for information on enabling '
2216 'extensions\n'))
2218 'extensions\n'))
2217
2219
2218 def helpextcmd(name):
2220 def helpextcmd(name):
2219 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2221 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2220 doc = gettext(mod.__doc__).splitlines()[0]
2222 doc = gettext(mod.__doc__).splitlines()[0]
2221
2223
2222 msg = help.listexts(_("'%s' is provided by the following "
2224 msg = help.listexts(_("'%s' is provided by the following "
2223 "extension:") % cmd, {ext: doc}, len(ext),
2225 "extension:") % cmd, {ext: doc}, len(ext),
2224 indent=4)
2226 indent=4)
2225 ui.write(minirst.format(msg, textwidth))
2227 ui.write(minirst.format(msg, textwidth))
2226 ui.write('\n\n')
2228 ui.write('\n\n')
2227 ui.write(_('use "hg help extensions" for information on enabling '
2229 ui.write(_('use "hg help extensions" for information on enabling '
2228 'extensions\n'))
2230 'extensions\n'))
2229
2231
2230 help.addtopichook('revsets', revset.makedoc)
2232 help.addtopichook('revsets', revset.makedoc)
2231 help.addtopichook('templates', templatekw.makedoc)
2233 help.addtopichook('templates', templatekw.makedoc)
2232 help.addtopichook('templates', templatefilters.makedoc)
2234 help.addtopichook('templates', templatefilters.makedoc)
2233
2235
2234 if name and name != 'shortlist':
2236 if name and name != 'shortlist':
2235 i = None
2237 i = None
2236 if unknowncmd:
2238 if unknowncmd:
2237 queries = (helpextcmd,)
2239 queries = (helpextcmd,)
2238 else:
2240 else:
2239 queries = (helptopic, helpcmd, helpext, helpextcmd)
2241 queries = (helptopic, helpcmd, helpext, helpextcmd)
2240 for f in queries:
2242 for f in queries:
2241 try:
2243 try:
2242 f(name)
2244 f(name)
2243 i = None
2245 i = None
2244 break
2246 break
2245 except error.UnknownCommand, inst:
2247 except error.UnknownCommand, inst:
2246 i = inst
2248 i = inst
2247 if i:
2249 if i:
2248 raise i
2250 raise i
2249
2251
2250 else:
2252 else:
2251 # program name
2253 # program name
2252 if ui.verbose or with_version:
2254 if ui.verbose or with_version:
2253 version_(ui)
2255 version_(ui)
2254 else:
2256 else:
2255 ui.status(_("Mercurial Distributed SCM\n"))
2257 ui.status(_("Mercurial Distributed SCM\n"))
2256 ui.status('\n')
2258 ui.status('\n')
2257
2259
2258 # list of commands
2260 # list of commands
2259 if name == "shortlist":
2261 if name == "shortlist":
2260 header = _('basic commands:\n\n')
2262 header = _('basic commands:\n\n')
2261 else:
2263 else:
2262 header = _('list of commands:\n\n')
2264 header = _('list of commands:\n\n')
2263
2265
2264 helplist(header)
2266 helplist(header)
2265 if name != 'shortlist':
2267 if name != 'shortlist':
2266 exts, maxlength = extensions.enabled()
2268 exts, maxlength = extensions.enabled()
2267 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2269 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2268 if text:
2270 if text:
2269 ui.write("\n%s\n" % minirst.format(text, textwidth))
2271 ui.write("\n%s\n" % minirst.format(text, textwidth))
2270
2272
2271 # list all option lists
2273 # list all option lists
2272 opt_output = []
2274 opt_output = []
2273 multioccur = False
2275 multioccur = False
2274 for title, options in option_lists:
2276 for title, options in option_lists:
2275 opt_output.append(("\n%s" % title, None))
2277 opt_output.append(("\n%s" % title, None))
2276 for option in options:
2278 for option in options:
2277 if len(option) == 5:
2279 if len(option) == 5:
2278 shortopt, longopt, default, desc, optlabel = option
2280 shortopt, longopt, default, desc, optlabel = option
2279 else:
2281 else:
2280 shortopt, longopt, default, desc = option
2282 shortopt, longopt, default, desc = option
2281 optlabel = _("VALUE") # default label
2283 optlabel = _("VALUE") # default label
2282
2284
2283 if _("DEPRECATED") in desc and not ui.verbose:
2285 if _("DEPRECATED") in desc and not ui.verbose:
2284 continue
2286 continue
2285 if isinstance(default, list):
2287 if isinstance(default, list):
2286 numqualifier = " %s [+]" % optlabel
2288 numqualifier = " %s [+]" % optlabel
2287 multioccur = True
2289 multioccur = True
2288 elif (default is not None) and not isinstance(default, bool):
2290 elif (default is not None) and not isinstance(default, bool):
2289 numqualifier = " %s" % optlabel
2291 numqualifier = " %s" % optlabel
2290 else:
2292 else:
2291 numqualifier = ""
2293 numqualifier = ""
2292 opt_output.append(("%2s%s" %
2294 opt_output.append(("%2s%s" %
2293 (shortopt and "-%s" % shortopt,
2295 (shortopt and "-%s" % shortopt,
2294 longopt and " --%s%s" %
2296 longopt and " --%s%s" %
2295 (longopt, numqualifier)),
2297 (longopt, numqualifier)),
2296 "%s%s" % (desc,
2298 "%s%s" % (desc,
2297 default
2299 default
2298 and _(" (default: %s)") % default
2300 and _(" (default: %s)") % default
2299 or "")))
2301 or "")))
2300 if multioccur:
2302 if multioccur:
2301 msg = _("\n[+] marked option can be specified multiple times")
2303 msg = _("\n[+] marked option can be specified multiple times")
2302 if ui.verbose and name != 'shortlist':
2304 if ui.verbose and name != 'shortlist':
2303 opt_output.append((msg, None))
2305 opt_output.append((msg, None))
2304 else:
2306 else:
2305 opt_output.insert(-1, (msg, None))
2307 opt_output.insert(-1, (msg, None))
2306
2308
2307 if not name:
2309 if not name:
2308 ui.write(_("\nadditional help topics:\n\n"))
2310 ui.write(_("\nadditional help topics:\n\n"))
2309 topics = []
2311 topics = []
2310 for names, header, doc in help.helptable:
2312 for names, header, doc in help.helptable:
2311 topics.append((sorted(names, key=len, reverse=True)[0], header))
2313 topics.append((sorted(names, key=len, reverse=True)[0], header))
2312 topics_len = max([len(s[0]) for s in topics])
2314 topics_len = max([len(s[0]) for s in topics])
2313 for t, desc in topics:
2315 for t, desc in topics:
2314 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2316 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2315
2317
2316 if opt_output:
2318 if opt_output:
2317 colwidth = encoding.colwidth
2319 colwidth = encoding.colwidth
2318 # normalize: (opt or message, desc or None, width of opt)
2320 # normalize: (opt or message, desc or None, width of opt)
2319 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2321 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2320 for opt, desc in opt_output]
2322 for opt, desc in opt_output]
2321 hanging = max([e[2] for e in entries])
2323 hanging = max([e[2] for e in entries])
2322 for opt, desc, width in entries:
2324 for opt, desc, width in entries:
2323 if desc:
2325 if desc:
2324 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2326 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2325 hangindent = ' ' * (hanging + 3)
2327 hangindent = ' ' * (hanging + 3)
2326 ui.write('%s\n' % (util.wrap(desc, textwidth,
2328 ui.write('%s\n' % (util.wrap(desc, textwidth,
2327 initindent=initindent,
2329 initindent=initindent,
2328 hangindent=hangindent)))
2330 hangindent=hangindent)))
2329 else:
2331 else:
2330 ui.write("%s\n" % opt)
2332 ui.write("%s\n" % opt)
2331
2333
2332 def identify(ui, repo, source=None, rev=None,
2334 def identify(ui, repo, source=None, rev=None,
2333 num=None, id=None, branch=None, tags=None, bookmarks=None):
2335 num=None, id=None, branch=None, tags=None, bookmarks=None):
2334 """identify the working copy or specified revision
2336 """identify the working copy or specified revision
2335
2337
2336 With no revision, print a summary of the current state of the
2338 With no revision, print a summary of the current state of the
2337 repository.
2339 repository.
2338
2340
2339 Specifying a path to a repository root or Mercurial bundle will
2341 Specifying a path to a repository root or Mercurial bundle will
2340 cause lookup to operate on that repository/bundle.
2342 cause lookup to operate on that repository/bundle.
2341
2343
2342 This summary identifies the repository state using one or two
2344 This summary identifies the repository state using one or two
2343 parent hash identifiers, followed by a "+" if there are
2345 parent hash identifiers, followed by a "+" if there are
2344 uncommitted changes in the working directory, a list of tags for
2346 uncommitted changes in the working directory, a list of tags for
2345 this revision and a branch name for non-default branches.
2347 this revision and a branch name for non-default branches.
2346
2348
2347 Returns 0 if successful.
2349 Returns 0 if successful.
2348 """
2350 """
2349
2351
2350 if not repo and not source:
2352 if not repo and not source:
2351 raise util.Abort(_("there is no Mercurial repository here "
2353 raise util.Abort(_("there is no Mercurial repository here "
2352 "(.hg not found)"))
2354 "(.hg not found)"))
2353
2355
2354 hexfunc = ui.debugflag and hex or short
2356 hexfunc = ui.debugflag and hex or short
2355 default = not (num or id or branch or tags or bookmarks)
2357 default = not (num or id or branch or tags or bookmarks)
2356 output = []
2358 output = []
2357
2359
2358 revs = []
2360 revs = []
2359 bms = []
2361 bms = []
2360 if source:
2362 if source:
2361 source, branches = hg.parseurl(ui.expandpath(source))
2363 source, branches = hg.parseurl(ui.expandpath(source))
2362 repo = hg.repository(ui, source)
2364 repo = hg.repository(ui, source)
2363 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2365 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2364
2366
2365 if not repo.local():
2367 if not repo.local():
2366 if not rev and revs:
2368 if not rev and revs:
2367 rev = revs[0]
2369 rev = revs[0]
2368 if not rev:
2370 if not rev:
2369 rev = "tip"
2371 rev = "tip"
2370 if num or branch or tags:
2372 if num or branch or tags:
2371 raise util.Abort(
2373 raise util.Abort(
2372 _("can't query remote revision number, branch, or tags"))
2374 _("can't query remote revision number, branch, or tags"))
2373
2375
2374 remoterev = repo.lookup(rev)
2376 remoterev = repo.lookup(rev)
2375 if default or id:
2377 if default or id:
2376 output = [hexfunc(remoterev)]
2378 output = [hexfunc(remoterev)]
2377
2379
2378 if 'bookmarks' in repo.listkeys('namespaces'):
2380 if 'bookmarks' in repo.listkeys('namespaces'):
2379 hexremoterev = hex(remoterev)
2381 hexremoterev = hex(remoterev)
2380 bms = [bm for bm, bmrev in repo.listkeys('bookmarks').iteritems()
2382 bms = [bm for bm, bmrev in repo.listkeys('bookmarks').iteritems()
2381 if bmrev == hexremoterev]
2383 if bmrev == hexremoterev]
2382
2384
2383 elif not rev:
2385 elif not rev:
2384 ctx = repo[None]
2386 ctx = repo[None]
2385 parents = ctx.parents()
2387 parents = ctx.parents()
2386 changed = False
2388 changed = False
2387 if default or id or num:
2389 if default or id or num:
2388 changed = util.any(repo.status())
2390 changed = util.any(repo.status())
2389 if default or id:
2391 if default or id:
2390 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2392 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2391 (changed) and "+" or "")]
2393 (changed) and "+" or "")]
2392 if num:
2394 if num:
2393 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2395 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2394 (changed) and "+" or ""))
2396 (changed) and "+" or ""))
2395 else:
2397 else:
2396 ctx = cmdutil.revsingle(repo, rev)
2398 ctx = cmdutil.revsingle(repo, rev)
2397 if default or id:
2399 if default or id:
2398 output = [hexfunc(ctx.node())]
2400 output = [hexfunc(ctx.node())]
2399 if num:
2401 if num:
2400 output.append(str(ctx.rev()))
2402 output.append(str(ctx.rev()))
2401
2403
2402 if repo.local():
2404 if repo.local():
2403 bms = ctx.bookmarks()
2405 bms = ctx.bookmarks()
2404
2406
2405 if repo.local() and default and not ui.quiet:
2407 if repo.local() and default and not ui.quiet:
2406 b = ctx.branch()
2408 b = ctx.branch()
2407 if b != 'default':
2409 if b != 'default':
2408 output.append("(%s)" % b)
2410 output.append("(%s)" % b)
2409
2411
2410 # multiple tags for a single parent separated by '/'
2412 # multiple tags for a single parent separated by '/'
2411 t = "/".join(ctx.tags())
2413 t = "/".join(ctx.tags())
2412 if t:
2414 if t:
2413 output.append(t)
2415 output.append(t)
2414
2416
2415 if default and not ui.quiet:
2417 if default and not ui.quiet:
2416 # multiple bookmarks for a single parent separated by '/'
2418 # multiple bookmarks for a single parent separated by '/'
2417 bm = '/'.join(bms)
2419 bm = '/'.join(bms)
2418 if bm:
2420 if bm:
2419 output.append(bm)
2421 output.append(bm)
2420
2422
2421 if branch:
2423 if branch:
2422 output.append(ctx.branch())
2424 output.append(ctx.branch())
2423
2425
2424 if tags:
2426 if tags:
2425 output.extend(ctx.tags())
2427 output.extend(ctx.tags())
2426
2428
2427 if bookmarks:
2429 if bookmarks:
2428 output.extend(bms)
2430 output.extend(bms)
2429
2431
2430 ui.write("%s\n" % ' '.join(output))
2432 ui.write("%s\n" % ' '.join(output))
2431
2433
2432 def import_(ui, repo, patch1, *patches, **opts):
2434 def import_(ui, repo, patch1, *patches, **opts):
2433 """import an ordered set of patches
2435 """import an ordered set of patches
2434
2436
2435 Import a list of patches and commit them individually (unless
2437 Import a list of patches and commit them individually (unless
2436 --no-commit is specified).
2438 --no-commit is specified).
2437
2439
2438 If there are outstanding changes in the working directory, import
2440 If there are outstanding changes in the working directory, import
2439 will abort unless given the -f/--force flag.
2441 will abort unless given the -f/--force flag.
2440
2442
2441 You can import a patch straight from a mail message. Even patches
2443 You can import a patch straight from a mail message. Even patches
2442 as attachments work (to use the body part, it must have type
2444 as attachments work (to use the body part, it must have type
2443 text/plain or text/x-patch). From and Subject headers of email
2445 text/plain or text/x-patch). From and Subject headers of email
2444 message are used as default committer and commit message. All
2446 message are used as default committer and commit message. All
2445 text/plain body parts before first diff are added to commit
2447 text/plain body parts before first diff are added to commit
2446 message.
2448 message.
2447
2449
2448 If the imported patch was generated by :hg:`export`, user and
2450 If the imported patch was generated by :hg:`export`, user and
2449 description from patch override values from message headers and
2451 description from patch override values from message headers and
2450 body. Values given on command line with -m/--message and -u/--user
2452 body. Values given on command line with -m/--message and -u/--user
2451 override these.
2453 override these.
2452
2454
2453 If --exact is specified, import will set the working directory to
2455 If --exact is specified, import will set the working directory to
2454 the parent of each patch before applying it, and will abort if the
2456 the parent of each patch before applying it, and will abort if the
2455 resulting changeset has a different ID than the one recorded in
2457 resulting changeset has a different ID than the one recorded in
2456 the patch. This may happen due to character set problems or other
2458 the patch. This may happen due to character set problems or other
2457 deficiencies in the text patch format.
2459 deficiencies in the text patch format.
2458
2460
2459 With -s/--similarity, hg will attempt to discover renames and
2461 With -s/--similarity, hg will attempt to discover renames and
2460 copies in the patch in the same way as 'addremove'.
2462 copies in the patch in the same way as 'addremove'.
2461
2463
2462 To read a patch from standard input, use "-" as the patch name. If
2464 To read a patch from standard input, use "-" as the patch name. If
2463 a URL is specified, the patch will be downloaded from it.
2465 a URL is specified, the patch will be downloaded from it.
2464 See :hg:`help dates` for a list of formats valid for -d/--date.
2466 See :hg:`help dates` for a list of formats valid for -d/--date.
2465
2467
2466 Returns 0 on success.
2468 Returns 0 on success.
2467 """
2469 """
2468 patches = (patch1,) + patches
2470 patches = (patch1,) + patches
2469
2471
2470 date = opts.get('date')
2472 date = opts.get('date')
2471 if date:
2473 if date:
2472 opts['date'] = util.parsedate(date)
2474 opts['date'] = util.parsedate(date)
2473
2475
2474 try:
2476 try:
2475 sim = float(opts.get('similarity') or 0)
2477 sim = float(opts.get('similarity') or 0)
2476 except ValueError:
2478 except ValueError:
2477 raise util.Abort(_('similarity must be a number'))
2479 raise util.Abort(_('similarity must be a number'))
2478 if sim < 0 or sim > 100:
2480 if sim < 0 or sim > 100:
2479 raise util.Abort(_('similarity must be between 0 and 100'))
2481 raise util.Abort(_('similarity must be between 0 and 100'))
2480
2482
2481 if opts.get('exact') or not opts.get('force'):
2483 if opts.get('exact') or not opts.get('force'):
2482 cmdutil.bail_if_changed(repo)
2484 cmdutil.bail_if_changed(repo)
2483
2485
2484 d = opts["base"]
2486 d = opts["base"]
2485 strip = opts["strip"]
2487 strip = opts["strip"]
2486 wlock = lock = None
2488 wlock = lock = None
2487 msgs = []
2489 msgs = []
2488
2490
2489 def tryone(ui, hunk):
2491 def tryone(ui, hunk):
2490 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2492 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2491 patch.extract(ui, hunk)
2493 patch.extract(ui, hunk)
2492
2494
2493 if not tmpname:
2495 if not tmpname:
2494 return None
2496 return None
2495 commitid = _('to working directory')
2497 commitid = _('to working directory')
2496
2498
2497 try:
2499 try:
2498 cmdline_message = cmdutil.logmessage(opts)
2500 cmdline_message = cmdutil.logmessage(opts)
2499 if cmdline_message:
2501 if cmdline_message:
2500 # pickup the cmdline msg
2502 # pickup the cmdline msg
2501 message = cmdline_message
2503 message = cmdline_message
2502 elif message:
2504 elif message:
2503 # pickup the patch msg
2505 # pickup the patch msg
2504 message = message.strip()
2506 message = message.strip()
2505 else:
2507 else:
2506 # launch the editor
2508 # launch the editor
2507 message = None
2509 message = None
2508 ui.debug('message:\n%s\n' % message)
2510 ui.debug('message:\n%s\n' % message)
2509
2511
2510 wp = repo.parents()
2512 wp = repo.parents()
2511 if opts.get('exact'):
2513 if opts.get('exact'):
2512 if not nodeid or not p1:
2514 if not nodeid or not p1:
2513 raise util.Abort(_('not a Mercurial patch'))
2515 raise util.Abort(_('not a Mercurial patch'))
2514 p1 = repo.lookup(p1)
2516 p1 = repo.lookup(p1)
2515 p2 = repo.lookup(p2 or hex(nullid))
2517 p2 = repo.lookup(p2 or hex(nullid))
2516
2518
2517 if p1 != wp[0].node():
2519 if p1 != wp[0].node():
2518 hg.clean(repo, p1)
2520 hg.clean(repo, p1)
2519 repo.dirstate.setparents(p1, p2)
2521 repo.dirstate.setparents(p1, p2)
2520 elif p2:
2522 elif p2:
2521 try:
2523 try:
2522 p1 = repo.lookup(p1)
2524 p1 = repo.lookup(p1)
2523 p2 = repo.lookup(p2)
2525 p2 = repo.lookup(p2)
2524 if p1 == wp[0].node():
2526 if p1 == wp[0].node():
2525 repo.dirstate.setparents(p1, p2)
2527 repo.dirstate.setparents(p1, p2)
2526 except error.RepoError:
2528 except error.RepoError:
2527 pass
2529 pass
2528 if opts.get('exact') or opts.get('import_branch'):
2530 if opts.get('exact') or opts.get('import_branch'):
2529 repo.dirstate.setbranch(branch or 'default')
2531 repo.dirstate.setbranch(branch or 'default')
2530
2532
2531 files = {}
2533 files = {}
2532 try:
2534 try:
2533 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2535 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2534 files=files, eolmode=None)
2536 files=files, eolmode=None)
2535 finally:
2537 finally:
2536 files = cmdutil.updatedir(ui, repo, files,
2538 files = cmdutil.updatedir(ui, repo, files,
2537 similarity=sim / 100.0)
2539 similarity=sim / 100.0)
2538 if opts.get('no_commit'):
2540 if opts.get('no_commit'):
2539 if message:
2541 if message:
2540 msgs.append(message)
2542 msgs.append(message)
2541 else:
2543 else:
2542 if opts.get('exact'):
2544 if opts.get('exact'):
2543 m = None
2545 m = None
2544 else:
2546 else:
2545 m = cmdutil.matchfiles(repo, files or [])
2547 m = cmdutil.matchfiles(repo, files or [])
2546 n = repo.commit(message, opts.get('user') or user,
2548 n = repo.commit(message, opts.get('user') or user,
2547 opts.get('date') or date, match=m,
2549 opts.get('date') or date, match=m,
2548 editor=cmdutil.commiteditor)
2550 editor=cmdutil.commiteditor)
2549 if opts.get('exact'):
2551 if opts.get('exact'):
2550 if hex(n) != nodeid:
2552 if hex(n) != nodeid:
2551 repo.rollback()
2553 repo.rollback()
2552 raise util.Abort(_('patch is damaged'
2554 raise util.Abort(_('patch is damaged'
2553 ' or loses information'))
2555 ' or loses information'))
2554 # Force a dirstate write so that the next transaction
2556 # Force a dirstate write so that the next transaction
2555 # backups an up-do-date file.
2557 # backups an up-do-date file.
2556 repo.dirstate.write()
2558 repo.dirstate.write()
2557 if n:
2559 if n:
2558 commitid = short(n)
2560 commitid = short(n)
2559
2561
2560 return commitid
2562 return commitid
2561 finally:
2563 finally:
2562 os.unlink(tmpname)
2564 os.unlink(tmpname)
2563
2565
2564 try:
2566 try:
2565 wlock = repo.wlock()
2567 wlock = repo.wlock()
2566 lock = repo.lock()
2568 lock = repo.lock()
2567 lastcommit = None
2569 lastcommit = None
2568 for p in patches:
2570 for p in patches:
2569 pf = os.path.join(d, p)
2571 pf = os.path.join(d, p)
2570
2572
2571 if pf == '-':
2573 if pf == '-':
2572 ui.status(_("applying patch from stdin\n"))
2574 ui.status(_("applying patch from stdin\n"))
2573 pf = sys.stdin
2575 pf = sys.stdin
2574 else:
2576 else:
2575 ui.status(_("applying %s\n") % p)
2577 ui.status(_("applying %s\n") % p)
2576 pf = url.open(ui, pf)
2578 pf = url.open(ui, pf)
2577
2579
2578 haspatch = False
2580 haspatch = False
2579 for hunk in patch.split(pf):
2581 for hunk in patch.split(pf):
2580 commitid = tryone(ui, hunk)
2582 commitid = tryone(ui, hunk)
2581 if commitid:
2583 if commitid:
2582 haspatch = True
2584 haspatch = True
2583 if lastcommit:
2585 if lastcommit:
2584 ui.status(_('applied %s\n') % lastcommit)
2586 ui.status(_('applied %s\n') % lastcommit)
2585 lastcommit = commitid
2587 lastcommit = commitid
2586
2588
2587 if not haspatch:
2589 if not haspatch:
2588 raise util.Abort(_('no diffs found'))
2590 raise util.Abort(_('no diffs found'))
2589
2591
2590 if msgs:
2592 if msgs:
2591 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2593 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2592 finally:
2594 finally:
2593 release(lock, wlock)
2595 release(lock, wlock)
2594
2596
2595 def incoming(ui, repo, source="default", **opts):
2597 def incoming(ui, repo, source="default", **opts):
2596 """show new changesets found in source
2598 """show new changesets found in source
2597
2599
2598 Show new changesets found in the specified path/URL or the default
2600 Show new changesets found in the specified path/URL or the default
2599 pull location. These are the changesets that would have been pulled
2601 pull location. These are the changesets that would have been pulled
2600 if a pull at the time you issued this command.
2602 if a pull at the time you issued this command.
2601
2603
2602 For remote repository, using --bundle avoids downloading the
2604 For remote repository, using --bundle avoids downloading the
2603 changesets twice if the incoming is followed by a pull.
2605 changesets twice if the incoming is followed by a pull.
2604
2606
2605 See pull for valid source format details.
2607 See pull for valid source format details.
2606
2608
2607 Returns 0 if there are incoming changes, 1 otherwise.
2609 Returns 0 if there are incoming changes, 1 otherwise.
2608 """
2610 """
2609 if opts.get('bundle') and opts.get('subrepos'):
2611 if opts.get('bundle') and opts.get('subrepos'):
2610 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2612 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2611
2613
2612 if opts.get('bookmarks'):
2614 if opts.get('bookmarks'):
2613 source, branches = hg.parseurl(ui.expandpath(source),
2615 source, branches = hg.parseurl(ui.expandpath(source),
2614 opts.get('branch'))
2616 opts.get('branch'))
2615 other = hg.repository(hg.remoteui(repo, opts), source)
2617 other = hg.repository(hg.remoteui(repo, opts), source)
2616 if 'bookmarks' not in other.listkeys('namespaces'):
2618 if 'bookmarks' not in other.listkeys('namespaces'):
2617 ui.warn(_("remote doesn't support bookmarks\n"))
2619 ui.warn(_("remote doesn't support bookmarks\n"))
2618 return 0
2620 return 0
2619 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2621 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2620 return bookmarks.diff(ui, repo, other)
2622 return bookmarks.diff(ui, repo, other)
2621
2623
2622 ret = hg.incoming(ui, repo, source, opts)
2624 ret = hg.incoming(ui, repo, source, opts)
2623 return ret
2625 return ret
2624
2626
2625 def init(ui, dest=".", **opts):
2627 def init(ui, dest=".", **opts):
2626 """create a new repository in the given directory
2628 """create a new repository in the given directory
2627
2629
2628 Initialize a new repository in the given directory. If the given
2630 Initialize a new repository in the given directory. If the given
2629 directory does not exist, it will be created.
2631 directory does not exist, it will be created.
2630
2632
2631 If no directory is given, the current directory is used.
2633 If no directory is given, the current directory is used.
2632
2634
2633 It is possible to specify an ``ssh://`` URL as the destination.
2635 It is possible to specify an ``ssh://`` URL as the destination.
2634 See :hg:`help urls` for more information.
2636 See :hg:`help urls` for more information.
2635
2637
2636 Returns 0 on success.
2638 Returns 0 on success.
2637 """
2639 """
2638 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2640 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2639
2641
2640 def locate(ui, repo, *pats, **opts):
2642 def locate(ui, repo, *pats, **opts):
2641 """locate files matching specific patterns
2643 """locate files matching specific patterns
2642
2644
2643 Print files under Mercurial control in the working directory whose
2645 Print files under Mercurial control in the working directory whose
2644 names match the given patterns.
2646 names match the given patterns.
2645
2647
2646 By default, this command searches all directories in the working
2648 By default, this command searches all directories in the working
2647 directory. To search just the current directory and its
2649 directory. To search just the current directory and its
2648 subdirectories, use "--include .".
2650 subdirectories, use "--include .".
2649
2651
2650 If no patterns are given to match, this command prints the names
2652 If no patterns are given to match, this command prints the names
2651 of all files under Mercurial control in the working directory.
2653 of all files under Mercurial control in the working directory.
2652
2654
2653 If you want to feed the output of this command into the "xargs"
2655 If you want to feed the output of this command into the "xargs"
2654 command, use the -0 option to both this command and "xargs". This
2656 command, use the -0 option to both this command and "xargs". This
2655 will avoid the problem of "xargs" treating single filenames that
2657 will avoid the problem of "xargs" treating single filenames that
2656 contain whitespace as multiple filenames.
2658 contain whitespace as multiple filenames.
2657
2659
2658 Returns 0 if a match is found, 1 otherwise.
2660 Returns 0 if a match is found, 1 otherwise.
2659 """
2661 """
2660 end = opts.get('print0') and '\0' or '\n'
2662 end = opts.get('print0') and '\0' or '\n'
2661 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2663 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2662
2664
2663 ret = 1
2665 ret = 1
2664 m = cmdutil.match(repo, pats, opts, default='relglob')
2666 m = cmdutil.match(repo, pats, opts, default='relglob')
2665 m.bad = lambda x, y: False
2667 m.bad = lambda x, y: False
2666 for abs in repo[rev].walk(m):
2668 for abs in repo[rev].walk(m):
2667 if not rev and abs not in repo.dirstate:
2669 if not rev and abs not in repo.dirstate:
2668 continue
2670 continue
2669 if opts.get('fullpath'):
2671 if opts.get('fullpath'):
2670 ui.write(repo.wjoin(abs), end)
2672 ui.write(repo.wjoin(abs), end)
2671 else:
2673 else:
2672 ui.write(((pats and m.rel(abs)) or abs), end)
2674 ui.write(((pats and m.rel(abs)) or abs), end)
2673 ret = 0
2675 ret = 0
2674
2676
2675 return ret
2677 return ret
2676
2678
2677 def log(ui, repo, *pats, **opts):
2679 def log(ui, repo, *pats, **opts):
2678 """show revision history of entire repository or files
2680 """show revision history of entire repository or files
2679
2681
2680 Print the revision history of the specified files or the entire
2682 Print the revision history of the specified files or the entire
2681 project.
2683 project.
2682
2684
2683 File history is shown without following rename or copy history of
2685 File history is shown without following rename or copy history of
2684 files. Use -f/--follow with a filename to follow history across
2686 files. Use -f/--follow with a filename to follow history across
2685 renames and copies. --follow without a filename will only show
2687 renames and copies. --follow without a filename will only show
2686 ancestors or descendants of the starting revision. --follow-first
2688 ancestors or descendants of the starting revision. --follow-first
2687 only follows the first parent of merge revisions.
2689 only follows the first parent of merge revisions.
2688
2690
2689 If no revision range is specified, the default is ``tip:0`` unless
2691 If no revision range is specified, the default is ``tip:0`` unless
2690 --follow is set, in which case the working directory parent is
2692 --follow is set, in which case the working directory parent is
2691 used as the starting revision. You can specify a revision set for
2693 used as the starting revision. You can specify a revision set for
2692 log, see :hg:`help revsets` for more information.
2694 log, see :hg:`help revsets` for more information.
2693
2695
2694 See :hg:`help dates` for a list of formats valid for -d/--date.
2696 See :hg:`help dates` for a list of formats valid for -d/--date.
2695
2697
2696 By default this command prints revision number and changeset id,
2698 By default this command prints revision number and changeset id,
2697 tags, non-trivial parents, user, date and time, and a summary for
2699 tags, non-trivial parents, user, date and time, and a summary for
2698 each commit. When the -v/--verbose switch is used, the list of
2700 each commit. When the -v/--verbose switch is used, the list of
2699 changed files and full commit message are shown.
2701 changed files and full commit message are shown.
2700
2702
2701 .. note::
2703 .. note::
2702 log -p/--patch may generate unexpected diff output for merge
2704 log -p/--patch may generate unexpected diff output for merge
2703 changesets, as it will only compare the merge changeset against
2705 changesets, as it will only compare the merge changeset against
2704 its first parent. Also, only files different from BOTH parents
2706 its first parent. Also, only files different from BOTH parents
2705 will appear in files:.
2707 will appear in files:.
2706
2708
2707 Returns 0 on success.
2709 Returns 0 on success.
2708 """
2710 """
2709
2711
2710 matchfn = cmdutil.match(repo, pats, opts)
2712 matchfn = cmdutil.match(repo, pats, opts)
2711 limit = cmdutil.loglimit(opts)
2713 limit = cmdutil.loglimit(opts)
2712 count = 0
2714 count = 0
2713
2715
2714 endrev = None
2716 endrev = None
2715 if opts.get('copies') and opts.get('rev'):
2717 if opts.get('copies') and opts.get('rev'):
2716 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2718 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2717
2719
2718 df = False
2720 df = False
2719 if opts["date"]:
2721 if opts["date"]:
2720 df = util.matchdate(opts["date"])
2722 df = util.matchdate(opts["date"])
2721
2723
2722 branches = opts.get('branch', []) + opts.get('only_branch', [])
2724 branches = opts.get('branch', []) + opts.get('only_branch', [])
2723 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2725 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2724
2726
2725 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2727 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2726 def prep(ctx, fns):
2728 def prep(ctx, fns):
2727 rev = ctx.rev()
2729 rev = ctx.rev()
2728 parents = [p for p in repo.changelog.parentrevs(rev)
2730 parents = [p for p in repo.changelog.parentrevs(rev)
2729 if p != nullrev]
2731 if p != nullrev]
2730 if opts.get('no_merges') and len(parents) == 2:
2732 if opts.get('no_merges') and len(parents) == 2:
2731 return
2733 return
2732 if opts.get('only_merges') and len(parents) != 2:
2734 if opts.get('only_merges') and len(parents) != 2:
2733 return
2735 return
2734 if opts.get('branch') and ctx.branch() not in opts['branch']:
2736 if opts.get('branch') and ctx.branch() not in opts['branch']:
2735 return
2737 return
2736 if df and not df(ctx.date()[0]):
2738 if df and not df(ctx.date()[0]):
2737 return
2739 return
2738 if opts['user'] and not [k for k in opts['user']
2740 if opts['user'] and not [k for k in opts['user']
2739 if k.lower() in ctx.user().lower()]:
2741 if k.lower() in ctx.user().lower()]:
2740 return
2742 return
2741 if opts.get('keyword'):
2743 if opts.get('keyword'):
2742 for k in [kw.lower() for kw in opts['keyword']]:
2744 for k in [kw.lower() for kw in opts['keyword']]:
2743 if (k in ctx.user().lower() or
2745 if (k in ctx.user().lower() or
2744 k in ctx.description().lower() or
2746 k in ctx.description().lower() or
2745 k in " ".join(ctx.files()).lower()):
2747 k in " ".join(ctx.files()).lower()):
2746 break
2748 break
2747 else:
2749 else:
2748 return
2750 return
2749
2751
2750 copies = None
2752 copies = None
2751 if opts.get('copies') and rev:
2753 if opts.get('copies') and rev:
2752 copies = []
2754 copies = []
2753 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2755 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2754 for fn in ctx.files():
2756 for fn in ctx.files():
2755 rename = getrenamed(fn, rev)
2757 rename = getrenamed(fn, rev)
2756 if rename:
2758 if rename:
2757 copies.append((fn, rename[0]))
2759 copies.append((fn, rename[0]))
2758
2760
2759 revmatchfn = None
2761 revmatchfn = None
2760 if opts.get('patch') or opts.get('stat'):
2762 if opts.get('patch') or opts.get('stat'):
2761 if opts.get('follow') or opts.get('follow_first'):
2763 if opts.get('follow') or opts.get('follow_first'):
2762 # note: this might be wrong when following through merges
2764 # note: this might be wrong when following through merges
2763 revmatchfn = cmdutil.match(repo, fns, default='path')
2765 revmatchfn = cmdutil.match(repo, fns, default='path')
2764 else:
2766 else:
2765 revmatchfn = matchfn
2767 revmatchfn = matchfn
2766
2768
2767 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2769 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2768
2770
2769 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2771 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2770 if count == limit:
2772 if count == limit:
2771 break
2773 break
2772 if displayer.flush(ctx.rev()):
2774 if displayer.flush(ctx.rev()):
2773 count += 1
2775 count += 1
2774 displayer.close()
2776 displayer.close()
2775
2777
2776 def manifest(ui, repo, node=None, rev=None):
2778 def manifest(ui, repo, node=None, rev=None):
2777 """output the current or given revision of the project manifest
2779 """output the current or given revision of the project manifest
2778
2780
2779 Print a list of version controlled files for the given revision.
2781 Print a list of version controlled files for the given revision.
2780 If no revision is given, the first parent of the working directory
2782 If no revision is given, the first parent of the working directory
2781 is used, or the null revision if no revision is checked out.
2783 is used, or the null revision if no revision is checked out.
2782
2784
2783 With -v, print file permissions, symlink and executable bits.
2785 With -v, print file permissions, symlink and executable bits.
2784 With --debug, print file revision hashes.
2786 With --debug, print file revision hashes.
2785
2787
2786 Returns 0 on success.
2788 Returns 0 on success.
2787 """
2789 """
2788
2790
2789 if rev and node:
2791 if rev and node:
2790 raise util.Abort(_("please specify just one revision"))
2792 raise util.Abort(_("please specify just one revision"))
2791
2793
2792 if not node:
2794 if not node:
2793 node = rev
2795 node = rev
2794
2796
2795 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2797 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2796 ctx = cmdutil.revsingle(repo, node)
2798 ctx = cmdutil.revsingle(repo, node)
2797 for f in ctx:
2799 for f in ctx:
2798 if ui.debugflag:
2800 if ui.debugflag:
2799 ui.write("%40s " % hex(ctx.manifest()[f]))
2801 ui.write("%40s " % hex(ctx.manifest()[f]))
2800 if ui.verbose:
2802 if ui.verbose:
2801 ui.write(decor[ctx.flags(f)])
2803 ui.write(decor[ctx.flags(f)])
2802 ui.write("%s\n" % f)
2804 ui.write("%s\n" % f)
2803
2805
2804 def merge(ui, repo, node=None, **opts):
2806 def merge(ui, repo, node=None, **opts):
2805 """merge working directory with another revision
2807 """merge working directory with another revision
2806
2808
2807 The current working directory is updated with all changes made in
2809 The current working directory is updated with all changes made in
2808 the requested revision since the last common predecessor revision.
2810 the requested revision since the last common predecessor revision.
2809
2811
2810 Files that changed between either parent are marked as changed for
2812 Files that changed between either parent are marked as changed for
2811 the next commit and a commit must be performed before any further
2813 the next commit and a commit must be performed before any further
2812 updates to the repository are allowed. The next commit will have
2814 updates to the repository are allowed. The next commit will have
2813 two parents.
2815 two parents.
2814
2816
2815 ``--tool`` can be used to specify the merge tool used for file
2817 ``--tool`` can be used to specify the merge tool used for file
2816 merges. It overrides the HGMERGE environment variable and your
2818 merges. It overrides the HGMERGE environment variable and your
2817 configuration files. See :hg:`help merge-tools` for options.
2819 configuration files. See :hg:`help merge-tools` for options.
2818
2820
2819 If no revision is specified, the working directory's parent is a
2821 If no revision is specified, the working directory's parent is a
2820 head revision, and the current branch contains exactly one other
2822 head revision, and the current branch contains exactly one other
2821 head, the other head is merged with by default. Otherwise, an
2823 head, the other head is merged with by default. Otherwise, an
2822 explicit revision with which to merge with must be provided.
2824 explicit revision with which to merge with must be provided.
2823
2825
2824 :hg:`resolve` must be used to resolve unresolved files.
2826 :hg:`resolve` must be used to resolve unresolved files.
2825
2827
2826 To undo an uncommitted merge, use :hg:`update --clean .` which
2828 To undo an uncommitted merge, use :hg:`update --clean .` which
2827 will check out a clean copy of the original merge parent, losing
2829 will check out a clean copy of the original merge parent, losing
2828 all changes.
2830 all changes.
2829
2831
2830 Returns 0 on success, 1 if there are unresolved files.
2832 Returns 0 on success, 1 if there are unresolved files.
2831 """
2833 """
2832
2834
2833 if opts.get('rev') and node:
2835 if opts.get('rev') and node:
2834 raise util.Abort(_("please specify just one revision"))
2836 raise util.Abort(_("please specify just one revision"))
2835 if not node:
2837 if not node:
2836 node = opts.get('rev')
2838 node = opts.get('rev')
2837
2839
2838 if not node:
2840 if not node:
2839 branch = repo[None].branch()
2841 branch = repo[None].branch()
2840 bheads = repo.branchheads(branch)
2842 bheads = repo.branchheads(branch)
2841 if len(bheads) > 2:
2843 if len(bheads) > 2:
2842 raise util.Abort(_(
2844 raise util.Abort(_(
2843 'branch \'%s\' has %d heads - '
2845 'branch \'%s\' has %d heads - '
2844 'please merge with an explicit rev\n'
2846 'please merge with an explicit rev\n'
2845 '(run \'hg heads .\' to see heads)')
2847 '(run \'hg heads .\' to see heads)')
2846 % (branch, len(bheads)))
2848 % (branch, len(bheads)))
2847
2849
2848 parent = repo.dirstate.p1()
2850 parent = repo.dirstate.p1()
2849 if len(bheads) == 1:
2851 if len(bheads) == 1:
2850 if len(repo.heads()) > 1:
2852 if len(repo.heads()) > 1:
2851 raise util.Abort(_(
2853 raise util.Abort(_(
2852 'branch \'%s\' has one head - '
2854 'branch \'%s\' has one head - '
2853 'please merge with an explicit rev\n'
2855 'please merge with an explicit rev\n'
2854 '(run \'hg heads\' to see all heads)')
2856 '(run \'hg heads\' to see all heads)')
2855 % branch)
2857 % branch)
2856 msg = _('there is nothing to merge')
2858 msg = _('there is nothing to merge')
2857 if parent != repo.lookup(repo[None].branch()):
2859 if parent != repo.lookup(repo[None].branch()):
2858 msg = _('%s - use "hg update" instead') % msg
2860 msg = _('%s - use "hg update" instead') % msg
2859 raise util.Abort(msg)
2861 raise util.Abort(msg)
2860
2862
2861 if parent not in bheads:
2863 if parent not in bheads:
2862 raise util.Abort(_('working dir not at a head rev - '
2864 raise util.Abort(_('working dir not at a head rev - '
2863 'use "hg update" or merge with an explicit rev'))
2865 'use "hg update" or merge with an explicit rev'))
2864 node = parent == bheads[0] and bheads[-1] or bheads[0]
2866 node = parent == bheads[0] and bheads[-1] or bheads[0]
2865 else:
2867 else:
2866 node = cmdutil.revsingle(repo, node).node()
2868 node = cmdutil.revsingle(repo, node).node()
2867
2869
2868 if opts.get('preview'):
2870 if opts.get('preview'):
2869 # find nodes that are ancestors of p2 but not of p1
2871 # find nodes that are ancestors of p2 but not of p1
2870 p1 = repo.lookup('.')
2872 p1 = repo.lookup('.')
2871 p2 = repo.lookup(node)
2873 p2 = repo.lookup(node)
2872 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2874 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2873
2875
2874 displayer = cmdutil.show_changeset(ui, repo, opts)
2876 displayer = cmdutil.show_changeset(ui, repo, opts)
2875 for node in nodes:
2877 for node in nodes:
2876 displayer.show(repo[node])
2878 displayer.show(repo[node])
2877 displayer.close()
2879 displayer.close()
2878 return 0
2880 return 0
2879
2881
2880 try:
2882 try:
2881 # ui.forcemerge is an internal variable, do not document
2883 # ui.forcemerge is an internal variable, do not document
2882 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2884 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2883 return hg.merge(repo, node, force=opts.get('force'))
2885 return hg.merge(repo, node, force=opts.get('force'))
2884 finally:
2886 finally:
2885 ui.setconfig('ui', 'forcemerge', '')
2887 ui.setconfig('ui', 'forcemerge', '')
2886
2888
2887 def outgoing(ui, repo, dest=None, **opts):
2889 def outgoing(ui, repo, dest=None, **opts):
2888 """show changesets not found in the destination
2890 """show changesets not found in the destination
2889
2891
2890 Show changesets not found in the specified destination repository
2892 Show changesets not found in the specified destination repository
2891 or the default push location. These are the changesets that would
2893 or the default push location. These are the changesets that would
2892 be pushed if a push was requested.
2894 be pushed if a push was requested.
2893
2895
2894 See pull for details of valid destination formats.
2896 See pull for details of valid destination formats.
2895
2897
2896 Returns 0 if there are outgoing changes, 1 otherwise.
2898 Returns 0 if there are outgoing changes, 1 otherwise.
2897 """
2899 """
2898
2900
2899 if opts.get('bookmarks'):
2901 if opts.get('bookmarks'):
2900 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2902 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2901 dest, branches = hg.parseurl(dest, opts.get('branch'))
2903 dest, branches = hg.parseurl(dest, opts.get('branch'))
2902 other = hg.repository(hg.remoteui(repo, opts), dest)
2904 other = hg.repository(hg.remoteui(repo, opts), dest)
2903 if 'bookmarks' not in other.listkeys('namespaces'):
2905 if 'bookmarks' not in other.listkeys('namespaces'):
2904 ui.warn(_("remote doesn't support bookmarks\n"))
2906 ui.warn(_("remote doesn't support bookmarks\n"))
2905 return 0
2907 return 0
2906 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2908 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2907 return bookmarks.diff(ui, other, repo)
2909 return bookmarks.diff(ui, other, repo)
2908
2910
2909 ret = hg.outgoing(ui, repo, dest, opts)
2911 ret = hg.outgoing(ui, repo, dest, opts)
2910 return ret
2912 return ret
2911
2913
2912 def parents(ui, repo, file_=None, **opts):
2914 def parents(ui, repo, file_=None, **opts):
2913 """show the parents of the working directory or revision
2915 """show the parents of the working directory or revision
2914
2916
2915 Print the working directory's parent revisions. If a revision is
2917 Print the working directory's parent revisions. If a revision is
2916 given via -r/--rev, the parent of that revision will be printed.
2918 given via -r/--rev, the parent of that revision will be printed.
2917 If a file argument is given, the revision in which the file was
2919 If a file argument is given, the revision in which the file was
2918 last changed (before the working directory revision or the
2920 last changed (before the working directory revision or the
2919 argument to --rev if given) is printed.
2921 argument to --rev if given) is printed.
2920
2922
2921 Returns 0 on success.
2923 Returns 0 on success.
2922 """
2924 """
2923
2925
2924 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2926 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2925
2927
2926 if file_:
2928 if file_:
2927 m = cmdutil.match(repo, (file_,), opts)
2929 m = cmdutil.match(repo, (file_,), opts)
2928 if m.anypats() or len(m.files()) != 1:
2930 if m.anypats() or len(m.files()) != 1:
2929 raise util.Abort(_('can only specify an explicit filename'))
2931 raise util.Abort(_('can only specify an explicit filename'))
2930 file_ = m.files()[0]
2932 file_ = m.files()[0]
2931 filenodes = []
2933 filenodes = []
2932 for cp in ctx.parents():
2934 for cp in ctx.parents():
2933 if not cp:
2935 if not cp:
2934 continue
2936 continue
2935 try:
2937 try:
2936 filenodes.append(cp.filenode(file_))
2938 filenodes.append(cp.filenode(file_))
2937 except error.LookupError:
2939 except error.LookupError:
2938 pass
2940 pass
2939 if not filenodes:
2941 if not filenodes:
2940 raise util.Abort(_("'%s' not found in manifest!") % file_)
2942 raise util.Abort(_("'%s' not found in manifest!") % file_)
2941 fl = repo.file(file_)
2943 fl = repo.file(file_)
2942 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2944 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2943 else:
2945 else:
2944 p = [cp.node() for cp in ctx.parents()]
2946 p = [cp.node() for cp in ctx.parents()]
2945
2947
2946 displayer = cmdutil.show_changeset(ui, repo, opts)
2948 displayer = cmdutil.show_changeset(ui, repo, opts)
2947 for n in p:
2949 for n in p:
2948 if n != nullid:
2950 if n != nullid:
2949 displayer.show(repo[n])
2951 displayer.show(repo[n])
2950 displayer.close()
2952 displayer.close()
2951
2953
2952 def paths(ui, repo, search=None):
2954 def paths(ui, repo, search=None):
2953 """show aliases for remote repositories
2955 """show aliases for remote repositories
2954
2956
2955 Show definition of symbolic path name NAME. If no name is given,
2957 Show definition of symbolic path name NAME. If no name is given,
2956 show definition of all available names.
2958 show definition of all available names.
2957
2959
2958 Path names are defined in the [paths] section of your
2960 Path names are defined in the [paths] section of your
2959 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2961 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2960 repository, ``.hg/hgrc`` is used, too.
2962 repository, ``.hg/hgrc`` is used, too.
2961
2963
2962 The path names ``default`` and ``default-push`` have a special
2964 The path names ``default`` and ``default-push`` have a special
2963 meaning. When performing a push or pull operation, they are used
2965 meaning. When performing a push or pull operation, they are used
2964 as fallbacks if no location is specified on the command-line.
2966 as fallbacks if no location is specified on the command-line.
2965 When ``default-push`` is set, it will be used for push and
2967 When ``default-push`` is set, it will be used for push and
2966 ``default`` will be used for pull; otherwise ``default`` is used
2968 ``default`` will be used for pull; otherwise ``default`` is used
2967 as the fallback for both. When cloning a repository, the clone
2969 as the fallback for both. When cloning a repository, the clone
2968 source is written as ``default`` in ``.hg/hgrc``. Note that
2970 source is written as ``default`` in ``.hg/hgrc``. Note that
2969 ``default`` and ``default-push`` apply to all inbound (e.g.
2971 ``default`` and ``default-push`` apply to all inbound (e.g.
2970 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2972 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2971 :hg:`bundle`) operations.
2973 :hg:`bundle`) operations.
2972
2974
2973 See :hg:`help urls` for more information.
2975 See :hg:`help urls` for more information.
2974
2976
2975 Returns 0 on success.
2977 Returns 0 on success.
2976 """
2978 """
2977 if search:
2979 if search:
2978 for name, path in ui.configitems("paths"):
2980 for name, path in ui.configitems("paths"):
2979 if name == search:
2981 if name == search:
2980 ui.write("%s\n" % url.hidepassword(path))
2982 ui.write("%s\n" % url.hidepassword(path))
2981 return
2983 return
2982 ui.warn(_("not found!\n"))
2984 ui.warn(_("not found!\n"))
2983 return 1
2985 return 1
2984 else:
2986 else:
2985 for name, path in ui.configitems("paths"):
2987 for name, path in ui.configitems("paths"):
2986 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2988 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2987
2989
2988 def postincoming(ui, repo, modheads, optupdate, checkout):
2990 def postincoming(ui, repo, modheads, optupdate, checkout):
2989 if modheads == 0:
2991 if modheads == 0:
2990 return
2992 return
2991 if optupdate:
2993 if optupdate:
2992 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2994 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2993 return hg.update(repo, checkout)
2995 return hg.update(repo, checkout)
2994 else:
2996 else:
2995 ui.status(_("not updating, since new heads added\n"))
2997 ui.status(_("not updating, since new heads added\n"))
2996 if modheads > 1:
2998 if modheads > 1:
2997 currentbranchheads = len(repo.branchheads())
2999 currentbranchheads = len(repo.branchheads())
2998 if currentbranchheads == modheads:
3000 if currentbranchheads == modheads:
2999 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3001 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3000 elif currentbranchheads > 1:
3002 elif currentbranchheads > 1:
3001 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3003 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3002 else:
3004 else:
3003 ui.status(_("(run 'hg heads' to see heads)\n"))
3005 ui.status(_("(run 'hg heads' to see heads)\n"))
3004 else:
3006 else:
3005 ui.status(_("(run 'hg update' to get a working copy)\n"))
3007 ui.status(_("(run 'hg update' to get a working copy)\n"))
3006
3008
3007 def pull(ui, repo, source="default", **opts):
3009 def pull(ui, repo, source="default", **opts):
3008 """pull changes from the specified source
3010 """pull changes from the specified source
3009
3011
3010 Pull changes from a remote repository to a local one.
3012 Pull changes from a remote repository to a local one.
3011
3013
3012 This finds all changes from the repository at the specified path
3014 This finds all changes from the repository at the specified path
3013 or URL and adds them to a local repository (the current one unless
3015 or URL and adds them to a local repository (the current one unless
3014 -R is specified). By default, this does not update the copy of the
3016 -R is specified). By default, this does not update the copy of the
3015 project in the working directory.
3017 project in the working directory.
3016
3018
3017 Use :hg:`incoming` if you want to see what would have been added
3019 Use :hg:`incoming` if you want to see what would have been added
3018 by a pull at the time you issued this command. If you then decide
3020 by a pull at the time you issued this command. If you then decide
3019 to add those changes to the repository, you should use :hg:`pull
3021 to add those changes to the repository, you should use :hg:`pull
3020 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3022 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3021
3023
3022 If SOURCE is omitted, the 'default' path will be used.
3024 If SOURCE is omitted, the 'default' path will be used.
3023 See :hg:`help urls` for more information.
3025 See :hg:`help urls` for more information.
3024
3026
3025 Returns 0 on success, 1 if an update had unresolved files.
3027 Returns 0 on success, 1 if an update had unresolved files.
3026 """
3028 """
3027 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3029 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3028 other = hg.repository(hg.remoteui(repo, opts), source)
3030 other = hg.repository(hg.remoteui(repo, opts), source)
3029 ui.status(_('pulling from %s\n') % url.hidepassword(source))
3031 ui.status(_('pulling from %s\n') % url.hidepassword(source))
3030 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3032 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3031
3033
3032 if opts.get('bookmark'):
3034 if opts.get('bookmark'):
3033 if not revs:
3035 if not revs:
3034 revs = []
3036 revs = []
3035 rb = other.listkeys('bookmarks')
3037 rb = other.listkeys('bookmarks')
3036 for b in opts['bookmark']:
3038 for b in opts['bookmark']:
3037 if b not in rb:
3039 if b not in rb:
3038 raise util.Abort(_('remote bookmark %s not found!') % b)
3040 raise util.Abort(_('remote bookmark %s not found!') % b)
3039 revs.append(rb[b])
3041 revs.append(rb[b])
3040
3042
3041 if revs:
3043 if revs:
3042 try:
3044 try:
3043 revs = [other.lookup(rev) for rev in revs]
3045 revs = [other.lookup(rev) for rev in revs]
3044 except error.CapabilityError:
3046 except error.CapabilityError:
3045 err = _("other repository doesn't support revision lookup, "
3047 err = _("other repository doesn't support revision lookup, "
3046 "so a rev cannot be specified.")
3048 "so a rev cannot be specified.")
3047 raise util.Abort(err)
3049 raise util.Abort(err)
3048
3050
3049 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3051 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
3050 bookmarks.updatefromremote(ui, repo, other)
3052 bookmarks.updatefromremote(ui, repo, other)
3051 if checkout:
3053 if checkout:
3052 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3054 checkout = str(repo.changelog.rev(other.lookup(checkout)))
3053 repo._subtoppath = source
3055 repo._subtoppath = source
3054 try:
3056 try:
3055 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3057 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
3056
3058
3057 finally:
3059 finally:
3058 del repo._subtoppath
3060 del repo._subtoppath
3059
3061
3060 # update specified bookmarks
3062 # update specified bookmarks
3061 if opts.get('bookmark'):
3063 if opts.get('bookmark'):
3062 for b in opts['bookmark']:
3064 for b in opts['bookmark']:
3063 # explicit pull overrides local bookmark if any
3065 # explicit pull overrides local bookmark if any
3064 ui.status(_("importing bookmark %s\n") % b)
3066 ui.status(_("importing bookmark %s\n") % b)
3065 repo._bookmarks[b] = repo[rb[b]].node()
3067 repo._bookmarks[b] = repo[rb[b]].node()
3066 bookmarks.write(repo)
3068 bookmarks.write(repo)
3067
3069
3068 return ret
3070 return ret
3069
3071
3070 def push(ui, repo, dest=None, **opts):
3072 def push(ui, repo, dest=None, **opts):
3071 """push changes to the specified destination
3073 """push changes to the specified destination
3072
3074
3073 Push changesets from the local repository to the specified
3075 Push changesets from the local repository to the specified
3074 destination.
3076 destination.
3075
3077
3076 This operation is symmetrical to pull: it is identical to a pull
3078 This operation is symmetrical to pull: it is identical to a pull
3077 in the destination repository from the current one.
3079 in the destination repository from the current one.
3078
3080
3079 By default, push will not allow creation of new heads at the
3081 By default, push will not allow creation of new heads at the
3080 destination, since multiple heads would make it unclear which head
3082 destination, since multiple heads would make it unclear which head
3081 to use. In this situation, it is recommended to pull and merge
3083 to use. In this situation, it is recommended to pull and merge
3082 before pushing.
3084 before pushing.
3083
3085
3084 Use --new-branch if you want to allow push to create a new named
3086 Use --new-branch if you want to allow push to create a new named
3085 branch that is not present at the destination. This allows you to
3087 branch that is not present at the destination. This allows you to
3086 only create a new branch without forcing other changes.
3088 only create a new branch without forcing other changes.
3087
3089
3088 Use -f/--force to override the default behavior and push all
3090 Use -f/--force to override the default behavior and push all
3089 changesets on all branches.
3091 changesets on all branches.
3090
3092
3091 If -r/--rev is used, the specified revision and all its ancestors
3093 If -r/--rev is used, the specified revision and all its ancestors
3092 will be pushed to the remote repository.
3094 will be pushed to the remote repository.
3093
3095
3094 Please see :hg:`help urls` for important details about ``ssh://``
3096 Please see :hg:`help urls` for important details about ``ssh://``
3095 URLs. If DESTINATION is omitted, a default path will be used.
3097 URLs. If DESTINATION is omitted, a default path will be used.
3096
3098
3097 Returns 0 if push was successful, 1 if nothing to push.
3099 Returns 0 if push was successful, 1 if nothing to push.
3098 """
3100 """
3099
3101
3100 if opts.get('bookmark'):
3102 if opts.get('bookmark'):
3101 for b in opts['bookmark']:
3103 for b in opts['bookmark']:
3102 # translate -B options to -r so changesets get pushed
3104 # translate -B options to -r so changesets get pushed
3103 if b in repo._bookmarks:
3105 if b in repo._bookmarks:
3104 opts.setdefault('rev', []).append(b)
3106 opts.setdefault('rev', []).append(b)
3105 else:
3107 else:
3106 # if we try to push a deleted bookmark, translate it to null
3108 # if we try to push a deleted bookmark, translate it to null
3107 # this lets simultaneous -r, -b options continue working
3109 # this lets simultaneous -r, -b options continue working
3108 opts.setdefault('rev', []).append("null")
3110 opts.setdefault('rev', []).append("null")
3109
3111
3110 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3112 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3111 dest, branches = hg.parseurl(dest, opts.get('branch'))
3113 dest, branches = hg.parseurl(dest, opts.get('branch'))
3112 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
3114 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
3113 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3115 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3114 other = hg.repository(hg.remoteui(repo, opts), dest)
3116 other = hg.repository(hg.remoteui(repo, opts), dest)
3115 if revs:
3117 if revs:
3116 revs = [repo.lookup(rev) for rev in revs]
3118 revs = [repo.lookup(rev) for rev in revs]
3117
3119
3118 repo._subtoppath = dest
3120 repo._subtoppath = dest
3119 try:
3121 try:
3120 # push subrepos depth-first for coherent ordering
3122 # push subrepos depth-first for coherent ordering
3121 c = repo['']
3123 c = repo['']
3122 subs = c.substate # only repos that are committed
3124 subs = c.substate # only repos that are committed
3123 for s in sorted(subs):
3125 for s in sorted(subs):
3124 if not c.sub(s).push(opts.get('force')):
3126 if not c.sub(s).push(opts.get('force')):
3125 return False
3127 return False
3126 finally:
3128 finally:
3127 del repo._subtoppath
3129 del repo._subtoppath
3128 result = repo.push(other, opts.get('force'), revs=revs,
3130 result = repo.push(other, opts.get('force'), revs=revs,
3129 newbranch=opts.get('new_branch'))
3131 newbranch=opts.get('new_branch'))
3130
3132
3131 result = (result == 0)
3133 result = (result == 0)
3132
3134
3133 if opts.get('bookmark'):
3135 if opts.get('bookmark'):
3134 rb = other.listkeys('bookmarks')
3136 rb = other.listkeys('bookmarks')
3135 for b in opts['bookmark']:
3137 for b in opts['bookmark']:
3136 # explicit push overrides remote bookmark if any
3138 # explicit push overrides remote bookmark if any
3137 if b in repo._bookmarks:
3139 if b in repo._bookmarks:
3138 ui.status(_("exporting bookmark %s\n") % b)
3140 ui.status(_("exporting bookmark %s\n") % b)
3139 new = repo[b].hex()
3141 new = repo[b].hex()
3140 elif b in rb:
3142 elif b in rb:
3141 ui.status(_("deleting remote bookmark %s\n") % b)
3143 ui.status(_("deleting remote bookmark %s\n") % b)
3142 new = '' # delete
3144 new = '' # delete
3143 else:
3145 else:
3144 ui.warn(_('bookmark %s does not exist on the local '
3146 ui.warn(_('bookmark %s does not exist on the local '
3145 'or remote repository!\n') % b)
3147 'or remote repository!\n') % b)
3146 return 2
3148 return 2
3147 old = rb.get(b, '')
3149 old = rb.get(b, '')
3148 r = other.pushkey('bookmarks', b, old, new)
3150 r = other.pushkey('bookmarks', b, old, new)
3149 if not r:
3151 if not r:
3150 ui.warn(_('updating bookmark %s failed!\n') % b)
3152 ui.warn(_('updating bookmark %s failed!\n') % b)
3151 if not result:
3153 if not result:
3152 result = 2
3154 result = 2
3153
3155
3154 return result
3156 return result
3155
3157
3156 def recover(ui, repo):
3158 def recover(ui, repo):
3157 """roll back an interrupted transaction
3159 """roll back an interrupted transaction
3158
3160
3159 Recover from an interrupted commit or pull.
3161 Recover from an interrupted commit or pull.
3160
3162
3161 This command tries to fix the repository status after an
3163 This command tries to fix the repository status after an
3162 interrupted operation. It should only be necessary when Mercurial
3164 interrupted operation. It should only be necessary when Mercurial
3163 suggests it.
3165 suggests it.
3164
3166
3165 Returns 0 if successful, 1 if nothing to recover or verify fails.
3167 Returns 0 if successful, 1 if nothing to recover or verify fails.
3166 """
3168 """
3167 if repo.recover():
3169 if repo.recover():
3168 return hg.verify(repo)
3170 return hg.verify(repo)
3169 return 1
3171 return 1
3170
3172
3171 def remove(ui, repo, *pats, **opts):
3173 def remove(ui, repo, *pats, **opts):
3172 """remove the specified files on the next commit
3174 """remove the specified files on the next commit
3173
3175
3174 Schedule the indicated files for removal from the repository.
3176 Schedule the indicated files for removal from the repository.
3175
3177
3176 This only removes files from the current branch, not from the
3178 This only removes files from the current branch, not from the
3177 entire project history. -A/--after can be used to remove only
3179 entire project history. -A/--after can be used to remove only
3178 files that have already been deleted, -f/--force can be used to
3180 files that have already been deleted, -f/--force can be used to
3179 force deletion, and -Af can be used to remove files from the next
3181 force deletion, and -Af can be used to remove files from the next
3180 revision without deleting them from the working directory.
3182 revision without deleting them from the working directory.
3181
3183
3182 The following table details the behavior of remove for different
3184 The following table details the behavior of remove for different
3183 file states (columns) and option combinations (rows). The file
3185 file states (columns) and option combinations (rows). The file
3184 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3186 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3185 reported by :hg:`status`). The actions are Warn, Remove (from
3187 reported by :hg:`status`). The actions are Warn, Remove (from
3186 branch) and Delete (from disk)::
3188 branch) and Delete (from disk)::
3187
3189
3188 A C M !
3190 A C M !
3189 none W RD W R
3191 none W RD W R
3190 -f R RD RD R
3192 -f R RD RD R
3191 -A W W W R
3193 -A W W W R
3192 -Af R R R R
3194 -Af R R R R
3193
3195
3194 This command schedules the files to be removed at the next commit.
3196 This command schedules the files to be removed at the next commit.
3195 To undo a remove before that, see :hg:`revert`.
3197 To undo a remove before that, see :hg:`revert`.
3196
3198
3197 Returns 0 on success, 1 if any warnings encountered.
3199 Returns 0 on success, 1 if any warnings encountered.
3198 """
3200 """
3199
3201
3200 ret = 0
3202 ret = 0
3201 after, force = opts.get('after'), opts.get('force')
3203 after, force = opts.get('after'), opts.get('force')
3202 if not pats and not after:
3204 if not pats and not after:
3203 raise util.Abort(_('no files specified'))
3205 raise util.Abort(_('no files specified'))
3204
3206
3205 m = cmdutil.match(repo, pats, opts)
3207 m = cmdutil.match(repo, pats, opts)
3206 s = repo.status(match=m, clean=True)
3208 s = repo.status(match=m, clean=True)
3207 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3209 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3208
3210
3209 for f in m.files():
3211 for f in m.files():
3210 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3212 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3211 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3213 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3212 ret = 1
3214 ret = 1
3213
3215
3214 if force:
3216 if force:
3215 remove, forget = modified + deleted + clean, added
3217 remove, forget = modified + deleted + clean, added
3216 elif after:
3218 elif after:
3217 remove, forget = deleted, []
3219 remove, forget = deleted, []
3218 for f in modified + added + clean:
3220 for f in modified + added + clean:
3219 ui.warn(_('not removing %s: file still exists (use -f'
3221 ui.warn(_('not removing %s: file still exists (use -f'
3220 ' to force removal)\n') % m.rel(f))
3222 ' to force removal)\n') % m.rel(f))
3221 ret = 1
3223 ret = 1
3222 else:
3224 else:
3223 remove, forget = deleted + clean, []
3225 remove, forget = deleted + clean, []
3224 for f in modified:
3226 for f in modified:
3225 ui.warn(_('not removing %s: file is modified (use -f'
3227 ui.warn(_('not removing %s: file is modified (use -f'
3226 ' to force removal)\n') % m.rel(f))
3228 ' to force removal)\n') % m.rel(f))
3227 ret = 1
3229 ret = 1
3228 for f in added:
3230 for f in added:
3229 ui.warn(_('not removing %s: file has been marked for add (use -f'
3231 ui.warn(_('not removing %s: file has been marked for add (use -f'
3230 ' to force removal)\n') % m.rel(f))
3232 ' to force removal)\n') % m.rel(f))
3231 ret = 1
3233 ret = 1
3232
3234
3233 for f in sorted(remove + forget):
3235 for f in sorted(remove + forget):
3234 if ui.verbose or not m.exact(f):
3236 if ui.verbose or not m.exact(f):
3235 ui.status(_('removing %s\n') % m.rel(f))
3237 ui.status(_('removing %s\n') % m.rel(f))
3236
3238
3237 repo[None].forget(forget)
3239 repo[None].forget(forget)
3238 repo[None].remove(remove, unlink=not after)
3240 repo[None].remove(remove, unlink=not after)
3239 return ret
3241 return ret
3240
3242
3241 def rename(ui, repo, *pats, **opts):
3243 def rename(ui, repo, *pats, **opts):
3242 """rename files; equivalent of copy + remove
3244 """rename files; equivalent of copy + remove
3243
3245
3244 Mark dest as copies of sources; mark sources for deletion. If dest
3246 Mark dest as copies of sources; mark sources for deletion. If dest
3245 is a directory, copies are put in that directory. If dest is a
3247 is a directory, copies are put in that directory. If dest is a
3246 file, there can only be one source.
3248 file, there can only be one source.
3247
3249
3248 By default, this command copies the contents of files as they
3250 By default, this command copies the contents of files as they
3249 exist in the working directory. If invoked with -A/--after, the
3251 exist in the working directory. If invoked with -A/--after, the
3250 operation is recorded, but no copying is performed.
3252 operation is recorded, but no copying is performed.
3251
3253
3252 This command takes effect at the next commit. To undo a rename
3254 This command takes effect at the next commit. To undo a rename
3253 before that, see :hg:`revert`.
3255 before that, see :hg:`revert`.
3254
3256
3255 Returns 0 on success, 1 if errors are encountered.
3257 Returns 0 on success, 1 if errors are encountered.
3256 """
3258 """
3257 wlock = repo.wlock(False)
3259 wlock = repo.wlock(False)
3258 try:
3260 try:
3259 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3261 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3260 finally:
3262 finally:
3261 wlock.release()
3263 wlock.release()
3262
3264
3263 def resolve(ui, repo, *pats, **opts):
3265 def resolve(ui, repo, *pats, **opts):
3264 """redo merges or set/view the merge status of files
3266 """redo merges or set/view the merge status of files
3265
3267
3266 Merges with unresolved conflicts are often the result of
3268 Merges with unresolved conflicts are often the result of
3267 non-interactive merging using the ``internal:merge`` configuration
3269 non-interactive merging using the ``internal:merge`` configuration
3268 setting, or a command-line merge tool like ``diff3``. The resolve
3270 setting, or a command-line merge tool like ``diff3``. The resolve
3269 command is used to manage the files involved in a merge, after
3271 command is used to manage the files involved in a merge, after
3270 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3272 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3271 working directory must have two parents).
3273 working directory must have two parents).
3272
3274
3273 The resolve command can be used in the following ways:
3275 The resolve command can be used in the following ways:
3274
3276
3275 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3277 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3276 files, discarding any previous merge attempts. Re-merging is not
3278 files, discarding any previous merge attempts. Re-merging is not
3277 performed for files already marked as resolved. Use ``--all/-a``
3279 performed for files already marked as resolved. Use ``--all/-a``
3278 to selects all unresolved files. ``--tool`` can be used to specify
3280 to selects all unresolved files. ``--tool`` can be used to specify
3279 the merge tool used for the given files. It overrides the HGMERGE
3281 the merge tool used for the given files. It overrides the HGMERGE
3280 environment variable and your configuration files.
3282 environment variable and your configuration files.
3281
3283
3282 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3284 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3283 (e.g. after having manually fixed-up the files). The default is
3285 (e.g. after having manually fixed-up the files). The default is
3284 to mark all unresolved files.
3286 to mark all unresolved files.
3285
3287
3286 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3288 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3287 default is to mark all resolved files.
3289 default is to mark all resolved files.
3288
3290
3289 - :hg:`resolve -l`: list files which had or still have conflicts.
3291 - :hg:`resolve -l`: list files which had or still have conflicts.
3290 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3292 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3291
3293
3292 Note that Mercurial will not let you commit files with unresolved
3294 Note that Mercurial will not let you commit files with unresolved
3293 merge conflicts. You must use :hg:`resolve -m ...` before you can
3295 merge conflicts. You must use :hg:`resolve -m ...` before you can
3294 commit after a conflicting merge.
3296 commit after a conflicting merge.
3295
3297
3296 Returns 0 on success, 1 if any files fail a resolve attempt.
3298 Returns 0 on success, 1 if any files fail a resolve attempt.
3297 """
3299 """
3298
3300
3299 all, mark, unmark, show, nostatus = \
3301 all, mark, unmark, show, nostatus = \
3300 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3302 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3301
3303
3302 if (show and (mark or unmark)) or (mark and unmark):
3304 if (show and (mark or unmark)) or (mark and unmark):
3303 raise util.Abort(_("too many options specified"))
3305 raise util.Abort(_("too many options specified"))
3304 if pats and all:
3306 if pats and all:
3305 raise util.Abort(_("can't specify --all and patterns"))
3307 raise util.Abort(_("can't specify --all and patterns"))
3306 if not (all or pats or show or mark or unmark):
3308 if not (all or pats or show or mark or unmark):
3307 raise util.Abort(_('no files or directories specified; '
3309 raise util.Abort(_('no files or directories specified; '
3308 'use --all to remerge all files'))
3310 'use --all to remerge all files'))
3309
3311
3310 ms = mergemod.mergestate(repo)
3312 ms = mergemod.mergestate(repo)
3311 m = cmdutil.match(repo, pats, opts)
3313 m = cmdutil.match(repo, pats, opts)
3312 ret = 0
3314 ret = 0
3313
3315
3314 for f in ms:
3316 for f in ms:
3315 if m(f):
3317 if m(f):
3316 if show:
3318 if show:
3317 if nostatus:
3319 if nostatus:
3318 ui.write("%s\n" % f)
3320 ui.write("%s\n" % f)
3319 else:
3321 else:
3320 ui.write("%s %s\n" % (ms[f].upper(), f),
3322 ui.write("%s %s\n" % (ms[f].upper(), f),
3321 label='resolve.' +
3323 label='resolve.' +
3322 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3324 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3323 elif mark:
3325 elif mark:
3324 ms.mark(f, "r")
3326 ms.mark(f, "r")
3325 elif unmark:
3327 elif unmark:
3326 ms.mark(f, "u")
3328 ms.mark(f, "u")
3327 else:
3329 else:
3328 wctx = repo[None]
3330 wctx = repo[None]
3329 mctx = wctx.parents()[-1]
3331 mctx = wctx.parents()[-1]
3330
3332
3331 # backup pre-resolve (merge uses .orig for its own purposes)
3333 # backup pre-resolve (merge uses .orig for its own purposes)
3332 a = repo.wjoin(f)
3334 a = repo.wjoin(f)
3333 util.copyfile(a, a + ".resolve")
3335 util.copyfile(a, a + ".resolve")
3334
3336
3335 try:
3337 try:
3336 # resolve file
3338 # resolve file
3337 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3339 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3338 if ms.resolve(f, wctx, mctx):
3340 if ms.resolve(f, wctx, mctx):
3339 ret = 1
3341 ret = 1
3340 finally:
3342 finally:
3341 ui.setconfig('ui', 'forcemerge', '')
3343 ui.setconfig('ui', 'forcemerge', '')
3342
3344
3343 # replace filemerge's .orig file with our resolve file
3345 # replace filemerge's .orig file with our resolve file
3344 util.rename(a + ".resolve", a + ".orig")
3346 util.rename(a + ".resolve", a + ".orig")
3345
3347
3346 ms.commit()
3348 ms.commit()
3347 return ret
3349 return ret
3348
3350
3349 def revert(ui, repo, *pats, **opts):
3351 def revert(ui, repo, *pats, **opts):
3350 """restore individual files or directories to an earlier state
3352 """restore individual files or directories to an earlier state
3351
3353
3352 .. note::
3354 .. note::
3353 This command is most likely not what you are looking for.
3355 This command is most likely not what you are looking for.
3354 Revert will partially overwrite content in the working
3356 Revert will partially overwrite content in the working
3355 directory without changing the working directory parents. Use
3357 directory without changing the working directory parents. Use
3356 :hg:`update -r rev` to check out earlier revisions, or
3358 :hg:`update -r rev` to check out earlier revisions, or
3357 :hg:`update --clean .` to undo a merge which has added another
3359 :hg:`update --clean .` to undo a merge which has added another
3358 parent.
3360 parent.
3359
3361
3360 With no revision specified, revert the named files or directories
3362 With no revision specified, revert the named files or directories
3361 to the contents they had in the parent of the working directory.
3363 to the contents they had in the parent of the working directory.
3362 This restores the contents of the affected files to an unmodified
3364 This restores the contents of the affected files to an unmodified
3363 state and unschedules adds, removes, copies, and renames. If the
3365 state and unschedules adds, removes, copies, and renames. If the
3364 working directory has two parents, you must explicitly specify a
3366 working directory has two parents, you must explicitly specify a
3365 revision.
3367 revision.
3366
3368
3367 Using the -r/--rev option, revert the given files or directories
3369 Using the -r/--rev option, revert the given files or directories
3368 to their contents as of a specific revision. This can be helpful
3370 to their contents as of a specific revision. This can be helpful
3369 to "roll back" some or all of an earlier change. See :hg:`help
3371 to "roll back" some or all of an earlier change. See :hg:`help
3370 dates` for a list of formats valid for -d/--date.
3372 dates` for a list of formats valid for -d/--date.
3371
3373
3372 Revert modifies the working directory. It does not commit any
3374 Revert modifies the working directory. It does not commit any
3373 changes, or change the parent of the working directory. If you
3375 changes, or change the parent of the working directory. If you
3374 revert to a revision other than the parent of the working
3376 revert to a revision other than the parent of the working
3375 directory, the reverted files will thus appear modified
3377 directory, the reverted files will thus appear modified
3376 afterwards.
3378 afterwards.
3377
3379
3378 If a file has been deleted, it is restored. Files scheduled for
3380 If a file has been deleted, it is restored. Files scheduled for
3379 addition are just unscheduled and left as they are. If the
3381 addition are just unscheduled and left as they are. If the
3380 executable mode of a file was changed, it is reset.
3382 executable mode of a file was changed, it is reset.
3381
3383
3382 If names are given, all files matching the names are reverted.
3384 If names are given, all files matching the names are reverted.
3383 If no arguments are given, no files are reverted.
3385 If no arguments are given, no files are reverted.
3384
3386
3385 Modified files are saved with a .orig suffix before reverting.
3387 Modified files are saved with a .orig suffix before reverting.
3386 To disable these backups, use --no-backup.
3388 To disable these backups, use --no-backup.
3387
3389
3388 Returns 0 on success.
3390 Returns 0 on success.
3389 """
3391 """
3390
3392
3391 if opts.get("date"):
3393 if opts.get("date"):
3392 if opts.get("rev"):
3394 if opts.get("rev"):
3393 raise util.Abort(_("you can't specify a revision and a date"))
3395 raise util.Abort(_("you can't specify a revision and a date"))
3394 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3396 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3395
3397
3396 parent, p2 = repo.dirstate.parents()
3398 parent, p2 = repo.dirstate.parents()
3397 if not opts.get('rev') and p2 != nullid:
3399 if not opts.get('rev') and p2 != nullid:
3398 raise util.Abort(_('uncommitted merge - '
3400 raise util.Abort(_('uncommitted merge - '
3399 'use "hg update", see "hg help revert"'))
3401 'use "hg update", see "hg help revert"'))
3400
3402
3401 if not pats and not opts.get('all'):
3403 if not pats and not opts.get('all'):
3402 raise util.Abort(_('no files or directories specified; '
3404 raise util.Abort(_('no files or directories specified; '
3403 'use --all to revert the whole repo'))
3405 'use --all to revert the whole repo'))
3404
3406
3405 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3407 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3406 node = ctx.node()
3408 node = ctx.node()
3407 mf = ctx.manifest()
3409 mf = ctx.manifest()
3408 if node == parent:
3410 if node == parent:
3409 pmf = mf
3411 pmf = mf
3410 else:
3412 else:
3411 pmf = None
3413 pmf = None
3412
3414
3413 # need all matching names in dirstate and manifest of target rev,
3415 # need all matching names in dirstate and manifest of target rev,
3414 # so have to walk both. do not print errors if files exist in one
3416 # so have to walk both. do not print errors if files exist in one
3415 # but not other.
3417 # but not other.
3416
3418
3417 names = {}
3419 names = {}
3418
3420
3419 wlock = repo.wlock()
3421 wlock = repo.wlock()
3420 try:
3422 try:
3421 # walk dirstate.
3423 # walk dirstate.
3422
3424
3423 m = cmdutil.match(repo, pats, opts)
3425 m = cmdutil.match(repo, pats, opts)
3424 m.bad = lambda x, y: False
3426 m.bad = lambda x, y: False
3425 for abs in repo.walk(m):
3427 for abs in repo.walk(m):
3426 names[abs] = m.rel(abs), m.exact(abs)
3428 names[abs] = m.rel(abs), m.exact(abs)
3427
3429
3428 # walk target manifest.
3430 # walk target manifest.
3429
3431
3430 def badfn(path, msg):
3432 def badfn(path, msg):
3431 if path in names:
3433 if path in names:
3432 return
3434 return
3433 path_ = path + '/'
3435 path_ = path + '/'
3434 for f in names:
3436 for f in names:
3435 if f.startswith(path_):
3437 if f.startswith(path_):
3436 return
3438 return
3437 ui.warn("%s: %s\n" % (m.rel(path), msg))
3439 ui.warn("%s: %s\n" % (m.rel(path), msg))
3438
3440
3439 m = cmdutil.match(repo, pats, opts)
3441 m = cmdutil.match(repo, pats, opts)
3440 m.bad = badfn
3442 m.bad = badfn
3441 for abs in repo[node].walk(m):
3443 for abs in repo[node].walk(m):
3442 if abs not in names:
3444 if abs not in names:
3443 names[abs] = m.rel(abs), m.exact(abs)
3445 names[abs] = m.rel(abs), m.exact(abs)
3444
3446
3445 m = cmdutil.matchfiles(repo, names)
3447 m = cmdutil.matchfiles(repo, names)
3446 changes = repo.status(match=m)[:4]
3448 changes = repo.status(match=m)[:4]
3447 modified, added, removed, deleted = map(set, changes)
3449 modified, added, removed, deleted = map(set, changes)
3448
3450
3449 # if f is a rename, also revert the source
3451 # if f is a rename, also revert the source
3450 cwd = repo.getcwd()
3452 cwd = repo.getcwd()
3451 for f in added:
3453 for f in added:
3452 src = repo.dirstate.copied(f)
3454 src = repo.dirstate.copied(f)
3453 if src and src not in names and repo.dirstate[src] == 'r':
3455 if src and src not in names and repo.dirstate[src] == 'r':
3454 removed.add(src)
3456 removed.add(src)
3455 names[src] = (repo.pathto(src, cwd), True)
3457 names[src] = (repo.pathto(src, cwd), True)
3456
3458
3457 def removeforget(abs):
3459 def removeforget(abs):
3458 if repo.dirstate[abs] == 'a':
3460 if repo.dirstate[abs] == 'a':
3459 return _('forgetting %s\n')
3461 return _('forgetting %s\n')
3460 return _('removing %s\n')
3462 return _('removing %s\n')
3461
3463
3462 revert = ([], _('reverting %s\n'))
3464 revert = ([], _('reverting %s\n'))
3463 add = ([], _('adding %s\n'))
3465 add = ([], _('adding %s\n'))
3464 remove = ([], removeforget)
3466 remove = ([], removeforget)
3465 undelete = ([], _('undeleting %s\n'))
3467 undelete = ([], _('undeleting %s\n'))
3466
3468
3467 disptable = (
3469 disptable = (
3468 # dispatch table:
3470 # dispatch table:
3469 # file state
3471 # file state
3470 # action if in target manifest
3472 # action if in target manifest
3471 # action if not in target manifest
3473 # action if not in target manifest
3472 # make backup if in target manifest
3474 # make backup if in target manifest
3473 # make backup if not in target manifest
3475 # make backup if not in target manifest
3474 (modified, revert, remove, True, True),
3476 (modified, revert, remove, True, True),
3475 (added, revert, remove, True, False),
3477 (added, revert, remove, True, False),
3476 (removed, undelete, None, False, False),
3478 (removed, undelete, None, False, False),
3477 (deleted, revert, remove, False, False),
3479 (deleted, revert, remove, False, False),
3478 )
3480 )
3479
3481
3480 for abs, (rel, exact) in sorted(names.items()):
3482 for abs, (rel, exact) in sorted(names.items()):
3481 mfentry = mf.get(abs)
3483 mfentry = mf.get(abs)
3482 target = repo.wjoin(abs)
3484 target = repo.wjoin(abs)
3483 def handle(xlist, dobackup):
3485 def handle(xlist, dobackup):
3484 xlist[0].append(abs)
3486 xlist[0].append(abs)
3485 if (dobackup and not opts.get('no_backup') and
3487 if (dobackup and not opts.get('no_backup') and
3486 os.path.lexists(target)):
3488 os.path.lexists(target)):
3487 bakname = "%s.orig" % rel
3489 bakname = "%s.orig" % rel
3488 ui.note(_('saving current version of %s as %s\n') %
3490 ui.note(_('saving current version of %s as %s\n') %
3489 (rel, bakname))
3491 (rel, bakname))
3490 if not opts.get('dry_run'):
3492 if not opts.get('dry_run'):
3491 util.rename(target, bakname)
3493 util.rename(target, bakname)
3492 if ui.verbose or not exact:
3494 if ui.verbose or not exact:
3493 msg = xlist[1]
3495 msg = xlist[1]
3494 if not isinstance(msg, basestring):
3496 if not isinstance(msg, basestring):
3495 msg = msg(abs)
3497 msg = msg(abs)
3496 ui.status(msg % rel)
3498 ui.status(msg % rel)
3497 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3499 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3498 if abs not in table:
3500 if abs not in table:
3499 continue
3501 continue
3500 # file has changed in dirstate
3502 # file has changed in dirstate
3501 if mfentry:
3503 if mfentry:
3502 handle(hitlist, backuphit)
3504 handle(hitlist, backuphit)
3503 elif misslist is not None:
3505 elif misslist is not None:
3504 handle(misslist, backupmiss)
3506 handle(misslist, backupmiss)
3505 break
3507 break
3506 else:
3508 else:
3507 if abs not in repo.dirstate:
3509 if abs not in repo.dirstate:
3508 if mfentry:
3510 if mfentry:
3509 handle(add, True)
3511 handle(add, True)
3510 elif exact:
3512 elif exact:
3511 ui.warn(_('file not managed: %s\n') % rel)
3513 ui.warn(_('file not managed: %s\n') % rel)
3512 continue
3514 continue
3513 # file has not changed in dirstate
3515 # file has not changed in dirstate
3514 if node == parent:
3516 if node == parent:
3515 if exact:
3517 if exact:
3516 ui.warn(_('no changes needed to %s\n') % rel)
3518 ui.warn(_('no changes needed to %s\n') % rel)
3517 continue
3519 continue
3518 if pmf is None:
3520 if pmf is None:
3519 # only need parent manifest in this unlikely case,
3521 # only need parent manifest in this unlikely case,
3520 # so do not read by default
3522 # so do not read by default
3521 pmf = repo[parent].manifest()
3523 pmf = repo[parent].manifest()
3522 if abs in pmf:
3524 if abs in pmf:
3523 if mfentry:
3525 if mfentry:
3524 # if version of file is same in parent and target
3526 # if version of file is same in parent and target
3525 # manifests, do nothing
3527 # manifests, do nothing
3526 if (pmf[abs] != mfentry or
3528 if (pmf[abs] != mfentry or
3527 pmf.flags(abs) != mf.flags(abs)):
3529 pmf.flags(abs) != mf.flags(abs)):
3528 handle(revert, False)
3530 handle(revert, False)
3529 else:
3531 else:
3530 handle(remove, False)
3532 handle(remove, False)
3531
3533
3532 if not opts.get('dry_run'):
3534 if not opts.get('dry_run'):
3533 def checkout(f):
3535 def checkout(f):
3534 fc = ctx[f]
3536 fc = ctx[f]
3535 repo.wwrite(f, fc.data(), fc.flags())
3537 repo.wwrite(f, fc.data(), fc.flags())
3536
3538
3537 audit_path = util.path_auditor(repo.root)
3539 audit_path = util.path_auditor(repo.root)
3538 for f in remove[0]:
3540 for f in remove[0]:
3539 if repo.dirstate[f] == 'a':
3541 if repo.dirstate[f] == 'a':
3540 repo.dirstate.forget(f)
3542 repo.dirstate.forget(f)
3541 continue
3543 continue
3542 audit_path(f)
3544 audit_path(f)
3543 try:
3545 try:
3544 util.unlinkpath(repo.wjoin(f))
3546 util.unlinkpath(repo.wjoin(f))
3545 except OSError:
3547 except OSError:
3546 pass
3548 pass
3547 repo.dirstate.remove(f)
3549 repo.dirstate.remove(f)
3548
3550
3549 normal = None
3551 normal = None
3550 if node == parent:
3552 if node == parent:
3551 # We're reverting to our parent. If possible, we'd like status
3553 # We're reverting to our parent. If possible, we'd like status
3552 # to report the file as clean. We have to use normallookup for
3554 # to report the file as clean. We have to use normallookup for
3553 # merges to avoid losing information about merged/dirty files.
3555 # merges to avoid losing information about merged/dirty files.
3554 if p2 != nullid:
3556 if p2 != nullid:
3555 normal = repo.dirstate.normallookup
3557 normal = repo.dirstate.normallookup
3556 else:
3558 else:
3557 normal = repo.dirstate.normal
3559 normal = repo.dirstate.normal
3558 for f in revert[0]:
3560 for f in revert[0]:
3559 checkout(f)
3561 checkout(f)
3560 if normal:
3562 if normal:
3561 normal(f)
3563 normal(f)
3562
3564
3563 for f in add[0]:
3565 for f in add[0]:
3564 checkout(f)
3566 checkout(f)
3565 repo.dirstate.add(f)
3567 repo.dirstate.add(f)
3566
3568
3567 normal = repo.dirstate.normallookup
3569 normal = repo.dirstate.normallookup
3568 if node == parent and p2 == nullid:
3570 if node == parent and p2 == nullid:
3569 normal = repo.dirstate.normal
3571 normal = repo.dirstate.normal
3570 for f in undelete[0]:
3572 for f in undelete[0]:
3571 checkout(f)
3573 checkout(f)
3572 normal(f)
3574 normal(f)
3573
3575
3574 finally:
3576 finally:
3575 wlock.release()
3577 wlock.release()
3576
3578
3577 def rollback(ui, repo, **opts):
3579 def rollback(ui, repo, **opts):
3578 """roll back the last transaction (dangerous)
3580 """roll back the last transaction (dangerous)
3579
3581
3580 This command should be used with care. There is only one level of
3582 This command should be used with care. There is only one level of
3581 rollback, and there is no way to undo a rollback. It will also
3583 rollback, and there is no way to undo a rollback. It will also
3582 restore the dirstate at the time of the last transaction, losing
3584 restore the dirstate at the time of the last transaction, losing
3583 any dirstate changes since that time. This command does not alter
3585 any dirstate changes since that time. This command does not alter
3584 the working directory.
3586 the working directory.
3585
3587
3586 Transactions are used to encapsulate the effects of all commands
3588 Transactions are used to encapsulate the effects of all commands
3587 that create new changesets or propagate existing changesets into a
3589 that create new changesets or propagate existing changesets into a
3588 repository. For example, the following commands are transactional,
3590 repository. For example, the following commands are transactional,
3589 and their effects can be rolled back:
3591 and their effects can be rolled back:
3590
3592
3591 - commit
3593 - commit
3592 - import
3594 - import
3593 - pull
3595 - pull
3594 - push (with this repository as the destination)
3596 - push (with this repository as the destination)
3595 - unbundle
3597 - unbundle
3596
3598
3597 This command is not intended for use on public repositories. Once
3599 This command is not intended for use on public repositories. Once
3598 changes are visible for pull by other users, rolling a transaction
3600 changes are visible for pull by other users, rolling a transaction
3599 back locally is ineffective (someone else may already have pulled
3601 back locally is ineffective (someone else may already have pulled
3600 the changes). Furthermore, a race is possible with readers of the
3602 the changes). Furthermore, a race is possible with readers of the
3601 repository; for example an in-progress pull from the repository
3603 repository; for example an in-progress pull from the repository
3602 may fail if a rollback is performed.
3604 may fail if a rollback is performed.
3603
3605
3604 Returns 0 on success, 1 if no rollback data is available.
3606 Returns 0 on success, 1 if no rollback data is available.
3605 """
3607 """
3606 return repo.rollback(opts.get('dry_run'))
3608 return repo.rollback(opts.get('dry_run'))
3607
3609
3608 def root(ui, repo):
3610 def root(ui, repo):
3609 """print the root (top) of the current working directory
3611 """print the root (top) of the current working directory
3610
3612
3611 Print the root directory of the current repository.
3613 Print the root directory of the current repository.
3612
3614
3613 Returns 0 on success.
3615 Returns 0 on success.
3614 """
3616 """
3615 ui.write(repo.root + "\n")
3617 ui.write(repo.root + "\n")
3616
3618
3617 def serve(ui, repo, **opts):
3619 def serve(ui, repo, **opts):
3618 """start stand-alone webserver
3620 """start stand-alone webserver
3619
3621
3620 Start a local HTTP repository browser and pull server. You can use
3622 Start a local HTTP repository browser and pull server. You can use
3621 this for ad-hoc sharing and browsing of repositories. It is
3623 this for ad-hoc sharing and browsing of repositories. It is
3622 recommended to use a real web server to serve a repository for
3624 recommended to use a real web server to serve a repository for
3623 longer periods of time.
3625 longer periods of time.
3624
3626
3625 Please note that the server does not implement access control.
3627 Please note that the server does not implement access control.
3626 This means that, by default, anybody can read from the server and
3628 This means that, by default, anybody can read from the server and
3627 nobody can write to it by default. Set the ``web.allow_push``
3629 nobody can write to it by default. Set the ``web.allow_push``
3628 option to ``*`` to allow everybody to push to the server. You
3630 option to ``*`` to allow everybody to push to the server. You
3629 should use a real web server if you need to authenticate users.
3631 should use a real web server if you need to authenticate users.
3630
3632
3631 By default, the server logs accesses to stdout and errors to
3633 By default, the server logs accesses to stdout and errors to
3632 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3634 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3633 files.
3635 files.
3634
3636
3635 To have the server choose a free port number to listen on, specify
3637 To have the server choose a free port number to listen on, specify
3636 a port number of 0; in this case, the server will print the port
3638 a port number of 0; in this case, the server will print the port
3637 number it uses.
3639 number it uses.
3638
3640
3639 Returns 0 on success.
3641 Returns 0 on success.
3640 """
3642 """
3641
3643
3642 if opts["stdio"]:
3644 if opts["stdio"]:
3643 if repo is None:
3645 if repo is None:
3644 raise error.RepoError(_("There is no Mercurial repository here"
3646 raise error.RepoError(_("There is no Mercurial repository here"
3645 " (.hg not found)"))
3647 " (.hg not found)"))
3646 s = sshserver.sshserver(ui, repo)
3648 s = sshserver.sshserver(ui, repo)
3647 s.serve_forever()
3649 s.serve_forever()
3648
3650
3649 # this way we can check if something was given in the command-line
3651 # this way we can check if something was given in the command-line
3650 if opts.get('port'):
3652 if opts.get('port'):
3651 opts['port'] = util.getport(opts.get('port'))
3653 opts['port'] = util.getport(opts.get('port'))
3652
3654
3653 baseui = repo and repo.baseui or ui
3655 baseui = repo and repo.baseui or ui
3654 optlist = ("name templates style address port prefix ipv6"
3656 optlist = ("name templates style address port prefix ipv6"
3655 " accesslog errorlog certificate encoding")
3657 " accesslog errorlog certificate encoding")
3656 for o in optlist.split():
3658 for o in optlist.split():
3657 val = opts.get(o, '')
3659 val = opts.get(o, '')
3658 if val in (None, ''): # should check against default options instead
3660 if val in (None, ''): # should check against default options instead
3659 continue
3661 continue
3660 baseui.setconfig("web", o, val)
3662 baseui.setconfig("web", o, val)
3661 if repo and repo.ui != baseui:
3663 if repo and repo.ui != baseui:
3662 repo.ui.setconfig("web", o, val)
3664 repo.ui.setconfig("web", o, val)
3663
3665
3664 o = opts.get('web_conf') or opts.get('webdir_conf')
3666 o = opts.get('web_conf') or opts.get('webdir_conf')
3665 if not o:
3667 if not o:
3666 if not repo:
3668 if not repo:
3667 raise error.RepoError(_("There is no Mercurial repository"
3669 raise error.RepoError(_("There is no Mercurial repository"
3668 " here (.hg not found)"))
3670 " here (.hg not found)"))
3669 o = repo.root
3671 o = repo.root
3670
3672
3671 app = hgweb.hgweb(o, baseui=ui)
3673 app = hgweb.hgweb(o, baseui=ui)
3672
3674
3673 class service(object):
3675 class service(object):
3674 def init(self):
3676 def init(self):
3675 util.set_signal_handler()
3677 util.set_signal_handler()
3676 self.httpd = hgweb.server.create_server(ui, app)
3678 self.httpd = hgweb.server.create_server(ui, app)
3677
3679
3678 if opts['port'] and not ui.verbose:
3680 if opts['port'] and not ui.verbose:
3679 return
3681 return
3680
3682
3681 if self.httpd.prefix:
3683 if self.httpd.prefix:
3682 prefix = self.httpd.prefix.strip('/') + '/'
3684 prefix = self.httpd.prefix.strip('/') + '/'
3683 else:
3685 else:
3684 prefix = ''
3686 prefix = ''
3685
3687
3686 port = ':%d' % self.httpd.port
3688 port = ':%d' % self.httpd.port
3687 if port == ':80':
3689 if port == ':80':
3688 port = ''
3690 port = ''
3689
3691
3690 bindaddr = self.httpd.addr
3692 bindaddr = self.httpd.addr
3691 if bindaddr == '0.0.0.0':
3693 if bindaddr == '0.0.0.0':
3692 bindaddr = '*'
3694 bindaddr = '*'
3693 elif ':' in bindaddr: # IPv6
3695 elif ':' in bindaddr: # IPv6
3694 bindaddr = '[%s]' % bindaddr
3696 bindaddr = '[%s]' % bindaddr
3695
3697
3696 fqaddr = self.httpd.fqaddr
3698 fqaddr = self.httpd.fqaddr
3697 if ':' in fqaddr:
3699 if ':' in fqaddr:
3698 fqaddr = '[%s]' % fqaddr
3700 fqaddr = '[%s]' % fqaddr
3699 if opts['port']:
3701 if opts['port']:
3700 write = ui.status
3702 write = ui.status
3701 else:
3703 else:
3702 write = ui.write
3704 write = ui.write
3703 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3705 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3704 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3706 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3705
3707
3706 def run(self):
3708 def run(self):
3707 self.httpd.serve_forever()
3709 self.httpd.serve_forever()
3708
3710
3709 service = service()
3711 service = service()
3710
3712
3711 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3713 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3712
3714
3713 def status(ui, repo, *pats, **opts):
3715 def status(ui, repo, *pats, **opts):
3714 """show changed files in the working directory
3716 """show changed files in the working directory
3715
3717
3716 Show status of files in the repository. If names are given, only
3718 Show status of files in the repository. If names are given, only
3717 files that match are shown. Files that are clean or ignored or
3719 files that match are shown. Files that are clean or ignored or
3718 the source of a copy/move operation, are not listed unless
3720 the source of a copy/move operation, are not listed unless
3719 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3721 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3720 Unless options described with "show only ..." are given, the
3722 Unless options described with "show only ..." are given, the
3721 options -mardu are used.
3723 options -mardu are used.
3722
3724
3723 Option -q/--quiet hides untracked (unknown and ignored) files
3725 Option -q/--quiet hides untracked (unknown and ignored) files
3724 unless explicitly requested with -u/--unknown or -i/--ignored.
3726 unless explicitly requested with -u/--unknown or -i/--ignored.
3725
3727
3726 .. note::
3728 .. note::
3727 status may appear to disagree with diff if permissions have
3729 status may appear to disagree with diff if permissions have
3728 changed or a merge has occurred. The standard diff format does
3730 changed or a merge has occurred. The standard diff format does
3729 not report permission changes and diff only reports changes
3731 not report permission changes and diff only reports changes
3730 relative to one merge parent.
3732 relative to one merge parent.
3731
3733
3732 If one revision is given, it is used as the base revision.
3734 If one revision is given, it is used as the base revision.
3733 If two revisions are given, the differences between them are
3735 If two revisions are given, the differences between them are
3734 shown. The --change option can also be used as a shortcut to list
3736 shown. The --change option can also be used as a shortcut to list
3735 the changed files of a revision from its first parent.
3737 the changed files of a revision from its first parent.
3736
3738
3737 The codes used to show the status of files are::
3739 The codes used to show the status of files are::
3738
3740
3739 M = modified
3741 M = modified
3740 A = added
3742 A = added
3741 R = removed
3743 R = removed
3742 C = clean
3744 C = clean
3743 ! = missing (deleted by non-hg command, but still tracked)
3745 ! = missing (deleted by non-hg command, but still tracked)
3744 ? = not tracked
3746 ? = not tracked
3745 I = ignored
3747 I = ignored
3746 = origin of the previous file listed as A (added)
3748 = origin of the previous file listed as A (added)
3747
3749
3748 Returns 0 on success.
3750 Returns 0 on success.
3749 """
3751 """
3750
3752
3751 revs = opts.get('rev')
3753 revs = opts.get('rev')
3752 change = opts.get('change')
3754 change = opts.get('change')
3753
3755
3754 if revs and change:
3756 if revs and change:
3755 msg = _('cannot specify --rev and --change at the same time')
3757 msg = _('cannot specify --rev and --change at the same time')
3756 raise util.Abort(msg)
3758 raise util.Abort(msg)
3757 elif change:
3759 elif change:
3758 node2 = repo.lookup(change)
3760 node2 = repo.lookup(change)
3759 node1 = repo[node2].p1().node()
3761 node1 = repo[node2].p1().node()
3760 else:
3762 else:
3761 node1, node2 = cmdutil.revpair(repo, revs)
3763 node1, node2 = cmdutil.revpair(repo, revs)
3762
3764
3763 cwd = (pats and repo.getcwd()) or ''
3765 cwd = (pats and repo.getcwd()) or ''
3764 end = opts.get('print0') and '\0' or '\n'
3766 end = opts.get('print0') and '\0' or '\n'
3765 copy = {}
3767 copy = {}
3766 states = 'modified added removed deleted unknown ignored clean'.split()
3768 states = 'modified added removed deleted unknown ignored clean'.split()
3767 show = [k for k in states if opts.get(k)]
3769 show = [k for k in states if opts.get(k)]
3768 if opts.get('all'):
3770 if opts.get('all'):
3769 show += ui.quiet and (states[:4] + ['clean']) or states
3771 show += ui.quiet and (states[:4] + ['clean']) or states
3770 if not show:
3772 if not show:
3771 show = ui.quiet and states[:4] or states[:5]
3773 show = ui.quiet and states[:4] or states[:5]
3772
3774
3773 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3775 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3774 'ignored' in show, 'clean' in show, 'unknown' in show,
3776 'ignored' in show, 'clean' in show, 'unknown' in show,
3775 opts.get('subrepos'))
3777 opts.get('subrepos'))
3776 changestates = zip(states, 'MAR!?IC', stat)
3778 changestates = zip(states, 'MAR!?IC', stat)
3777
3779
3778 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3780 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3779 ctxn = repo[nullid]
3781 ctxn = repo[nullid]
3780 ctx1 = repo[node1]
3782 ctx1 = repo[node1]
3781 ctx2 = repo[node2]
3783 ctx2 = repo[node2]
3782 added = stat[1]
3784 added = stat[1]
3783 if node2 is None:
3785 if node2 is None:
3784 added = stat[0] + stat[1] # merged?
3786 added = stat[0] + stat[1] # merged?
3785
3787
3786 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3788 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3787 if k in added:
3789 if k in added:
3788 copy[k] = v
3790 copy[k] = v
3789 elif v in added:
3791 elif v in added:
3790 copy[v] = k
3792 copy[v] = k
3791
3793
3792 for state, char, files in changestates:
3794 for state, char, files in changestates:
3793 if state in show:
3795 if state in show:
3794 format = "%s %%s%s" % (char, end)
3796 format = "%s %%s%s" % (char, end)
3795 if opts.get('no_status'):
3797 if opts.get('no_status'):
3796 format = "%%s%s" % end
3798 format = "%%s%s" % end
3797
3799
3798 for f in files:
3800 for f in files:
3799 ui.write(format % repo.pathto(f, cwd),
3801 ui.write(format % repo.pathto(f, cwd),
3800 label='status.' + state)
3802 label='status.' + state)
3801 if f in copy:
3803 if f in copy:
3802 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3804 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3803 label='status.copied')
3805 label='status.copied')
3804
3806
3805 def summary(ui, repo, **opts):
3807 def summary(ui, repo, **opts):
3806 """summarize working directory state
3808 """summarize working directory state
3807
3809
3808 This generates a brief summary of the working directory state,
3810 This generates a brief summary of the working directory state,
3809 including parents, branch, commit status, and available updates.
3811 including parents, branch, commit status, and available updates.
3810
3812
3811 With the --remote option, this will check the default paths for
3813 With the --remote option, this will check the default paths for
3812 incoming and outgoing changes. This can be time-consuming.
3814 incoming and outgoing changes. This can be time-consuming.
3813
3815
3814 Returns 0 on success.
3816 Returns 0 on success.
3815 """
3817 """
3816
3818
3817 ctx = repo[None]
3819 ctx = repo[None]
3818 parents = ctx.parents()
3820 parents = ctx.parents()
3819 pnode = parents[0].node()
3821 pnode = parents[0].node()
3820
3822
3821 for p in parents:
3823 for p in parents:
3822 # label with log.changeset (instead of log.parent) since this
3824 # label with log.changeset (instead of log.parent) since this
3823 # shows a working directory parent *changeset*:
3825 # shows a working directory parent *changeset*:
3824 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3826 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3825 label='log.changeset')
3827 label='log.changeset')
3826 ui.write(' '.join(p.tags()), label='log.tag')
3828 ui.write(' '.join(p.tags()), label='log.tag')
3827 if p.bookmarks():
3829 if p.bookmarks():
3828 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
3830 ui.write(' ' + ' '.join(p.bookmarks()), label='log.bookmark')
3829 if p.rev() == -1:
3831 if p.rev() == -1:
3830 if not len(repo):
3832 if not len(repo):
3831 ui.write(_(' (empty repository)'))
3833 ui.write(_(' (empty repository)'))
3832 else:
3834 else:
3833 ui.write(_(' (no revision checked out)'))
3835 ui.write(_(' (no revision checked out)'))
3834 ui.write('\n')
3836 ui.write('\n')
3835 if p.description():
3837 if p.description():
3836 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3838 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3837 label='log.summary')
3839 label='log.summary')
3838
3840
3839 branch = ctx.branch()
3841 branch = ctx.branch()
3840 bheads = repo.branchheads(branch)
3842 bheads = repo.branchheads(branch)
3841 m = _('branch: %s\n') % branch
3843 m = _('branch: %s\n') % branch
3842 if branch != 'default':
3844 if branch != 'default':
3843 ui.write(m, label='log.branch')
3845 ui.write(m, label='log.branch')
3844 else:
3846 else:
3845 ui.status(m, label='log.branch')
3847 ui.status(m, label='log.branch')
3846
3848
3847 st = list(repo.status(unknown=True))[:6]
3849 st = list(repo.status(unknown=True))[:6]
3848
3850
3849 c = repo.dirstate.copies()
3851 c = repo.dirstate.copies()
3850 copied, renamed = [], []
3852 copied, renamed = [], []
3851 for d, s in c.iteritems():
3853 for d, s in c.iteritems():
3852 if s in st[2]:
3854 if s in st[2]:
3853 st[2].remove(s)
3855 st[2].remove(s)
3854 renamed.append(d)
3856 renamed.append(d)
3855 else:
3857 else:
3856 copied.append(d)
3858 copied.append(d)
3857 if d in st[1]:
3859 if d in st[1]:
3858 st[1].remove(d)
3860 st[1].remove(d)
3859 st.insert(3, renamed)
3861 st.insert(3, renamed)
3860 st.insert(4, copied)
3862 st.insert(4, copied)
3861
3863
3862 ms = mergemod.mergestate(repo)
3864 ms = mergemod.mergestate(repo)
3863 st.append([f for f in ms if ms[f] == 'u'])
3865 st.append([f for f in ms if ms[f] == 'u'])
3864
3866
3865 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3867 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3866 st.append(subs)
3868 st.append(subs)
3867
3869
3868 labels = [ui.label(_('%d modified'), 'status.modified'),
3870 labels = [ui.label(_('%d modified'), 'status.modified'),
3869 ui.label(_('%d added'), 'status.added'),
3871 ui.label(_('%d added'), 'status.added'),
3870 ui.label(_('%d removed'), 'status.removed'),
3872 ui.label(_('%d removed'), 'status.removed'),
3871 ui.label(_('%d renamed'), 'status.copied'),
3873 ui.label(_('%d renamed'), 'status.copied'),
3872 ui.label(_('%d copied'), 'status.copied'),
3874 ui.label(_('%d copied'), 'status.copied'),
3873 ui.label(_('%d deleted'), 'status.deleted'),
3875 ui.label(_('%d deleted'), 'status.deleted'),
3874 ui.label(_('%d unknown'), 'status.unknown'),
3876 ui.label(_('%d unknown'), 'status.unknown'),
3875 ui.label(_('%d ignored'), 'status.ignored'),
3877 ui.label(_('%d ignored'), 'status.ignored'),
3876 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3878 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3877 ui.label(_('%d subrepos'), 'status.modified')]
3879 ui.label(_('%d subrepos'), 'status.modified')]
3878 t = []
3880 t = []
3879 for s, l in zip(st, labels):
3881 for s, l in zip(st, labels):
3880 if s:
3882 if s:
3881 t.append(l % len(s))
3883 t.append(l % len(s))
3882
3884
3883 t = ', '.join(t)
3885 t = ', '.join(t)
3884 cleanworkdir = False
3886 cleanworkdir = False
3885
3887
3886 if len(parents) > 1:
3888 if len(parents) > 1:
3887 t += _(' (merge)')
3889 t += _(' (merge)')
3888 elif branch != parents[0].branch():
3890 elif branch != parents[0].branch():
3889 t += _(' (new branch)')
3891 t += _(' (new branch)')
3890 elif (parents[0].extra().get('close') and
3892 elif (parents[0].extra().get('close') and
3891 pnode in repo.branchheads(branch, closed=True)):
3893 pnode in repo.branchheads(branch, closed=True)):
3892 t += _(' (head closed)')
3894 t += _(' (head closed)')
3893 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3895 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3894 t += _(' (clean)')
3896 t += _(' (clean)')
3895 cleanworkdir = True
3897 cleanworkdir = True
3896 elif pnode not in bheads:
3898 elif pnode not in bheads:
3897 t += _(' (new branch head)')
3899 t += _(' (new branch head)')
3898
3900
3899 if cleanworkdir:
3901 if cleanworkdir:
3900 ui.status(_('commit: %s\n') % t.strip())
3902 ui.status(_('commit: %s\n') % t.strip())
3901 else:
3903 else:
3902 ui.write(_('commit: %s\n') % t.strip())
3904 ui.write(_('commit: %s\n') % t.strip())
3903
3905
3904 # all ancestors of branch heads - all ancestors of parent = new csets
3906 # all ancestors of branch heads - all ancestors of parent = new csets
3905 new = [0] * len(repo)
3907 new = [0] * len(repo)
3906 cl = repo.changelog
3908 cl = repo.changelog
3907 for a in [cl.rev(n) for n in bheads]:
3909 for a in [cl.rev(n) for n in bheads]:
3908 new[a] = 1
3910 new[a] = 1
3909 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3911 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3910 new[a] = 1
3912 new[a] = 1
3911 for a in [p.rev() for p in parents]:
3913 for a in [p.rev() for p in parents]:
3912 if a >= 0:
3914 if a >= 0:
3913 new[a] = 0
3915 new[a] = 0
3914 for a in cl.ancestors(*[p.rev() for p in parents]):
3916 for a in cl.ancestors(*[p.rev() for p in parents]):
3915 new[a] = 0
3917 new[a] = 0
3916 new = sum(new)
3918 new = sum(new)
3917
3919
3918 if new == 0:
3920 if new == 0:
3919 ui.status(_('update: (current)\n'))
3921 ui.status(_('update: (current)\n'))
3920 elif pnode not in bheads:
3922 elif pnode not in bheads:
3921 ui.write(_('update: %d new changesets (update)\n') % new)
3923 ui.write(_('update: %d new changesets (update)\n') % new)
3922 else:
3924 else:
3923 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3925 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3924 (new, len(bheads)))
3926 (new, len(bheads)))
3925
3927
3926 if opts.get('remote'):
3928 if opts.get('remote'):
3927 t = []
3929 t = []
3928 source, branches = hg.parseurl(ui.expandpath('default'))
3930 source, branches = hg.parseurl(ui.expandpath('default'))
3929 other = hg.repository(hg.remoteui(repo, {}), source)
3931 other = hg.repository(hg.remoteui(repo, {}), source)
3930 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3932 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3931 ui.debug('comparing with %s\n' % url.hidepassword(source))
3933 ui.debug('comparing with %s\n' % url.hidepassword(source))
3932 repo.ui.pushbuffer()
3934 repo.ui.pushbuffer()
3933 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3935 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3934 repo.ui.popbuffer()
3936 repo.ui.popbuffer()
3935 if incoming:
3937 if incoming:
3936 t.append(_('1 or more incoming'))
3938 t.append(_('1 or more incoming'))
3937
3939
3938 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3940 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3939 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3941 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3940 other = hg.repository(hg.remoteui(repo, {}), dest)
3942 other = hg.repository(hg.remoteui(repo, {}), dest)
3941 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3943 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3942 repo.ui.pushbuffer()
3944 repo.ui.pushbuffer()
3943 o = discovery.findoutgoing(repo, other)
3945 o = discovery.findoutgoing(repo, other)
3944 repo.ui.popbuffer()
3946 repo.ui.popbuffer()
3945 o = repo.changelog.nodesbetween(o, None)[0]
3947 o = repo.changelog.nodesbetween(o, None)[0]
3946 if o:
3948 if o:
3947 t.append(_('%d outgoing') % len(o))
3949 t.append(_('%d outgoing') % len(o))
3948 if 'bookmarks' in other.listkeys('namespaces'):
3950 if 'bookmarks' in other.listkeys('namespaces'):
3949 lmarks = repo.listkeys('bookmarks')
3951 lmarks = repo.listkeys('bookmarks')
3950 rmarks = other.listkeys('bookmarks')
3952 rmarks = other.listkeys('bookmarks')
3951 diff = set(rmarks) - set(lmarks)
3953 diff = set(rmarks) - set(lmarks)
3952 if len(diff) > 0:
3954 if len(diff) > 0:
3953 t.append(_('%d incoming bookmarks') % len(diff))
3955 t.append(_('%d incoming bookmarks') % len(diff))
3954 diff = set(lmarks) - set(rmarks)
3956 diff = set(lmarks) - set(rmarks)
3955 if len(diff) > 0:
3957 if len(diff) > 0:
3956 t.append(_('%d outgoing bookmarks') % len(diff))
3958 t.append(_('%d outgoing bookmarks') % len(diff))
3957
3959
3958 if t:
3960 if t:
3959 ui.write(_('remote: %s\n') % (', '.join(t)))
3961 ui.write(_('remote: %s\n') % (', '.join(t)))
3960 else:
3962 else:
3961 ui.status(_('remote: (synced)\n'))
3963 ui.status(_('remote: (synced)\n'))
3962
3964
3963 def tag(ui, repo, name1, *names, **opts):
3965 def tag(ui, repo, name1, *names, **opts):
3964 """add one or more tags for the current or given revision
3966 """add one or more tags for the current or given revision
3965
3967
3966 Name a particular revision using <name>.
3968 Name a particular revision using <name>.
3967
3969
3968 Tags are used to name particular revisions of the repository and are
3970 Tags are used to name particular revisions of the repository and are
3969 very useful to compare different revisions, to go back to significant
3971 very useful to compare different revisions, to go back to significant
3970 earlier versions or to mark branch points as releases, etc. Changing
3972 earlier versions or to mark branch points as releases, etc. Changing
3971 an existing tag is normally disallowed; use -f/--force to override.
3973 an existing tag is normally disallowed; use -f/--force to override.
3972
3974
3973 If no revision is given, the parent of the working directory is
3975 If no revision is given, the parent of the working directory is
3974 used, or tip if no revision is checked out.
3976 used, or tip if no revision is checked out.
3975
3977
3976 To facilitate version control, distribution, and merging of tags,
3978 To facilitate version control, distribution, and merging of tags,
3977 they are stored as a file named ".hgtags" which is managed similarly
3979 they are stored as a file named ".hgtags" which is managed similarly
3978 to other project files and can be hand-edited if necessary. This
3980 to other project files and can be hand-edited if necessary. This
3979 also means that tagging creates a new commit. The file
3981 also means that tagging creates a new commit. The file
3980 ".hg/localtags" is used for local tags (not shared among
3982 ".hg/localtags" is used for local tags (not shared among
3981 repositories).
3983 repositories).
3982
3984
3983 Tag commits are usually made at the head of a branch. If the parent
3985 Tag commits are usually made at the head of a branch. If the parent
3984 of the working directory is not a branch head, :hg:`tag` aborts; use
3986 of the working directory is not a branch head, :hg:`tag` aborts; use
3985 -f/--force to force the tag commit to be based on a non-head
3987 -f/--force to force the tag commit to be based on a non-head
3986 changeset.
3988 changeset.
3987
3989
3988 See :hg:`help dates` for a list of formats valid for -d/--date.
3990 See :hg:`help dates` for a list of formats valid for -d/--date.
3989
3991
3990 Since tag names have priority over branch names during revision
3992 Since tag names have priority over branch names during revision
3991 lookup, using an existing branch name as a tag name is discouraged.
3993 lookup, using an existing branch name as a tag name is discouraged.
3992
3994
3993 Returns 0 on success.
3995 Returns 0 on success.
3994 """
3996 """
3995
3997
3996 rev_ = "."
3998 rev_ = "."
3997 names = [t.strip() for t in (name1,) + names]
3999 names = [t.strip() for t in (name1,) + names]
3998 if len(names) != len(set(names)):
4000 if len(names) != len(set(names)):
3999 raise util.Abort(_('tag names must be unique'))
4001 raise util.Abort(_('tag names must be unique'))
4000 for n in names:
4002 for n in names:
4001 if n in ['tip', '.', 'null']:
4003 if n in ['tip', '.', 'null']:
4002 raise util.Abort(_('the name \'%s\' is reserved') % n)
4004 raise util.Abort(_('the name \'%s\' is reserved') % n)
4003 if not n:
4005 if not n:
4004 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
4006 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
4005 if opts.get('rev') and opts.get('remove'):
4007 if opts.get('rev') and opts.get('remove'):
4006 raise util.Abort(_("--rev and --remove are incompatible"))
4008 raise util.Abort(_("--rev and --remove are incompatible"))
4007 if opts.get('rev'):
4009 if opts.get('rev'):
4008 rev_ = opts['rev']
4010 rev_ = opts['rev']
4009 message = opts.get('message')
4011 message = opts.get('message')
4010 if opts.get('remove'):
4012 if opts.get('remove'):
4011 expectedtype = opts.get('local') and 'local' or 'global'
4013 expectedtype = opts.get('local') and 'local' or 'global'
4012 for n in names:
4014 for n in names:
4013 if not repo.tagtype(n):
4015 if not repo.tagtype(n):
4014 raise util.Abort(_('tag \'%s\' does not exist') % n)
4016 raise util.Abort(_('tag \'%s\' does not exist') % n)
4015 if repo.tagtype(n) != expectedtype:
4017 if repo.tagtype(n) != expectedtype:
4016 if expectedtype == 'global':
4018 if expectedtype == 'global':
4017 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
4019 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
4018 else:
4020 else:
4019 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
4021 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
4020 rev_ = nullid
4022 rev_ = nullid
4021 if not message:
4023 if not message:
4022 # we don't translate commit messages
4024 # we don't translate commit messages
4023 message = 'Removed tag %s' % ', '.join(names)
4025 message = 'Removed tag %s' % ', '.join(names)
4024 elif not opts.get('force'):
4026 elif not opts.get('force'):
4025 for n in names:
4027 for n in names:
4026 if n in repo.tags():
4028 if n in repo.tags():
4027 raise util.Abort(_('tag \'%s\' already exists '
4029 raise util.Abort(_('tag \'%s\' already exists '
4028 '(use -f to force)') % n)
4030 '(use -f to force)') % n)
4029 if not opts.get('local'):
4031 if not opts.get('local'):
4030 p1, p2 = repo.dirstate.parents()
4032 p1, p2 = repo.dirstate.parents()
4031 if p2 != nullid:
4033 if p2 != nullid:
4032 raise util.Abort(_('uncommitted merge'))
4034 raise util.Abort(_('uncommitted merge'))
4033 bheads = repo.branchheads()
4035 bheads = repo.branchheads()
4034 if not opts.get('force') and bheads and p1 not in bheads:
4036 if not opts.get('force') and bheads and p1 not in bheads:
4035 raise util.Abort(_('not at a branch head (use -f to force)'))
4037 raise util.Abort(_('not at a branch head (use -f to force)'))
4036 r = cmdutil.revsingle(repo, rev_).node()
4038 r = cmdutil.revsingle(repo, rev_).node()
4037
4039
4038 if not message:
4040 if not message:
4039 # we don't translate commit messages
4041 # we don't translate commit messages
4040 message = ('Added tag %s for changeset %s' %
4042 message = ('Added tag %s for changeset %s' %
4041 (', '.join(names), short(r)))
4043 (', '.join(names), short(r)))
4042
4044
4043 date = opts.get('date')
4045 date = opts.get('date')
4044 if date:
4046 if date:
4045 date = util.parsedate(date)
4047 date = util.parsedate(date)
4046
4048
4047 if opts.get('edit'):
4049 if opts.get('edit'):
4048 message = ui.edit(message, ui.username())
4050 message = ui.edit(message, ui.username())
4049
4051
4050 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
4052 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
4051
4053
4052 def tags(ui, repo):
4054 def tags(ui, repo):
4053 """list repository tags
4055 """list repository tags
4054
4056
4055 This lists both regular and local tags. When the -v/--verbose
4057 This lists both regular and local tags. When the -v/--verbose
4056 switch is used, a third column "local" is printed for local tags.
4058 switch is used, a third column "local" is printed for local tags.
4057
4059
4058 Returns 0 on success.
4060 Returns 0 on success.
4059 """
4061 """
4060
4062
4061 hexfunc = ui.debugflag and hex or short
4063 hexfunc = ui.debugflag and hex or short
4062 tagtype = ""
4064 tagtype = ""
4063
4065
4064 for t, n in reversed(repo.tagslist()):
4066 for t, n in reversed(repo.tagslist()):
4065 if ui.quiet:
4067 if ui.quiet:
4066 ui.write("%s\n" % t)
4068 ui.write("%s\n" % t)
4067 continue
4069 continue
4068
4070
4069 hn = hexfunc(n)
4071 hn = hexfunc(n)
4070 r = "%5d:%s" % (repo.changelog.rev(n), hn)
4072 r = "%5d:%s" % (repo.changelog.rev(n), hn)
4071 spaces = " " * (30 - encoding.colwidth(t))
4073 spaces = " " * (30 - encoding.colwidth(t))
4072
4074
4073 if ui.verbose:
4075 if ui.verbose:
4074 if repo.tagtype(t) == 'local':
4076 if repo.tagtype(t) == 'local':
4075 tagtype = " local"
4077 tagtype = " local"
4076 else:
4078 else:
4077 tagtype = ""
4079 tagtype = ""
4078 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
4080 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
4079
4081
4080 def tip(ui, repo, **opts):
4082 def tip(ui, repo, **opts):
4081 """show the tip revision
4083 """show the tip revision
4082
4084
4083 The tip revision (usually just called the tip) is the changeset
4085 The tip revision (usually just called the tip) is the changeset
4084 most recently added to the repository (and therefore the most
4086 most recently added to the repository (and therefore the most
4085 recently changed head).
4087 recently changed head).
4086
4088
4087 If you have just made a commit, that commit will be the tip. If
4089 If you have just made a commit, that commit will be the tip. If
4088 you have just pulled changes from another repository, the tip of
4090 you have just pulled changes from another repository, the tip of
4089 that repository becomes the current tip. The "tip" tag is special
4091 that repository becomes the current tip. The "tip" tag is special
4090 and cannot be renamed or assigned to a different changeset.
4092 and cannot be renamed or assigned to a different changeset.
4091
4093
4092 Returns 0 on success.
4094 Returns 0 on success.
4093 """
4095 """
4094 displayer = cmdutil.show_changeset(ui, repo, opts)
4096 displayer = cmdutil.show_changeset(ui, repo, opts)
4095 displayer.show(repo[len(repo) - 1])
4097 displayer.show(repo[len(repo) - 1])
4096 displayer.close()
4098 displayer.close()
4097
4099
4098 def unbundle(ui, repo, fname1, *fnames, **opts):
4100 def unbundle(ui, repo, fname1, *fnames, **opts):
4099 """apply one or more changegroup files
4101 """apply one or more changegroup files
4100
4102
4101 Apply one or more compressed changegroup files generated by the
4103 Apply one or more compressed changegroup files generated by the
4102 bundle command.
4104 bundle command.
4103
4105
4104 Returns 0 on success, 1 if an update has unresolved files.
4106 Returns 0 on success, 1 if an update has unresolved files.
4105 """
4107 """
4106 fnames = (fname1,) + fnames
4108 fnames = (fname1,) + fnames
4107
4109
4108 lock = repo.lock()
4110 lock = repo.lock()
4109 wc = repo['.']
4111 wc = repo['.']
4110 try:
4112 try:
4111 for fname in fnames:
4113 for fname in fnames:
4112 f = url.open(ui, fname)
4114 f = url.open(ui, fname)
4113 gen = changegroup.readbundle(f, fname)
4115 gen = changegroup.readbundle(f, fname)
4114 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
4116 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
4115 lock=lock)
4117 lock=lock)
4116 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
4118 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
4117 finally:
4119 finally:
4118 lock.release()
4120 lock.release()
4119 return postincoming(ui, repo, modheads, opts.get('update'), None)
4121 return postincoming(ui, repo, modheads, opts.get('update'), None)
4120
4122
4121 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
4123 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
4122 """update working directory (or switch revisions)
4124 """update working directory (or switch revisions)
4123
4125
4124 Update the repository's working directory to the specified
4126 Update the repository's working directory to the specified
4125 changeset. If no changeset is specified, update to the tip of the
4127 changeset. If no changeset is specified, update to the tip of the
4126 current named branch.
4128 current named branch.
4127
4129
4128 If the changeset is not a descendant of the working directory's
4130 If the changeset is not a descendant of the working directory's
4129 parent, the update is aborted. With the -c/--check option, the
4131 parent, the update is aborted. With the -c/--check option, the
4130 working directory is checked for uncommitted changes; if none are
4132 working directory is checked for uncommitted changes; if none are
4131 found, the working directory is updated to the specified
4133 found, the working directory is updated to the specified
4132 changeset.
4134 changeset.
4133
4135
4134 The following rules apply when the working directory contains
4136 The following rules apply when the working directory contains
4135 uncommitted changes:
4137 uncommitted changes:
4136
4138
4137 1. If neither -c/--check nor -C/--clean is specified, and if
4139 1. If neither -c/--check nor -C/--clean is specified, and if
4138 the requested changeset is an ancestor or descendant of
4140 the requested changeset is an ancestor or descendant of
4139 the working directory's parent, the uncommitted changes
4141 the working directory's parent, the uncommitted changes
4140 are merged into the requested changeset and the merged
4142 are merged into the requested changeset and the merged
4141 result is left uncommitted. If the requested changeset is
4143 result is left uncommitted. If the requested changeset is
4142 not an ancestor or descendant (that is, it is on another
4144 not an ancestor or descendant (that is, it is on another
4143 branch), the update is aborted and the uncommitted changes
4145 branch), the update is aborted and the uncommitted changes
4144 are preserved.
4146 are preserved.
4145
4147
4146 2. With the -c/--check option, the update is aborted and the
4148 2. With the -c/--check option, the update is aborted and the
4147 uncommitted changes are preserved.
4149 uncommitted changes are preserved.
4148
4150
4149 3. With the -C/--clean option, uncommitted changes are discarded and
4151 3. With the -C/--clean option, uncommitted changes are discarded and
4150 the working directory is updated to the requested changeset.
4152 the working directory is updated to the requested changeset.
4151
4153
4152 Use null as the changeset to remove the working directory (like
4154 Use null as the changeset to remove the working directory (like
4153 :hg:`clone -U`).
4155 :hg:`clone -U`).
4154
4156
4155 If you want to update just one file to an older changeset, use
4157 If you want to update just one file to an older changeset, use
4156 :hg:`revert`.
4158 :hg:`revert`.
4157
4159
4158 See :hg:`help dates` for a list of formats valid for -d/--date.
4160 See :hg:`help dates` for a list of formats valid for -d/--date.
4159
4161
4160 Returns 0 on success, 1 if there are unresolved files.
4162 Returns 0 on success, 1 if there are unresolved files.
4161 """
4163 """
4162 if rev and node:
4164 if rev and node:
4163 raise util.Abort(_("please specify just one revision"))
4165 raise util.Abort(_("please specify just one revision"))
4164
4166
4165 if rev is None or rev == '':
4167 if rev is None or rev == '':
4166 rev = node
4168 rev = node
4167
4169
4168 # if we defined a bookmark, we have to remember the original bookmark name
4170 # if we defined a bookmark, we have to remember the original bookmark name
4169 brev = rev
4171 brev = rev
4170 rev = cmdutil.revsingle(repo, rev, rev).rev()
4172 rev = cmdutil.revsingle(repo, rev, rev).rev()
4171
4173
4172 if check and clean:
4174 if check and clean:
4173 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4175 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4174
4176
4175 if check:
4177 if check:
4176 # we could use dirty() but we can ignore merge and branch trivia
4178 # we could use dirty() but we can ignore merge and branch trivia
4177 c = repo[None]
4179 c = repo[None]
4178 if c.modified() or c.added() or c.removed():
4180 if c.modified() or c.added() or c.removed():
4179 raise util.Abort(_("uncommitted local changes"))
4181 raise util.Abort(_("uncommitted local changes"))
4180
4182
4181 if date:
4183 if date:
4182 if rev:
4184 if rev:
4183 raise util.Abort(_("you can't specify a revision and a date"))
4185 raise util.Abort(_("you can't specify a revision and a date"))
4184 rev = cmdutil.finddate(ui, repo, date)
4186 rev = cmdutil.finddate(ui, repo, date)
4185
4187
4186 if clean or check:
4188 if clean or check:
4187 ret = hg.clean(repo, rev)
4189 ret = hg.clean(repo, rev)
4188 else:
4190 else:
4189 ret = hg.update(repo, rev)
4191 ret = hg.update(repo, rev)
4190
4192
4191 if brev in repo._bookmarks:
4193 if brev in repo._bookmarks:
4192 bookmarks.setcurrent(repo, brev)
4194 bookmarks.setcurrent(repo, brev)
4193
4195
4194 return ret
4196 return ret
4195
4197
4196 def verify(ui, repo):
4198 def verify(ui, repo):
4197 """verify the integrity of the repository
4199 """verify the integrity of the repository
4198
4200
4199 Verify the integrity of the current repository.
4201 Verify the integrity of the current repository.
4200
4202
4201 This will perform an extensive check of the repository's
4203 This will perform an extensive check of the repository's
4202 integrity, validating the hashes and checksums of each entry in
4204 integrity, validating the hashes and checksums of each entry in
4203 the changelog, manifest, and tracked files, as well as the
4205 the changelog, manifest, and tracked files, as well as the
4204 integrity of their crosslinks and indices.
4206 integrity of their crosslinks and indices.
4205
4207
4206 Returns 0 on success, 1 if errors are encountered.
4208 Returns 0 on success, 1 if errors are encountered.
4207 """
4209 """
4208 return hg.verify(repo)
4210 return hg.verify(repo)
4209
4211
4210 def version_(ui):
4212 def version_(ui):
4211 """output version and copyright information"""
4213 """output version and copyright information"""
4212 ui.write(_("Mercurial Distributed SCM (version %s)\n")
4214 ui.write(_("Mercurial Distributed SCM (version %s)\n")
4213 % util.version())
4215 % util.version())
4214 ui.status(_(
4216 ui.status(_(
4215 "(see http://mercurial.selenic.com for more information)\n"
4217 "(see http://mercurial.selenic.com for more information)\n"
4216 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
4218 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
4217 "This is free software; see the source for copying conditions. "
4219 "This is free software; see the source for copying conditions. "
4218 "There is NO\nwarranty; "
4220 "There is NO\nwarranty; "
4219 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
4221 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
4220 ))
4222 ))
4221
4223
4222 # Command options and aliases are listed here, alphabetically
4224 # Command options and aliases are listed here, alphabetically
4223
4225
4224 globalopts = [
4226 globalopts = [
4225 ('R', 'repository', '',
4227 ('R', 'repository', '',
4226 _('repository root directory or name of overlay bundle file'),
4228 _('repository root directory or name of overlay bundle file'),
4227 _('REPO')),
4229 _('REPO')),
4228 ('', 'cwd', '',
4230 ('', 'cwd', '',
4229 _('change working directory'), _('DIR')),
4231 _('change working directory'), _('DIR')),
4230 ('y', 'noninteractive', None,
4232 ('y', 'noninteractive', None,
4231 _('do not prompt, assume \'yes\' for any required answers')),
4233 _('do not prompt, assume \'yes\' for any required answers')),
4232 ('q', 'quiet', None, _('suppress output')),
4234 ('q', 'quiet', None, _('suppress output')),
4233 ('v', 'verbose', None, _('enable additional output')),
4235 ('v', 'verbose', None, _('enable additional output')),
4234 ('', 'config', [],
4236 ('', 'config', [],
4235 _('set/override config option (use \'section.name=value\')'),
4237 _('set/override config option (use \'section.name=value\')'),
4236 _('CONFIG')),
4238 _('CONFIG')),
4237 ('', 'debug', None, _('enable debugging output')),
4239 ('', 'debug', None, _('enable debugging output')),
4238 ('', 'debugger', None, _('start debugger')),
4240 ('', 'debugger', None, _('start debugger')),
4239 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
4241 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
4240 _('ENCODE')),
4242 _('ENCODE')),
4241 ('', 'encodingmode', encoding.encodingmode,
4243 ('', 'encodingmode', encoding.encodingmode,
4242 _('set the charset encoding mode'), _('MODE')),
4244 _('set the charset encoding mode'), _('MODE')),
4243 ('', 'traceback', None, _('always print a traceback on exception')),
4245 ('', 'traceback', None, _('always print a traceback on exception')),
4244 ('', 'time', None, _('time how long the command takes')),
4246 ('', 'time', None, _('time how long the command takes')),
4245 ('', 'profile', None, _('print command execution profile')),
4247 ('', 'profile', None, _('print command execution profile')),
4246 ('', 'version', None, _('output version information and exit')),
4248 ('', 'version', None, _('output version information and exit')),
4247 ('h', 'help', None, _('display help and exit')),
4249 ('h', 'help', None, _('display help and exit')),
4248 ]
4250 ]
4249
4251
4250 dryrunopts = [('n', 'dry-run', None,
4252 dryrunopts = [('n', 'dry-run', None,
4251 _('do not perform actions, just print output'))]
4253 _('do not perform actions, just print output'))]
4252
4254
4253 remoteopts = [
4255 remoteopts = [
4254 ('e', 'ssh', '',
4256 ('e', 'ssh', '',
4255 _('specify ssh command to use'), _('CMD')),
4257 _('specify ssh command to use'), _('CMD')),
4256 ('', 'remotecmd', '',
4258 ('', 'remotecmd', '',
4257 _('specify hg command to run on the remote side'), _('CMD')),
4259 _('specify hg command to run on the remote side'), _('CMD')),
4258 ('', 'insecure', None,
4260 ('', 'insecure', None,
4259 _('do not verify server certificate (ignoring web.cacerts config)')),
4261 _('do not verify server certificate (ignoring web.cacerts config)')),
4260 ]
4262 ]
4261
4263
4262 walkopts = [
4264 walkopts = [
4263 ('I', 'include', [],
4265 ('I', 'include', [],
4264 _('include names matching the given patterns'), _('PATTERN')),
4266 _('include names matching the given patterns'), _('PATTERN')),
4265 ('X', 'exclude', [],
4267 ('X', 'exclude', [],
4266 _('exclude names matching the given patterns'), _('PATTERN')),
4268 _('exclude names matching the given patterns'), _('PATTERN')),
4267 ]
4269 ]
4268
4270
4269 commitopts = [
4271 commitopts = [
4270 ('m', 'message', '',
4272 ('m', 'message', '',
4271 _('use text as commit message'), _('TEXT')),
4273 _('use text as commit message'), _('TEXT')),
4272 ('l', 'logfile', '',
4274 ('l', 'logfile', '',
4273 _('read commit message from file'), _('FILE')),
4275 _('read commit message from file'), _('FILE')),
4274 ]
4276 ]
4275
4277
4276 commitopts2 = [
4278 commitopts2 = [
4277 ('d', 'date', '',
4279 ('d', 'date', '',
4278 _('record datecode as commit date'), _('DATE')),
4280 _('record datecode as commit date'), _('DATE')),
4279 ('u', 'user', '',
4281 ('u', 'user', '',
4280 _('record the specified user as committer'), _('USER')),
4282 _('record the specified user as committer'), _('USER')),
4281 ]
4283 ]
4282
4284
4283 templateopts = [
4285 templateopts = [
4284 ('', 'style', '',
4286 ('', 'style', '',
4285 _('display using template map file'), _('STYLE')),
4287 _('display using template map file'), _('STYLE')),
4286 ('', 'template', '',
4288 ('', 'template', '',
4287 _('display with template'), _('TEMPLATE')),
4289 _('display with template'), _('TEMPLATE')),
4288 ]
4290 ]
4289
4291
4290 logopts = [
4292 logopts = [
4291 ('p', 'patch', None, _('show patch')),
4293 ('p', 'patch', None, _('show patch')),
4292 ('g', 'git', None, _('use git extended diff format')),
4294 ('g', 'git', None, _('use git extended diff format')),
4293 ('l', 'limit', '',
4295 ('l', 'limit', '',
4294 _('limit number of changes displayed'), _('NUM')),
4296 _('limit number of changes displayed'), _('NUM')),
4295 ('M', 'no-merges', None, _('do not show merges')),
4297 ('M', 'no-merges', None, _('do not show merges')),
4296 ('', 'stat', None, _('output diffstat-style summary of changes')),
4298 ('', 'stat', None, _('output diffstat-style summary of changes')),
4297 ] + templateopts
4299 ] + templateopts
4298
4300
4299 diffopts = [
4301 diffopts = [
4300 ('a', 'text', None, _('treat all files as text')),
4302 ('a', 'text', None, _('treat all files as text')),
4301 ('g', 'git', None, _('use git extended diff format')),
4303 ('g', 'git', None, _('use git extended diff format')),
4302 ('', 'nodates', None, _('omit dates from diff headers'))
4304 ('', 'nodates', None, _('omit dates from diff headers'))
4303 ]
4305 ]
4304
4306
4305 diffopts2 = [
4307 diffopts2 = [
4306 ('p', 'show-function', None, _('show which function each change is in')),
4308 ('p', 'show-function', None, _('show which function each change is in')),
4307 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4309 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4308 ('w', 'ignore-all-space', None,
4310 ('w', 'ignore-all-space', None,
4309 _('ignore white space when comparing lines')),
4311 _('ignore white space when comparing lines')),
4310 ('b', 'ignore-space-change', None,
4312 ('b', 'ignore-space-change', None,
4311 _('ignore changes in the amount of white space')),
4313 _('ignore changes in the amount of white space')),
4312 ('B', 'ignore-blank-lines', None,
4314 ('B', 'ignore-blank-lines', None,
4313 _('ignore changes whose lines are all blank')),
4315 _('ignore changes whose lines are all blank')),
4314 ('U', 'unified', '',
4316 ('U', 'unified', '',
4315 _('number of lines of context to show'), _('NUM')),
4317 _('number of lines of context to show'), _('NUM')),
4316 ('', 'stat', None, _('output diffstat-style summary of changes')),
4318 ('', 'stat', None, _('output diffstat-style summary of changes')),
4317 ]
4319 ]
4318
4320
4319 similarityopts = [
4321 similarityopts = [
4320 ('s', 'similarity', '',
4322 ('s', 'similarity', '',
4321 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4323 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4322 ]
4324 ]
4323
4325
4324 subrepoopts = [
4326 subrepoopts = [
4325 ('S', 'subrepos', None,
4327 ('S', 'subrepos', None,
4326 _('recurse into subrepositories'))
4328 _('recurse into subrepositories'))
4327 ]
4329 ]
4328
4330
4329 table = {
4331 table = {
4330 "^add": (add, walkopts + subrepoopts + dryrunopts,
4332 "^add": (add, walkopts + subrepoopts + dryrunopts,
4331 _('[OPTION]... [FILE]...')),
4333 _('[OPTION]... [FILE]...')),
4332 "addremove":
4334 "addremove":
4333 (addremove, similarityopts + walkopts + dryrunopts,
4335 (addremove, similarityopts + walkopts + dryrunopts,
4334 _('[OPTION]... [FILE]...')),
4336 _('[OPTION]... [FILE]...')),
4335 "^annotate|blame":
4337 "^annotate|blame":
4336 (annotate,
4338 (annotate,
4337 [('r', 'rev', '',
4339 [('r', 'rev', '',
4338 _('annotate the specified revision'), _('REV')),
4340 _('annotate the specified revision'), _('REV')),
4339 ('', 'follow', None,
4341 ('', 'follow', None,
4340 _('follow copies/renames and list the filename (DEPRECATED)')),
4342 _('follow copies/renames and list the filename (DEPRECATED)')),
4341 ('', 'no-follow', None, _("don't follow copies and renames")),
4343 ('', 'no-follow', None, _("don't follow copies and renames")),
4342 ('a', 'text', None, _('treat all files as text')),
4344 ('a', 'text', None, _('treat all files as text')),
4343 ('u', 'user', None, _('list the author (long with -v)')),
4345 ('u', 'user', None, _('list the author (long with -v)')),
4344 ('f', 'file', None, _('list the filename')),
4346 ('f', 'file', None, _('list the filename')),
4345 ('d', 'date', None, _('list the date (short with -q)')),
4347 ('d', 'date', None, _('list the date (short with -q)')),
4346 ('n', 'number', None, _('list the revision number (default)')),
4348 ('n', 'number', None, _('list the revision number (default)')),
4347 ('c', 'changeset', None, _('list the changeset')),
4349 ('c', 'changeset', None, _('list the changeset')),
4348 ('l', 'line-number', None,
4350 ('l', 'line-number', None,
4349 _('show line number at the first appearance'))
4351 _('show line number at the first appearance'))
4350 ] + walkopts,
4352 ] + walkopts,
4351 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4353 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4352 "archive":
4354 "archive":
4353 (archive,
4355 (archive,
4354 [('', 'no-decode', None, _('do not pass files through decoders')),
4356 [('', 'no-decode', None, _('do not pass files through decoders')),
4355 ('p', 'prefix', '',
4357 ('p', 'prefix', '',
4356 _('directory prefix for files in archive'), _('PREFIX')),
4358 _('directory prefix for files in archive'), _('PREFIX')),
4357 ('r', 'rev', '',
4359 ('r', 'rev', '',
4358 _('revision to distribute'), _('REV')),
4360 _('revision to distribute'), _('REV')),
4359 ('t', 'type', '',
4361 ('t', 'type', '',
4360 _('type of distribution to create'), _('TYPE')),
4362 _('type of distribution to create'), _('TYPE')),
4361 ] + subrepoopts + walkopts,
4363 ] + subrepoopts + walkopts,
4362 _('[OPTION]... DEST')),
4364 _('[OPTION]... DEST')),
4363 "backout":
4365 "backout":
4364 (backout,
4366 (backout,
4365 [('', 'merge', None,
4367 [('', 'merge', None,
4366 _('merge with old dirstate parent after backout')),
4368 _('merge with old dirstate parent after backout')),
4367 ('', 'parent', '',
4369 ('', 'parent', '',
4368 _('parent to choose when backing out merge'), _('REV')),
4370 _('parent to choose when backing out merge'), _('REV')),
4369 ('t', 'tool', '',
4371 ('t', 'tool', '',
4370 _('specify merge tool')),
4372 _('specify merge tool')),
4371 ('r', 'rev', '',
4373 ('r', 'rev', '',
4372 _('revision to backout'), _('REV')),
4374 _('revision to backout'), _('REV')),
4373 ] + walkopts + commitopts + commitopts2,
4375 ] + walkopts + commitopts + commitopts2,
4374 _('[OPTION]... [-r] REV')),
4376 _('[OPTION]... [-r] REV')),
4375 "bisect":
4377 "bisect":
4376 (bisect,
4378 (bisect,
4377 [('r', 'reset', False, _('reset bisect state')),
4379 [('r', 'reset', False, _('reset bisect state')),
4378 ('g', 'good', False, _('mark changeset good')),
4380 ('g', 'good', False, _('mark changeset good')),
4379 ('b', 'bad', False, _('mark changeset bad')),
4381 ('b', 'bad', False, _('mark changeset bad')),
4380 ('s', 'skip', False, _('skip testing changeset')),
4382 ('s', 'skip', False, _('skip testing changeset')),
4381 ('e', 'extend', False, _('extend the bisect range')),
4383 ('e', 'extend', False, _('extend the bisect range')),
4382 ('c', 'command', '',
4384 ('c', 'command', '',
4383 _('use command to check changeset state'), _('CMD')),
4385 _('use command to check changeset state'), _('CMD')),
4384 ('U', 'noupdate', False, _('do not update to target'))],
4386 ('U', 'noupdate', False, _('do not update to target'))],
4385 _("[-gbsr] [-U] [-c CMD] [REV]")),
4387 _("[-gbsr] [-U] [-c CMD] [REV]")),
4386 "bookmarks":
4388 "bookmarks":
4387 (bookmark,
4389 (bookmark,
4388 [('f', 'force', False, _('force')),
4390 [('f', 'force', False, _('force')),
4389 ('r', 'rev', '', _('revision'), _('REV')),
4391 ('r', 'rev', '', _('revision'), _('REV')),
4390 ('d', 'delete', False, _('delete a given bookmark')),
4392 ('d', 'delete', False, _('delete a given bookmark')),
4391 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
4393 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
4392 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
4394 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
4393 "branch":
4395 "branch":
4394 (branch,
4396 (branch,
4395 [('f', 'force', None,
4397 [('f', 'force', None,
4396 _('set branch name even if it shadows an existing branch')),
4398 _('set branch name even if it shadows an existing branch')),
4397 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4399 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4398 _('[-fC] [NAME]')),
4400 _('[-fC] [NAME]')),
4399 "branches":
4401 "branches":
4400 (branches,
4402 (branches,
4401 [('a', 'active', False,
4403 [('a', 'active', False,
4402 _('show only branches that have unmerged heads')),
4404 _('show only branches that have unmerged heads')),
4403 ('c', 'closed', False,
4405 ('c', 'closed', False,
4404 _('show normal and closed branches'))],
4406 _('show normal and closed branches'))],
4405 _('[-ac]')),
4407 _('[-ac]')),
4406 "bundle":
4408 "bundle":
4407 (bundle,
4409 (bundle,
4408 [('f', 'force', None,
4410 [('f', 'force', None,
4409 _('run even when the destination is unrelated')),
4411 _('run even when the destination is unrelated')),
4410 ('r', 'rev', [],
4412 ('r', 'rev', [],
4411 _('a changeset intended to be added to the destination'),
4413 _('a changeset intended to be added to the destination'),
4412 _('REV')),
4414 _('REV')),
4413 ('b', 'branch', [],
4415 ('b', 'branch', [],
4414 _('a specific branch you would like to bundle'),
4416 _('a specific branch you would like to bundle'),
4415 _('BRANCH')),
4417 _('BRANCH')),
4416 ('', 'base', [],
4418 ('', 'base', [],
4417 _('a base changeset assumed to be available at the destination'),
4419 _('a base changeset assumed to be available at the destination'),
4418 _('REV')),
4420 _('REV')),
4419 ('a', 'all', None, _('bundle all changesets in the repository')),
4421 ('a', 'all', None, _('bundle all changesets in the repository')),
4420 ('t', 'type', 'bzip2',
4422 ('t', 'type', 'bzip2',
4421 _('bundle compression type to use'), _('TYPE')),
4423 _('bundle compression type to use'), _('TYPE')),
4422 ] + remoteopts,
4424 ] + remoteopts,
4423 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4425 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4424 "cat":
4426 "cat":
4425 (cat,
4427 (cat,
4426 [('o', 'output', '',
4428 [('o', 'output', '',
4427 _('print output to file with formatted name'), _('FORMAT')),
4429 _('print output to file with formatted name'), _('FORMAT')),
4428 ('r', 'rev', '',
4430 ('r', 'rev', '',
4429 _('print the given revision'), _('REV')),
4431 _('print the given revision'), _('REV')),
4430 ('', 'decode', None, _('apply any matching decode filter')),
4432 ('', 'decode', None, _('apply any matching decode filter')),
4431 ] + walkopts,
4433 ] + walkopts,
4432 _('[OPTION]... FILE...')),
4434 _('[OPTION]... FILE...')),
4433 "^clone":
4435 "^clone":
4434 (clone,
4436 (clone,
4435 [('U', 'noupdate', None,
4437 [('U', 'noupdate', None,
4436 _('the clone will include an empty working copy (only a repository)')),
4438 _('the clone will include an empty working copy (only a repository)')),
4437 ('u', 'updaterev', '',
4439 ('u', 'updaterev', '',
4438 _('revision, tag or branch to check out'), _('REV')),
4440 _('revision, tag or branch to check out'), _('REV')),
4439 ('r', 'rev', [],
4441 ('r', 'rev', [],
4440 _('include the specified changeset'), _('REV')),
4442 _('include the specified changeset'), _('REV')),
4441 ('b', 'branch', [],
4443 ('b', 'branch', [],
4442 _('clone only the specified branch'), _('BRANCH')),
4444 _('clone only the specified branch'), _('BRANCH')),
4443 ('', 'pull', None, _('use pull protocol to copy metadata')),
4445 ('', 'pull', None, _('use pull protocol to copy metadata')),
4444 ('', 'uncompressed', None,
4446 ('', 'uncompressed', None,
4445 _('use uncompressed transfer (fast over LAN)')),
4447 _('use uncompressed transfer (fast over LAN)')),
4446 ] + remoteopts,
4448 ] + remoteopts,
4447 _('[OPTION]... SOURCE [DEST]')),
4449 _('[OPTION]... SOURCE [DEST]')),
4448 "^commit|ci":
4450 "^commit|ci":
4449 (commit,
4451 (commit,
4450 [('A', 'addremove', None,
4452 [('A', 'addremove', None,
4451 _('mark new/missing files as added/removed before committing')),
4453 _('mark new/missing files as added/removed before committing')),
4452 ('', 'close-branch', None,
4454 ('', 'close-branch', None,
4453 _('mark a branch as closed, hiding it from the branch list')),
4455 _('mark a branch as closed, hiding it from the branch list')),
4454 ] + walkopts + commitopts + commitopts2,
4456 ] + walkopts + commitopts + commitopts2,
4455 _('[OPTION]... [FILE]...')),
4457 _('[OPTION]... [FILE]...')),
4456 "copy|cp":
4458 "copy|cp":
4457 (copy,
4459 (copy,
4458 [('A', 'after', None, _('record a copy that has already occurred')),
4460 [('A', 'after', None, _('record a copy that has already occurred')),
4459 ('f', 'force', None,
4461 ('f', 'force', None,
4460 _('forcibly copy over an existing managed file')),
4462 _('forcibly copy over an existing managed file')),
4461 ] + walkopts + dryrunopts,
4463 ] + walkopts + dryrunopts,
4462 _('[OPTION]... [SOURCE]... DEST')),
4464 _('[OPTION]... [SOURCE]... DEST')),
4463 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4465 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4464 "debugbuilddag":
4466 "debugbuilddag":
4465 (debugbuilddag,
4467 (debugbuilddag,
4466 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4468 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4467 ('a', 'appended-file', None, _('add single file all revs append to')),
4469 ('a', 'appended-file', None, _('add single file all revs append to')),
4468 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4470 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4469 ('n', 'new-file', None, _('add new file at each rev')),
4471 ('n', 'new-file', None, _('add new file at each rev')),
4470 ],
4472 ],
4471 _('[OPTION]... TEXT')),
4473 _('[OPTION]... TEXT')),
4472 "debugbundle":
4474 "debugbundle":
4473 (debugbundle,
4475 (debugbundle,
4474 [('a', 'all', None, _('show all details')),
4476 [('a', 'all', None, _('show all details')),
4475 ],
4477 ],
4476 _('FILE')),
4478 _('FILE')),
4477 "debugcheckstate": (debugcheckstate, [], ''),
4479 "debugcheckstate": (debugcheckstate, [], ''),
4478 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4480 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4479 "debugcomplete":
4481 "debugcomplete":
4480 (debugcomplete,
4482 (debugcomplete,
4481 [('o', 'options', None, _('show the command options'))],
4483 [('o', 'options', None, _('show the command options'))],
4482 _('[-o] CMD')),
4484 _('[-o] CMD')),
4483 "debugdag":
4485 "debugdag":
4484 (debugdag,
4486 (debugdag,
4485 [('t', 'tags', None, _('use tags as labels')),
4487 [('t', 'tags', None, _('use tags as labels')),
4486 ('b', 'branches', None, _('annotate with branch names')),
4488 ('b', 'branches', None, _('annotate with branch names')),
4487 ('', 'dots', None, _('use dots for runs')),
4489 ('', 'dots', None, _('use dots for runs')),
4488 ('s', 'spaces', None, _('separate elements by spaces')),
4490 ('s', 'spaces', None, _('separate elements by spaces')),
4489 ],
4491 ],
4490 _('[OPTION]... [FILE [REV]...]')),
4492 _('[OPTION]... [FILE [REV]...]')),
4491 "debugdate":
4493 "debugdate":
4492 (debugdate,
4494 (debugdate,
4493 [('e', 'extended', None, _('try extended date formats'))],
4495 [('e', 'extended', None, _('try extended date formats'))],
4494 _('[-e] DATE [RANGE]')),
4496 _('[-e] DATE [RANGE]')),
4495 "debugdata": (debugdata, [], _('FILE REV')),
4497 "debugdata": (debugdata, [], _('FILE REV')),
4496 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4498 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4497 "debuggetbundle":
4499 "debuggetbundle":
4498 (debuggetbundle,
4500 (debuggetbundle,
4499 [('H', 'head', [], _('id of head node'), _('ID')),
4501 [('H', 'head', [], _('id of head node'), _('ID')),
4500 ('C', 'common', [], _('id of common node'), _('ID')),
4502 ('C', 'common', [], _('id of common node'), _('ID')),
4501 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
4503 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
4502 ],
4504 ],
4503 _('REPO FILE [-H|-C ID]...')),
4505 _('REPO FILE [-H|-C ID]...')),
4504 "debugignore": (debugignore, [], ''),
4506 "debugignore": (debugignore, [], ''),
4505 "debugindex": (debugindex,
4507 "debugindex": (debugindex,
4506 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4508 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4507 _('FILE')),
4509 _('FILE')),
4508 "debugindexdot": (debugindexdot, [], _('FILE')),
4510 "debugindexdot": (debugindexdot, [], _('FILE')),
4509 "debuginstall": (debuginstall, [], ''),
4511 "debuginstall": (debuginstall, [], ''),
4510 "debugknown": (debugknown, [], _('REPO ID...')),
4512 "debugknown": (debugknown, [], _('REPO ID...')),
4511 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4513 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4512 "debugrebuildstate":
4514 "debugrebuildstate":
4513 (debugrebuildstate,
4515 (debugrebuildstate,
4514 [('r', 'rev', '',
4516 [('r', 'rev', '',
4515 _('revision to rebuild to'), _('REV'))],
4517 _('revision to rebuild to'), _('REV'))],
4516 _('[-r REV] [REV]')),
4518 _('[-r REV] [REV]')),
4517 "debugrename":
4519 "debugrename":
4518 (debugrename,
4520 (debugrename,
4519 [('r', 'rev', '',
4521 [('r', 'rev', '',
4520 _('revision to debug'), _('REV'))],
4522 _('revision to debug'), _('REV'))],
4521 _('[-r REV] FILE')),
4523 _('[-r REV] FILE')),
4522 "debugrevspec":
4524 "debugrevspec":
4523 (debugrevspec, [], ('REVSPEC')),
4525 (debugrevspec, [], ('REVSPEC')),
4524 "debugsetparents":
4526 "debugsetparents":
4525 (debugsetparents, [], _('REV1 [REV2]')),
4527 (debugsetparents, [], _('REV1 [REV2]')),
4526 "debugstate":
4528 "debugstate":
4527 (debugstate,
4529 (debugstate,
4528 [('', 'nodates', None, _('do not display the saved mtime')),
4530 [('', 'nodates', None, _('do not display the saved mtime')),
4529 ('', 'datesort', None, _('sort by saved mtime'))],
4531 ('', 'datesort', None, _('sort by saved mtime'))],
4530 _('[OPTION]...')),
4532 _('[OPTION]...')),
4531 "debugsub":
4533 "debugsub":
4532 (debugsub,
4534 (debugsub,
4533 [('r', 'rev', '',
4535 [('r', 'rev', '',
4534 _('revision to check'), _('REV'))],
4536 _('revision to check'), _('REV'))],
4535 _('[-r REV] [REV]')),
4537 _('[-r REV] [REV]')),
4536 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4538 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4537 "debugwireargs":
4539 "debugwireargs":
4538 (debugwireargs,
4540 (debugwireargs,
4539 [('', 'three', '', 'three'),
4541 [('', 'three', '', 'three'),
4540 ('', 'four', '', 'four'),
4542 ('', 'four', '', 'four'),
4541 ] + remoteopts,
4543 ] + remoteopts,
4542 _('REPO [OPTIONS]... [ONE [TWO]]')),
4544 _('REPO [OPTIONS]... [ONE [TWO]]')),
4543 "^diff":
4545 "^diff":
4544 (diff,
4546 (diff,
4545 [('r', 'rev', [],
4547 [('r', 'rev', [],
4546 _('revision'), _('REV')),
4548 _('revision'), _('REV')),
4547 ('c', 'change', '',
4549 ('c', 'change', '',
4548 _('change made by revision'), _('REV'))
4550 _('change made by revision'), _('REV'))
4549 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4551 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4550 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4552 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4551 "^export":
4553 "^export":
4552 (export,
4554 (export,
4553 [('o', 'output', '',
4555 [('o', 'output', '',
4554 _('print output to file with formatted name'), _('FORMAT')),
4556 _('print output to file with formatted name'), _('FORMAT')),
4555 ('', 'switch-parent', None, _('diff against the second parent')),
4557 ('', 'switch-parent', None, _('diff against the second parent')),
4556 ('r', 'rev', [],
4558 ('r', 'rev', [],
4557 _('revisions to export'), _('REV')),
4559 _('revisions to export'), _('REV')),
4558 ] + diffopts,
4560 ] + diffopts,
4559 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4561 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4560 "^forget":
4562 "^forget":
4561 (forget,
4563 (forget,
4562 [] + walkopts,
4564 [] + walkopts,
4563 _('[OPTION]... FILE...')),
4565 _('[OPTION]... FILE...')),
4564 "grep":
4566 "grep":
4565 (grep,
4567 (grep,
4566 [('0', 'print0', None, _('end fields with NUL')),
4568 [('0', 'print0', None, _('end fields with NUL')),
4567 ('', 'all', None, _('print all revisions that match')),
4569 ('', 'all', None, _('print all revisions that match')),
4568 ('f', 'follow', None,
4570 ('f', 'follow', None,
4569 _('follow changeset history,'
4571 _('follow changeset history,'
4570 ' or file history across copies and renames')),
4572 ' or file history across copies and renames')),
4571 ('i', 'ignore-case', None, _('ignore case when matching')),
4573 ('i', 'ignore-case', None, _('ignore case when matching')),
4572 ('l', 'files-with-matches', None,
4574 ('l', 'files-with-matches', None,
4573 _('print only filenames and revisions that match')),
4575 _('print only filenames and revisions that match')),
4574 ('n', 'line-number', None, _('print matching line numbers')),
4576 ('n', 'line-number', None, _('print matching line numbers')),
4575 ('r', 'rev', [],
4577 ('r', 'rev', [],
4576 _('only search files changed within revision range'), _('REV')),
4578 _('only search files changed within revision range'), _('REV')),
4577 ('u', 'user', None, _('list the author (long with -v)')),
4579 ('u', 'user', None, _('list the author (long with -v)')),
4578 ('d', 'date', None, _('list the date (short with -q)')),
4580 ('d', 'date', None, _('list the date (short with -q)')),
4579 ] + walkopts,
4581 ] + walkopts,
4580 _('[OPTION]... PATTERN [FILE]...')),
4582 _('[OPTION]... PATTERN [FILE]...')),
4581 "heads":
4583 "heads":
4582 (heads,
4584 (heads,
4583 [('r', 'rev', '',
4585 [('r', 'rev', '',
4584 _('show only heads which are descendants of STARTREV'),
4586 _('show only heads which are descendants of STARTREV'),
4585 _('STARTREV')),
4587 _('STARTREV')),
4586 ('t', 'topo', False, _('show topological heads only')),
4588 ('t', 'topo', False, _('show topological heads only')),
4587 ('a', 'active', False,
4589 ('a', 'active', False,
4588 _('show active branchheads only (DEPRECATED)')),
4590 _('show active branchheads only (DEPRECATED)')),
4589 ('c', 'closed', False,
4591 ('c', 'closed', False,
4590 _('show normal and closed branch heads')),
4592 _('show normal and closed branch heads')),
4591 ] + templateopts,
4593 ] + templateopts,
4592 _('[-ac] [-r STARTREV] [REV]...')),
4594 _('[-ac] [-r STARTREV] [REV]...')),
4593 "help": (help_, [], _('[TOPIC]')),
4595 "help": (help_, [], _('[TOPIC]')),
4594 "identify|id":
4596 "identify|id":
4595 (identify,
4597 (identify,
4596 [('r', 'rev', '',
4598 [('r', 'rev', '',
4597 _('identify the specified revision'), _('REV')),
4599 _('identify the specified revision'), _('REV')),
4598 ('n', 'num', None, _('show local revision number')),
4600 ('n', 'num', None, _('show local revision number')),
4599 ('i', 'id', None, _('show global revision id')),
4601 ('i', 'id', None, _('show global revision id')),
4600 ('b', 'branch', None, _('show branch')),
4602 ('b', 'branch', None, _('show branch')),
4601 ('t', 'tags', None, _('show tags')),
4603 ('t', 'tags', None, _('show tags')),
4602 ('B', 'bookmarks', None, _('show bookmarks'))],
4604 ('B', 'bookmarks', None, _('show bookmarks'))],
4603 _('[-nibtB] [-r REV] [SOURCE]')),
4605 _('[-nibtB] [-r REV] [SOURCE]')),
4604 "import|patch":
4606 "import|patch":
4605 (import_,
4607 (import_,
4606 [('p', 'strip', 1,
4608 [('p', 'strip', 1,
4607 _('directory strip option for patch. This has the same '
4609 _('directory strip option for patch. This has the same '
4608 'meaning as the corresponding patch option'),
4610 'meaning as the corresponding patch option'),
4609 _('NUM')),
4611 _('NUM')),
4610 ('b', 'base', '',
4612 ('b', 'base', '',
4611 _('base path'), _('PATH')),
4613 _('base path'), _('PATH')),
4612 ('f', 'force', None,
4614 ('f', 'force', None,
4613 _('skip check for outstanding uncommitted changes')),
4615 _('skip check for outstanding uncommitted changes')),
4614 ('', 'no-commit', None,
4616 ('', 'no-commit', None,
4615 _("don't commit, just update the working directory")),
4617 _("don't commit, just update the working directory")),
4616 ('', 'exact', None,
4618 ('', 'exact', None,
4617 _('apply patch to the nodes from which it was generated')),
4619 _('apply patch to the nodes from which it was generated')),
4618 ('', 'import-branch', None,
4620 ('', 'import-branch', None,
4619 _('use any branch information in patch (implied by --exact)'))] +
4621 _('use any branch information in patch (implied by --exact)'))] +
4620 commitopts + commitopts2 + similarityopts,
4622 commitopts + commitopts2 + similarityopts,
4621 _('[OPTION]... PATCH...')),
4623 _('[OPTION]... PATCH...')),
4622 "incoming|in":
4624 "incoming|in":
4623 (incoming,
4625 (incoming,
4624 [('f', 'force', None,
4626 [('f', 'force', None,
4625 _('run even if remote repository is unrelated')),
4627 _('run even if remote repository is unrelated')),
4626 ('n', 'newest-first', None, _('show newest record first')),
4628 ('n', 'newest-first', None, _('show newest record first')),
4627 ('', 'bundle', '',
4629 ('', 'bundle', '',
4628 _('file to store the bundles into'), _('FILE')),
4630 _('file to store the bundles into'), _('FILE')),
4629 ('r', 'rev', [],
4631 ('r', 'rev', [],
4630 _('a remote changeset intended to be added'), _('REV')),
4632 _('a remote changeset intended to be added'), _('REV')),
4631 ('B', 'bookmarks', False, _("compare bookmarks")),
4633 ('B', 'bookmarks', False, _("compare bookmarks")),
4632 ('b', 'branch', [],
4634 ('b', 'branch', [],
4633 _('a specific branch you would like to pull'), _('BRANCH')),
4635 _('a specific branch you would like to pull'), _('BRANCH')),
4634 ] + logopts + remoteopts + subrepoopts,
4636 ] + logopts + remoteopts + subrepoopts,
4635 _('[-p] [-n] [-M] [-f] [-r REV]...'
4637 _('[-p] [-n] [-M] [-f] [-r REV]...'
4636 ' [--bundle FILENAME] [SOURCE]')),
4638 ' [--bundle FILENAME] [SOURCE]')),
4637 "^init":
4639 "^init":
4638 (init,
4640 (init,
4639 remoteopts,
4641 remoteopts,
4640 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4642 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4641 "locate":
4643 "locate":
4642 (locate,
4644 (locate,
4643 [('r', 'rev', '',
4645 [('r', 'rev', '',
4644 _('search the repository as it is in REV'), _('REV')),
4646 _('search the repository as it is in REV'), _('REV')),
4645 ('0', 'print0', None,
4647 ('0', 'print0', None,
4646 _('end filenames with NUL, for use with xargs')),
4648 _('end filenames with NUL, for use with xargs')),
4647 ('f', 'fullpath', None,
4649 ('f', 'fullpath', None,
4648 _('print complete paths from the filesystem root')),
4650 _('print complete paths from the filesystem root')),
4649 ] + walkopts,
4651 ] + walkopts,
4650 _('[OPTION]... [PATTERN]...')),
4652 _('[OPTION]... [PATTERN]...')),
4651 "^log|history":
4653 "^log|history":
4652 (log,
4654 (log,
4653 [('f', 'follow', None,
4655 [('f', 'follow', None,
4654 _('follow changeset history,'
4656 _('follow changeset history,'
4655 ' or file history across copies and renames')),
4657 ' or file history across copies and renames')),
4656 ('', 'follow-first', None,
4658 ('', 'follow-first', None,
4657 _('only follow the first parent of merge changesets')),
4659 _('only follow the first parent of merge changesets')),
4658 ('d', 'date', '',
4660 ('d', 'date', '',
4659 _('show revisions matching date spec'), _('DATE')),
4661 _('show revisions matching date spec'), _('DATE')),
4660 ('C', 'copies', None, _('show copied files')),
4662 ('C', 'copies', None, _('show copied files')),
4661 ('k', 'keyword', [],
4663 ('k', 'keyword', [],
4662 _('do case-insensitive search for a given text'), _('TEXT')),
4664 _('do case-insensitive search for a given text'), _('TEXT')),
4663 ('r', 'rev', [],
4665 ('r', 'rev', [],
4664 _('show the specified revision or range'), _('REV')),
4666 _('show the specified revision or range'), _('REV')),
4665 ('', 'removed', None, _('include revisions where files were removed')),
4667 ('', 'removed', None, _('include revisions where files were removed')),
4666 ('m', 'only-merges', None, _('show only merges')),
4668 ('m', 'only-merges', None, _('show only merges')),
4667 ('u', 'user', [],
4669 ('u', 'user', [],
4668 _('revisions committed by user'), _('USER')),
4670 _('revisions committed by user'), _('USER')),
4669 ('', 'only-branch', [],
4671 ('', 'only-branch', [],
4670 _('show only changesets within the given named branch (DEPRECATED)'),
4672 _('show only changesets within the given named branch (DEPRECATED)'),
4671 _('BRANCH')),
4673 _('BRANCH')),
4672 ('b', 'branch', [],
4674 ('b', 'branch', [],
4673 _('show changesets within the given named branch'), _('BRANCH')),
4675 _('show changesets within the given named branch'), _('BRANCH')),
4674 ('P', 'prune', [],
4676 ('P', 'prune', [],
4675 _('do not display revision or any of its ancestors'), _('REV')),
4677 _('do not display revision or any of its ancestors'), _('REV')),
4676 ] + logopts + walkopts,
4678 ] + logopts + walkopts,
4677 _('[OPTION]... [FILE]')),
4679 _('[OPTION]... [FILE]')),
4678 "manifest":
4680 "manifest":
4679 (manifest,
4681 (manifest,
4680 [('r', 'rev', '',
4682 [('r', 'rev', '',
4681 _('revision to display'), _('REV'))],
4683 _('revision to display'), _('REV'))],
4682 _('[-r REV]')),
4684 _('[-r REV]')),
4683 "^merge":
4685 "^merge":
4684 (merge,
4686 (merge,
4685 [('f', 'force', None, _('force a merge with outstanding changes')),
4687 [('f', 'force', None, _('force a merge with outstanding changes')),
4686 ('t', 'tool', '', _('specify merge tool')),
4688 ('t', 'tool', '', _('specify merge tool')),
4687 ('r', 'rev', '',
4689 ('r', 'rev', '',
4688 _('revision to merge'), _('REV')),
4690 _('revision to merge'), _('REV')),
4689 ('P', 'preview', None,
4691 ('P', 'preview', None,
4690 _('review revisions to merge (no merge is performed)'))],
4692 _('review revisions to merge (no merge is performed)'))],
4691 _('[-P] [-f] [[-r] REV]')),
4693 _('[-P] [-f] [[-r] REV]')),
4692 "outgoing|out":
4694 "outgoing|out":
4693 (outgoing,
4695 (outgoing,
4694 [('f', 'force', None,
4696 [('f', 'force', None,
4695 _('run even when the destination is unrelated')),
4697 _('run even when the destination is unrelated')),
4696 ('r', 'rev', [],
4698 ('r', 'rev', [],
4697 _('a changeset intended to be included in the destination'),
4699 _('a changeset intended to be included in the destination'),
4698 _('REV')),
4700 _('REV')),
4699 ('n', 'newest-first', None, _('show newest record first')),
4701 ('n', 'newest-first', None, _('show newest record first')),
4700 ('B', 'bookmarks', False, _("compare bookmarks")),
4702 ('B', 'bookmarks', False, _("compare bookmarks")),
4701 ('b', 'branch', [],
4703 ('b', 'branch', [],
4702 _('a specific branch you would like to push'), _('BRANCH')),
4704 _('a specific branch you would like to push'), _('BRANCH')),
4703 ] + logopts + remoteopts + subrepoopts,
4705 ] + logopts + remoteopts + subrepoopts,
4704 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4706 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4705 "parents":
4707 "parents":
4706 (parents,
4708 (parents,
4707 [('r', 'rev', '',
4709 [('r', 'rev', '',
4708 _('show parents of the specified revision'), _('REV')),
4710 _('show parents of the specified revision'), _('REV')),
4709 ] + templateopts,
4711 ] + templateopts,
4710 _('[-r REV] [FILE]')),
4712 _('[-r REV] [FILE]')),
4711 "paths": (paths, [], _('[NAME]')),
4713 "paths": (paths, [], _('[NAME]')),
4712 "^pull":
4714 "^pull":
4713 (pull,
4715 (pull,
4714 [('u', 'update', None,
4716 [('u', 'update', None,
4715 _('update to new branch head if changesets were pulled')),
4717 _('update to new branch head if changesets were pulled')),
4716 ('f', 'force', None,
4718 ('f', 'force', None,
4717 _('run even when remote repository is unrelated')),
4719 _('run even when remote repository is unrelated')),
4718 ('r', 'rev', [],
4720 ('r', 'rev', [],
4719 _('a remote changeset intended to be added'), _('REV')),
4721 _('a remote changeset intended to be added'), _('REV')),
4720 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4722 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4721 ('b', 'branch', [],
4723 ('b', 'branch', [],
4722 _('a specific branch you would like to pull'), _('BRANCH')),
4724 _('a specific branch you would like to pull'), _('BRANCH')),
4723 ] + remoteopts,
4725 ] + remoteopts,
4724 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4726 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4725 "^push":
4727 "^push":
4726 (push,
4728 (push,
4727 [('f', 'force', None, _('force push')),
4729 [('f', 'force', None, _('force push')),
4728 ('r', 'rev', [],
4730 ('r', 'rev', [],
4729 _('a changeset intended to be included in the destination'),
4731 _('a changeset intended to be included in the destination'),
4730 _('REV')),
4732 _('REV')),
4731 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4733 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4732 ('b', 'branch', [],
4734 ('b', 'branch', [],
4733 _('a specific branch you would like to push'), _('BRANCH')),
4735 _('a specific branch you would like to push'), _('BRANCH')),
4734 ('', 'new-branch', False, _('allow pushing a new branch')),
4736 ('', 'new-branch', False, _('allow pushing a new branch')),
4735 ] + remoteopts,
4737 ] + remoteopts,
4736 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4738 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4737 "recover": (recover, []),
4739 "recover": (recover, []),
4738 "^remove|rm":
4740 "^remove|rm":
4739 (remove,
4741 (remove,
4740 [('A', 'after', None, _('record delete for missing files')),
4742 [('A', 'after', None, _('record delete for missing files')),
4741 ('f', 'force', None,
4743 ('f', 'force', None,
4742 _('remove (and delete) file even if added or modified')),
4744 _('remove (and delete) file even if added or modified')),
4743 ] + walkopts,
4745 ] + walkopts,
4744 _('[OPTION]... FILE...')),
4746 _('[OPTION]... FILE...')),
4745 "rename|move|mv":
4747 "rename|move|mv":
4746 (rename,
4748 (rename,
4747 [('A', 'after', None, _('record a rename that has already occurred')),
4749 [('A', 'after', None, _('record a rename that has already occurred')),
4748 ('f', 'force', None,
4750 ('f', 'force', None,
4749 _('forcibly copy over an existing managed file')),
4751 _('forcibly copy over an existing managed file')),
4750 ] + walkopts + dryrunopts,
4752 ] + walkopts + dryrunopts,
4751 _('[OPTION]... SOURCE... DEST')),
4753 _('[OPTION]... SOURCE... DEST')),
4752 "resolve":
4754 "resolve":
4753 (resolve,
4755 (resolve,
4754 [('a', 'all', None, _('select all unresolved files')),
4756 [('a', 'all', None, _('select all unresolved files')),
4755 ('l', 'list', None, _('list state of files needing merge')),
4757 ('l', 'list', None, _('list state of files needing merge')),
4756 ('m', 'mark', None, _('mark files as resolved')),
4758 ('m', 'mark', None, _('mark files as resolved')),
4757 ('u', 'unmark', None, _('mark files as unresolved')),
4759 ('u', 'unmark', None, _('mark files as unresolved')),
4758 ('t', 'tool', '', _('specify merge tool')),
4760 ('t', 'tool', '', _('specify merge tool')),
4759 ('n', 'no-status', None, _('hide status prefix'))]
4761 ('n', 'no-status', None, _('hide status prefix'))]
4760 + walkopts,
4762 + walkopts,
4761 _('[OPTION]... [FILE]...')),
4763 _('[OPTION]... [FILE]...')),
4762 "revert":
4764 "revert":
4763 (revert,
4765 (revert,
4764 [('a', 'all', None, _('revert all changes when no arguments given')),
4766 [('a', 'all', None, _('revert all changes when no arguments given')),
4765 ('d', 'date', '',
4767 ('d', 'date', '',
4766 _('tipmost revision matching date'), _('DATE')),
4768 _('tipmost revision matching date'), _('DATE')),
4767 ('r', 'rev', '',
4769 ('r', 'rev', '',
4768 _('revert to the specified revision'), _('REV')),
4770 _('revert to the specified revision'), _('REV')),
4769 ('', 'no-backup', None, _('do not save backup copies of files')),
4771 ('', 'no-backup', None, _('do not save backup copies of files')),
4770 ] + walkopts + dryrunopts,
4772 ] + walkopts + dryrunopts,
4771 _('[OPTION]... [-r REV] [NAME]...')),
4773 _('[OPTION]... [-r REV] [NAME]...')),
4772 "rollback": (rollback, dryrunopts),
4774 "rollback": (rollback, dryrunopts),
4773 "root": (root, []),
4775 "root": (root, []),
4774 "^serve":
4776 "^serve":
4775 (serve,
4777 (serve,
4776 [('A', 'accesslog', '',
4778 [('A', 'accesslog', '',
4777 _('name of access log file to write to'), _('FILE')),
4779 _('name of access log file to write to'), _('FILE')),
4778 ('d', 'daemon', None, _('run server in background')),
4780 ('d', 'daemon', None, _('run server in background')),
4779 ('', 'daemon-pipefds', '',
4781 ('', 'daemon-pipefds', '',
4780 _('used internally by daemon mode'), _('NUM')),
4782 _('used internally by daemon mode'), _('NUM')),
4781 ('E', 'errorlog', '',
4783 ('E', 'errorlog', '',
4782 _('name of error log file to write to'), _('FILE')),
4784 _('name of error log file to write to'), _('FILE')),
4783 # use string type, then we can check if something was passed
4785 # use string type, then we can check if something was passed
4784 ('p', 'port', '',
4786 ('p', 'port', '',
4785 _('port to listen on (default: 8000)'), _('PORT')),
4787 _('port to listen on (default: 8000)'), _('PORT')),
4786 ('a', 'address', '',
4788 ('a', 'address', '',
4787 _('address to listen on (default: all interfaces)'), _('ADDR')),
4789 _('address to listen on (default: all interfaces)'), _('ADDR')),
4788 ('', 'prefix', '',
4790 ('', 'prefix', '',
4789 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4791 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4790 ('n', 'name', '',
4792 ('n', 'name', '',
4791 _('name to show in web pages (default: working directory)'),
4793 _('name to show in web pages (default: working directory)'),
4792 _('NAME')),
4794 _('NAME')),
4793 ('', 'web-conf', '',
4795 ('', 'web-conf', '',
4794 _('name of the hgweb config file (see "hg help hgweb")'),
4796 _('name of the hgweb config file (see "hg help hgweb")'),
4795 _('FILE')),
4797 _('FILE')),
4796 ('', 'webdir-conf', '',
4798 ('', 'webdir-conf', '',
4797 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4799 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4798 ('', 'pid-file', '',
4800 ('', 'pid-file', '',
4799 _('name of file to write process ID to'), _('FILE')),
4801 _('name of file to write process ID to'), _('FILE')),
4800 ('', 'stdio', None, _('for remote clients')),
4802 ('', 'stdio', None, _('for remote clients')),
4801 ('t', 'templates', '',
4803 ('t', 'templates', '',
4802 _('web templates to use'), _('TEMPLATE')),
4804 _('web templates to use'), _('TEMPLATE')),
4803 ('', 'style', '',
4805 ('', 'style', '',
4804 _('template style to use'), _('STYLE')),
4806 _('template style to use'), _('STYLE')),
4805 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4807 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4806 ('', 'certificate', '',
4808 ('', 'certificate', '',
4807 _('SSL certificate file'), _('FILE'))],
4809 _('SSL certificate file'), _('FILE'))],
4808 _('[OPTION]...')),
4810 _('[OPTION]...')),
4809 "showconfig|debugconfig":
4811 "showconfig|debugconfig":
4810 (showconfig,
4812 (showconfig,
4811 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4813 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4812 _('[-u] [NAME]...')),
4814 _('[-u] [NAME]...')),
4813 "^summary|sum":
4815 "^summary|sum":
4814 (summary,
4816 (summary,
4815 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4817 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4816 "^status|st":
4818 "^status|st":
4817 (status,
4819 (status,
4818 [('A', 'all', None, _('show status of all files')),
4820 [('A', 'all', None, _('show status of all files')),
4819 ('m', 'modified', None, _('show only modified files')),
4821 ('m', 'modified', None, _('show only modified files')),
4820 ('a', 'added', None, _('show only added files')),
4822 ('a', 'added', None, _('show only added files')),
4821 ('r', 'removed', None, _('show only removed files')),
4823 ('r', 'removed', None, _('show only removed files')),
4822 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4824 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4823 ('c', 'clean', None, _('show only files without changes')),
4825 ('c', 'clean', None, _('show only files without changes')),
4824 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4826 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4825 ('i', 'ignored', None, _('show only ignored files')),
4827 ('i', 'ignored', None, _('show only ignored files')),
4826 ('n', 'no-status', None, _('hide status prefix')),
4828 ('n', 'no-status', None, _('hide status prefix')),
4827 ('C', 'copies', None, _('show source of copied files')),
4829 ('C', 'copies', None, _('show source of copied files')),
4828 ('0', 'print0', None,
4830 ('0', 'print0', None,
4829 _('end filenames with NUL, for use with xargs')),
4831 _('end filenames with NUL, for use with xargs')),
4830 ('', 'rev', [],
4832 ('', 'rev', [],
4831 _('show difference from revision'), _('REV')),
4833 _('show difference from revision'), _('REV')),
4832 ('', 'change', '',
4834 ('', 'change', '',
4833 _('list the changed files of a revision'), _('REV')),
4835 _('list the changed files of a revision'), _('REV')),
4834 ] + walkopts + subrepoopts,
4836 ] + walkopts + subrepoopts,
4835 _('[OPTION]... [FILE]...')),
4837 _('[OPTION]... [FILE]...')),
4836 "tag":
4838 "tag":
4837 (tag,
4839 (tag,
4838 [('f', 'force', None, _('force tag')),
4840 [('f', 'force', None, _('force tag')),
4839 ('l', 'local', None, _('make the tag local')),
4841 ('l', 'local', None, _('make the tag local')),
4840 ('r', 'rev', '',
4842 ('r', 'rev', '',
4841 _('revision to tag'), _('REV')),
4843 _('revision to tag'), _('REV')),
4842 ('', 'remove', None, _('remove a tag')),
4844 ('', 'remove', None, _('remove a tag')),
4843 # -l/--local is already there, commitopts cannot be used
4845 # -l/--local is already there, commitopts cannot be used
4844 ('e', 'edit', None, _('edit commit message')),
4846 ('e', 'edit', None, _('edit commit message')),
4845 ('m', 'message', '',
4847 ('m', 'message', '',
4846 _('use <text> as commit message'), _('TEXT')),
4848 _('use <text> as commit message'), _('TEXT')),
4847 ] + commitopts2,
4849 ] + commitopts2,
4848 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4850 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4849 "tags": (tags, [], ''),
4851 "tags": (tags, [], ''),
4850 "tip":
4852 "tip":
4851 (tip,
4853 (tip,
4852 [('p', 'patch', None, _('show patch')),
4854 [('p', 'patch', None, _('show patch')),
4853 ('g', 'git', None, _('use git extended diff format')),
4855 ('g', 'git', None, _('use git extended diff format')),
4854 ] + templateopts,
4856 ] + templateopts,
4855 _('[-p] [-g]')),
4857 _('[-p] [-g]')),
4856 "unbundle":
4858 "unbundle":
4857 (unbundle,
4859 (unbundle,
4858 [('u', 'update', None,
4860 [('u', 'update', None,
4859 _('update to new branch head if changesets were unbundled'))],
4861 _('update to new branch head if changesets were unbundled'))],
4860 _('[-u] FILE...')),
4862 _('[-u] FILE...')),
4861 "^update|up|checkout|co":
4863 "^update|up|checkout|co":
4862 (update,
4864 (update,
4863 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4865 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4864 ('c', 'check', None,
4866 ('c', 'check', None,
4865 _('update across branches if no uncommitted changes')),
4867 _('update across branches if no uncommitted changes')),
4866 ('d', 'date', '',
4868 ('d', 'date', '',
4867 _('tipmost revision matching date'), _('DATE')),
4869 _('tipmost revision matching date'), _('DATE')),
4868 ('r', 'rev', '',
4870 ('r', 'rev', '',
4869 _('revision'), _('REV'))],
4871 _('revision'), _('REV'))],
4870 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4872 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4871 "verify": (verify, []),
4873 "verify": (verify, []),
4872 "version": (version_, []),
4874 "version": (version_, []),
4873 }
4875 }
4874
4876
4875 norepo = ("clone init version help debugcommands debugcomplete"
4877 norepo = ("clone init version help debugcommands debugcomplete"
4876 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
4878 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
4877 " debugknown debuggetbundle debugbundle")
4879 " debugknown debuggetbundle debugbundle")
4878 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4880 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4879 " debugdata debugindex debugindexdot")
4881 " debugdata debugindex debugindexdot")
@@ -1,323 +1,323 b''
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 bookmark rev -1
8 bookmark rev -1
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmarks
14 $ hg bookmarks
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmarks --color=always
20 > bookmarks --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22
22
23 $ echo a > a
23 $ echo a > a
24 $ hg add a
24 $ hg add a
25 $ hg commit -m 0
25 $ hg commit -m 0
26
26
27 bookmark X moved to rev 0
27 bookmark X moved to rev 0
28
28
29 $ hg bookmarks
29 $ hg bookmarks
30 * X 0:f7b1eb17ad24
30 * X 0:f7b1eb17ad24
31
31
32 look up bookmark
32 look up bookmark
33
33
34 $ hg log -r X
34 $ hg log -r X
35 changeset: 0:f7b1eb17ad24
35 changeset: 0:f7b1eb17ad24
36 bookmark: X
36 bookmark: X
37 tag: tip
37 tag: tip
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 0
40 summary: 0
41
41
42
42
43 second bookmark for rev 0
43 second bookmark for rev 0
44
44
45 $ hg bookmark X2
45 $ hg bookmark X2
46
46
47 bookmark rev -1 again
47 bookmark rev -1 again
48
48
49 $ hg bookmark -r null Y
49 $ hg bookmark -r null Y
50
50
51 list bookmarks
51 list bookmarks
52
52
53 $ hg bookmarks
53 $ hg bookmarks
54 X 0:f7b1eb17ad24
54 X 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
56 Y -1:000000000000
56 Y -1:000000000000
57
57
58 $ echo b > b
58 $ echo b > b
59 $ hg add b
59 $ hg add b
60 $ hg commit -m 1
60 $ hg commit -m 1
61
61
62 bookmarks revset
62 bookmarks revset
63
63
64 $ hg log -r 'bookmark()'
64 $ hg log -r 'bookmark()'
65 changeset: 0:f7b1eb17ad24
65 changeset: 0:f7b1eb17ad24
66 bookmark: X
66 bookmark: X
67 user: test
67 user: test
68 date: Thu Jan 01 00:00:00 1970 +0000
68 date: Thu Jan 01 00:00:00 1970 +0000
69 summary: 0
69 summary: 0
70
70
71 changeset: 1:925d80f479bb
71 changeset: 1:925d80f479bb
72 bookmark: X2
72 bookmark: X2
73 tag: tip
73 tag: tip
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: 1
76 summary: 1
77
77
78 $ hg log -r 'bookmark(Y)'
78 $ hg log -r 'bookmark(Y)'
79 $ hg log -r 'bookmark(X2)'
79 $ hg log -r 'bookmark(X2)'
80 changeset: 1:925d80f479bb
80 changeset: 1:925d80f479bb
81 bookmark: X2
81 bookmark: X2
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:00 1970 +0000
84 date: Thu Jan 01 00:00:00 1970 +0000
85 summary: 1
85 summary: 1
86
86
87 $ hg help revsets | grep 'bookmark('
87 $ hg help revsets | grep 'bookmark('
88 "bookmark([name])"
88 "bookmark([name])"
89
89
90 bookmarks X and X2 moved to rev 1, Y at rev -1
90 bookmarks X and X2 moved to rev 1, Y at rev -1
91
91
92 $ hg bookmarks
92 $ hg bookmarks
93 X 0:f7b1eb17ad24
93 X 0:f7b1eb17ad24
94 * X2 1:925d80f479bb
94 * X2 1:925d80f479bb
95 Y -1:000000000000
95 Y -1:000000000000
96
96
97 bookmark rev 0 again
97 bookmark rev 0 again
98
98
99 $ hg bookmark -r 0 Z
99 $ hg bookmark -r 0 Z
100
100
101 $ hg update X
101 $ hg update X
102 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
102 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
103 $ echo c > c
103 $ echo c > c
104 $ hg add c
104 $ hg add c
105 $ hg commit -m 2
105 $ hg commit -m 2
106 created new head
106 created new head
107
107
108 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
108 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
109
109
110 $ hg bookmarks
110 $ hg bookmarks
111 * X 2:db815d6d32e6
111 * X 2:db815d6d32e6
112 X2 1:925d80f479bb
112 X2 1:925d80f479bb
113 Y -1:000000000000
113 Y -1:000000000000
114 Z 0:f7b1eb17ad24
114 Z 0:f7b1eb17ad24
115
115
116 rename nonexistent bookmark
116 rename nonexistent bookmark
117
117
118 $ hg bookmark -m A B
118 $ hg bookmark -m A B
119 abort: a bookmark of this name does not exist
119 abort: bookmark 'A' does not exist
120 [255]
120 [255]
121
121
122 rename to existent bookmark
122 rename to existent bookmark
123
123
124 $ hg bookmark -m X Y
124 $ hg bookmark -m X Y
125 abort: a bookmark of the same name already exists
125 abort: bookmark 'Y' already exists (use -f to force)
126 [255]
126 [255]
127
127
128 force rename to existent bookmark
128 force rename to existent bookmark
129
129
130 $ hg bookmark -f -m X Y
130 $ hg bookmark -f -m X Y
131
131
132 list bookmarks
132 list bookmarks
133
133
134 $ hg bookmark
134 $ hg bookmark
135 X2 1:925d80f479bb
135 X2 1:925d80f479bb
136 * Y 2:db815d6d32e6
136 * Y 2:db815d6d32e6
137 Z 0:f7b1eb17ad24
137 Z 0:f7b1eb17ad24
138
138
139 rename without new name
139 rename without new name
140
140
141 $ hg bookmark -m Y
141 $ hg bookmark -m Y
142 abort: new bookmark name required
142 abort: new bookmark name required
143 [255]
143 [255]
144
144
145 delete without name
145 delete without name
146
146
147 $ hg bookmark -d
147 $ hg bookmark -d
148 abort: bookmark name required
148 abort: bookmark name required
149 [255]
149 [255]
150
150
151 delete nonexistent bookmark
151 delete nonexistent bookmark
152
152
153 $ hg bookmark -d A
153 $ hg bookmark -d A
154 abort: a bookmark of this name does not exist
154 abort: bookmark 'A' does not exist
155 [255]
155 [255]
156
156
157 bookmark name with spaces should be stripped
157 bookmark name with spaces should be stripped
158
158
159 $ hg bookmark ' x y '
159 $ hg bookmark ' x y '
160
160
161 list bookmarks
161 list bookmarks
162
162
163 $ hg bookmarks
163 $ hg bookmarks
164 X2 1:925d80f479bb
164 X2 1:925d80f479bb
165 Y 2:db815d6d32e6
165 Y 2:db815d6d32e6
166 Z 0:f7b1eb17ad24
166 Z 0:f7b1eb17ad24
167 * x y 2:db815d6d32e6
167 * x y 2:db815d6d32e6
168
168
169 look up stripped bookmark name
169 look up stripped bookmark name
170
170
171 $ hg log -r '"x y"'
171 $ hg log -r '"x y"'
172 changeset: 2:db815d6d32e6
172 changeset: 2:db815d6d32e6
173 bookmark: Y
173 bookmark: Y
174 bookmark: x y
174 bookmark: x y
175 tag: tip
175 tag: tip
176 parent: 0:f7b1eb17ad24
176 parent: 0:f7b1eb17ad24
177 user: test
177 user: test
178 date: Thu Jan 01 00:00:00 1970 +0000
178 date: Thu Jan 01 00:00:00 1970 +0000
179 summary: 2
179 summary: 2
180
180
181
181
182 reject bookmark name with newline
182 reject bookmark name with newline
183
183
184 $ hg bookmark '
184 $ hg bookmark '
185 > '
185 > '
186 abort: bookmark name cannot contain newlines
186 abort: bookmark name cannot contain newlines
187 [255]
187 [255]
188
188
189 bookmark with existing name
189 bookmark with existing name
190
190
191 $ hg bookmark Z
191 $ hg bookmark Z
192 abort: a bookmark of the same name already exists
192 abort: bookmark 'Z' already exists (use -f to force)
193 [255]
193 [255]
194
194
195 force bookmark with existing name
195 force bookmark with existing name
196
196
197 $ hg bookmark -f Z
197 $ hg bookmark -f Z
198
198
199 list bookmarks
199 list bookmarks
200
200
201 $ hg bookmark
201 $ hg bookmark
202 X2 1:925d80f479bb
202 X2 1:925d80f479bb
203 Y 2:db815d6d32e6
203 Y 2:db815d6d32e6
204 * Z 2:db815d6d32e6
204 * Z 2:db815d6d32e6
205 x y 2:db815d6d32e6
205 x y 2:db815d6d32e6
206
206
207 revision but no bookmark name
207 revision but no bookmark name
208
208
209 $ hg bookmark -r .
209 $ hg bookmark -r .
210 abort: bookmark name required
210 abort: bookmark name required
211 [255]
211 [255]
212
212
213 bookmark name with whitespace only
213 bookmark name with whitespace only
214
214
215 $ hg bookmark ' '
215 $ hg bookmark ' '
216 abort: bookmark names cannot consist entirely of whitespace
216 abort: bookmark names cannot consist entirely of whitespace
217 [255]
217 [255]
218
218
219 invalid bookmark
219 invalid bookmark
220
220
221 $ hg bookmark 'foo:bar'
221 $ hg bookmark 'foo:bar'
222 abort: bookmark 'foo:bar' contains illegal character
222 abort: bookmark 'foo:bar' contains illegal character
223 [255]
223 [255]
224
224
225 the bookmark extension should be ignored now that it is part of core
225 the bookmark extension should be ignored now that it is part of core
226
226
227 $ echo "[extensions]" >> $HGRCPATH
227 $ echo "[extensions]" >> $HGRCPATH
228 $ echo "bookmarks=" >> $HGRCPATH
228 $ echo "bookmarks=" >> $HGRCPATH
229 $ hg bookmarks
229 $ hg bookmarks
230 X2 1:925d80f479bb
230 X2 1:925d80f479bb
231 Y 2:db815d6d32e6
231 Y 2:db815d6d32e6
232 * Z 2:db815d6d32e6
232 * Z 2:db815d6d32e6
233 x y 2:db815d6d32e6
233 x y 2:db815d6d32e6
234 test summary
234 test summary
235
235
236 $ hg summary
236 $ hg summary
237 parent: 2:db815d6d32e6 tip Y Z x y
237 parent: 2:db815d6d32e6 tip Y Z x y
238 2
238 2
239 branch: default
239 branch: default
240 commit: (clean)
240 commit: (clean)
241 update: 1 new changesets, 2 branch heads (merge)
241 update: 1 new changesets, 2 branch heads (merge)
242
242
243 test id
243 test id
244
244
245 $ hg id
245 $ hg id
246 db815d6d32e6 tip Y/Z/x y
246 db815d6d32e6 tip Y/Z/x y
247
247
248 test clone
248 test clone
249
249
250 $ hg bookmarks
250 $ hg bookmarks
251 X2 1:925d80f479bb
251 X2 1:925d80f479bb
252 Y 2:db815d6d32e6
252 Y 2:db815d6d32e6
253 * Z 2:db815d6d32e6
253 * Z 2:db815d6d32e6
254 x y 2:db815d6d32e6
254 x y 2:db815d6d32e6
255 $ hg clone . cloned-bookmarks
255 $ hg clone . cloned-bookmarks
256 updating to branch default
256 updating to branch default
257 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 $ hg -R cloned-bookmarks bookmarks
258 $ hg -R cloned-bookmarks bookmarks
259 X2 1:925d80f479bb
259 X2 1:925d80f479bb
260 Y 2:db815d6d32e6
260 Y 2:db815d6d32e6
261 Z 2:db815d6d32e6
261 Z 2:db815d6d32e6
262 x y 2:db815d6d32e6
262 x y 2:db815d6d32e6
263
263
264 test clone with pull protocol
264 test clone with pull protocol
265
265
266 $ hg clone --pull . cloned-bookmarks-pull
266 $ hg clone --pull . cloned-bookmarks-pull
267 requesting all changes
267 requesting all changes
268 adding changesets
268 adding changesets
269 adding manifests
269 adding manifests
270 adding file changes
270 adding file changes
271 added 3 changesets with 3 changes to 3 files (+1 heads)
271 added 3 changesets with 3 changes to 3 files (+1 heads)
272 updating to branch default
272 updating to branch default
273 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
273 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
274 $ hg -R cloned-bookmarks-pull bookmarks
274 $ hg -R cloned-bookmarks-pull bookmarks
275 X2 1:925d80f479bb
275 X2 1:925d80f479bb
276 Y 2:db815d6d32e6
276 Y 2:db815d6d32e6
277 Z 2:db815d6d32e6
277 Z 2:db815d6d32e6
278 x y 2:db815d6d32e6
278 x y 2:db815d6d32e6
279
279
280 test clone with a specific revision
280 test clone with a specific revision
281
281
282 $ hg clone -r 925d80 . cloned-bookmarks-rev
282 $ hg clone -r 925d80 . cloned-bookmarks-rev
283 adding changesets
283 adding changesets
284 adding manifests
284 adding manifests
285 adding file changes
285 adding file changes
286 added 2 changesets with 2 changes to 2 files
286 added 2 changesets with 2 changes to 2 files
287 updating to branch default
287 updating to branch default
288 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
288 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
289 $ hg -R cloned-bookmarks-rev bookmarks
289 $ hg -R cloned-bookmarks-rev bookmarks
290 X2 1:925d80f479bb
290 X2 1:925d80f479bb
291
291
292 create bundle with two heads
292 create bundle with two heads
293
293
294 $ hg clone . tobundle
294 $ hg clone . tobundle
295 updating to branch default
295 updating to branch default
296 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
296 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
297 $ echo x > tobundle/x
297 $ echo x > tobundle/x
298 $ hg -R tobundle add tobundle/x
298 $ hg -R tobundle add tobundle/x
299 $ hg -R tobundle commit -m'x'
299 $ hg -R tobundle commit -m'x'
300 $ hg -R tobundle update -r -2
300 $ hg -R tobundle update -r -2
301 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
301 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
302 $ echo y > tobundle/y
302 $ echo y > tobundle/y
303 $ hg -R tobundle branch test
303 $ hg -R tobundle branch test
304 marked working directory as branch test
304 marked working directory as branch test
305 $ hg -R tobundle add tobundle/y
305 $ hg -R tobundle add tobundle/y
306 $ hg -R tobundle commit -m'y'
306 $ hg -R tobundle commit -m'y'
307 $ hg -R tobundle bundle tobundle.hg
307 $ hg -R tobundle bundle tobundle.hg
308 searching for changes
308 searching for changes
309 2 changesets found
309 2 changesets found
310 $ hg unbundle tobundle.hg
310 $ hg unbundle tobundle.hg
311 adding changesets
311 adding changesets
312 adding manifests
312 adding manifests
313 adding file changes
313 adding file changes
314 added 2 changesets with 2 changes to 2 files (+1 heads)
314 added 2 changesets with 2 changes to 2 files (+1 heads)
315 (run 'hg heads' to see heads, 'hg merge' to merge)
315 (run 'hg heads' to see heads, 'hg merge' to merge)
316 $ hg update
316 $ hg update
317 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
317 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
318 $ hg bookmarks
318 $ hg bookmarks
319 X2 1:925d80f479bb
319 X2 1:925d80f479bb
320 Y 2:db815d6d32e6
320 Y 2:db815d6d32e6
321 * Z 3:125c9a1d6df6
321 * Z 3:125c9a1d6df6
322 x y 2:db815d6d32e6
322 x y 2:db815d6d32e6
323
323
General Comments 0
You need to be logged in to leave comments. Login now