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