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