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