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