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