##// END OF EJS Templates
tag: abort if not at a branch head (issue2552)...
Kevin Bullock -
r13135:1c1ca9d3 stable
parent child Browse files
Show More
@@ -1,4518 +1,4530 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, extensions, copies, error
12 import hg, util, revlog, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 opts.get('subrepos'), prefix="")
51 opts.get('subrepos'), prefix="")
52 return rejected and 1 or 0
52 return rejected and 1 or 0
53
53
54 def addremove(ui, repo, *pats, **opts):
54 def addremove(ui, repo, *pats, **opts):
55 """add all new files, delete all missing files
55 """add all new files, delete all missing files
56
56
57 Add all new files and remove all missing files from the
57 Add all new files and remove all missing files from the
58 repository.
58 repository.
59
59
60 New files are ignored if they match any of the patterns in
60 New files are ignored if they match any of the patterns in
61 .hgignore. As with add, these changes take effect at the next
61 .hgignore. As with add, these changes take effect at the next
62 commit.
62 commit.
63
63
64 Use the -s/--similarity option to detect renamed files. With a
64 Use the -s/--similarity option to detect renamed files. With a
65 parameter greater than 0, this compares every removed file with
65 parameter greater than 0, this compares every removed file with
66 every added file and records those similar enough as renames. This
66 every added file and records those similar enough as renames. This
67 option takes a percentage between 0 (disabled) and 100 (files must
67 option takes a percentage between 0 (disabled) and 100 (files must
68 be identical) as its parameter. Detecting renamed files this way
68 be identical) as its parameter. Detecting renamed files this way
69 can be expensive. After using this option, :hg:`status -C` can be
69 can be expensive. After using this option, :hg:`status -C` can be
70 used to check which files were identified as moved or renamed.
70 used to check which files were identified as moved or renamed.
71
71
72 Returns 0 if all files are successfully added.
72 Returns 0 if all files are successfully added.
73 """
73 """
74 try:
74 try:
75 sim = float(opts.get('similarity') or 100)
75 sim = float(opts.get('similarity') or 100)
76 except ValueError:
76 except ValueError:
77 raise util.Abort(_('similarity must be a number'))
77 raise util.Abort(_('similarity must be a number'))
78 if sim < 0 or sim > 100:
78 if sim < 0 or sim > 100:
79 raise util.Abort(_('similarity must be between 0 and 100'))
79 raise util.Abort(_('similarity must be between 0 and 100'))
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81
81
82 def annotate(ui, repo, *pats, **opts):
82 def annotate(ui, repo, *pats, **opts):
83 """show changeset information by line for each file
83 """show changeset information by line for each file
84
84
85 List changes in files, showing the revision id responsible for
85 List changes in files, showing the revision id responsible for
86 each line
86 each line
87
87
88 This command is useful for discovering when a change was made and
88 This command is useful for discovering when a change was made and
89 by whom.
89 by whom.
90
90
91 Without the -a/--text option, annotate will avoid processing files
91 Without the -a/--text option, annotate will avoid processing files
92 it detects as binary. With -a, annotate will annotate the file
92 it detects as binary. With -a, annotate will annotate the file
93 anyway, although the results will probably be neither useful
93 anyway, although the results will probably be neither useful
94 nor desirable.
94 nor desirable.
95
95
96 Returns 0 on success.
96 Returns 0 on success.
97 """
97 """
98 if opts.get('follow'):
98 if opts.get('follow'):
99 # --follow is deprecated and now just an alias for -f/--file
99 # --follow is deprecated and now just an alias for -f/--file
100 # to mimic the behavior of Mercurial before version 1.5
100 # to mimic the behavior of Mercurial before version 1.5
101 opts['file'] = 1
101 opts['file'] = 1
102
102
103 datefunc = ui.quiet and util.shortdate or util.datestr
103 datefunc = ui.quiet and util.shortdate or util.datestr
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105
105
106 if not pats:
106 if not pats:
107 raise util.Abort(_('at least one filename or pattern is required'))
107 raise util.Abort(_('at least one filename or pattern is required'))
108
108
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 ('number', lambda x: str(x[0].rev())),
110 ('number', lambda x: str(x[0].rev())),
111 ('changeset', lambda x: short(x[0].node())),
111 ('changeset', lambda x: short(x[0].node())),
112 ('date', getdate),
112 ('date', getdate),
113 ('file', lambda x: x[0].path()),
113 ('file', lambda x: x[0].path()),
114 ]
114 ]
115
115
116 if (not opts.get('user') and not opts.get('changeset')
116 if (not opts.get('user') and not opts.get('changeset')
117 and not opts.get('date') and not opts.get('file')):
117 and not opts.get('date') and not opts.get('file')):
118 opts['number'] = 1
118 opts['number'] = 1
119
119
120 linenumber = opts.get('line_number') is not None
120 linenumber = opts.get('line_number') is not None
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123
123
124 funcmap = [func for op, func in opmap if opts.get(op)]
124 funcmap = [func for op, func in opmap if opts.get(op)]
125 if linenumber:
125 if linenumber:
126 lastfunc = funcmap[-1]
126 lastfunc = funcmap[-1]
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128
128
129 ctx = repo[opts.get('rev')]
129 ctx = repo[opts.get('rev')]
130 m = cmdutil.match(repo, pats, opts)
130 m = cmdutil.match(repo, pats, opts)
131 follow = not opts.get('no_follow')
131 follow = not opts.get('no_follow')
132 for abs in ctx.walk(m):
132 for abs in ctx.walk(m):
133 fctx = ctx[abs]
133 fctx = ctx[abs]
134 if not opts.get('text') and util.binary(fctx.data()):
134 if not opts.get('text') and util.binary(fctx.data()):
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 continue
136 continue
137
137
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 pieces = []
139 pieces = []
140
140
141 for f in funcmap:
141 for f in funcmap:
142 l = [f(n) for n, dummy in lines]
142 l = [f(n) for n, dummy in lines]
143 if l:
143 if l:
144 sized = [(x, encoding.colwidth(x)) for x in l]
144 sized = [(x, encoding.colwidth(x)) for x in l]
145 ml = max([w for x, w in sized])
145 ml = max([w for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147
147
148 if pieces:
148 if pieces:
149 for p, l in zip(zip(*pieces), lines):
149 for p, l in zip(zip(*pieces), lines):
150 ui.write("%s: %s" % (" ".join(p), l[1]))
150 ui.write("%s: %s" % (" ".join(p), l[1]))
151
151
152 def archive(ui, repo, dest, **opts):
152 def archive(ui, repo, dest, **opts):
153 '''create an unversioned archive of a repository revision
153 '''create an unversioned archive of a repository revision
154
154
155 By default, the revision used is the parent of the working
155 By default, the revision used is the parent of the working
156 directory; use -r/--rev to specify a different revision.
156 directory; use -r/--rev to specify a different revision.
157
157
158 The archive type is automatically detected based on file
158 The archive type is automatically detected based on file
159 extension (or override using -t/--type).
159 extension (or override using -t/--type).
160
160
161 Valid types are:
161 Valid types are:
162
162
163 :``files``: a directory full of files (default)
163 :``files``: a directory full of files (default)
164 :``tar``: tar archive, uncompressed
164 :``tar``: tar archive, uncompressed
165 :``tbz2``: tar archive, compressed using bzip2
165 :``tbz2``: tar archive, compressed using bzip2
166 :``tgz``: tar archive, compressed using gzip
166 :``tgz``: tar archive, compressed using gzip
167 :``uzip``: zip archive, uncompressed
167 :``uzip``: zip archive, uncompressed
168 :``zip``: zip archive, compressed using deflate
168 :``zip``: zip archive, compressed using deflate
169
169
170 The exact name of the destination archive or directory is given
170 The exact name of the destination archive or directory is given
171 using a format string; see :hg:`help export` for details.
171 using a format string; see :hg:`help export` for details.
172
172
173 Each member added to an archive file has a directory prefix
173 Each member added to an archive file has a directory prefix
174 prepended. Use -p/--prefix to specify a format string for the
174 prepended. Use -p/--prefix to specify a format string for the
175 prefix. The default is the basename of the archive, with suffixes
175 prefix. The default is the basename of the archive, with suffixes
176 removed.
176 removed.
177
177
178 Returns 0 on success.
178 Returns 0 on success.
179 '''
179 '''
180
180
181 ctx = repo[opts.get('rev')]
181 ctx = repo[opts.get('rev')]
182 if not ctx:
182 if not ctx:
183 raise util.Abort(_('no working directory: please specify a revision'))
183 raise util.Abort(_('no working directory: please specify a revision'))
184 node = ctx.node()
184 node = ctx.node()
185 dest = cmdutil.make_filename(repo, dest, node)
185 dest = cmdutil.make_filename(repo, dest, node)
186 if os.path.realpath(dest) == repo.root:
186 if os.path.realpath(dest) == repo.root:
187 raise util.Abort(_('repository root cannot be destination'))
187 raise util.Abort(_('repository root cannot be destination'))
188
188
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 prefix = opts.get('prefix')
190 prefix = opts.get('prefix')
191
191
192 if dest == '-':
192 if dest == '-':
193 if kind == 'files':
193 if kind == 'files':
194 raise util.Abort(_('cannot archive plain files to stdout'))
194 raise util.Abort(_('cannot archive plain files to stdout'))
195 dest = sys.stdout
195 dest = sys.stdout
196 if not prefix:
196 if not prefix:
197 prefix = os.path.basename(repo.root) + '-%h'
197 prefix = os.path.basename(repo.root) + '-%h'
198
198
199 prefix = cmdutil.make_filename(repo, prefix, node)
199 prefix = cmdutil.make_filename(repo, prefix, node)
200 matchfn = cmdutil.match(repo, [], opts)
200 matchfn = cmdutil.match(repo, [], opts)
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 matchfn, prefix, subrepos=opts.get('subrepos'))
202 matchfn, prefix, subrepos=opts.get('subrepos'))
203
203
204 def backout(ui, repo, node=None, rev=None, **opts):
204 def backout(ui, repo, node=None, rev=None, **opts):
205 '''reverse effect of earlier changeset
205 '''reverse effect of earlier changeset
206
206
207 The backout command merges the reverse effect of the reverted
207 The backout command merges the reverse effect of the reverted
208 changeset into the working directory.
208 changeset into the working directory.
209
209
210 With the --merge option, it first commits the reverted changes
210 With the --merge option, it first commits the reverted changes
211 as a new changeset. This new changeset is a child of the reverted
211 as a new changeset. This new changeset is a child of the reverted
212 changeset.
212 changeset.
213 The --merge option remembers the parent of the working directory
213 The --merge option remembers the parent of the working directory
214 before starting the backout, then merges the new head with that
214 before starting the backout, then merges the new head with that
215 changeset afterwards.
215 changeset afterwards.
216 This will result in an explicit merge in the history.
216 This will result in an explicit merge in the history.
217
217
218 If you backout a changeset other than the original parent of the
218 If you backout a changeset other than the original parent of the
219 working directory, the result of this merge is not committed,
219 working directory, the result of this merge is not committed,
220 as with a normal merge. Otherwise, no merge is needed and the
220 as with a normal merge. Otherwise, no merge is needed and the
221 commit is automatic.
221 commit is automatic.
222
222
223 Note that the default behavior (without --merge) has changed in
223 Note that the default behavior (without --merge) has changed in
224 version 1.7. To restore the previous default behavior, use
224 version 1.7. To restore the previous default behavior, use
225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
226 the ongoing merge.
226 the ongoing merge.
227
227
228 See :hg:`help dates` for a list of formats valid for -d/--date.
228 See :hg:`help dates` for a list of formats valid for -d/--date.
229
229
230 Returns 0 on success.
230 Returns 0 on success.
231 '''
231 '''
232 if rev and node:
232 if rev and node:
233 raise util.Abort(_("please specify just one revision"))
233 raise util.Abort(_("please specify just one revision"))
234
234
235 if not rev:
235 if not rev:
236 rev = node
236 rev = node
237
237
238 if not rev:
238 if not rev:
239 raise util.Abort(_("please specify a revision to backout"))
239 raise util.Abort(_("please specify a revision to backout"))
240
240
241 date = opts.get('date')
241 date = opts.get('date')
242 if date:
242 if date:
243 opts['date'] = util.parsedate(date)
243 opts['date'] = util.parsedate(date)
244
244
245 cmdutil.bail_if_changed(repo)
245 cmdutil.bail_if_changed(repo)
246 node = repo.lookup(rev)
246 node = repo.lookup(rev)
247
247
248 op1, op2 = repo.dirstate.parents()
248 op1, op2 = repo.dirstate.parents()
249 a = repo.changelog.ancestor(op1, node)
249 a = repo.changelog.ancestor(op1, node)
250 if a != node:
250 if a != node:
251 raise util.Abort(_('cannot backout change on a different branch'))
251 raise util.Abort(_('cannot backout change on a different branch'))
252
252
253 p1, p2 = repo.changelog.parents(node)
253 p1, p2 = repo.changelog.parents(node)
254 if p1 == nullid:
254 if p1 == nullid:
255 raise util.Abort(_('cannot backout a change with no parents'))
255 raise util.Abort(_('cannot backout a change with no parents'))
256 if p2 != nullid:
256 if p2 != nullid:
257 if not opts.get('parent'):
257 if not opts.get('parent'):
258 raise util.Abort(_('cannot backout a merge changeset without '
258 raise util.Abort(_('cannot backout a merge changeset without '
259 '--parent'))
259 '--parent'))
260 p = repo.lookup(opts['parent'])
260 p = repo.lookup(opts['parent'])
261 if p not in (p1, p2):
261 if p not in (p1, p2):
262 raise util.Abort(_('%s is not a parent of %s') %
262 raise util.Abort(_('%s is not a parent of %s') %
263 (short(p), short(node)))
263 (short(p), short(node)))
264 parent = p
264 parent = p
265 else:
265 else:
266 if opts.get('parent'):
266 if opts.get('parent'):
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
268 parent = p1
268 parent = p1
269
269
270 # the backout should appear on the same branch
270 # the backout should appear on the same branch
271 branch = repo.dirstate.branch()
271 branch = repo.dirstate.branch()
272 hg.clean(repo, node, show_stats=False)
272 hg.clean(repo, node, show_stats=False)
273 repo.dirstate.setbranch(branch)
273 repo.dirstate.setbranch(branch)
274 revert_opts = opts.copy()
274 revert_opts = opts.copy()
275 revert_opts['date'] = None
275 revert_opts['date'] = None
276 revert_opts['all'] = True
276 revert_opts['all'] = True
277 revert_opts['rev'] = hex(parent)
277 revert_opts['rev'] = hex(parent)
278 revert_opts['no_backup'] = None
278 revert_opts['no_backup'] = None
279 revert(ui, repo, **revert_opts)
279 revert(ui, repo, **revert_opts)
280 if not opts.get('merge') and op1 != node:
280 if not opts.get('merge') and op1 != node:
281 try:
281 try:
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
283 return hg.update(repo, op1)
283 return hg.update(repo, op1)
284 finally:
284 finally:
285 ui.setconfig('ui', 'forcemerge', '')
285 ui.setconfig('ui', 'forcemerge', '')
286
286
287 commit_opts = opts.copy()
287 commit_opts = opts.copy()
288 commit_opts['addremove'] = False
288 commit_opts['addremove'] = False
289 if not commit_opts['message'] and not commit_opts['logfile']:
289 if not commit_opts['message'] and not commit_opts['logfile']:
290 # we don't translate commit messages
290 # we don't translate commit messages
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
292 commit_opts['force_editor'] = True
292 commit_opts['force_editor'] = True
293 commit(ui, repo, **commit_opts)
293 commit(ui, repo, **commit_opts)
294 def nice(node):
294 def nice(node):
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
296 ui.status(_('changeset %s backs out changeset %s\n') %
296 ui.status(_('changeset %s backs out changeset %s\n') %
297 (nice(repo.changelog.tip()), nice(node)))
297 (nice(repo.changelog.tip()), nice(node)))
298 if opts.get('merge') and op1 != node:
298 if opts.get('merge') and op1 != node:
299 hg.clean(repo, op1, show_stats=False)
299 hg.clean(repo, op1, show_stats=False)
300 ui.status(_('merging with changeset %s\n')
300 ui.status(_('merging with changeset %s\n')
301 % nice(repo.changelog.tip()))
301 % nice(repo.changelog.tip()))
302 try:
302 try:
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
304 return hg.merge(repo, hex(repo.changelog.tip()))
304 return hg.merge(repo, hex(repo.changelog.tip()))
305 finally:
305 finally:
306 ui.setconfig('ui', 'forcemerge', '')
306 ui.setconfig('ui', 'forcemerge', '')
307 return 0
307 return 0
308
308
309 def bisect(ui, repo, rev=None, extra=None, command=None,
309 def bisect(ui, repo, rev=None, extra=None, command=None,
310 reset=None, good=None, bad=None, skip=None, noupdate=None):
310 reset=None, good=None, bad=None, skip=None, noupdate=None):
311 """subdivision search of changesets
311 """subdivision search of changesets
312
312
313 This command helps to find changesets which introduce problems. To
313 This command helps to find changesets which introduce problems. To
314 use, mark the earliest changeset you know exhibits the problem as
314 use, mark the earliest changeset you know exhibits the problem as
315 bad, then mark the latest changeset which is free from the problem
315 bad, then mark the latest changeset which is free from the problem
316 as good. Bisect will update your working directory to a revision
316 as good. Bisect will update your working directory to a revision
317 for testing (unless the -U/--noupdate option is specified). Once
317 for testing (unless the -U/--noupdate option is specified). Once
318 you have performed tests, mark the working directory as good or
318 you have performed tests, mark the working directory as good or
319 bad, and bisect will either update to another candidate changeset
319 bad, and bisect will either update to another candidate changeset
320 or announce that it has found the bad revision.
320 or announce that it has found the bad revision.
321
321
322 As a shortcut, you can also use the revision argument to mark a
322 As a shortcut, you can also use the revision argument to mark a
323 revision as good or bad without checking it out first.
323 revision as good or bad without checking it out first.
324
324
325 If you supply a command, it will be used for automatic bisection.
325 If you supply a command, it will be used for automatic bisection.
326 Its exit status will be used to mark revisions as good or bad:
326 Its exit status will be used to mark revisions as good or bad:
327 status 0 means good, 125 means to skip the revision, 127
327 status 0 means good, 125 means to skip the revision, 127
328 (command not found) will abort the bisection, and any other
328 (command not found) will abort the bisection, and any other
329 non-zero exit status means the revision is bad.
329 non-zero exit status means the revision is bad.
330
330
331 Returns 0 on success.
331 Returns 0 on success.
332 """
332 """
333 def print_result(nodes, good):
333 def print_result(nodes, good):
334 displayer = cmdutil.show_changeset(ui, repo, {})
334 displayer = cmdutil.show_changeset(ui, repo, {})
335 if len(nodes) == 1:
335 if len(nodes) == 1:
336 # narrowed it down to a single revision
336 # narrowed it down to a single revision
337 if good:
337 if good:
338 ui.write(_("The first good revision is:\n"))
338 ui.write(_("The first good revision is:\n"))
339 else:
339 else:
340 ui.write(_("The first bad revision is:\n"))
340 ui.write(_("The first bad revision is:\n"))
341 displayer.show(repo[nodes[0]])
341 displayer.show(repo[nodes[0]])
342 parents = repo[nodes[0]].parents()
342 parents = repo[nodes[0]].parents()
343 if len(parents) > 1:
343 if len(parents) > 1:
344 side = good and state['bad'] or state['good']
344 side = good and state['bad'] or state['good']
345 num = len(set(i.node() for i in parents) & set(side))
345 num = len(set(i.node() for i in parents) & set(side))
346 if num == 1:
346 if num == 1:
347 common = parents[0].ancestor(parents[1])
347 common = parents[0].ancestor(parents[1])
348 ui.write(_('Not all ancestors of this changeset have been'
348 ui.write(_('Not all ancestors of this changeset have been'
349 ' checked.\nTo check the other ancestors, start'
349 ' checked.\nTo check the other ancestors, start'
350 ' from the common ancestor, %s.\n' % common))
350 ' from the common ancestor, %s.\n' % common))
351 else:
351 else:
352 # multiple possible revisions
352 # multiple possible revisions
353 if good:
353 if good:
354 ui.write(_("Due to skipped revisions, the first "
354 ui.write(_("Due to skipped revisions, the first "
355 "good revision could be any of:\n"))
355 "good revision could be any of:\n"))
356 else:
356 else:
357 ui.write(_("Due to skipped revisions, the first "
357 ui.write(_("Due to skipped revisions, the first "
358 "bad revision could be any of:\n"))
358 "bad revision could be any of:\n"))
359 for n in nodes:
359 for n in nodes:
360 displayer.show(repo[n])
360 displayer.show(repo[n])
361 displayer.close()
361 displayer.close()
362
362
363 def check_state(state, interactive=True):
363 def check_state(state, interactive=True):
364 if not state['good'] or not state['bad']:
364 if not state['good'] or not state['bad']:
365 if (good or bad or skip or reset) and interactive:
365 if (good or bad or skip or reset) and interactive:
366 return
366 return
367 if not state['good']:
367 if not state['good']:
368 raise util.Abort(_('cannot bisect (no known good revisions)'))
368 raise util.Abort(_('cannot bisect (no known good revisions)'))
369 else:
369 else:
370 raise util.Abort(_('cannot bisect (no known bad revisions)'))
370 raise util.Abort(_('cannot bisect (no known bad revisions)'))
371 return True
371 return True
372
372
373 # backward compatibility
373 # backward compatibility
374 if rev in "good bad reset init".split():
374 if rev in "good bad reset init".split():
375 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
375 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
376 cmd, rev, extra = rev, extra, None
376 cmd, rev, extra = rev, extra, None
377 if cmd == "good":
377 if cmd == "good":
378 good = True
378 good = True
379 elif cmd == "bad":
379 elif cmd == "bad":
380 bad = True
380 bad = True
381 else:
381 else:
382 reset = True
382 reset = True
383 elif extra or good + bad + skip + reset + bool(command) > 1:
383 elif extra or good + bad + skip + reset + bool(command) > 1:
384 raise util.Abort(_('incompatible arguments'))
384 raise util.Abort(_('incompatible arguments'))
385
385
386 if reset:
386 if reset:
387 p = repo.join("bisect.state")
387 p = repo.join("bisect.state")
388 if os.path.exists(p):
388 if os.path.exists(p):
389 os.unlink(p)
389 os.unlink(p)
390 return
390 return
391
391
392 state = hbisect.load_state(repo)
392 state = hbisect.load_state(repo)
393
393
394 if command:
394 if command:
395 changesets = 1
395 changesets = 1
396 try:
396 try:
397 while changesets:
397 while changesets:
398 # update state
398 # update state
399 status = util.system(command)
399 status = util.system(command)
400 if status == 125:
400 if status == 125:
401 transition = "skip"
401 transition = "skip"
402 elif status == 0:
402 elif status == 0:
403 transition = "good"
403 transition = "good"
404 # status < 0 means process was killed
404 # status < 0 means process was killed
405 elif status == 127:
405 elif status == 127:
406 raise util.Abort(_("failed to execute %s") % command)
406 raise util.Abort(_("failed to execute %s") % command)
407 elif status < 0:
407 elif status < 0:
408 raise util.Abort(_("%s killed") % command)
408 raise util.Abort(_("%s killed") % command)
409 else:
409 else:
410 transition = "bad"
410 transition = "bad"
411 ctx = repo[rev or '.']
411 ctx = repo[rev or '.']
412 state[transition].append(ctx.node())
412 state[transition].append(ctx.node())
413 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
413 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
414 check_state(state, interactive=False)
414 check_state(state, interactive=False)
415 # bisect
415 # bisect
416 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
416 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
417 # update to next check
417 # update to next check
418 cmdutil.bail_if_changed(repo)
418 cmdutil.bail_if_changed(repo)
419 hg.clean(repo, nodes[0], show_stats=False)
419 hg.clean(repo, nodes[0], show_stats=False)
420 finally:
420 finally:
421 hbisect.save_state(repo, state)
421 hbisect.save_state(repo, state)
422 print_result(nodes, good)
422 print_result(nodes, good)
423 return
423 return
424
424
425 # update state
425 # update state
426
426
427 if rev:
427 if rev:
428 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
428 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
429 else:
429 else:
430 nodes = [repo.lookup('.')]
430 nodes = [repo.lookup('.')]
431
431
432 if good or bad or skip:
432 if good or bad or skip:
433 if good:
433 if good:
434 state['good'] += nodes
434 state['good'] += nodes
435 elif bad:
435 elif bad:
436 state['bad'] += nodes
436 state['bad'] += nodes
437 elif skip:
437 elif skip:
438 state['skip'] += nodes
438 state['skip'] += nodes
439 hbisect.save_state(repo, state)
439 hbisect.save_state(repo, state)
440
440
441 if not check_state(state):
441 if not check_state(state):
442 return
442 return
443
443
444 # actually bisect
444 # actually bisect
445 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
445 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
446 if changesets == 0:
446 if changesets == 0:
447 print_result(nodes, good)
447 print_result(nodes, good)
448 else:
448 else:
449 assert len(nodes) == 1 # only a single node can be tested next
449 assert len(nodes) == 1 # only a single node can be tested next
450 node = nodes[0]
450 node = nodes[0]
451 # compute the approximate number of remaining tests
451 # compute the approximate number of remaining tests
452 tests, size = 0, 2
452 tests, size = 0, 2
453 while size <= changesets:
453 while size <= changesets:
454 tests, size = tests + 1, size * 2
454 tests, size = tests + 1, size * 2
455 rev = repo.changelog.rev(node)
455 rev = repo.changelog.rev(node)
456 ui.write(_("Testing changeset %d:%s "
456 ui.write(_("Testing changeset %d:%s "
457 "(%d changesets remaining, ~%d tests)\n")
457 "(%d changesets remaining, ~%d tests)\n")
458 % (rev, short(node), changesets, tests))
458 % (rev, short(node), changesets, tests))
459 if not noupdate:
459 if not noupdate:
460 cmdutil.bail_if_changed(repo)
460 cmdutil.bail_if_changed(repo)
461 return hg.clean(repo, node)
461 return hg.clean(repo, node)
462
462
463 def branch(ui, repo, label=None, **opts):
463 def branch(ui, repo, label=None, **opts):
464 """set or show the current branch name
464 """set or show the current branch name
465
465
466 With no argument, show the current branch name. With one argument,
466 With no argument, show the current branch name. With one argument,
467 set the working directory branch name (the branch will not exist
467 set the working directory branch name (the branch will not exist
468 in the repository until the next commit). Standard practice
468 in the repository until the next commit). Standard practice
469 recommends that primary development take place on the 'default'
469 recommends that primary development take place on the 'default'
470 branch.
470 branch.
471
471
472 Unless -f/--force is specified, branch will not let you set a
472 Unless -f/--force is specified, branch will not let you set a
473 branch name that already exists, even if it's inactive.
473 branch name that already exists, even if it's inactive.
474
474
475 Use -C/--clean to reset the working directory branch to that of
475 Use -C/--clean to reset the working directory branch to that of
476 the parent of the working directory, negating a previous branch
476 the parent of the working directory, negating a previous branch
477 change.
477 change.
478
478
479 Use the command :hg:`update` to switch to an existing branch. Use
479 Use the command :hg:`update` to switch to an existing branch. Use
480 :hg:`commit --close-branch` to mark this branch as closed.
480 :hg:`commit --close-branch` to mark this branch as closed.
481
481
482 Returns 0 on success.
482 Returns 0 on success.
483 """
483 """
484
484
485 if opts.get('clean'):
485 if opts.get('clean'):
486 label = repo[None].parents()[0].branch()
486 label = repo[None].parents()[0].branch()
487 repo.dirstate.setbranch(label)
487 repo.dirstate.setbranch(label)
488 ui.status(_('reset working directory to branch %s\n') % label)
488 ui.status(_('reset working directory to branch %s\n') % label)
489 elif label:
489 elif label:
490 utflabel = encoding.fromlocal(label)
490 utflabel = encoding.fromlocal(label)
491 if not opts.get('force') and utflabel in repo.branchtags():
491 if not opts.get('force') and utflabel in repo.branchtags():
492 if label not in [p.branch() for p in repo.parents()]:
492 if label not in [p.branch() for p in repo.parents()]:
493 raise util.Abort(_('a branch of the same name already exists'
493 raise util.Abort(_('a branch of the same name already exists'
494 " (use 'hg update' to switch to it)"))
494 " (use 'hg update' to switch to it)"))
495 repo.dirstate.setbranch(utflabel)
495 repo.dirstate.setbranch(utflabel)
496 ui.status(_('marked working directory as branch %s\n') % label)
496 ui.status(_('marked working directory as branch %s\n') % label)
497 else:
497 else:
498 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
498 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
499
499
500 def branches(ui, repo, active=False, closed=False):
500 def branches(ui, repo, active=False, closed=False):
501 """list repository named branches
501 """list repository named branches
502
502
503 List the repository's named branches, indicating which ones are
503 List the repository's named branches, indicating which ones are
504 inactive. If -c/--closed is specified, also list branches which have
504 inactive. If -c/--closed is specified, also list branches which have
505 been marked closed (see :hg:`commit --close-branch`).
505 been marked closed (see :hg:`commit --close-branch`).
506
506
507 If -a/--active is specified, only show active branches. A branch
507 If -a/--active is specified, only show active branches. A branch
508 is considered active if it contains repository heads.
508 is considered active if it contains repository heads.
509
509
510 Use the command :hg:`update` to switch to an existing branch.
510 Use the command :hg:`update` to switch to an existing branch.
511
511
512 Returns 0.
512 Returns 0.
513 """
513 """
514
514
515 hexfunc = ui.debugflag and hex or short
515 hexfunc = ui.debugflag and hex or short
516 activebranches = [repo[n].branch() for n in repo.heads()]
516 activebranches = [repo[n].branch() for n in repo.heads()]
517 def testactive(tag, node):
517 def testactive(tag, node):
518 realhead = tag in activebranches
518 realhead = tag in activebranches
519 open = node in repo.branchheads(tag, closed=False)
519 open = node in repo.branchheads(tag, closed=False)
520 return realhead and open
520 return realhead and open
521 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
521 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
522 for tag, node in repo.branchtags().items()],
522 for tag, node in repo.branchtags().items()],
523 reverse=True)
523 reverse=True)
524
524
525 for isactive, node, tag in branches:
525 for isactive, node, tag in branches:
526 if (not active) or isactive:
526 if (not active) or isactive:
527 encodedtag = encoding.tolocal(tag)
527 encodedtag = encoding.tolocal(tag)
528 if ui.quiet:
528 if ui.quiet:
529 ui.write("%s\n" % encodedtag)
529 ui.write("%s\n" % encodedtag)
530 else:
530 else:
531 hn = repo.lookup(node)
531 hn = repo.lookup(node)
532 if isactive:
532 if isactive:
533 label = 'branches.active'
533 label = 'branches.active'
534 notice = ''
534 notice = ''
535 elif hn not in repo.branchheads(tag, closed=False):
535 elif hn not in repo.branchheads(tag, closed=False):
536 if not closed:
536 if not closed:
537 continue
537 continue
538 label = 'branches.closed'
538 label = 'branches.closed'
539 notice = _(' (closed)')
539 notice = _(' (closed)')
540 else:
540 else:
541 label = 'branches.inactive'
541 label = 'branches.inactive'
542 notice = _(' (inactive)')
542 notice = _(' (inactive)')
543 if tag == repo.dirstate.branch():
543 if tag == repo.dirstate.branch():
544 label = 'branches.current'
544 label = 'branches.current'
545 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
545 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
546 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
546 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
547 encodedtag = ui.label(encodedtag, label)
547 encodedtag = ui.label(encodedtag, label)
548 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
548 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
549
549
550 def bundle(ui, repo, fname, dest=None, **opts):
550 def bundle(ui, repo, fname, dest=None, **opts):
551 """create a changegroup file
551 """create a changegroup file
552
552
553 Generate a compressed changegroup file collecting changesets not
553 Generate a compressed changegroup file collecting changesets not
554 known to be in another repository.
554 known to be in another repository.
555
555
556 If you omit the destination repository, then hg assumes the
556 If you omit the destination repository, then hg assumes the
557 destination will have all the nodes you specify with --base
557 destination will have all the nodes you specify with --base
558 parameters. To create a bundle containing all changesets, use
558 parameters. To create a bundle containing all changesets, use
559 -a/--all (or --base null).
559 -a/--all (or --base null).
560
560
561 You can change compression method with the -t/--type option.
561 You can change compression method with the -t/--type option.
562 The available compression methods are: none, bzip2, and
562 The available compression methods are: none, bzip2, and
563 gzip (by default, bundles are compressed using bzip2).
563 gzip (by default, bundles are compressed using bzip2).
564
564
565 The bundle file can then be transferred using conventional means
565 The bundle file can then be transferred using conventional means
566 and applied to another repository with the unbundle or pull
566 and applied to another repository with the unbundle or pull
567 command. This is useful when direct push and pull are not
567 command. This is useful when direct push and pull are not
568 available or when exporting an entire repository is undesirable.
568 available or when exporting an entire repository is undesirable.
569
569
570 Applying bundles preserves all changeset contents including
570 Applying bundles preserves all changeset contents including
571 permissions, copy/rename information, and revision history.
571 permissions, copy/rename information, and revision history.
572
572
573 Returns 0 on success, 1 if no changes found.
573 Returns 0 on success, 1 if no changes found.
574 """
574 """
575 revs = opts.get('rev') or None
575 revs = opts.get('rev') or None
576 if opts.get('all'):
576 if opts.get('all'):
577 base = ['null']
577 base = ['null']
578 else:
578 else:
579 base = opts.get('base')
579 base = opts.get('base')
580 if base:
580 if base:
581 if dest:
581 if dest:
582 raise util.Abort(_("--base is incompatible with specifying "
582 raise util.Abort(_("--base is incompatible with specifying "
583 "a destination"))
583 "a destination"))
584 base = [repo.lookup(rev) for rev in base]
584 base = [repo.lookup(rev) for rev in base]
585 # create the right base
585 # create the right base
586 # XXX: nodesbetween / changegroup* should be "fixed" instead
586 # XXX: nodesbetween / changegroup* should be "fixed" instead
587 o = []
587 o = []
588 has = set((nullid,))
588 has = set((nullid,))
589 for n in base:
589 for n in base:
590 has.update(repo.changelog.reachable(n))
590 has.update(repo.changelog.reachable(n))
591 if revs:
591 if revs:
592 revs = [repo.lookup(rev) for rev in revs]
592 revs = [repo.lookup(rev) for rev in revs]
593 visit = revs[:]
593 visit = revs[:]
594 has.difference_update(visit)
594 has.difference_update(visit)
595 else:
595 else:
596 visit = repo.changelog.heads()
596 visit = repo.changelog.heads()
597 seen = {}
597 seen = {}
598 while visit:
598 while visit:
599 n = visit.pop(0)
599 n = visit.pop(0)
600 parents = [p for p in repo.changelog.parents(n) if p not in has]
600 parents = [p for p in repo.changelog.parents(n) if p not in has]
601 if len(parents) == 0:
601 if len(parents) == 0:
602 if n not in has:
602 if n not in has:
603 o.append(n)
603 o.append(n)
604 else:
604 else:
605 for p in parents:
605 for p in parents:
606 if p not in seen:
606 if p not in seen:
607 seen[p] = 1
607 seen[p] = 1
608 visit.append(p)
608 visit.append(p)
609 else:
609 else:
610 dest = ui.expandpath(dest or 'default-push', dest or 'default')
610 dest = ui.expandpath(dest or 'default-push', dest or 'default')
611 dest, branches = hg.parseurl(dest, opts.get('branch'))
611 dest, branches = hg.parseurl(dest, opts.get('branch'))
612 other = hg.repository(hg.remoteui(repo, opts), dest)
612 other = hg.repository(hg.remoteui(repo, opts), dest)
613 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
613 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
614 if revs:
614 if revs:
615 revs = [repo.lookup(rev) for rev in revs]
615 revs = [repo.lookup(rev) for rev in revs]
616 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
616 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
617
617
618 if not o:
618 if not o:
619 ui.status(_("no changes found\n"))
619 ui.status(_("no changes found\n"))
620 return 1
620 return 1
621
621
622 if revs:
622 if revs:
623 cg = repo.changegroupsubset(o, revs, 'bundle')
623 cg = repo.changegroupsubset(o, revs, 'bundle')
624 else:
624 else:
625 cg = repo.changegroup(o, 'bundle')
625 cg = repo.changegroup(o, 'bundle')
626
626
627 bundletype = opts.get('type', 'bzip2').lower()
627 bundletype = opts.get('type', 'bzip2').lower()
628 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
628 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
629 bundletype = btypes.get(bundletype)
629 bundletype = btypes.get(bundletype)
630 if bundletype not in changegroup.bundletypes:
630 if bundletype not in changegroup.bundletypes:
631 raise util.Abort(_('unknown bundle type specified with --type'))
631 raise util.Abort(_('unknown bundle type specified with --type'))
632
632
633 changegroup.writebundle(cg, fname, bundletype)
633 changegroup.writebundle(cg, fname, bundletype)
634
634
635 def cat(ui, repo, file1, *pats, **opts):
635 def cat(ui, repo, file1, *pats, **opts):
636 """output the current or given revision of files
636 """output the current or given revision of files
637
637
638 Print the specified files as they were at the given revision. If
638 Print the specified files as they were at the given revision. If
639 no revision is given, the parent of the working directory is used,
639 no revision is given, the parent of the working directory is used,
640 or tip if no revision is checked out.
640 or tip if no revision is checked out.
641
641
642 Output may be to a file, in which case the name of the file is
642 Output may be to a file, in which case the name of the file is
643 given using a format string. The formatting rules are the same as
643 given using a format string. The formatting rules are the same as
644 for the export command, with the following additions:
644 for the export command, with the following additions:
645
645
646 :``%s``: basename of file being printed
646 :``%s``: basename of file being printed
647 :``%d``: dirname of file being printed, or '.' if in repository root
647 :``%d``: dirname of file being printed, or '.' if in repository root
648 :``%p``: root-relative path name of file being printed
648 :``%p``: root-relative path name of file being printed
649
649
650 Returns 0 on success.
650 Returns 0 on success.
651 """
651 """
652 ctx = cmdutil.revsingle(repo, opts.get('rev'))
652 ctx = cmdutil.revsingle(repo, opts.get('rev'))
653 err = 1
653 err = 1
654 m = cmdutil.match(repo, (file1,) + pats, opts)
654 m = cmdutil.match(repo, (file1,) + pats, opts)
655 for abs in ctx.walk(m):
655 for abs in ctx.walk(m):
656 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
656 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
657 data = ctx[abs].data()
657 data = ctx[abs].data()
658 if opts.get('decode'):
658 if opts.get('decode'):
659 data = repo.wwritedata(abs, data)
659 data = repo.wwritedata(abs, data)
660 fp.write(data)
660 fp.write(data)
661 err = 0
661 err = 0
662 return err
662 return err
663
663
664 def clone(ui, source, dest=None, **opts):
664 def clone(ui, source, dest=None, **opts):
665 """make a copy of an existing repository
665 """make a copy of an existing repository
666
666
667 Create a copy of an existing repository in a new directory.
667 Create a copy of an existing repository in a new directory.
668
668
669 If no destination directory name is specified, it defaults to the
669 If no destination directory name is specified, it defaults to the
670 basename of the source.
670 basename of the source.
671
671
672 The location of the source is added to the new repository's
672 The location of the source is added to the new repository's
673 .hg/hgrc file, as the default to be used for future pulls.
673 .hg/hgrc file, as the default to be used for future pulls.
674
674
675 See :hg:`help urls` for valid source format details.
675 See :hg:`help urls` for valid source format details.
676
676
677 It is possible to specify an ``ssh://`` URL as the destination, but no
677 It is possible to specify an ``ssh://`` URL as the destination, but no
678 .hg/hgrc and working directory will be created on the remote side.
678 .hg/hgrc and working directory will be created on the remote side.
679 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
679 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
680
680
681 A set of changesets (tags, or branch names) to pull may be specified
681 A set of changesets (tags, or branch names) to pull may be specified
682 by listing each changeset (tag, or branch name) with -r/--rev.
682 by listing each changeset (tag, or branch name) with -r/--rev.
683 If -r/--rev is used, the cloned repository will contain only a subset
683 If -r/--rev is used, the cloned repository will contain only a subset
684 of the changesets of the source repository. Only the set of changesets
684 of the changesets of the source repository. Only the set of changesets
685 defined by all -r/--rev options (including all their ancestors)
685 defined by all -r/--rev options (including all their ancestors)
686 will be pulled into the destination repository.
686 will be pulled into the destination repository.
687 No subsequent changesets (including subsequent tags) will be present
687 No subsequent changesets (including subsequent tags) will be present
688 in the destination.
688 in the destination.
689
689
690 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
690 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
691 local source repositories.
691 local source repositories.
692
692
693 For efficiency, hardlinks are used for cloning whenever the source
693 For efficiency, hardlinks are used for cloning whenever the source
694 and destination are on the same filesystem (note this applies only
694 and destination are on the same filesystem (note this applies only
695 to the repository data, not to the working directory). Some
695 to the repository data, not to the working directory). Some
696 filesystems, such as AFS, implement hardlinking incorrectly, but
696 filesystems, such as AFS, implement hardlinking incorrectly, but
697 do not report errors. In these cases, use the --pull option to
697 do not report errors. In these cases, use the --pull option to
698 avoid hardlinking.
698 avoid hardlinking.
699
699
700 In some cases, you can clone repositories and the working directory
700 In some cases, you can clone repositories and the working directory
701 using full hardlinks with ::
701 using full hardlinks with ::
702
702
703 $ cp -al REPO REPOCLONE
703 $ cp -al REPO REPOCLONE
704
704
705 This is the fastest way to clone, but it is not always safe. The
705 This is the fastest way to clone, but it is not always safe. The
706 operation is not atomic (making sure REPO is not modified during
706 operation is not atomic (making sure REPO is not modified during
707 the operation is up to you) and you have to make sure your editor
707 the operation is up to you) and you have to make sure your editor
708 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
708 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
709 this is not compatible with certain extensions that place their
709 this is not compatible with certain extensions that place their
710 metadata under the .hg directory, such as mq.
710 metadata under the .hg directory, such as mq.
711
711
712 Mercurial will update the working directory to the first applicable
712 Mercurial will update the working directory to the first applicable
713 revision from this list:
713 revision from this list:
714
714
715 a) null if -U or the source repository has no changesets
715 a) null if -U or the source repository has no changesets
716 b) if -u . and the source repository is local, the first parent of
716 b) if -u . and the source repository is local, the first parent of
717 the source repository's working directory
717 the source repository's working directory
718 c) the changeset specified with -u (if a branch name, this means the
718 c) the changeset specified with -u (if a branch name, this means the
719 latest head of that branch)
719 latest head of that branch)
720 d) the changeset specified with -r
720 d) the changeset specified with -r
721 e) the tipmost head specified with -b
721 e) the tipmost head specified with -b
722 f) the tipmost head specified with the url#branch source syntax
722 f) the tipmost head specified with the url#branch source syntax
723 g) the tipmost head of the default branch
723 g) the tipmost head of the default branch
724 h) tip
724 h) tip
725
725
726 Returns 0 on success.
726 Returns 0 on success.
727 """
727 """
728 if opts.get('noupdate') and opts.get('updaterev'):
728 if opts.get('noupdate') and opts.get('updaterev'):
729 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
729 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
730
730
731 r = hg.clone(hg.remoteui(ui, opts), source, dest,
731 r = hg.clone(hg.remoteui(ui, opts), source, dest,
732 pull=opts.get('pull'),
732 pull=opts.get('pull'),
733 stream=opts.get('uncompressed'),
733 stream=opts.get('uncompressed'),
734 rev=opts.get('rev'),
734 rev=opts.get('rev'),
735 update=opts.get('updaterev') or not opts.get('noupdate'),
735 update=opts.get('updaterev') or not opts.get('noupdate'),
736 branch=opts.get('branch'))
736 branch=opts.get('branch'))
737
737
738 return r is None
738 return r is None
739
739
740 def commit(ui, repo, *pats, **opts):
740 def commit(ui, repo, *pats, **opts):
741 """commit the specified files or all outstanding changes
741 """commit the specified files or all outstanding changes
742
742
743 Commit changes to the given files into the repository. Unlike a
743 Commit changes to the given files into the repository. Unlike a
744 centralized RCS, this operation is a local operation. See
744 centralized RCS, this operation is a local operation. See
745 :hg:`push` for a way to actively distribute your changes.
745 :hg:`push` for a way to actively distribute your changes.
746
746
747 If a list of files is omitted, all changes reported by :hg:`status`
747 If a list of files is omitted, all changes reported by :hg:`status`
748 will be committed.
748 will be committed.
749
749
750 If you are committing the result of a merge, do not provide any
750 If you are committing the result of a merge, do not provide any
751 filenames or -I/-X filters.
751 filenames or -I/-X filters.
752
752
753 If no commit message is specified, Mercurial starts your
753 If no commit message is specified, Mercurial starts your
754 configured editor where you can enter a message. In case your
754 configured editor where you can enter a message. In case your
755 commit fails, you will find a backup of your message in
755 commit fails, you will find a backup of your message in
756 ``.hg/last-message.txt``.
756 ``.hg/last-message.txt``.
757
757
758 See :hg:`help dates` for a list of formats valid for -d/--date.
758 See :hg:`help dates` for a list of formats valid for -d/--date.
759
759
760 Returns 0 on success, 1 if nothing changed.
760 Returns 0 on success, 1 if nothing changed.
761 """
761 """
762 extra = {}
762 extra = {}
763 if opts.get('close_branch'):
763 if opts.get('close_branch'):
764 if repo['.'].node() not in repo.branchheads():
764 if repo['.'].node() not in repo.branchheads():
765 # The topo heads set is included in the branch heads set of the
765 # The topo heads set is included in the branch heads set of the
766 # current branch, so it's sufficient to test branchheads
766 # current branch, so it's sufficient to test branchheads
767 raise util.Abort(_('can only close branch heads'))
767 raise util.Abort(_('can only close branch heads'))
768 extra['close'] = 1
768 extra['close'] = 1
769 e = cmdutil.commiteditor
769 e = cmdutil.commiteditor
770 if opts.get('force_editor'):
770 if opts.get('force_editor'):
771 e = cmdutil.commitforceeditor
771 e = cmdutil.commitforceeditor
772
772
773 def commitfunc(ui, repo, message, match, opts):
773 def commitfunc(ui, repo, message, match, opts):
774 return repo.commit(message, opts.get('user'), opts.get('date'), match,
774 return repo.commit(message, opts.get('user'), opts.get('date'), match,
775 editor=e, extra=extra)
775 editor=e, extra=extra)
776
776
777 branch = repo[None].branch()
777 branch = repo[None].branch()
778 bheads = repo.branchheads(branch)
778 bheads = repo.branchheads(branch)
779
779
780 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
780 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
781 if not node:
781 if not node:
782 ui.status(_("nothing changed\n"))
782 ui.status(_("nothing changed\n"))
783 return 1
783 return 1
784
784
785 ctx = repo[node]
785 ctx = repo[node]
786 parents = ctx.parents()
786 parents = ctx.parents()
787
787
788 if bheads and not [x for x in parents
788 if bheads and not [x for x in parents
789 if x.node() in bheads and x.branch() == branch]:
789 if x.node() in bheads and x.branch() == branch]:
790 ui.status(_('created new head\n'))
790 ui.status(_('created new head\n'))
791 # The message is not printed for initial roots. For the other
791 # The message is not printed for initial roots. For the other
792 # changesets, it is printed in the following situations:
792 # changesets, it is printed in the following situations:
793 #
793 #
794 # Par column: for the 2 parents with ...
794 # Par column: for the 2 parents with ...
795 # N: null or no parent
795 # N: null or no parent
796 # B: parent is on another named branch
796 # B: parent is on another named branch
797 # C: parent is a regular non head changeset
797 # C: parent is a regular non head changeset
798 # H: parent was a branch head of the current branch
798 # H: parent was a branch head of the current branch
799 # Msg column: whether we print "created new head" message
799 # Msg column: whether we print "created new head" message
800 # In the following, it is assumed that there already exists some
800 # In the following, it is assumed that there already exists some
801 # initial branch heads of the current branch, otherwise nothing is
801 # initial branch heads of the current branch, otherwise nothing is
802 # printed anyway.
802 # printed anyway.
803 #
803 #
804 # Par Msg Comment
804 # Par Msg Comment
805 # NN y additional topo root
805 # NN y additional topo root
806 #
806 #
807 # BN y additional branch root
807 # BN y additional branch root
808 # CN y additional topo head
808 # CN y additional topo head
809 # HN n usual case
809 # HN n usual case
810 #
810 #
811 # BB y weird additional branch root
811 # BB y weird additional branch root
812 # CB y branch merge
812 # CB y branch merge
813 # HB n merge with named branch
813 # HB n merge with named branch
814 #
814 #
815 # CC y additional head from merge
815 # CC y additional head from merge
816 # CH n merge with a head
816 # CH n merge with a head
817 #
817 #
818 # HH n head merge: head count decreases
818 # HH n head merge: head count decreases
819
819
820 if not opts.get('close_branch'):
820 if not opts.get('close_branch'):
821 for r in parents:
821 for r in parents:
822 if r.extra().get('close') and r.branch() == branch:
822 if r.extra().get('close') and r.branch() == branch:
823 ui.status(_('reopening closed branch head %d\n') % r)
823 ui.status(_('reopening closed branch head %d\n') % r)
824
824
825 if ui.debugflag:
825 if ui.debugflag:
826 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
826 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
827 elif ui.verbose:
827 elif ui.verbose:
828 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
828 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
829
829
830 def copy(ui, repo, *pats, **opts):
830 def copy(ui, repo, *pats, **opts):
831 """mark files as copied for the next commit
831 """mark files as copied for the next commit
832
832
833 Mark dest as having copies of source files. If dest is a
833 Mark dest as having copies of source files. If dest is a
834 directory, copies are put in that directory. If dest is a file,
834 directory, copies are put in that directory. If dest is a file,
835 the source must be a single file.
835 the source must be a single file.
836
836
837 By default, this command copies the contents of files as they
837 By default, this command copies the contents of files as they
838 exist in the working directory. If invoked with -A/--after, the
838 exist in the working directory. If invoked with -A/--after, the
839 operation is recorded, but no copying is performed.
839 operation is recorded, but no copying is performed.
840
840
841 This command takes effect with the next commit. To undo a copy
841 This command takes effect with the next commit. To undo a copy
842 before that, see :hg:`revert`.
842 before that, see :hg:`revert`.
843
843
844 Returns 0 on success, 1 if errors are encountered.
844 Returns 0 on success, 1 if errors are encountered.
845 """
845 """
846 wlock = repo.wlock(False)
846 wlock = repo.wlock(False)
847 try:
847 try:
848 return cmdutil.copy(ui, repo, pats, opts)
848 return cmdutil.copy(ui, repo, pats, opts)
849 finally:
849 finally:
850 wlock.release()
850 wlock.release()
851
851
852 def debugancestor(ui, repo, *args):
852 def debugancestor(ui, repo, *args):
853 """find the ancestor revision of two revisions in a given index"""
853 """find the ancestor revision of two revisions in a given index"""
854 if len(args) == 3:
854 if len(args) == 3:
855 index, rev1, rev2 = args
855 index, rev1, rev2 = args
856 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
856 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
857 lookup = r.lookup
857 lookup = r.lookup
858 elif len(args) == 2:
858 elif len(args) == 2:
859 if not repo:
859 if not repo:
860 raise util.Abort(_("there is no Mercurial repository here "
860 raise util.Abort(_("there is no Mercurial repository here "
861 "(.hg not found)"))
861 "(.hg not found)"))
862 rev1, rev2 = args
862 rev1, rev2 = args
863 r = repo.changelog
863 r = repo.changelog
864 lookup = repo.lookup
864 lookup = repo.lookup
865 else:
865 else:
866 raise util.Abort(_('either two or three arguments required'))
866 raise util.Abort(_('either two or three arguments required'))
867 a = r.ancestor(lookup(rev1), lookup(rev2))
867 a = r.ancestor(lookup(rev1), lookup(rev2))
868 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
868 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
869
869
870 def debugbuilddag(ui, repo, text,
870 def debugbuilddag(ui, repo, text,
871 mergeable_file=False,
871 mergeable_file=False,
872 appended_file=False,
872 appended_file=False,
873 overwritten_file=False,
873 overwritten_file=False,
874 new_file=False):
874 new_file=False):
875 """builds a repo with a given dag from scratch in the current empty repo
875 """builds a repo with a given dag from scratch in the current empty repo
876
876
877 Elements:
877 Elements:
878
878
879 - "+n" is a linear run of n nodes based on the current default parent
879 - "+n" is a linear run of n nodes based on the current default parent
880 - "." is a single node based on the current default parent
880 - "." is a single node based on the current default parent
881 - "$" resets the default parent to null (implied at the start);
881 - "$" resets the default parent to null (implied at the start);
882 otherwise the default parent is always the last node created
882 otherwise the default parent is always the last node created
883 - "<p" sets the default parent to the backref p
883 - "<p" sets the default parent to the backref p
884 - "*p" is a fork at parent p, which is a backref
884 - "*p" is a fork at parent p, which is a backref
885 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
885 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
886 - "/p2" is a merge of the preceding node and p2
886 - "/p2" is a merge of the preceding node and p2
887 - ":tag" defines a local tag for the preceding node
887 - ":tag" defines a local tag for the preceding node
888 - "@branch" sets the named branch for subsequent nodes
888 - "@branch" sets the named branch for subsequent nodes
889 - "!command" runs the command using your shell
889 - "!command" runs the command using your shell
890 - "!!my command\\n" is like "!", but to the end of the line
890 - "!!my command\\n" is like "!", but to the end of the line
891 - "#...\\n" is a comment up to the end of the line
891 - "#...\\n" is a comment up to the end of the line
892
892
893 Whitespace between the above elements is ignored.
893 Whitespace between the above elements is ignored.
894
894
895 A backref is either
895 A backref is either
896
896
897 - a number n, which references the node curr-n, where curr is the current
897 - a number n, which references the node curr-n, where curr is the current
898 node, or
898 node, or
899 - the name of a local tag you placed earlier using ":tag", or
899 - the name of a local tag you placed earlier using ":tag", or
900 - empty to denote the default parent.
900 - empty to denote the default parent.
901
901
902 All string valued-elements are either strictly alphanumeric, or must
902 All string valued-elements are either strictly alphanumeric, or must
903 be enclosed in double quotes ("..."), with "\\" as escape character.
903 be enclosed in double quotes ("..."), with "\\" as escape character.
904
904
905 Note that the --overwritten-file and --appended-file options imply the
905 Note that the --overwritten-file and --appended-file options imply the
906 use of "HGMERGE=internal:local" during DAG buildup.
906 use of "HGMERGE=internal:local" during DAG buildup.
907 """
907 """
908
908
909 if not (mergeable_file or appended_file or overwritten_file or new_file):
909 if not (mergeable_file or appended_file or overwritten_file or new_file):
910 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
910 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
911
911
912 if len(repo.changelog) > 0:
912 if len(repo.changelog) > 0:
913 raise util.Abort(_('repository is not empty'))
913 raise util.Abort(_('repository is not empty'))
914
914
915 if overwritten_file or appended_file:
915 if overwritten_file or appended_file:
916 # we don't want to fail in merges during buildup
916 # we don't want to fail in merges during buildup
917 os.environ['HGMERGE'] = 'internal:local'
917 os.environ['HGMERGE'] = 'internal:local'
918
918
919 def writefile(fname, text, fmode="wb"):
919 def writefile(fname, text, fmode="wb"):
920 f = open(fname, fmode)
920 f = open(fname, fmode)
921 try:
921 try:
922 f.write(text)
922 f.write(text)
923 finally:
923 finally:
924 f.close()
924 f.close()
925
925
926 if mergeable_file:
926 if mergeable_file:
927 linesperrev = 2
927 linesperrev = 2
928 # determine number of revs in DAG
928 # determine number of revs in DAG
929 n = 0
929 n = 0
930 for type, data in dagparser.parsedag(text):
930 for type, data in dagparser.parsedag(text):
931 if type == 'n':
931 if type == 'n':
932 n += 1
932 n += 1
933 # make a file with k lines per rev
933 # make a file with k lines per rev
934 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
934 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
935 + "\n")
935 + "\n")
936
936
937 at = -1
937 at = -1
938 atbranch = 'default'
938 atbranch = 'default'
939 for type, data in dagparser.parsedag(text):
939 for type, data in dagparser.parsedag(text):
940 if type == 'n':
940 if type == 'n':
941 ui.status('node %s\n' % str(data))
941 ui.status('node %s\n' % str(data))
942 id, ps = data
942 id, ps = data
943 p1 = ps[0]
943 p1 = ps[0]
944 if p1 != at:
944 if p1 != at:
945 update(ui, repo, node=str(p1), clean=True)
945 update(ui, repo, node=str(p1), clean=True)
946 at = p1
946 at = p1
947 if repo.dirstate.branch() != atbranch:
947 if repo.dirstate.branch() != atbranch:
948 branch(ui, repo, atbranch, force=True)
948 branch(ui, repo, atbranch, force=True)
949 if len(ps) > 1:
949 if len(ps) > 1:
950 p2 = ps[1]
950 p2 = ps[1]
951 merge(ui, repo, node=p2)
951 merge(ui, repo, node=p2)
952
952
953 if mergeable_file:
953 if mergeable_file:
954 f = open("mf", "rb+")
954 f = open("mf", "rb+")
955 try:
955 try:
956 lines = f.read().split("\n")
956 lines = f.read().split("\n")
957 lines[id * linesperrev] += " r%i" % id
957 lines[id * linesperrev] += " r%i" % id
958 f.seek(0)
958 f.seek(0)
959 f.write("\n".join(lines))
959 f.write("\n".join(lines))
960 finally:
960 finally:
961 f.close()
961 f.close()
962
962
963 if appended_file:
963 if appended_file:
964 writefile("af", "r%i\n" % id, "ab")
964 writefile("af", "r%i\n" % id, "ab")
965
965
966 if overwritten_file:
966 if overwritten_file:
967 writefile("of", "r%i\n" % id)
967 writefile("of", "r%i\n" % id)
968
968
969 if new_file:
969 if new_file:
970 writefile("nf%i" % id, "r%i\n" % id)
970 writefile("nf%i" % id, "r%i\n" % id)
971
971
972 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
972 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
973 at = id
973 at = id
974 elif type == 'l':
974 elif type == 'l':
975 id, name = data
975 id, name = data
976 ui.status('tag %s\n' % name)
976 ui.status('tag %s\n' % name)
977 tag(ui, repo, name, local=True)
977 tag(ui, repo, name, local=True)
978 elif type == 'a':
978 elif type == 'a':
979 ui.status('branch %s\n' % data)
979 ui.status('branch %s\n' % data)
980 atbranch = data
980 atbranch = data
981 elif type in 'cC':
981 elif type in 'cC':
982 r = util.system(data, cwd=repo.root)
982 r = util.system(data, cwd=repo.root)
983 if r:
983 if r:
984 desc, r = util.explain_exit(r)
984 desc, r = util.explain_exit(r)
985 raise util.Abort(_('%s command %s') % (data, desc))
985 raise util.Abort(_('%s command %s') % (data, desc))
986
986
987 def debugcommands(ui, cmd='', *args):
987 def debugcommands(ui, cmd='', *args):
988 """list all available commands and options"""
988 """list all available commands and options"""
989 for cmd, vals in sorted(table.iteritems()):
989 for cmd, vals in sorted(table.iteritems()):
990 cmd = cmd.split('|')[0].strip('^')
990 cmd = cmd.split('|')[0].strip('^')
991 opts = ', '.join([i[1] for i in vals[1]])
991 opts = ', '.join([i[1] for i in vals[1]])
992 ui.write('%s: %s\n' % (cmd, opts))
992 ui.write('%s: %s\n' % (cmd, opts))
993
993
994 def debugcomplete(ui, cmd='', **opts):
994 def debugcomplete(ui, cmd='', **opts):
995 """returns the completion list associated with the given command"""
995 """returns the completion list associated with the given command"""
996
996
997 if opts.get('options'):
997 if opts.get('options'):
998 options = []
998 options = []
999 otables = [globalopts]
999 otables = [globalopts]
1000 if cmd:
1000 if cmd:
1001 aliases, entry = cmdutil.findcmd(cmd, table, False)
1001 aliases, entry = cmdutil.findcmd(cmd, table, False)
1002 otables.append(entry[1])
1002 otables.append(entry[1])
1003 for t in otables:
1003 for t in otables:
1004 for o in t:
1004 for o in t:
1005 if "(DEPRECATED)" in o[3]:
1005 if "(DEPRECATED)" in o[3]:
1006 continue
1006 continue
1007 if o[0]:
1007 if o[0]:
1008 options.append('-%s' % o[0])
1008 options.append('-%s' % o[0])
1009 options.append('--%s' % o[1])
1009 options.append('--%s' % o[1])
1010 ui.write("%s\n" % "\n".join(options))
1010 ui.write("%s\n" % "\n".join(options))
1011 return
1011 return
1012
1012
1013 cmdlist = cmdutil.findpossible(cmd, table)
1013 cmdlist = cmdutil.findpossible(cmd, table)
1014 if ui.verbose:
1014 if ui.verbose:
1015 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1015 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1016 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1016 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1017
1017
1018 def debugfsinfo(ui, path = "."):
1018 def debugfsinfo(ui, path = "."):
1019 """show information detected about current filesystem"""
1019 """show information detected about current filesystem"""
1020 open('.debugfsinfo', 'w').write('')
1020 open('.debugfsinfo', 'w').write('')
1021 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1021 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1022 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1022 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1023 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1023 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1024 and 'yes' or 'no'))
1024 and 'yes' or 'no'))
1025 os.unlink('.debugfsinfo')
1025 os.unlink('.debugfsinfo')
1026
1026
1027 def debugrebuildstate(ui, repo, rev="tip"):
1027 def debugrebuildstate(ui, repo, rev="tip"):
1028 """rebuild the dirstate as it would look like for the given revision"""
1028 """rebuild the dirstate as it would look like for the given revision"""
1029 ctx = repo[rev]
1029 ctx = repo[rev]
1030 wlock = repo.wlock()
1030 wlock = repo.wlock()
1031 try:
1031 try:
1032 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1032 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1033 finally:
1033 finally:
1034 wlock.release()
1034 wlock.release()
1035
1035
1036 def debugcheckstate(ui, repo):
1036 def debugcheckstate(ui, repo):
1037 """validate the correctness of the current dirstate"""
1037 """validate the correctness of the current dirstate"""
1038 parent1, parent2 = repo.dirstate.parents()
1038 parent1, parent2 = repo.dirstate.parents()
1039 m1 = repo[parent1].manifest()
1039 m1 = repo[parent1].manifest()
1040 m2 = repo[parent2].manifest()
1040 m2 = repo[parent2].manifest()
1041 errors = 0
1041 errors = 0
1042 for f in repo.dirstate:
1042 for f in repo.dirstate:
1043 state = repo.dirstate[f]
1043 state = repo.dirstate[f]
1044 if state in "nr" and f not in m1:
1044 if state in "nr" and f not in m1:
1045 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1045 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1046 errors += 1
1046 errors += 1
1047 if state in "a" and f in m1:
1047 if state in "a" and f in m1:
1048 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1048 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1049 errors += 1
1049 errors += 1
1050 if state in "m" and f not in m1 and f not in m2:
1050 if state in "m" and f not in m1 and f not in m2:
1051 ui.warn(_("%s in state %s, but not in either manifest\n") %
1051 ui.warn(_("%s in state %s, but not in either manifest\n") %
1052 (f, state))
1052 (f, state))
1053 errors += 1
1053 errors += 1
1054 for f in m1:
1054 for f in m1:
1055 state = repo.dirstate[f]
1055 state = repo.dirstate[f]
1056 if state not in "nrm":
1056 if state not in "nrm":
1057 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1057 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1058 errors += 1
1058 errors += 1
1059 if errors:
1059 if errors:
1060 error = _(".hg/dirstate inconsistent with current parent's manifest")
1060 error = _(".hg/dirstate inconsistent with current parent's manifest")
1061 raise util.Abort(error)
1061 raise util.Abort(error)
1062
1062
1063 def showconfig(ui, repo, *values, **opts):
1063 def showconfig(ui, repo, *values, **opts):
1064 """show combined config settings from all hgrc files
1064 """show combined config settings from all hgrc files
1065
1065
1066 With no arguments, print names and values of all config items.
1066 With no arguments, print names and values of all config items.
1067
1067
1068 With one argument of the form section.name, print just the value
1068 With one argument of the form section.name, print just the value
1069 of that config item.
1069 of that config item.
1070
1070
1071 With multiple arguments, print names and values of all config
1071 With multiple arguments, print names and values of all config
1072 items with matching section names.
1072 items with matching section names.
1073
1073
1074 With --debug, the source (filename and line number) is printed
1074 With --debug, the source (filename and line number) is printed
1075 for each config item.
1075 for each config item.
1076
1076
1077 Returns 0 on success.
1077 Returns 0 on success.
1078 """
1078 """
1079
1079
1080 for f in util.rcpath():
1080 for f in util.rcpath():
1081 ui.debug(_('read config from: %s\n') % f)
1081 ui.debug(_('read config from: %s\n') % f)
1082 untrusted = bool(opts.get('untrusted'))
1082 untrusted = bool(opts.get('untrusted'))
1083 if values:
1083 if values:
1084 sections = [v for v in values if '.' not in v]
1084 sections = [v for v in values if '.' not in v]
1085 items = [v for v in values if '.' in v]
1085 items = [v for v in values if '.' in v]
1086 if len(items) > 1 or items and sections:
1086 if len(items) > 1 or items and sections:
1087 raise util.Abort(_('only one config item permitted'))
1087 raise util.Abort(_('only one config item permitted'))
1088 for section, name, value in ui.walkconfig(untrusted=untrusted):
1088 for section, name, value in ui.walkconfig(untrusted=untrusted):
1089 sectname = section + '.' + name
1089 sectname = section + '.' + name
1090 if values:
1090 if values:
1091 for v in values:
1091 for v in values:
1092 if v == section:
1092 if v == section:
1093 ui.debug('%s: ' %
1093 ui.debug('%s: ' %
1094 ui.configsource(section, name, untrusted))
1094 ui.configsource(section, name, untrusted))
1095 ui.write('%s=%s\n' % (sectname, value))
1095 ui.write('%s=%s\n' % (sectname, value))
1096 elif v == sectname:
1096 elif v == sectname:
1097 ui.debug('%s: ' %
1097 ui.debug('%s: ' %
1098 ui.configsource(section, name, untrusted))
1098 ui.configsource(section, name, untrusted))
1099 ui.write(value, '\n')
1099 ui.write(value, '\n')
1100 else:
1100 else:
1101 ui.debug('%s: ' %
1101 ui.debug('%s: ' %
1102 ui.configsource(section, name, untrusted))
1102 ui.configsource(section, name, untrusted))
1103 ui.write('%s=%s\n' % (sectname, value))
1103 ui.write('%s=%s\n' % (sectname, value))
1104
1104
1105 def debugpushkey(ui, repopath, namespace, *keyinfo):
1105 def debugpushkey(ui, repopath, namespace, *keyinfo):
1106 '''access the pushkey key/value protocol
1106 '''access the pushkey key/value protocol
1107
1107
1108 With two args, list the keys in the given namespace.
1108 With two args, list the keys in the given namespace.
1109
1109
1110 With five args, set a key to new if it currently is set to old.
1110 With five args, set a key to new if it currently is set to old.
1111 Reports success or failure.
1111 Reports success or failure.
1112 '''
1112 '''
1113
1113
1114 target = hg.repository(ui, repopath)
1114 target = hg.repository(ui, repopath)
1115 if keyinfo:
1115 if keyinfo:
1116 key, old, new = keyinfo
1116 key, old, new = keyinfo
1117 r = target.pushkey(namespace, key, old, new)
1117 r = target.pushkey(namespace, key, old, new)
1118 ui.status(str(r) + '\n')
1118 ui.status(str(r) + '\n')
1119 return not(r)
1119 return not(r)
1120 else:
1120 else:
1121 for k, v in target.listkeys(namespace).iteritems():
1121 for k, v in target.listkeys(namespace).iteritems():
1122 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1122 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1123 v.encode('string-escape')))
1123 v.encode('string-escape')))
1124
1124
1125 def debugrevspec(ui, repo, expr):
1125 def debugrevspec(ui, repo, expr):
1126 '''parse and apply a revision specification'''
1126 '''parse and apply a revision specification'''
1127 if ui.verbose:
1127 if ui.verbose:
1128 tree = revset.parse(expr)
1128 tree = revset.parse(expr)
1129 ui.note(tree, "\n")
1129 ui.note(tree, "\n")
1130 func = revset.match(expr)
1130 func = revset.match(expr)
1131 for c in func(repo, range(len(repo))):
1131 for c in func(repo, range(len(repo))):
1132 ui.write("%s\n" % c)
1132 ui.write("%s\n" % c)
1133
1133
1134 def debugsetparents(ui, repo, rev1, rev2=None):
1134 def debugsetparents(ui, repo, rev1, rev2=None):
1135 """manually set the parents of the current working directory
1135 """manually set the parents of the current working directory
1136
1136
1137 This is useful for writing repository conversion tools, but should
1137 This is useful for writing repository conversion tools, but should
1138 be used with care.
1138 be used with care.
1139
1139
1140 Returns 0 on success.
1140 Returns 0 on success.
1141 """
1141 """
1142
1142
1143 if not rev2:
1143 if not rev2:
1144 rev2 = hex(nullid)
1144 rev2 = hex(nullid)
1145
1145
1146 wlock = repo.wlock()
1146 wlock = repo.wlock()
1147 try:
1147 try:
1148 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1148 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1149 finally:
1149 finally:
1150 wlock.release()
1150 wlock.release()
1151
1151
1152 def debugstate(ui, repo, nodates=None):
1152 def debugstate(ui, repo, nodates=None):
1153 """show the contents of the current dirstate"""
1153 """show the contents of the current dirstate"""
1154 timestr = ""
1154 timestr = ""
1155 showdate = not nodates
1155 showdate = not nodates
1156 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1156 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1157 if showdate:
1157 if showdate:
1158 if ent[3] == -1:
1158 if ent[3] == -1:
1159 # Pad or slice to locale representation
1159 # Pad or slice to locale representation
1160 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1160 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1161 time.localtime(0)))
1161 time.localtime(0)))
1162 timestr = 'unset'
1162 timestr = 'unset'
1163 timestr = (timestr[:locale_len] +
1163 timestr = (timestr[:locale_len] +
1164 ' ' * (locale_len - len(timestr)))
1164 ' ' * (locale_len - len(timestr)))
1165 else:
1165 else:
1166 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1166 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1167 time.localtime(ent[3]))
1167 time.localtime(ent[3]))
1168 if ent[1] & 020000:
1168 if ent[1] & 020000:
1169 mode = 'lnk'
1169 mode = 'lnk'
1170 else:
1170 else:
1171 mode = '%3o' % (ent[1] & 0777)
1171 mode = '%3o' % (ent[1] & 0777)
1172 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1172 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1173 for f in repo.dirstate.copies():
1173 for f in repo.dirstate.copies():
1174 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1174 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1175
1175
1176 def debugsub(ui, repo, rev=None):
1176 def debugsub(ui, repo, rev=None):
1177 if rev == '':
1177 if rev == '':
1178 rev = None
1178 rev = None
1179 for k, v in sorted(repo[rev].substate.items()):
1179 for k, v in sorted(repo[rev].substate.items()):
1180 ui.write('path %s\n' % k)
1180 ui.write('path %s\n' % k)
1181 ui.write(' source %s\n' % v[0])
1181 ui.write(' source %s\n' % v[0])
1182 ui.write(' revision %s\n' % v[1])
1182 ui.write(' revision %s\n' % v[1])
1183
1183
1184 def debugdag(ui, repo, file_=None, *revs, **opts):
1184 def debugdag(ui, repo, file_=None, *revs, **opts):
1185 """format the changelog or an index DAG as a concise textual description
1185 """format the changelog or an index DAG as a concise textual description
1186
1186
1187 If you pass a revlog index, the revlog's DAG is emitted. If you list
1187 If you pass a revlog index, the revlog's DAG is emitted. If you list
1188 revision numbers, they get labelled in the output as rN.
1188 revision numbers, they get labelled in the output as rN.
1189
1189
1190 Otherwise, the changelog DAG of the current repo is emitted.
1190 Otherwise, the changelog DAG of the current repo is emitted.
1191 """
1191 """
1192 spaces = opts.get('spaces')
1192 spaces = opts.get('spaces')
1193 dots = opts.get('dots')
1193 dots = opts.get('dots')
1194 if file_:
1194 if file_:
1195 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1195 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1196 revs = set((int(r) for r in revs))
1196 revs = set((int(r) for r in revs))
1197 def events():
1197 def events():
1198 for r in rlog:
1198 for r in rlog:
1199 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1199 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1200 if r in revs:
1200 if r in revs:
1201 yield 'l', (r, "r%i" % r)
1201 yield 'l', (r, "r%i" % r)
1202 elif repo:
1202 elif repo:
1203 cl = repo.changelog
1203 cl = repo.changelog
1204 tags = opts.get('tags')
1204 tags = opts.get('tags')
1205 branches = opts.get('branches')
1205 branches = opts.get('branches')
1206 if tags:
1206 if tags:
1207 labels = {}
1207 labels = {}
1208 for l, n in repo.tags().items():
1208 for l, n in repo.tags().items():
1209 labels.setdefault(cl.rev(n), []).append(l)
1209 labels.setdefault(cl.rev(n), []).append(l)
1210 def events():
1210 def events():
1211 b = "default"
1211 b = "default"
1212 for r in cl:
1212 for r in cl:
1213 if branches:
1213 if branches:
1214 newb = cl.read(cl.node(r))[5]['branch']
1214 newb = cl.read(cl.node(r))[5]['branch']
1215 if newb != b:
1215 if newb != b:
1216 yield 'a', newb
1216 yield 'a', newb
1217 b = newb
1217 b = newb
1218 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1218 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1219 if tags:
1219 if tags:
1220 ls = labels.get(r)
1220 ls = labels.get(r)
1221 if ls:
1221 if ls:
1222 for l in ls:
1222 for l in ls:
1223 yield 'l', (r, l)
1223 yield 'l', (r, l)
1224 else:
1224 else:
1225 raise util.Abort(_('need repo for changelog dag'))
1225 raise util.Abort(_('need repo for changelog dag'))
1226
1226
1227 for line in dagparser.dagtextlines(events(),
1227 for line in dagparser.dagtextlines(events(),
1228 addspaces=spaces,
1228 addspaces=spaces,
1229 wraplabels=True,
1229 wraplabels=True,
1230 wrapannotations=True,
1230 wrapannotations=True,
1231 wrapnonlinear=dots,
1231 wrapnonlinear=dots,
1232 usedots=dots,
1232 usedots=dots,
1233 maxlinewidth=70):
1233 maxlinewidth=70):
1234 ui.write(line)
1234 ui.write(line)
1235 ui.write("\n")
1235 ui.write("\n")
1236
1236
1237 def debugdata(ui, repo, file_, rev):
1237 def debugdata(ui, repo, file_, rev):
1238 """dump the contents of a data file revision"""
1238 """dump the contents of a data file revision"""
1239 r = None
1239 r = None
1240 if repo:
1240 if repo:
1241 filelog = repo.file(file_)
1241 filelog = repo.file(file_)
1242 if len(filelog):
1242 if len(filelog):
1243 r = filelog
1243 r = filelog
1244 if not r:
1244 if not r:
1245 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1245 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1246 try:
1246 try:
1247 ui.write(r.revision(r.lookup(rev)))
1247 ui.write(r.revision(r.lookup(rev)))
1248 except KeyError:
1248 except KeyError:
1249 raise util.Abort(_('invalid revision identifier %s') % rev)
1249 raise util.Abort(_('invalid revision identifier %s') % rev)
1250
1250
1251 def debugdate(ui, date, range=None, **opts):
1251 def debugdate(ui, date, range=None, **opts):
1252 """parse and display a date"""
1252 """parse and display a date"""
1253 if opts["extended"]:
1253 if opts["extended"]:
1254 d = util.parsedate(date, util.extendeddateformats)
1254 d = util.parsedate(date, util.extendeddateformats)
1255 else:
1255 else:
1256 d = util.parsedate(date)
1256 d = util.parsedate(date)
1257 ui.write("internal: %s %s\n" % d)
1257 ui.write("internal: %s %s\n" % d)
1258 ui.write("standard: %s\n" % util.datestr(d))
1258 ui.write("standard: %s\n" % util.datestr(d))
1259 if range:
1259 if range:
1260 m = util.matchdate(range)
1260 m = util.matchdate(range)
1261 ui.write("match: %s\n" % m(d[0]))
1261 ui.write("match: %s\n" % m(d[0]))
1262
1262
1263 def debugindex(ui, repo, file_, **opts):
1263 def debugindex(ui, repo, file_, **opts):
1264 """dump the contents of an index file"""
1264 """dump the contents of an index file"""
1265 r = None
1265 r = None
1266 if repo:
1266 if repo:
1267 filelog = repo.file(file_)
1267 filelog = repo.file(file_)
1268 if len(filelog):
1268 if len(filelog):
1269 r = filelog
1269 r = filelog
1270
1270
1271 format = opts.get('format', 0)
1271 format = opts.get('format', 0)
1272 if format not in (0, 1):
1272 if format not in (0, 1):
1273 raise util.Abort("unknown format %d" % format)
1273 raise util.Abort("unknown format %d" % format)
1274
1274
1275 if not r:
1275 if not r:
1276 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1276 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1277
1277
1278 if format == 0:
1278 if format == 0:
1279 ui.write(" rev offset length base linkrev"
1279 ui.write(" rev offset length base linkrev"
1280 " nodeid p1 p2\n")
1280 " nodeid p1 p2\n")
1281 elif format == 1:
1281 elif format == 1:
1282 ui.write(" rev flag offset length"
1282 ui.write(" rev flag offset length"
1283 " size base link p1 p2 nodeid\n")
1283 " size base link p1 p2 nodeid\n")
1284
1284
1285 for i in r:
1285 for i in r:
1286 node = r.node(i)
1286 node = r.node(i)
1287 if format == 0:
1287 if format == 0:
1288 try:
1288 try:
1289 pp = r.parents(node)
1289 pp = r.parents(node)
1290 except:
1290 except:
1291 pp = [nullid, nullid]
1291 pp = [nullid, nullid]
1292 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1292 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1293 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1293 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1294 short(node), short(pp[0]), short(pp[1])))
1294 short(node), short(pp[0]), short(pp[1])))
1295 elif format == 1:
1295 elif format == 1:
1296 pr = r.parentrevs(i)
1296 pr = r.parentrevs(i)
1297 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1297 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1298 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1298 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1299 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1299 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1300
1300
1301 def debugindexdot(ui, repo, file_):
1301 def debugindexdot(ui, repo, file_):
1302 """dump an index DAG as a graphviz dot file"""
1302 """dump an index DAG as a graphviz dot file"""
1303 r = None
1303 r = None
1304 if repo:
1304 if repo:
1305 filelog = repo.file(file_)
1305 filelog = repo.file(file_)
1306 if len(filelog):
1306 if len(filelog):
1307 r = filelog
1307 r = filelog
1308 if not r:
1308 if not r:
1309 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1309 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1310 ui.write("digraph G {\n")
1310 ui.write("digraph G {\n")
1311 for i in r:
1311 for i in r:
1312 node = r.node(i)
1312 node = r.node(i)
1313 pp = r.parents(node)
1313 pp = r.parents(node)
1314 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1314 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1315 if pp[1] != nullid:
1315 if pp[1] != nullid:
1316 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1316 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1317 ui.write("}\n")
1317 ui.write("}\n")
1318
1318
1319 def debuginstall(ui):
1319 def debuginstall(ui):
1320 '''test Mercurial installation
1320 '''test Mercurial installation
1321
1321
1322 Returns 0 on success.
1322 Returns 0 on success.
1323 '''
1323 '''
1324
1324
1325 def writetemp(contents):
1325 def writetemp(contents):
1326 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1326 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1327 f = os.fdopen(fd, "wb")
1327 f = os.fdopen(fd, "wb")
1328 f.write(contents)
1328 f.write(contents)
1329 f.close()
1329 f.close()
1330 return name
1330 return name
1331
1331
1332 problems = 0
1332 problems = 0
1333
1333
1334 # encoding
1334 # encoding
1335 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1335 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1336 try:
1336 try:
1337 encoding.fromlocal("test")
1337 encoding.fromlocal("test")
1338 except util.Abort, inst:
1338 except util.Abort, inst:
1339 ui.write(" %s\n" % inst)
1339 ui.write(" %s\n" % inst)
1340 ui.write(_(" (check that your locale is properly set)\n"))
1340 ui.write(_(" (check that your locale is properly set)\n"))
1341 problems += 1
1341 problems += 1
1342
1342
1343 # compiled modules
1343 # compiled modules
1344 ui.status(_("Checking installed modules (%s)...\n")
1344 ui.status(_("Checking installed modules (%s)...\n")
1345 % os.path.dirname(__file__))
1345 % os.path.dirname(__file__))
1346 try:
1346 try:
1347 import bdiff, mpatch, base85, osutil
1347 import bdiff, mpatch, base85, osutil
1348 except Exception, inst:
1348 except Exception, inst:
1349 ui.write(" %s\n" % inst)
1349 ui.write(" %s\n" % inst)
1350 ui.write(_(" One or more extensions could not be found"))
1350 ui.write(_(" One or more extensions could not be found"))
1351 ui.write(_(" (check that you compiled the extensions)\n"))
1351 ui.write(_(" (check that you compiled the extensions)\n"))
1352 problems += 1
1352 problems += 1
1353
1353
1354 # templates
1354 # templates
1355 ui.status(_("Checking templates...\n"))
1355 ui.status(_("Checking templates...\n"))
1356 try:
1356 try:
1357 import templater
1357 import templater
1358 templater.templater(templater.templatepath("map-cmdline.default"))
1358 templater.templater(templater.templatepath("map-cmdline.default"))
1359 except Exception, inst:
1359 except Exception, inst:
1360 ui.write(" %s\n" % inst)
1360 ui.write(" %s\n" % inst)
1361 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1361 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1362 problems += 1
1362 problems += 1
1363
1363
1364 # patch
1364 # patch
1365 ui.status(_("Checking patch...\n"))
1365 ui.status(_("Checking patch...\n"))
1366 patchproblems = 0
1366 patchproblems = 0
1367 a = "1\n2\n3\n4\n"
1367 a = "1\n2\n3\n4\n"
1368 b = "1\n2\n3\ninsert\n4\n"
1368 b = "1\n2\n3\ninsert\n4\n"
1369 fa = writetemp(a)
1369 fa = writetemp(a)
1370 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1370 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1371 os.path.basename(fa))
1371 os.path.basename(fa))
1372 fd = writetemp(d)
1372 fd = writetemp(d)
1373
1373
1374 files = {}
1374 files = {}
1375 try:
1375 try:
1376 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1376 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1377 except util.Abort, e:
1377 except util.Abort, e:
1378 ui.write(_(" patch call failed:\n"))
1378 ui.write(_(" patch call failed:\n"))
1379 ui.write(" " + str(e) + "\n")
1379 ui.write(" " + str(e) + "\n")
1380 patchproblems += 1
1380 patchproblems += 1
1381 else:
1381 else:
1382 if list(files) != [os.path.basename(fa)]:
1382 if list(files) != [os.path.basename(fa)]:
1383 ui.write(_(" unexpected patch output!\n"))
1383 ui.write(_(" unexpected patch output!\n"))
1384 patchproblems += 1
1384 patchproblems += 1
1385 a = open(fa).read()
1385 a = open(fa).read()
1386 if a != b:
1386 if a != b:
1387 ui.write(_(" patch test failed!\n"))
1387 ui.write(_(" patch test failed!\n"))
1388 patchproblems += 1
1388 patchproblems += 1
1389
1389
1390 if patchproblems:
1390 if patchproblems:
1391 if ui.config('ui', 'patch'):
1391 if ui.config('ui', 'patch'):
1392 ui.write(_(" (Current patch tool may be incompatible with patch,"
1392 ui.write(_(" (Current patch tool may be incompatible with patch,"
1393 " or misconfigured. Please check your configuration"
1393 " or misconfigured. Please check your configuration"
1394 " file)\n"))
1394 " file)\n"))
1395 else:
1395 else:
1396 ui.write(_(" Internal patcher failure, please report this error"
1396 ui.write(_(" Internal patcher failure, please report this error"
1397 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1397 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1398 problems += patchproblems
1398 problems += patchproblems
1399
1399
1400 os.unlink(fa)
1400 os.unlink(fa)
1401 os.unlink(fd)
1401 os.unlink(fd)
1402
1402
1403 # editor
1403 # editor
1404 ui.status(_("Checking commit editor...\n"))
1404 ui.status(_("Checking commit editor...\n"))
1405 editor = ui.geteditor()
1405 editor = ui.geteditor()
1406 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1406 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1407 if not cmdpath:
1407 if not cmdpath:
1408 if editor == 'vi':
1408 if editor == 'vi':
1409 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1409 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1410 ui.write(_(" (specify a commit editor in your configuration"
1410 ui.write(_(" (specify a commit editor in your configuration"
1411 " file)\n"))
1411 " file)\n"))
1412 else:
1412 else:
1413 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1413 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1414 ui.write(_(" (specify a commit editor in your configuration"
1414 ui.write(_(" (specify a commit editor in your configuration"
1415 " file)\n"))
1415 " file)\n"))
1416 problems += 1
1416 problems += 1
1417
1417
1418 # check username
1418 # check username
1419 ui.status(_("Checking username...\n"))
1419 ui.status(_("Checking username...\n"))
1420 try:
1420 try:
1421 ui.username()
1421 ui.username()
1422 except util.Abort, e:
1422 except util.Abort, e:
1423 ui.write(" %s\n" % e)
1423 ui.write(" %s\n" % e)
1424 ui.write(_(" (specify a username in your configuration file)\n"))
1424 ui.write(_(" (specify a username in your configuration file)\n"))
1425 problems += 1
1425 problems += 1
1426
1426
1427 if not problems:
1427 if not problems:
1428 ui.status(_("No problems detected\n"))
1428 ui.status(_("No problems detected\n"))
1429 else:
1429 else:
1430 ui.write(_("%s problems detected,"
1430 ui.write(_("%s problems detected,"
1431 " please check your install!\n") % problems)
1431 " please check your install!\n") % problems)
1432
1432
1433 return problems
1433 return problems
1434
1434
1435 def debugrename(ui, repo, file1, *pats, **opts):
1435 def debugrename(ui, repo, file1, *pats, **opts):
1436 """dump rename information"""
1436 """dump rename information"""
1437
1437
1438 ctx = repo[opts.get('rev')]
1438 ctx = repo[opts.get('rev')]
1439 m = cmdutil.match(repo, (file1,) + pats, opts)
1439 m = cmdutil.match(repo, (file1,) + pats, opts)
1440 for abs in ctx.walk(m):
1440 for abs in ctx.walk(m):
1441 fctx = ctx[abs]
1441 fctx = ctx[abs]
1442 o = fctx.filelog().renamed(fctx.filenode())
1442 o = fctx.filelog().renamed(fctx.filenode())
1443 rel = m.rel(abs)
1443 rel = m.rel(abs)
1444 if o:
1444 if o:
1445 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1445 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1446 else:
1446 else:
1447 ui.write(_("%s not renamed\n") % rel)
1447 ui.write(_("%s not renamed\n") % rel)
1448
1448
1449 def debugwalk(ui, repo, *pats, **opts):
1449 def debugwalk(ui, repo, *pats, **opts):
1450 """show how files match on given patterns"""
1450 """show how files match on given patterns"""
1451 m = cmdutil.match(repo, pats, opts)
1451 m = cmdutil.match(repo, pats, opts)
1452 items = list(repo.walk(m))
1452 items = list(repo.walk(m))
1453 if not items:
1453 if not items:
1454 return
1454 return
1455 fmt = 'f %%-%ds %%-%ds %%s' % (
1455 fmt = 'f %%-%ds %%-%ds %%s' % (
1456 max([len(abs) for abs in items]),
1456 max([len(abs) for abs in items]),
1457 max([len(m.rel(abs)) for abs in items]))
1457 max([len(m.rel(abs)) for abs in items]))
1458 for abs in items:
1458 for abs in items:
1459 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1459 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1460 ui.write("%s\n" % line.rstrip())
1460 ui.write("%s\n" % line.rstrip())
1461
1461
1462 def diff(ui, repo, *pats, **opts):
1462 def diff(ui, repo, *pats, **opts):
1463 """diff repository (or selected files)
1463 """diff repository (or selected files)
1464
1464
1465 Show differences between revisions for the specified files.
1465 Show differences between revisions for the specified files.
1466
1466
1467 Differences between files are shown using the unified diff format.
1467 Differences between files are shown using the unified diff format.
1468
1468
1469 .. note::
1469 .. note::
1470 diff may generate unexpected results for merges, as it will
1470 diff may generate unexpected results for merges, as it will
1471 default to comparing against the working directory's first
1471 default to comparing against the working directory's first
1472 parent changeset if no revisions are specified.
1472 parent changeset if no revisions are specified.
1473
1473
1474 When two revision arguments are given, then changes are shown
1474 When two revision arguments are given, then changes are shown
1475 between those revisions. If only one revision is specified then
1475 between those revisions. If only one revision is specified then
1476 that revision is compared to the working directory, and, when no
1476 that revision is compared to the working directory, and, when no
1477 revisions are specified, the working directory files are compared
1477 revisions are specified, the working directory files are compared
1478 to its parent.
1478 to its parent.
1479
1479
1480 Alternatively you can specify -c/--change with a revision to see
1480 Alternatively you can specify -c/--change with a revision to see
1481 the changes in that changeset relative to its first parent.
1481 the changes in that changeset relative to its first parent.
1482
1482
1483 Without the -a/--text option, diff will avoid generating diffs of
1483 Without the -a/--text option, diff will avoid generating diffs of
1484 files it detects as binary. With -a, diff will generate a diff
1484 files it detects as binary. With -a, diff will generate a diff
1485 anyway, probably with undesirable results.
1485 anyway, probably with undesirable results.
1486
1486
1487 Use the -g/--git option to generate diffs in the git extended diff
1487 Use the -g/--git option to generate diffs in the git extended diff
1488 format. For more information, read :hg:`help diffs`.
1488 format. For more information, read :hg:`help diffs`.
1489
1489
1490 Returns 0 on success.
1490 Returns 0 on success.
1491 """
1491 """
1492
1492
1493 revs = opts.get('rev')
1493 revs = opts.get('rev')
1494 change = opts.get('change')
1494 change = opts.get('change')
1495 stat = opts.get('stat')
1495 stat = opts.get('stat')
1496 reverse = opts.get('reverse')
1496 reverse = opts.get('reverse')
1497
1497
1498 if revs and change:
1498 if revs and change:
1499 msg = _('cannot specify --rev and --change at the same time')
1499 msg = _('cannot specify --rev and --change at the same time')
1500 raise util.Abort(msg)
1500 raise util.Abort(msg)
1501 elif change:
1501 elif change:
1502 node2 = repo.lookup(change)
1502 node2 = repo.lookup(change)
1503 node1 = repo[node2].parents()[0].node()
1503 node1 = repo[node2].parents()[0].node()
1504 else:
1504 else:
1505 node1, node2 = cmdutil.revpair(repo, revs)
1505 node1, node2 = cmdutil.revpair(repo, revs)
1506
1506
1507 if reverse:
1507 if reverse:
1508 node1, node2 = node2, node1
1508 node1, node2 = node2, node1
1509
1509
1510 diffopts = patch.diffopts(ui, opts)
1510 diffopts = patch.diffopts(ui, opts)
1511 m = cmdutil.match(repo, pats, opts)
1511 m = cmdutil.match(repo, pats, opts)
1512 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1512 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1513 listsubrepos=opts.get('subrepos'))
1513 listsubrepos=opts.get('subrepos'))
1514
1514
1515 def export(ui, repo, *changesets, **opts):
1515 def export(ui, repo, *changesets, **opts):
1516 """dump the header and diffs for one or more changesets
1516 """dump the header and diffs for one or more changesets
1517
1517
1518 Print the changeset header and diffs for one or more revisions.
1518 Print the changeset header and diffs for one or more revisions.
1519
1519
1520 The information shown in the changeset header is: author, date,
1520 The information shown in the changeset header is: author, date,
1521 branch name (if non-default), changeset hash, parent(s) and commit
1521 branch name (if non-default), changeset hash, parent(s) and commit
1522 comment.
1522 comment.
1523
1523
1524 .. note::
1524 .. note::
1525 export may generate unexpected diff output for merge
1525 export may generate unexpected diff output for merge
1526 changesets, as it will compare the merge changeset against its
1526 changesets, as it will compare the merge changeset against its
1527 first parent only.
1527 first parent only.
1528
1528
1529 Output may be to a file, in which case the name of the file is
1529 Output may be to a file, in which case the name of the file is
1530 given using a format string. The formatting rules are as follows:
1530 given using a format string. The formatting rules are as follows:
1531
1531
1532 :``%%``: literal "%" character
1532 :``%%``: literal "%" character
1533 :``%H``: changeset hash (40 hexadecimal digits)
1533 :``%H``: changeset hash (40 hexadecimal digits)
1534 :``%N``: number of patches being generated
1534 :``%N``: number of patches being generated
1535 :``%R``: changeset revision number
1535 :``%R``: changeset revision number
1536 :``%b``: basename of the exporting repository
1536 :``%b``: basename of the exporting repository
1537 :``%h``: short-form changeset hash (12 hexadecimal digits)
1537 :``%h``: short-form changeset hash (12 hexadecimal digits)
1538 :``%n``: zero-padded sequence number, starting at 1
1538 :``%n``: zero-padded sequence number, starting at 1
1539 :``%r``: zero-padded changeset revision number
1539 :``%r``: zero-padded changeset revision number
1540
1540
1541 Without the -a/--text option, export will avoid generating diffs
1541 Without the -a/--text option, export will avoid generating diffs
1542 of files it detects as binary. With -a, export will generate a
1542 of files it detects as binary. With -a, export will generate a
1543 diff anyway, probably with undesirable results.
1543 diff anyway, probably with undesirable results.
1544
1544
1545 Use the -g/--git option to generate diffs in the git extended diff
1545 Use the -g/--git option to generate diffs in the git extended diff
1546 format. See :hg:`help diffs` for more information.
1546 format. See :hg:`help diffs` for more information.
1547
1547
1548 With the --switch-parent option, the diff will be against the
1548 With the --switch-parent option, the diff will be against the
1549 second parent. It can be useful to review a merge.
1549 second parent. It can be useful to review a merge.
1550
1550
1551 Returns 0 on success.
1551 Returns 0 on success.
1552 """
1552 """
1553 changesets += tuple(opts.get('rev', []))
1553 changesets += tuple(opts.get('rev', []))
1554 if not changesets:
1554 if not changesets:
1555 raise util.Abort(_("export requires at least one changeset"))
1555 raise util.Abort(_("export requires at least one changeset"))
1556 revs = cmdutil.revrange(repo, changesets)
1556 revs = cmdutil.revrange(repo, changesets)
1557 if len(revs) > 1:
1557 if len(revs) > 1:
1558 ui.note(_('exporting patches:\n'))
1558 ui.note(_('exporting patches:\n'))
1559 else:
1559 else:
1560 ui.note(_('exporting patch:\n'))
1560 ui.note(_('exporting patch:\n'))
1561 cmdutil.export(repo, revs, template=opts.get('output'),
1561 cmdutil.export(repo, revs, template=opts.get('output'),
1562 switch_parent=opts.get('switch_parent'),
1562 switch_parent=opts.get('switch_parent'),
1563 opts=patch.diffopts(ui, opts))
1563 opts=patch.diffopts(ui, opts))
1564
1564
1565 def forget(ui, repo, *pats, **opts):
1565 def forget(ui, repo, *pats, **opts):
1566 """forget the specified files on the next commit
1566 """forget the specified files on the next commit
1567
1567
1568 Mark the specified files so they will no longer be tracked
1568 Mark the specified files so they will no longer be tracked
1569 after the next commit.
1569 after the next commit.
1570
1570
1571 This only removes files from the current branch, not from the
1571 This only removes files from the current branch, not from the
1572 entire project history, and it does not delete them from the
1572 entire project history, and it does not delete them from the
1573 working directory.
1573 working directory.
1574
1574
1575 To undo a forget before the next commit, see :hg:`add`.
1575 To undo a forget before the next commit, see :hg:`add`.
1576
1576
1577 Returns 0 on success.
1577 Returns 0 on success.
1578 """
1578 """
1579
1579
1580 if not pats:
1580 if not pats:
1581 raise util.Abort(_('no files specified'))
1581 raise util.Abort(_('no files specified'))
1582
1582
1583 m = cmdutil.match(repo, pats, opts)
1583 m = cmdutil.match(repo, pats, opts)
1584 s = repo.status(match=m, clean=True)
1584 s = repo.status(match=m, clean=True)
1585 forget = sorted(s[0] + s[1] + s[3] + s[6])
1585 forget = sorted(s[0] + s[1] + s[3] + s[6])
1586 errs = 0
1586 errs = 0
1587
1587
1588 for f in m.files():
1588 for f in m.files():
1589 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1589 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1590 ui.warn(_('not removing %s: file is already untracked\n')
1590 ui.warn(_('not removing %s: file is already untracked\n')
1591 % m.rel(f))
1591 % m.rel(f))
1592 errs = 1
1592 errs = 1
1593
1593
1594 for f in forget:
1594 for f in forget:
1595 if ui.verbose or not m.exact(f):
1595 if ui.verbose or not m.exact(f):
1596 ui.status(_('removing %s\n') % m.rel(f))
1596 ui.status(_('removing %s\n') % m.rel(f))
1597
1597
1598 repo[None].remove(forget, unlink=False)
1598 repo[None].remove(forget, unlink=False)
1599 return errs
1599 return errs
1600
1600
1601 def grep(ui, repo, pattern, *pats, **opts):
1601 def grep(ui, repo, pattern, *pats, **opts):
1602 """search for a pattern in specified files and revisions
1602 """search for a pattern in specified files and revisions
1603
1603
1604 Search revisions of files for a regular expression.
1604 Search revisions of files for a regular expression.
1605
1605
1606 This command behaves differently than Unix grep. It only accepts
1606 This command behaves differently than Unix grep. It only accepts
1607 Python/Perl regexps. It searches repository history, not the
1607 Python/Perl regexps. It searches repository history, not the
1608 working directory. It always prints the revision number in which a
1608 working directory. It always prints the revision number in which a
1609 match appears.
1609 match appears.
1610
1610
1611 By default, grep only prints output for the first revision of a
1611 By default, grep only prints output for the first revision of a
1612 file in which it finds a match. To get it to print every revision
1612 file in which it finds a match. To get it to print every revision
1613 that contains a change in match status ("-" for a match that
1613 that contains a change in match status ("-" for a match that
1614 becomes a non-match, or "+" for a non-match that becomes a match),
1614 becomes a non-match, or "+" for a non-match that becomes a match),
1615 use the --all flag.
1615 use the --all flag.
1616
1616
1617 Returns 0 if a match is found, 1 otherwise.
1617 Returns 0 if a match is found, 1 otherwise.
1618 """
1618 """
1619 reflags = 0
1619 reflags = 0
1620 if opts.get('ignore_case'):
1620 if opts.get('ignore_case'):
1621 reflags |= re.I
1621 reflags |= re.I
1622 try:
1622 try:
1623 regexp = re.compile(pattern, reflags)
1623 regexp = re.compile(pattern, reflags)
1624 except re.error, inst:
1624 except re.error, inst:
1625 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1625 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1626 return 1
1626 return 1
1627 sep, eol = ':', '\n'
1627 sep, eol = ':', '\n'
1628 if opts.get('print0'):
1628 if opts.get('print0'):
1629 sep = eol = '\0'
1629 sep = eol = '\0'
1630
1630
1631 getfile = util.lrucachefunc(repo.file)
1631 getfile = util.lrucachefunc(repo.file)
1632
1632
1633 def matchlines(body):
1633 def matchlines(body):
1634 begin = 0
1634 begin = 0
1635 linenum = 0
1635 linenum = 0
1636 while True:
1636 while True:
1637 match = regexp.search(body, begin)
1637 match = regexp.search(body, begin)
1638 if not match:
1638 if not match:
1639 break
1639 break
1640 mstart, mend = match.span()
1640 mstart, mend = match.span()
1641 linenum += body.count('\n', begin, mstart) + 1
1641 linenum += body.count('\n', begin, mstart) + 1
1642 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1642 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1643 begin = body.find('\n', mend) + 1 or len(body)
1643 begin = body.find('\n', mend) + 1 or len(body)
1644 lend = begin - 1
1644 lend = begin - 1
1645 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1645 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1646
1646
1647 class linestate(object):
1647 class linestate(object):
1648 def __init__(self, line, linenum, colstart, colend):
1648 def __init__(self, line, linenum, colstart, colend):
1649 self.line = line
1649 self.line = line
1650 self.linenum = linenum
1650 self.linenum = linenum
1651 self.colstart = colstart
1651 self.colstart = colstart
1652 self.colend = colend
1652 self.colend = colend
1653
1653
1654 def __hash__(self):
1654 def __hash__(self):
1655 return hash((self.linenum, self.line))
1655 return hash((self.linenum, self.line))
1656
1656
1657 def __eq__(self, other):
1657 def __eq__(self, other):
1658 return self.line == other.line
1658 return self.line == other.line
1659
1659
1660 matches = {}
1660 matches = {}
1661 copies = {}
1661 copies = {}
1662 def grepbody(fn, rev, body):
1662 def grepbody(fn, rev, body):
1663 matches[rev].setdefault(fn, [])
1663 matches[rev].setdefault(fn, [])
1664 m = matches[rev][fn]
1664 m = matches[rev][fn]
1665 for lnum, cstart, cend, line in matchlines(body):
1665 for lnum, cstart, cend, line in matchlines(body):
1666 s = linestate(line, lnum, cstart, cend)
1666 s = linestate(line, lnum, cstart, cend)
1667 m.append(s)
1667 m.append(s)
1668
1668
1669 def difflinestates(a, b):
1669 def difflinestates(a, b):
1670 sm = difflib.SequenceMatcher(None, a, b)
1670 sm = difflib.SequenceMatcher(None, a, b)
1671 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1671 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1672 if tag == 'insert':
1672 if tag == 'insert':
1673 for i in xrange(blo, bhi):
1673 for i in xrange(blo, bhi):
1674 yield ('+', b[i])
1674 yield ('+', b[i])
1675 elif tag == 'delete':
1675 elif tag == 'delete':
1676 for i in xrange(alo, ahi):
1676 for i in xrange(alo, ahi):
1677 yield ('-', a[i])
1677 yield ('-', a[i])
1678 elif tag == 'replace':
1678 elif tag == 'replace':
1679 for i in xrange(alo, ahi):
1679 for i in xrange(alo, ahi):
1680 yield ('-', a[i])
1680 yield ('-', a[i])
1681 for i in xrange(blo, bhi):
1681 for i in xrange(blo, bhi):
1682 yield ('+', b[i])
1682 yield ('+', b[i])
1683
1683
1684 def display(fn, ctx, pstates, states):
1684 def display(fn, ctx, pstates, states):
1685 rev = ctx.rev()
1685 rev = ctx.rev()
1686 datefunc = ui.quiet and util.shortdate or util.datestr
1686 datefunc = ui.quiet and util.shortdate or util.datestr
1687 found = False
1687 found = False
1688 filerevmatches = {}
1688 filerevmatches = {}
1689 if opts.get('all'):
1689 if opts.get('all'):
1690 iter = difflinestates(pstates, states)
1690 iter = difflinestates(pstates, states)
1691 else:
1691 else:
1692 iter = [('', l) for l in states]
1692 iter = [('', l) for l in states]
1693 for change, l in iter:
1693 for change, l in iter:
1694 cols = [fn, str(rev)]
1694 cols = [fn, str(rev)]
1695 before, match, after = None, None, None
1695 before, match, after = None, None, None
1696 if opts.get('line_number'):
1696 if opts.get('line_number'):
1697 cols.append(str(l.linenum))
1697 cols.append(str(l.linenum))
1698 if opts.get('all'):
1698 if opts.get('all'):
1699 cols.append(change)
1699 cols.append(change)
1700 if opts.get('user'):
1700 if opts.get('user'):
1701 cols.append(ui.shortuser(ctx.user()))
1701 cols.append(ui.shortuser(ctx.user()))
1702 if opts.get('date'):
1702 if opts.get('date'):
1703 cols.append(datefunc(ctx.date()))
1703 cols.append(datefunc(ctx.date()))
1704 if opts.get('files_with_matches'):
1704 if opts.get('files_with_matches'):
1705 c = (fn, rev)
1705 c = (fn, rev)
1706 if c in filerevmatches:
1706 if c in filerevmatches:
1707 continue
1707 continue
1708 filerevmatches[c] = 1
1708 filerevmatches[c] = 1
1709 else:
1709 else:
1710 before = l.line[:l.colstart]
1710 before = l.line[:l.colstart]
1711 match = l.line[l.colstart:l.colend]
1711 match = l.line[l.colstart:l.colend]
1712 after = l.line[l.colend:]
1712 after = l.line[l.colend:]
1713 ui.write(sep.join(cols))
1713 ui.write(sep.join(cols))
1714 if before is not None:
1714 if before is not None:
1715 ui.write(sep + before)
1715 ui.write(sep + before)
1716 ui.write(match, label='grep.match')
1716 ui.write(match, label='grep.match')
1717 ui.write(after)
1717 ui.write(after)
1718 ui.write(eol)
1718 ui.write(eol)
1719 found = True
1719 found = True
1720 return found
1720 return found
1721
1721
1722 skip = {}
1722 skip = {}
1723 revfiles = {}
1723 revfiles = {}
1724 matchfn = cmdutil.match(repo, pats, opts)
1724 matchfn = cmdutil.match(repo, pats, opts)
1725 found = False
1725 found = False
1726 follow = opts.get('follow')
1726 follow = opts.get('follow')
1727
1727
1728 def prep(ctx, fns):
1728 def prep(ctx, fns):
1729 rev = ctx.rev()
1729 rev = ctx.rev()
1730 pctx = ctx.parents()[0]
1730 pctx = ctx.parents()[0]
1731 parent = pctx.rev()
1731 parent = pctx.rev()
1732 matches.setdefault(rev, {})
1732 matches.setdefault(rev, {})
1733 matches.setdefault(parent, {})
1733 matches.setdefault(parent, {})
1734 files = revfiles.setdefault(rev, [])
1734 files = revfiles.setdefault(rev, [])
1735 for fn in fns:
1735 for fn in fns:
1736 flog = getfile(fn)
1736 flog = getfile(fn)
1737 try:
1737 try:
1738 fnode = ctx.filenode(fn)
1738 fnode = ctx.filenode(fn)
1739 except error.LookupError:
1739 except error.LookupError:
1740 continue
1740 continue
1741
1741
1742 copied = flog.renamed(fnode)
1742 copied = flog.renamed(fnode)
1743 copy = follow and copied and copied[0]
1743 copy = follow and copied and copied[0]
1744 if copy:
1744 if copy:
1745 copies.setdefault(rev, {})[fn] = copy
1745 copies.setdefault(rev, {})[fn] = copy
1746 if fn in skip:
1746 if fn in skip:
1747 if copy:
1747 if copy:
1748 skip[copy] = True
1748 skip[copy] = True
1749 continue
1749 continue
1750 files.append(fn)
1750 files.append(fn)
1751
1751
1752 if fn not in matches[rev]:
1752 if fn not in matches[rev]:
1753 grepbody(fn, rev, flog.read(fnode))
1753 grepbody(fn, rev, flog.read(fnode))
1754
1754
1755 pfn = copy or fn
1755 pfn = copy or fn
1756 if pfn not in matches[parent]:
1756 if pfn not in matches[parent]:
1757 try:
1757 try:
1758 fnode = pctx.filenode(pfn)
1758 fnode = pctx.filenode(pfn)
1759 grepbody(pfn, parent, flog.read(fnode))
1759 grepbody(pfn, parent, flog.read(fnode))
1760 except error.LookupError:
1760 except error.LookupError:
1761 pass
1761 pass
1762
1762
1763 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1763 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1764 rev = ctx.rev()
1764 rev = ctx.rev()
1765 parent = ctx.parents()[0].rev()
1765 parent = ctx.parents()[0].rev()
1766 for fn in sorted(revfiles.get(rev, [])):
1766 for fn in sorted(revfiles.get(rev, [])):
1767 states = matches[rev][fn]
1767 states = matches[rev][fn]
1768 copy = copies.get(rev, {}).get(fn)
1768 copy = copies.get(rev, {}).get(fn)
1769 if fn in skip:
1769 if fn in skip:
1770 if copy:
1770 if copy:
1771 skip[copy] = True
1771 skip[copy] = True
1772 continue
1772 continue
1773 pstates = matches.get(parent, {}).get(copy or fn, [])
1773 pstates = matches.get(parent, {}).get(copy or fn, [])
1774 if pstates or states:
1774 if pstates or states:
1775 r = display(fn, ctx, pstates, states)
1775 r = display(fn, ctx, pstates, states)
1776 found = found or r
1776 found = found or r
1777 if r and not opts.get('all'):
1777 if r and not opts.get('all'):
1778 skip[fn] = True
1778 skip[fn] = True
1779 if copy:
1779 if copy:
1780 skip[copy] = True
1780 skip[copy] = True
1781 del matches[rev]
1781 del matches[rev]
1782 del revfiles[rev]
1782 del revfiles[rev]
1783
1783
1784 return not found
1784 return not found
1785
1785
1786 def heads(ui, repo, *branchrevs, **opts):
1786 def heads(ui, repo, *branchrevs, **opts):
1787 """show current repository heads or show branch heads
1787 """show current repository heads or show branch heads
1788
1788
1789 With no arguments, show all repository branch heads.
1789 With no arguments, show all repository branch heads.
1790
1790
1791 Repository "heads" are changesets with no child changesets. They are
1791 Repository "heads" are changesets with no child changesets. They are
1792 where development generally takes place and are the usual targets
1792 where development generally takes place and are the usual targets
1793 for update and merge operations. Branch heads are changesets that have
1793 for update and merge operations. Branch heads are changesets that have
1794 no child changeset on the same branch.
1794 no child changeset on the same branch.
1795
1795
1796 If one or more REVs are given, only branch heads on the branches
1796 If one or more REVs are given, only branch heads on the branches
1797 associated with the specified changesets are shown.
1797 associated with the specified changesets are shown.
1798
1798
1799 If -c/--closed is specified, also show branch heads marked closed
1799 If -c/--closed is specified, also show branch heads marked closed
1800 (see :hg:`commit --close-branch`).
1800 (see :hg:`commit --close-branch`).
1801
1801
1802 If STARTREV is specified, only those heads that are descendants of
1802 If STARTREV is specified, only those heads that are descendants of
1803 STARTREV will be displayed.
1803 STARTREV will be displayed.
1804
1804
1805 If -t/--topo is specified, named branch mechanics will be ignored and only
1805 If -t/--topo is specified, named branch mechanics will be ignored and only
1806 changesets without children will be shown.
1806 changesets without children will be shown.
1807
1807
1808 Returns 0 if matching heads are found, 1 if not.
1808 Returns 0 if matching heads are found, 1 if not.
1809 """
1809 """
1810
1810
1811 if opts.get('rev'):
1811 if opts.get('rev'):
1812 start = repo.lookup(opts['rev'])
1812 start = repo.lookup(opts['rev'])
1813 else:
1813 else:
1814 start = None
1814 start = None
1815
1815
1816 if opts.get('topo'):
1816 if opts.get('topo'):
1817 heads = [repo[h] for h in repo.heads(start)]
1817 heads = [repo[h] for h in repo.heads(start)]
1818 else:
1818 else:
1819 heads = []
1819 heads = []
1820 for b, ls in repo.branchmap().iteritems():
1820 for b, ls in repo.branchmap().iteritems():
1821 if start is None:
1821 if start is None:
1822 heads += [repo[h] for h in ls]
1822 heads += [repo[h] for h in ls]
1823 continue
1823 continue
1824 startrev = repo.changelog.rev(start)
1824 startrev = repo.changelog.rev(start)
1825 descendants = set(repo.changelog.descendants(startrev))
1825 descendants = set(repo.changelog.descendants(startrev))
1826 descendants.add(startrev)
1826 descendants.add(startrev)
1827 rev = repo.changelog.rev
1827 rev = repo.changelog.rev
1828 heads += [repo[h] for h in ls if rev(h) in descendants]
1828 heads += [repo[h] for h in ls if rev(h) in descendants]
1829
1829
1830 if branchrevs:
1830 if branchrevs:
1831 decode, encode = encoding.fromlocal, encoding.tolocal
1831 decode, encode = encoding.fromlocal, encoding.tolocal
1832 branches = set(repo[decode(br)].branch() for br in branchrevs)
1832 branches = set(repo[decode(br)].branch() for br in branchrevs)
1833 heads = [h for h in heads if h.branch() in branches]
1833 heads = [h for h in heads if h.branch() in branches]
1834
1834
1835 if not opts.get('closed'):
1835 if not opts.get('closed'):
1836 heads = [h for h in heads if not h.extra().get('close')]
1836 heads = [h for h in heads if not h.extra().get('close')]
1837
1837
1838 if opts.get('active') and branchrevs:
1838 if opts.get('active') and branchrevs:
1839 dagheads = repo.heads(start)
1839 dagheads = repo.heads(start)
1840 heads = [h for h in heads if h.node() in dagheads]
1840 heads = [h for h in heads if h.node() in dagheads]
1841
1841
1842 if branchrevs:
1842 if branchrevs:
1843 haveheads = set(h.branch() for h in heads)
1843 haveheads = set(h.branch() for h in heads)
1844 if branches - haveheads:
1844 if branches - haveheads:
1845 headless = ', '.join(encode(b) for b in branches - haveheads)
1845 headless = ', '.join(encode(b) for b in branches - haveheads)
1846 msg = _('no open branch heads found on branches %s')
1846 msg = _('no open branch heads found on branches %s')
1847 if opts.get('rev'):
1847 if opts.get('rev'):
1848 msg += _(' (started at %s)' % opts['rev'])
1848 msg += _(' (started at %s)' % opts['rev'])
1849 ui.warn((msg + '\n') % headless)
1849 ui.warn((msg + '\n') % headless)
1850
1850
1851 if not heads:
1851 if not heads:
1852 return 1
1852 return 1
1853
1853
1854 heads = sorted(heads, key=lambda x: -x.rev())
1854 heads = sorted(heads, key=lambda x: -x.rev())
1855 displayer = cmdutil.show_changeset(ui, repo, opts)
1855 displayer = cmdutil.show_changeset(ui, repo, opts)
1856 for ctx in heads:
1856 for ctx in heads:
1857 displayer.show(ctx)
1857 displayer.show(ctx)
1858 displayer.close()
1858 displayer.close()
1859
1859
1860 def help_(ui, name=None, with_version=False, unknowncmd=False):
1860 def help_(ui, name=None, with_version=False, unknowncmd=False):
1861 """show help for a given topic or a help overview
1861 """show help for a given topic or a help overview
1862
1862
1863 With no arguments, print a list of commands with short help messages.
1863 With no arguments, print a list of commands with short help messages.
1864
1864
1865 Given a topic, extension, or command name, print help for that
1865 Given a topic, extension, or command name, print help for that
1866 topic.
1866 topic.
1867
1867
1868 Returns 0 if successful.
1868 Returns 0 if successful.
1869 """
1869 """
1870 option_lists = []
1870 option_lists = []
1871 textwidth = ui.termwidth() - 2
1871 textwidth = ui.termwidth() - 2
1872
1872
1873 def addglobalopts(aliases):
1873 def addglobalopts(aliases):
1874 if ui.verbose:
1874 if ui.verbose:
1875 option_lists.append((_("global options:"), globalopts))
1875 option_lists.append((_("global options:"), globalopts))
1876 if name == 'shortlist':
1876 if name == 'shortlist':
1877 option_lists.append((_('use "hg help" for the full list '
1877 option_lists.append((_('use "hg help" for the full list '
1878 'of commands'), ()))
1878 'of commands'), ()))
1879 else:
1879 else:
1880 if name == 'shortlist':
1880 if name == 'shortlist':
1881 msg = _('use "hg help" for the full list of commands '
1881 msg = _('use "hg help" for the full list of commands '
1882 'or "hg -v" for details')
1882 'or "hg -v" for details')
1883 elif aliases:
1883 elif aliases:
1884 msg = _('use "hg -v help%s" to show aliases and '
1884 msg = _('use "hg -v help%s" to show aliases and '
1885 'global options') % (name and " " + name or "")
1885 'global options') % (name and " " + name or "")
1886 else:
1886 else:
1887 msg = _('use "hg -v help %s" to show global options') % name
1887 msg = _('use "hg -v help %s" to show global options') % name
1888 option_lists.append((msg, ()))
1888 option_lists.append((msg, ()))
1889
1889
1890 def helpcmd(name):
1890 def helpcmd(name):
1891 if with_version:
1891 if with_version:
1892 version_(ui)
1892 version_(ui)
1893 ui.write('\n')
1893 ui.write('\n')
1894
1894
1895 try:
1895 try:
1896 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1896 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1897 except error.AmbiguousCommand, inst:
1897 except error.AmbiguousCommand, inst:
1898 # py3k fix: except vars can't be used outside the scope of the
1898 # py3k fix: except vars can't be used outside the scope of the
1899 # except block, nor can be used inside a lambda. python issue4617
1899 # except block, nor can be used inside a lambda. python issue4617
1900 prefix = inst.args[0]
1900 prefix = inst.args[0]
1901 select = lambda c: c.lstrip('^').startswith(prefix)
1901 select = lambda c: c.lstrip('^').startswith(prefix)
1902 helplist(_('list of commands:\n\n'), select)
1902 helplist(_('list of commands:\n\n'), select)
1903 return
1903 return
1904
1904
1905 # check if it's an invalid alias and display its error if it is
1905 # check if it's an invalid alias and display its error if it is
1906 if getattr(entry[0], 'badalias', False):
1906 if getattr(entry[0], 'badalias', False):
1907 if not unknowncmd:
1907 if not unknowncmd:
1908 entry[0](ui)
1908 entry[0](ui)
1909 return
1909 return
1910
1910
1911 # synopsis
1911 # synopsis
1912 if len(entry) > 2:
1912 if len(entry) > 2:
1913 if entry[2].startswith('hg'):
1913 if entry[2].startswith('hg'):
1914 ui.write("%s\n" % entry[2])
1914 ui.write("%s\n" % entry[2])
1915 else:
1915 else:
1916 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1916 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1917 else:
1917 else:
1918 ui.write('hg %s\n' % aliases[0])
1918 ui.write('hg %s\n' % aliases[0])
1919
1919
1920 # aliases
1920 # aliases
1921 if not ui.quiet and len(aliases) > 1:
1921 if not ui.quiet and len(aliases) > 1:
1922 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1922 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1923
1923
1924 # description
1924 # description
1925 doc = gettext(entry[0].__doc__)
1925 doc = gettext(entry[0].__doc__)
1926 if not doc:
1926 if not doc:
1927 doc = _("(no help text available)")
1927 doc = _("(no help text available)")
1928 if hasattr(entry[0], 'definition'): # aliased command
1928 if hasattr(entry[0], 'definition'): # aliased command
1929 if entry[0].definition.startswith('!'): # shell alias
1929 if entry[0].definition.startswith('!'): # shell alias
1930 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1930 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1931 else:
1931 else:
1932 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1932 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1933 if ui.quiet:
1933 if ui.quiet:
1934 doc = doc.splitlines()[0]
1934 doc = doc.splitlines()[0]
1935 keep = ui.verbose and ['verbose'] or []
1935 keep = ui.verbose and ['verbose'] or []
1936 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1936 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1937 ui.write("\n%s\n" % formatted)
1937 ui.write("\n%s\n" % formatted)
1938 if pruned:
1938 if pruned:
1939 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1939 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1940
1940
1941 if not ui.quiet:
1941 if not ui.quiet:
1942 # options
1942 # options
1943 if entry[1]:
1943 if entry[1]:
1944 option_lists.append((_("options:\n"), entry[1]))
1944 option_lists.append((_("options:\n"), entry[1]))
1945
1945
1946 addglobalopts(False)
1946 addglobalopts(False)
1947
1947
1948 def helplist(header, select=None):
1948 def helplist(header, select=None):
1949 h = {}
1949 h = {}
1950 cmds = {}
1950 cmds = {}
1951 for c, e in table.iteritems():
1951 for c, e in table.iteritems():
1952 f = c.split("|", 1)[0]
1952 f = c.split("|", 1)[0]
1953 if select and not select(f):
1953 if select and not select(f):
1954 continue
1954 continue
1955 if (not select and name != 'shortlist' and
1955 if (not select and name != 'shortlist' and
1956 e[0].__module__ != __name__):
1956 e[0].__module__ != __name__):
1957 continue
1957 continue
1958 if name == "shortlist" and not f.startswith("^"):
1958 if name == "shortlist" and not f.startswith("^"):
1959 continue
1959 continue
1960 f = f.lstrip("^")
1960 f = f.lstrip("^")
1961 if not ui.debugflag and f.startswith("debug"):
1961 if not ui.debugflag and f.startswith("debug"):
1962 continue
1962 continue
1963 doc = e[0].__doc__
1963 doc = e[0].__doc__
1964 if doc and 'DEPRECATED' in doc and not ui.verbose:
1964 if doc and 'DEPRECATED' in doc and not ui.verbose:
1965 continue
1965 continue
1966 doc = gettext(doc)
1966 doc = gettext(doc)
1967 if not doc:
1967 if not doc:
1968 doc = _("(no help text available)")
1968 doc = _("(no help text available)")
1969 h[f] = doc.splitlines()[0].rstrip()
1969 h[f] = doc.splitlines()[0].rstrip()
1970 cmds[f] = c.lstrip("^")
1970 cmds[f] = c.lstrip("^")
1971
1971
1972 if not h:
1972 if not h:
1973 ui.status(_('no commands defined\n'))
1973 ui.status(_('no commands defined\n'))
1974 return
1974 return
1975
1975
1976 ui.status(header)
1976 ui.status(header)
1977 fns = sorted(h)
1977 fns = sorted(h)
1978 m = max(map(len, fns))
1978 m = max(map(len, fns))
1979 for f in fns:
1979 for f in fns:
1980 if ui.verbose:
1980 if ui.verbose:
1981 commands = cmds[f].replace("|",", ")
1981 commands = cmds[f].replace("|",", ")
1982 ui.write(" %s:\n %s\n"%(commands, h[f]))
1982 ui.write(" %s:\n %s\n"%(commands, h[f]))
1983 else:
1983 else:
1984 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1984 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1985 initindent=' %-*s ' % (m, f),
1985 initindent=' %-*s ' % (m, f),
1986 hangindent=' ' * (m + 4))))
1986 hangindent=' ' * (m + 4))))
1987
1987
1988 if not ui.quiet:
1988 if not ui.quiet:
1989 addglobalopts(True)
1989 addglobalopts(True)
1990
1990
1991 def helptopic(name):
1991 def helptopic(name):
1992 for names, header, doc in help.helptable:
1992 for names, header, doc in help.helptable:
1993 if name in names:
1993 if name in names:
1994 break
1994 break
1995 else:
1995 else:
1996 raise error.UnknownCommand(name)
1996 raise error.UnknownCommand(name)
1997
1997
1998 # description
1998 # description
1999 if not doc:
1999 if not doc:
2000 doc = _("(no help text available)")
2000 doc = _("(no help text available)")
2001 if hasattr(doc, '__call__'):
2001 if hasattr(doc, '__call__'):
2002 doc = doc()
2002 doc = doc()
2003
2003
2004 ui.write("%s\n\n" % header)
2004 ui.write("%s\n\n" % header)
2005 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2005 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2006
2006
2007 def helpext(name):
2007 def helpext(name):
2008 try:
2008 try:
2009 mod = extensions.find(name)
2009 mod = extensions.find(name)
2010 doc = gettext(mod.__doc__) or _('no help text available')
2010 doc = gettext(mod.__doc__) or _('no help text available')
2011 except KeyError:
2011 except KeyError:
2012 mod = None
2012 mod = None
2013 doc = extensions.disabledext(name)
2013 doc = extensions.disabledext(name)
2014 if not doc:
2014 if not doc:
2015 raise error.UnknownCommand(name)
2015 raise error.UnknownCommand(name)
2016
2016
2017 if '\n' not in doc:
2017 if '\n' not in doc:
2018 head, tail = doc, ""
2018 head, tail = doc, ""
2019 else:
2019 else:
2020 head, tail = doc.split('\n', 1)
2020 head, tail = doc.split('\n', 1)
2021 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2021 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2022 if tail:
2022 if tail:
2023 ui.write(minirst.format(tail, textwidth))
2023 ui.write(minirst.format(tail, textwidth))
2024 ui.status('\n\n')
2024 ui.status('\n\n')
2025
2025
2026 if mod:
2026 if mod:
2027 try:
2027 try:
2028 ct = mod.cmdtable
2028 ct = mod.cmdtable
2029 except AttributeError:
2029 except AttributeError:
2030 ct = {}
2030 ct = {}
2031 modcmds = set([c.split('|', 1)[0] for c in ct])
2031 modcmds = set([c.split('|', 1)[0] for c in ct])
2032 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2032 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2033 else:
2033 else:
2034 ui.write(_('use "hg help extensions" for information on enabling '
2034 ui.write(_('use "hg help extensions" for information on enabling '
2035 'extensions\n'))
2035 'extensions\n'))
2036
2036
2037 def helpextcmd(name):
2037 def helpextcmd(name):
2038 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2038 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2039 doc = gettext(mod.__doc__).splitlines()[0]
2039 doc = gettext(mod.__doc__).splitlines()[0]
2040
2040
2041 msg = help.listexts(_("'%s' is provided by the following "
2041 msg = help.listexts(_("'%s' is provided by the following "
2042 "extension:") % cmd, {ext: doc}, len(ext),
2042 "extension:") % cmd, {ext: doc}, len(ext),
2043 indent=4)
2043 indent=4)
2044 ui.write(minirst.format(msg, textwidth))
2044 ui.write(minirst.format(msg, textwidth))
2045 ui.write('\n\n')
2045 ui.write('\n\n')
2046 ui.write(_('use "hg help extensions" for information on enabling '
2046 ui.write(_('use "hg help extensions" for information on enabling '
2047 'extensions\n'))
2047 'extensions\n'))
2048
2048
2049 help.addtopichook('revsets', revset.makedoc)
2049 help.addtopichook('revsets', revset.makedoc)
2050
2050
2051 if name and name != 'shortlist':
2051 if name and name != 'shortlist':
2052 i = None
2052 i = None
2053 if unknowncmd:
2053 if unknowncmd:
2054 queries = (helpextcmd,)
2054 queries = (helpextcmd,)
2055 else:
2055 else:
2056 queries = (helptopic, helpcmd, helpext, helpextcmd)
2056 queries = (helptopic, helpcmd, helpext, helpextcmd)
2057 for f in queries:
2057 for f in queries:
2058 try:
2058 try:
2059 f(name)
2059 f(name)
2060 i = None
2060 i = None
2061 break
2061 break
2062 except error.UnknownCommand, inst:
2062 except error.UnknownCommand, inst:
2063 i = inst
2063 i = inst
2064 if i:
2064 if i:
2065 raise i
2065 raise i
2066
2066
2067 else:
2067 else:
2068 # program name
2068 # program name
2069 if ui.verbose or with_version:
2069 if ui.verbose or with_version:
2070 version_(ui)
2070 version_(ui)
2071 else:
2071 else:
2072 ui.status(_("Mercurial Distributed SCM\n"))
2072 ui.status(_("Mercurial Distributed SCM\n"))
2073 ui.status('\n')
2073 ui.status('\n')
2074
2074
2075 # list of commands
2075 # list of commands
2076 if name == "shortlist":
2076 if name == "shortlist":
2077 header = _('basic commands:\n\n')
2077 header = _('basic commands:\n\n')
2078 else:
2078 else:
2079 header = _('list of commands:\n\n')
2079 header = _('list of commands:\n\n')
2080
2080
2081 helplist(header)
2081 helplist(header)
2082 if name != 'shortlist':
2082 if name != 'shortlist':
2083 exts, maxlength = extensions.enabled()
2083 exts, maxlength = extensions.enabled()
2084 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2084 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2085 if text:
2085 if text:
2086 ui.write("\n%s\n" % minirst.format(text, textwidth))
2086 ui.write("\n%s\n" % minirst.format(text, textwidth))
2087
2087
2088 # list all option lists
2088 # list all option lists
2089 opt_output = []
2089 opt_output = []
2090 multioccur = False
2090 multioccur = False
2091 for title, options in option_lists:
2091 for title, options in option_lists:
2092 opt_output.append(("\n%s" % title, None))
2092 opt_output.append(("\n%s" % title, None))
2093 for option in options:
2093 for option in options:
2094 if len(option) == 5:
2094 if len(option) == 5:
2095 shortopt, longopt, default, desc, optlabel = option
2095 shortopt, longopt, default, desc, optlabel = option
2096 else:
2096 else:
2097 shortopt, longopt, default, desc = option
2097 shortopt, longopt, default, desc = option
2098 optlabel = _("VALUE") # default label
2098 optlabel = _("VALUE") # default label
2099
2099
2100 if _("DEPRECATED") in desc and not ui.verbose:
2100 if _("DEPRECATED") in desc and not ui.verbose:
2101 continue
2101 continue
2102 if isinstance(default, list):
2102 if isinstance(default, list):
2103 numqualifier = " %s [+]" % optlabel
2103 numqualifier = " %s [+]" % optlabel
2104 multioccur = True
2104 multioccur = True
2105 elif (default is not None) and not isinstance(default, bool):
2105 elif (default is not None) and not isinstance(default, bool):
2106 numqualifier = " %s" % optlabel
2106 numqualifier = " %s" % optlabel
2107 else:
2107 else:
2108 numqualifier = ""
2108 numqualifier = ""
2109 opt_output.append(("%2s%s" %
2109 opt_output.append(("%2s%s" %
2110 (shortopt and "-%s" % shortopt,
2110 (shortopt and "-%s" % shortopt,
2111 longopt and " --%s%s" %
2111 longopt and " --%s%s" %
2112 (longopt, numqualifier)),
2112 (longopt, numqualifier)),
2113 "%s%s" % (desc,
2113 "%s%s" % (desc,
2114 default
2114 default
2115 and _(" (default: %s)") % default
2115 and _(" (default: %s)") % default
2116 or "")))
2116 or "")))
2117 if multioccur:
2117 if multioccur:
2118 msg = _("\n[+] marked option can be specified multiple times")
2118 msg = _("\n[+] marked option can be specified multiple times")
2119 if ui.verbose and name != 'shortlist':
2119 if ui.verbose and name != 'shortlist':
2120 opt_output.append((msg, None))
2120 opt_output.append((msg, None))
2121 else:
2121 else:
2122 opt_output.insert(-1, (msg, None))
2122 opt_output.insert(-1, (msg, None))
2123
2123
2124 if not name:
2124 if not name:
2125 ui.write(_("\nadditional help topics:\n\n"))
2125 ui.write(_("\nadditional help topics:\n\n"))
2126 topics = []
2126 topics = []
2127 for names, header, doc in help.helptable:
2127 for names, header, doc in help.helptable:
2128 topics.append((sorted(names, key=len, reverse=True)[0], header))
2128 topics.append((sorted(names, key=len, reverse=True)[0], header))
2129 topics_len = max([len(s[0]) for s in topics])
2129 topics_len = max([len(s[0]) for s in topics])
2130 for t, desc in topics:
2130 for t, desc in topics:
2131 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2131 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2132
2132
2133 if opt_output:
2133 if opt_output:
2134 colwidth = encoding.colwidth
2134 colwidth = encoding.colwidth
2135 # normalize: (opt or message, desc or None, width of opt)
2135 # normalize: (opt or message, desc or None, width of opt)
2136 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2136 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2137 for opt, desc in opt_output]
2137 for opt, desc in opt_output]
2138 hanging = max([e[2] for e in entries])
2138 hanging = max([e[2] for e in entries])
2139 for opt, desc, width in entries:
2139 for opt, desc, width in entries:
2140 if desc:
2140 if desc:
2141 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2141 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2142 hangindent = ' ' * (hanging + 3)
2142 hangindent = ' ' * (hanging + 3)
2143 ui.write('%s\n' % (util.wrap(desc, textwidth,
2143 ui.write('%s\n' % (util.wrap(desc, textwidth,
2144 initindent=initindent,
2144 initindent=initindent,
2145 hangindent=hangindent)))
2145 hangindent=hangindent)))
2146 else:
2146 else:
2147 ui.write("%s\n" % opt)
2147 ui.write("%s\n" % opt)
2148
2148
2149 def identify(ui, repo, source=None,
2149 def identify(ui, repo, source=None,
2150 rev=None, num=None, id=None, branch=None, tags=None):
2150 rev=None, num=None, id=None, branch=None, tags=None):
2151 """identify the working copy or specified revision
2151 """identify the working copy or specified revision
2152
2152
2153 With no revision, print a summary of the current state of the
2153 With no revision, print a summary of the current state of the
2154 repository.
2154 repository.
2155
2155
2156 Specifying a path to a repository root or Mercurial bundle will
2156 Specifying a path to a repository root or Mercurial bundle will
2157 cause lookup to operate on that repository/bundle.
2157 cause lookup to operate on that repository/bundle.
2158
2158
2159 This summary identifies the repository state using one or two
2159 This summary identifies the repository state using one or two
2160 parent hash identifiers, followed by a "+" if there are
2160 parent hash identifiers, followed by a "+" if there are
2161 uncommitted changes in the working directory, a list of tags for
2161 uncommitted changes in the working directory, a list of tags for
2162 this revision and a branch name for non-default branches.
2162 this revision and a branch name for non-default branches.
2163
2163
2164 Returns 0 if successful.
2164 Returns 0 if successful.
2165 """
2165 """
2166
2166
2167 if not repo and not source:
2167 if not repo and not source:
2168 raise util.Abort(_("there is no Mercurial repository here "
2168 raise util.Abort(_("there is no Mercurial repository here "
2169 "(.hg not found)"))
2169 "(.hg not found)"))
2170
2170
2171 hexfunc = ui.debugflag and hex or short
2171 hexfunc = ui.debugflag and hex or short
2172 default = not (num or id or branch or tags)
2172 default = not (num or id or branch or tags)
2173 output = []
2173 output = []
2174
2174
2175 revs = []
2175 revs = []
2176 if source:
2176 if source:
2177 source, branches = hg.parseurl(ui.expandpath(source))
2177 source, branches = hg.parseurl(ui.expandpath(source))
2178 repo = hg.repository(ui, source)
2178 repo = hg.repository(ui, source)
2179 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2179 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2180
2180
2181 if not repo.local():
2181 if not repo.local():
2182 if not rev and revs:
2182 if not rev and revs:
2183 rev = revs[0]
2183 rev = revs[0]
2184 if not rev:
2184 if not rev:
2185 rev = "tip"
2185 rev = "tip"
2186 if num or branch or tags:
2186 if num or branch or tags:
2187 raise util.Abort(
2187 raise util.Abort(
2188 "can't query remote revision number, branch, or tags")
2188 "can't query remote revision number, branch, or tags")
2189 output = [hexfunc(repo.lookup(rev))]
2189 output = [hexfunc(repo.lookup(rev))]
2190 elif not rev:
2190 elif not rev:
2191 ctx = repo[None]
2191 ctx = repo[None]
2192 parents = ctx.parents()
2192 parents = ctx.parents()
2193 changed = False
2193 changed = False
2194 if default or id or num:
2194 if default or id or num:
2195 changed = util.any(repo.status())
2195 changed = util.any(repo.status())
2196 if default or id:
2196 if default or id:
2197 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2197 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2198 (changed) and "+" or "")]
2198 (changed) and "+" or "")]
2199 if num:
2199 if num:
2200 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2200 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2201 (changed) and "+" or ""))
2201 (changed) and "+" or ""))
2202 else:
2202 else:
2203 ctx = repo[rev]
2203 ctx = repo[rev]
2204 if default or id:
2204 if default or id:
2205 output = [hexfunc(ctx.node())]
2205 output = [hexfunc(ctx.node())]
2206 if num:
2206 if num:
2207 output.append(str(ctx.rev()))
2207 output.append(str(ctx.rev()))
2208
2208
2209 if repo.local() and default and not ui.quiet:
2209 if repo.local() and default and not ui.quiet:
2210 b = encoding.tolocal(ctx.branch())
2210 b = encoding.tolocal(ctx.branch())
2211 if b != 'default':
2211 if b != 'default':
2212 output.append("(%s)" % b)
2212 output.append("(%s)" % b)
2213
2213
2214 # multiple tags for a single parent separated by '/'
2214 # multiple tags for a single parent separated by '/'
2215 t = "/".join(ctx.tags())
2215 t = "/".join(ctx.tags())
2216 if t:
2216 if t:
2217 output.append(t)
2217 output.append(t)
2218
2218
2219 if branch:
2219 if branch:
2220 output.append(encoding.tolocal(ctx.branch()))
2220 output.append(encoding.tolocal(ctx.branch()))
2221
2221
2222 if tags:
2222 if tags:
2223 output.extend(ctx.tags())
2223 output.extend(ctx.tags())
2224
2224
2225 ui.write("%s\n" % ' '.join(output))
2225 ui.write("%s\n" % ' '.join(output))
2226
2226
2227 def import_(ui, repo, patch1, *patches, **opts):
2227 def import_(ui, repo, patch1, *patches, **opts):
2228 """import an ordered set of patches
2228 """import an ordered set of patches
2229
2229
2230 Import a list of patches and commit them individually (unless
2230 Import a list of patches and commit them individually (unless
2231 --no-commit is specified).
2231 --no-commit is specified).
2232
2232
2233 If there are outstanding changes in the working directory, import
2233 If there are outstanding changes in the working directory, import
2234 will abort unless given the -f/--force flag.
2234 will abort unless given the -f/--force flag.
2235
2235
2236 You can import a patch straight from a mail message. Even patches
2236 You can import a patch straight from a mail message. Even patches
2237 as attachments work (to use the body part, it must have type
2237 as attachments work (to use the body part, it must have type
2238 text/plain or text/x-patch). From and Subject headers of email
2238 text/plain or text/x-patch). From and Subject headers of email
2239 message are used as default committer and commit message. All
2239 message are used as default committer and commit message. All
2240 text/plain body parts before first diff are added to commit
2240 text/plain body parts before first diff are added to commit
2241 message.
2241 message.
2242
2242
2243 If the imported patch was generated by :hg:`export`, user and
2243 If the imported patch was generated by :hg:`export`, user and
2244 description from patch override values from message headers and
2244 description from patch override values from message headers and
2245 body. Values given on command line with -m/--message and -u/--user
2245 body. Values given on command line with -m/--message and -u/--user
2246 override these.
2246 override these.
2247
2247
2248 If --exact is specified, import will set the working directory to
2248 If --exact is specified, import will set the working directory to
2249 the parent of each patch before applying it, and will abort if the
2249 the parent of each patch before applying it, and will abort if the
2250 resulting changeset has a different ID than the one recorded in
2250 resulting changeset has a different ID than the one recorded in
2251 the patch. This may happen due to character set problems or other
2251 the patch. This may happen due to character set problems or other
2252 deficiencies in the text patch format.
2252 deficiencies in the text patch format.
2253
2253
2254 With -s/--similarity, hg will attempt to discover renames and
2254 With -s/--similarity, hg will attempt to discover renames and
2255 copies in the patch in the same way as 'addremove'.
2255 copies in the patch in the same way as 'addremove'.
2256
2256
2257 To read a patch from standard input, use "-" as the patch name. If
2257 To read a patch from standard input, use "-" as the patch name. If
2258 a URL is specified, the patch will be downloaded from it.
2258 a URL is specified, the patch will be downloaded from it.
2259 See :hg:`help dates` for a list of formats valid for -d/--date.
2259 See :hg:`help dates` for a list of formats valid for -d/--date.
2260
2260
2261 Returns 0 on success.
2261 Returns 0 on success.
2262 """
2262 """
2263 patches = (patch1,) + patches
2263 patches = (patch1,) + patches
2264
2264
2265 date = opts.get('date')
2265 date = opts.get('date')
2266 if date:
2266 if date:
2267 opts['date'] = util.parsedate(date)
2267 opts['date'] = util.parsedate(date)
2268
2268
2269 try:
2269 try:
2270 sim = float(opts.get('similarity') or 0)
2270 sim = float(opts.get('similarity') or 0)
2271 except ValueError:
2271 except ValueError:
2272 raise util.Abort(_('similarity must be a number'))
2272 raise util.Abort(_('similarity must be a number'))
2273 if sim < 0 or sim > 100:
2273 if sim < 0 or sim > 100:
2274 raise util.Abort(_('similarity must be between 0 and 100'))
2274 raise util.Abort(_('similarity must be between 0 and 100'))
2275
2275
2276 if opts.get('exact') or not opts.get('force'):
2276 if opts.get('exact') or not opts.get('force'):
2277 cmdutil.bail_if_changed(repo)
2277 cmdutil.bail_if_changed(repo)
2278
2278
2279 d = opts["base"]
2279 d = opts["base"]
2280 strip = opts["strip"]
2280 strip = opts["strip"]
2281 wlock = lock = None
2281 wlock = lock = None
2282
2282
2283 def tryone(ui, hunk):
2283 def tryone(ui, hunk):
2284 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2284 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2285 patch.extract(ui, hunk)
2285 patch.extract(ui, hunk)
2286
2286
2287 if not tmpname:
2287 if not tmpname:
2288 return None
2288 return None
2289 commitid = _('to working directory')
2289 commitid = _('to working directory')
2290
2290
2291 try:
2291 try:
2292 cmdline_message = cmdutil.logmessage(opts)
2292 cmdline_message = cmdutil.logmessage(opts)
2293 if cmdline_message:
2293 if cmdline_message:
2294 # pickup the cmdline msg
2294 # pickup the cmdline msg
2295 message = cmdline_message
2295 message = cmdline_message
2296 elif message:
2296 elif message:
2297 # pickup the patch msg
2297 # pickup the patch msg
2298 message = message.strip()
2298 message = message.strip()
2299 else:
2299 else:
2300 # launch the editor
2300 # launch the editor
2301 message = None
2301 message = None
2302 ui.debug('message:\n%s\n' % message)
2302 ui.debug('message:\n%s\n' % message)
2303
2303
2304 wp = repo.parents()
2304 wp = repo.parents()
2305 if opts.get('exact'):
2305 if opts.get('exact'):
2306 if not nodeid or not p1:
2306 if not nodeid or not p1:
2307 raise util.Abort(_('not a Mercurial patch'))
2307 raise util.Abort(_('not a Mercurial patch'))
2308 p1 = repo.lookup(p1)
2308 p1 = repo.lookup(p1)
2309 p2 = repo.lookup(p2 or hex(nullid))
2309 p2 = repo.lookup(p2 or hex(nullid))
2310
2310
2311 if p1 != wp[0].node():
2311 if p1 != wp[0].node():
2312 hg.clean(repo, p1)
2312 hg.clean(repo, p1)
2313 repo.dirstate.setparents(p1, p2)
2313 repo.dirstate.setparents(p1, p2)
2314 elif p2:
2314 elif p2:
2315 try:
2315 try:
2316 p1 = repo.lookup(p1)
2316 p1 = repo.lookup(p1)
2317 p2 = repo.lookup(p2)
2317 p2 = repo.lookup(p2)
2318 if p1 == wp[0].node():
2318 if p1 == wp[0].node():
2319 repo.dirstate.setparents(p1, p2)
2319 repo.dirstate.setparents(p1, p2)
2320 except error.RepoError:
2320 except error.RepoError:
2321 pass
2321 pass
2322 if opts.get('exact') or opts.get('import_branch'):
2322 if opts.get('exact') or opts.get('import_branch'):
2323 repo.dirstate.setbranch(branch or 'default')
2323 repo.dirstate.setbranch(branch or 'default')
2324
2324
2325 files = {}
2325 files = {}
2326 try:
2326 try:
2327 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2327 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2328 files=files, eolmode=None)
2328 files=files, eolmode=None)
2329 finally:
2329 finally:
2330 files = cmdutil.updatedir(ui, repo, files,
2330 files = cmdutil.updatedir(ui, repo, files,
2331 similarity=sim / 100.0)
2331 similarity=sim / 100.0)
2332 if not opts.get('no_commit'):
2332 if not opts.get('no_commit'):
2333 if opts.get('exact'):
2333 if opts.get('exact'):
2334 m = None
2334 m = None
2335 else:
2335 else:
2336 m = cmdutil.matchfiles(repo, files or [])
2336 m = cmdutil.matchfiles(repo, files or [])
2337 n = repo.commit(message, opts.get('user') or user,
2337 n = repo.commit(message, opts.get('user') or user,
2338 opts.get('date') or date, match=m,
2338 opts.get('date') or date, match=m,
2339 editor=cmdutil.commiteditor)
2339 editor=cmdutil.commiteditor)
2340 if opts.get('exact'):
2340 if opts.get('exact'):
2341 if hex(n) != nodeid:
2341 if hex(n) != nodeid:
2342 repo.rollback()
2342 repo.rollback()
2343 raise util.Abort(_('patch is damaged'
2343 raise util.Abort(_('patch is damaged'
2344 ' or loses information'))
2344 ' or loses information'))
2345 # Force a dirstate write so that the next transaction
2345 # Force a dirstate write so that the next transaction
2346 # backups an up-do-date file.
2346 # backups an up-do-date file.
2347 repo.dirstate.write()
2347 repo.dirstate.write()
2348 if n:
2348 if n:
2349 commitid = short(n)
2349 commitid = short(n)
2350
2350
2351 return commitid
2351 return commitid
2352 finally:
2352 finally:
2353 os.unlink(tmpname)
2353 os.unlink(tmpname)
2354
2354
2355 try:
2355 try:
2356 wlock = repo.wlock()
2356 wlock = repo.wlock()
2357 lock = repo.lock()
2357 lock = repo.lock()
2358 lastcommit = None
2358 lastcommit = None
2359 for p in patches:
2359 for p in patches:
2360 pf = os.path.join(d, p)
2360 pf = os.path.join(d, p)
2361
2361
2362 if pf == '-':
2362 if pf == '-':
2363 ui.status(_("applying patch from stdin\n"))
2363 ui.status(_("applying patch from stdin\n"))
2364 pf = sys.stdin
2364 pf = sys.stdin
2365 else:
2365 else:
2366 ui.status(_("applying %s\n") % p)
2366 ui.status(_("applying %s\n") % p)
2367 pf = url.open(ui, pf)
2367 pf = url.open(ui, pf)
2368
2368
2369 haspatch = False
2369 haspatch = False
2370 for hunk in patch.split(pf):
2370 for hunk in patch.split(pf):
2371 commitid = tryone(ui, hunk)
2371 commitid = tryone(ui, hunk)
2372 if commitid:
2372 if commitid:
2373 haspatch = True
2373 haspatch = True
2374 if lastcommit:
2374 if lastcommit:
2375 ui.status(_('applied %s\n') % lastcommit)
2375 ui.status(_('applied %s\n') % lastcommit)
2376 lastcommit = commitid
2376 lastcommit = commitid
2377
2377
2378 if not haspatch:
2378 if not haspatch:
2379 raise util.Abort(_('no diffs found'))
2379 raise util.Abort(_('no diffs found'))
2380
2380
2381 finally:
2381 finally:
2382 release(lock, wlock)
2382 release(lock, wlock)
2383
2383
2384 def incoming(ui, repo, source="default", **opts):
2384 def incoming(ui, repo, source="default", **opts):
2385 """show new changesets found in source
2385 """show new changesets found in source
2386
2386
2387 Show new changesets found in the specified path/URL or the default
2387 Show new changesets found in the specified path/URL or the default
2388 pull location. These are the changesets that would have been pulled
2388 pull location. These are the changesets that would have been pulled
2389 if a pull at the time you issued this command.
2389 if a pull at the time you issued this command.
2390
2390
2391 For remote repository, using --bundle avoids downloading the
2391 For remote repository, using --bundle avoids downloading the
2392 changesets twice if the incoming is followed by a pull.
2392 changesets twice if the incoming is followed by a pull.
2393
2393
2394 See pull for valid source format details.
2394 See pull for valid source format details.
2395
2395
2396 Returns 0 if there are incoming changes, 1 otherwise.
2396 Returns 0 if there are incoming changes, 1 otherwise.
2397 """
2397 """
2398 if opts.get('bundle') and opts.get('subrepos'):
2398 if opts.get('bundle') and opts.get('subrepos'):
2399 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2399 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2400
2400
2401 ret = hg.incoming(ui, repo, source, opts)
2401 ret = hg.incoming(ui, repo, source, opts)
2402 return ret
2402 return ret
2403
2403
2404 def init(ui, dest=".", **opts):
2404 def init(ui, dest=".", **opts):
2405 """create a new repository in the given directory
2405 """create a new repository in the given directory
2406
2406
2407 Initialize a new repository in the given directory. If the given
2407 Initialize a new repository in the given directory. If the given
2408 directory does not exist, it will be created.
2408 directory does not exist, it will be created.
2409
2409
2410 If no directory is given, the current directory is used.
2410 If no directory is given, the current directory is used.
2411
2411
2412 It is possible to specify an ``ssh://`` URL as the destination.
2412 It is possible to specify an ``ssh://`` URL as the destination.
2413 See :hg:`help urls` for more information.
2413 See :hg:`help urls` for more information.
2414
2414
2415 Returns 0 on success.
2415 Returns 0 on success.
2416 """
2416 """
2417 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2417 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2418
2418
2419 def locate(ui, repo, *pats, **opts):
2419 def locate(ui, repo, *pats, **opts):
2420 """locate files matching specific patterns
2420 """locate files matching specific patterns
2421
2421
2422 Print files under Mercurial control in the working directory whose
2422 Print files under Mercurial control in the working directory whose
2423 names match the given patterns.
2423 names match the given patterns.
2424
2424
2425 By default, this command searches all directories in the working
2425 By default, this command searches all directories in the working
2426 directory. To search just the current directory and its
2426 directory. To search just the current directory and its
2427 subdirectories, use "--include .".
2427 subdirectories, use "--include .".
2428
2428
2429 If no patterns are given to match, this command prints the names
2429 If no patterns are given to match, this command prints the names
2430 of all files under Mercurial control in the working directory.
2430 of all files under Mercurial control in the working directory.
2431
2431
2432 If you want to feed the output of this command into the "xargs"
2432 If you want to feed the output of this command into the "xargs"
2433 command, use the -0 option to both this command and "xargs". This
2433 command, use the -0 option to both this command and "xargs". This
2434 will avoid the problem of "xargs" treating single filenames that
2434 will avoid the problem of "xargs" treating single filenames that
2435 contain whitespace as multiple filenames.
2435 contain whitespace as multiple filenames.
2436
2436
2437 Returns 0 if a match is found, 1 otherwise.
2437 Returns 0 if a match is found, 1 otherwise.
2438 """
2438 """
2439 end = opts.get('print0') and '\0' or '\n'
2439 end = opts.get('print0') and '\0' or '\n'
2440 rev = opts.get('rev') or None
2440 rev = opts.get('rev') or None
2441
2441
2442 ret = 1
2442 ret = 1
2443 m = cmdutil.match(repo, pats, opts, default='relglob')
2443 m = cmdutil.match(repo, pats, opts, default='relglob')
2444 m.bad = lambda x, y: False
2444 m.bad = lambda x, y: False
2445 for abs in repo[rev].walk(m):
2445 for abs in repo[rev].walk(m):
2446 if not rev and abs not in repo.dirstate:
2446 if not rev and abs not in repo.dirstate:
2447 continue
2447 continue
2448 if opts.get('fullpath'):
2448 if opts.get('fullpath'):
2449 ui.write(repo.wjoin(abs), end)
2449 ui.write(repo.wjoin(abs), end)
2450 else:
2450 else:
2451 ui.write(((pats and m.rel(abs)) or abs), end)
2451 ui.write(((pats and m.rel(abs)) or abs), end)
2452 ret = 0
2452 ret = 0
2453
2453
2454 return ret
2454 return ret
2455
2455
2456 def log(ui, repo, *pats, **opts):
2456 def log(ui, repo, *pats, **opts):
2457 """show revision history of entire repository or files
2457 """show revision history of entire repository or files
2458
2458
2459 Print the revision history of the specified files or the entire
2459 Print the revision history of the specified files or the entire
2460 project.
2460 project.
2461
2461
2462 File history is shown without following rename or copy history of
2462 File history is shown without following rename or copy history of
2463 files. Use -f/--follow with a filename to follow history across
2463 files. Use -f/--follow with a filename to follow history across
2464 renames and copies. --follow without a filename will only show
2464 renames and copies. --follow without a filename will only show
2465 ancestors or descendants of the starting revision. --follow-first
2465 ancestors or descendants of the starting revision. --follow-first
2466 only follows the first parent of merge revisions.
2466 only follows the first parent of merge revisions.
2467
2467
2468 If no revision range is specified, the default is ``tip:0`` unless
2468 If no revision range is specified, the default is ``tip:0`` unless
2469 --follow is set, in which case the working directory parent is
2469 --follow is set, in which case the working directory parent is
2470 used as the starting revision. You can specify a revision set for
2470 used as the starting revision. You can specify a revision set for
2471 log, see :hg:`help revsets` for more information.
2471 log, see :hg:`help revsets` for more information.
2472
2472
2473 See :hg:`help dates` for a list of formats valid for -d/--date.
2473 See :hg:`help dates` for a list of formats valid for -d/--date.
2474
2474
2475 By default this command prints revision number and changeset id,
2475 By default this command prints revision number and changeset id,
2476 tags, non-trivial parents, user, date and time, and a summary for
2476 tags, non-trivial parents, user, date and time, and a summary for
2477 each commit. When the -v/--verbose switch is used, the list of
2477 each commit. When the -v/--verbose switch is used, the list of
2478 changed files and full commit message are shown.
2478 changed files and full commit message are shown.
2479
2479
2480 .. note::
2480 .. note::
2481 log -p/--patch may generate unexpected diff output for merge
2481 log -p/--patch may generate unexpected diff output for merge
2482 changesets, as it will only compare the merge changeset against
2482 changesets, as it will only compare the merge changeset against
2483 its first parent. Also, only files different from BOTH parents
2483 its first parent. Also, only files different from BOTH parents
2484 will appear in files:.
2484 will appear in files:.
2485
2485
2486 Returns 0 on success.
2486 Returns 0 on success.
2487 """
2487 """
2488
2488
2489 matchfn = cmdutil.match(repo, pats, opts)
2489 matchfn = cmdutil.match(repo, pats, opts)
2490 limit = cmdutil.loglimit(opts)
2490 limit = cmdutil.loglimit(opts)
2491 count = 0
2491 count = 0
2492
2492
2493 endrev = None
2493 endrev = None
2494 if opts.get('copies') and opts.get('rev'):
2494 if opts.get('copies') and opts.get('rev'):
2495 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2495 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2496
2496
2497 df = False
2497 df = False
2498 if opts["date"]:
2498 if opts["date"]:
2499 df = util.matchdate(opts["date"])
2499 df = util.matchdate(opts["date"])
2500
2500
2501 branches = opts.get('branch', []) + opts.get('only_branch', [])
2501 branches = opts.get('branch', []) + opts.get('only_branch', [])
2502 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2502 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2503
2503
2504 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2504 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2505 def prep(ctx, fns):
2505 def prep(ctx, fns):
2506 rev = ctx.rev()
2506 rev = ctx.rev()
2507 parents = [p for p in repo.changelog.parentrevs(rev)
2507 parents = [p for p in repo.changelog.parentrevs(rev)
2508 if p != nullrev]
2508 if p != nullrev]
2509 if opts.get('no_merges') and len(parents) == 2:
2509 if opts.get('no_merges') and len(parents) == 2:
2510 return
2510 return
2511 if opts.get('only_merges') and len(parents) != 2:
2511 if opts.get('only_merges') and len(parents) != 2:
2512 return
2512 return
2513 if opts.get('branch') and ctx.branch() not in opts['branch']:
2513 if opts.get('branch') and ctx.branch() not in opts['branch']:
2514 return
2514 return
2515 if df and not df(ctx.date()[0]):
2515 if df and not df(ctx.date()[0]):
2516 return
2516 return
2517 if opts['user'] and not [k for k in opts['user']
2517 if opts['user'] and not [k for k in opts['user']
2518 if k.lower() in ctx.user().lower()]:
2518 if k.lower() in ctx.user().lower()]:
2519 return
2519 return
2520 if opts.get('keyword'):
2520 if opts.get('keyword'):
2521 for k in [kw.lower() for kw in opts['keyword']]:
2521 for k in [kw.lower() for kw in opts['keyword']]:
2522 if (k in ctx.user().lower() or
2522 if (k in ctx.user().lower() or
2523 k in ctx.description().lower() or
2523 k in ctx.description().lower() or
2524 k in " ".join(ctx.files()).lower()):
2524 k in " ".join(ctx.files()).lower()):
2525 break
2525 break
2526 else:
2526 else:
2527 return
2527 return
2528
2528
2529 copies = None
2529 copies = None
2530 if opts.get('copies') and rev:
2530 if opts.get('copies') and rev:
2531 copies = []
2531 copies = []
2532 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2532 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2533 for fn in ctx.files():
2533 for fn in ctx.files():
2534 rename = getrenamed(fn, rev)
2534 rename = getrenamed(fn, rev)
2535 if rename:
2535 if rename:
2536 copies.append((fn, rename[0]))
2536 copies.append((fn, rename[0]))
2537
2537
2538 revmatchfn = None
2538 revmatchfn = None
2539 if opts.get('patch') or opts.get('stat'):
2539 if opts.get('patch') or opts.get('stat'):
2540 if opts.get('follow') or opts.get('follow_first'):
2540 if opts.get('follow') or opts.get('follow_first'):
2541 # note: this might be wrong when following through merges
2541 # note: this might be wrong when following through merges
2542 revmatchfn = cmdutil.match(repo, fns, default='path')
2542 revmatchfn = cmdutil.match(repo, fns, default='path')
2543 else:
2543 else:
2544 revmatchfn = matchfn
2544 revmatchfn = matchfn
2545
2545
2546 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2546 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2547
2547
2548 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2548 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2549 if count == limit:
2549 if count == limit:
2550 break
2550 break
2551 if displayer.flush(ctx.rev()):
2551 if displayer.flush(ctx.rev()):
2552 count += 1
2552 count += 1
2553 displayer.close()
2553 displayer.close()
2554
2554
2555 def manifest(ui, repo, node=None, rev=None):
2555 def manifest(ui, repo, node=None, rev=None):
2556 """output the current or given revision of the project manifest
2556 """output the current or given revision of the project manifest
2557
2557
2558 Print a list of version controlled files for the given revision.
2558 Print a list of version controlled files for the given revision.
2559 If no revision is given, the first parent of the working directory
2559 If no revision is given, the first parent of the working directory
2560 is used, or the null revision if no revision is checked out.
2560 is used, or the null revision if no revision is checked out.
2561
2561
2562 With -v, print file permissions, symlink and executable bits.
2562 With -v, print file permissions, symlink and executable bits.
2563 With --debug, print file revision hashes.
2563 With --debug, print file revision hashes.
2564
2564
2565 Returns 0 on success.
2565 Returns 0 on success.
2566 """
2566 """
2567
2567
2568 if rev and node:
2568 if rev and node:
2569 raise util.Abort(_("please specify just one revision"))
2569 raise util.Abort(_("please specify just one revision"))
2570
2570
2571 if not node:
2571 if not node:
2572 node = rev
2572 node = rev
2573
2573
2574 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2574 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2575 ctx = repo[node]
2575 ctx = repo[node]
2576 for f in ctx:
2576 for f in ctx:
2577 if ui.debugflag:
2577 if ui.debugflag:
2578 ui.write("%40s " % hex(ctx.manifest()[f]))
2578 ui.write("%40s " % hex(ctx.manifest()[f]))
2579 if ui.verbose:
2579 if ui.verbose:
2580 ui.write(decor[ctx.flags(f)])
2580 ui.write(decor[ctx.flags(f)])
2581 ui.write("%s\n" % f)
2581 ui.write("%s\n" % f)
2582
2582
2583 def merge(ui, repo, node=None, **opts):
2583 def merge(ui, repo, node=None, **opts):
2584 """merge working directory with another revision
2584 """merge working directory with another revision
2585
2585
2586 The current working directory is updated with all changes made in
2586 The current working directory is updated with all changes made in
2587 the requested revision since the last common predecessor revision.
2587 the requested revision since the last common predecessor revision.
2588
2588
2589 Files that changed between either parent are marked as changed for
2589 Files that changed between either parent are marked as changed for
2590 the next commit and a commit must be performed before any further
2590 the next commit and a commit must be performed before any further
2591 updates to the repository are allowed. The next commit will have
2591 updates to the repository are allowed. The next commit will have
2592 two parents.
2592 two parents.
2593
2593
2594 ``--tool`` can be used to specify the merge tool used for file
2594 ``--tool`` can be used to specify the merge tool used for file
2595 merges. It overrides the HGMERGE environment variable and your
2595 merges. It overrides the HGMERGE environment variable and your
2596 configuration files.
2596 configuration files.
2597
2597
2598 If no revision is specified, the working directory's parent is a
2598 If no revision is specified, the working directory's parent is a
2599 head revision, and the current branch contains exactly one other
2599 head revision, and the current branch contains exactly one other
2600 head, the other head is merged with by default. Otherwise, an
2600 head, the other head is merged with by default. Otherwise, an
2601 explicit revision with which to merge with must be provided.
2601 explicit revision with which to merge with must be provided.
2602
2602
2603 :hg:`resolve` must be used to resolve unresolved files.
2603 :hg:`resolve` must be used to resolve unresolved files.
2604
2604
2605 To undo an uncommitted merge, use :hg:`update --clean .` which
2605 To undo an uncommitted merge, use :hg:`update --clean .` which
2606 will check out a clean copy of the original merge parent, losing
2606 will check out a clean copy of the original merge parent, losing
2607 all changes.
2607 all changes.
2608
2608
2609 Returns 0 on success, 1 if there are unresolved files.
2609 Returns 0 on success, 1 if there are unresolved files.
2610 """
2610 """
2611
2611
2612 if opts.get('rev') and node:
2612 if opts.get('rev') and node:
2613 raise util.Abort(_("please specify just one revision"))
2613 raise util.Abort(_("please specify just one revision"))
2614 if not node:
2614 if not node:
2615 node = opts.get('rev')
2615 node = opts.get('rev')
2616
2616
2617 if not node:
2617 if not node:
2618 branch = repo.changectx(None).branch()
2618 branch = repo.changectx(None).branch()
2619 bheads = repo.branchheads(branch)
2619 bheads = repo.branchheads(branch)
2620 if len(bheads) > 2:
2620 if len(bheads) > 2:
2621 raise util.Abort(_(
2621 raise util.Abort(_(
2622 'branch \'%s\' has %d heads - '
2622 'branch \'%s\' has %d heads - '
2623 'please merge with an explicit rev\n'
2623 'please merge with an explicit rev\n'
2624 '(run \'hg heads .\' to see heads)')
2624 '(run \'hg heads .\' to see heads)')
2625 % (branch, len(bheads)))
2625 % (branch, len(bheads)))
2626
2626
2627 parent = repo.dirstate.parents()[0]
2627 parent = repo.dirstate.parents()[0]
2628 if len(bheads) == 1:
2628 if len(bheads) == 1:
2629 if len(repo.heads()) > 1:
2629 if len(repo.heads()) > 1:
2630 raise util.Abort(_(
2630 raise util.Abort(_(
2631 'branch \'%s\' has one head - '
2631 'branch \'%s\' has one head - '
2632 'please merge with an explicit rev\n'
2632 'please merge with an explicit rev\n'
2633 '(run \'hg heads\' to see all heads)')
2633 '(run \'hg heads\' to see all heads)')
2634 % branch)
2634 % branch)
2635 msg = _('there is nothing to merge')
2635 msg = _('there is nothing to merge')
2636 if parent != repo.lookup(repo[None].branch()):
2636 if parent != repo.lookup(repo[None].branch()):
2637 msg = _('%s - use "hg update" instead') % msg
2637 msg = _('%s - use "hg update" instead') % msg
2638 raise util.Abort(msg)
2638 raise util.Abort(msg)
2639
2639
2640 if parent not in bheads:
2640 if parent not in bheads:
2641 raise util.Abort(_('working dir not at a head rev - '
2641 raise util.Abort(_('working dir not at a head rev - '
2642 'use "hg update" or merge with an explicit rev'))
2642 'use "hg update" or merge with an explicit rev'))
2643 node = parent == bheads[0] and bheads[-1] or bheads[0]
2643 node = parent == bheads[0] and bheads[-1] or bheads[0]
2644
2644
2645 if opts.get('preview'):
2645 if opts.get('preview'):
2646 # find nodes that are ancestors of p2 but not of p1
2646 # find nodes that are ancestors of p2 but not of p1
2647 p1 = repo.lookup('.')
2647 p1 = repo.lookup('.')
2648 p2 = repo.lookup(node)
2648 p2 = repo.lookup(node)
2649 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2649 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2650
2650
2651 displayer = cmdutil.show_changeset(ui, repo, opts)
2651 displayer = cmdutil.show_changeset(ui, repo, opts)
2652 for node in nodes:
2652 for node in nodes:
2653 displayer.show(repo[node])
2653 displayer.show(repo[node])
2654 displayer.close()
2654 displayer.close()
2655 return 0
2655 return 0
2656
2656
2657 try:
2657 try:
2658 # ui.forcemerge is an internal variable, do not document
2658 # ui.forcemerge is an internal variable, do not document
2659 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2659 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2660 return hg.merge(repo, node, force=opts.get('force'))
2660 return hg.merge(repo, node, force=opts.get('force'))
2661 finally:
2661 finally:
2662 ui.setconfig('ui', 'forcemerge', '')
2662 ui.setconfig('ui', 'forcemerge', '')
2663
2663
2664 def outgoing(ui, repo, dest=None, **opts):
2664 def outgoing(ui, repo, dest=None, **opts):
2665 """show changesets not found in the destination
2665 """show changesets not found in the destination
2666
2666
2667 Show changesets not found in the specified destination repository
2667 Show changesets not found in the specified destination repository
2668 or the default push location. These are the changesets that would
2668 or the default push location. These are the changesets that would
2669 be pushed if a push was requested.
2669 be pushed if a push was requested.
2670
2670
2671 See pull for details of valid destination formats.
2671 See pull for details of valid destination formats.
2672
2672
2673 Returns 0 if there are outgoing changes, 1 otherwise.
2673 Returns 0 if there are outgoing changes, 1 otherwise.
2674 """
2674 """
2675 ret = hg.outgoing(ui, repo, dest, opts)
2675 ret = hg.outgoing(ui, repo, dest, opts)
2676 return ret
2676 return ret
2677
2677
2678 def parents(ui, repo, file_=None, **opts):
2678 def parents(ui, repo, file_=None, **opts):
2679 """show the parents of the working directory or revision
2679 """show the parents of the working directory or revision
2680
2680
2681 Print the working directory's parent revisions. If a revision is
2681 Print the working directory's parent revisions. If a revision is
2682 given via -r/--rev, the parent of that revision will be printed.
2682 given via -r/--rev, the parent of that revision will be printed.
2683 If a file argument is given, the revision in which the file was
2683 If a file argument is given, the revision in which the file was
2684 last changed (before the working directory revision or the
2684 last changed (before the working directory revision or the
2685 argument to --rev if given) is printed.
2685 argument to --rev if given) is printed.
2686
2686
2687 Returns 0 on success.
2687 Returns 0 on success.
2688 """
2688 """
2689 rev = opts.get('rev')
2689 rev = opts.get('rev')
2690 if rev:
2690 if rev:
2691 ctx = repo[rev]
2691 ctx = repo[rev]
2692 else:
2692 else:
2693 ctx = repo[None]
2693 ctx = repo[None]
2694
2694
2695 if file_:
2695 if file_:
2696 m = cmdutil.match(repo, (file_,), opts)
2696 m = cmdutil.match(repo, (file_,), opts)
2697 if m.anypats() or len(m.files()) != 1:
2697 if m.anypats() or len(m.files()) != 1:
2698 raise util.Abort(_('can only specify an explicit filename'))
2698 raise util.Abort(_('can only specify an explicit filename'))
2699 file_ = m.files()[0]
2699 file_ = m.files()[0]
2700 filenodes = []
2700 filenodes = []
2701 for cp in ctx.parents():
2701 for cp in ctx.parents():
2702 if not cp:
2702 if not cp:
2703 continue
2703 continue
2704 try:
2704 try:
2705 filenodes.append(cp.filenode(file_))
2705 filenodes.append(cp.filenode(file_))
2706 except error.LookupError:
2706 except error.LookupError:
2707 pass
2707 pass
2708 if not filenodes:
2708 if not filenodes:
2709 raise util.Abort(_("'%s' not found in manifest!") % file_)
2709 raise util.Abort(_("'%s' not found in manifest!") % file_)
2710 fl = repo.file(file_)
2710 fl = repo.file(file_)
2711 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2711 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2712 else:
2712 else:
2713 p = [cp.node() for cp in ctx.parents()]
2713 p = [cp.node() for cp in ctx.parents()]
2714
2714
2715 displayer = cmdutil.show_changeset(ui, repo, opts)
2715 displayer = cmdutil.show_changeset(ui, repo, opts)
2716 for n in p:
2716 for n in p:
2717 if n != nullid:
2717 if n != nullid:
2718 displayer.show(repo[n])
2718 displayer.show(repo[n])
2719 displayer.close()
2719 displayer.close()
2720
2720
2721 def paths(ui, repo, search=None):
2721 def paths(ui, repo, search=None):
2722 """show aliases for remote repositories
2722 """show aliases for remote repositories
2723
2723
2724 Show definition of symbolic path name NAME. If no name is given,
2724 Show definition of symbolic path name NAME. If no name is given,
2725 show definition of all available names.
2725 show definition of all available names.
2726
2726
2727 Path names are defined in the [paths] section of your
2727 Path names are defined in the [paths] section of your
2728 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2728 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2729 repository, ``.hg/hgrc`` is used, too.
2729 repository, ``.hg/hgrc`` is used, too.
2730
2730
2731 The path names ``default`` and ``default-push`` have a special
2731 The path names ``default`` and ``default-push`` have a special
2732 meaning. When performing a push or pull operation, they are used
2732 meaning. When performing a push or pull operation, they are used
2733 as fallbacks if no location is specified on the command-line.
2733 as fallbacks if no location is specified on the command-line.
2734 When ``default-push`` is set, it will be used for push and
2734 When ``default-push`` is set, it will be used for push and
2735 ``default`` will be used for pull; otherwise ``default`` is used
2735 ``default`` will be used for pull; otherwise ``default`` is used
2736 as the fallback for both. When cloning a repository, the clone
2736 as the fallback for both. When cloning a repository, the clone
2737 source is written as ``default`` in ``.hg/hgrc``. Note that
2737 source is written as ``default`` in ``.hg/hgrc``. Note that
2738 ``default`` and ``default-push`` apply to all inbound (e.g.
2738 ``default`` and ``default-push`` apply to all inbound (e.g.
2739 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2739 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2740 :hg:`bundle`) operations.
2740 :hg:`bundle`) operations.
2741
2741
2742 See :hg:`help urls` for more information.
2742 See :hg:`help urls` for more information.
2743
2743
2744 Returns 0 on success.
2744 Returns 0 on success.
2745 """
2745 """
2746 if search:
2746 if search:
2747 for name, path in ui.configitems("paths"):
2747 for name, path in ui.configitems("paths"):
2748 if name == search:
2748 if name == search:
2749 ui.write("%s\n" % url.hidepassword(path))
2749 ui.write("%s\n" % url.hidepassword(path))
2750 return
2750 return
2751 ui.warn(_("not found!\n"))
2751 ui.warn(_("not found!\n"))
2752 return 1
2752 return 1
2753 else:
2753 else:
2754 for name, path in ui.configitems("paths"):
2754 for name, path in ui.configitems("paths"):
2755 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2755 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2756
2756
2757 def postincoming(ui, repo, modheads, optupdate, checkout):
2757 def postincoming(ui, repo, modheads, optupdate, checkout):
2758 if modheads == 0:
2758 if modheads == 0:
2759 return
2759 return
2760 if optupdate:
2760 if optupdate:
2761 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2761 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2762 return hg.update(repo, checkout)
2762 return hg.update(repo, checkout)
2763 else:
2763 else:
2764 ui.status(_("not updating, since new heads added\n"))
2764 ui.status(_("not updating, since new heads added\n"))
2765 if modheads > 1:
2765 if modheads > 1:
2766 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2766 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2767 else:
2767 else:
2768 ui.status(_("(run 'hg update' to get a working copy)\n"))
2768 ui.status(_("(run 'hg update' to get a working copy)\n"))
2769
2769
2770 def pull(ui, repo, source="default", **opts):
2770 def pull(ui, repo, source="default", **opts):
2771 """pull changes from the specified source
2771 """pull changes from the specified source
2772
2772
2773 Pull changes from a remote repository to a local one.
2773 Pull changes from a remote repository to a local one.
2774
2774
2775 This finds all changes from the repository at the specified path
2775 This finds all changes from the repository at the specified path
2776 or URL and adds them to a local repository (the current one unless
2776 or URL and adds them to a local repository (the current one unless
2777 -R is specified). By default, this does not update the copy of the
2777 -R is specified). By default, this does not update the copy of the
2778 project in the working directory.
2778 project in the working directory.
2779
2779
2780 Use :hg:`incoming` if you want to see what would have been added
2780 Use :hg:`incoming` if you want to see what would have been added
2781 by a pull at the time you issued this command. If you then decide
2781 by a pull at the time you issued this command. If you then decide
2782 to add those changes to the repository, you should use :hg:`pull
2782 to add those changes to the repository, you should use :hg:`pull
2783 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2783 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2784
2784
2785 If SOURCE is omitted, the 'default' path will be used.
2785 If SOURCE is omitted, the 'default' path will be used.
2786 See :hg:`help urls` for more information.
2786 See :hg:`help urls` for more information.
2787
2787
2788 Returns 0 on success, 1 if an update had unresolved files.
2788 Returns 0 on success, 1 if an update had unresolved files.
2789 """
2789 """
2790 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2790 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2791 other = hg.repository(hg.remoteui(repo, opts), source)
2791 other = hg.repository(hg.remoteui(repo, opts), source)
2792 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2792 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2793 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2793 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2794 if revs:
2794 if revs:
2795 try:
2795 try:
2796 revs = [other.lookup(rev) for rev in revs]
2796 revs = [other.lookup(rev) for rev in revs]
2797 except error.CapabilityError:
2797 except error.CapabilityError:
2798 err = _("other repository doesn't support revision lookup, "
2798 err = _("other repository doesn't support revision lookup, "
2799 "so a rev cannot be specified.")
2799 "so a rev cannot be specified.")
2800 raise util.Abort(err)
2800 raise util.Abort(err)
2801
2801
2802 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2802 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2803 if checkout:
2803 if checkout:
2804 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2804 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2805 repo._subtoppath = source
2805 repo._subtoppath = source
2806 try:
2806 try:
2807 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2807 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2808 finally:
2808 finally:
2809 del repo._subtoppath
2809 del repo._subtoppath
2810
2810
2811 def push(ui, repo, dest=None, **opts):
2811 def push(ui, repo, dest=None, **opts):
2812 """push changes to the specified destination
2812 """push changes to the specified destination
2813
2813
2814 Push changesets from the local repository to the specified
2814 Push changesets from the local repository to the specified
2815 destination.
2815 destination.
2816
2816
2817 This operation is symmetrical to pull: it is identical to a pull
2817 This operation is symmetrical to pull: it is identical to a pull
2818 in the destination repository from the current one.
2818 in the destination repository from the current one.
2819
2819
2820 By default, push will not allow creation of new heads at the
2820 By default, push will not allow creation of new heads at the
2821 destination, since multiple heads would make it unclear which head
2821 destination, since multiple heads would make it unclear which head
2822 to use. In this situation, it is recommended to pull and merge
2822 to use. In this situation, it is recommended to pull and merge
2823 before pushing.
2823 before pushing.
2824
2824
2825 Use --new-branch if you want to allow push to create a new named
2825 Use --new-branch if you want to allow push to create a new named
2826 branch that is not present at the destination. This allows you to
2826 branch that is not present at the destination. This allows you to
2827 only create a new branch without forcing other changes.
2827 only create a new branch without forcing other changes.
2828
2828
2829 Use -f/--force to override the default behavior and push all
2829 Use -f/--force to override the default behavior and push all
2830 changesets on all branches.
2830 changesets on all branches.
2831
2831
2832 If -r/--rev is used, the specified revision and all its ancestors
2832 If -r/--rev is used, the specified revision and all its ancestors
2833 will be pushed to the remote repository.
2833 will be pushed to the remote repository.
2834
2834
2835 Please see :hg:`help urls` for important details about ``ssh://``
2835 Please see :hg:`help urls` for important details about ``ssh://``
2836 URLs. If DESTINATION is omitted, a default path will be used.
2836 URLs. If DESTINATION is omitted, a default path will be used.
2837
2837
2838 Returns 0 if push was successful, 1 if nothing to push.
2838 Returns 0 if push was successful, 1 if nothing to push.
2839 """
2839 """
2840 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2840 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2841 dest, branches = hg.parseurl(dest, opts.get('branch'))
2841 dest, branches = hg.parseurl(dest, opts.get('branch'))
2842 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2842 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2843 other = hg.repository(hg.remoteui(repo, opts), dest)
2843 other = hg.repository(hg.remoteui(repo, opts), dest)
2844 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2844 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2845 if revs:
2845 if revs:
2846 revs = [repo.lookup(rev) for rev in revs]
2846 revs = [repo.lookup(rev) for rev in revs]
2847
2847
2848 repo._subtoppath = dest
2848 repo._subtoppath = dest
2849 try:
2849 try:
2850 # push subrepos depth-first for coherent ordering
2850 # push subrepos depth-first for coherent ordering
2851 c = repo['']
2851 c = repo['']
2852 subs = c.substate # only repos that are committed
2852 subs = c.substate # only repos that are committed
2853 for s in sorted(subs):
2853 for s in sorted(subs):
2854 if not c.sub(s).push(opts.get('force')):
2854 if not c.sub(s).push(opts.get('force')):
2855 return False
2855 return False
2856 finally:
2856 finally:
2857 del repo._subtoppath
2857 del repo._subtoppath
2858 r = repo.push(other, opts.get('force'), revs=revs,
2858 r = repo.push(other, opts.get('force'), revs=revs,
2859 newbranch=opts.get('new_branch'))
2859 newbranch=opts.get('new_branch'))
2860 return r == 0
2860 return r == 0
2861
2861
2862 def recover(ui, repo):
2862 def recover(ui, repo):
2863 """roll back an interrupted transaction
2863 """roll back an interrupted transaction
2864
2864
2865 Recover from an interrupted commit or pull.
2865 Recover from an interrupted commit or pull.
2866
2866
2867 This command tries to fix the repository status after an
2867 This command tries to fix the repository status after an
2868 interrupted operation. It should only be necessary when Mercurial
2868 interrupted operation. It should only be necessary when Mercurial
2869 suggests it.
2869 suggests it.
2870
2870
2871 Returns 0 if successful, 1 if nothing to recover or verify fails.
2871 Returns 0 if successful, 1 if nothing to recover or verify fails.
2872 """
2872 """
2873 if repo.recover():
2873 if repo.recover():
2874 return hg.verify(repo)
2874 return hg.verify(repo)
2875 return 1
2875 return 1
2876
2876
2877 def remove(ui, repo, *pats, **opts):
2877 def remove(ui, repo, *pats, **opts):
2878 """remove the specified files on the next commit
2878 """remove the specified files on the next commit
2879
2879
2880 Schedule the indicated files for removal from the repository.
2880 Schedule the indicated files for removal from the repository.
2881
2881
2882 This only removes files from the current branch, not from the
2882 This only removes files from the current branch, not from the
2883 entire project history. -A/--after can be used to remove only
2883 entire project history. -A/--after can be used to remove only
2884 files that have already been deleted, -f/--force can be used to
2884 files that have already been deleted, -f/--force can be used to
2885 force deletion, and -Af can be used to remove files from the next
2885 force deletion, and -Af can be used to remove files from the next
2886 revision without deleting them from the working directory.
2886 revision without deleting them from the working directory.
2887
2887
2888 The following table details the behavior of remove for different
2888 The following table details the behavior of remove for different
2889 file states (columns) and option combinations (rows). The file
2889 file states (columns) and option combinations (rows). The file
2890 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2890 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2891 reported by :hg:`status`). The actions are Warn, Remove (from
2891 reported by :hg:`status`). The actions are Warn, Remove (from
2892 branch) and Delete (from disk)::
2892 branch) and Delete (from disk)::
2893
2893
2894 A C M !
2894 A C M !
2895 none W RD W R
2895 none W RD W R
2896 -f R RD RD R
2896 -f R RD RD R
2897 -A W W W R
2897 -A W W W R
2898 -Af R R R R
2898 -Af R R R R
2899
2899
2900 This command schedules the files to be removed at the next commit.
2900 This command schedules the files to be removed at the next commit.
2901 To undo a remove before that, see :hg:`revert`.
2901 To undo a remove before that, see :hg:`revert`.
2902
2902
2903 Returns 0 on success, 1 if any warnings encountered.
2903 Returns 0 on success, 1 if any warnings encountered.
2904 """
2904 """
2905
2905
2906 ret = 0
2906 ret = 0
2907 after, force = opts.get('after'), opts.get('force')
2907 after, force = opts.get('after'), opts.get('force')
2908 if not pats and not after:
2908 if not pats and not after:
2909 raise util.Abort(_('no files specified'))
2909 raise util.Abort(_('no files specified'))
2910
2910
2911 m = cmdutil.match(repo, pats, opts)
2911 m = cmdutil.match(repo, pats, opts)
2912 s = repo.status(match=m, clean=True)
2912 s = repo.status(match=m, clean=True)
2913 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2913 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2914
2914
2915 for f in m.files():
2915 for f in m.files():
2916 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2916 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2917 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2917 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2918 ret = 1
2918 ret = 1
2919
2919
2920 if force:
2920 if force:
2921 remove, forget = modified + deleted + clean, added
2921 remove, forget = modified + deleted + clean, added
2922 elif after:
2922 elif after:
2923 remove, forget = deleted, []
2923 remove, forget = deleted, []
2924 for f in modified + added + clean:
2924 for f in modified + added + clean:
2925 ui.warn(_('not removing %s: file still exists (use -f'
2925 ui.warn(_('not removing %s: file still exists (use -f'
2926 ' to force removal)\n') % m.rel(f))
2926 ' to force removal)\n') % m.rel(f))
2927 ret = 1
2927 ret = 1
2928 else:
2928 else:
2929 remove, forget = deleted + clean, []
2929 remove, forget = deleted + clean, []
2930 for f in modified:
2930 for f in modified:
2931 ui.warn(_('not removing %s: file is modified (use -f'
2931 ui.warn(_('not removing %s: file is modified (use -f'
2932 ' to force removal)\n') % m.rel(f))
2932 ' to force removal)\n') % m.rel(f))
2933 ret = 1
2933 ret = 1
2934 for f in added:
2934 for f in added:
2935 ui.warn(_('not removing %s: file has been marked for add (use -f'
2935 ui.warn(_('not removing %s: file has been marked for add (use -f'
2936 ' to force removal)\n') % m.rel(f))
2936 ' to force removal)\n') % m.rel(f))
2937 ret = 1
2937 ret = 1
2938
2938
2939 for f in sorted(remove + forget):
2939 for f in sorted(remove + forget):
2940 if ui.verbose or not m.exact(f):
2940 if ui.verbose or not m.exact(f):
2941 ui.status(_('removing %s\n') % m.rel(f))
2941 ui.status(_('removing %s\n') % m.rel(f))
2942
2942
2943 repo[None].forget(forget)
2943 repo[None].forget(forget)
2944 repo[None].remove(remove, unlink=not after)
2944 repo[None].remove(remove, unlink=not after)
2945 return ret
2945 return ret
2946
2946
2947 def rename(ui, repo, *pats, **opts):
2947 def rename(ui, repo, *pats, **opts):
2948 """rename files; equivalent of copy + remove
2948 """rename files; equivalent of copy + remove
2949
2949
2950 Mark dest as copies of sources; mark sources for deletion. If dest
2950 Mark dest as copies of sources; mark sources for deletion. If dest
2951 is a directory, copies are put in that directory. If dest is a
2951 is a directory, copies are put in that directory. If dest is a
2952 file, there can only be one source.
2952 file, there can only be one source.
2953
2953
2954 By default, this command copies the contents of files as they
2954 By default, this command copies the contents of files as they
2955 exist in the working directory. If invoked with -A/--after, the
2955 exist in the working directory. If invoked with -A/--after, the
2956 operation is recorded, but no copying is performed.
2956 operation is recorded, but no copying is performed.
2957
2957
2958 This command takes effect at the next commit. To undo a rename
2958 This command takes effect at the next commit. To undo a rename
2959 before that, see :hg:`revert`.
2959 before that, see :hg:`revert`.
2960
2960
2961 Returns 0 on success, 1 if errors are encountered.
2961 Returns 0 on success, 1 if errors are encountered.
2962 """
2962 """
2963 wlock = repo.wlock(False)
2963 wlock = repo.wlock(False)
2964 try:
2964 try:
2965 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2965 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2966 finally:
2966 finally:
2967 wlock.release()
2967 wlock.release()
2968
2968
2969 def resolve(ui, repo, *pats, **opts):
2969 def resolve(ui, repo, *pats, **opts):
2970 """redo merges or set/view the merge status of files
2970 """redo merges or set/view the merge status of files
2971
2971
2972 Merges with unresolved conflicts are often the result of
2972 Merges with unresolved conflicts are often the result of
2973 non-interactive merging using the ``internal:merge`` configuration
2973 non-interactive merging using the ``internal:merge`` configuration
2974 setting, or a command-line merge tool like ``diff3``. The resolve
2974 setting, or a command-line merge tool like ``diff3``. The resolve
2975 command is used to manage the files involved in a merge, after
2975 command is used to manage the files involved in a merge, after
2976 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2976 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2977 working directory must have two parents).
2977 working directory must have two parents).
2978
2978
2979 The resolve command can be used in the following ways:
2979 The resolve command can be used in the following ways:
2980
2980
2981 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2981 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2982 files, discarding any previous merge attempts. Re-merging is not
2982 files, discarding any previous merge attempts. Re-merging is not
2983 performed for files already marked as resolved. Use ``--all/-a``
2983 performed for files already marked as resolved. Use ``--all/-a``
2984 to selects all unresolved files. ``--tool`` can be used to specify
2984 to selects all unresolved files. ``--tool`` can be used to specify
2985 the merge tool used for the given files. It overrides the HGMERGE
2985 the merge tool used for the given files. It overrides the HGMERGE
2986 environment variable and your configuration files.
2986 environment variable and your configuration files.
2987
2987
2988 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2988 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2989 (e.g. after having manually fixed-up the files). The default is
2989 (e.g. after having manually fixed-up the files). The default is
2990 to mark all unresolved files.
2990 to mark all unresolved files.
2991
2991
2992 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2992 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2993 default is to mark all resolved files.
2993 default is to mark all resolved files.
2994
2994
2995 - :hg:`resolve -l`: list files which had or still have conflicts.
2995 - :hg:`resolve -l`: list files which had or still have conflicts.
2996 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2996 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2997
2997
2998 Note that Mercurial will not let you commit files with unresolved
2998 Note that Mercurial will not let you commit files with unresolved
2999 merge conflicts. You must use :hg:`resolve -m ...` before you can
2999 merge conflicts. You must use :hg:`resolve -m ...` before you can
3000 commit after a conflicting merge.
3000 commit after a conflicting merge.
3001
3001
3002 Returns 0 on success, 1 if any files fail a resolve attempt.
3002 Returns 0 on success, 1 if any files fail a resolve attempt.
3003 """
3003 """
3004
3004
3005 all, mark, unmark, show, nostatus = \
3005 all, mark, unmark, show, nostatus = \
3006 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3006 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3007
3007
3008 if (show and (mark or unmark)) or (mark and unmark):
3008 if (show and (mark or unmark)) or (mark and unmark):
3009 raise util.Abort(_("too many options specified"))
3009 raise util.Abort(_("too many options specified"))
3010 if pats and all:
3010 if pats and all:
3011 raise util.Abort(_("can't specify --all and patterns"))
3011 raise util.Abort(_("can't specify --all and patterns"))
3012 if not (all or pats or show or mark or unmark):
3012 if not (all or pats or show or mark or unmark):
3013 raise util.Abort(_('no files or directories specified; '
3013 raise util.Abort(_('no files or directories specified; '
3014 'use --all to remerge all files'))
3014 'use --all to remerge all files'))
3015
3015
3016 ms = mergemod.mergestate(repo)
3016 ms = mergemod.mergestate(repo)
3017 m = cmdutil.match(repo, pats, opts)
3017 m = cmdutil.match(repo, pats, opts)
3018 ret = 0
3018 ret = 0
3019
3019
3020 for f in ms:
3020 for f in ms:
3021 if m(f):
3021 if m(f):
3022 if show:
3022 if show:
3023 if nostatus:
3023 if nostatus:
3024 ui.write("%s\n" % f)
3024 ui.write("%s\n" % f)
3025 else:
3025 else:
3026 ui.write("%s %s\n" % (ms[f].upper(), f),
3026 ui.write("%s %s\n" % (ms[f].upper(), f),
3027 label='resolve.' +
3027 label='resolve.' +
3028 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3028 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3029 elif mark:
3029 elif mark:
3030 ms.mark(f, "r")
3030 ms.mark(f, "r")
3031 elif unmark:
3031 elif unmark:
3032 ms.mark(f, "u")
3032 ms.mark(f, "u")
3033 else:
3033 else:
3034 wctx = repo[None]
3034 wctx = repo[None]
3035 mctx = wctx.parents()[-1]
3035 mctx = wctx.parents()[-1]
3036
3036
3037 # backup pre-resolve (merge uses .orig for its own purposes)
3037 # backup pre-resolve (merge uses .orig for its own purposes)
3038 a = repo.wjoin(f)
3038 a = repo.wjoin(f)
3039 util.copyfile(a, a + ".resolve")
3039 util.copyfile(a, a + ".resolve")
3040
3040
3041 try:
3041 try:
3042 # resolve file
3042 # resolve file
3043 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3043 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3044 if ms.resolve(f, wctx, mctx):
3044 if ms.resolve(f, wctx, mctx):
3045 ret = 1
3045 ret = 1
3046 finally:
3046 finally:
3047 ui.setconfig('ui', 'forcemerge', '')
3047 ui.setconfig('ui', 'forcemerge', '')
3048
3048
3049 # replace filemerge's .orig file with our resolve file
3049 # replace filemerge's .orig file with our resolve file
3050 util.rename(a + ".resolve", a + ".orig")
3050 util.rename(a + ".resolve", a + ".orig")
3051
3051
3052 ms.commit()
3052 ms.commit()
3053 return ret
3053 return ret
3054
3054
3055 def revert(ui, repo, *pats, **opts):
3055 def revert(ui, repo, *pats, **opts):
3056 """restore individual files or directories to an earlier state
3056 """restore individual files or directories to an earlier state
3057
3057
3058 .. note::
3058 .. note::
3059 This command is most likely not what you are looking for.
3059 This command is most likely not what you are looking for.
3060 Revert will partially overwrite content in the working
3060 Revert will partially overwrite content in the working
3061 directory without changing the working directory parents. Use
3061 directory without changing the working directory parents. Use
3062 :hg:`update -r rev` to check out earlier revisions, or
3062 :hg:`update -r rev` to check out earlier revisions, or
3063 :hg:`update --clean .` to undo a merge which has added another
3063 :hg:`update --clean .` to undo a merge which has added another
3064 parent.
3064 parent.
3065
3065
3066 With no revision specified, revert the named files or directories
3066 With no revision specified, revert the named files or directories
3067 to the contents they had in the parent of the working directory.
3067 to the contents they had in the parent of the working directory.
3068 This restores the contents of the affected files to an unmodified
3068 This restores the contents of the affected files to an unmodified
3069 state and unschedules adds, removes, copies, and renames. If the
3069 state and unschedules adds, removes, copies, and renames. If the
3070 working directory has two parents, you must explicitly specify a
3070 working directory has two parents, you must explicitly specify a
3071 revision.
3071 revision.
3072
3072
3073 Using the -r/--rev option, revert the given files or directories
3073 Using the -r/--rev option, revert the given files or directories
3074 to their contents as of a specific revision. This can be helpful
3074 to their contents as of a specific revision. This can be helpful
3075 to "roll back" some or all of an earlier change. See :hg:`help
3075 to "roll back" some or all of an earlier change. See :hg:`help
3076 dates` for a list of formats valid for -d/--date.
3076 dates` for a list of formats valid for -d/--date.
3077
3077
3078 Revert modifies the working directory. It does not commit any
3078 Revert modifies the working directory. It does not commit any
3079 changes, or change the parent of the working directory. If you
3079 changes, or change the parent of the working directory. If you
3080 revert to a revision other than the parent of the working
3080 revert to a revision other than the parent of the working
3081 directory, the reverted files will thus appear modified
3081 directory, the reverted files will thus appear modified
3082 afterwards.
3082 afterwards.
3083
3083
3084 If a file has been deleted, it is restored. If the executable mode
3084 If a file has been deleted, it is restored. If the executable mode
3085 of a file was changed, it is reset.
3085 of a file was changed, it is reset.
3086
3086
3087 If names are given, all files matching the names are reverted.
3087 If names are given, all files matching the names are reverted.
3088 If no arguments are given, no files are reverted.
3088 If no arguments are given, no files are reverted.
3089
3089
3090 Modified files are saved with a .orig suffix before reverting.
3090 Modified files are saved with a .orig suffix before reverting.
3091 To disable these backups, use --no-backup.
3091 To disable these backups, use --no-backup.
3092
3092
3093 Returns 0 on success.
3093 Returns 0 on success.
3094 """
3094 """
3095
3095
3096 if opts.get("date"):
3096 if opts.get("date"):
3097 if opts.get("rev"):
3097 if opts.get("rev"):
3098 raise util.Abort(_("you can't specify a revision and a date"))
3098 raise util.Abort(_("you can't specify a revision and a date"))
3099 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3099 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3100
3100
3101 if not pats and not opts.get('all'):
3101 if not pats and not opts.get('all'):
3102 raise util.Abort(_('no files or directories specified; '
3102 raise util.Abort(_('no files or directories specified; '
3103 'use --all to revert the whole repo'))
3103 'use --all to revert the whole repo'))
3104
3104
3105 parent, p2 = repo.dirstate.parents()
3105 parent, p2 = repo.dirstate.parents()
3106 if not opts.get('rev') and p2 != nullid:
3106 if not opts.get('rev') and p2 != nullid:
3107 raise util.Abort(_('uncommitted merge - please provide a '
3107 raise util.Abort(_('uncommitted merge - please provide a '
3108 'specific revision'))
3108 'specific revision'))
3109 ctx = repo[opts.get('rev')]
3109 ctx = repo[opts.get('rev')]
3110 node = ctx.node()
3110 node = ctx.node()
3111 mf = ctx.manifest()
3111 mf = ctx.manifest()
3112 if node == parent:
3112 if node == parent:
3113 pmf = mf
3113 pmf = mf
3114 else:
3114 else:
3115 pmf = None
3115 pmf = None
3116
3116
3117 # need all matching names in dirstate and manifest of target rev,
3117 # need all matching names in dirstate and manifest of target rev,
3118 # so have to walk both. do not print errors if files exist in one
3118 # so have to walk both. do not print errors if files exist in one
3119 # but not other.
3119 # but not other.
3120
3120
3121 names = {}
3121 names = {}
3122
3122
3123 wlock = repo.wlock()
3123 wlock = repo.wlock()
3124 try:
3124 try:
3125 # walk dirstate.
3125 # walk dirstate.
3126
3126
3127 m = cmdutil.match(repo, pats, opts)
3127 m = cmdutil.match(repo, pats, opts)
3128 m.bad = lambda x, y: False
3128 m.bad = lambda x, y: False
3129 for abs in repo.walk(m):
3129 for abs in repo.walk(m):
3130 names[abs] = m.rel(abs), m.exact(abs)
3130 names[abs] = m.rel(abs), m.exact(abs)
3131
3131
3132 # walk target manifest.
3132 # walk target manifest.
3133
3133
3134 def badfn(path, msg):
3134 def badfn(path, msg):
3135 if path in names:
3135 if path in names:
3136 return
3136 return
3137 path_ = path + '/'
3137 path_ = path + '/'
3138 for f in names:
3138 for f in names:
3139 if f.startswith(path_):
3139 if f.startswith(path_):
3140 return
3140 return
3141 ui.warn("%s: %s\n" % (m.rel(path), msg))
3141 ui.warn("%s: %s\n" % (m.rel(path), msg))
3142
3142
3143 m = cmdutil.match(repo, pats, opts)
3143 m = cmdutil.match(repo, pats, opts)
3144 m.bad = badfn
3144 m.bad = badfn
3145 for abs in repo[node].walk(m):
3145 for abs in repo[node].walk(m):
3146 if abs not in names:
3146 if abs not in names:
3147 names[abs] = m.rel(abs), m.exact(abs)
3147 names[abs] = m.rel(abs), m.exact(abs)
3148
3148
3149 m = cmdutil.matchfiles(repo, names)
3149 m = cmdutil.matchfiles(repo, names)
3150 changes = repo.status(match=m)[:4]
3150 changes = repo.status(match=m)[:4]
3151 modified, added, removed, deleted = map(set, changes)
3151 modified, added, removed, deleted = map(set, changes)
3152
3152
3153 # if f is a rename, also revert the source
3153 # if f is a rename, also revert the source
3154 cwd = repo.getcwd()
3154 cwd = repo.getcwd()
3155 for f in added:
3155 for f in added:
3156 src = repo.dirstate.copied(f)
3156 src = repo.dirstate.copied(f)
3157 if src and src not in names and repo.dirstate[src] == 'r':
3157 if src and src not in names and repo.dirstate[src] == 'r':
3158 removed.add(src)
3158 removed.add(src)
3159 names[src] = (repo.pathto(src, cwd), True)
3159 names[src] = (repo.pathto(src, cwd), True)
3160
3160
3161 def removeforget(abs):
3161 def removeforget(abs):
3162 if repo.dirstate[abs] == 'a':
3162 if repo.dirstate[abs] == 'a':
3163 return _('forgetting %s\n')
3163 return _('forgetting %s\n')
3164 return _('removing %s\n')
3164 return _('removing %s\n')
3165
3165
3166 revert = ([], _('reverting %s\n'))
3166 revert = ([], _('reverting %s\n'))
3167 add = ([], _('adding %s\n'))
3167 add = ([], _('adding %s\n'))
3168 remove = ([], removeforget)
3168 remove = ([], removeforget)
3169 undelete = ([], _('undeleting %s\n'))
3169 undelete = ([], _('undeleting %s\n'))
3170
3170
3171 disptable = (
3171 disptable = (
3172 # dispatch table:
3172 # dispatch table:
3173 # file state
3173 # file state
3174 # action if in target manifest
3174 # action if in target manifest
3175 # action if not in target manifest
3175 # action if not in target manifest
3176 # make backup if in target manifest
3176 # make backup if in target manifest
3177 # make backup if not in target manifest
3177 # make backup if not in target manifest
3178 (modified, revert, remove, True, True),
3178 (modified, revert, remove, True, True),
3179 (added, revert, remove, True, False),
3179 (added, revert, remove, True, False),
3180 (removed, undelete, None, False, False),
3180 (removed, undelete, None, False, False),
3181 (deleted, revert, remove, False, False),
3181 (deleted, revert, remove, False, False),
3182 )
3182 )
3183
3183
3184 for abs, (rel, exact) in sorted(names.items()):
3184 for abs, (rel, exact) in sorted(names.items()):
3185 mfentry = mf.get(abs)
3185 mfentry = mf.get(abs)
3186 target = repo.wjoin(abs)
3186 target = repo.wjoin(abs)
3187 def handle(xlist, dobackup):
3187 def handle(xlist, dobackup):
3188 xlist[0].append(abs)
3188 xlist[0].append(abs)
3189 if (dobackup and not opts.get('no_backup') and
3189 if (dobackup and not opts.get('no_backup') and
3190 os.path.lexists(target)):
3190 os.path.lexists(target)):
3191 bakname = "%s.orig" % rel
3191 bakname = "%s.orig" % rel
3192 ui.note(_('saving current version of %s as %s\n') %
3192 ui.note(_('saving current version of %s as %s\n') %
3193 (rel, bakname))
3193 (rel, bakname))
3194 if not opts.get('dry_run'):
3194 if not opts.get('dry_run'):
3195 util.rename(target, bakname)
3195 util.rename(target, bakname)
3196 if ui.verbose or not exact:
3196 if ui.verbose or not exact:
3197 msg = xlist[1]
3197 msg = xlist[1]
3198 if not isinstance(msg, basestring):
3198 if not isinstance(msg, basestring):
3199 msg = msg(abs)
3199 msg = msg(abs)
3200 ui.status(msg % rel)
3200 ui.status(msg % rel)
3201 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3201 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3202 if abs not in table:
3202 if abs not in table:
3203 continue
3203 continue
3204 # file has changed in dirstate
3204 # file has changed in dirstate
3205 if mfentry:
3205 if mfentry:
3206 handle(hitlist, backuphit)
3206 handle(hitlist, backuphit)
3207 elif misslist is not None:
3207 elif misslist is not None:
3208 handle(misslist, backupmiss)
3208 handle(misslist, backupmiss)
3209 break
3209 break
3210 else:
3210 else:
3211 if abs not in repo.dirstate:
3211 if abs not in repo.dirstate:
3212 if mfentry:
3212 if mfentry:
3213 handle(add, True)
3213 handle(add, True)
3214 elif exact:
3214 elif exact:
3215 ui.warn(_('file not managed: %s\n') % rel)
3215 ui.warn(_('file not managed: %s\n') % rel)
3216 continue
3216 continue
3217 # file has not changed in dirstate
3217 # file has not changed in dirstate
3218 if node == parent:
3218 if node == parent:
3219 if exact:
3219 if exact:
3220 ui.warn(_('no changes needed to %s\n') % rel)
3220 ui.warn(_('no changes needed to %s\n') % rel)
3221 continue
3221 continue
3222 if pmf is None:
3222 if pmf is None:
3223 # only need parent manifest in this unlikely case,
3223 # only need parent manifest in this unlikely case,
3224 # so do not read by default
3224 # so do not read by default
3225 pmf = repo[parent].manifest()
3225 pmf = repo[parent].manifest()
3226 if abs in pmf:
3226 if abs in pmf:
3227 if mfentry:
3227 if mfentry:
3228 # if version of file is same in parent and target
3228 # if version of file is same in parent and target
3229 # manifests, do nothing
3229 # manifests, do nothing
3230 if (pmf[abs] != mfentry or
3230 if (pmf[abs] != mfentry or
3231 pmf.flags(abs) != mf.flags(abs)):
3231 pmf.flags(abs) != mf.flags(abs)):
3232 handle(revert, False)
3232 handle(revert, False)
3233 else:
3233 else:
3234 handle(remove, False)
3234 handle(remove, False)
3235
3235
3236 if not opts.get('dry_run'):
3236 if not opts.get('dry_run'):
3237 def checkout(f):
3237 def checkout(f):
3238 fc = ctx[f]
3238 fc = ctx[f]
3239 repo.wwrite(f, fc.data(), fc.flags())
3239 repo.wwrite(f, fc.data(), fc.flags())
3240
3240
3241 audit_path = util.path_auditor(repo.root)
3241 audit_path = util.path_auditor(repo.root)
3242 for f in remove[0]:
3242 for f in remove[0]:
3243 if repo.dirstate[f] == 'a':
3243 if repo.dirstate[f] == 'a':
3244 repo.dirstate.forget(f)
3244 repo.dirstate.forget(f)
3245 continue
3245 continue
3246 audit_path(f)
3246 audit_path(f)
3247 try:
3247 try:
3248 util.unlink(repo.wjoin(f))
3248 util.unlink(repo.wjoin(f))
3249 except OSError:
3249 except OSError:
3250 pass
3250 pass
3251 repo.dirstate.remove(f)
3251 repo.dirstate.remove(f)
3252
3252
3253 normal = None
3253 normal = None
3254 if node == parent:
3254 if node == parent:
3255 # We're reverting to our parent. If possible, we'd like status
3255 # We're reverting to our parent. If possible, we'd like status
3256 # to report the file as clean. We have to use normallookup for
3256 # to report the file as clean. We have to use normallookup for
3257 # merges to avoid losing information about merged/dirty files.
3257 # merges to avoid losing information about merged/dirty files.
3258 if p2 != nullid:
3258 if p2 != nullid:
3259 normal = repo.dirstate.normallookup
3259 normal = repo.dirstate.normallookup
3260 else:
3260 else:
3261 normal = repo.dirstate.normal
3261 normal = repo.dirstate.normal
3262 for f in revert[0]:
3262 for f in revert[0]:
3263 checkout(f)
3263 checkout(f)
3264 if normal:
3264 if normal:
3265 normal(f)
3265 normal(f)
3266
3266
3267 for f in add[0]:
3267 for f in add[0]:
3268 checkout(f)
3268 checkout(f)
3269 repo.dirstate.add(f)
3269 repo.dirstate.add(f)
3270
3270
3271 normal = repo.dirstate.normallookup
3271 normal = repo.dirstate.normallookup
3272 if node == parent and p2 == nullid:
3272 if node == parent and p2 == nullid:
3273 normal = repo.dirstate.normal
3273 normal = repo.dirstate.normal
3274 for f in undelete[0]:
3274 for f in undelete[0]:
3275 checkout(f)
3275 checkout(f)
3276 normal(f)
3276 normal(f)
3277
3277
3278 finally:
3278 finally:
3279 wlock.release()
3279 wlock.release()
3280
3280
3281 def rollback(ui, repo, **opts):
3281 def rollback(ui, repo, **opts):
3282 """roll back the last transaction (dangerous)
3282 """roll back the last transaction (dangerous)
3283
3283
3284 This command should be used with care. There is only one level of
3284 This command should be used with care. There is only one level of
3285 rollback, and there is no way to undo a rollback. It will also
3285 rollback, and there is no way to undo a rollback. It will also
3286 restore the dirstate at the time of the last transaction, losing
3286 restore the dirstate at the time of the last transaction, losing
3287 any dirstate changes since that time. This command does not alter
3287 any dirstate changes since that time. This command does not alter
3288 the working directory.
3288 the working directory.
3289
3289
3290 Transactions are used to encapsulate the effects of all commands
3290 Transactions are used to encapsulate the effects of all commands
3291 that create new changesets or propagate existing changesets into a
3291 that create new changesets or propagate existing changesets into a
3292 repository. For example, the following commands are transactional,
3292 repository. For example, the following commands are transactional,
3293 and their effects can be rolled back:
3293 and their effects can be rolled back:
3294
3294
3295 - commit
3295 - commit
3296 - import
3296 - import
3297 - pull
3297 - pull
3298 - push (with this repository as the destination)
3298 - push (with this repository as the destination)
3299 - unbundle
3299 - unbundle
3300
3300
3301 This command is not intended for use on public repositories. Once
3301 This command is not intended for use on public repositories. Once
3302 changes are visible for pull by other users, rolling a transaction
3302 changes are visible for pull by other users, rolling a transaction
3303 back locally is ineffective (someone else may already have pulled
3303 back locally is ineffective (someone else may already have pulled
3304 the changes). Furthermore, a race is possible with readers of the
3304 the changes). Furthermore, a race is possible with readers of the
3305 repository; for example an in-progress pull from the repository
3305 repository; for example an in-progress pull from the repository
3306 may fail if a rollback is performed.
3306 may fail if a rollback is performed.
3307
3307
3308 Returns 0 on success, 1 if no rollback data is available.
3308 Returns 0 on success, 1 if no rollback data is available.
3309 """
3309 """
3310 return repo.rollback(opts.get('dry_run'))
3310 return repo.rollback(opts.get('dry_run'))
3311
3311
3312 def root(ui, repo):
3312 def root(ui, repo):
3313 """print the root (top) of the current working directory
3313 """print the root (top) of the current working directory
3314
3314
3315 Print the root directory of the current repository.
3315 Print the root directory of the current repository.
3316
3316
3317 Returns 0 on success.
3317 Returns 0 on success.
3318 """
3318 """
3319 ui.write(repo.root + "\n")
3319 ui.write(repo.root + "\n")
3320
3320
3321 def serve(ui, repo, **opts):
3321 def serve(ui, repo, **opts):
3322 """start stand-alone webserver
3322 """start stand-alone webserver
3323
3323
3324 Start a local HTTP repository browser and pull server. You can use
3324 Start a local HTTP repository browser and pull server. You can use
3325 this for ad-hoc sharing and browsing of repositories. It is
3325 this for ad-hoc sharing and browsing of repositories. It is
3326 recommended to use a real web server to serve a repository for
3326 recommended to use a real web server to serve a repository for
3327 longer periods of time.
3327 longer periods of time.
3328
3328
3329 Please note that the server does not implement access control.
3329 Please note that the server does not implement access control.
3330 This means that, by default, anybody can read from the server and
3330 This means that, by default, anybody can read from the server and
3331 nobody can write to it by default. Set the ``web.allow_push``
3331 nobody can write to it by default. Set the ``web.allow_push``
3332 option to ``*`` to allow everybody to push to the server. You
3332 option to ``*`` to allow everybody to push to the server. You
3333 should use a real web server if you need to authenticate users.
3333 should use a real web server if you need to authenticate users.
3334
3334
3335 By default, the server logs accesses to stdout and errors to
3335 By default, the server logs accesses to stdout and errors to
3336 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3336 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3337 files.
3337 files.
3338
3338
3339 To have the server choose a free port number to listen on, specify
3339 To have the server choose a free port number to listen on, specify
3340 a port number of 0; in this case, the server will print the port
3340 a port number of 0; in this case, the server will print the port
3341 number it uses.
3341 number it uses.
3342
3342
3343 Returns 0 on success.
3343 Returns 0 on success.
3344 """
3344 """
3345
3345
3346 if opts["stdio"]:
3346 if opts["stdio"]:
3347 if repo is None:
3347 if repo is None:
3348 raise error.RepoError(_("There is no Mercurial repository here"
3348 raise error.RepoError(_("There is no Mercurial repository here"
3349 " (.hg not found)"))
3349 " (.hg not found)"))
3350 s = sshserver.sshserver(ui, repo)
3350 s = sshserver.sshserver(ui, repo)
3351 s.serve_forever()
3351 s.serve_forever()
3352
3352
3353 # this way we can check if something was given in the command-line
3353 # this way we can check if something was given in the command-line
3354 if opts.get('port'):
3354 if opts.get('port'):
3355 opts['port'] = util.getport(opts.get('port'))
3355 opts['port'] = util.getport(opts.get('port'))
3356
3356
3357 baseui = repo and repo.baseui or ui
3357 baseui = repo and repo.baseui or ui
3358 optlist = ("name templates style address port prefix ipv6"
3358 optlist = ("name templates style address port prefix ipv6"
3359 " accesslog errorlog certificate encoding")
3359 " accesslog errorlog certificate encoding")
3360 for o in optlist.split():
3360 for o in optlist.split():
3361 val = opts.get(o, '')
3361 val = opts.get(o, '')
3362 if val in (None, ''): # should check against default options instead
3362 if val in (None, ''): # should check against default options instead
3363 continue
3363 continue
3364 baseui.setconfig("web", o, val)
3364 baseui.setconfig("web", o, val)
3365 if repo and repo.ui != baseui:
3365 if repo and repo.ui != baseui:
3366 repo.ui.setconfig("web", o, val)
3366 repo.ui.setconfig("web", o, val)
3367
3367
3368 o = opts.get('web_conf') or opts.get('webdir_conf')
3368 o = opts.get('web_conf') or opts.get('webdir_conf')
3369 if not o:
3369 if not o:
3370 if not repo:
3370 if not repo:
3371 raise error.RepoError(_("There is no Mercurial repository"
3371 raise error.RepoError(_("There is no Mercurial repository"
3372 " here (.hg not found)"))
3372 " here (.hg not found)"))
3373 o = repo.root
3373 o = repo.root
3374
3374
3375 app = hgweb.hgweb(o, baseui=ui)
3375 app = hgweb.hgweb(o, baseui=ui)
3376
3376
3377 class service(object):
3377 class service(object):
3378 def init(self):
3378 def init(self):
3379 util.set_signal_handler()
3379 util.set_signal_handler()
3380 self.httpd = hgweb.server.create_server(ui, app)
3380 self.httpd = hgweb.server.create_server(ui, app)
3381
3381
3382 if opts['port'] and not ui.verbose:
3382 if opts['port'] and not ui.verbose:
3383 return
3383 return
3384
3384
3385 if self.httpd.prefix:
3385 if self.httpd.prefix:
3386 prefix = self.httpd.prefix.strip('/') + '/'
3386 prefix = self.httpd.prefix.strip('/') + '/'
3387 else:
3387 else:
3388 prefix = ''
3388 prefix = ''
3389
3389
3390 port = ':%d' % self.httpd.port
3390 port = ':%d' % self.httpd.port
3391 if port == ':80':
3391 if port == ':80':
3392 port = ''
3392 port = ''
3393
3393
3394 bindaddr = self.httpd.addr
3394 bindaddr = self.httpd.addr
3395 if bindaddr == '0.0.0.0':
3395 if bindaddr == '0.0.0.0':
3396 bindaddr = '*'
3396 bindaddr = '*'
3397 elif ':' in bindaddr: # IPv6
3397 elif ':' in bindaddr: # IPv6
3398 bindaddr = '[%s]' % bindaddr
3398 bindaddr = '[%s]' % bindaddr
3399
3399
3400 fqaddr = self.httpd.fqaddr
3400 fqaddr = self.httpd.fqaddr
3401 if ':' in fqaddr:
3401 if ':' in fqaddr:
3402 fqaddr = '[%s]' % fqaddr
3402 fqaddr = '[%s]' % fqaddr
3403 if opts['port']:
3403 if opts['port']:
3404 write = ui.status
3404 write = ui.status
3405 else:
3405 else:
3406 write = ui.write
3406 write = ui.write
3407 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3407 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3408 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3408 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3409
3409
3410 def run(self):
3410 def run(self):
3411 self.httpd.serve_forever()
3411 self.httpd.serve_forever()
3412
3412
3413 service = service()
3413 service = service()
3414
3414
3415 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3415 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3416
3416
3417 def status(ui, repo, *pats, **opts):
3417 def status(ui, repo, *pats, **opts):
3418 """show changed files in the working directory
3418 """show changed files in the working directory
3419
3419
3420 Show status of files in the repository. If names are given, only
3420 Show status of files in the repository. If names are given, only
3421 files that match are shown. Files that are clean or ignored or
3421 files that match are shown. Files that are clean or ignored or
3422 the source of a copy/move operation, are not listed unless
3422 the source of a copy/move operation, are not listed unless
3423 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3423 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3424 Unless options described with "show only ..." are given, the
3424 Unless options described with "show only ..." are given, the
3425 options -mardu are used.
3425 options -mardu are used.
3426
3426
3427 Option -q/--quiet hides untracked (unknown and ignored) files
3427 Option -q/--quiet hides untracked (unknown and ignored) files
3428 unless explicitly requested with -u/--unknown or -i/--ignored.
3428 unless explicitly requested with -u/--unknown or -i/--ignored.
3429
3429
3430 .. note::
3430 .. note::
3431 status may appear to disagree with diff if permissions have
3431 status may appear to disagree with diff if permissions have
3432 changed or a merge has occurred. The standard diff format does
3432 changed or a merge has occurred. The standard diff format does
3433 not report permission changes and diff only reports changes
3433 not report permission changes and diff only reports changes
3434 relative to one merge parent.
3434 relative to one merge parent.
3435
3435
3436 If one revision is given, it is used as the base revision.
3436 If one revision is given, it is used as the base revision.
3437 If two revisions are given, the differences between them are
3437 If two revisions are given, the differences between them are
3438 shown. The --change option can also be used as a shortcut to list
3438 shown. The --change option can also be used as a shortcut to list
3439 the changed files of a revision from its first parent.
3439 the changed files of a revision from its first parent.
3440
3440
3441 The codes used to show the status of files are::
3441 The codes used to show the status of files are::
3442
3442
3443 M = modified
3443 M = modified
3444 A = added
3444 A = added
3445 R = removed
3445 R = removed
3446 C = clean
3446 C = clean
3447 ! = missing (deleted by non-hg command, but still tracked)
3447 ! = missing (deleted by non-hg command, but still tracked)
3448 ? = not tracked
3448 ? = not tracked
3449 I = ignored
3449 I = ignored
3450 = origin of the previous file listed as A (added)
3450 = origin of the previous file listed as A (added)
3451
3451
3452 Returns 0 on success.
3452 Returns 0 on success.
3453 """
3453 """
3454
3454
3455 revs = opts.get('rev')
3455 revs = opts.get('rev')
3456 change = opts.get('change')
3456 change = opts.get('change')
3457
3457
3458 if revs and change:
3458 if revs and change:
3459 msg = _('cannot specify --rev and --change at the same time')
3459 msg = _('cannot specify --rev and --change at the same time')
3460 raise util.Abort(msg)
3460 raise util.Abort(msg)
3461 elif change:
3461 elif change:
3462 node2 = repo.lookup(change)
3462 node2 = repo.lookup(change)
3463 node1 = repo[node2].parents()[0].node()
3463 node1 = repo[node2].parents()[0].node()
3464 else:
3464 else:
3465 node1, node2 = cmdutil.revpair(repo, revs)
3465 node1, node2 = cmdutil.revpair(repo, revs)
3466
3466
3467 cwd = (pats and repo.getcwd()) or ''
3467 cwd = (pats and repo.getcwd()) or ''
3468 end = opts.get('print0') and '\0' or '\n'
3468 end = opts.get('print0') and '\0' or '\n'
3469 copy = {}
3469 copy = {}
3470 states = 'modified added removed deleted unknown ignored clean'.split()
3470 states = 'modified added removed deleted unknown ignored clean'.split()
3471 show = [k for k in states if opts.get(k)]
3471 show = [k for k in states if opts.get(k)]
3472 if opts.get('all'):
3472 if opts.get('all'):
3473 show += ui.quiet and (states[:4] + ['clean']) or states
3473 show += ui.quiet and (states[:4] + ['clean']) or states
3474 if not show:
3474 if not show:
3475 show = ui.quiet and states[:4] or states[:5]
3475 show = ui.quiet and states[:4] or states[:5]
3476
3476
3477 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3477 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3478 'ignored' in show, 'clean' in show, 'unknown' in show,
3478 'ignored' in show, 'clean' in show, 'unknown' in show,
3479 opts.get('subrepos'))
3479 opts.get('subrepos'))
3480 changestates = zip(states, 'MAR!?IC', stat)
3480 changestates = zip(states, 'MAR!?IC', stat)
3481
3481
3482 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3482 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3483 ctxn = repo[nullid]
3483 ctxn = repo[nullid]
3484 ctx1 = repo[node1]
3484 ctx1 = repo[node1]
3485 ctx2 = repo[node2]
3485 ctx2 = repo[node2]
3486 added = stat[1]
3486 added = stat[1]
3487 if node2 is None:
3487 if node2 is None:
3488 added = stat[0] + stat[1] # merged?
3488 added = stat[0] + stat[1] # merged?
3489
3489
3490 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3490 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3491 if k in added:
3491 if k in added:
3492 copy[k] = v
3492 copy[k] = v
3493 elif v in added:
3493 elif v in added:
3494 copy[v] = k
3494 copy[v] = k
3495
3495
3496 for state, char, files in changestates:
3496 for state, char, files in changestates:
3497 if state in show:
3497 if state in show:
3498 format = "%s %%s%s" % (char, end)
3498 format = "%s %%s%s" % (char, end)
3499 if opts.get('no_status'):
3499 if opts.get('no_status'):
3500 format = "%%s%s" % end
3500 format = "%%s%s" % end
3501
3501
3502 for f in files:
3502 for f in files:
3503 ui.write(format % repo.pathto(f, cwd),
3503 ui.write(format % repo.pathto(f, cwd),
3504 label='status.' + state)
3504 label='status.' + state)
3505 if f in copy:
3505 if f in copy:
3506 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3506 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3507 label='status.copied')
3507 label='status.copied')
3508
3508
3509 def summary(ui, repo, **opts):
3509 def summary(ui, repo, **opts):
3510 """summarize working directory state
3510 """summarize working directory state
3511
3511
3512 This generates a brief summary of the working directory state,
3512 This generates a brief summary of the working directory state,
3513 including parents, branch, commit status, and available updates.
3513 including parents, branch, commit status, and available updates.
3514
3514
3515 With the --remote option, this will check the default paths for
3515 With the --remote option, this will check the default paths for
3516 incoming and outgoing changes. This can be time-consuming.
3516 incoming and outgoing changes. This can be time-consuming.
3517
3517
3518 Returns 0 on success.
3518 Returns 0 on success.
3519 """
3519 """
3520
3520
3521 ctx = repo[None]
3521 ctx = repo[None]
3522 parents = ctx.parents()
3522 parents = ctx.parents()
3523 pnode = parents[0].node()
3523 pnode = parents[0].node()
3524
3524
3525 for p in parents:
3525 for p in parents:
3526 # label with log.changeset (instead of log.parent) since this
3526 # label with log.changeset (instead of log.parent) since this
3527 # shows a working directory parent *changeset*:
3527 # shows a working directory parent *changeset*:
3528 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3528 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3529 label='log.changeset')
3529 label='log.changeset')
3530 ui.write(' '.join(p.tags()), label='log.tag')
3530 ui.write(' '.join(p.tags()), label='log.tag')
3531 if p.rev() == -1:
3531 if p.rev() == -1:
3532 if not len(repo):
3532 if not len(repo):
3533 ui.write(_(' (empty repository)'))
3533 ui.write(_(' (empty repository)'))
3534 else:
3534 else:
3535 ui.write(_(' (no revision checked out)'))
3535 ui.write(_(' (no revision checked out)'))
3536 ui.write('\n')
3536 ui.write('\n')
3537 if p.description():
3537 if p.description():
3538 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3538 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3539 label='log.summary')
3539 label='log.summary')
3540
3540
3541 branch = ctx.branch()
3541 branch = ctx.branch()
3542 bheads = repo.branchheads(branch)
3542 bheads = repo.branchheads(branch)
3543 m = _('branch: %s\n') % branch
3543 m = _('branch: %s\n') % branch
3544 if branch != 'default':
3544 if branch != 'default':
3545 ui.write(m, label='log.branch')
3545 ui.write(m, label='log.branch')
3546 else:
3546 else:
3547 ui.status(m, label='log.branch')
3547 ui.status(m, label='log.branch')
3548
3548
3549 st = list(repo.status(unknown=True))[:6]
3549 st = list(repo.status(unknown=True))[:6]
3550
3550
3551 c = repo.dirstate.copies()
3551 c = repo.dirstate.copies()
3552 copied, renamed = [], []
3552 copied, renamed = [], []
3553 for d, s in c.iteritems():
3553 for d, s in c.iteritems():
3554 if s in st[2]:
3554 if s in st[2]:
3555 st[2].remove(s)
3555 st[2].remove(s)
3556 renamed.append(d)
3556 renamed.append(d)
3557 else:
3557 else:
3558 copied.append(d)
3558 copied.append(d)
3559 if d in st[1]:
3559 if d in st[1]:
3560 st[1].remove(d)
3560 st[1].remove(d)
3561 st.insert(3, renamed)
3561 st.insert(3, renamed)
3562 st.insert(4, copied)
3562 st.insert(4, copied)
3563
3563
3564 ms = mergemod.mergestate(repo)
3564 ms = mergemod.mergestate(repo)
3565 st.append([f for f in ms if ms[f] == 'u'])
3565 st.append([f for f in ms if ms[f] == 'u'])
3566
3566
3567 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3567 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3568 st.append(subs)
3568 st.append(subs)
3569
3569
3570 labels = [ui.label(_('%d modified'), 'status.modified'),
3570 labels = [ui.label(_('%d modified'), 'status.modified'),
3571 ui.label(_('%d added'), 'status.added'),
3571 ui.label(_('%d added'), 'status.added'),
3572 ui.label(_('%d removed'), 'status.removed'),
3572 ui.label(_('%d removed'), 'status.removed'),
3573 ui.label(_('%d renamed'), 'status.copied'),
3573 ui.label(_('%d renamed'), 'status.copied'),
3574 ui.label(_('%d copied'), 'status.copied'),
3574 ui.label(_('%d copied'), 'status.copied'),
3575 ui.label(_('%d deleted'), 'status.deleted'),
3575 ui.label(_('%d deleted'), 'status.deleted'),
3576 ui.label(_('%d unknown'), 'status.unknown'),
3576 ui.label(_('%d unknown'), 'status.unknown'),
3577 ui.label(_('%d ignored'), 'status.ignored'),
3577 ui.label(_('%d ignored'), 'status.ignored'),
3578 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3578 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3579 ui.label(_('%d subrepos'), 'status.modified')]
3579 ui.label(_('%d subrepos'), 'status.modified')]
3580 t = []
3580 t = []
3581 for s, l in zip(st, labels):
3581 for s, l in zip(st, labels):
3582 if s:
3582 if s:
3583 t.append(l % len(s))
3583 t.append(l % len(s))
3584
3584
3585 t = ', '.join(t)
3585 t = ', '.join(t)
3586 cleanworkdir = False
3586 cleanworkdir = False
3587
3587
3588 if len(parents) > 1:
3588 if len(parents) > 1:
3589 t += _(' (merge)')
3589 t += _(' (merge)')
3590 elif branch != parents[0].branch():
3590 elif branch != parents[0].branch():
3591 t += _(' (new branch)')
3591 t += _(' (new branch)')
3592 elif (parents[0].extra().get('close') and
3592 elif (parents[0].extra().get('close') and
3593 pnode in repo.branchheads(branch, closed=True)):
3593 pnode in repo.branchheads(branch, closed=True)):
3594 t += _(' (head closed)')
3594 t += _(' (head closed)')
3595 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3595 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3596 t += _(' (clean)')
3596 t += _(' (clean)')
3597 cleanworkdir = True
3597 cleanworkdir = True
3598 elif pnode not in bheads:
3598 elif pnode not in bheads:
3599 t += _(' (new branch head)')
3599 t += _(' (new branch head)')
3600
3600
3601 if cleanworkdir:
3601 if cleanworkdir:
3602 ui.status(_('commit: %s\n') % t.strip())
3602 ui.status(_('commit: %s\n') % t.strip())
3603 else:
3603 else:
3604 ui.write(_('commit: %s\n') % t.strip())
3604 ui.write(_('commit: %s\n') % t.strip())
3605
3605
3606 # all ancestors of branch heads - all ancestors of parent = new csets
3606 # all ancestors of branch heads - all ancestors of parent = new csets
3607 new = [0] * len(repo)
3607 new = [0] * len(repo)
3608 cl = repo.changelog
3608 cl = repo.changelog
3609 for a in [cl.rev(n) for n in bheads]:
3609 for a in [cl.rev(n) for n in bheads]:
3610 new[a] = 1
3610 new[a] = 1
3611 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3611 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3612 new[a] = 1
3612 new[a] = 1
3613 for a in [p.rev() for p in parents]:
3613 for a in [p.rev() for p in parents]:
3614 if a >= 0:
3614 if a >= 0:
3615 new[a] = 0
3615 new[a] = 0
3616 for a in cl.ancestors(*[p.rev() for p in parents]):
3616 for a in cl.ancestors(*[p.rev() for p in parents]):
3617 new[a] = 0
3617 new[a] = 0
3618 new = sum(new)
3618 new = sum(new)
3619
3619
3620 if new == 0:
3620 if new == 0:
3621 ui.status(_('update: (current)\n'))
3621 ui.status(_('update: (current)\n'))
3622 elif pnode not in bheads:
3622 elif pnode not in bheads:
3623 ui.write(_('update: %d new changesets (update)\n') % new)
3623 ui.write(_('update: %d new changesets (update)\n') % new)
3624 else:
3624 else:
3625 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3625 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3626 (new, len(bheads)))
3626 (new, len(bheads)))
3627
3627
3628 if opts.get('remote'):
3628 if opts.get('remote'):
3629 t = []
3629 t = []
3630 source, branches = hg.parseurl(ui.expandpath('default'))
3630 source, branches = hg.parseurl(ui.expandpath('default'))
3631 other = hg.repository(hg.remoteui(repo, {}), source)
3631 other = hg.repository(hg.remoteui(repo, {}), source)
3632 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3632 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3633 ui.debug('comparing with %s\n' % url.hidepassword(source))
3633 ui.debug('comparing with %s\n' % url.hidepassword(source))
3634 repo.ui.pushbuffer()
3634 repo.ui.pushbuffer()
3635 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3635 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3636 repo.ui.popbuffer()
3636 repo.ui.popbuffer()
3637 if incoming:
3637 if incoming:
3638 t.append(_('1 or more incoming'))
3638 t.append(_('1 or more incoming'))
3639
3639
3640 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3640 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3641 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3641 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3642 other = hg.repository(hg.remoteui(repo, {}), dest)
3642 other = hg.repository(hg.remoteui(repo, {}), dest)
3643 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3643 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3644 repo.ui.pushbuffer()
3644 repo.ui.pushbuffer()
3645 o = discovery.findoutgoing(repo, other)
3645 o = discovery.findoutgoing(repo, other)
3646 repo.ui.popbuffer()
3646 repo.ui.popbuffer()
3647 o = repo.changelog.nodesbetween(o, None)[0]
3647 o = repo.changelog.nodesbetween(o, None)[0]
3648 if o:
3648 if o:
3649 t.append(_('%d outgoing') % len(o))
3649 t.append(_('%d outgoing') % len(o))
3650
3650
3651 if t:
3651 if t:
3652 ui.write(_('remote: %s\n') % (', '.join(t)))
3652 ui.write(_('remote: %s\n') % (', '.join(t)))
3653 else:
3653 else:
3654 ui.status(_('remote: (synced)\n'))
3654 ui.status(_('remote: (synced)\n'))
3655
3655
3656 def tag(ui, repo, name1, *names, **opts):
3656 def tag(ui, repo, name1, *names, **opts):
3657 """add one or more tags for the current or given revision
3657 """add one or more tags for the current or given revision
3658
3658
3659 Name a particular revision using <name>.
3659 Name a particular revision using <name>.
3660
3660
3661 Tags are used to name particular revisions of the repository and are
3661 Tags are used to name particular revisions of the repository and are
3662 very useful to compare different revisions, to go back to significant
3662 very useful to compare different revisions, to go back to significant
3663 earlier versions or to mark branch points as releases, etc.
3663 earlier versions or to mark branch points as releases, etc. Changing
3664 an existing tag is normally disallowed; use -f/--force to override.
3664
3665
3665 If no revision is given, the parent of the working directory is
3666 If no revision is given, the parent of the working directory is
3666 used, or tip if no revision is checked out.
3667 used, or tip if no revision is checked out.
3667
3668
3668 To facilitate version control, distribution, and merging of tags,
3669 To facilitate version control, distribution, and merging of tags,
3669 they are stored as a file named ".hgtags" which is managed
3670 they are stored as a file named ".hgtags" which is managed similarly
3670 similarly to other project files and can be hand-edited if
3671 to other project files and can be hand-edited if necessary. This
3671 necessary. The file '.hg/localtags' is used for local tags (not
3672 also means that tagging creates a new commit. The file
3672 shared among repositories).
3673 ".hg/localtags" is used for local tags (not shared among
3674 repositories).
3675
3676 Tag commits are usually made at the head of a branch. If the parent
3677 of the working directory is not a branch head, :hg:`tag` aborts; use
3678 -f/--force to force the tag commit to be based on a non-head
3679 changeset.
3673
3680
3674 See :hg:`help dates` for a list of formats valid for -d/--date.
3681 See :hg:`help dates` for a list of formats valid for -d/--date.
3675
3682
3676 Since tag names have priority over branch names during revision
3683 Since tag names have priority over branch names during revision
3677 lookup, using an existing branch name as a tag name is discouraged.
3684 lookup, using an existing branch name as a tag name is discouraged.
3678
3685
3679 Returns 0 on success.
3686 Returns 0 on success.
3680 """
3687 """
3681
3688
3682 rev_ = "."
3689 rev_ = "."
3683 names = [t.strip() for t in (name1,) + names]
3690 names = [t.strip() for t in (name1,) + names]
3684 if len(names) != len(set(names)):
3691 if len(names) != len(set(names)):
3685 raise util.Abort(_('tag names must be unique'))
3692 raise util.Abort(_('tag names must be unique'))
3686 for n in names:
3693 for n in names:
3687 if n in ['tip', '.', 'null']:
3694 if n in ['tip', '.', 'null']:
3688 raise util.Abort(_('the name \'%s\' is reserved') % n)
3695 raise util.Abort(_('the name \'%s\' is reserved') % n)
3689 if not n:
3696 if not n:
3690 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3697 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3691 if opts.get('rev') and opts.get('remove'):
3698 if opts.get('rev') and opts.get('remove'):
3692 raise util.Abort(_("--rev and --remove are incompatible"))
3699 raise util.Abort(_("--rev and --remove are incompatible"))
3693 if opts.get('rev'):
3700 if opts.get('rev'):
3694 rev_ = opts['rev']
3701 rev_ = opts['rev']
3695 message = opts.get('message')
3702 message = opts.get('message')
3696 if opts.get('remove'):
3703 if opts.get('remove'):
3697 expectedtype = opts.get('local') and 'local' or 'global'
3704 expectedtype = opts.get('local') and 'local' or 'global'
3698 for n in names:
3705 for n in names:
3699 if not repo.tagtype(n):
3706 if not repo.tagtype(n):
3700 raise util.Abort(_('tag \'%s\' does not exist') % n)
3707 raise util.Abort(_('tag \'%s\' does not exist') % n)
3701 if repo.tagtype(n) != expectedtype:
3708 if repo.tagtype(n) != expectedtype:
3702 if expectedtype == 'global':
3709 if expectedtype == 'global':
3703 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3710 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3704 else:
3711 else:
3705 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3712 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3706 rev_ = nullid
3713 rev_ = nullid
3707 if not message:
3714 if not message:
3708 # we don't translate commit messages
3715 # we don't translate commit messages
3709 message = 'Removed tag %s' % ', '.join(names)
3716 message = 'Removed tag %s' % ', '.join(names)
3710 elif not opts.get('force'):
3717 elif not opts.get('force'):
3711 for n in names:
3718 for n in names:
3712 if n in repo.tags():
3719 if n in repo.tags():
3713 raise util.Abort(_('tag \'%s\' already exists '
3720 raise util.Abort(_('tag \'%s\' already exists '
3714 '(use -f to force)') % n)
3721 '(use -f to force)') % n)
3715 if not opts.get('local') and repo.dirstate.parents()[1] != nullid:
3722 if not opts.get('local'):
3716 raise util.Abort(_('uncommitted merge'))
3723 p1, p2 = repo.dirstate.parents()
3724 if p2 != nullid:
3725 raise util.Abort(_('uncommitted merge'))
3726 bheads = repo.branchheads()
3727 if not opts.get('force') and bheads and p1 not in bheads:
3728 raise util.Abort(_('not at a branch head (use -f to force)'))
3717 r = repo[rev_].node()
3729 r = repo[rev_].node()
3718
3730
3719 if not message:
3731 if not message:
3720 # we don't translate commit messages
3732 # we don't translate commit messages
3721 message = ('Added tag %s for changeset %s' %
3733 message = ('Added tag %s for changeset %s' %
3722 (', '.join(names), short(r)))
3734 (', '.join(names), short(r)))
3723
3735
3724 date = opts.get('date')
3736 date = opts.get('date')
3725 if date:
3737 if date:
3726 date = util.parsedate(date)
3738 date = util.parsedate(date)
3727
3739
3728 if opts.get('edit'):
3740 if opts.get('edit'):
3729 message = ui.edit(message, ui.username())
3741 message = ui.edit(message, ui.username())
3730
3742
3731 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3743 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3732
3744
3733 def tags(ui, repo):
3745 def tags(ui, repo):
3734 """list repository tags
3746 """list repository tags
3735
3747
3736 This lists both regular and local tags. When the -v/--verbose
3748 This lists both regular and local tags. When the -v/--verbose
3737 switch is used, a third column "local" is printed for local tags.
3749 switch is used, a third column "local" is printed for local tags.
3738
3750
3739 Returns 0 on success.
3751 Returns 0 on success.
3740 """
3752 """
3741
3753
3742 hexfunc = ui.debugflag and hex or short
3754 hexfunc = ui.debugflag and hex or short
3743 tagtype = ""
3755 tagtype = ""
3744
3756
3745 for t, n in reversed(repo.tagslist()):
3757 for t, n in reversed(repo.tagslist()):
3746 if ui.quiet:
3758 if ui.quiet:
3747 ui.write("%s\n" % t)
3759 ui.write("%s\n" % t)
3748 continue
3760 continue
3749
3761
3750 try:
3762 try:
3751 hn = hexfunc(n)
3763 hn = hexfunc(n)
3752 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3764 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3753 except error.LookupError:
3765 except error.LookupError:
3754 r = " ?:%s" % hn
3766 r = " ?:%s" % hn
3755 else:
3767 else:
3756 spaces = " " * (30 - encoding.colwidth(t))
3768 spaces = " " * (30 - encoding.colwidth(t))
3757 if ui.verbose:
3769 if ui.verbose:
3758 if repo.tagtype(t) == 'local':
3770 if repo.tagtype(t) == 'local':
3759 tagtype = " local"
3771 tagtype = " local"
3760 else:
3772 else:
3761 tagtype = ""
3773 tagtype = ""
3762 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3774 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3763
3775
3764 def tip(ui, repo, **opts):
3776 def tip(ui, repo, **opts):
3765 """show the tip revision
3777 """show the tip revision
3766
3778
3767 The tip revision (usually just called the tip) is the changeset
3779 The tip revision (usually just called the tip) is the changeset
3768 most recently added to the repository (and therefore the most
3780 most recently added to the repository (and therefore the most
3769 recently changed head).
3781 recently changed head).
3770
3782
3771 If you have just made a commit, that commit will be the tip. If
3783 If you have just made a commit, that commit will be the tip. If
3772 you have just pulled changes from another repository, the tip of
3784 you have just pulled changes from another repository, the tip of
3773 that repository becomes the current tip. The "tip" tag is special
3785 that repository becomes the current tip. The "tip" tag is special
3774 and cannot be renamed or assigned to a different changeset.
3786 and cannot be renamed or assigned to a different changeset.
3775
3787
3776 Returns 0 on success.
3788 Returns 0 on success.
3777 """
3789 """
3778 displayer = cmdutil.show_changeset(ui, repo, opts)
3790 displayer = cmdutil.show_changeset(ui, repo, opts)
3779 displayer.show(repo[len(repo) - 1])
3791 displayer.show(repo[len(repo) - 1])
3780 displayer.close()
3792 displayer.close()
3781
3793
3782 def unbundle(ui, repo, fname1, *fnames, **opts):
3794 def unbundle(ui, repo, fname1, *fnames, **opts):
3783 """apply one or more changegroup files
3795 """apply one or more changegroup files
3784
3796
3785 Apply one or more compressed changegroup files generated by the
3797 Apply one or more compressed changegroup files generated by the
3786 bundle command.
3798 bundle command.
3787
3799
3788 Returns 0 on success, 1 if an update has unresolved files.
3800 Returns 0 on success, 1 if an update has unresolved files.
3789 """
3801 """
3790 fnames = (fname1,) + fnames
3802 fnames = (fname1,) + fnames
3791
3803
3792 lock = repo.lock()
3804 lock = repo.lock()
3793 try:
3805 try:
3794 for fname in fnames:
3806 for fname in fnames:
3795 f = url.open(ui, fname)
3807 f = url.open(ui, fname)
3796 gen = changegroup.readbundle(f, fname)
3808 gen = changegroup.readbundle(f, fname)
3797 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3809 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3798 lock=lock)
3810 lock=lock)
3799 finally:
3811 finally:
3800 lock.release()
3812 lock.release()
3801
3813
3802 return postincoming(ui, repo, modheads, opts.get('update'), None)
3814 return postincoming(ui, repo, modheads, opts.get('update'), None)
3803
3815
3804 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3816 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3805 """update working directory (or switch revisions)
3817 """update working directory (or switch revisions)
3806
3818
3807 Update the repository's working directory to the specified
3819 Update the repository's working directory to the specified
3808 changeset. If no changeset is specified, update to the tip of the
3820 changeset. If no changeset is specified, update to the tip of the
3809 current named branch.
3821 current named branch.
3810
3822
3811 If the changeset is not a descendant of the working directory's
3823 If the changeset is not a descendant of the working directory's
3812 parent, the update is aborted. With the -c/--check option, the
3824 parent, the update is aborted. With the -c/--check option, the
3813 working directory is checked for uncommitted changes; if none are
3825 working directory is checked for uncommitted changes; if none are
3814 found, the working directory is updated to the specified
3826 found, the working directory is updated to the specified
3815 changeset.
3827 changeset.
3816
3828
3817 The following rules apply when the working directory contains
3829 The following rules apply when the working directory contains
3818 uncommitted changes:
3830 uncommitted changes:
3819
3831
3820 1. If neither -c/--check nor -C/--clean is specified, and if
3832 1. If neither -c/--check nor -C/--clean is specified, and if
3821 the requested changeset is an ancestor or descendant of
3833 the requested changeset is an ancestor or descendant of
3822 the working directory's parent, the uncommitted changes
3834 the working directory's parent, the uncommitted changes
3823 are merged into the requested changeset and the merged
3835 are merged into the requested changeset and the merged
3824 result is left uncommitted. If the requested changeset is
3836 result is left uncommitted. If the requested changeset is
3825 not an ancestor or descendant (that is, it is on another
3837 not an ancestor or descendant (that is, it is on another
3826 branch), the update is aborted and the uncommitted changes
3838 branch), the update is aborted and the uncommitted changes
3827 are preserved.
3839 are preserved.
3828
3840
3829 2. With the -c/--check option, the update is aborted and the
3841 2. With the -c/--check option, the update is aborted and the
3830 uncommitted changes are preserved.
3842 uncommitted changes are preserved.
3831
3843
3832 3. With the -C/--clean option, uncommitted changes are discarded and
3844 3. With the -C/--clean option, uncommitted changes are discarded and
3833 the working directory is updated to the requested changeset.
3845 the working directory is updated to the requested changeset.
3834
3846
3835 Use null as the changeset to remove the working directory (like
3847 Use null as the changeset to remove the working directory (like
3836 :hg:`clone -U`).
3848 :hg:`clone -U`).
3837
3849
3838 If you want to update just one file to an older changeset, use
3850 If you want to update just one file to an older changeset, use
3839 :hg:`revert`.
3851 :hg:`revert`.
3840
3852
3841 See :hg:`help dates` for a list of formats valid for -d/--date.
3853 See :hg:`help dates` for a list of formats valid for -d/--date.
3842
3854
3843 Returns 0 on success, 1 if there are unresolved files.
3855 Returns 0 on success, 1 if there are unresolved files.
3844 """
3856 """
3845 if rev and node:
3857 if rev and node:
3846 raise util.Abort(_("please specify just one revision"))
3858 raise util.Abort(_("please specify just one revision"))
3847
3859
3848 if not rev:
3860 if not rev:
3849 rev = node
3861 rev = node
3850
3862
3851 rev = cmdutil.revsingle(repo, rev, rev).rev()
3863 rev = cmdutil.revsingle(repo, rev, rev).rev()
3852
3864
3853 if check and clean:
3865 if check and clean:
3854 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3866 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3855
3867
3856 if check:
3868 if check:
3857 # we could use dirty() but we can ignore merge and branch trivia
3869 # we could use dirty() but we can ignore merge and branch trivia
3858 c = repo[None]
3870 c = repo[None]
3859 if c.modified() or c.added() or c.removed():
3871 if c.modified() or c.added() or c.removed():
3860 raise util.Abort(_("uncommitted local changes"))
3872 raise util.Abort(_("uncommitted local changes"))
3861
3873
3862 if date:
3874 if date:
3863 if rev:
3875 if rev:
3864 raise util.Abort(_("you can't specify a revision and a date"))
3876 raise util.Abort(_("you can't specify a revision and a date"))
3865 rev = cmdutil.finddate(ui, repo, date)
3877 rev = cmdutil.finddate(ui, repo, date)
3866
3878
3867 if clean or check:
3879 if clean or check:
3868 return hg.clean(repo, rev)
3880 return hg.clean(repo, rev)
3869 else:
3881 else:
3870 return hg.update(repo, rev)
3882 return hg.update(repo, rev)
3871
3883
3872 def verify(ui, repo):
3884 def verify(ui, repo):
3873 """verify the integrity of the repository
3885 """verify the integrity of the repository
3874
3886
3875 Verify the integrity of the current repository.
3887 Verify the integrity of the current repository.
3876
3888
3877 This will perform an extensive check of the repository's
3889 This will perform an extensive check of the repository's
3878 integrity, validating the hashes and checksums of each entry in
3890 integrity, validating the hashes and checksums of each entry in
3879 the changelog, manifest, and tracked files, as well as the
3891 the changelog, manifest, and tracked files, as well as the
3880 integrity of their crosslinks and indices.
3892 integrity of their crosslinks and indices.
3881
3893
3882 Returns 0 on success, 1 if errors are encountered.
3894 Returns 0 on success, 1 if errors are encountered.
3883 """
3895 """
3884 return hg.verify(repo)
3896 return hg.verify(repo)
3885
3897
3886 def version_(ui):
3898 def version_(ui):
3887 """output version and copyright information"""
3899 """output version and copyright information"""
3888 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3900 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3889 % util.version())
3901 % util.version())
3890 ui.status(_(
3902 ui.status(_(
3891 "(see http://mercurial.selenic.com for more information)\n"
3903 "(see http://mercurial.selenic.com for more information)\n"
3892 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3904 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3893 "This is free software; see the source for copying conditions. "
3905 "This is free software; see the source for copying conditions. "
3894 "There is NO\nwarranty; "
3906 "There is NO\nwarranty; "
3895 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3907 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3896 ))
3908 ))
3897
3909
3898 # Command options and aliases are listed here, alphabetically
3910 # Command options and aliases are listed here, alphabetically
3899
3911
3900 globalopts = [
3912 globalopts = [
3901 ('R', 'repository', '',
3913 ('R', 'repository', '',
3902 _('repository root directory or name of overlay bundle file'),
3914 _('repository root directory or name of overlay bundle file'),
3903 _('REPO')),
3915 _('REPO')),
3904 ('', 'cwd', '',
3916 ('', 'cwd', '',
3905 _('change working directory'), _('DIR')),
3917 _('change working directory'), _('DIR')),
3906 ('y', 'noninteractive', None,
3918 ('y', 'noninteractive', None,
3907 _('do not prompt, assume \'yes\' for any required answers')),
3919 _('do not prompt, assume \'yes\' for any required answers')),
3908 ('q', 'quiet', None, _('suppress output')),
3920 ('q', 'quiet', None, _('suppress output')),
3909 ('v', 'verbose', None, _('enable additional output')),
3921 ('v', 'verbose', None, _('enable additional output')),
3910 ('', 'config', [],
3922 ('', 'config', [],
3911 _('set/override config option (use \'section.name=value\')'),
3923 _('set/override config option (use \'section.name=value\')'),
3912 _('CONFIG')),
3924 _('CONFIG')),
3913 ('', 'debug', None, _('enable debugging output')),
3925 ('', 'debug', None, _('enable debugging output')),
3914 ('', 'debugger', None, _('start debugger')),
3926 ('', 'debugger', None, _('start debugger')),
3915 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3927 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3916 _('ENCODE')),
3928 _('ENCODE')),
3917 ('', 'encodingmode', encoding.encodingmode,
3929 ('', 'encodingmode', encoding.encodingmode,
3918 _('set the charset encoding mode'), _('MODE')),
3930 _('set the charset encoding mode'), _('MODE')),
3919 ('', 'traceback', None, _('always print a traceback on exception')),
3931 ('', 'traceback', None, _('always print a traceback on exception')),
3920 ('', 'time', None, _('time how long the command takes')),
3932 ('', 'time', None, _('time how long the command takes')),
3921 ('', 'profile', None, _('print command execution profile')),
3933 ('', 'profile', None, _('print command execution profile')),
3922 ('', 'version', None, _('output version information and exit')),
3934 ('', 'version', None, _('output version information and exit')),
3923 ('h', 'help', None, _('display help and exit')),
3935 ('h', 'help', None, _('display help and exit')),
3924 ]
3936 ]
3925
3937
3926 dryrunopts = [('n', 'dry-run', None,
3938 dryrunopts = [('n', 'dry-run', None,
3927 _('do not perform actions, just print output'))]
3939 _('do not perform actions, just print output'))]
3928
3940
3929 remoteopts = [
3941 remoteopts = [
3930 ('e', 'ssh', '',
3942 ('e', 'ssh', '',
3931 _('specify ssh command to use'), _('CMD')),
3943 _('specify ssh command to use'), _('CMD')),
3932 ('', 'remotecmd', '',
3944 ('', 'remotecmd', '',
3933 _('specify hg command to run on the remote side'), _('CMD')),
3945 _('specify hg command to run on the remote side'), _('CMD')),
3934 ]
3946 ]
3935
3947
3936 walkopts = [
3948 walkopts = [
3937 ('I', 'include', [],
3949 ('I', 'include', [],
3938 _('include names matching the given patterns'), _('PATTERN')),
3950 _('include names matching the given patterns'), _('PATTERN')),
3939 ('X', 'exclude', [],
3951 ('X', 'exclude', [],
3940 _('exclude names matching the given patterns'), _('PATTERN')),
3952 _('exclude names matching the given patterns'), _('PATTERN')),
3941 ]
3953 ]
3942
3954
3943 commitopts = [
3955 commitopts = [
3944 ('m', 'message', '',
3956 ('m', 'message', '',
3945 _('use text as commit message'), _('TEXT')),
3957 _('use text as commit message'), _('TEXT')),
3946 ('l', 'logfile', '',
3958 ('l', 'logfile', '',
3947 _('read commit message from file'), _('FILE')),
3959 _('read commit message from file'), _('FILE')),
3948 ]
3960 ]
3949
3961
3950 commitopts2 = [
3962 commitopts2 = [
3951 ('d', 'date', '',
3963 ('d', 'date', '',
3952 _('record datecode as commit date'), _('DATE')),
3964 _('record datecode as commit date'), _('DATE')),
3953 ('u', 'user', '',
3965 ('u', 'user', '',
3954 _('record the specified user as committer'), _('USER')),
3966 _('record the specified user as committer'), _('USER')),
3955 ]
3967 ]
3956
3968
3957 templateopts = [
3969 templateopts = [
3958 ('', 'style', '',
3970 ('', 'style', '',
3959 _('display using template map file'), _('STYLE')),
3971 _('display using template map file'), _('STYLE')),
3960 ('', 'template', '',
3972 ('', 'template', '',
3961 _('display with template'), _('TEMPLATE')),
3973 _('display with template'), _('TEMPLATE')),
3962 ]
3974 ]
3963
3975
3964 logopts = [
3976 logopts = [
3965 ('p', 'patch', None, _('show patch')),
3977 ('p', 'patch', None, _('show patch')),
3966 ('g', 'git', None, _('use git extended diff format')),
3978 ('g', 'git', None, _('use git extended diff format')),
3967 ('l', 'limit', '',
3979 ('l', 'limit', '',
3968 _('limit number of changes displayed'), _('NUM')),
3980 _('limit number of changes displayed'), _('NUM')),
3969 ('M', 'no-merges', None, _('do not show merges')),
3981 ('M', 'no-merges', None, _('do not show merges')),
3970 ('', 'stat', None, _('output diffstat-style summary of changes')),
3982 ('', 'stat', None, _('output diffstat-style summary of changes')),
3971 ] + templateopts
3983 ] + templateopts
3972
3984
3973 diffopts = [
3985 diffopts = [
3974 ('a', 'text', None, _('treat all files as text')),
3986 ('a', 'text', None, _('treat all files as text')),
3975 ('g', 'git', None, _('use git extended diff format')),
3987 ('g', 'git', None, _('use git extended diff format')),
3976 ('', 'nodates', None, _('omit dates from diff headers'))
3988 ('', 'nodates', None, _('omit dates from diff headers'))
3977 ]
3989 ]
3978
3990
3979 diffopts2 = [
3991 diffopts2 = [
3980 ('p', 'show-function', None, _('show which function each change is in')),
3992 ('p', 'show-function', None, _('show which function each change is in')),
3981 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3993 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3982 ('w', 'ignore-all-space', None,
3994 ('w', 'ignore-all-space', None,
3983 _('ignore white space when comparing lines')),
3995 _('ignore white space when comparing lines')),
3984 ('b', 'ignore-space-change', None,
3996 ('b', 'ignore-space-change', None,
3985 _('ignore changes in the amount of white space')),
3997 _('ignore changes in the amount of white space')),
3986 ('B', 'ignore-blank-lines', None,
3998 ('B', 'ignore-blank-lines', None,
3987 _('ignore changes whose lines are all blank')),
3999 _('ignore changes whose lines are all blank')),
3988 ('U', 'unified', '',
4000 ('U', 'unified', '',
3989 _('number of lines of context to show'), _('NUM')),
4001 _('number of lines of context to show'), _('NUM')),
3990 ('', 'stat', None, _('output diffstat-style summary of changes')),
4002 ('', 'stat', None, _('output diffstat-style summary of changes')),
3991 ]
4003 ]
3992
4004
3993 similarityopts = [
4005 similarityopts = [
3994 ('s', 'similarity', '',
4006 ('s', 'similarity', '',
3995 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4007 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3996 ]
4008 ]
3997
4009
3998 subrepoopts = [
4010 subrepoopts = [
3999 ('S', 'subrepos', None,
4011 ('S', 'subrepos', None,
4000 _('recurse into subrepositories'))
4012 _('recurse into subrepositories'))
4001 ]
4013 ]
4002
4014
4003 table = {
4015 table = {
4004 "^add": (add, walkopts + subrepoopts + dryrunopts,
4016 "^add": (add, walkopts + subrepoopts + dryrunopts,
4005 _('[OPTION]... [FILE]...')),
4017 _('[OPTION]... [FILE]...')),
4006 "addremove":
4018 "addremove":
4007 (addremove, similarityopts + walkopts + dryrunopts,
4019 (addremove, similarityopts + walkopts + dryrunopts,
4008 _('[OPTION]... [FILE]...')),
4020 _('[OPTION]... [FILE]...')),
4009 "^annotate|blame":
4021 "^annotate|blame":
4010 (annotate,
4022 (annotate,
4011 [('r', 'rev', '',
4023 [('r', 'rev', '',
4012 _('annotate the specified revision'), _('REV')),
4024 _('annotate the specified revision'), _('REV')),
4013 ('', 'follow', None,
4025 ('', 'follow', None,
4014 _('follow copies/renames and list the filename (DEPRECATED)')),
4026 _('follow copies/renames and list the filename (DEPRECATED)')),
4015 ('', 'no-follow', None, _("don't follow copies and renames")),
4027 ('', 'no-follow', None, _("don't follow copies and renames")),
4016 ('a', 'text', None, _('treat all files as text')),
4028 ('a', 'text', None, _('treat all files as text')),
4017 ('u', 'user', None, _('list the author (long with -v)')),
4029 ('u', 'user', None, _('list the author (long with -v)')),
4018 ('f', 'file', None, _('list the filename')),
4030 ('f', 'file', None, _('list the filename')),
4019 ('d', 'date', None, _('list the date (short with -q)')),
4031 ('d', 'date', None, _('list the date (short with -q)')),
4020 ('n', 'number', None, _('list the revision number (default)')),
4032 ('n', 'number', None, _('list the revision number (default)')),
4021 ('c', 'changeset', None, _('list the changeset')),
4033 ('c', 'changeset', None, _('list the changeset')),
4022 ('l', 'line-number', None,
4034 ('l', 'line-number', None,
4023 _('show line number at the first appearance'))
4035 _('show line number at the first appearance'))
4024 ] + walkopts,
4036 ] + walkopts,
4025 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4037 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4026 "archive":
4038 "archive":
4027 (archive,
4039 (archive,
4028 [('', 'no-decode', None, _('do not pass files through decoders')),
4040 [('', 'no-decode', None, _('do not pass files through decoders')),
4029 ('p', 'prefix', '',
4041 ('p', 'prefix', '',
4030 _('directory prefix for files in archive'), _('PREFIX')),
4042 _('directory prefix for files in archive'), _('PREFIX')),
4031 ('r', 'rev', '',
4043 ('r', 'rev', '',
4032 _('revision to distribute'), _('REV')),
4044 _('revision to distribute'), _('REV')),
4033 ('t', 'type', '',
4045 ('t', 'type', '',
4034 _('type of distribution to create'), _('TYPE')),
4046 _('type of distribution to create'), _('TYPE')),
4035 ] + subrepoopts + walkopts,
4047 ] + subrepoopts + walkopts,
4036 _('[OPTION]... DEST')),
4048 _('[OPTION]... DEST')),
4037 "backout":
4049 "backout":
4038 (backout,
4050 (backout,
4039 [('', 'merge', None,
4051 [('', 'merge', None,
4040 _('merge with old dirstate parent after backout')),
4052 _('merge with old dirstate parent after backout')),
4041 ('', 'parent', '',
4053 ('', 'parent', '',
4042 _('parent to choose when backing out merge'), _('REV')),
4054 _('parent to choose when backing out merge'), _('REV')),
4043 ('t', 'tool', '',
4055 ('t', 'tool', '',
4044 _('specify merge tool')),
4056 _('specify merge tool')),
4045 ('r', 'rev', '',
4057 ('r', 'rev', '',
4046 _('revision to backout'), _('REV')),
4058 _('revision to backout'), _('REV')),
4047 ] + walkopts + commitopts + commitopts2,
4059 ] + walkopts + commitopts + commitopts2,
4048 _('[OPTION]... [-r] REV')),
4060 _('[OPTION]... [-r] REV')),
4049 "bisect":
4061 "bisect":
4050 (bisect,
4062 (bisect,
4051 [('r', 'reset', False, _('reset bisect state')),
4063 [('r', 'reset', False, _('reset bisect state')),
4052 ('g', 'good', False, _('mark changeset good')),
4064 ('g', 'good', False, _('mark changeset good')),
4053 ('b', 'bad', False, _('mark changeset bad')),
4065 ('b', 'bad', False, _('mark changeset bad')),
4054 ('s', 'skip', False, _('skip testing changeset')),
4066 ('s', 'skip', False, _('skip testing changeset')),
4055 ('c', 'command', '',
4067 ('c', 'command', '',
4056 _('use command to check changeset state'), _('CMD')),
4068 _('use command to check changeset state'), _('CMD')),
4057 ('U', 'noupdate', False, _('do not update to target'))],
4069 ('U', 'noupdate', False, _('do not update to target'))],
4058 _("[-gbsr] [-U] [-c CMD] [REV]")),
4070 _("[-gbsr] [-U] [-c CMD] [REV]")),
4059 "branch":
4071 "branch":
4060 (branch,
4072 (branch,
4061 [('f', 'force', None,
4073 [('f', 'force', None,
4062 _('set branch name even if it shadows an existing branch')),
4074 _('set branch name even if it shadows an existing branch')),
4063 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4075 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4064 _('[-fC] [NAME]')),
4076 _('[-fC] [NAME]')),
4065 "branches":
4077 "branches":
4066 (branches,
4078 (branches,
4067 [('a', 'active', False,
4079 [('a', 'active', False,
4068 _('show only branches that have unmerged heads')),
4080 _('show only branches that have unmerged heads')),
4069 ('c', 'closed', False,
4081 ('c', 'closed', False,
4070 _('show normal and closed branches'))],
4082 _('show normal and closed branches'))],
4071 _('[-ac]')),
4083 _('[-ac]')),
4072 "bundle":
4084 "bundle":
4073 (bundle,
4085 (bundle,
4074 [('f', 'force', None,
4086 [('f', 'force', None,
4075 _('run even when the destination is unrelated')),
4087 _('run even when the destination is unrelated')),
4076 ('r', 'rev', [],
4088 ('r', 'rev', [],
4077 _('a changeset intended to be added to the destination'),
4089 _('a changeset intended to be added to the destination'),
4078 _('REV')),
4090 _('REV')),
4079 ('b', 'branch', [],
4091 ('b', 'branch', [],
4080 _('a specific branch you would like to bundle'),
4092 _('a specific branch you would like to bundle'),
4081 _('BRANCH')),
4093 _('BRANCH')),
4082 ('', 'base', [],
4094 ('', 'base', [],
4083 _('a base changeset assumed to be available at the destination'),
4095 _('a base changeset assumed to be available at the destination'),
4084 _('REV')),
4096 _('REV')),
4085 ('a', 'all', None, _('bundle all changesets in the repository')),
4097 ('a', 'all', None, _('bundle all changesets in the repository')),
4086 ('t', 'type', 'bzip2',
4098 ('t', 'type', 'bzip2',
4087 _('bundle compression type to use'), _('TYPE')),
4099 _('bundle compression type to use'), _('TYPE')),
4088 ] + remoteopts,
4100 ] + remoteopts,
4089 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4101 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4090 "cat":
4102 "cat":
4091 (cat,
4103 (cat,
4092 [('o', 'output', '',
4104 [('o', 'output', '',
4093 _('print output to file with formatted name'), _('FORMAT')),
4105 _('print output to file with formatted name'), _('FORMAT')),
4094 ('r', 'rev', '',
4106 ('r', 'rev', '',
4095 _('print the given revision'), _('REV')),
4107 _('print the given revision'), _('REV')),
4096 ('', 'decode', None, _('apply any matching decode filter')),
4108 ('', 'decode', None, _('apply any matching decode filter')),
4097 ] + walkopts,
4109 ] + walkopts,
4098 _('[OPTION]... FILE...')),
4110 _('[OPTION]... FILE...')),
4099 "^clone":
4111 "^clone":
4100 (clone,
4112 (clone,
4101 [('U', 'noupdate', None,
4113 [('U', 'noupdate', None,
4102 _('the clone will include an empty working copy (only a repository)')),
4114 _('the clone will include an empty working copy (only a repository)')),
4103 ('u', 'updaterev', '',
4115 ('u', 'updaterev', '',
4104 _('revision, tag or branch to check out'), _('REV')),
4116 _('revision, tag or branch to check out'), _('REV')),
4105 ('r', 'rev', [],
4117 ('r', 'rev', [],
4106 _('include the specified changeset'), _('REV')),
4118 _('include the specified changeset'), _('REV')),
4107 ('b', 'branch', [],
4119 ('b', 'branch', [],
4108 _('clone only the specified branch'), _('BRANCH')),
4120 _('clone only the specified branch'), _('BRANCH')),
4109 ('', 'pull', None, _('use pull protocol to copy metadata')),
4121 ('', 'pull', None, _('use pull protocol to copy metadata')),
4110 ('', 'uncompressed', None,
4122 ('', 'uncompressed', None,
4111 _('use uncompressed transfer (fast over LAN)')),
4123 _('use uncompressed transfer (fast over LAN)')),
4112 ] + remoteopts,
4124 ] + remoteopts,
4113 _('[OPTION]... SOURCE [DEST]')),
4125 _('[OPTION]... SOURCE [DEST]')),
4114 "^commit|ci":
4126 "^commit|ci":
4115 (commit,
4127 (commit,
4116 [('A', 'addremove', None,
4128 [('A', 'addremove', None,
4117 _('mark new/missing files as added/removed before committing')),
4129 _('mark new/missing files as added/removed before committing')),
4118 ('', 'close-branch', None,
4130 ('', 'close-branch', None,
4119 _('mark a branch as closed, hiding it from the branch list')),
4131 _('mark a branch as closed, hiding it from the branch list')),
4120 ] + walkopts + commitopts + commitopts2,
4132 ] + walkopts + commitopts + commitopts2,
4121 _('[OPTION]... [FILE]...')),
4133 _('[OPTION]... [FILE]...')),
4122 "copy|cp":
4134 "copy|cp":
4123 (copy,
4135 (copy,
4124 [('A', 'after', None, _('record a copy that has already occurred')),
4136 [('A', 'after', None, _('record a copy that has already occurred')),
4125 ('f', 'force', None,
4137 ('f', 'force', None,
4126 _('forcibly copy over an existing managed file')),
4138 _('forcibly copy over an existing managed file')),
4127 ] + walkopts + dryrunopts,
4139 ] + walkopts + dryrunopts,
4128 _('[OPTION]... [SOURCE]... DEST')),
4140 _('[OPTION]... [SOURCE]... DEST')),
4129 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4141 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4130 "debugbuilddag":
4142 "debugbuilddag":
4131 (debugbuilddag,
4143 (debugbuilddag,
4132 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4144 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4133 ('a', 'appended-file', None, _('add single file all revs append to')),
4145 ('a', 'appended-file', None, _('add single file all revs append to')),
4134 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4146 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4135 ('n', 'new-file', None, _('add new file at each rev')),
4147 ('n', 'new-file', None, _('add new file at each rev')),
4136 ],
4148 ],
4137 _('[OPTION]... TEXT')),
4149 _('[OPTION]... TEXT')),
4138 "debugcheckstate": (debugcheckstate, [], ''),
4150 "debugcheckstate": (debugcheckstate, [], ''),
4139 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4151 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4140 "debugcomplete":
4152 "debugcomplete":
4141 (debugcomplete,
4153 (debugcomplete,
4142 [('o', 'options', None, _('show the command options'))],
4154 [('o', 'options', None, _('show the command options'))],
4143 _('[-o] CMD')),
4155 _('[-o] CMD')),
4144 "debugdag":
4156 "debugdag":
4145 (debugdag,
4157 (debugdag,
4146 [('t', 'tags', None, _('use tags as labels')),
4158 [('t', 'tags', None, _('use tags as labels')),
4147 ('b', 'branches', None, _('annotate with branch names')),
4159 ('b', 'branches', None, _('annotate with branch names')),
4148 ('', 'dots', None, _('use dots for runs')),
4160 ('', 'dots', None, _('use dots for runs')),
4149 ('s', 'spaces', None, _('separate elements by spaces')),
4161 ('s', 'spaces', None, _('separate elements by spaces')),
4150 ],
4162 ],
4151 _('[OPTION]... [FILE [REV]...]')),
4163 _('[OPTION]... [FILE [REV]...]')),
4152 "debugdate":
4164 "debugdate":
4153 (debugdate,
4165 (debugdate,
4154 [('e', 'extended', None, _('try extended date formats'))],
4166 [('e', 'extended', None, _('try extended date formats'))],
4155 _('[-e] DATE [RANGE]')),
4167 _('[-e] DATE [RANGE]')),
4156 "debugdata": (debugdata, [], _('FILE REV')),
4168 "debugdata": (debugdata, [], _('FILE REV')),
4157 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4169 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4158 "debugindex": (debugindex,
4170 "debugindex": (debugindex,
4159 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4171 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4160 _('FILE')),
4172 _('FILE')),
4161 "debugindexdot": (debugindexdot, [], _('FILE')),
4173 "debugindexdot": (debugindexdot, [], _('FILE')),
4162 "debuginstall": (debuginstall, [], ''),
4174 "debuginstall": (debuginstall, [], ''),
4163 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4175 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4164 "debugrebuildstate":
4176 "debugrebuildstate":
4165 (debugrebuildstate,
4177 (debugrebuildstate,
4166 [('r', 'rev', '',
4178 [('r', 'rev', '',
4167 _('revision to rebuild to'), _('REV'))],
4179 _('revision to rebuild to'), _('REV'))],
4168 _('[-r REV] [REV]')),
4180 _('[-r REV] [REV]')),
4169 "debugrename":
4181 "debugrename":
4170 (debugrename,
4182 (debugrename,
4171 [('r', 'rev', '',
4183 [('r', 'rev', '',
4172 _('revision to debug'), _('REV'))],
4184 _('revision to debug'), _('REV'))],
4173 _('[-r REV] FILE')),
4185 _('[-r REV] FILE')),
4174 "debugrevspec":
4186 "debugrevspec":
4175 (debugrevspec, [], ('REVSPEC')),
4187 (debugrevspec, [], ('REVSPEC')),
4176 "debugsetparents":
4188 "debugsetparents":
4177 (debugsetparents, [], _('REV1 [REV2]')),
4189 (debugsetparents, [], _('REV1 [REV2]')),
4178 "debugstate":
4190 "debugstate":
4179 (debugstate,
4191 (debugstate,
4180 [('', 'nodates', None, _('do not display the saved mtime'))],
4192 [('', 'nodates', None, _('do not display the saved mtime'))],
4181 _('[OPTION]...')),
4193 _('[OPTION]...')),
4182 "debugsub":
4194 "debugsub":
4183 (debugsub,
4195 (debugsub,
4184 [('r', 'rev', '',
4196 [('r', 'rev', '',
4185 _('revision to check'), _('REV'))],
4197 _('revision to check'), _('REV'))],
4186 _('[-r REV] [REV]')),
4198 _('[-r REV] [REV]')),
4187 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4199 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4188 "^diff":
4200 "^diff":
4189 (diff,
4201 (diff,
4190 [('r', 'rev', [],
4202 [('r', 'rev', [],
4191 _('revision'), _('REV')),
4203 _('revision'), _('REV')),
4192 ('c', 'change', '',
4204 ('c', 'change', '',
4193 _('change made by revision'), _('REV'))
4205 _('change made by revision'), _('REV'))
4194 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4206 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4195 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4207 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4196 "^export":
4208 "^export":
4197 (export,
4209 (export,
4198 [('o', 'output', '',
4210 [('o', 'output', '',
4199 _('print output to file with formatted name'), _('FORMAT')),
4211 _('print output to file with formatted name'), _('FORMAT')),
4200 ('', 'switch-parent', None, _('diff against the second parent')),
4212 ('', 'switch-parent', None, _('diff against the second parent')),
4201 ('r', 'rev', [],
4213 ('r', 'rev', [],
4202 _('revisions to export'), _('REV')),
4214 _('revisions to export'), _('REV')),
4203 ] + diffopts,
4215 ] + diffopts,
4204 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4216 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4205 "^forget":
4217 "^forget":
4206 (forget,
4218 (forget,
4207 [] + walkopts,
4219 [] + walkopts,
4208 _('[OPTION]... FILE...')),
4220 _('[OPTION]... FILE...')),
4209 "grep":
4221 "grep":
4210 (grep,
4222 (grep,
4211 [('0', 'print0', None, _('end fields with NUL')),
4223 [('0', 'print0', None, _('end fields with NUL')),
4212 ('', 'all', None, _('print all revisions that match')),
4224 ('', 'all', None, _('print all revisions that match')),
4213 ('f', 'follow', None,
4225 ('f', 'follow', None,
4214 _('follow changeset history,'
4226 _('follow changeset history,'
4215 ' or file history across copies and renames')),
4227 ' or file history across copies and renames')),
4216 ('i', 'ignore-case', None, _('ignore case when matching')),
4228 ('i', 'ignore-case', None, _('ignore case when matching')),
4217 ('l', 'files-with-matches', None,
4229 ('l', 'files-with-matches', None,
4218 _('print only filenames and revisions that match')),
4230 _('print only filenames and revisions that match')),
4219 ('n', 'line-number', None, _('print matching line numbers')),
4231 ('n', 'line-number', None, _('print matching line numbers')),
4220 ('r', 'rev', [],
4232 ('r', 'rev', [],
4221 _('only search files changed within revision range'), _('REV')),
4233 _('only search files changed within revision range'), _('REV')),
4222 ('u', 'user', None, _('list the author (long with -v)')),
4234 ('u', 'user', None, _('list the author (long with -v)')),
4223 ('d', 'date', None, _('list the date (short with -q)')),
4235 ('d', 'date', None, _('list the date (short with -q)')),
4224 ] + walkopts,
4236 ] + walkopts,
4225 _('[OPTION]... PATTERN [FILE]...')),
4237 _('[OPTION]... PATTERN [FILE]...')),
4226 "heads":
4238 "heads":
4227 (heads,
4239 (heads,
4228 [('r', 'rev', '',
4240 [('r', 'rev', '',
4229 _('show only heads which are descendants of STARTREV'),
4241 _('show only heads which are descendants of STARTREV'),
4230 _('STARTREV')),
4242 _('STARTREV')),
4231 ('t', 'topo', False, _('show topological heads only')),
4243 ('t', 'topo', False, _('show topological heads only')),
4232 ('a', 'active', False,
4244 ('a', 'active', False,
4233 _('show active branchheads only (DEPRECATED)')),
4245 _('show active branchheads only (DEPRECATED)')),
4234 ('c', 'closed', False,
4246 ('c', 'closed', False,
4235 _('show normal and closed branch heads')),
4247 _('show normal and closed branch heads')),
4236 ] + templateopts,
4248 ] + templateopts,
4237 _('[-ac] [-r STARTREV] [REV]...')),
4249 _('[-ac] [-r STARTREV] [REV]...')),
4238 "help": (help_, [], _('[TOPIC]')),
4250 "help": (help_, [], _('[TOPIC]')),
4239 "identify|id":
4251 "identify|id":
4240 (identify,
4252 (identify,
4241 [('r', 'rev', '',
4253 [('r', 'rev', '',
4242 _('identify the specified revision'), _('REV')),
4254 _('identify the specified revision'), _('REV')),
4243 ('n', 'num', None, _('show local revision number')),
4255 ('n', 'num', None, _('show local revision number')),
4244 ('i', 'id', None, _('show global revision id')),
4256 ('i', 'id', None, _('show global revision id')),
4245 ('b', 'branch', None, _('show branch')),
4257 ('b', 'branch', None, _('show branch')),
4246 ('t', 'tags', None, _('show tags'))],
4258 ('t', 'tags', None, _('show tags'))],
4247 _('[-nibt] [-r REV] [SOURCE]')),
4259 _('[-nibt] [-r REV] [SOURCE]')),
4248 "import|patch":
4260 "import|patch":
4249 (import_,
4261 (import_,
4250 [('p', 'strip', 1,
4262 [('p', 'strip', 1,
4251 _('directory strip option for patch. This has the same '
4263 _('directory strip option for patch. This has the same '
4252 'meaning as the corresponding patch option'),
4264 'meaning as the corresponding patch option'),
4253 _('NUM')),
4265 _('NUM')),
4254 ('b', 'base', '',
4266 ('b', 'base', '',
4255 _('base path'), _('PATH')),
4267 _('base path'), _('PATH')),
4256 ('f', 'force', None,
4268 ('f', 'force', None,
4257 _('skip check for outstanding uncommitted changes')),
4269 _('skip check for outstanding uncommitted changes')),
4258 ('', 'no-commit', None,
4270 ('', 'no-commit', None,
4259 _("don't commit, just update the working directory")),
4271 _("don't commit, just update the working directory")),
4260 ('', 'exact', None,
4272 ('', 'exact', None,
4261 _('apply patch to the nodes from which it was generated')),
4273 _('apply patch to the nodes from which it was generated')),
4262 ('', 'import-branch', None,
4274 ('', 'import-branch', None,
4263 _('use any branch information in patch (implied by --exact)'))] +
4275 _('use any branch information in patch (implied by --exact)'))] +
4264 commitopts + commitopts2 + similarityopts,
4276 commitopts + commitopts2 + similarityopts,
4265 _('[OPTION]... PATCH...')),
4277 _('[OPTION]... PATCH...')),
4266 "incoming|in":
4278 "incoming|in":
4267 (incoming,
4279 (incoming,
4268 [('f', 'force', None,
4280 [('f', 'force', None,
4269 _('run even if remote repository is unrelated')),
4281 _('run even if remote repository is unrelated')),
4270 ('n', 'newest-first', None, _('show newest record first')),
4282 ('n', 'newest-first', None, _('show newest record first')),
4271 ('', 'bundle', '',
4283 ('', 'bundle', '',
4272 _('file to store the bundles into'), _('FILE')),
4284 _('file to store the bundles into'), _('FILE')),
4273 ('r', 'rev', [],
4285 ('r', 'rev', [],
4274 _('a remote changeset intended to be added'), _('REV')),
4286 _('a remote changeset intended to be added'), _('REV')),
4275 ('b', 'branch', [],
4287 ('b', 'branch', [],
4276 _('a specific branch you would like to pull'), _('BRANCH')),
4288 _('a specific branch you would like to pull'), _('BRANCH')),
4277 ] + logopts + remoteopts + subrepoopts,
4289 ] + logopts + remoteopts + subrepoopts,
4278 _('[-p] [-n] [-M] [-f] [-r REV]...'
4290 _('[-p] [-n] [-M] [-f] [-r REV]...'
4279 ' [--bundle FILENAME] [SOURCE]')),
4291 ' [--bundle FILENAME] [SOURCE]')),
4280 "^init":
4292 "^init":
4281 (init,
4293 (init,
4282 remoteopts,
4294 remoteopts,
4283 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4295 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4284 "locate":
4296 "locate":
4285 (locate,
4297 (locate,
4286 [('r', 'rev', '',
4298 [('r', 'rev', '',
4287 _('search the repository as it is in REV'), _('REV')),
4299 _('search the repository as it is in REV'), _('REV')),
4288 ('0', 'print0', None,
4300 ('0', 'print0', None,
4289 _('end filenames with NUL, for use with xargs')),
4301 _('end filenames with NUL, for use with xargs')),
4290 ('f', 'fullpath', None,
4302 ('f', 'fullpath', None,
4291 _('print complete paths from the filesystem root')),
4303 _('print complete paths from the filesystem root')),
4292 ] + walkopts,
4304 ] + walkopts,
4293 _('[OPTION]... [PATTERN]...')),
4305 _('[OPTION]... [PATTERN]...')),
4294 "^log|history":
4306 "^log|history":
4295 (log,
4307 (log,
4296 [('f', 'follow', None,
4308 [('f', 'follow', None,
4297 _('follow changeset history,'
4309 _('follow changeset history,'
4298 ' or file history across copies and renames')),
4310 ' or file history across copies and renames')),
4299 ('', 'follow-first', None,
4311 ('', 'follow-first', None,
4300 _('only follow the first parent of merge changesets')),
4312 _('only follow the first parent of merge changesets')),
4301 ('d', 'date', '',
4313 ('d', 'date', '',
4302 _('show revisions matching date spec'), _('DATE')),
4314 _('show revisions matching date spec'), _('DATE')),
4303 ('C', 'copies', None, _('show copied files')),
4315 ('C', 'copies', None, _('show copied files')),
4304 ('k', 'keyword', [],
4316 ('k', 'keyword', [],
4305 _('do case-insensitive search for a given text'), _('TEXT')),
4317 _('do case-insensitive search for a given text'), _('TEXT')),
4306 ('r', 'rev', [],
4318 ('r', 'rev', [],
4307 _('show the specified revision or range'), _('REV')),
4319 _('show the specified revision or range'), _('REV')),
4308 ('', 'removed', None, _('include revisions where files were removed')),
4320 ('', 'removed', None, _('include revisions where files were removed')),
4309 ('m', 'only-merges', None, _('show only merges')),
4321 ('m', 'only-merges', None, _('show only merges')),
4310 ('u', 'user', [],
4322 ('u', 'user', [],
4311 _('revisions committed by user'), _('USER')),
4323 _('revisions committed by user'), _('USER')),
4312 ('', 'only-branch', [],
4324 ('', 'only-branch', [],
4313 _('show only changesets within the given named branch (DEPRECATED)'),
4325 _('show only changesets within the given named branch (DEPRECATED)'),
4314 _('BRANCH')),
4326 _('BRANCH')),
4315 ('b', 'branch', [],
4327 ('b', 'branch', [],
4316 _('show changesets within the given named branch'), _('BRANCH')),
4328 _('show changesets within the given named branch'), _('BRANCH')),
4317 ('P', 'prune', [],
4329 ('P', 'prune', [],
4318 _('do not display revision or any of its ancestors'), _('REV')),
4330 _('do not display revision or any of its ancestors'), _('REV')),
4319 ] + logopts + walkopts,
4331 ] + logopts + walkopts,
4320 _('[OPTION]... [FILE]')),
4332 _('[OPTION]... [FILE]')),
4321 "manifest":
4333 "manifest":
4322 (manifest,
4334 (manifest,
4323 [('r', 'rev', '',
4335 [('r', 'rev', '',
4324 _('revision to display'), _('REV'))],
4336 _('revision to display'), _('REV'))],
4325 _('[-r REV]')),
4337 _('[-r REV]')),
4326 "^merge":
4338 "^merge":
4327 (merge,
4339 (merge,
4328 [('f', 'force', None, _('force a merge with outstanding changes')),
4340 [('f', 'force', None, _('force a merge with outstanding changes')),
4329 ('t', 'tool', '', _('specify merge tool')),
4341 ('t', 'tool', '', _('specify merge tool')),
4330 ('r', 'rev', '',
4342 ('r', 'rev', '',
4331 _('revision to merge'), _('REV')),
4343 _('revision to merge'), _('REV')),
4332 ('P', 'preview', None,
4344 ('P', 'preview', None,
4333 _('review revisions to merge (no merge is performed)'))],
4345 _('review revisions to merge (no merge is performed)'))],
4334 _('[-P] [-f] [[-r] REV]')),
4346 _('[-P] [-f] [[-r] REV]')),
4335 "outgoing|out":
4347 "outgoing|out":
4336 (outgoing,
4348 (outgoing,
4337 [('f', 'force', None,
4349 [('f', 'force', None,
4338 _('run even when the destination is unrelated')),
4350 _('run even when the destination is unrelated')),
4339 ('r', 'rev', [],
4351 ('r', 'rev', [],
4340 _('a changeset intended to be included in the destination'),
4352 _('a changeset intended to be included in the destination'),
4341 _('REV')),
4353 _('REV')),
4342 ('n', 'newest-first', None, _('show newest record first')),
4354 ('n', 'newest-first', None, _('show newest record first')),
4343 ('b', 'branch', [],
4355 ('b', 'branch', [],
4344 _('a specific branch you would like to push'), _('BRANCH')),
4356 _('a specific branch you would like to push'), _('BRANCH')),
4345 ] + logopts + remoteopts + subrepoopts,
4357 ] + logopts + remoteopts + subrepoopts,
4346 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4358 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4347 "parents":
4359 "parents":
4348 (parents,
4360 (parents,
4349 [('r', 'rev', '',
4361 [('r', 'rev', '',
4350 _('show parents of the specified revision'), _('REV')),
4362 _('show parents of the specified revision'), _('REV')),
4351 ] + templateopts,
4363 ] + templateopts,
4352 _('[-r REV] [FILE]')),
4364 _('[-r REV] [FILE]')),
4353 "paths": (paths, [], _('[NAME]')),
4365 "paths": (paths, [], _('[NAME]')),
4354 "^pull":
4366 "^pull":
4355 (pull,
4367 (pull,
4356 [('u', 'update', None,
4368 [('u', 'update', None,
4357 _('update to new branch head if changesets were pulled')),
4369 _('update to new branch head if changesets were pulled')),
4358 ('f', 'force', None,
4370 ('f', 'force', None,
4359 _('run even when remote repository is unrelated')),
4371 _('run even when remote repository is unrelated')),
4360 ('r', 'rev', [],
4372 ('r', 'rev', [],
4361 _('a remote changeset intended to be added'), _('REV')),
4373 _('a remote changeset intended to be added'), _('REV')),
4362 ('b', 'branch', [],
4374 ('b', 'branch', [],
4363 _('a specific branch you would like to pull'), _('BRANCH')),
4375 _('a specific branch you would like to pull'), _('BRANCH')),
4364 ] + remoteopts,
4376 ] + remoteopts,
4365 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4377 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4366 "^push":
4378 "^push":
4367 (push,
4379 (push,
4368 [('f', 'force', None, _('force push')),
4380 [('f', 'force', None, _('force push')),
4369 ('r', 'rev', [],
4381 ('r', 'rev', [],
4370 _('a changeset intended to be included in the destination'),
4382 _('a changeset intended to be included in the destination'),
4371 _('REV')),
4383 _('REV')),
4372 ('b', 'branch', [],
4384 ('b', 'branch', [],
4373 _('a specific branch you would like to push'), _('BRANCH')),
4385 _('a specific branch you would like to push'), _('BRANCH')),
4374 ('', 'new-branch', False, _('allow pushing a new branch')),
4386 ('', 'new-branch', False, _('allow pushing a new branch')),
4375 ] + remoteopts,
4387 ] + remoteopts,
4376 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4388 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4377 "recover": (recover, []),
4389 "recover": (recover, []),
4378 "^remove|rm":
4390 "^remove|rm":
4379 (remove,
4391 (remove,
4380 [('A', 'after', None, _('record delete for missing files')),
4392 [('A', 'after', None, _('record delete for missing files')),
4381 ('f', 'force', None,
4393 ('f', 'force', None,
4382 _('remove (and delete) file even if added or modified')),
4394 _('remove (and delete) file even if added or modified')),
4383 ] + walkopts,
4395 ] + walkopts,
4384 _('[OPTION]... FILE...')),
4396 _('[OPTION]... FILE...')),
4385 "rename|move|mv":
4397 "rename|move|mv":
4386 (rename,
4398 (rename,
4387 [('A', 'after', None, _('record a rename that has already occurred')),
4399 [('A', 'after', None, _('record a rename that has already occurred')),
4388 ('f', 'force', None,
4400 ('f', 'force', None,
4389 _('forcibly copy over an existing managed file')),
4401 _('forcibly copy over an existing managed file')),
4390 ] + walkopts + dryrunopts,
4402 ] + walkopts + dryrunopts,
4391 _('[OPTION]... SOURCE... DEST')),
4403 _('[OPTION]... SOURCE... DEST')),
4392 "resolve":
4404 "resolve":
4393 (resolve,
4405 (resolve,
4394 [('a', 'all', None, _('select all unresolved files')),
4406 [('a', 'all', None, _('select all unresolved files')),
4395 ('l', 'list', None, _('list state of files needing merge')),
4407 ('l', 'list', None, _('list state of files needing merge')),
4396 ('m', 'mark', None, _('mark files as resolved')),
4408 ('m', 'mark', None, _('mark files as resolved')),
4397 ('u', 'unmark', None, _('mark files as unresolved')),
4409 ('u', 'unmark', None, _('mark files as unresolved')),
4398 ('t', 'tool', '', _('specify merge tool')),
4410 ('t', 'tool', '', _('specify merge tool')),
4399 ('n', 'no-status', None, _('hide status prefix'))]
4411 ('n', 'no-status', None, _('hide status prefix'))]
4400 + walkopts,
4412 + walkopts,
4401 _('[OPTION]... [FILE]...')),
4413 _('[OPTION]... [FILE]...')),
4402 "revert":
4414 "revert":
4403 (revert,
4415 (revert,
4404 [('a', 'all', None, _('revert all changes when no arguments given')),
4416 [('a', 'all', None, _('revert all changes when no arguments given')),
4405 ('d', 'date', '',
4417 ('d', 'date', '',
4406 _('tipmost revision matching date'), _('DATE')),
4418 _('tipmost revision matching date'), _('DATE')),
4407 ('r', 'rev', '',
4419 ('r', 'rev', '',
4408 _('revert to the specified revision'), _('REV')),
4420 _('revert to the specified revision'), _('REV')),
4409 ('', 'no-backup', None, _('do not save backup copies of files')),
4421 ('', 'no-backup', None, _('do not save backup copies of files')),
4410 ] + walkopts + dryrunopts,
4422 ] + walkopts + dryrunopts,
4411 _('[OPTION]... [-r REV] [NAME]...')),
4423 _('[OPTION]... [-r REV] [NAME]...')),
4412 "rollback": (rollback, dryrunopts),
4424 "rollback": (rollback, dryrunopts),
4413 "root": (root, []),
4425 "root": (root, []),
4414 "^serve":
4426 "^serve":
4415 (serve,
4427 (serve,
4416 [('A', 'accesslog', '',
4428 [('A', 'accesslog', '',
4417 _('name of access log file to write to'), _('FILE')),
4429 _('name of access log file to write to'), _('FILE')),
4418 ('d', 'daemon', None, _('run server in background')),
4430 ('d', 'daemon', None, _('run server in background')),
4419 ('', 'daemon-pipefds', '',
4431 ('', 'daemon-pipefds', '',
4420 _('used internally by daemon mode'), _('NUM')),
4432 _('used internally by daemon mode'), _('NUM')),
4421 ('E', 'errorlog', '',
4433 ('E', 'errorlog', '',
4422 _('name of error log file to write to'), _('FILE')),
4434 _('name of error log file to write to'), _('FILE')),
4423 # use string type, then we can check if something was passed
4435 # use string type, then we can check if something was passed
4424 ('p', 'port', '',
4436 ('p', 'port', '',
4425 _('port to listen on (default: 8000)'), _('PORT')),
4437 _('port to listen on (default: 8000)'), _('PORT')),
4426 ('a', 'address', '',
4438 ('a', 'address', '',
4427 _('address to listen on (default: all interfaces)'), _('ADDR')),
4439 _('address to listen on (default: all interfaces)'), _('ADDR')),
4428 ('', 'prefix', '',
4440 ('', 'prefix', '',
4429 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4441 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4430 ('n', 'name', '',
4442 ('n', 'name', '',
4431 _('name to show in web pages (default: working directory)'),
4443 _('name to show in web pages (default: working directory)'),
4432 _('NAME')),
4444 _('NAME')),
4433 ('', 'web-conf', '',
4445 ('', 'web-conf', '',
4434 _('name of the hgweb config file (see "hg help hgweb")'),
4446 _('name of the hgweb config file (see "hg help hgweb")'),
4435 _('FILE')),
4447 _('FILE')),
4436 ('', 'webdir-conf', '',
4448 ('', 'webdir-conf', '',
4437 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4449 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4438 ('', 'pid-file', '',
4450 ('', 'pid-file', '',
4439 _('name of file to write process ID to'), _('FILE')),
4451 _('name of file to write process ID to'), _('FILE')),
4440 ('', 'stdio', None, _('for remote clients')),
4452 ('', 'stdio', None, _('for remote clients')),
4441 ('t', 'templates', '',
4453 ('t', 'templates', '',
4442 _('web templates to use'), _('TEMPLATE')),
4454 _('web templates to use'), _('TEMPLATE')),
4443 ('', 'style', '',
4455 ('', 'style', '',
4444 _('template style to use'), _('STYLE')),
4456 _('template style to use'), _('STYLE')),
4445 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4457 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4446 ('', 'certificate', '',
4458 ('', 'certificate', '',
4447 _('SSL certificate file'), _('FILE'))],
4459 _('SSL certificate file'), _('FILE'))],
4448 _('[OPTION]...')),
4460 _('[OPTION]...')),
4449 "showconfig|debugconfig":
4461 "showconfig|debugconfig":
4450 (showconfig,
4462 (showconfig,
4451 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4463 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4452 _('[-u] [NAME]...')),
4464 _('[-u] [NAME]...')),
4453 "^summary|sum":
4465 "^summary|sum":
4454 (summary,
4466 (summary,
4455 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4467 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4456 "^status|st":
4468 "^status|st":
4457 (status,
4469 (status,
4458 [('A', 'all', None, _('show status of all files')),
4470 [('A', 'all', None, _('show status of all files')),
4459 ('m', 'modified', None, _('show only modified files')),
4471 ('m', 'modified', None, _('show only modified files')),
4460 ('a', 'added', None, _('show only added files')),
4472 ('a', 'added', None, _('show only added files')),
4461 ('r', 'removed', None, _('show only removed files')),
4473 ('r', 'removed', None, _('show only removed files')),
4462 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4474 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4463 ('c', 'clean', None, _('show only files without changes')),
4475 ('c', 'clean', None, _('show only files without changes')),
4464 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4476 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4465 ('i', 'ignored', None, _('show only ignored files')),
4477 ('i', 'ignored', None, _('show only ignored files')),
4466 ('n', 'no-status', None, _('hide status prefix')),
4478 ('n', 'no-status', None, _('hide status prefix')),
4467 ('C', 'copies', None, _('show source of copied files')),
4479 ('C', 'copies', None, _('show source of copied files')),
4468 ('0', 'print0', None,
4480 ('0', 'print0', None,
4469 _('end filenames with NUL, for use with xargs')),
4481 _('end filenames with NUL, for use with xargs')),
4470 ('', 'rev', [],
4482 ('', 'rev', [],
4471 _('show difference from revision'), _('REV')),
4483 _('show difference from revision'), _('REV')),
4472 ('', 'change', '',
4484 ('', 'change', '',
4473 _('list the changed files of a revision'), _('REV')),
4485 _('list the changed files of a revision'), _('REV')),
4474 ] + walkopts + subrepoopts,
4486 ] + walkopts + subrepoopts,
4475 _('[OPTION]... [FILE]...')),
4487 _('[OPTION]... [FILE]...')),
4476 "tag":
4488 "tag":
4477 (tag,
4489 (tag,
4478 [('f', 'force', None, _('replace existing tag')),
4490 [('f', 'force', None, _('force tag')),
4479 ('l', 'local', None, _('make the tag local')),
4491 ('l', 'local', None, _('make the tag local')),
4480 ('r', 'rev', '',
4492 ('r', 'rev', '',
4481 _('revision to tag'), _('REV')),
4493 _('revision to tag'), _('REV')),
4482 ('', 'remove', None, _('remove a tag')),
4494 ('', 'remove', None, _('remove a tag')),
4483 # -l/--local is already there, commitopts cannot be used
4495 # -l/--local is already there, commitopts cannot be used
4484 ('e', 'edit', None, _('edit commit message')),
4496 ('e', 'edit', None, _('edit commit message')),
4485 ('m', 'message', '',
4497 ('m', 'message', '',
4486 _('use <text> as commit message'), _('TEXT')),
4498 _('use <text> as commit message'), _('TEXT')),
4487 ] + commitopts2,
4499 ] + commitopts2,
4488 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4500 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4489 "tags": (tags, [], ''),
4501 "tags": (tags, [], ''),
4490 "tip":
4502 "tip":
4491 (tip,
4503 (tip,
4492 [('p', 'patch', None, _('show patch')),
4504 [('p', 'patch', None, _('show patch')),
4493 ('g', 'git', None, _('use git extended diff format')),
4505 ('g', 'git', None, _('use git extended diff format')),
4494 ] + templateopts,
4506 ] + templateopts,
4495 _('[-p] [-g]')),
4507 _('[-p] [-g]')),
4496 "unbundle":
4508 "unbundle":
4497 (unbundle,
4509 (unbundle,
4498 [('u', 'update', None,
4510 [('u', 'update', None,
4499 _('update to new branch head if changesets were unbundled'))],
4511 _('update to new branch head if changesets were unbundled'))],
4500 _('[-u] FILE...')),
4512 _('[-u] FILE...')),
4501 "^update|up|checkout|co":
4513 "^update|up|checkout|co":
4502 (update,
4514 (update,
4503 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4515 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4504 ('c', 'check', None,
4516 ('c', 'check', None,
4505 _('update across branches if no uncommitted changes')),
4517 _('update across branches if no uncommitted changes')),
4506 ('d', 'date', '',
4518 ('d', 'date', '',
4507 _('tipmost revision matching date'), _('DATE')),
4519 _('tipmost revision matching date'), _('DATE')),
4508 ('r', 'rev', '',
4520 ('r', 'rev', '',
4509 _('revision'), _('REV'))],
4521 _('revision'), _('REV'))],
4510 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4522 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4511 "verify": (verify, []),
4523 "verify": (verify, []),
4512 "version": (version_, []),
4524 "version": (version_, []),
4513 }
4525 }
4514
4526
4515 norepo = ("clone init version help debugcommands debugcomplete"
4527 norepo = ("clone init version help debugcommands debugcomplete"
4516 " debugdate debuginstall debugfsinfo debugpushkey")
4528 " debugdate debuginstall debugfsinfo debugpushkey")
4517 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4529 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4518 " debugdata debugindex debugindexdot")
4530 " debugdata debugindex debugindexdot")
@@ -1,16 +1,16 b''
1 $ rm -rf a
1 $ rm -rf a
2 $ hg init a
2 $ hg init a
3 $ cd a
3 $ cd a
4 $ echo a > a
4 $ echo a > a
5 $ hg ci -Am0
5 $ hg ci -Am0
6 adding a
6 adding a
7 $ hg tag t1 # 1
7 $ hg tag t1 # 1
8 $ hg tag --remove t1 # 2
8 $ hg tag --remove t1 # 2
9
9
10 $ hg co 1
10 $ hg co 1
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 $ hg tag -r0 t1
12 $ hg tag -f -r0 t1
13 $ hg tags
13 $ hg tags
14 tip 3:a49829c4fc11
14 tip 3:a49829c4fc11
15 t1 0:f7b1eb17ad24
15 t1 0:f7b1eb17ad24
16
16
@@ -1,244 +1,278 b''
1 $ hg init test
1 $ hg init test
2 $ cd test
2 $ cd test
3
3
4 $ echo a > a
4 $ echo a > a
5 $ hg add a
5 $ hg add a
6 $ hg commit -m "test"
6 $ hg commit -m "test"
7 $ hg history
7 $ hg history
8 changeset: 0:acb14030fe0a
8 changeset: 0:acb14030fe0a
9 tag: tip
9 tag: tip
10 user: test
10 user: test
11 date: Thu Jan 01 00:00:00 1970 +0000
11 date: Thu Jan 01 00:00:00 1970 +0000
12 summary: test
12 summary: test
13
13
14
14
15 $ hg tag ' '
15 $ hg tag ' '
16 abort: tag names cannot consist entirely of whitespace
16 abort: tag names cannot consist entirely of whitespace
17 [255]
17 [255]
18
18
19 $ hg tag "bleah"
19 $ hg tag "bleah"
20 $ hg history
20 $ hg history
21 changeset: 1:d4f0d2909abc
21 changeset: 1:d4f0d2909abc
22 tag: tip
22 tag: tip
23 user: test
23 user: test
24 date: Thu Jan 01 00:00:00 1970 +0000
24 date: Thu Jan 01 00:00:00 1970 +0000
25 summary: Added tag bleah for changeset acb14030fe0a
25 summary: Added tag bleah for changeset acb14030fe0a
26
26
27 changeset: 0:acb14030fe0a
27 changeset: 0:acb14030fe0a
28 tag: bleah
28 tag: bleah
29 user: test
29 user: test
30 date: Thu Jan 01 00:00:00 1970 +0000
30 date: Thu Jan 01 00:00:00 1970 +0000
31 summary: test
31 summary: test
32
32
33
33
34 $ echo foo >> .hgtags
34 $ echo foo >> .hgtags
35 $ hg tag "bleah2"
35 $ hg tag "bleah2"
36 abort: working copy of .hgtags is changed (please commit .hgtags manually)
36 abort: working copy of .hgtags is changed (please commit .hgtags manually)
37 [255]
37 [255]
38
38
39 $ hg revert .hgtags
39 $ hg revert .hgtags
40 $ hg tag -r 0 x y z y y z
40 $ hg tag -r 0 x y z y y z
41 abort: tag names must be unique
41 abort: tag names must be unique
42 [255]
42 [255]
43 $ hg tag tap nada dot tip null .
43 $ hg tag tap nada dot tip null .
44 abort: the name 'tip' is reserved
44 abort: the name 'tip' is reserved
45 [255]
45 [255]
46 $ hg tag "bleah"
46 $ hg tag "bleah"
47 abort: tag 'bleah' already exists (use -f to force)
47 abort: tag 'bleah' already exists (use -f to force)
48 [255]
48 [255]
49 $ hg tag "blecch" "bleah"
49 $ hg tag "blecch" "bleah"
50 abort: tag 'bleah' already exists (use -f to force)
50 abort: tag 'bleah' already exists (use -f to force)
51 [255]
51 [255]
52
52
53 $ hg tag --remove "blecch"
53 $ hg tag --remove "blecch"
54 abort: tag 'blecch' does not exist
54 abort: tag 'blecch' does not exist
55 [255]
55 [255]
56 $ hg tag --remove "bleah" "blecch" "blough"
56 $ hg tag --remove "bleah" "blecch" "blough"
57 abort: tag 'blecch' does not exist
57 abort: tag 'blecch' does not exist
58 [255]
58 [255]
59
59
60 $ hg tag -r 0 "bleah0"
60 $ hg tag -r 0 "bleah0"
61 $ hg tag -l -r 1 "bleah1"
61 $ hg tag -l -r 1 "bleah1"
62 $ hg tag gack gawk gorp
62 $ hg tag gack gawk gorp
63 $ hg tag -f gack
63 $ hg tag -f gack
64 $ hg tag --remove gack gorp
64 $ hg tag --remove gack gorp
65
65
66 $ cat .hgtags
66 $ cat .hgtags
67 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
67 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
68 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
68 acb14030fe0a21b60322c440ad2d20cf7685a376 bleah0
69 336fccc858a4eb69609a291105009e484a6b6b8d gack
69 336fccc858a4eb69609a291105009e484a6b6b8d gack
70 336fccc858a4eb69609a291105009e484a6b6b8d gawk
70 336fccc858a4eb69609a291105009e484a6b6b8d gawk
71 336fccc858a4eb69609a291105009e484a6b6b8d gorp
71 336fccc858a4eb69609a291105009e484a6b6b8d gorp
72 336fccc858a4eb69609a291105009e484a6b6b8d gack
72 336fccc858a4eb69609a291105009e484a6b6b8d gack
73 799667b6f2d9b957f73fa644a918c2df22bab58f gack
73 799667b6f2d9b957f73fa644a918c2df22bab58f gack
74 799667b6f2d9b957f73fa644a918c2df22bab58f gack
74 799667b6f2d9b957f73fa644a918c2df22bab58f gack
75 0000000000000000000000000000000000000000 gack
75 0000000000000000000000000000000000000000 gack
76 336fccc858a4eb69609a291105009e484a6b6b8d gorp
76 336fccc858a4eb69609a291105009e484a6b6b8d gorp
77 0000000000000000000000000000000000000000 gorp
77 0000000000000000000000000000000000000000 gorp
78 $ cat .hg/localtags
78 $ cat .hg/localtags
79 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
79 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
80
80
81 tagging on a non-head revision
82
81 $ hg update 0
83 $ hg update 0
82 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
85 $ hg tag -l localblah
83 $ hg tag "foobar"
86 $ hg tag "foobar"
87 abort: not at a branch head (use -f to force)
88 [255]
89 $ hg tag -f "foobar"
84 $ cat .hgtags
90 $ cat .hgtags
85 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
91 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
86 $ cat .hg/localtags
92 $ cat .hg/localtags
87 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
93 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
94 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
88
95
89 $ hg tag -l 'xx
96 $ hg tag -l 'xx
90 > newline'
97 > newline'
91 abort: '\n' cannot be used in a tag name
98 abort: '\n' cannot be used in a tag name
92 [255]
99 [255]
93 $ hg tag -l 'xx:xx'
100 $ hg tag -l 'xx:xx'
94 abort: ':' cannot be used in a tag name
101 abort: ':' cannot be used in a tag name
95 [255]
102 [255]
96
103
97 cloning local tags
104 cloning local tags
98
105
99 $ cd ..
106 $ cd ..
100 $ hg -R test log -r0:5
107 $ hg -R test log -r0:5
101 changeset: 0:acb14030fe0a
108 changeset: 0:acb14030fe0a
102 tag: bleah
109 tag: bleah
103 tag: bleah0
110 tag: bleah0
104 tag: foobar
111 tag: foobar
112 tag: localblah
105 user: test
113 user: test
106 date: Thu Jan 01 00:00:00 1970 +0000
114 date: Thu Jan 01 00:00:00 1970 +0000
107 summary: test
115 summary: test
108
116
109 changeset: 1:d4f0d2909abc
117 changeset: 1:d4f0d2909abc
110 tag: bleah1
118 tag: bleah1
111 user: test
119 user: test
112 date: Thu Jan 01 00:00:00 1970 +0000
120 date: Thu Jan 01 00:00:00 1970 +0000
113 summary: Added tag bleah for changeset acb14030fe0a
121 summary: Added tag bleah for changeset acb14030fe0a
114
122
115 changeset: 2:336fccc858a4
123 changeset: 2:336fccc858a4
116 tag: gawk
124 tag: gawk
117 user: test
125 user: test
118 date: Thu Jan 01 00:00:00 1970 +0000
126 date: Thu Jan 01 00:00:00 1970 +0000
119 summary: Added tag bleah0 for changeset acb14030fe0a
127 summary: Added tag bleah0 for changeset acb14030fe0a
120
128
121 changeset: 3:799667b6f2d9
129 changeset: 3:799667b6f2d9
122 user: test
130 user: test
123 date: Thu Jan 01 00:00:00 1970 +0000
131 date: Thu Jan 01 00:00:00 1970 +0000
124 summary: Added tag gack, gawk, gorp for changeset 336fccc858a4
132 summary: Added tag gack, gawk, gorp for changeset 336fccc858a4
125
133
126 changeset: 4:154eeb7c0138
134 changeset: 4:154eeb7c0138
127 user: test
135 user: test
128 date: Thu Jan 01 00:00:00 1970 +0000
136 date: Thu Jan 01 00:00:00 1970 +0000
129 summary: Added tag gack for changeset 799667b6f2d9
137 summary: Added tag gack for changeset 799667b6f2d9
130
138
131 changeset: 5:b4bb47aaff09
139 changeset: 5:b4bb47aaff09
132 user: test
140 user: test
133 date: Thu Jan 01 00:00:00 1970 +0000
141 date: Thu Jan 01 00:00:00 1970 +0000
134 summary: Removed tag gack, gorp
142 summary: Removed tag gack, gorp
135
143
136 $ hg clone -q -rbleah1 test test1
144 $ hg clone -q -rbleah1 test test1
137 $ hg -R test1 parents --style=compact
145 $ hg -R test1 parents --style=compact
138 1[tip] d4f0d2909abc 1970-01-01 00:00 +0000 test
146 1[tip] d4f0d2909abc 1970-01-01 00:00 +0000 test
139 Added tag bleah for changeset acb14030fe0a
147 Added tag bleah for changeset acb14030fe0a
140
148
141 $ hg clone -q -r5 test#bleah1 test2
149 $ hg clone -q -r5 test#bleah1 test2
142 $ hg -R test2 parents --style=compact
150 $ hg -R test2 parents --style=compact
143 5[tip] b4bb47aaff09 1970-01-01 00:00 +0000 test
151 5[tip] b4bb47aaff09 1970-01-01 00:00 +0000 test
144 Removed tag gack, gorp
152 Removed tag gack, gorp
145
153
146 $ hg clone -q -U test#bleah1 test3
154 $ hg clone -q -U test#bleah1 test3
147 $ hg -R test3 parents --style=compact
155 $ hg -R test3 parents --style=compact
148
156
149 $ cd test
157 $ cd test
150
158
151 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
159 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
152 doesn't end with EOL
160 doesn't end with EOL
153
161
154 $ python << EOF
162 $ python << EOF
155 > f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
163 > f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
156 > f = file('.hg/localtags', 'w'); f.write(last); f.close()
164 > f = file('.hg/localtags', 'w'); f.write(last); f.close()
157 > EOF
165 > EOF
158 $ cat .hg/localtags; echo
166 $ cat .hg/localtags; echo
159 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
167 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
160 $ hg tag -l localnewline
168 $ hg tag -l localnewline
161 $ cat .hg/localtags; echo
169 $ cat .hg/localtags; echo
162 d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
170 acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
163 c2899151f4e76890c602a2597a650a72666681bf localnewline
171 c2899151f4e76890c602a2597a650a72666681bf localnewline
164
172
165
173
166 $ python << EOF
174 $ python << EOF
167 > f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
175 > f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
168 > f = file('.hgtags', 'w'); f.write(last); f.close()
176 > f = file('.hgtags', 'w'); f.write(last); f.close()
169 > EOF
177 > EOF
170 $ hg ci -m'broken manual edit of .hgtags'
178 $ hg ci -m'broken manual edit of .hgtags'
171 $ cat .hgtags; echo
179 $ cat .hgtags; echo
172 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
180 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
173 $ hg tag newline
181 $ hg tag newline
174 $ cat .hgtags; echo
182 $ cat .hgtags; echo
175 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
183 acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
176 a0eea09de1eeec777b46f2085260a373b2fbc293 newline
184 a0eea09de1eeec777b46f2085260a373b2fbc293 newline
177
185
178
186
179 tag and branch using same name
187 tag and branch using same name
180
188
181 $ hg branch tag-and-branch-same-name
189 $ hg branch tag-and-branch-same-name
182 marked working directory as branch tag-and-branch-same-name
190 marked working directory as branch tag-and-branch-same-name
183 $ hg ci -m"discouraged"
191 $ hg ci -m"discouraged"
184 $ hg tag tag-and-branch-same-name
192 $ hg tag tag-and-branch-same-name
185 warning: tag tag-and-branch-same-name conflicts with existing branch name
193 warning: tag tag-and-branch-same-name conflicts with existing branch name
186
194
187 test custom commit messages
195 test custom commit messages
188
196
189 $ cat > editor << '__EOF__'
197 $ cat > editor << '__EOF__'
190 > #!/bin/sh
198 > #!/bin/sh
191 > echo "custom tag message" > "$1"
199 > echo "custom tag message" > "$1"
192 > echo "second line" >> "$1"
200 > echo "second line" >> "$1"
193 > __EOF__
201 > __EOF__
194 $ chmod +x editor
202 $ chmod +x editor
195 $ HGEDITOR="'`pwd`'"/editor hg tag custom-tag -e
203 $ HGEDITOR="'`pwd`'"/editor hg tag custom-tag -e
196 $ hg log -l1 --template "{desc}\n"
204 $ hg log -l1 --template "{desc}\n"
197 custom tag message
205 custom tag message
198 second line
206 second line
199
207
208
200 local tag with .hgtags modified
209 local tag with .hgtags modified
201
210
202 $ hg tag hgtags-modified
211 $ hg tag hgtags-modified
203 $ hg rollback
212 $ hg rollback
204 rolling back to revision 11 (undo commit)
213 rolling back to revision 11 (undo commit)
205 $ hg st
214 $ hg st
206 M .hgtags
215 M .hgtags
207 ? .hgtags.orig
216 ? .hgtags.orig
208 ? editor
217 ? editor
209 $ hg tag --local baz
218 $ hg tag --local baz
210 $ hg revert --no-backup .hgtags
219 $ hg revert --no-backup .hgtags
211
220
221
222 tagging when at named-branch-head that's not a topo-head
223
224 $ hg up default
225 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
226 $ hg merge -t internal:local
227 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
228 (branch merge, don't forget to commit)
229 $ hg ci -m 'merge named branch'
230 $ hg up 11
231 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
232 $ hg tag new-topo-head
233
234
235 tagging on null rev
236
237 $ hg up null
238 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
239 $ hg tag nullrev
240 abort: not at a branch head (use -f to force)
241 [255]
242
243 $ hg init empty
244 $ hg tag -R empty nullrev
245
212 $ cd ..
246 $ cd ..
213
247
214 tagging on an uncommitted merge (issue2542)
248 tagging on an uncommitted merge (issue2542)
215
249
216 $ hg init repo-tag-uncommitted-merge
250 $ hg init repo-tag-uncommitted-merge
217 $ cd repo-tag-uncommitted-merge
251 $ cd repo-tag-uncommitted-merge
218 $ echo c1 > f1
252 $ echo c1 > f1
219 $ hg ci -Am0
253 $ hg ci -Am0
220 adding f1
254 adding f1
221 $ hg branch b1
255 $ hg branch b1
222 marked working directory as branch b1
256 marked working directory as branch b1
223 $ echo c2 >> f1
257 $ echo c2 >> f1
224 $ hg ci -m1
258 $ hg ci -m1
225 $ hg up default
259 $ hg up default
226 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
260 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 $ hg merge b1
261 $ hg merge b1
228 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
262 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
229 (branch merge, don't forget to commit)
263 (branch merge, don't forget to commit)
230
264
231 $ hg tag t1
265 $ hg tag t1
232 abort: uncommitted merge
266 abort: uncommitted merge
233 [255]
267 [255]
234 $ hg status
268 $ hg status
235 M f1
269 M f1
236 $ hg tag --rev 1 t2
270 $ hg tag --rev 1 t2
237 abort: uncommitted merge
271 abort: uncommitted merge
238 [255]
272 [255]
239 $ hg tag --rev 1 --local t3
273 $ hg tag --rev 1 --local t3
240 $ hg tags -v
274 $ hg tags -v
241 tip 1:9466ada9ee90
275 tip 1:9466ada9ee90
242 t3 1:9466ada9ee90 local
276 t3 1:9466ada9ee90 local
243
277
244 $ cd ..
278 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now