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