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