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