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