##// END OF EJS Templates
dispatch: add shell aliases...
Steve Losh -
r11524:24965bb2 default
parent child Browse files
Show More
@@ -1,4463 +1,4466 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, bundlerepo, extensions, copies, error
12 import hg, util, revlog, bundlerepo, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 bad = []
49 bad = []
50 names = []
50 names = []
51 m = cmdutil.match(repo, pats, opts)
51 m = cmdutil.match(repo, pats, opts)
52 oldbad = m.bad
52 oldbad = m.bad
53 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
53 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
54
54
55 for f in repo.walk(m):
55 for f in repo.walk(m):
56 exact = m.exact(f)
56 exact = m.exact(f)
57 if exact or f not in repo.dirstate:
57 if exact or f not in repo.dirstate:
58 names.append(f)
58 names.append(f)
59 if ui.verbose or not exact:
59 if ui.verbose or not exact:
60 ui.status(_('adding %s\n') % m.rel(f))
60 ui.status(_('adding %s\n') % m.rel(f))
61 if not opts.get('dry_run'):
61 if not opts.get('dry_run'):
62 bad += [f for f in repo[None].add(names) if f in m.files()]
62 bad += [f for f in repo[None].add(names) if f in m.files()]
63 return bad and 1 or 0
63 return bad and 1 or 0
64
64
65 def addremove(ui, repo, *pats, **opts):
65 def addremove(ui, repo, *pats, **opts):
66 """add all new files, delete all missing files
66 """add all new files, delete all missing files
67
67
68 Add all new files and remove all missing files from the
68 Add all new files and remove all missing files from the
69 repository.
69 repository.
70
70
71 New files are ignored if they match any of the patterns in
71 New files are ignored if they match any of the patterns in
72 .hgignore. As with add, these changes take effect at the next
72 .hgignore. As with add, these changes take effect at the next
73 commit.
73 commit.
74
74
75 Use the -s/--similarity option to detect renamed files. With a
75 Use the -s/--similarity option to detect renamed files. With a
76 parameter greater than 0, this compares every removed file with
76 parameter greater than 0, this compares every removed file with
77 every added file and records those similar enough as renames. This
77 every added file and records those similar enough as renames. This
78 option takes a percentage between 0 (disabled) and 100 (files must
78 option takes a percentage between 0 (disabled) and 100 (files must
79 be identical) as its parameter. Detecting renamed files this way
79 be identical) as its parameter. Detecting renamed files this way
80 can be expensive.
80 can be expensive.
81
81
82 Returns 0 if all files are successfully added.
82 Returns 0 if all files are successfully added.
83 """
83 """
84 try:
84 try:
85 sim = float(opts.get('similarity') or 0)
85 sim = float(opts.get('similarity') or 0)
86 except ValueError:
86 except ValueError:
87 raise util.Abort(_('similarity must be a number'))
87 raise util.Abort(_('similarity must be a number'))
88 if sim < 0 or sim > 100:
88 if sim < 0 or sim > 100:
89 raise util.Abort(_('similarity must be between 0 and 100'))
89 raise util.Abort(_('similarity must be between 0 and 100'))
90 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
90 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
91
91
92 def annotate(ui, repo, *pats, **opts):
92 def annotate(ui, repo, *pats, **opts):
93 """show changeset information by line for each file
93 """show changeset information by line for each file
94
94
95 List changes in files, showing the revision id responsible for
95 List changes in files, showing the revision id responsible for
96 each line
96 each line
97
97
98 This command is useful for discovering when a change was made and
98 This command is useful for discovering when a change was made and
99 by whom.
99 by whom.
100
100
101 Without the -a/--text option, annotate will avoid processing files
101 Without the -a/--text option, annotate will avoid processing files
102 it detects as binary. With -a, annotate will annotate the file
102 it detects as binary. With -a, annotate will annotate the file
103 anyway, although the results will probably be neither useful
103 anyway, although the results will probably be neither useful
104 nor desirable.
104 nor desirable.
105
105
106 Returns 0 on success.
106 Returns 0 on success.
107 """
107 """
108 if opts.get('follow'):
108 if opts.get('follow'):
109 # --follow is deprecated and now just an alias for -f/--file
109 # --follow is deprecated and now just an alias for -f/--file
110 # to mimic the behavior of Mercurial before version 1.5
110 # to mimic the behavior of Mercurial before version 1.5
111 opts['file'] = 1
111 opts['file'] = 1
112
112
113 datefunc = ui.quiet and util.shortdate or util.datestr
113 datefunc = ui.quiet and util.shortdate or util.datestr
114 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
114 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
115
115
116 if not pats:
116 if not pats:
117 raise util.Abort(_('at least one filename or pattern is required'))
117 raise util.Abort(_('at least one filename or pattern is required'))
118
118
119 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
119 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
120 ('number', lambda x: str(x[0].rev())),
120 ('number', lambda x: str(x[0].rev())),
121 ('changeset', lambda x: short(x[0].node())),
121 ('changeset', lambda x: short(x[0].node())),
122 ('date', getdate),
122 ('date', getdate),
123 ('file', lambda x: x[0].path()),
123 ('file', lambda x: x[0].path()),
124 ]
124 ]
125
125
126 if (not opts.get('user') and not opts.get('changeset')
126 if (not opts.get('user') and not opts.get('changeset')
127 and not opts.get('date') and not opts.get('file')):
127 and not opts.get('date') and not opts.get('file')):
128 opts['number'] = 1
128 opts['number'] = 1
129
129
130 linenumber = opts.get('line_number') is not None
130 linenumber = opts.get('line_number') is not None
131 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
131 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
132 raise util.Abort(_('at least one of -n/-c is required for -l'))
132 raise util.Abort(_('at least one of -n/-c is required for -l'))
133
133
134 funcmap = [func for op, func in opmap if opts.get(op)]
134 funcmap = [func for op, func in opmap if opts.get(op)]
135 if linenumber:
135 if linenumber:
136 lastfunc = funcmap[-1]
136 lastfunc = funcmap[-1]
137 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
137 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
138
138
139 ctx = repo[opts.get('rev')]
139 ctx = repo[opts.get('rev')]
140 m = cmdutil.match(repo, pats, opts)
140 m = cmdutil.match(repo, pats, opts)
141 follow = not opts.get('no_follow')
141 follow = not opts.get('no_follow')
142 for abs in ctx.walk(m):
142 for abs in ctx.walk(m):
143 fctx = ctx[abs]
143 fctx = ctx[abs]
144 if not opts.get('text') and util.binary(fctx.data()):
144 if not opts.get('text') and util.binary(fctx.data()):
145 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
145 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
146 continue
146 continue
147
147
148 lines = fctx.annotate(follow=follow, linenumber=linenumber)
148 lines = fctx.annotate(follow=follow, linenumber=linenumber)
149 pieces = []
149 pieces = []
150
150
151 for f in funcmap:
151 for f in funcmap:
152 l = [f(n) for n, dummy in lines]
152 l = [f(n) for n, dummy in lines]
153 if l:
153 if l:
154 ml = max(map(len, l))
154 ml = max(map(len, l))
155 pieces.append(["%*s" % (ml, x) for x in l])
155 pieces.append(["%*s" % (ml, x) for x in l])
156
156
157 if pieces:
157 if pieces:
158 for p, l in zip(zip(*pieces), lines):
158 for p, l in zip(zip(*pieces), lines):
159 ui.write("%s: %s" % (" ".join(p), l[1]))
159 ui.write("%s: %s" % (" ".join(p), l[1]))
160
160
161 def archive(ui, repo, dest, **opts):
161 def archive(ui, repo, dest, **opts):
162 '''create an unversioned archive of a repository revision
162 '''create an unversioned archive of a repository revision
163
163
164 By default, the revision used is the parent of the working
164 By default, the revision used is the parent of the working
165 directory; use -r/--rev to specify a different revision.
165 directory; use -r/--rev to specify a different revision.
166
166
167 The archive type is automatically detected based on file
167 The archive type is automatically detected based on file
168 extension (or override using -t/--type).
168 extension (or override using -t/--type).
169
169
170 Valid types are:
170 Valid types are:
171
171
172 :``files``: a directory full of files (default)
172 :``files``: a directory full of files (default)
173 :``tar``: tar archive, uncompressed
173 :``tar``: tar archive, uncompressed
174 :``tbz2``: tar archive, compressed using bzip2
174 :``tbz2``: tar archive, compressed using bzip2
175 :``tgz``: tar archive, compressed using gzip
175 :``tgz``: tar archive, compressed using gzip
176 :``uzip``: zip archive, uncompressed
176 :``uzip``: zip archive, uncompressed
177 :``zip``: zip archive, compressed using deflate
177 :``zip``: zip archive, compressed using deflate
178
178
179 The exact name of the destination archive or directory is given
179 The exact name of the destination archive or directory is given
180 using a format string; see :hg:`help export` for details.
180 using a format string; see :hg:`help export` for details.
181
181
182 Each member added to an archive file has a directory prefix
182 Each member added to an archive file has a directory prefix
183 prepended. Use -p/--prefix to specify a format string for the
183 prepended. Use -p/--prefix to specify a format string for the
184 prefix. The default is the basename of the archive, with suffixes
184 prefix. The default is the basename of the archive, with suffixes
185 removed.
185 removed.
186
186
187 Returns 0 on success.
187 Returns 0 on success.
188 '''
188 '''
189
189
190 ctx = repo[opts.get('rev')]
190 ctx = repo[opts.get('rev')]
191 if not ctx:
191 if not ctx:
192 raise util.Abort(_('no working directory: please specify a revision'))
192 raise util.Abort(_('no working directory: please specify a revision'))
193 node = ctx.node()
193 node = ctx.node()
194 dest = cmdutil.make_filename(repo, dest, node)
194 dest = cmdutil.make_filename(repo, dest, node)
195 if os.path.realpath(dest) == repo.root:
195 if os.path.realpath(dest) == repo.root:
196 raise util.Abort(_('repository root cannot be destination'))
196 raise util.Abort(_('repository root cannot be destination'))
197
197
198 def guess_type():
198 def guess_type():
199 exttypes = {
199 exttypes = {
200 'tar': ['.tar'],
200 'tar': ['.tar'],
201 'tbz2': ['.tbz2', '.tar.bz2'],
201 'tbz2': ['.tbz2', '.tar.bz2'],
202 'tgz': ['.tgz', '.tar.gz'],
202 'tgz': ['.tgz', '.tar.gz'],
203 'zip': ['.zip'],
203 'zip': ['.zip'],
204 }
204 }
205
205
206 for type, extensions in exttypes.items():
206 for type, extensions in exttypes.items():
207 if util.any(dest.endswith(ext) for ext in extensions):
207 if util.any(dest.endswith(ext) for ext in extensions):
208 return type
208 return type
209 return None
209 return None
210
210
211 kind = opts.get('type') or guess_type() or 'files'
211 kind = opts.get('type') or guess_type() or 'files'
212 prefix = opts.get('prefix')
212 prefix = opts.get('prefix')
213
213
214 if dest == '-':
214 if dest == '-':
215 if kind == 'files':
215 if kind == 'files':
216 raise util.Abort(_('cannot archive plain files to stdout'))
216 raise util.Abort(_('cannot archive plain files to stdout'))
217 dest = sys.stdout
217 dest = sys.stdout
218 if not prefix:
218 if not prefix:
219 prefix = os.path.basename(repo.root) + '-%h'
219 prefix = os.path.basename(repo.root) + '-%h'
220
220
221 prefix = cmdutil.make_filename(repo, prefix, node)
221 prefix = cmdutil.make_filename(repo, prefix, node)
222 matchfn = cmdutil.match(repo, [], opts)
222 matchfn = cmdutil.match(repo, [], opts)
223 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
223 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
224 matchfn, prefix)
224 matchfn, prefix)
225
225
226 def backout(ui, repo, node=None, rev=None, **opts):
226 def backout(ui, repo, node=None, rev=None, **opts):
227 '''reverse effect of earlier changeset
227 '''reverse effect of earlier changeset
228
228
229 Commit the backed out changes as a new changeset. The new
229 Commit the backed out changes as a new changeset. The new
230 changeset is a child of the backed out changeset.
230 changeset is a child of the backed out changeset.
231
231
232 If you backout a changeset other than the tip, a new head is
232 If you backout a changeset other than the tip, a new head is
233 created. This head will be the new tip and you should merge this
233 created. This head will be the new tip and you should merge this
234 backout changeset with another head.
234 backout changeset with another head.
235
235
236 The --merge option remembers the parent of the working directory
236 The --merge option remembers the parent of the working directory
237 before starting the backout, then merges the new head with that
237 before starting the backout, then merges the new head with that
238 changeset afterwards. This saves you from doing the merge by hand.
238 changeset afterwards. This saves you from doing the merge by hand.
239 The result of this merge is not committed, as with a normal merge.
239 The result of this merge is not committed, as with a normal merge.
240
240
241 See :hg:`help dates` for a list of formats valid for -d/--date.
241 See :hg:`help dates` for a list of formats valid for -d/--date.
242
242
243 Returns 0 on success.
243 Returns 0 on success.
244 '''
244 '''
245 if rev and node:
245 if rev and node:
246 raise util.Abort(_("please specify just one revision"))
246 raise util.Abort(_("please specify just one revision"))
247
247
248 if not rev:
248 if not rev:
249 rev = node
249 rev = node
250
250
251 if not rev:
251 if not rev:
252 raise util.Abort(_("please specify a revision to backout"))
252 raise util.Abort(_("please specify a revision to backout"))
253
253
254 date = opts.get('date')
254 date = opts.get('date')
255 if date:
255 if date:
256 opts['date'] = util.parsedate(date)
256 opts['date'] = util.parsedate(date)
257
257
258 cmdutil.bail_if_changed(repo)
258 cmdutil.bail_if_changed(repo)
259 node = repo.lookup(rev)
259 node = repo.lookup(rev)
260
260
261 op1, op2 = repo.dirstate.parents()
261 op1, op2 = repo.dirstate.parents()
262 a = repo.changelog.ancestor(op1, node)
262 a = repo.changelog.ancestor(op1, node)
263 if a != node:
263 if a != node:
264 raise util.Abort(_('cannot backout change on a different branch'))
264 raise util.Abort(_('cannot backout change on a different branch'))
265
265
266 p1, p2 = repo.changelog.parents(node)
266 p1, p2 = repo.changelog.parents(node)
267 if p1 == nullid:
267 if p1 == nullid:
268 raise util.Abort(_('cannot backout a change with no parents'))
268 raise util.Abort(_('cannot backout a change with no parents'))
269 if p2 != nullid:
269 if p2 != nullid:
270 if not opts.get('parent'):
270 if not opts.get('parent'):
271 raise util.Abort(_('cannot backout a merge changeset without '
271 raise util.Abort(_('cannot backout a merge changeset without '
272 '--parent'))
272 '--parent'))
273 p = repo.lookup(opts['parent'])
273 p = repo.lookup(opts['parent'])
274 if p not in (p1, p2):
274 if p not in (p1, p2):
275 raise util.Abort(_('%s is not a parent of %s') %
275 raise util.Abort(_('%s is not a parent of %s') %
276 (short(p), short(node)))
276 (short(p), short(node)))
277 parent = p
277 parent = p
278 else:
278 else:
279 if opts.get('parent'):
279 if opts.get('parent'):
280 raise util.Abort(_('cannot use --parent on non-merge changeset'))
280 raise util.Abort(_('cannot use --parent on non-merge changeset'))
281 parent = p1
281 parent = p1
282
282
283 # the backout should appear on the same branch
283 # the backout should appear on the same branch
284 branch = repo.dirstate.branch()
284 branch = repo.dirstate.branch()
285 hg.clean(repo, node, show_stats=False)
285 hg.clean(repo, node, show_stats=False)
286 repo.dirstate.setbranch(branch)
286 repo.dirstate.setbranch(branch)
287 revert_opts = opts.copy()
287 revert_opts = opts.copy()
288 revert_opts['date'] = None
288 revert_opts['date'] = None
289 revert_opts['all'] = True
289 revert_opts['all'] = True
290 revert_opts['rev'] = hex(parent)
290 revert_opts['rev'] = hex(parent)
291 revert_opts['no_backup'] = None
291 revert_opts['no_backup'] = None
292 revert(ui, repo, **revert_opts)
292 revert(ui, repo, **revert_opts)
293 commit_opts = opts.copy()
293 commit_opts = opts.copy()
294 commit_opts['addremove'] = False
294 commit_opts['addremove'] = False
295 if not commit_opts['message'] and not commit_opts['logfile']:
295 if not commit_opts['message'] and not commit_opts['logfile']:
296 # we don't translate commit messages
296 # we don't translate commit messages
297 commit_opts['message'] = "Backed out changeset %s" % short(node)
297 commit_opts['message'] = "Backed out changeset %s" % short(node)
298 commit_opts['force_editor'] = True
298 commit_opts['force_editor'] = True
299 commit(ui, repo, **commit_opts)
299 commit(ui, repo, **commit_opts)
300 def nice(node):
300 def nice(node):
301 return '%d:%s' % (repo.changelog.rev(node), short(node))
301 return '%d:%s' % (repo.changelog.rev(node), short(node))
302 ui.status(_('changeset %s backs out changeset %s\n') %
302 ui.status(_('changeset %s backs out changeset %s\n') %
303 (nice(repo.changelog.tip()), nice(node)))
303 (nice(repo.changelog.tip()), nice(node)))
304 if op1 != node:
304 if op1 != node:
305 hg.clean(repo, op1, show_stats=False)
305 hg.clean(repo, op1, show_stats=False)
306 if opts.get('merge'):
306 if opts.get('merge'):
307 ui.status(_('merging with changeset %s\n')
307 ui.status(_('merging with changeset %s\n')
308 % nice(repo.changelog.tip()))
308 % nice(repo.changelog.tip()))
309 hg.merge(repo, hex(repo.changelog.tip()))
309 hg.merge(repo, hex(repo.changelog.tip()))
310 else:
310 else:
311 ui.status(_('the backout changeset is a new head - '
311 ui.status(_('the backout changeset is a new head - '
312 'do not forget to merge\n'))
312 'do not forget to merge\n'))
313 ui.status(_('(use "backout --merge" '
313 ui.status(_('(use "backout --merge" '
314 'if you want to auto-merge)\n'))
314 'if you want to auto-merge)\n'))
315
315
316 def bisect(ui, repo, rev=None, extra=None, command=None,
316 def bisect(ui, repo, rev=None, extra=None, command=None,
317 reset=None, good=None, bad=None, skip=None, noupdate=None):
317 reset=None, good=None, bad=None, skip=None, noupdate=None):
318 """subdivision search of changesets
318 """subdivision search of changesets
319
319
320 This command helps to find changesets which introduce problems. To
320 This command helps to find changesets which introduce problems. To
321 use, mark the earliest changeset you know exhibits the problem as
321 use, mark the earliest changeset you know exhibits the problem as
322 bad, then mark the latest changeset which is free from the problem
322 bad, then mark the latest changeset which is free from the problem
323 as good. Bisect will update your working directory to a revision
323 as good. Bisect will update your working directory to a revision
324 for testing (unless the -U/--noupdate option is specified). Once
324 for testing (unless the -U/--noupdate option is specified). Once
325 you have performed tests, mark the working directory as good or
325 you have performed tests, mark the working directory as good or
326 bad, and bisect will either update to another candidate changeset
326 bad, and bisect will either update to another candidate changeset
327 or announce that it has found the bad revision.
327 or announce that it has found the bad revision.
328
328
329 As a shortcut, you can also use the revision argument to mark a
329 As a shortcut, you can also use the revision argument to mark a
330 revision as good or bad without checking it out first.
330 revision as good or bad without checking it out first.
331
331
332 If you supply a command, it will be used for automatic bisection.
332 If you supply a command, it will be used for automatic bisection.
333 Its exit status will be used to mark revisions as good or bad:
333 Its exit status will be used to mark revisions as good or bad:
334 status 0 means good, 125 means to skip the revision, 127
334 status 0 means good, 125 means to skip the revision, 127
335 (command not found) will abort the bisection, and any other
335 (command not found) will abort the bisection, and any other
336 non-zero exit status means the revision is bad.
336 non-zero exit status means the revision is bad.
337
337
338 Returns 0 on success.
338 Returns 0 on success.
339 """
339 """
340 def print_result(nodes, good):
340 def print_result(nodes, good):
341 displayer = cmdutil.show_changeset(ui, repo, {})
341 displayer = cmdutil.show_changeset(ui, repo, {})
342 if len(nodes) == 1:
342 if len(nodes) == 1:
343 # narrowed it down to a single revision
343 # narrowed it down to a single revision
344 if good:
344 if good:
345 ui.write(_("The first good revision is:\n"))
345 ui.write(_("The first good revision is:\n"))
346 else:
346 else:
347 ui.write(_("The first bad revision is:\n"))
347 ui.write(_("The first bad revision is:\n"))
348 displayer.show(repo[nodes[0]])
348 displayer.show(repo[nodes[0]])
349 else:
349 else:
350 # multiple possible revisions
350 # multiple possible revisions
351 if good:
351 if good:
352 ui.write(_("Due to skipped revisions, the first "
352 ui.write(_("Due to skipped revisions, the first "
353 "good revision could be any of:\n"))
353 "good revision could be any of:\n"))
354 else:
354 else:
355 ui.write(_("Due to skipped revisions, the first "
355 ui.write(_("Due to skipped revisions, the first "
356 "bad revision could be any of:\n"))
356 "bad revision could be any of:\n"))
357 for n in nodes:
357 for n in nodes:
358 displayer.show(repo[n])
358 displayer.show(repo[n])
359 displayer.close()
359 displayer.close()
360
360
361 def check_state(state, interactive=True):
361 def check_state(state, interactive=True):
362 if not state['good'] or not state['bad']:
362 if not state['good'] or not state['bad']:
363 if (good or bad or skip or reset) and interactive:
363 if (good or bad or skip or reset) and interactive:
364 return
364 return
365 if not state['good']:
365 if not state['good']:
366 raise util.Abort(_('cannot bisect (no known good revisions)'))
366 raise util.Abort(_('cannot bisect (no known good revisions)'))
367 else:
367 else:
368 raise util.Abort(_('cannot bisect (no known bad revisions)'))
368 raise util.Abort(_('cannot bisect (no known bad revisions)'))
369 return True
369 return True
370
370
371 # backward compatibility
371 # backward compatibility
372 if rev in "good bad reset init".split():
372 if rev in "good bad reset init".split():
373 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
373 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
374 cmd, rev, extra = rev, extra, None
374 cmd, rev, extra = rev, extra, None
375 if cmd == "good":
375 if cmd == "good":
376 good = True
376 good = True
377 elif cmd == "bad":
377 elif cmd == "bad":
378 bad = True
378 bad = True
379 else:
379 else:
380 reset = True
380 reset = True
381 elif extra or good + bad + skip + reset + bool(command) > 1:
381 elif extra or good + bad + skip + reset + bool(command) > 1:
382 raise util.Abort(_('incompatible arguments'))
382 raise util.Abort(_('incompatible arguments'))
383
383
384 if reset:
384 if reset:
385 p = repo.join("bisect.state")
385 p = repo.join("bisect.state")
386 if os.path.exists(p):
386 if os.path.exists(p):
387 os.unlink(p)
387 os.unlink(p)
388 return
388 return
389
389
390 state = hbisect.load_state(repo)
390 state = hbisect.load_state(repo)
391
391
392 if command:
392 if command:
393 changesets = 1
393 changesets = 1
394 try:
394 try:
395 while changesets:
395 while changesets:
396 # update state
396 # update state
397 status = util.system(command)
397 status = util.system(command)
398 if status == 125:
398 if status == 125:
399 transition = "skip"
399 transition = "skip"
400 elif status == 0:
400 elif status == 0:
401 transition = "good"
401 transition = "good"
402 # status < 0 means process was killed
402 # status < 0 means process was killed
403 elif status == 127:
403 elif status == 127:
404 raise util.Abort(_("failed to execute %s") % command)
404 raise util.Abort(_("failed to execute %s") % command)
405 elif status < 0:
405 elif status < 0:
406 raise util.Abort(_("%s killed") % command)
406 raise util.Abort(_("%s killed") % command)
407 else:
407 else:
408 transition = "bad"
408 transition = "bad"
409 ctx = repo[rev or '.']
409 ctx = repo[rev or '.']
410 state[transition].append(ctx.node())
410 state[transition].append(ctx.node())
411 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
411 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
412 check_state(state, interactive=False)
412 check_state(state, interactive=False)
413 # bisect
413 # bisect
414 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
414 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
415 # update to next check
415 # update to next check
416 cmdutil.bail_if_changed(repo)
416 cmdutil.bail_if_changed(repo)
417 hg.clean(repo, nodes[0], show_stats=False)
417 hg.clean(repo, nodes[0], show_stats=False)
418 finally:
418 finally:
419 hbisect.save_state(repo, state)
419 hbisect.save_state(repo, state)
420 print_result(nodes, good)
420 print_result(nodes, good)
421 return
421 return
422
422
423 # update state
423 # update state
424 node = repo.lookup(rev or '.')
424 node = repo.lookup(rev or '.')
425 if good or bad or skip:
425 if good or bad or skip:
426 if good:
426 if good:
427 state['good'].append(node)
427 state['good'].append(node)
428 elif bad:
428 elif bad:
429 state['bad'].append(node)
429 state['bad'].append(node)
430 elif skip:
430 elif skip:
431 state['skip'].append(node)
431 state['skip'].append(node)
432 hbisect.save_state(repo, state)
432 hbisect.save_state(repo, state)
433
433
434 if not check_state(state):
434 if not check_state(state):
435 return
435 return
436
436
437 # actually bisect
437 # actually bisect
438 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
438 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
439 if changesets == 0:
439 if changesets == 0:
440 print_result(nodes, good)
440 print_result(nodes, good)
441 else:
441 else:
442 assert len(nodes) == 1 # only a single node can be tested next
442 assert len(nodes) == 1 # only a single node can be tested next
443 node = nodes[0]
443 node = nodes[0]
444 # compute the approximate number of remaining tests
444 # compute the approximate number of remaining tests
445 tests, size = 0, 2
445 tests, size = 0, 2
446 while size <= changesets:
446 while size <= changesets:
447 tests, size = tests + 1, size * 2
447 tests, size = tests + 1, size * 2
448 rev = repo.changelog.rev(node)
448 rev = repo.changelog.rev(node)
449 ui.write(_("Testing changeset %d:%s "
449 ui.write(_("Testing changeset %d:%s "
450 "(%d changesets remaining, ~%d tests)\n")
450 "(%d changesets remaining, ~%d tests)\n")
451 % (rev, short(node), changesets, tests))
451 % (rev, short(node), changesets, tests))
452 if not noupdate:
452 if not noupdate:
453 cmdutil.bail_if_changed(repo)
453 cmdutil.bail_if_changed(repo)
454 return hg.clean(repo, node)
454 return hg.clean(repo, node)
455
455
456 def branch(ui, repo, label=None, **opts):
456 def branch(ui, repo, label=None, **opts):
457 """set or show the current branch name
457 """set or show the current branch name
458
458
459 With no argument, show the current branch name. With one argument,
459 With no argument, show the current branch name. With one argument,
460 set the working directory branch name (the branch will not exist
460 set the working directory branch name (the branch will not exist
461 in the repository until the next commit). Standard practice
461 in the repository until the next commit). Standard practice
462 recommends that primary development take place on the 'default'
462 recommends that primary development take place on the 'default'
463 branch.
463 branch.
464
464
465 Unless -f/--force is specified, branch will not let you set a
465 Unless -f/--force is specified, branch will not let you set a
466 branch name that already exists, even if it's inactive.
466 branch name that already exists, even if it's inactive.
467
467
468 Use -C/--clean to reset the working directory branch to that of
468 Use -C/--clean to reset the working directory branch to that of
469 the parent of the working directory, negating a previous branch
469 the parent of the working directory, negating a previous branch
470 change.
470 change.
471
471
472 Use the command :hg:`update` to switch to an existing branch. Use
472 Use the command :hg:`update` to switch to an existing branch. Use
473 :hg:`commit --close-branch` to mark this branch as closed.
473 :hg:`commit --close-branch` to mark this branch as closed.
474
474
475 Returns 0 on success.
475 Returns 0 on success.
476 """
476 """
477
477
478 if opts.get('clean'):
478 if opts.get('clean'):
479 label = repo[None].parents()[0].branch()
479 label = repo[None].parents()[0].branch()
480 repo.dirstate.setbranch(label)
480 repo.dirstate.setbranch(label)
481 ui.status(_('reset working directory to branch %s\n') % label)
481 ui.status(_('reset working directory to branch %s\n') % label)
482 elif label:
482 elif label:
483 utflabel = encoding.fromlocal(label)
483 utflabel = encoding.fromlocal(label)
484 if not opts.get('force') and utflabel in repo.branchtags():
484 if not opts.get('force') and utflabel in repo.branchtags():
485 if label not in [p.branch() for p in repo.parents()]:
485 if label not in [p.branch() for p in repo.parents()]:
486 raise util.Abort(_('a branch of the same name already exists'
486 raise util.Abort(_('a branch of the same name already exists'
487 " (use 'hg update' to switch to it)"))
487 " (use 'hg update' to switch to it)"))
488 repo.dirstate.setbranch(utflabel)
488 repo.dirstate.setbranch(utflabel)
489 ui.status(_('marked working directory as branch %s\n') % label)
489 ui.status(_('marked working directory as branch %s\n') % label)
490 else:
490 else:
491 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
491 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
492
492
493 def branches(ui, repo, active=False, closed=False):
493 def branches(ui, repo, active=False, closed=False):
494 """list repository named branches
494 """list repository named branches
495
495
496 List the repository's named branches, indicating which ones are
496 List the repository's named branches, indicating which ones are
497 inactive. If -c/--closed is specified, also list branches which have
497 inactive. If -c/--closed is specified, also list branches which have
498 been marked closed (see :hg:`commit --close-branch`).
498 been marked closed (see :hg:`commit --close-branch`).
499
499
500 If -a/--active is specified, only show active branches. A branch
500 If -a/--active is specified, only show active branches. A branch
501 is considered active if it contains repository heads.
501 is considered active if it contains repository heads.
502
502
503 Use the command :hg:`update` to switch to an existing branch.
503 Use the command :hg:`update` to switch to an existing branch.
504
504
505 Returns 0.
505 Returns 0.
506 """
506 """
507
507
508 hexfunc = ui.debugflag and hex or short
508 hexfunc = ui.debugflag and hex or short
509 activebranches = [repo[n].branch() for n in repo.heads()]
509 activebranches = [repo[n].branch() for n in repo.heads()]
510 def testactive(tag, node):
510 def testactive(tag, node):
511 realhead = tag in activebranches
511 realhead = tag in activebranches
512 open = node in repo.branchheads(tag, closed=False)
512 open = node in repo.branchheads(tag, closed=False)
513 return realhead and open
513 return realhead and open
514 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
514 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
515 for tag, node in repo.branchtags().items()],
515 for tag, node in repo.branchtags().items()],
516 reverse=True)
516 reverse=True)
517
517
518 for isactive, node, tag in branches:
518 for isactive, node, tag in branches:
519 if (not active) or isactive:
519 if (not active) or isactive:
520 encodedtag = encoding.tolocal(tag)
520 encodedtag = encoding.tolocal(tag)
521 if ui.quiet:
521 if ui.quiet:
522 ui.write("%s\n" % encodedtag)
522 ui.write("%s\n" % encodedtag)
523 else:
523 else:
524 hn = repo.lookup(node)
524 hn = repo.lookup(node)
525 if isactive:
525 if isactive:
526 notice = ''
526 notice = ''
527 elif hn not in repo.branchheads(tag, closed=False):
527 elif hn not in repo.branchheads(tag, closed=False):
528 if not closed:
528 if not closed:
529 continue
529 continue
530 notice = _(' (closed)')
530 notice = _(' (closed)')
531 else:
531 else:
532 notice = _(' (inactive)')
532 notice = _(' (inactive)')
533 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
533 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
534 data = encodedtag, rev, hexfunc(hn), notice
534 data = encodedtag, rev, hexfunc(hn), notice
535 ui.write("%s %s:%s%s\n" % data)
535 ui.write("%s %s:%s%s\n" % data)
536
536
537 def bundle(ui, repo, fname, dest=None, **opts):
537 def bundle(ui, repo, fname, dest=None, **opts):
538 """create a changegroup file
538 """create a changegroup file
539
539
540 Generate a compressed changegroup file collecting changesets not
540 Generate a compressed changegroup file collecting changesets not
541 known to be in another repository.
541 known to be in another repository.
542
542
543 If you omit the destination repository, then hg assumes the
543 If you omit the destination repository, then hg assumes the
544 destination will have all the nodes you specify with --base
544 destination will have all the nodes you specify with --base
545 parameters. To create a bundle containing all changesets, use
545 parameters. To create a bundle containing all changesets, use
546 -a/--all (or --base null).
546 -a/--all (or --base null).
547
547
548 You can change compression method with the -t/--type option.
548 You can change compression method with the -t/--type option.
549 The available compression methods are: none, bzip2, and
549 The available compression methods are: none, bzip2, and
550 gzip (by default, bundles are compressed using bzip2).
550 gzip (by default, bundles are compressed using bzip2).
551
551
552 The bundle file can then be transferred using conventional means
552 The bundle file can then be transferred using conventional means
553 and applied to another repository with the unbundle or pull
553 and applied to another repository with the unbundle or pull
554 command. This is useful when direct push and pull are not
554 command. This is useful when direct push and pull are not
555 available or when exporting an entire repository is undesirable.
555 available or when exporting an entire repository is undesirable.
556
556
557 Applying bundles preserves all changeset contents including
557 Applying bundles preserves all changeset contents including
558 permissions, copy/rename information, and revision history.
558 permissions, copy/rename information, and revision history.
559
559
560 Returns 0 on success, 1 if no changes found.
560 Returns 0 on success, 1 if no changes found.
561 """
561 """
562 revs = opts.get('rev') or None
562 revs = opts.get('rev') or None
563 if revs:
563 if revs:
564 revs = [repo.lookup(rev) for rev in revs]
564 revs = [repo.lookup(rev) for rev in revs]
565 if opts.get('all'):
565 if opts.get('all'):
566 base = ['null']
566 base = ['null']
567 else:
567 else:
568 base = opts.get('base')
568 base = opts.get('base')
569 if base:
569 if base:
570 if dest:
570 if dest:
571 raise util.Abort(_("--base is incompatible with specifying "
571 raise util.Abort(_("--base is incompatible with specifying "
572 "a destination"))
572 "a destination"))
573 base = [repo.lookup(rev) for rev in base]
573 base = [repo.lookup(rev) for rev in base]
574 # create the right base
574 # create the right base
575 # XXX: nodesbetween / changegroup* should be "fixed" instead
575 # XXX: nodesbetween / changegroup* should be "fixed" instead
576 o = []
576 o = []
577 has = set((nullid,))
577 has = set((nullid,))
578 for n in base:
578 for n in base:
579 has.update(repo.changelog.reachable(n))
579 has.update(repo.changelog.reachable(n))
580 if revs:
580 if revs:
581 visit = list(revs)
581 visit = list(revs)
582 has.difference_update(revs)
582 has.difference_update(revs)
583 else:
583 else:
584 visit = repo.changelog.heads()
584 visit = repo.changelog.heads()
585 seen = {}
585 seen = {}
586 while visit:
586 while visit:
587 n = visit.pop(0)
587 n = visit.pop(0)
588 parents = [p for p in repo.changelog.parents(n) if p not in has]
588 parents = [p for p in repo.changelog.parents(n) if p not in has]
589 if len(parents) == 0:
589 if len(parents) == 0:
590 if n not in has:
590 if n not in has:
591 o.append(n)
591 o.append(n)
592 else:
592 else:
593 for p in parents:
593 for p in parents:
594 if p not in seen:
594 if p not in seen:
595 seen[p] = 1
595 seen[p] = 1
596 visit.append(p)
596 visit.append(p)
597 else:
597 else:
598 dest = ui.expandpath(dest or 'default-push', dest or 'default')
598 dest = ui.expandpath(dest or 'default-push', dest or 'default')
599 dest, branches = hg.parseurl(dest, opts.get('branch'))
599 dest, branches = hg.parseurl(dest, opts.get('branch'))
600 other = hg.repository(hg.remoteui(repo, opts), dest)
600 other = hg.repository(hg.remoteui(repo, opts), dest)
601 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
601 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
602 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
602 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
603
603
604 if not o:
604 if not o:
605 ui.status(_("no changes found\n"))
605 ui.status(_("no changes found\n"))
606 return 1
606 return 1
607
607
608 if revs:
608 if revs:
609 cg = repo.changegroupsubset(o, revs, 'bundle')
609 cg = repo.changegroupsubset(o, revs, 'bundle')
610 else:
610 else:
611 cg = repo.changegroup(o, 'bundle')
611 cg = repo.changegroup(o, 'bundle')
612
612
613 bundletype = opts.get('type', 'bzip2').lower()
613 bundletype = opts.get('type', 'bzip2').lower()
614 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
614 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
615 bundletype = btypes.get(bundletype)
615 bundletype = btypes.get(bundletype)
616 if bundletype not in changegroup.bundletypes:
616 if bundletype not in changegroup.bundletypes:
617 raise util.Abort(_('unknown bundle type specified with --type'))
617 raise util.Abort(_('unknown bundle type specified with --type'))
618
618
619 changegroup.writebundle(cg, fname, bundletype)
619 changegroup.writebundle(cg, fname, bundletype)
620
620
621 def cat(ui, repo, file1, *pats, **opts):
621 def cat(ui, repo, file1, *pats, **opts):
622 """output the current or given revision of files
622 """output the current or given revision of files
623
623
624 Print the specified files as they were at the given revision. If
624 Print the specified files as they were at the given revision. If
625 no revision is given, the parent of the working directory is used,
625 no revision is given, the parent of the working directory is used,
626 or tip if no revision is checked out.
626 or tip if no revision is checked out.
627
627
628 Output may be to a file, in which case the name of the file is
628 Output may be to a file, in which case the name of the file is
629 given using a format string. The formatting rules are the same as
629 given using a format string. The formatting rules are the same as
630 for the export command, with the following additions:
630 for the export command, with the following additions:
631
631
632 :``%s``: basename of file being printed
632 :``%s``: basename of file being printed
633 :``%d``: dirname of file being printed, or '.' if in repository root
633 :``%d``: dirname of file being printed, or '.' if in repository root
634 :``%p``: root-relative path name of file being printed
634 :``%p``: root-relative path name of file being printed
635
635
636 Returns 0 on success.
636 Returns 0 on success.
637 """
637 """
638 ctx = repo[opts.get('rev')]
638 ctx = repo[opts.get('rev')]
639 err = 1
639 err = 1
640 m = cmdutil.match(repo, (file1,) + pats, opts)
640 m = cmdutil.match(repo, (file1,) + pats, opts)
641 for abs in ctx.walk(m):
641 for abs in ctx.walk(m):
642 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
642 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
643 data = ctx[abs].data()
643 data = ctx[abs].data()
644 if opts.get('decode'):
644 if opts.get('decode'):
645 data = repo.wwritedata(abs, data)
645 data = repo.wwritedata(abs, data)
646 fp.write(data)
646 fp.write(data)
647 err = 0
647 err = 0
648 return err
648 return err
649
649
650 def clone(ui, source, dest=None, **opts):
650 def clone(ui, source, dest=None, **opts):
651 """make a copy of an existing repository
651 """make a copy of an existing repository
652
652
653 Create a copy of an existing repository in a new directory.
653 Create a copy of an existing repository in a new directory.
654
654
655 If no destination directory name is specified, it defaults to the
655 If no destination directory name is specified, it defaults to the
656 basename of the source.
656 basename of the source.
657
657
658 The location of the source is added to the new repository's
658 The location of the source is added to the new repository's
659 .hg/hgrc file, as the default to be used for future pulls.
659 .hg/hgrc file, as the default to be used for future pulls.
660
660
661 See :hg:`help urls` for valid source format details.
661 See :hg:`help urls` for valid source format details.
662
662
663 It is possible to specify an ``ssh://`` URL as the destination, but no
663 It is possible to specify an ``ssh://`` URL as the destination, but no
664 .hg/hgrc and working directory will be created on the remote side.
664 .hg/hgrc and working directory will be created on the remote side.
665 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
665 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
666
666
667 A set of changesets (tags, or branch names) to pull may be specified
667 A set of changesets (tags, or branch names) to pull may be specified
668 by listing each changeset (tag, or branch name) with -r/--rev.
668 by listing each changeset (tag, or branch name) with -r/--rev.
669 If -r/--rev is used, the cloned repository will contain only a subset
669 If -r/--rev is used, the cloned repository will contain only a subset
670 of the changesets of the source repository. Only the set of changesets
670 of the changesets of the source repository. Only the set of changesets
671 defined by all -r/--rev options (including all their ancestors)
671 defined by all -r/--rev options (including all their ancestors)
672 will be pulled into the destination repository.
672 will be pulled into the destination repository.
673 No subsequent changesets (including subsequent tags) will be present
673 No subsequent changesets (including subsequent tags) will be present
674 in the destination.
674 in the destination.
675
675
676 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
676 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
677 local source repositories.
677 local source repositories.
678
678
679 For efficiency, hardlinks are used for cloning whenever the source
679 For efficiency, hardlinks are used for cloning whenever the source
680 and destination are on the same filesystem (note this applies only
680 and destination are on the same filesystem (note this applies only
681 to the repository data, not to the working directory). Some
681 to the repository data, not to the working directory). Some
682 filesystems, such as AFS, implement hardlinking incorrectly, but
682 filesystems, such as AFS, implement hardlinking incorrectly, but
683 do not report errors. In these cases, use the --pull option to
683 do not report errors. In these cases, use the --pull option to
684 avoid hardlinking.
684 avoid hardlinking.
685
685
686 In some cases, you can clone repositories and the working directory
686 In some cases, you can clone repositories and the working directory
687 using full hardlinks with ::
687 using full hardlinks with ::
688
688
689 $ cp -al REPO REPOCLONE
689 $ cp -al REPO REPOCLONE
690
690
691 This is the fastest way to clone, but it is not always safe. The
691 This is the fastest way to clone, but it is not always safe. The
692 operation is not atomic (making sure REPO is not modified during
692 operation is not atomic (making sure REPO is not modified during
693 the operation is up to you) and you have to make sure your editor
693 the operation is up to you) and you have to make sure your editor
694 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
694 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
695 this is not compatible with certain extensions that place their
695 this is not compatible with certain extensions that place their
696 metadata under the .hg directory, such as mq.
696 metadata under the .hg directory, such as mq.
697
697
698 Mercurial will update the working directory to the first applicable
698 Mercurial will update the working directory to the first applicable
699 revision from this list:
699 revision from this list:
700
700
701 a) null if -U or the source repository has no changesets
701 a) null if -U or the source repository has no changesets
702 b) if -u . and the source repository is local, the first parent of
702 b) if -u . and the source repository is local, the first parent of
703 the source repository's working directory
703 the source repository's working directory
704 c) the changeset specified with -u (if a branch name, this means the
704 c) the changeset specified with -u (if a branch name, this means the
705 latest head of that branch)
705 latest head of that branch)
706 d) the changeset specified with -r
706 d) the changeset specified with -r
707 e) the tipmost head specified with -b
707 e) the tipmost head specified with -b
708 f) the tipmost head specified with the url#branch source syntax
708 f) the tipmost head specified with the url#branch source syntax
709 g) the tipmost head of the default branch
709 g) the tipmost head of the default branch
710 h) tip
710 h) tip
711
711
712 Returns 0 on success.
712 Returns 0 on success.
713 """
713 """
714 if opts.get('noupdate') and opts.get('updaterev'):
714 if opts.get('noupdate') and opts.get('updaterev'):
715 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
715 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
716
716
717 r = hg.clone(hg.remoteui(ui, opts), source, dest,
717 r = hg.clone(hg.remoteui(ui, opts), source, dest,
718 pull=opts.get('pull'),
718 pull=opts.get('pull'),
719 stream=opts.get('uncompressed'),
719 stream=opts.get('uncompressed'),
720 rev=opts.get('rev'),
720 rev=opts.get('rev'),
721 update=opts.get('updaterev') or not opts.get('noupdate'),
721 update=opts.get('updaterev') or not opts.get('noupdate'),
722 branch=opts.get('branch'))
722 branch=opts.get('branch'))
723
723
724 return r is None
724 return r is None
725
725
726 def commit(ui, repo, *pats, **opts):
726 def commit(ui, repo, *pats, **opts):
727 """commit the specified files or all outstanding changes
727 """commit the specified files or all outstanding changes
728
728
729 Commit changes to the given files into the repository. Unlike a
729 Commit changes to the given files into the repository. Unlike a
730 centralized RCS, this operation is a local operation. See
730 centralized RCS, this operation is a local operation. See
731 :hg:`push` for a way to actively distribute your changes.
731 :hg:`push` for a way to actively distribute your changes.
732
732
733 If a list of files is omitted, all changes reported by :hg:`status`
733 If a list of files is omitted, all changes reported by :hg:`status`
734 will be committed.
734 will be committed.
735
735
736 If you are committing the result of a merge, do not provide any
736 If you are committing the result of a merge, do not provide any
737 filenames or -I/-X filters.
737 filenames or -I/-X filters.
738
738
739 If no commit message is specified, the configured editor is
739 If no commit message is specified, the configured editor is
740 started to prompt you for a message.
740 started to prompt you for a message.
741
741
742 See :hg:`help dates` for a list of formats valid for -d/--date.
742 See :hg:`help dates` for a list of formats valid for -d/--date.
743
743
744 Returns 0 on success, 1 if nothing changed.
744 Returns 0 on success, 1 if nothing changed.
745 """
745 """
746 extra = {}
746 extra = {}
747 if opts.get('close_branch'):
747 if opts.get('close_branch'):
748 if repo['.'].node() not in repo.branchheads():
748 if repo['.'].node() not in repo.branchheads():
749 # The topo heads set is included in the branch heads set of the
749 # The topo heads set is included in the branch heads set of the
750 # current branch, so it's sufficient to test branchheads
750 # current branch, so it's sufficient to test branchheads
751 raise util.Abort(_('can only close branch heads'))
751 raise util.Abort(_('can only close branch heads'))
752 extra['close'] = 1
752 extra['close'] = 1
753 e = cmdutil.commiteditor
753 e = cmdutil.commiteditor
754 if opts.get('force_editor'):
754 if opts.get('force_editor'):
755 e = cmdutil.commitforceeditor
755 e = cmdutil.commitforceeditor
756
756
757 def commitfunc(ui, repo, message, match, opts):
757 def commitfunc(ui, repo, message, match, opts):
758 return repo.commit(message, opts.get('user'), opts.get('date'), match,
758 return repo.commit(message, opts.get('user'), opts.get('date'), match,
759 editor=e, extra=extra)
759 editor=e, extra=extra)
760
760
761 branch = repo[None].branch()
761 branch = repo[None].branch()
762 bheads = repo.branchheads(branch)
762 bheads = repo.branchheads(branch)
763
763
764 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
764 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
765 if not node:
765 if not node:
766 ui.status(_("nothing changed\n"))
766 ui.status(_("nothing changed\n"))
767 return 1
767 return 1
768
768
769 ctx = repo[node]
769 ctx = repo[node]
770 parents = ctx.parents()
770 parents = ctx.parents()
771
771
772 if bheads and not [x for x in parents
772 if bheads and not [x for x in parents
773 if x.node() in bheads and x.branch() == branch]:
773 if x.node() in bheads and x.branch() == branch]:
774 ui.status(_('created new head\n'))
774 ui.status(_('created new head\n'))
775 # The message is not printed for initial roots. For the other
775 # The message is not printed for initial roots. For the other
776 # changesets, it is printed in the following situations:
776 # changesets, it is printed in the following situations:
777 #
777 #
778 # Par column: for the 2 parents with ...
778 # Par column: for the 2 parents with ...
779 # N: null or no parent
779 # N: null or no parent
780 # B: parent is on another named branch
780 # B: parent is on another named branch
781 # C: parent is a regular non head changeset
781 # C: parent is a regular non head changeset
782 # H: parent was a branch head of the current branch
782 # H: parent was a branch head of the current branch
783 # Msg column: whether we print "created new head" message
783 # Msg column: whether we print "created new head" message
784 # In the following, it is assumed that there already exists some
784 # In the following, it is assumed that there already exists some
785 # initial branch heads of the current branch, otherwise nothing is
785 # initial branch heads of the current branch, otherwise nothing is
786 # printed anyway.
786 # printed anyway.
787 #
787 #
788 # Par Msg Comment
788 # Par Msg Comment
789 # NN y additional topo root
789 # NN y additional topo root
790 #
790 #
791 # BN y additional branch root
791 # BN y additional branch root
792 # CN y additional topo head
792 # CN y additional topo head
793 # HN n usual case
793 # HN n usual case
794 #
794 #
795 # BB y weird additional branch root
795 # BB y weird additional branch root
796 # CB y branch merge
796 # CB y branch merge
797 # HB n merge with named branch
797 # HB n merge with named branch
798 #
798 #
799 # CC y additional head from merge
799 # CC y additional head from merge
800 # CH n merge with a head
800 # CH n merge with a head
801 #
801 #
802 # HH n head merge: head count decreases
802 # HH n head merge: head count decreases
803
803
804 if not opts.get('close_branch'):
804 if not opts.get('close_branch'):
805 for r in parents:
805 for r in parents:
806 if r.extra().get('close') and r.branch() == branch:
806 if r.extra().get('close') and r.branch() == branch:
807 ui.status(_('reopening closed branch head %d\n') % r)
807 ui.status(_('reopening closed branch head %d\n') % r)
808
808
809 if ui.debugflag:
809 if ui.debugflag:
810 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
810 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
811 elif ui.verbose:
811 elif ui.verbose:
812 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
812 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
813
813
814 def copy(ui, repo, *pats, **opts):
814 def copy(ui, repo, *pats, **opts):
815 """mark files as copied for the next commit
815 """mark files as copied for the next commit
816
816
817 Mark dest as having copies of source files. If dest is a
817 Mark dest as having copies of source files. If dest is a
818 directory, copies are put in that directory. If dest is a file,
818 directory, copies are put in that directory. If dest is a file,
819 the source must be a single file.
819 the source must be a single file.
820
820
821 By default, this command copies the contents of files as they
821 By default, this command copies the contents of files as they
822 exist in the working directory. If invoked with -A/--after, the
822 exist in the working directory. If invoked with -A/--after, the
823 operation is recorded, but no copying is performed.
823 operation is recorded, but no copying is performed.
824
824
825 This command takes effect with the next commit. To undo a copy
825 This command takes effect with the next commit. To undo a copy
826 before that, see :hg:`revert`.
826 before that, see :hg:`revert`.
827
827
828 Returns 0 on success, 1 if errors are encountered.
828 Returns 0 on success, 1 if errors are encountered.
829 """
829 """
830 wlock = repo.wlock(False)
830 wlock = repo.wlock(False)
831 try:
831 try:
832 return cmdutil.copy(ui, repo, pats, opts)
832 return cmdutil.copy(ui, repo, pats, opts)
833 finally:
833 finally:
834 wlock.release()
834 wlock.release()
835
835
836 def debugancestor(ui, repo, *args):
836 def debugancestor(ui, repo, *args):
837 """find the ancestor revision of two revisions in a given index"""
837 """find the ancestor revision of two revisions in a given index"""
838 if len(args) == 3:
838 if len(args) == 3:
839 index, rev1, rev2 = args
839 index, rev1, rev2 = args
840 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
840 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
841 lookup = r.lookup
841 lookup = r.lookup
842 elif len(args) == 2:
842 elif len(args) == 2:
843 if not repo:
843 if not repo:
844 raise util.Abort(_("There is no Mercurial repository here "
844 raise util.Abort(_("There is no Mercurial repository here "
845 "(.hg not found)"))
845 "(.hg not found)"))
846 rev1, rev2 = args
846 rev1, rev2 = args
847 r = repo.changelog
847 r = repo.changelog
848 lookup = repo.lookup
848 lookup = repo.lookup
849 else:
849 else:
850 raise util.Abort(_('either two or three arguments required'))
850 raise util.Abort(_('either two or three arguments required'))
851 a = r.ancestor(lookup(rev1), lookup(rev2))
851 a = r.ancestor(lookup(rev1), lookup(rev2))
852 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
852 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
853
853
854 def debugbuilddag(ui, repo, text,
854 def debugbuilddag(ui, repo, text,
855 mergeable_file=False,
855 mergeable_file=False,
856 appended_file=False,
856 appended_file=False,
857 overwritten_file=False,
857 overwritten_file=False,
858 new_file=False):
858 new_file=False):
859 """builds a repo with a given dag from scratch in the current empty repo
859 """builds a repo with a given dag from scratch in the current empty repo
860
860
861 Elements:
861 Elements:
862
862
863 - "+n" is a linear run of n nodes based on the current default parent
863 - "+n" is a linear run of n nodes based on the current default parent
864 - "." is a single node based on the current default parent
864 - "." is a single node based on the current default parent
865 - "$" resets the default parent to null (implied at the start);
865 - "$" resets the default parent to null (implied at the start);
866 otherwise the default parent is always the last node created
866 otherwise the default parent is always the last node created
867 - "<p" sets the default parent to the backref p
867 - "<p" sets the default parent to the backref p
868 - "*p" is a fork at parent p, which is a backref
868 - "*p" is a fork at parent p, which is a backref
869 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
869 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
870 - "/p2" is a merge of the preceding node and p2
870 - "/p2" is a merge of the preceding node and p2
871 - ":tag" defines a local tag for the preceding node
871 - ":tag" defines a local tag for the preceding node
872 - "@branch" sets the named branch for subsequent nodes
872 - "@branch" sets the named branch for subsequent nodes
873 - "!command" runs the command using your shell
873 - "!command" runs the command using your shell
874 - "!!my command\\n" is like "!", but to the end of the line
874 - "!!my command\\n" is like "!", but to the end of the line
875 - "#...\\n" is a comment up to the end of the line
875 - "#...\\n" is a comment up to the end of the line
876
876
877 Whitespace between the above elements is ignored.
877 Whitespace between the above elements is ignored.
878
878
879 A backref is either
879 A backref is either
880
880
881 - a number n, which references the node curr-n, where curr is the current
881 - a number n, which references the node curr-n, where curr is the current
882 node, or
882 node, or
883 - the name of a local tag you placed earlier using ":tag", or
883 - the name of a local tag you placed earlier using ":tag", or
884 - empty to denote the default parent.
884 - empty to denote the default parent.
885
885
886 All string valued-elements are either strictly alphanumeric, or must
886 All string valued-elements are either strictly alphanumeric, or must
887 be enclosed in double quotes ("..."), with "\" as escape character.
887 be enclosed in double quotes ("..."), with "\" as escape character.
888
888
889 Note that the --overwritten-file and --appended-file options imply the
889 Note that the --overwritten-file and --appended-file options imply the
890 use of "HGMERGE=internal:local" during DAG buildup.
890 use of "HGMERGE=internal:local" during DAG buildup.
891 """
891 """
892
892
893 if not (mergeable_file or appended_file or overwritten_file or new_file):
893 if not (mergeable_file or appended_file or overwritten_file or new_file):
894 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
894 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
895
895
896 if len(repo.changelog) > 0:
896 if len(repo.changelog) > 0:
897 raise util.Abort(_('repository is not empty'))
897 raise util.Abort(_('repository is not empty'))
898
898
899 if overwritten_file or appended_file:
899 if overwritten_file or appended_file:
900 # we don't want to fail in merges during buildup
900 # we don't want to fail in merges during buildup
901 os.environ['HGMERGE'] = 'internal:local'
901 os.environ['HGMERGE'] = 'internal:local'
902
902
903 def writefile(fname, text, fmode="w"):
903 def writefile(fname, text, fmode="w"):
904 f = open(fname, fmode)
904 f = open(fname, fmode)
905 try:
905 try:
906 f.write(text)
906 f.write(text)
907 finally:
907 finally:
908 f.close()
908 f.close()
909
909
910 if mergeable_file:
910 if mergeable_file:
911 linesperrev = 2
911 linesperrev = 2
912 # determine number of revs in DAG
912 # determine number of revs in DAG
913 n = 0
913 n = 0
914 for type, data in dagparser.parsedag(text):
914 for type, data in dagparser.parsedag(text):
915 if type == 'n':
915 if type == 'n':
916 n += 1
916 n += 1
917 # make a file with k lines per rev
917 # make a file with k lines per rev
918 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
918 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
919 + "\n")
919 + "\n")
920
920
921 at = -1
921 at = -1
922 atbranch = 'default'
922 atbranch = 'default'
923 for type, data in dagparser.parsedag(text):
923 for type, data in dagparser.parsedag(text):
924 if type == 'n':
924 if type == 'n':
925 ui.status('node %s\n' % str(data))
925 ui.status('node %s\n' % str(data))
926 id, ps = data
926 id, ps = data
927 p1 = ps[0]
927 p1 = ps[0]
928 if p1 != at:
928 if p1 != at:
929 update(ui, repo, node=p1, clean=True)
929 update(ui, repo, node=p1, clean=True)
930 at = p1
930 at = p1
931 if repo.dirstate.branch() != atbranch:
931 if repo.dirstate.branch() != atbranch:
932 branch(ui, repo, atbranch, force=True)
932 branch(ui, repo, atbranch, force=True)
933 if len(ps) > 1:
933 if len(ps) > 1:
934 p2 = ps[1]
934 p2 = ps[1]
935 merge(ui, repo, node=p2)
935 merge(ui, repo, node=p2)
936
936
937 if mergeable_file:
937 if mergeable_file:
938 f = open("mf", "r+")
938 f = open("mf", "r+")
939 try:
939 try:
940 lines = f.read().split("\n")
940 lines = f.read().split("\n")
941 lines[id * linesperrev] += " r%i" % id
941 lines[id * linesperrev] += " r%i" % id
942 f.seek(0)
942 f.seek(0)
943 f.write("\n".join(lines))
943 f.write("\n".join(lines))
944 finally:
944 finally:
945 f.close()
945 f.close()
946
946
947 if appended_file:
947 if appended_file:
948 writefile("af", "r%i\n" % id, "a")
948 writefile("af", "r%i\n" % id, "a")
949
949
950 if overwritten_file:
950 if overwritten_file:
951 writefile("of", "r%i\n" % id)
951 writefile("of", "r%i\n" % id)
952
952
953 if new_file:
953 if new_file:
954 writefile("nf%i" % id, "r%i\n" % id)
954 writefile("nf%i" % id, "r%i\n" % id)
955
955
956 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
956 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
957 at = id
957 at = id
958 elif type == 'l':
958 elif type == 'l':
959 id, name = data
959 id, name = data
960 ui.status('tag %s\n' % name)
960 ui.status('tag %s\n' % name)
961 tag(ui, repo, name, local=True)
961 tag(ui, repo, name, local=True)
962 elif type == 'a':
962 elif type == 'a':
963 ui.status('branch %s\n' % data)
963 ui.status('branch %s\n' % data)
964 atbranch = data
964 atbranch = data
965 elif type in 'cC':
965 elif type in 'cC':
966 r = util.system(data, cwd=repo.root)
966 r = util.system(data, cwd=repo.root)
967 if r:
967 if r:
968 desc, r = util.explain_exit(r)
968 desc, r = util.explain_exit(r)
969 raise util.Abort(_('%s command %s') % (data, desc))
969 raise util.Abort(_('%s command %s') % (data, desc))
970
970
971 def debugcommands(ui, cmd='', *args):
971 def debugcommands(ui, cmd='', *args):
972 """list all available commands and options"""
972 """list all available commands and options"""
973 for cmd, vals in sorted(table.iteritems()):
973 for cmd, vals in sorted(table.iteritems()):
974 cmd = cmd.split('|')[0].strip('^')
974 cmd = cmd.split('|')[0].strip('^')
975 opts = ', '.join([i[1] for i in vals[1]])
975 opts = ', '.join([i[1] for i in vals[1]])
976 ui.write('%s: %s\n' % (cmd, opts))
976 ui.write('%s: %s\n' % (cmd, opts))
977
977
978 def debugcomplete(ui, cmd='', **opts):
978 def debugcomplete(ui, cmd='', **opts):
979 """returns the completion list associated with the given command"""
979 """returns the completion list associated with the given command"""
980
980
981 if opts.get('options'):
981 if opts.get('options'):
982 options = []
982 options = []
983 otables = [globalopts]
983 otables = [globalopts]
984 if cmd:
984 if cmd:
985 aliases, entry = cmdutil.findcmd(cmd, table, False)
985 aliases, entry = cmdutil.findcmd(cmd, table, False)
986 otables.append(entry[1])
986 otables.append(entry[1])
987 for t in otables:
987 for t in otables:
988 for o in t:
988 for o in t:
989 if "(DEPRECATED)" in o[3]:
989 if "(DEPRECATED)" in o[3]:
990 continue
990 continue
991 if o[0]:
991 if o[0]:
992 options.append('-%s' % o[0])
992 options.append('-%s' % o[0])
993 options.append('--%s' % o[1])
993 options.append('--%s' % o[1])
994 ui.write("%s\n" % "\n".join(options))
994 ui.write("%s\n" % "\n".join(options))
995 return
995 return
996
996
997 cmdlist = cmdutil.findpossible(cmd, table)
997 cmdlist = cmdutil.findpossible(cmd, table)
998 if ui.verbose:
998 if ui.verbose:
999 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
999 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1000 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1000 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1001
1001
1002 def debugfsinfo(ui, path = "."):
1002 def debugfsinfo(ui, path = "."):
1003 """show information detected about current filesystem"""
1003 """show information detected about current filesystem"""
1004 open('.debugfsinfo', 'w').write('')
1004 open('.debugfsinfo', 'w').write('')
1005 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1005 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1006 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1006 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1007 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1007 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1008 and 'yes' or 'no'))
1008 and 'yes' or 'no'))
1009 os.unlink('.debugfsinfo')
1009 os.unlink('.debugfsinfo')
1010
1010
1011 def debugrebuildstate(ui, repo, rev="tip"):
1011 def debugrebuildstate(ui, repo, rev="tip"):
1012 """rebuild the dirstate as it would look like for the given revision"""
1012 """rebuild the dirstate as it would look like for the given revision"""
1013 ctx = repo[rev]
1013 ctx = repo[rev]
1014 wlock = repo.wlock()
1014 wlock = repo.wlock()
1015 try:
1015 try:
1016 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1016 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1017 finally:
1017 finally:
1018 wlock.release()
1018 wlock.release()
1019
1019
1020 def debugcheckstate(ui, repo):
1020 def debugcheckstate(ui, repo):
1021 """validate the correctness of the current dirstate"""
1021 """validate the correctness of the current dirstate"""
1022 parent1, parent2 = repo.dirstate.parents()
1022 parent1, parent2 = repo.dirstate.parents()
1023 m1 = repo[parent1].manifest()
1023 m1 = repo[parent1].manifest()
1024 m2 = repo[parent2].manifest()
1024 m2 = repo[parent2].manifest()
1025 errors = 0
1025 errors = 0
1026 for f in repo.dirstate:
1026 for f in repo.dirstate:
1027 state = repo.dirstate[f]
1027 state = repo.dirstate[f]
1028 if state in "nr" and f not in m1:
1028 if state in "nr" and f not in m1:
1029 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1029 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1030 errors += 1
1030 errors += 1
1031 if state in "a" and f in m1:
1031 if state in "a" and f in m1:
1032 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1032 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1033 errors += 1
1033 errors += 1
1034 if state in "m" and f not in m1 and f not in m2:
1034 if state in "m" and f not in m1 and f not in m2:
1035 ui.warn(_("%s in state %s, but not in either manifest\n") %
1035 ui.warn(_("%s in state %s, but not in either manifest\n") %
1036 (f, state))
1036 (f, state))
1037 errors += 1
1037 errors += 1
1038 for f in m1:
1038 for f in m1:
1039 state = repo.dirstate[f]
1039 state = repo.dirstate[f]
1040 if state not in "nrm":
1040 if state not in "nrm":
1041 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1041 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1042 errors += 1
1042 errors += 1
1043 if errors:
1043 if errors:
1044 error = _(".hg/dirstate inconsistent with current parent's manifest")
1044 error = _(".hg/dirstate inconsistent with current parent's manifest")
1045 raise util.Abort(error)
1045 raise util.Abort(error)
1046
1046
1047 def showconfig(ui, repo, *values, **opts):
1047 def showconfig(ui, repo, *values, **opts):
1048 """show combined config settings from all hgrc files
1048 """show combined config settings from all hgrc files
1049
1049
1050 With no arguments, print names and values of all config items.
1050 With no arguments, print names and values of all config items.
1051
1051
1052 With one argument of the form section.name, print just the value
1052 With one argument of the form section.name, print just the value
1053 of that config item.
1053 of that config item.
1054
1054
1055 With multiple arguments, print names and values of all config
1055 With multiple arguments, print names and values of all config
1056 items with matching section names.
1056 items with matching section names.
1057
1057
1058 With --debug, the source (filename and line number) is printed
1058 With --debug, the source (filename and line number) is printed
1059 for each config item.
1059 for each config item.
1060
1060
1061 Returns 0 on success.
1061 Returns 0 on success.
1062 """
1062 """
1063
1063
1064 for f in util.rcpath():
1064 for f in util.rcpath():
1065 ui.debug(_('read config from: %s\n') % f)
1065 ui.debug(_('read config from: %s\n') % f)
1066 untrusted = bool(opts.get('untrusted'))
1066 untrusted = bool(opts.get('untrusted'))
1067 if values:
1067 if values:
1068 if len([v for v in values if '.' in v]) > 1:
1068 if len([v for v in values if '.' in v]) > 1:
1069 raise util.Abort(_('only one config item permitted'))
1069 raise util.Abort(_('only one config item permitted'))
1070 for section, name, value in ui.walkconfig(untrusted=untrusted):
1070 for section, name, value in ui.walkconfig(untrusted=untrusted):
1071 sectname = section + '.' + name
1071 sectname = section + '.' + name
1072 if values:
1072 if values:
1073 for v in values:
1073 for v in values:
1074 if v == section:
1074 if v == section:
1075 ui.debug('%s: ' %
1075 ui.debug('%s: ' %
1076 ui.configsource(section, name, untrusted))
1076 ui.configsource(section, name, untrusted))
1077 ui.write('%s=%s\n' % (sectname, value))
1077 ui.write('%s=%s\n' % (sectname, value))
1078 elif v == sectname:
1078 elif v == sectname:
1079 ui.debug('%s: ' %
1079 ui.debug('%s: ' %
1080 ui.configsource(section, name, untrusted))
1080 ui.configsource(section, name, untrusted))
1081 ui.write(value, '\n')
1081 ui.write(value, '\n')
1082 else:
1082 else:
1083 ui.debug('%s: ' %
1083 ui.debug('%s: ' %
1084 ui.configsource(section, name, untrusted))
1084 ui.configsource(section, name, untrusted))
1085 ui.write('%s=%s\n' % (sectname, value))
1085 ui.write('%s=%s\n' % (sectname, value))
1086
1086
1087 def debugpushkey(ui, repopath, namespace, *keyinfo):
1087 def debugpushkey(ui, repopath, namespace, *keyinfo):
1088 '''access the pushkey key/value protocol
1088 '''access the pushkey key/value protocol
1089
1089
1090 With two args, list the keys in the given namespace.
1090 With two args, list the keys in the given namespace.
1091
1091
1092 With five args, set a key to new if it currently is set to old.
1092 With five args, set a key to new if it currently is set to old.
1093 Reports success or failure.
1093 Reports success or failure.
1094 '''
1094 '''
1095
1095
1096 target = hg.repository(ui, repopath)
1096 target = hg.repository(ui, repopath)
1097 if keyinfo:
1097 if keyinfo:
1098 key, old, new = keyinfo
1098 key, old, new = keyinfo
1099 r = target.pushkey(namespace, key, old, new)
1099 r = target.pushkey(namespace, key, old, new)
1100 ui.status(str(r) + '\n')
1100 ui.status(str(r) + '\n')
1101 return not(r)
1101 return not(r)
1102 else:
1102 else:
1103 for k, v in target.listkeys(namespace).iteritems():
1103 for k, v in target.listkeys(namespace).iteritems():
1104 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1104 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1105 v.encode('string-escape')))
1105 v.encode('string-escape')))
1106
1106
1107 def debugrevspec(ui, repo, expr):
1107 def debugrevspec(ui, repo, expr):
1108 '''parse and apply a revision specification'''
1108 '''parse and apply a revision specification'''
1109 if ui.verbose:
1109 if ui.verbose:
1110 tree = revset.parse(expr)
1110 tree = revset.parse(expr)
1111 ui.note(tree, "\n")
1111 ui.note(tree, "\n")
1112 func = revset.match(expr)
1112 func = revset.match(expr)
1113 for c in func(repo, range(len(repo))):
1113 for c in func(repo, range(len(repo))):
1114 ui.write("%s\n" % c)
1114 ui.write("%s\n" % c)
1115
1115
1116 def debugsetparents(ui, repo, rev1, rev2=None):
1116 def debugsetparents(ui, repo, rev1, rev2=None):
1117 """manually set the parents of the current working directory
1117 """manually set the parents of the current working directory
1118
1118
1119 This is useful for writing repository conversion tools, but should
1119 This is useful for writing repository conversion tools, but should
1120 be used with care.
1120 be used with care.
1121
1121
1122 Returns 0 on success.
1122 Returns 0 on success.
1123 """
1123 """
1124
1124
1125 if not rev2:
1125 if not rev2:
1126 rev2 = hex(nullid)
1126 rev2 = hex(nullid)
1127
1127
1128 wlock = repo.wlock()
1128 wlock = repo.wlock()
1129 try:
1129 try:
1130 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1130 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1131 finally:
1131 finally:
1132 wlock.release()
1132 wlock.release()
1133
1133
1134 def debugstate(ui, repo, nodates=None):
1134 def debugstate(ui, repo, nodates=None):
1135 """show the contents of the current dirstate"""
1135 """show the contents of the current dirstate"""
1136 timestr = ""
1136 timestr = ""
1137 showdate = not nodates
1137 showdate = not nodates
1138 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1138 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1139 if showdate:
1139 if showdate:
1140 if ent[3] == -1:
1140 if ent[3] == -1:
1141 # Pad or slice to locale representation
1141 # Pad or slice to locale representation
1142 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1142 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1143 time.localtime(0)))
1143 time.localtime(0)))
1144 timestr = 'unset'
1144 timestr = 'unset'
1145 timestr = (timestr[:locale_len] +
1145 timestr = (timestr[:locale_len] +
1146 ' ' * (locale_len - len(timestr)))
1146 ' ' * (locale_len - len(timestr)))
1147 else:
1147 else:
1148 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1148 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1149 time.localtime(ent[3]))
1149 time.localtime(ent[3]))
1150 if ent[1] & 020000:
1150 if ent[1] & 020000:
1151 mode = 'lnk'
1151 mode = 'lnk'
1152 else:
1152 else:
1153 mode = '%3o' % (ent[1] & 0777)
1153 mode = '%3o' % (ent[1] & 0777)
1154 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1154 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1155 for f in repo.dirstate.copies():
1155 for f in repo.dirstate.copies():
1156 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1156 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1157
1157
1158 def debugsub(ui, repo, rev=None):
1158 def debugsub(ui, repo, rev=None):
1159 if rev == '':
1159 if rev == '':
1160 rev = None
1160 rev = None
1161 for k, v in sorted(repo[rev].substate.items()):
1161 for k, v in sorted(repo[rev].substate.items()):
1162 ui.write('path %s\n' % k)
1162 ui.write('path %s\n' % k)
1163 ui.write(' source %s\n' % v[0])
1163 ui.write(' source %s\n' % v[0])
1164 ui.write(' revision %s\n' % v[1])
1164 ui.write(' revision %s\n' % v[1])
1165
1165
1166 def debugdag(ui, repo, file_=None, *revs, **opts):
1166 def debugdag(ui, repo, file_=None, *revs, **opts):
1167 """format the changelog or an index DAG as a concise textual description
1167 """format the changelog or an index DAG as a concise textual description
1168
1168
1169 If you pass a revlog index, the revlog's DAG is emitted. If you list
1169 If you pass a revlog index, the revlog's DAG is emitted. If you list
1170 revision numbers, they get labelled in the output as rN.
1170 revision numbers, they get labelled in the output as rN.
1171
1171
1172 Otherwise, the changelog DAG of the current repo is emitted.
1172 Otherwise, the changelog DAG of the current repo is emitted.
1173 """
1173 """
1174 spaces = opts.get('spaces')
1174 spaces = opts.get('spaces')
1175 dots = opts.get('dots')
1175 dots = opts.get('dots')
1176 if file_:
1176 if file_:
1177 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1177 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1178 revs = set((int(r) for r in revs))
1178 revs = set((int(r) for r in revs))
1179 def events():
1179 def events():
1180 for r in rlog:
1180 for r in rlog:
1181 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1181 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1182 if r in revs:
1182 if r in revs:
1183 yield 'l', (r, "r%i" % r)
1183 yield 'l', (r, "r%i" % r)
1184 elif repo:
1184 elif repo:
1185 cl = repo.changelog
1185 cl = repo.changelog
1186 tags = opts.get('tags')
1186 tags = opts.get('tags')
1187 branches = opts.get('branches')
1187 branches = opts.get('branches')
1188 if tags:
1188 if tags:
1189 labels = {}
1189 labels = {}
1190 for l, n in repo.tags().items():
1190 for l, n in repo.tags().items():
1191 labels.setdefault(cl.rev(n), []).append(l)
1191 labels.setdefault(cl.rev(n), []).append(l)
1192 def events():
1192 def events():
1193 b = "default"
1193 b = "default"
1194 for r in cl:
1194 for r in cl:
1195 if branches:
1195 if branches:
1196 newb = cl.read(cl.node(r))[5]['branch']
1196 newb = cl.read(cl.node(r))[5]['branch']
1197 if newb != b:
1197 if newb != b:
1198 yield 'a', newb
1198 yield 'a', newb
1199 b = newb
1199 b = newb
1200 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1200 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1201 if tags:
1201 if tags:
1202 ls = labels.get(r)
1202 ls = labels.get(r)
1203 if ls:
1203 if ls:
1204 for l in ls:
1204 for l in ls:
1205 yield 'l', (r, l)
1205 yield 'l', (r, l)
1206 else:
1206 else:
1207 raise util.Abort(_('need repo for changelog dag'))
1207 raise util.Abort(_('need repo for changelog dag'))
1208
1208
1209 for line in dagparser.dagtextlines(events(),
1209 for line in dagparser.dagtextlines(events(),
1210 addspaces=spaces,
1210 addspaces=spaces,
1211 wraplabels=True,
1211 wraplabels=True,
1212 wrapannotations=True,
1212 wrapannotations=True,
1213 wrapnonlinear=dots,
1213 wrapnonlinear=dots,
1214 usedots=dots,
1214 usedots=dots,
1215 maxlinewidth=70):
1215 maxlinewidth=70):
1216 ui.write(line)
1216 ui.write(line)
1217 ui.write("\n")
1217 ui.write("\n")
1218
1218
1219 def debugdata(ui, file_, rev):
1219 def debugdata(ui, file_, rev):
1220 """dump the contents of a data file revision"""
1220 """dump the contents of a data file revision"""
1221 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1221 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1222 try:
1222 try:
1223 ui.write(r.revision(r.lookup(rev)))
1223 ui.write(r.revision(r.lookup(rev)))
1224 except KeyError:
1224 except KeyError:
1225 raise util.Abort(_('invalid revision identifier %s') % rev)
1225 raise util.Abort(_('invalid revision identifier %s') % rev)
1226
1226
1227 def debugdate(ui, date, range=None, **opts):
1227 def debugdate(ui, date, range=None, **opts):
1228 """parse and display a date"""
1228 """parse and display a date"""
1229 if opts["extended"]:
1229 if opts["extended"]:
1230 d = util.parsedate(date, util.extendeddateformats)
1230 d = util.parsedate(date, util.extendeddateformats)
1231 else:
1231 else:
1232 d = util.parsedate(date)
1232 d = util.parsedate(date)
1233 ui.write("internal: %s %s\n" % d)
1233 ui.write("internal: %s %s\n" % d)
1234 ui.write("standard: %s\n" % util.datestr(d))
1234 ui.write("standard: %s\n" % util.datestr(d))
1235 if range:
1235 if range:
1236 m = util.matchdate(range)
1236 m = util.matchdate(range)
1237 ui.write("match: %s\n" % m(d[0]))
1237 ui.write("match: %s\n" % m(d[0]))
1238
1238
1239 def debugindex(ui, file_):
1239 def debugindex(ui, file_):
1240 """dump the contents of an index file"""
1240 """dump the contents of an index file"""
1241 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1241 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1242 ui.write(" rev offset length base linkrev"
1242 ui.write(" rev offset length base linkrev"
1243 " nodeid p1 p2\n")
1243 " nodeid p1 p2\n")
1244 for i in r:
1244 for i in r:
1245 node = r.node(i)
1245 node = r.node(i)
1246 try:
1246 try:
1247 pp = r.parents(node)
1247 pp = r.parents(node)
1248 except:
1248 except:
1249 pp = [nullid, nullid]
1249 pp = [nullid, nullid]
1250 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1250 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1251 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1251 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1252 short(node), short(pp[0]), short(pp[1])))
1252 short(node), short(pp[0]), short(pp[1])))
1253
1253
1254 def debugindexdot(ui, file_):
1254 def debugindexdot(ui, file_):
1255 """dump an index DAG as a graphviz dot file"""
1255 """dump an index DAG as a graphviz dot file"""
1256 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1256 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1257 ui.write("digraph G {\n")
1257 ui.write("digraph G {\n")
1258 for i in r:
1258 for i in r:
1259 node = r.node(i)
1259 node = r.node(i)
1260 pp = r.parents(node)
1260 pp = r.parents(node)
1261 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1261 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1262 if pp[1] != nullid:
1262 if pp[1] != nullid:
1263 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1263 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1264 ui.write("}\n")
1264 ui.write("}\n")
1265
1265
1266 def debuginstall(ui):
1266 def debuginstall(ui):
1267 '''test Mercurial installation
1267 '''test Mercurial installation
1268
1268
1269 Returns 0 on success.
1269 Returns 0 on success.
1270 '''
1270 '''
1271
1271
1272 def writetemp(contents):
1272 def writetemp(contents):
1273 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1273 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1274 f = os.fdopen(fd, "wb")
1274 f = os.fdopen(fd, "wb")
1275 f.write(contents)
1275 f.write(contents)
1276 f.close()
1276 f.close()
1277 return name
1277 return name
1278
1278
1279 problems = 0
1279 problems = 0
1280
1280
1281 # encoding
1281 # encoding
1282 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1282 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1283 try:
1283 try:
1284 encoding.fromlocal("test")
1284 encoding.fromlocal("test")
1285 except util.Abort, inst:
1285 except util.Abort, inst:
1286 ui.write(" %s\n" % inst)
1286 ui.write(" %s\n" % inst)
1287 ui.write(_(" (check that your locale is properly set)\n"))
1287 ui.write(_(" (check that your locale is properly set)\n"))
1288 problems += 1
1288 problems += 1
1289
1289
1290 # compiled modules
1290 # compiled modules
1291 ui.status(_("Checking extensions...\n"))
1291 ui.status(_("Checking extensions...\n"))
1292 try:
1292 try:
1293 import bdiff, mpatch, base85
1293 import bdiff, mpatch, base85
1294 except Exception, inst:
1294 except Exception, inst:
1295 ui.write(" %s\n" % inst)
1295 ui.write(" %s\n" % inst)
1296 ui.write(_(" One or more extensions could not be found"))
1296 ui.write(_(" One or more extensions could not be found"))
1297 ui.write(_(" (check that you compiled the extensions)\n"))
1297 ui.write(_(" (check that you compiled the extensions)\n"))
1298 problems += 1
1298 problems += 1
1299
1299
1300 # templates
1300 # templates
1301 ui.status(_("Checking templates...\n"))
1301 ui.status(_("Checking templates...\n"))
1302 try:
1302 try:
1303 import templater
1303 import templater
1304 templater.templater(templater.templatepath("map-cmdline.default"))
1304 templater.templater(templater.templatepath("map-cmdline.default"))
1305 except Exception, inst:
1305 except Exception, inst:
1306 ui.write(" %s\n" % inst)
1306 ui.write(" %s\n" % inst)
1307 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1307 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1308 problems += 1
1308 problems += 1
1309
1309
1310 # patch
1310 # patch
1311 ui.status(_("Checking patch...\n"))
1311 ui.status(_("Checking patch...\n"))
1312 patchproblems = 0
1312 patchproblems = 0
1313 a = "1\n2\n3\n4\n"
1313 a = "1\n2\n3\n4\n"
1314 b = "1\n2\n3\ninsert\n4\n"
1314 b = "1\n2\n3\ninsert\n4\n"
1315 fa = writetemp(a)
1315 fa = writetemp(a)
1316 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1316 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1317 os.path.basename(fa))
1317 os.path.basename(fa))
1318 fd = writetemp(d)
1318 fd = writetemp(d)
1319
1319
1320 files = {}
1320 files = {}
1321 try:
1321 try:
1322 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1322 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1323 except util.Abort, e:
1323 except util.Abort, e:
1324 ui.write(_(" patch call failed:\n"))
1324 ui.write(_(" patch call failed:\n"))
1325 ui.write(" " + str(e) + "\n")
1325 ui.write(" " + str(e) + "\n")
1326 patchproblems += 1
1326 patchproblems += 1
1327 else:
1327 else:
1328 if list(files) != [os.path.basename(fa)]:
1328 if list(files) != [os.path.basename(fa)]:
1329 ui.write(_(" unexpected patch output!\n"))
1329 ui.write(_(" unexpected patch output!\n"))
1330 patchproblems += 1
1330 patchproblems += 1
1331 a = open(fa).read()
1331 a = open(fa).read()
1332 if a != b:
1332 if a != b:
1333 ui.write(_(" patch test failed!\n"))
1333 ui.write(_(" patch test failed!\n"))
1334 patchproblems += 1
1334 patchproblems += 1
1335
1335
1336 if patchproblems:
1336 if patchproblems:
1337 if ui.config('ui', 'patch'):
1337 if ui.config('ui', 'patch'):
1338 ui.write(_(" (Current patch tool may be incompatible with patch,"
1338 ui.write(_(" (Current patch tool may be incompatible with patch,"
1339 " or misconfigured. Please check your .hgrc file)\n"))
1339 " or misconfigured. Please check your .hgrc file)\n"))
1340 else:
1340 else:
1341 ui.write(_(" Internal patcher failure, please report this error"
1341 ui.write(_(" Internal patcher failure, please report this error"
1342 " to http://mercurial.selenic.com/bts/\n"))
1342 " to http://mercurial.selenic.com/bts/\n"))
1343 problems += patchproblems
1343 problems += patchproblems
1344
1344
1345 os.unlink(fa)
1345 os.unlink(fa)
1346 os.unlink(fd)
1346 os.unlink(fd)
1347
1347
1348 # editor
1348 # editor
1349 ui.status(_("Checking commit editor...\n"))
1349 ui.status(_("Checking commit editor...\n"))
1350 editor = ui.geteditor()
1350 editor = ui.geteditor()
1351 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1351 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1352 if not cmdpath:
1352 if not cmdpath:
1353 if editor == 'vi':
1353 if editor == 'vi':
1354 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1354 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1355 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1355 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1356 else:
1356 else:
1357 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1357 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1358 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1358 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1359 problems += 1
1359 problems += 1
1360
1360
1361 # check username
1361 # check username
1362 ui.status(_("Checking username...\n"))
1362 ui.status(_("Checking username...\n"))
1363 try:
1363 try:
1364 user = ui.username()
1364 user = ui.username()
1365 except util.Abort, e:
1365 except util.Abort, e:
1366 ui.write(" %s\n" % e)
1366 ui.write(" %s\n" % e)
1367 ui.write(_(" (specify a username in your .hgrc file)\n"))
1367 ui.write(_(" (specify a username in your .hgrc file)\n"))
1368 problems += 1
1368 problems += 1
1369
1369
1370 if not problems:
1370 if not problems:
1371 ui.status(_("No problems detected\n"))
1371 ui.status(_("No problems detected\n"))
1372 else:
1372 else:
1373 ui.write(_("%s problems detected,"
1373 ui.write(_("%s problems detected,"
1374 " please check your install!\n") % problems)
1374 " please check your install!\n") % problems)
1375
1375
1376 return problems
1376 return problems
1377
1377
1378 def debugrename(ui, repo, file1, *pats, **opts):
1378 def debugrename(ui, repo, file1, *pats, **opts):
1379 """dump rename information"""
1379 """dump rename information"""
1380
1380
1381 ctx = repo[opts.get('rev')]
1381 ctx = repo[opts.get('rev')]
1382 m = cmdutil.match(repo, (file1,) + pats, opts)
1382 m = cmdutil.match(repo, (file1,) + pats, opts)
1383 for abs in ctx.walk(m):
1383 for abs in ctx.walk(m):
1384 fctx = ctx[abs]
1384 fctx = ctx[abs]
1385 o = fctx.filelog().renamed(fctx.filenode())
1385 o = fctx.filelog().renamed(fctx.filenode())
1386 rel = m.rel(abs)
1386 rel = m.rel(abs)
1387 if o:
1387 if o:
1388 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1388 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1389 else:
1389 else:
1390 ui.write(_("%s not renamed\n") % rel)
1390 ui.write(_("%s not renamed\n") % rel)
1391
1391
1392 def debugwalk(ui, repo, *pats, **opts):
1392 def debugwalk(ui, repo, *pats, **opts):
1393 """show how files match on given patterns"""
1393 """show how files match on given patterns"""
1394 m = cmdutil.match(repo, pats, opts)
1394 m = cmdutil.match(repo, pats, opts)
1395 items = list(repo.walk(m))
1395 items = list(repo.walk(m))
1396 if not items:
1396 if not items:
1397 return
1397 return
1398 fmt = 'f %%-%ds %%-%ds %%s' % (
1398 fmt = 'f %%-%ds %%-%ds %%s' % (
1399 max([len(abs) for abs in items]),
1399 max([len(abs) for abs in items]),
1400 max([len(m.rel(abs)) for abs in items]))
1400 max([len(m.rel(abs)) for abs in items]))
1401 for abs in items:
1401 for abs in items:
1402 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1402 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1403 ui.write("%s\n" % line.rstrip())
1403 ui.write("%s\n" % line.rstrip())
1404
1404
1405 def diff(ui, repo, *pats, **opts):
1405 def diff(ui, repo, *pats, **opts):
1406 """diff repository (or selected files)
1406 """diff repository (or selected files)
1407
1407
1408 Show differences between revisions for the specified files.
1408 Show differences between revisions for the specified files.
1409
1409
1410 Differences between files are shown using the unified diff format.
1410 Differences between files are shown using the unified diff format.
1411
1411
1412 NOTE: diff may generate unexpected results for merges, as it will
1412 NOTE: diff may generate unexpected results for merges, as it will
1413 default to comparing against the working directory's first parent
1413 default to comparing against the working directory's first parent
1414 changeset if no revisions are specified.
1414 changeset if no revisions are specified.
1415
1415
1416 When two revision arguments are given, then changes are shown
1416 When two revision arguments are given, then changes are shown
1417 between those revisions. If only one revision is specified then
1417 between those revisions. If only one revision is specified then
1418 that revision is compared to the working directory, and, when no
1418 that revision is compared to the working directory, and, when no
1419 revisions are specified, the working directory files are compared
1419 revisions are specified, the working directory files are compared
1420 to its parent.
1420 to its parent.
1421
1421
1422 Alternatively you can specify -c/--change with a revision to see
1422 Alternatively you can specify -c/--change with a revision to see
1423 the changes in that changeset relative to its first parent.
1423 the changes in that changeset relative to its first parent.
1424
1424
1425 Without the -a/--text option, diff will avoid generating diffs of
1425 Without the -a/--text option, diff will avoid generating diffs of
1426 files it detects as binary. With -a, diff will generate a diff
1426 files it detects as binary. With -a, diff will generate a diff
1427 anyway, probably with undesirable results.
1427 anyway, probably with undesirable results.
1428
1428
1429 Use the -g/--git option to generate diffs in the git extended diff
1429 Use the -g/--git option to generate diffs in the git extended diff
1430 format. For more information, read :hg:`help diffs`.
1430 format. For more information, read :hg:`help diffs`.
1431
1431
1432 Returns 0 on success.
1432 Returns 0 on success.
1433 """
1433 """
1434
1434
1435 revs = opts.get('rev')
1435 revs = opts.get('rev')
1436 change = opts.get('change')
1436 change = opts.get('change')
1437 stat = opts.get('stat')
1437 stat = opts.get('stat')
1438 reverse = opts.get('reverse')
1438 reverse = opts.get('reverse')
1439
1439
1440 if revs and change:
1440 if revs and change:
1441 msg = _('cannot specify --rev and --change at the same time')
1441 msg = _('cannot specify --rev and --change at the same time')
1442 raise util.Abort(msg)
1442 raise util.Abort(msg)
1443 elif change:
1443 elif change:
1444 node2 = repo.lookup(change)
1444 node2 = repo.lookup(change)
1445 node1 = repo[node2].parents()[0].node()
1445 node1 = repo[node2].parents()[0].node()
1446 else:
1446 else:
1447 node1, node2 = cmdutil.revpair(repo, revs)
1447 node1, node2 = cmdutil.revpair(repo, revs)
1448
1448
1449 if reverse:
1449 if reverse:
1450 node1, node2 = node2, node1
1450 node1, node2 = node2, node1
1451
1451
1452 diffopts = patch.diffopts(ui, opts)
1452 diffopts = patch.diffopts(ui, opts)
1453 m = cmdutil.match(repo, pats, opts)
1453 m = cmdutil.match(repo, pats, opts)
1454 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
1454 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
1455
1455
1456 def export(ui, repo, *changesets, **opts):
1456 def export(ui, repo, *changesets, **opts):
1457 """dump the header and diffs for one or more changesets
1457 """dump the header and diffs for one or more changesets
1458
1458
1459 Print the changeset header and diffs for one or more revisions.
1459 Print the changeset header and diffs for one or more revisions.
1460
1460
1461 The information shown in the changeset header is: author, date,
1461 The information shown in the changeset header is: author, date,
1462 branch name (if non-default), changeset hash, parent(s) and commit
1462 branch name (if non-default), changeset hash, parent(s) and commit
1463 comment.
1463 comment.
1464
1464
1465 NOTE: export may generate unexpected diff output for merge
1465 NOTE: export may generate unexpected diff output for merge
1466 changesets, as it will compare the merge changeset against its
1466 changesets, as it will compare the merge changeset against its
1467 first parent only.
1467 first parent only.
1468
1468
1469 Output may be to a file, in which case the name of the file is
1469 Output may be to a file, in which case the name of the file is
1470 given using a format string. The formatting rules are as follows:
1470 given using a format string. The formatting rules are as follows:
1471
1471
1472 :``%%``: literal "%" character
1472 :``%%``: literal "%" character
1473 :``%H``: changeset hash (40 bytes of hexadecimal)
1473 :``%H``: changeset hash (40 bytes of hexadecimal)
1474 :``%N``: number of patches being generated
1474 :``%N``: number of patches being generated
1475 :``%R``: changeset revision number
1475 :``%R``: changeset revision number
1476 :``%b``: basename of the exporting repository
1476 :``%b``: basename of the exporting repository
1477 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1477 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1478 :``%n``: zero-padded sequence number, starting at 1
1478 :``%n``: zero-padded sequence number, starting at 1
1479 :``%r``: zero-padded changeset revision number
1479 :``%r``: zero-padded changeset revision number
1480
1480
1481 Without the -a/--text option, export will avoid generating diffs
1481 Without the -a/--text option, export will avoid generating diffs
1482 of files it detects as binary. With -a, export will generate a
1482 of files it detects as binary. With -a, export will generate a
1483 diff anyway, probably with undesirable results.
1483 diff anyway, probably with undesirable results.
1484
1484
1485 Use the -g/--git option to generate diffs in the git extended diff
1485 Use the -g/--git option to generate diffs in the git extended diff
1486 format. See :hg:`help diffs` for more information.
1486 format. See :hg:`help diffs` for more information.
1487
1487
1488 With the --switch-parent option, the diff will be against the
1488 With the --switch-parent option, the diff will be against the
1489 second parent. It can be useful to review a merge.
1489 second parent. It can be useful to review a merge.
1490
1490
1491 Returns 0 on success.
1491 Returns 0 on success.
1492 """
1492 """
1493 changesets += tuple(opts.get('rev', []))
1493 changesets += tuple(opts.get('rev', []))
1494 if not changesets:
1494 if not changesets:
1495 raise util.Abort(_("export requires at least one changeset"))
1495 raise util.Abort(_("export requires at least one changeset"))
1496 revs = cmdutil.revrange(repo, changesets)
1496 revs = cmdutil.revrange(repo, changesets)
1497 if len(revs) > 1:
1497 if len(revs) > 1:
1498 ui.note(_('exporting patches:\n'))
1498 ui.note(_('exporting patches:\n'))
1499 else:
1499 else:
1500 ui.note(_('exporting patch:\n'))
1500 ui.note(_('exporting patch:\n'))
1501 cmdutil.export(repo, revs, template=opts.get('output'),
1501 cmdutil.export(repo, revs, template=opts.get('output'),
1502 switch_parent=opts.get('switch_parent'),
1502 switch_parent=opts.get('switch_parent'),
1503 opts=patch.diffopts(ui, opts))
1503 opts=patch.diffopts(ui, opts))
1504
1504
1505 def forget(ui, repo, *pats, **opts):
1505 def forget(ui, repo, *pats, **opts):
1506 """forget the specified files on the next commit
1506 """forget the specified files on the next commit
1507
1507
1508 Mark the specified files so they will no longer be tracked
1508 Mark the specified files so they will no longer be tracked
1509 after the next commit.
1509 after the next commit.
1510
1510
1511 This only removes files from the current branch, not from the
1511 This only removes files from the current branch, not from the
1512 entire project history, and it does not delete them from the
1512 entire project history, and it does not delete them from the
1513 working directory.
1513 working directory.
1514
1514
1515 To undo a forget before the next commit, see :hg:`add`.
1515 To undo a forget before the next commit, see :hg:`add`.
1516
1516
1517 Returns 0 on success.
1517 Returns 0 on success.
1518 """
1518 """
1519
1519
1520 if not pats:
1520 if not pats:
1521 raise util.Abort(_('no files specified'))
1521 raise util.Abort(_('no files specified'))
1522
1522
1523 m = cmdutil.match(repo, pats, opts)
1523 m = cmdutil.match(repo, pats, opts)
1524 s = repo.status(match=m, clean=True)
1524 s = repo.status(match=m, clean=True)
1525 forget = sorted(s[0] + s[1] + s[3] + s[6])
1525 forget = sorted(s[0] + s[1] + s[3] + s[6])
1526 errs = 0
1526 errs = 0
1527
1527
1528 for f in m.files():
1528 for f in m.files():
1529 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1529 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1530 ui.warn(_('not removing %s: file is already untracked\n')
1530 ui.warn(_('not removing %s: file is already untracked\n')
1531 % m.rel(f))
1531 % m.rel(f))
1532 errs = 1
1532 errs = 1
1533
1533
1534 for f in forget:
1534 for f in forget:
1535 if ui.verbose or not m.exact(f):
1535 if ui.verbose or not m.exact(f):
1536 ui.status(_('removing %s\n') % m.rel(f))
1536 ui.status(_('removing %s\n') % m.rel(f))
1537
1537
1538 repo[None].remove(forget, unlink=False)
1538 repo[None].remove(forget, unlink=False)
1539 return errs
1539 return errs
1540
1540
1541 def grep(ui, repo, pattern, *pats, **opts):
1541 def grep(ui, repo, pattern, *pats, **opts):
1542 """search for a pattern in specified files and revisions
1542 """search for a pattern in specified files and revisions
1543
1543
1544 Search revisions of files for a regular expression.
1544 Search revisions of files for a regular expression.
1545
1545
1546 This command behaves differently than Unix grep. It only accepts
1546 This command behaves differently than Unix grep. It only accepts
1547 Python/Perl regexps. It searches repository history, not the
1547 Python/Perl regexps. It searches repository history, not the
1548 working directory. It always prints the revision number in which a
1548 working directory. It always prints the revision number in which a
1549 match appears.
1549 match appears.
1550
1550
1551 By default, grep only prints output for the first revision of a
1551 By default, grep only prints output for the first revision of a
1552 file in which it finds a match. To get it to print every revision
1552 file in which it finds a match. To get it to print every revision
1553 that contains a change in match status ("-" for a match that
1553 that contains a change in match status ("-" for a match that
1554 becomes a non-match, or "+" for a non-match that becomes a match),
1554 becomes a non-match, or "+" for a non-match that becomes a match),
1555 use the --all flag.
1555 use the --all flag.
1556
1556
1557 Returns 0 if a match is found, 1 otherwise.
1557 Returns 0 if a match is found, 1 otherwise.
1558 """
1558 """
1559 reflags = 0
1559 reflags = 0
1560 if opts.get('ignore_case'):
1560 if opts.get('ignore_case'):
1561 reflags |= re.I
1561 reflags |= re.I
1562 try:
1562 try:
1563 regexp = re.compile(pattern, reflags)
1563 regexp = re.compile(pattern, reflags)
1564 except Exception, inst:
1564 except Exception, inst:
1565 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1565 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1566 return 1
1566 return 1
1567 sep, eol = ':', '\n'
1567 sep, eol = ':', '\n'
1568 if opts.get('print0'):
1568 if opts.get('print0'):
1569 sep = eol = '\0'
1569 sep = eol = '\0'
1570
1570
1571 getfile = util.lrucachefunc(repo.file)
1571 getfile = util.lrucachefunc(repo.file)
1572
1572
1573 def matchlines(body):
1573 def matchlines(body):
1574 begin = 0
1574 begin = 0
1575 linenum = 0
1575 linenum = 0
1576 while True:
1576 while True:
1577 match = regexp.search(body, begin)
1577 match = regexp.search(body, begin)
1578 if not match:
1578 if not match:
1579 break
1579 break
1580 mstart, mend = match.span()
1580 mstart, mend = match.span()
1581 linenum += body.count('\n', begin, mstart) + 1
1581 linenum += body.count('\n', begin, mstart) + 1
1582 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1582 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1583 begin = body.find('\n', mend) + 1 or len(body)
1583 begin = body.find('\n', mend) + 1 or len(body)
1584 lend = begin - 1
1584 lend = begin - 1
1585 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1585 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1586
1586
1587 class linestate(object):
1587 class linestate(object):
1588 def __init__(self, line, linenum, colstart, colend):
1588 def __init__(self, line, linenum, colstart, colend):
1589 self.line = line
1589 self.line = line
1590 self.linenum = linenum
1590 self.linenum = linenum
1591 self.colstart = colstart
1591 self.colstart = colstart
1592 self.colend = colend
1592 self.colend = colend
1593
1593
1594 def __hash__(self):
1594 def __hash__(self):
1595 return hash((self.linenum, self.line))
1595 return hash((self.linenum, self.line))
1596
1596
1597 def __eq__(self, other):
1597 def __eq__(self, other):
1598 return self.line == other.line
1598 return self.line == other.line
1599
1599
1600 matches = {}
1600 matches = {}
1601 copies = {}
1601 copies = {}
1602 def grepbody(fn, rev, body):
1602 def grepbody(fn, rev, body):
1603 matches[rev].setdefault(fn, [])
1603 matches[rev].setdefault(fn, [])
1604 m = matches[rev][fn]
1604 m = matches[rev][fn]
1605 for lnum, cstart, cend, line in matchlines(body):
1605 for lnum, cstart, cend, line in matchlines(body):
1606 s = linestate(line, lnum, cstart, cend)
1606 s = linestate(line, lnum, cstart, cend)
1607 m.append(s)
1607 m.append(s)
1608
1608
1609 def difflinestates(a, b):
1609 def difflinestates(a, b):
1610 sm = difflib.SequenceMatcher(None, a, b)
1610 sm = difflib.SequenceMatcher(None, a, b)
1611 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1611 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1612 if tag == 'insert':
1612 if tag == 'insert':
1613 for i in xrange(blo, bhi):
1613 for i in xrange(blo, bhi):
1614 yield ('+', b[i])
1614 yield ('+', b[i])
1615 elif tag == 'delete':
1615 elif tag == 'delete':
1616 for i in xrange(alo, ahi):
1616 for i in xrange(alo, ahi):
1617 yield ('-', a[i])
1617 yield ('-', a[i])
1618 elif tag == 'replace':
1618 elif tag == 'replace':
1619 for i in xrange(alo, ahi):
1619 for i in xrange(alo, ahi):
1620 yield ('-', a[i])
1620 yield ('-', a[i])
1621 for i in xrange(blo, bhi):
1621 for i in xrange(blo, bhi):
1622 yield ('+', b[i])
1622 yield ('+', b[i])
1623
1623
1624 def display(fn, ctx, pstates, states):
1624 def display(fn, ctx, pstates, states):
1625 rev = ctx.rev()
1625 rev = ctx.rev()
1626 datefunc = ui.quiet and util.shortdate or util.datestr
1626 datefunc = ui.quiet and util.shortdate or util.datestr
1627 found = False
1627 found = False
1628 filerevmatches = {}
1628 filerevmatches = {}
1629 if opts.get('all'):
1629 if opts.get('all'):
1630 iter = difflinestates(pstates, states)
1630 iter = difflinestates(pstates, states)
1631 else:
1631 else:
1632 iter = [('', l) for l in states]
1632 iter = [('', l) for l in states]
1633 for change, l in iter:
1633 for change, l in iter:
1634 cols = [fn, str(rev)]
1634 cols = [fn, str(rev)]
1635 before, match, after = None, None, None
1635 before, match, after = None, None, None
1636 if opts.get('line_number'):
1636 if opts.get('line_number'):
1637 cols.append(str(l.linenum))
1637 cols.append(str(l.linenum))
1638 if opts.get('all'):
1638 if opts.get('all'):
1639 cols.append(change)
1639 cols.append(change)
1640 if opts.get('user'):
1640 if opts.get('user'):
1641 cols.append(ui.shortuser(ctx.user()))
1641 cols.append(ui.shortuser(ctx.user()))
1642 if opts.get('date'):
1642 if opts.get('date'):
1643 cols.append(datefunc(ctx.date()))
1643 cols.append(datefunc(ctx.date()))
1644 if opts.get('files_with_matches'):
1644 if opts.get('files_with_matches'):
1645 c = (fn, rev)
1645 c = (fn, rev)
1646 if c in filerevmatches:
1646 if c in filerevmatches:
1647 continue
1647 continue
1648 filerevmatches[c] = 1
1648 filerevmatches[c] = 1
1649 else:
1649 else:
1650 before = l.line[:l.colstart]
1650 before = l.line[:l.colstart]
1651 match = l.line[l.colstart:l.colend]
1651 match = l.line[l.colstart:l.colend]
1652 after = l.line[l.colend:]
1652 after = l.line[l.colend:]
1653 ui.write(sep.join(cols))
1653 ui.write(sep.join(cols))
1654 if before is not None:
1654 if before is not None:
1655 ui.write(sep + before)
1655 ui.write(sep + before)
1656 ui.write(match, label='grep.match')
1656 ui.write(match, label='grep.match')
1657 ui.write(after)
1657 ui.write(after)
1658 ui.write(eol)
1658 ui.write(eol)
1659 found = True
1659 found = True
1660 return found
1660 return found
1661
1661
1662 skip = {}
1662 skip = {}
1663 revfiles = {}
1663 revfiles = {}
1664 matchfn = cmdutil.match(repo, pats, opts)
1664 matchfn = cmdutil.match(repo, pats, opts)
1665 found = False
1665 found = False
1666 follow = opts.get('follow')
1666 follow = opts.get('follow')
1667
1667
1668 def prep(ctx, fns):
1668 def prep(ctx, fns):
1669 rev = ctx.rev()
1669 rev = ctx.rev()
1670 pctx = ctx.parents()[0]
1670 pctx = ctx.parents()[0]
1671 parent = pctx.rev()
1671 parent = pctx.rev()
1672 matches.setdefault(rev, {})
1672 matches.setdefault(rev, {})
1673 matches.setdefault(parent, {})
1673 matches.setdefault(parent, {})
1674 files = revfiles.setdefault(rev, [])
1674 files = revfiles.setdefault(rev, [])
1675 for fn in fns:
1675 for fn in fns:
1676 flog = getfile(fn)
1676 flog = getfile(fn)
1677 try:
1677 try:
1678 fnode = ctx.filenode(fn)
1678 fnode = ctx.filenode(fn)
1679 except error.LookupError:
1679 except error.LookupError:
1680 continue
1680 continue
1681
1681
1682 copied = flog.renamed(fnode)
1682 copied = flog.renamed(fnode)
1683 copy = follow and copied and copied[0]
1683 copy = follow and copied and copied[0]
1684 if copy:
1684 if copy:
1685 copies.setdefault(rev, {})[fn] = copy
1685 copies.setdefault(rev, {})[fn] = copy
1686 if fn in skip:
1686 if fn in skip:
1687 if copy:
1687 if copy:
1688 skip[copy] = True
1688 skip[copy] = True
1689 continue
1689 continue
1690 files.append(fn)
1690 files.append(fn)
1691
1691
1692 if fn not in matches[rev]:
1692 if fn not in matches[rev]:
1693 grepbody(fn, rev, flog.read(fnode))
1693 grepbody(fn, rev, flog.read(fnode))
1694
1694
1695 pfn = copy or fn
1695 pfn = copy or fn
1696 if pfn not in matches[parent]:
1696 if pfn not in matches[parent]:
1697 try:
1697 try:
1698 fnode = pctx.filenode(pfn)
1698 fnode = pctx.filenode(pfn)
1699 grepbody(pfn, parent, flog.read(fnode))
1699 grepbody(pfn, parent, flog.read(fnode))
1700 except error.LookupError:
1700 except error.LookupError:
1701 pass
1701 pass
1702
1702
1703 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1703 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1704 rev = ctx.rev()
1704 rev = ctx.rev()
1705 parent = ctx.parents()[0].rev()
1705 parent = ctx.parents()[0].rev()
1706 for fn in sorted(revfiles.get(rev, [])):
1706 for fn in sorted(revfiles.get(rev, [])):
1707 states = matches[rev][fn]
1707 states = matches[rev][fn]
1708 copy = copies.get(rev, {}).get(fn)
1708 copy = copies.get(rev, {}).get(fn)
1709 if fn in skip:
1709 if fn in skip:
1710 if copy:
1710 if copy:
1711 skip[copy] = True
1711 skip[copy] = True
1712 continue
1712 continue
1713 pstates = matches.get(parent, {}).get(copy or fn, [])
1713 pstates = matches.get(parent, {}).get(copy or fn, [])
1714 if pstates or states:
1714 if pstates or states:
1715 r = display(fn, ctx, pstates, states)
1715 r = display(fn, ctx, pstates, states)
1716 found = found or r
1716 found = found or r
1717 if r and not opts.get('all'):
1717 if r and not opts.get('all'):
1718 skip[fn] = True
1718 skip[fn] = True
1719 if copy:
1719 if copy:
1720 skip[copy] = True
1720 skip[copy] = True
1721 del matches[rev]
1721 del matches[rev]
1722 del revfiles[rev]
1722 del revfiles[rev]
1723
1723
1724 return not found
1724 return not found
1725
1725
1726 def heads(ui, repo, *branchrevs, **opts):
1726 def heads(ui, repo, *branchrevs, **opts):
1727 """show current repository heads or show branch heads
1727 """show current repository heads or show branch heads
1728
1728
1729 With no arguments, show all repository branch heads.
1729 With no arguments, show all repository branch heads.
1730
1730
1731 Repository "heads" are changesets with no child changesets. They are
1731 Repository "heads" are changesets with no child changesets. They are
1732 where development generally takes place and are the usual targets
1732 where development generally takes place and are the usual targets
1733 for update and merge operations. Branch heads are changesets that have
1733 for update and merge operations. Branch heads are changesets that have
1734 no child changeset on the same branch.
1734 no child changeset on the same branch.
1735
1735
1736 If one or more REVs are given, only branch heads on the branches
1736 If one or more REVs are given, only branch heads on the branches
1737 associated with the specified changesets are shown.
1737 associated with the specified changesets are shown.
1738
1738
1739 If -c/--closed is specified, also show branch heads marked closed
1739 If -c/--closed is specified, also show branch heads marked closed
1740 (see :hg:`commit --close-branch`).
1740 (see :hg:`commit --close-branch`).
1741
1741
1742 If STARTREV is specified, only those heads that are descendants of
1742 If STARTREV is specified, only those heads that are descendants of
1743 STARTREV will be displayed.
1743 STARTREV will be displayed.
1744
1744
1745 If -t/--topo is specified, named branch mechanics will be ignored and only
1745 If -t/--topo is specified, named branch mechanics will be ignored and only
1746 changesets without children will be shown.
1746 changesets without children will be shown.
1747
1747
1748 Returns 0 if matching heads are found, 1 if not.
1748 Returns 0 if matching heads are found, 1 if not.
1749 """
1749 """
1750
1750
1751 if opts.get('rev'):
1751 if opts.get('rev'):
1752 start = repo.lookup(opts['rev'])
1752 start = repo.lookup(opts['rev'])
1753 else:
1753 else:
1754 start = None
1754 start = None
1755
1755
1756 if opts.get('topo'):
1756 if opts.get('topo'):
1757 heads = [repo[h] for h in repo.heads(start)]
1757 heads = [repo[h] for h in repo.heads(start)]
1758 else:
1758 else:
1759 heads = []
1759 heads = []
1760 for b, ls in repo.branchmap().iteritems():
1760 for b, ls in repo.branchmap().iteritems():
1761 if start is None:
1761 if start is None:
1762 heads += [repo[h] for h in ls]
1762 heads += [repo[h] for h in ls]
1763 continue
1763 continue
1764 startrev = repo.changelog.rev(start)
1764 startrev = repo.changelog.rev(start)
1765 descendants = set(repo.changelog.descendants(startrev))
1765 descendants = set(repo.changelog.descendants(startrev))
1766 descendants.add(startrev)
1766 descendants.add(startrev)
1767 rev = repo.changelog.rev
1767 rev = repo.changelog.rev
1768 heads += [repo[h] for h in ls if rev(h) in descendants]
1768 heads += [repo[h] for h in ls if rev(h) in descendants]
1769
1769
1770 if branchrevs:
1770 if branchrevs:
1771 decode, encode = encoding.fromlocal, encoding.tolocal
1771 decode, encode = encoding.fromlocal, encoding.tolocal
1772 branches = set(repo[decode(br)].branch() for br in branchrevs)
1772 branches = set(repo[decode(br)].branch() for br in branchrevs)
1773 heads = [h for h in heads if h.branch() in branches]
1773 heads = [h for h in heads if h.branch() in branches]
1774
1774
1775 if not opts.get('closed'):
1775 if not opts.get('closed'):
1776 heads = [h for h in heads if not h.extra().get('close')]
1776 heads = [h for h in heads if not h.extra().get('close')]
1777
1777
1778 if opts.get('active') and branchrevs:
1778 if opts.get('active') and branchrevs:
1779 dagheads = repo.heads(start)
1779 dagheads = repo.heads(start)
1780 heads = [h for h in heads if h.node() in dagheads]
1780 heads = [h for h in heads if h.node() in dagheads]
1781
1781
1782 if branchrevs:
1782 if branchrevs:
1783 haveheads = set(h.branch() for h in heads)
1783 haveheads = set(h.branch() for h in heads)
1784 if branches - haveheads:
1784 if branches - haveheads:
1785 headless = ', '.join(encode(b) for b in branches - haveheads)
1785 headless = ', '.join(encode(b) for b in branches - haveheads)
1786 msg = _('no open branch heads found on branches %s')
1786 msg = _('no open branch heads found on branches %s')
1787 if opts.get('rev'):
1787 if opts.get('rev'):
1788 msg += _(' (started at %s)' % opts['rev'])
1788 msg += _(' (started at %s)' % opts['rev'])
1789 ui.warn((msg + '\n') % headless)
1789 ui.warn((msg + '\n') % headless)
1790
1790
1791 if not heads:
1791 if not heads:
1792 return 1
1792 return 1
1793
1793
1794 heads = sorted(heads, key=lambda x: -x.rev())
1794 heads = sorted(heads, key=lambda x: -x.rev())
1795 displayer = cmdutil.show_changeset(ui, repo, opts)
1795 displayer = cmdutil.show_changeset(ui, repo, opts)
1796 for ctx in heads:
1796 for ctx in heads:
1797 displayer.show(ctx)
1797 displayer.show(ctx)
1798 displayer.close()
1798 displayer.close()
1799
1799
1800 def help_(ui, name=None, with_version=False, unknowncmd=False):
1800 def help_(ui, name=None, with_version=False, unknowncmd=False):
1801 """show help for a given topic or a help overview
1801 """show help for a given topic or a help overview
1802
1802
1803 With no arguments, print a list of commands with short help messages.
1803 With no arguments, print a list of commands with short help messages.
1804
1804
1805 Given a topic, extension, or command name, print help for that
1805 Given a topic, extension, or command name, print help for that
1806 topic.
1806 topic.
1807
1807
1808 Returns 0 if successful.
1808 Returns 0 if successful.
1809 """
1809 """
1810 option_lists = []
1810 option_lists = []
1811 textwidth = util.termwidth() - 2
1811 textwidth = util.termwidth() - 2
1812
1812
1813 def addglobalopts(aliases):
1813 def addglobalopts(aliases):
1814 if ui.verbose:
1814 if ui.verbose:
1815 option_lists.append((_("global options:"), globalopts))
1815 option_lists.append((_("global options:"), globalopts))
1816 if name == 'shortlist':
1816 if name == 'shortlist':
1817 option_lists.append((_('use "hg help" for the full list '
1817 option_lists.append((_('use "hg help" for the full list '
1818 'of commands'), ()))
1818 'of commands'), ()))
1819 else:
1819 else:
1820 if name == 'shortlist':
1820 if name == 'shortlist':
1821 msg = _('use "hg help" for the full list of commands '
1821 msg = _('use "hg help" for the full list of commands '
1822 'or "hg -v" for details')
1822 'or "hg -v" for details')
1823 elif aliases:
1823 elif aliases:
1824 msg = _('use "hg -v help%s" to show aliases and '
1824 msg = _('use "hg -v help%s" to show aliases and '
1825 'global options') % (name and " " + name or "")
1825 'global options') % (name and " " + name or "")
1826 else:
1826 else:
1827 msg = _('use "hg -v help %s" to show global options') % name
1827 msg = _('use "hg -v help %s" to show global options') % name
1828 option_lists.append((msg, ()))
1828 option_lists.append((msg, ()))
1829
1829
1830 def helpcmd(name):
1830 def helpcmd(name):
1831 if with_version:
1831 if with_version:
1832 version_(ui)
1832 version_(ui)
1833 ui.write('\n')
1833 ui.write('\n')
1834
1834
1835 try:
1835 try:
1836 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1836 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1837 except error.AmbiguousCommand, inst:
1837 except error.AmbiguousCommand, inst:
1838 # py3k fix: except vars can't be used outside the scope of the
1838 # py3k fix: except vars can't be used outside the scope of the
1839 # except block, nor can be used inside a lambda. python issue4617
1839 # except block, nor can be used inside a lambda. python issue4617
1840 prefix = inst.args[0]
1840 prefix = inst.args[0]
1841 select = lambda c: c.lstrip('^').startswith(prefix)
1841 select = lambda c: c.lstrip('^').startswith(prefix)
1842 helplist(_('list of commands:\n\n'), select)
1842 helplist(_('list of commands:\n\n'), select)
1843 return
1843 return
1844
1844
1845 # check if it's an invalid alias and display its error if it is
1845 # check if it's an invalid alias and display its error if it is
1846 if getattr(entry[0], 'badalias', False):
1846 if getattr(entry[0], 'badalias', False):
1847 if not unknowncmd:
1847 if not unknowncmd:
1848 entry[0](ui)
1848 entry[0](ui)
1849 return
1849 return
1850
1850
1851 # synopsis
1851 # synopsis
1852 if len(entry) > 2:
1852 if len(entry) > 2:
1853 if entry[2].startswith('hg'):
1853 if entry[2].startswith('hg'):
1854 ui.write("%s\n" % entry[2])
1854 ui.write("%s\n" % entry[2])
1855 else:
1855 else:
1856 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1856 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1857 else:
1857 else:
1858 ui.write('hg %s\n' % aliases[0])
1858 ui.write('hg %s\n' % aliases[0])
1859
1859
1860 # aliases
1860 # aliases
1861 if not ui.quiet and len(aliases) > 1:
1861 if not ui.quiet and len(aliases) > 1:
1862 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1862 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1863
1863
1864 # description
1864 # description
1865 doc = gettext(entry[0].__doc__)
1865 doc = gettext(entry[0].__doc__)
1866 if not doc:
1866 if not doc:
1867 doc = _("(no help text available)")
1867 doc = _("(no help text available)")
1868 if hasattr(entry[0], 'definition'): # aliased command
1868 if hasattr(entry[0], 'definition'): # aliased command
1869 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1869 if entry[0].definition.startswith('!'): # shell alias
1870 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1871 else:
1872 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1870 if ui.quiet:
1873 if ui.quiet:
1871 doc = doc.splitlines()[0]
1874 doc = doc.splitlines()[0]
1872 keep = ui.verbose and ['verbose'] or []
1875 keep = ui.verbose and ['verbose'] or []
1873 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1876 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1874 ui.write("\n%s\n" % formatted)
1877 ui.write("\n%s\n" % formatted)
1875 if pruned:
1878 if pruned:
1876 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1879 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1877
1880
1878 if not ui.quiet:
1881 if not ui.quiet:
1879 # options
1882 # options
1880 if entry[1]:
1883 if entry[1]:
1881 option_lists.append((_("options:\n"), entry[1]))
1884 option_lists.append((_("options:\n"), entry[1]))
1882
1885
1883 addglobalopts(False)
1886 addglobalopts(False)
1884
1887
1885 def helplist(header, select=None):
1888 def helplist(header, select=None):
1886 h = {}
1889 h = {}
1887 cmds = {}
1890 cmds = {}
1888 for c, e in table.iteritems():
1891 for c, e in table.iteritems():
1889 f = c.split("|", 1)[0]
1892 f = c.split("|", 1)[0]
1890 if select and not select(f):
1893 if select and not select(f):
1891 continue
1894 continue
1892 if (not select and name != 'shortlist' and
1895 if (not select and name != 'shortlist' and
1893 e[0].__module__ != __name__):
1896 e[0].__module__ != __name__):
1894 continue
1897 continue
1895 if name == "shortlist" and not f.startswith("^"):
1898 if name == "shortlist" and not f.startswith("^"):
1896 continue
1899 continue
1897 f = f.lstrip("^")
1900 f = f.lstrip("^")
1898 if not ui.debugflag and f.startswith("debug"):
1901 if not ui.debugflag and f.startswith("debug"):
1899 continue
1902 continue
1900 doc = e[0].__doc__
1903 doc = e[0].__doc__
1901 if doc and 'DEPRECATED' in doc and not ui.verbose:
1904 if doc and 'DEPRECATED' in doc and not ui.verbose:
1902 continue
1905 continue
1903 doc = gettext(doc)
1906 doc = gettext(doc)
1904 if not doc:
1907 if not doc:
1905 doc = _("(no help text available)")
1908 doc = _("(no help text available)")
1906 h[f] = doc.splitlines()[0].rstrip()
1909 h[f] = doc.splitlines()[0].rstrip()
1907 cmds[f] = c.lstrip("^")
1910 cmds[f] = c.lstrip("^")
1908
1911
1909 if not h:
1912 if not h:
1910 ui.status(_('no commands defined\n'))
1913 ui.status(_('no commands defined\n'))
1911 return
1914 return
1912
1915
1913 ui.status(header)
1916 ui.status(header)
1914 fns = sorted(h)
1917 fns = sorted(h)
1915 m = max(map(len, fns))
1918 m = max(map(len, fns))
1916 for f in fns:
1919 for f in fns:
1917 if ui.verbose:
1920 if ui.verbose:
1918 commands = cmds[f].replace("|",", ")
1921 commands = cmds[f].replace("|",", ")
1919 ui.write(" %s:\n %s\n"%(commands, h[f]))
1922 ui.write(" %s:\n %s\n"%(commands, h[f]))
1920 else:
1923 else:
1921 ui.write('%s\n' % (util.wrap(h[f],
1924 ui.write('%s\n' % (util.wrap(h[f],
1922 initindent=' %-*s ' % (m, f),
1925 initindent=' %-*s ' % (m, f),
1923 hangindent=' ' * (m + 4))))
1926 hangindent=' ' * (m + 4))))
1924
1927
1925 if not ui.quiet:
1928 if not ui.quiet:
1926 addglobalopts(True)
1929 addglobalopts(True)
1927
1930
1928 def helptopic(name):
1931 def helptopic(name):
1929 for names, header, doc in help.helptable:
1932 for names, header, doc in help.helptable:
1930 if name in names:
1933 if name in names:
1931 break
1934 break
1932 else:
1935 else:
1933 raise error.UnknownCommand(name)
1936 raise error.UnknownCommand(name)
1934
1937
1935 # description
1938 # description
1936 if not doc:
1939 if not doc:
1937 doc = _("(no help text available)")
1940 doc = _("(no help text available)")
1938 if hasattr(doc, '__call__'):
1941 if hasattr(doc, '__call__'):
1939 doc = doc()
1942 doc = doc()
1940
1943
1941 ui.write("%s\n\n" % header)
1944 ui.write("%s\n\n" % header)
1942 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1945 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1943
1946
1944 def helpext(name):
1947 def helpext(name):
1945 try:
1948 try:
1946 mod = extensions.find(name)
1949 mod = extensions.find(name)
1947 doc = gettext(mod.__doc__) or _('no help text available')
1950 doc = gettext(mod.__doc__) or _('no help text available')
1948 except KeyError:
1951 except KeyError:
1949 mod = None
1952 mod = None
1950 doc = extensions.disabledext(name)
1953 doc = extensions.disabledext(name)
1951 if not doc:
1954 if not doc:
1952 raise error.UnknownCommand(name)
1955 raise error.UnknownCommand(name)
1953
1956
1954 if '\n' not in doc:
1957 if '\n' not in doc:
1955 head, tail = doc, ""
1958 head, tail = doc, ""
1956 else:
1959 else:
1957 head, tail = doc.split('\n', 1)
1960 head, tail = doc.split('\n', 1)
1958 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1961 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1959 if tail:
1962 if tail:
1960 ui.write(minirst.format(tail, textwidth))
1963 ui.write(minirst.format(tail, textwidth))
1961 ui.status('\n\n')
1964 ui.status('\n\n')
1962
1965
1963 if mod:
1966 if mod:
1964 try:
1967 try:
1965 ct = mod.cmdtable
1968 ct = mod.cmdtable
1966 except AttributeError:
1969 except AttributeError:
1967 ct = {}
1970 ct = {}
1968 modcmds = set([c.split('|', 1)[0] for c in ct])
1971 modcmds = set([c.split('|', 1)[0] for c in ct])
1969 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1972 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1970 else:
1973 else:
1971 ui.write(_('use "hg help extensions" for information on enabling '
1974 ui.write(_('use "hg help extensions" for information on enabling '
1972 'extensions\n'))
1975 'extensions\n'))
1973
1976
1974 def helpextcmd(name):
1977 def helpextcmd(name):
1975 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1978 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1976 doc = gettext(mod.__doc__).splitlines()[0]
1979 doc = gettext(mod.__doc__).splitlines()[0]
1977
1980
1978 msg = help.listexts(_("'%s' is provided by the following "
1981 msg = help.listexts(_("'%s' is provided by the following "
1979 "extension:") % cmd, {ext: doc}, len(ext),
1982 "extension:") % cmd, {ext: doc}, len(ext),
1980 indent=4)
1983 indent=4)
1981 ui.write(minirst.format(msg, textwidth))
1984 ui.write(minirst.format(msg, textwidth))
1982 ui.write('\n\n')
1985 ui.write('\n\n')
1983 ui.write(_('use "hg help extensions" for information on enabling '
1986 ui.write(_('use "hg help extensions" for information on enabling '
1984 'extensions\n'))
1987 'extensions\n'))
1985
1988
1986 if name and name != 'shortlist':
1989 if name and name != 'shortlist':
1987 i = None
1990 i = None
1988 if unknowncmd:
1991 if unknowncmd:
1989 queries = (helpextcmd,)
1992 queries = (helpextcmd,)
1990 else:
1993 else:
1991 queries = (helptopic, helpcmd, helpext, helpextcmd)
1994 queries = (helptopic, helpcmd, helpext, helpextcmd)
1992 for f in queries:
1995 for f in queries:
1993 try:
1996 try:
1994 f(name)
1997 f(name)
1995 i = None
1998 i = None
1996 break
1999 break
1997 except error.UnknownCommand, inst:
2000 except error.UnknownCommand, inst:
1998 i = inst
2001 i = inst
1999 if i:
2002 if i:
2000 raise i
2003 raise i
2001
2004
2002 else:
2005 else:
2003 # program name
2006 # program name
2004 if ui.verbose or with_version:
2007 if ui.verbose or with_version:
2005 version_(ui)
2008 version_(ui)
2006 else:
2009 else:
2007 ui.status(_("Mercurial Distributed SCM\n"))
2010 ui.status(_("Mercurial Distributed SCM\n"))
2008 ui.status('\n')
2011 ui.status('\n')
2009
2012
2010 # list of commands
2013 # list of commands
2011 if name == "shortlist":
2014 if name == "shortlist":
2012 header = _('basic commands:\n\n')
2015 header = _('basic commands:\n\n')
2013 else:
2016 else:
2014 header = _('list of commands:\n\n')
2017 header = _('list of commands:\n\n')
2015
2018
2016 helplist(header)
2019 helplist(header)
2017 if name != 'shortlist':
2020 if name != 'shortlist':
2018 exts, maxlength = extensions.enabled()
2021 exts, maxlength = extensions.enabled()
2019 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2022 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2020 if text:
2023 if text:
2021 ui.write("\n%s\n" % minirst.format(text, textwidth))
2024 ui.write("\n%s\n" % minirst.format(text, textwidth))
2022
2025
2023 # list all option lists
2026 # list all option lists
2024 opt_output = []
2027 opt_output = []
2025 multioccur = False
2028 multioccur = False
2026 for title, options in option_lists:
2029 for title, options in option_lists:
2027 opt_output.append(("\n%s" % title, None))
2030 opt_output.append(("\n%s" % title, None))
2028 for option in options:
2031 for option in options:
2029 if len(option) == 5:
2032 if len(option) == 5:
2030 shortopt, longopt, default, desc, optlabel = option
2033 shortopt, longopt, default, desc, optlabel = option
2031 else:
2034 else:
2032 shortopt, longopt, default, desc = option
2035 shortopt, longopt, default, desc = option
2033 optlabel = _("VALUE") # default label
2036 optlabel = _("VALUE") # default label
2034
2037
2035 if _("DEPRECATED") in desc and not ui.verbose:
2038 if _("DEPRECATED") in desc and not ui.verbose:
2036 continue
2039 continue
2037 if isinstance(default, list):
2040 if isinstance(default, list):
2038 numqualifier = " %s [+]" % optlabel
2041 numqualifier = " %s [+]" % optlabel
2039 multioccur = True
2042 multioccur = True
2040 elif (default is not None) and not isinstance(default, bool):
2043 elif (default is not None) and not isinstance(default, bool):
2041 numqualifier = " %s" % optlabel
2044 numqualifier = " %s" % optlabel
2042 else:
2045 else:
2043 numqualifier = ""
2046 numqualifier = ""
2044 opt_output.append(("%2s%s" %
2047 opt_output.append(("%2s%s" %
2045 (shortopt and "-%s" % shortopt,
2048 (shortopt and "-%s" % shortopt,
2046 longopt and " --%s%s" %
2049 longopt and " --%s%s" %
2047 (longopt, numqualifier)),
2050 (longopt, numqualifier)),
2048 "%s%s" % (desc,
2051 "%s%s" % (desc,
2049 default
2052 default
2050 and _(" (default: %s)") % default
2053 and _(" (default: %s)") % default
2051 or "")))
2054 or "")))
2052 if multioccur:
2055 if multioccur:
2053 msg = _("\n[+] marked option can be specified multiple times")
2056 msg = _("\n[+] marked option can be specified multiple times")
2054 if ui.verbose and name != 'shortlist':
2057 if ui.verbose and name != 'shortlist':
2055 opt_output.append((msg, ()))
2058 opt_output.append((msg, ()))
2056 else:
2059 else:
2057 opt_output.insert(-1, (msg, ()))
2060 opt_output.insert(-1, (msg, ()))
2058
2061
2059 if not name:
2062 if not name:
2060 ui.write(_("\nadditional help topics:\n\n"))
2063 ui.write(_("\nadditional help topics:\n\n"))
2061 topics = []
2064 topics = []
2062 for names, header, doc in help.helptable:
2065 for names, header, doc in help.helptable:
2063 topics.append((sorted(names, key=len, reverse=True)[0], header))
2066 topics.append((sorted(names, key=len, reverse=True)[0], header))
2064 topics_len = max([len(s[0]) for s in topics])
2067 topics_len = max([len(s[0]) for s in topics])
2065 for t, desc in topics:
2068 for t, desc in topics:
2066 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2069 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2067
2070
2068 if opt_output:
2071 if opt_output:
2069 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
2072 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
2070 for first, second in opt_output:
2073 for first, second in opt_output:
2071 if second:
2074 if second:
2072 initindent = ' %-*s ' % (opts_len, first)
2075 initindent = ' %-*s ' % (opts_len, first)
2073 hangindent = ' ' * (opts_len + 3)
2076 hangindent = ' ' * (opts_len + 3)
2074 ui.write('%s\n' % (util.wrap(second,
2077 ui.write('%s\n' % (util.wrap(second,
2075 initindent=initindent,
2078 initindent=initindent,
2076 hangindent=hangindent)))
2079 hangindent=hangindent)))
2077 else:
2080 else:
2078 ui.write("%s\n" % first)
2081 ui.write("%s\n" % first)
2079
2082
2080 def identify(ui, repo, source=None,
2083 def identify(ui, repo, source=None,
2081 rev=None, num=None, id=None, branch=None, tags=None):
2084 rev=None, num=None, id=None, branch=None, tags=None):
2082 """identify the working copy or specified revision
2085 """identify the working copy or specified revision
2083
2086
2084 With no revision, print a summary of the current state of the
2087 With no revision, print a summary of the current state of the
2085 repository.
2088 repository.
2086
2089
2087 Specifying a path to a repository root or Mercurial bundle will
2090 Specifying a path to a repository root or Mercurial bundle will
2088 cause lookup to operate on that repository/bundle.
2091 cause lookup to operate on that repository/bundle.
2089
2092
2090 This summary identifies the repository state using one or two
2093 This summary identifies the repository state using one or two
2091 parent hash identifiers, followed by a "+" if there are
2094 parent hash identifiers, followed by a "+" if there are
2092 uncommitted changes in the working directory, a list of tags for
2095 uncommitted changes in the working directory, a list of tags for
2093 this revision and a branch name for non-default branches.
2096 this revision and a branch name for non-default branches.
2094
2097
2095 Returns 0 if successful.
2098 Returns 0 if successful.
2096 """
2099 """
2097
2100
2098 if not repo and not source:
2101 if not repo and not source:
2099 raise util.Abort(_("There is no Mercurial repository here "
2102 raise util.Abort(_("There is no Mercurial repository here "
2100 "(.hg not found)"))
2103 "(.hg not found)"))
2101
2104
2102 hexfunc = ui.debugflag and hex or short
2105 hexfunc = ui.debugflag and hex or short
2103 default = not (num or id or branch or tags)
2106 default = not (num or id or branch or tags)
2104 output = []
2107 output = []
2105
2108
2106 revs = []
2109 revs = []
2107 if source:
2110 if source:
2108 source, branches = hg.parseurl(ui.expandpath(source))
2111 source, branches = hg.parseurl(ui.expandpath(source))
2109 repo = hg.repository(ui, source)
2112 repo = hg.repository(ui, source)
2110 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2113 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2111
2114
2112 if not repo.local():
2115 if not repo.local():
2113 if not rev and revs:
2116 if not rev and revs:
2114 rev = revs[0]
2117 rev = revs[0]
2115 if not rev:
2118 if not rev:
2116 rev = "tip"
2119 rev = "tip"
2117 if num or branch or tags:
2120 if num or branch or tags:
2118 raise util.Abort(
2121 raise util.Abort(
2119 "can't query remote revision number, branch, or tags")
2122 "can't query remote revision number, branch, or tags")
2120 output = [hexfunc(repo.lookup(rev))]
2123 output = [hexfunc(repo.lookup(rev))]
2121 elif not rev:
2124 elif not rev:
2122 ctx = repo[None]
2125 ctx = repo[None]
2123 parents = ctx.parents()
2126 parents = ctx.parents()
2124 changed = False
2127 changed = False
2125 if default or id or num:
2128 if default or id or num:
2126 changed = util.any(repo.status())
2129 changed = util.any(repo.status())
2127 if default or id:
2130 if default or id:
2128 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2131 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2129 (changed) and "+" or "")]
2132 (changed) and "+" or "")]
2130 if num:
2133 if num:
2131 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2134 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2132 (changed) and "+" or ""))
2135 (changed) and "+" or ""))
2133 else:
2136 else:
2134 ctx = repo[rev]
2137 ctx = repo[rev]
2135 if default or id:
2138 if default or id:
2136 output = [hexfunc(ctx.node())]
2139 output = [hexfunc(ctx.node())]
2137 if num:
2140 if num:
2138 output.append(str(ctx.rev()))
2141 output.append(str(ctx.rev()))
2139
2142
2140 if repo.local() and default and not ui.quiet:
2143 if repo.local() and default and not ui.quiet:
2141 b = encoding.tolocal(ctx.branch())
2144 b = encoding.tolocal(ctx.branch())
2142 if b != 'default':
2145 if b != 'default':
2143 output.append("(%s)" % b)
2146 output.append("(%s)" % b)
2144
2147
2145 # multiple tags for a single parent separated by '/'
2148 # multiple tags for a single parent separated by '/'
2146 t = "/".join(ctx.tags())
2149 t = "/".join(ctx.tags())
2147 if t:
2150 if t:
2148 output.append(t)
2151 output.append(t)
2149
2152
2150 if branch:
2153 if branch:
2151 output.append(encoding.tolocal(ctx.branch()))
2154 output.append(encoding.tolocal(ctx.branch()))
2152
2155
2153 if tags:
2156 if tags:
2154 output.extend(ctx.tags())
2157 output.extend(ctx.tags())
2155
2158
2156 ui.write("%s\n" % ' '.join(output))
2159 ui.write("%s\n" % ' '.join(output))
2157
2160
2158 def import_(ui, repo, patch1, *patches, **opts):
2161 def import_(ui, repo, patch1, *patches, **opts):
2159 """import an ordered set of patches
2162 """import an ordered set of patches
2160
2163
2161 Import a list of patches and commit them individually (unless
2164 Import a list of patches and commit them individually (unless
2162 --no-commit is specified).
2165 --no-commit is specified).
2163
2166
2164 If there are outstanding changes in the working directory, import
2167 If there are outstanding changes in the working directory, import
2165 will abort unless given the -f/--force flag.
2168 will abort unless given the -f/--force flag.
2166
2169
2167 You can import a patch straight from a mail message. Even patches
2170 You can import a patch straight from a mail message. Even patches
2168 as attachments work (to use the body part, it must have type
2171 as attachments work (to use the body part, it must have type
2169 text/plain or text/x-patch). From and Subject headers of email
2172 text/plain or text/x-patch). From and Subject headers of email
2170 message are used as default committer and commit message. All
2173 message are used as default committer and commit message. All
2171 text/plain body parts before first diff are added to commit
2174 text/plain body parts before first diff are added to commit
2172 message.
2175 message.
2173
2176
2174 If the imported patch was generated by :hg:`export`, user and
2177 If the imported patch was generated by :hg:`export`, user and
2175 description from patch override values from message headers and
2178 description from patch override values from message headers and
2176 body. Values given on command line with -m/--message and -u/--user
2179 body. Values given on command line with -m/--message and -u/--user
2177 override these.
2180 override these.
2178
2181
2179 If --exact is specified, import will set the working directory to
2182 If --exact is specified, import will set the working directory to
2180 the parent of each patch before applying it, and will abort if the
2183 the parent of each patch before applying it, and will abort if the
2181 resulting changeset has a different ID than the one recorded in
2184 resulting changeset has a different ID than the one recorded in
2182 the patch. This may happen due to character set problems or other
2185 the patch. This may happen due to character set problems or other
2183 deficiencies in the text patch format.
2186 deficiencies in the text patch format.
2184
2187
2185 With -s/--similarity, hg will attempt to discover renames and
2188 With -s/--similarity, hg will attempt to discover renames and
2186 copies in the patch in the same way as 'addremove'.
2189 copies in the patch in the same way as 'addremove'.
2187
2190
2188 To read a patch from standard input, use "-" as the patch name. If
2191 To read a patch from standard input, use "-" as the patch name. If
2189 a URL is specified, the patch will be downloaded from it.
2192 a URL is specified, the patch will be downloaded from it.
2190 See :hg:`help dates` for a list of formats valid for -d/--date.
2193 See :hg:`help dates` for a list of formats valid for -d/--date.
2191
2194
2192 Returns 0 on success.
2195 Returns 0 on success.
2193 """
2196 """
2194 patches = (patch1,) + patches
2197 patches = (patch1,) + patches
2195
2198
2196 date = opts.get('date')
2199 date = opts.get('date')
2197 if date:
2200 if date:
2198 opts['date'] = util.parsedate(date)
2201 opts['date'] = util.parsedate(date)
2199
2202
2200 try:
2203 try:
2201 sim = float(opts.get('similarity') or 0)
2204 sim = float(opts.get('similarity') or 0)
2202 except ValueError:
2205 except ValueError:
2203 raise util.Abort(_('similarity must be a number'))
2206 raise util.Abort(_('similarity must be a number'))
2204 if sim < 0 or sim > 100:
2207 if sim < 0 or sim > 100:
2205 raise util.Abort(_('similarity must be between 0 and 100'))
2208 raise util.Abort(_('similarity must be between 0 and 100'))
2206
2209
2207 if opts.get('exact') or not opts.get('force'):
2210 if opts.get('exact') or not opts.get('force'):
2208 cmdutil.bail_if_changed(repo)
2211 cmdutil.bail_if_changed(repo)
2209
2212
2210 d = opts["base"]
2213 d = opts["base"]
2211 strip = opts["strip"]
2214 strip = opts["strip"]
2212 wlock = lock = None
2215 wlock = lock = None
2213
2216
2214 def tryone(ui, hunk):
2217 def tryone(ui, hunk):
2215 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2218 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2216 patch.extract(ui, hunk)
2219 patch.extract(ui, hunk)
2217
2220
2218 if not tmpname:
2221 if not tmpname:
2219 return None
2222 return None
2220 commitid = _('to working directory')
2223 commitid = _('to working directory')
2221
2224
2222 try:
2225 try:
2223 cmdline_message = cmdutil.logmessage(opts)
2226 cmdline_message = cmdutil.logmessage(opts)
2224 if cmdline_message:
2227 if cmdline_message:
2225 # pickup the cmdline msg
2228 # pickup the cmdline msg
2226 message = cmdline_message
2229 message = cmdline_message
2227 elif message:
2230 elif message:
2228 # pickup the patch msg
2231 # pickup the patch msg
2229 message = message.strip()
2232 message = message.strip()
2230 else:
2233 else:
2231 # launch the editor
2234 # launch the editor
2232 message = None
2235 message = None
2233 ui.debug('message:\n%s\n' % message)
2236 ui.debug('message:\n%s\n' % message)
2234
2237
2235 wp = repo.parents()
2238 wp = repo.parents()
2236 if opts.get('exact'):
2239 if opts.get('exact'):
2237 if not nodeid or not p1:
2240 if not nodeid or not p1:
2238 raise util.Abort(_('not a Mercurial patch'))
2241 raise util.Abort(_('not a Mercurial patch'))
2239 p1 = repo.lookup(p1)
2242 p1 = repo.lookup(p1)
2240 p2 = repo.lookup(p2 or hex(nullid))
2243 p2 = repo.lookup(p2 or hex(nullid))
2241
2244
2242 if p1 != wp[0].node():
2245 if p1 != wp[0].node():
2243 hg.clean(repo, p1)
2246 hg.clean(repo, p1)
2244 repo.dirstate.setparents(p1, p2)
2247 repo.dirstate.setparents(p1, p2)
2245 elif p2:
2248 elif p2:
2246 try:
2249 try:
2247 p1 = repo.lookup(p1)
2250 p1 = repo.lookup(p1)
2248 p2 = repo.lookup(p2)
2251 p2 = repo.lookup(p2)
2249 if p1 == wp[0].node():
2252 if p1 == wp[0].node():
2250 repo.dirstate.setparents(p1, p2)
2253 repo.dirstate.setparents(p1, p2)
2251 except error.RepoError:
2254 except error.RepoError:
2252 pass
2255 pass
2253 if opts.get('exact') or opts.get('import_branch'):
2256 if opts.get('exact') or opts.get('import_branch'):
2254 repo.dirstate.setbranch(branch or 'default')
2257 repo.dirstate.setbranch(branch or 'default')
2255
2258
2256 files = {}
2259 files = {}
2257 try:
2260 try:
2258 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2261 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2259 files=files, eolmode=None)
2262 files=files, eolmode=None)
2260 finally:
2263 finally:
2261 files = patch.updatedir(ui, repo, files,
2264 files = patch.updatedir(ui, repo, files,
2262 similarity=sim / 100.0)
2265 similarity=sim / 100.0)
2263 if not opts.get('no_commit'):
2266 if not opts.get('no_commit'):
2264 if opts.get('exact'):
2267 if opts.get('exact'):
2265 m = None
2268 m = None
2266 else:
2269 else:
2267 m = cmdutil.matchfiles(repo, files or [])
2270 m = cmdutil.matchfiles(repo, files or [])
2268 n = repo.commit(message, opts.get('user') or user,
2271 n = repo.commit(message, opts.get('user') or user,
2269 opts.get('date') or date, match=m,
2272 opts.get('date') or date, match=m,
2270 editor=cmdutil.commiteditor)
2273 editor=cmdutil.commiteditor)
2271 if opts.get('exact'):
2274 if opts.get('exact'):
2272 if hex(n) != nodeid:
2275 if hex(n) != nodeid:
2273 repo.rollback()
2276 repo.rollback()
2274 raise util.Abort(_('patch is damaged'
2277 raise util.Abort(_('patch is damaged'
2275 ' or loses information'))
2278 ' or loses information'))
2276 # Force a dirstate write so that the next transaction
2279 # Force a dirstate write so that the next transaction
2277 # backups an up-do-date file.
2280 # backups an up-do-date file.
2278 repo.dirstate.write()
2281 repo.dirstate.write()
2279 if n:
2282 if n:
2280 commitid = short(n)
2283 commitid = short(n)
2281
2284
2282 return commitid
2285 return commitid
2283 finally:
2286 finally:
2284 os.unlink(tmpname)
2287 os.unlink(tmpname)
2285
2288
2286 try:
2289 try:
2287 wlock = repo.wlock()
2290 wlock = repo.wlock()
2288 lock = repo.lock()
2291 lock = repo.lock()
2289 lastcommit = None
2292 lastcommit = None
2290 for p in patches:
2293 for p in patches:
2291 pf = os.path.join(d, p)
2294 pf = os.path.join(d, p)
2292
2295
2293 if pf == '-':
2296 if pf == '-':
2294 ui.status(_("applying patch from stdin\n"))
2297 ui.status(_("applying patch from stdin\n"))
2295 pf = sys.stdin
2298 pf = sys.stdin
2296 else:
2299 else:
2297 ui.status(_("applying %s\n") % p)
2300 ui.status(_("applying %s\n") % p)
2298 pf = url.open(ui, pf)
2301 pf = url.open(ui, pf)
2299
2302
2300 haspatch = False
2303 haspatch = False
2301 for hunk in patch.split(pf):
2304 for hunk in patch.split(pf):
2302 commitid = tryone(ui, hunk)
2305 commitid = tryone(ui, hunk)
2303 if commitid:
2306 if commitid:
2304 haspatch = True
2307 haspatch = True
2305 if lastcommit:
2308 if lastcommit:
2306 ui.status(_('applied %s\n') % lastcommit)
2309 ui.status(_('applied %s\n') % lastcommit)
2307 lastcommit = commitid
2310 lastcommit = commitid
2308
2311
2309 if not haspatch:
2312 if not haspatch:
2310 raise util.Abort(_('no diffs found'))
2313 raise util.Abort(_('no diffs found'))
2311
2314
2312 finally:
2315 finally:
2313 release(lock, wlock)
2316 release(lock, wlock)
2314
2317
2315 def incoming(ui, repo, source="default", **opts):
2318 def incoming(ui, repo, source="default", **opts):
2316 """show new changesets found in source
2319 """show new changesets found in source
2317
2320
2318 Show new changesets found in the specified path/URL or the default
2321 Show new changesets found in the specified path/URL or the default
2319 pull location. These are the changesets that would have been pulled
2322 pull location. These are the changesets that would have been pulled
2320 if a pull at the time you issued this command.
2323 if a pull at the time you issued this command.
2321
2324
2322 For remote repository, using --bundle avoids downloading the
2325 For remote repository, using --bundle avoids downloading the
2323 changesets twice if the incoming is followed by a pull.
2326 changesets twice if the incoming is followed by a pull.
2324
2327
2325 See pull for valid source format details.
2328 See pull for valid source format details.
2326
2329
2327 Returns 0 if there are incoming changes, 1 otherwise.
2330 Returns 0 if there are incoming changes, 1 otherwise.
2328 """
2331 """
2329 limit = cmdutil.loglimit(opts)
2332 limit = cmdutil.loglimit(opts)
2330 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2333 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2331 other = hg.repository(hg.remoteui(repo, opts), source)
2334 other = hg.repository(hg.remoteui(repo, opts), source)
2332 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2335 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2333 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2336 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2334 if revs:
2337 if revs:
2335 revs = [other.lookup(rev) for rev in revs]
2338 revs = [other.lookup(rev) for rev in revs]
2336
2339
2337 tmp = discovery.findcommonincoming(repo, other, heads=revs,
2340 tmp = discovery.findcommonincoming(repo, other, heads=revs,
2338 force=opts.get('force'))
2341 force=opts.get('force'))
2339 common, incoming, rheads = tmp
2342 common, incoming, rheads = tmp
2340 if not incoming:
2343 if not incoming:
2341 try:
2344 try:
2342 os.unlink(opts["bundle"])
2345 os.unlink(opts["bundle"])
2343 except:
2346 except:
2344 pass
2347 pass
2345 ui.status(_("no changes found\n"))
2348 ui.status(_("no changes found\n"))
2346 return 1
2349 return 1
2347
2350
2348 cleanup = None
2351 cleanup = None
2349 try:
2352 try:
2350 fname = opts["bundle"]
2353 fname = opts["bundle"]
2351 if fname or not other.local():
2354 if fname or not other.local():
2352 # create a bundle (uncompressed if other repo is not local)
2355 # create a bundle (uncompressed if other repo is not local)
2353
2356
2354 if revs is None and other.capable('changegroupsubset'):
2357 if revs is None and other.capable('changegroupsubset'):
2355 revs = rheads
2358 revs = rheads
2356
2359
2357 if revs is None:
2360 if revs is None:
2358 cg = other.changegroup(incoming, "incoming")
2361 cg = other.changegroup(incoming, "incoming")
2359 else:
2362 else:
2360 cg = other.changegroupsubset(incoming, revs, 'incoming')
2363 cg = other.changegroupsubset(incoming, revs, 'incoming')
2361 bundletype = other.local() and "HG10BZ" or "HG10UN"
2364 bundletype = other.local() and "HG10BZ" or "HG10UN"
2362 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2365 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2363 # keep written bundle?
2366 # keep written bundle?
2364 if opts["bundle"]:
2367 if opts["bundle"]:
2365 cleanup = None
2368 cleanup = None
2366 if not other.local():
2369 if not other.local():
2367 # use the created uncompressed bundlerepo
2370 # use the created uncompressed bundlerepo
2368 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2371 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2369
2372
2370 o = other.changelog.nodesbetween(incoming, revs)[0]
2373 o = other.changelog.nodesbetween(incoming, revs)[0]
2371 if opts.get('newest_first'):
2374 if opts.get('newest_first'):
2372 o.reverse()
2375 o.reverse()
2373 displayer = cmdutil.show_changeset(ui, other, opts)
2376 displayer = cmdutil.show_changeset(ui, other, opts)
2374 count = 0
2377 count = 0
2375 for n in o:
2378 for n in o:
2376 if limit is not None and count >= limit:
2379 if limit is not None and count >= limit:
2377 break
2380 break
2378 parents = [p for p in other.changelog.parents(n) if p != nullid]
2381 parents = [p for p in other.changelog.parents(n) if p != nullid]
2379 if opts.get('no_merges') and len(parents) == 2:
2382 if opts.get('no_merges') and len(parents) == 2:
2380 continue
2383 continue
2381 count += 1
2384 count += 1
2382 displayer.show(other[n])
2385 displayer.show(other[n])
2383 displayer.close()
2386 displayer.close()
2384 finally:
2387 finally:
2385 if hasattr(other, 'close'):
2388 if hasattr(other, 'close'):
2386 other.close()
2389 other.close()
2387 if cleanup:
2390 if cleanup:
2388 os.unlink(cleanup)
2391 os.unlink(cleanup)
2389
2392
2390 def init(ui, dest=".", **opts):
2393 def init(ui, dest=".", **opts):
2391 """create a new repository in the given directory
2394 """create a new repository in the given directory
2392
2395
2393 Initialize a new repository in the given directory. If the given
2396 Initialize a new repository in the given directory. If the given
2394 directory does not exist, it will be created.
2397 directory does not exist, it will be created.
2395
2398
2396 If no directory is given, the current directory is used.
2399 If no directory is given, the current directory is used.
2397
2400
2398 It is possible to specify an ``ssh://`` URL as the destination.
2401 It is possible to specify an ``ssh://`` URL as the destination.
2399 See :hg:`help urls` for more information.
2402 See :hg:`help urls` for more information.
2400
2403
2401 Returns 0 on success.
2404 Returns 0 on success.
2402 """
2405 """
2403 hg.repository(hg.remoteui(ui, opts), dest, create=1)
2406 hg.repository(hg.remoteui(ui, opts), dest, create=1)
2404
2407
2405 def locate(ui, repo, *pats, **opts):
2408 def locate(ui, repo, *pats, **opts):
2406 """locate files matching specific patterns
2409 """locate files matching specific patterns
2407
2410
2408 Print files under Mercurial control in the working directory whose
2411 Print files under Mercurial control in the working directory whose
2409 names match the given patterns.
2412 names match the given patterns.
2410
2413
2411 By default, this command searches all directories in the working
2414 By default, this command searches all directories in the working
2412 directory. To search just the current directory and its
2415 directory. To search just the current directory and its
2413 subdirectories, use "--include .".
2416 subdirectories, use "--include .".
2414
2417
2415 If no patterns are given to match, this command prints the names
2418 If no patterns are given to match, this command prints the names
2416 of all files under Mercurial control in the working directory.
2419 of all files under Mercurial control in the working directory.
2417
2420
2418 If you want to feed the output of this command into the "xargs"
2421 If you want to feed the output of this command into the "xargs"
2419 command, use the -0 option to both this command and "xargs". This
2422 command, use the -0 option to both this command and "xargs". This
2420 will avoid the problem of "xargs" treating single filenames that
2423 will avoid the problem of "xargs" treating single filenames that
2421 contain whitespace as multiple filenames.
2424 contain whitespace as multiple filenames.
2422
2425
2423 Returns 0 if a match is found, 1 otherwise.
2426 Returns 0 if a match is found, 1 otherwise.
2424 """
2427 """
2425 end = opts.get('print0') and '\0' or '\n'
2428 end = opts.get('print0') and '\0' or '\n'
2426 rev = opts.get('rev') or None
2429 rev = opts.get('rev') or None
2427
2430
2428 ret = 1
2431 ret = 1
2429 m = cmdutil.match(repo, pats, opts, default='relglob')
2432 m = cmdutil.match(repo, pats, opts, default='relglob')
2430 m.bad = lambda x, y: False
2433 m.bad = lambda x, y: False
2431 for abs in repo[rev].walk(m):
2434 for abs in repo[rev].walk(m):
2432 if not rev and abs not in repo.dirstate:
2435 if not rev and abs not in repo.dirstate:
2433 continue
2436 continue
2434 if opts.get('fullpath'):
2437 if opts.get('fullpath'):
2435 ui.write(repo.wjoin(abs), end)
2438 ui.write(repo.wjoin(abs), end)
2436 else:
2439 else:
2437 ui.write(((pats and m.rel(abs)) or abs), end)
2440 ui.write(((pats and m.rel(abs)) or abs), end)
2438 ret = 0
2441 ret = 0
2439
2442
2440 return ret
2443 return ret
2441
2444
2442 def log(ui, repo, *pats, **opts):
2445 def log(ui, repo, *pats, **opts):
2443 """show revision history of entire repository or files
2446 """show revision history of entire repository or files
2444
2447
2445 Print the revision history of the specified files or the entire
2448 Print the revision history of the specified files or the entire
2446 project.
2449 project.
2447
2450
2448 File history is shown without following rename or copy history of
2451 File history is shown without following rename or copy history of
2449 files. Use -f/--follow with a filename to follow history across
2452 files. Use -f/--follow with a filename to follow history across
2450 renames and copies. --follow without a filename will only show
2453 renames and copies. --follow without a filename will only show
2451 ancestors or descendants of the starting revision. --follow-first
2454 ancestors or descendants of the starting revision. --follow-first
2452 only follows the first parent of merge revisions.
2455 only follows the first parent of merge revisions.
2453
2456
2454 If no revision range is specified, the default is tip:0 unless
2457 If no revision range is specified, the default is tip:0 unless
2455 --follow is set, in which case the working directory parent is
2458 --follow is set, in which case the working directory parent is
2456 used as the starting revision. You can specify a revision set for
2459 used as the starting revision. You can specify a revision set for
2457 log, see :hg:`help revsets` for more information.
2460 log, see :hg:`help revsets` for more information.
2458
2461
2459 See :hg:`help dates` for a list of formats valid for -d/--date.
2462 See :hg:`help dates` for a list of formats valid for -d/--date.
2460
2463
2461 By default this command prints revision number and changeset id,
2464 By default this command prints revision number and changeset id,
2462 tags, non-trivial parents, user, date and time, and a summary for
2465 tags, non-trivial parents, user, date and time, and a summary for
2463 each commit. When the -v/--verbose switch is used, the list of
2466 each commit. When the -v/--verbose switch is used, the list of
2464 changed files and full commit message are shown.
2467 changed files and full commit message are shown.
2465
2468
2466 NOTE: log -p/--patch may generate unexpected diff output for merge
2469 NOTE: log -p/--patch may generate unexpected diff output for merge
2467 changesets, as it will only compare the merge changeset against
2470 changesets, as it will only compare the merge changeset against
2468 its first parent. Also, only files different from BOTH parents
2471 its first parent. Also, only files different from BOTH parents
2469 will appear in files:.
2472 will appear in files:.
2470
2473
2471 Returns 0 on success.
2474 Returns 0 on success.
2472 """
2475 """
2473
2476
2474 matchfn = cmdutil.match(repo, pats, opts)
2477 matchfn = cmdutil.match(repo, pats, opts)
2475 limit = cmdutil.loglimit(opts)
2478 limit = cmdutil.loglimit(opts)
2476 count = 0
2479 count = 0
2477
2480
2478 endrev = None
2481 endrev = None
2479 if opts.get('copies') and opts.get('rev'):
2482 if opts.get('copies') and opts.get('rev'):
2480 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2483 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2481
2484
2482 df = False
2485 df = False
2483 if opts["date"]:
2486 if opts["date"]:
2484 df = util.matchdate(opts["date"])
2487 df = util.matchdate(opts["date"])
2485
2488
2486 branches = opts.get('branch', []) + opts.get('only_branch', [])
2489 branches = opts.get('branch', []) + opts.get('only_branch', [])
2487 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2490 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2488
2491
2489 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2492 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2490 def prep(ctx, fns):
2493 def prep(ctx, fns):
2491 rev = ctx.rev()
2494 rev = ctx.rev()
2492 parents = [p for p in repo.changelog.parentrevs(rev)
2495 parents = [p for p in repo.changelog.parentrevs(rev)
2493 if p != nullrev]
2496 if p != nullrev]
2494 if opts.get('no_merges') and len(parents) == 2:
2497 if opts.get('no_merges') and len(parents) == 2:
2495 return
2498 return
2496 if opts.get('only_merges') and len(parents) != 2:
2499 if opts.get('only_merges') and len(parents) != 2:
2497 return
2500 return
2498 if opts.get('branch') and ctx.branch() not in opts['branch']:
2501 if opts.get('branch') and ctx.branch() not in opts['branch']:
2499 return
2502 return
2500 if df and not df(ctx.date()[0]):
2503 if df and not df(ctx.date()[0]):
2501 return
2504 return
2502 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2505 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2503 return
2506 return
2504 if opts.get('keyword'):
2507 if opts.get('keyword'):
2505 for k in [kw.lower() for kw in opts['keyword']]:
2508 for k in [kw.lower() for kw in opts['keyword']]:
2506 if (k in ctx.user().lower() or
2509 if (k in ctx.user().lower() or
2507 k in ctx.description().lower() or
2510 k in ctx.description().lower() or
2508 k in " ".join(ctx.files()).lower()):
2511 k in " ".join(ctx.files()).lower()):
2509 break
2512 break
2510 else:
2513 else:
2511 return
2514 return
2512
2515
2513 copies = None
2516 copies = None
2514 if opts.get('copies') and rev:
2517 if opts.get('copies') and rev:
2515 copies = []
2518 copies = []
2516 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2519 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2517 for fn in ctx.files():
2520 for fn in ctx.files():
2518 rename = getrenamed(fn, rev)
2521 rename = getrenamed(fn, rev)
2519 if rename:
2522 if rename:
2520 copies.append((fn, rename[0]))
2523 copies.append((fn, rename[0]))
2521
2524
2522 revmatchfn = None
2525 revmatchfn = None
2523 if opts.get('patch') or opts.get('stat'):
2526 if opts.get('patch') or opts.get('stat'):
2524 revmatchfn = cmdutil.match(repo, fns, default='path')
2527 revmatchfn = cmdutil.match(repo, fns, default='path')
2525
2528
2526 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2529 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2527
2530
2528 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2531 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2529 if count == limit:
2532 if count == limit:
2530 break
2533 break
2531 if displayer.flush(ctx.rev()):
2534 if displayer.flush(ctx.rev()):
2532 count += 1
2535 count += 1
2533 displayer.close()
2536 displayer.close()
2534
2537
2535 def manifest(ui, repo, node=None, rev=None):
2538 def manifest(ui, repo, node=None, rev=None):
2536 """output the current or given revision of the project manifest
2539 """output the current or given revision of the project manifest
2537
2540
2538 Print a list of version controlled files for the given revision.
2541 Print a list of version controlled files for the given revision.
2539 If no revision is given, the first parent of the working directory
2542 If no revision is given, the first parent of the working directory
2540 is used, or the null revision if no revision is checked out.
2543 is used, or the null revision if no revision is checked out.
2541
2544
2542 With -v, print file permissions, symlink and executable bits.
2545 With -v, print file permissions, symlink and executable bits.
2543 With --debug, print file revision hashes.
2546 With --debug, print file revision hashes.
2544
2547
2545 Returns 0 on success.
2548 Returns 0 on success.
2546 """
2549 """
2547
2550
2548 if rev and node:
2551 if rev and node:
2549 raise util.Abort(_("please specify just one revision"))
2552 raise util.Abort(_("please specify just one revision"))
2550
2553
2551 if not node:
2554 if not node:
2552 node = rev
2555 node = rev
2553
2556
2554 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2557 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2555 ctx = repo[node]
2558 ctx = repo[node]
2556 for f in ctx:
2559 for f in ctx:
2557 if ui.debugflag:
2560 if ui.debugflag:
2558 ui.write("%40s " % hex(ctx.manifest()[f]))
2561 ui.write("%40s " % hex(ctx.manifest()[f]))
2559 if ui.verbose:
2562 if ui.verbose:
2560 ui.write(decor[ctx.flags(f)])
2563 ui.write(decor[ctx.flags(f)])
2561 ui.write("%s\n" % f)
2564 ui.write("%s\n" % f)
2562
2565
2563 def merge(ui, repo, node=None, **opts):
2566 def merge(ui, repo, node=None, **opts):
2564 """merge working directory with another revision
2567 """merge working directory with another revision
2565
2568
2566 The current working directory is updated with all changes made in
2569 The current working directory is updated with all changes made in
2567 the requested revision since the last common predecessor revision.
2570 the requested revision since the last common predecessor revision.
2568
2571
2569 Files that changed between either parent are marked as changed for
2572 Files that changed between either parent are marked as changed for
2570 the next commit and a commit must be performed before any further
2573 the next commit and a commit must be performed before any further
2571 updates to the repository are allowed. The next commit will have
2574 updates to the repository are allowed. The next commit will have
2572 two parents.
2575 two parents.
2573
2576
2574 If no revision is specified, the working directory's parent is a
2577 If no revision is specified, the working directory's parent is a
2575 head revision, and the current branch contains exactly one other
2578 head revision, and the current branch contains exactly one other
2576 head, the other head is merged with by default. Otherwise, an
2579 head, the other head is merged with by default. Otherwise, an
2577 explicit revision with which to merge with must be provided.
2580 explicit revision with which to merge with must be provided.
2578
2581
2579 To undo an uncommitted merge, use :hg:`update --clean .` which
2582 To undo an uncommitted merge, use :hg:`update --clean .` which
2580 will check out a clean copy of the original merge parent, losing
2583 will check out a clean copy of the original merge parent, losing
2581 all changes.
2584 all changes.
2582
2585
2583 Returns 0 on success, 1 if there are unresolved files.
2586 Returns 0 on success, 1 if there are unresolved files.
2584 """
2587 """
2585
2588
2586 if opts.get('rev') and node:
2589 if opts.get('rev') and node:
2587 raise util.Abort(_("please specify just one revision"))
2590 raise util.Abort(_("please specify just one revision"))
2588 if not node:
2591 if not node:
2589 node = opts.get('rev')
2592 node = opts.get('rev')
2590
2593
2591 if not node:
2594 if not node:
2592 branch = repo.changectx(None).branch()
2595 branch = repo.changectx(None).branch()
2593 bheads = repo.branchheads(branch)
2596 bheads = repo.branchheads(branch)
2594 if len(bheads) > 2:
2597 if len(bheads) > 2:
2595 raise util.Abort(_(
2598 raise util.Abort(_(
2596 'branch \'%s\' has %d heads - '
2599 'branch \'%s\' has %d heads - '
2597 'please merge with an explicit rev\n'
2600 'please merge with an explicit rev\n'
2598 '(run \'hg heads .\' to see heads)')
2601 '(run \'hg heads .\' to see heads)')
2599 % (branch, len(bheads)))
2602 % (branch, len(bheads)))
2600
2603
2601 parent = repo.dirstate.parents()[0]
2604 parent = repo.dirstate.parents()[0]
2602 if len(bheads) == 1:
2605 if len(bheads) == 1:
2603 if len(repo.heads()) > 1:
2606 if len(repo.heads()) > 1:
2604 raise util.Abort(_(
2607 raise util.Abort(_(
2605 'branch \'%s\' has one head - '
2608 'branch \'%s\' has one head - '
2606 'please merge with an explicit rev\n'
2609 'please merge with an explicit rev\n'
2607 '(run \'hg heads\' to see all heads)')
2610 '(run \'hg heads\' to see all heads)')
2608 % branch)
2611 % branch)
2609 msg = _('there is nothing to merge')
2612 msg = _('there is nothing to merge')
2610 if parent != repo.lookup(repo[None].branch()):
2613 if parent != repo.lookup(repo[None].branch()):
2611 msg = _('%s - use "hg update" instead') % msg
2614 msg = _('%s - use "hg update" instead') % msg
2612 raise util.Abort(msg)
2615 raise util.Abort(msg)
2613
2616
2614 if parent not in bheads:
2617 if parent not in bheads:
2615 raise util.Abort(_('working dir not at a head rev - '
2618 raise util.Abort(_('working dir not at a head rev - '
2616 'use "hg update" or merge with an explicit rev'))
2619 'use "hg update" or merge with an explicit rev'))
2617 node = parent == bheads[0] and bheads[-1] or bheads[0]
2620 node = parent == bheads[0] and bheads[-1] or bheads[0]
2618
2621
2619 if opts.get('preview'):
2622 if opts.get('preview'):
2620 # find nodes that are ancestors of p2 but not of p1
2623 # find nodes that are ancestors of p2 but not of p1
2621 p1 = repo.lookup('.')
2624 p1 = repo.lookup('.')
2622 p2 = repo.lookup(node)
2625 p2 = repo.lookup(node)
2623 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2626 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2624
2627
2625 displayer = cmdutil.show_changeset(ui, repo, opts)
2628 displayer = cmdutil.show_changeset(ui, repo, opts)
2626 for node in nodes:
2629 for node in nodes:
2627 displayer.show(repo[node])
2630 displayer.show(repo[node])
2628 displayer.close()
2631 displayer.close()
2629 return 0
2632 return 0
2630
2633
2631 return hg.merge(repo, node, force=opts.get('force'))
2634 return hg.merge(repo, node, force=opts.get('force'))
2632
2635
2633 def outgoing(ui, repo, dest=None, **opts):
2636 def outgoing(ui, repo, dest=None, **opts):
2634 """show changesets not found in the destination
2637 """show changesets not found in the destination
2635
2638
2636 Show changesets not found in the specified destination repository
2639 Show changesets not found in the specified destination repository
2637 or the default push location. These are the changesets that would
2640 or the default push location. These are the changesets that would
2638 be pushed if a push was requested.
2641 be pushed if a push was requested.
2639
2642
2640 See pull for details of valid destination formats.
2643 See pull for details of valid destination formats.
2641
2644
2642 Returns 0 if there are outgoing changes, 1 otherwise.
2645 Returns 0 if there are outgoing changes, 1 otherwise.
2643 """
2646 """
2644 limit = cmdutil.loglimit(opts)
2647 limit = cmdutil.loglimit(opts)
2645 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2648 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2646 dest, branches = hg.parseurl(dest, opts.get('branch'))
2649 dest, branches = hg.parseurl(dest, opts.get('branch'))
2647 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2650 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2648 if revs:
2651 if revs:
2649 revs = [repo.lookup(rev) for rev in revs]
2652 revs = [repo.lookup(rev) for rev in revs]
2650
2653
2651 other = hg.repository(hg.remoteui(repo, opts), dest)
2654 other = hg.repository(hg.remoteui(repo, opts), dest)
2652 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2655 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2653 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
2656 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
2654 if not o:
2657 if not o:
2655 ui.status(_("no changes found\n"))
2658 ui.status(_("no changes found\n"))
2656 return 1
2659 return 1
2657 o = repo.changelog.nodesbetween(o, revs)[0]
2660 o = repo.changelog.nodesbetween(o, revs)[0]
2658 if opts.get('newest_first'):
2661 if opts.get('newest_first'):
2659 o.reverse()
2662 o.reverse()
2660 displayer = cmdutil.show_changeset(ui, repo, opts)
2663 displayer = cmdutil.show_changeset(ui, repo, opts)
2661 count = 0
2664 count = 0
2662 for n in o:
2665 for n in o:
2663 if limit is not None and count >= limit:
2666 if limit is not None and count >= limit:
2664 break
2667 break
2665 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2668 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2666 if opts.get('no_merges') and len(parents) == 2:
2669 if opts.get('no_merges') and len(parents) == 2:
2667 continue
2670 continue
2668 count += 1
2671 count += 1
2669 displayer.show(repo[n])
2672 displayer.show(repo[n])
2670 displayer.close()
2673 displayer.close()
2671
2674
2672 def parents(ui, repo, file_=None, **opts):
2675 def parents(ui, repo, file_=None, **opts):
2673 """show the parents of the working directory or revision
2676 """show the parents of the working directory or revision
2674
2677
2675 Print the working directory's parent revisions. If a revision is
2678 Print the working directory's parent revisions. If a revision is
2676 given via -r/--rev, the parent of that revision will be printed.
2679 given via -r/--rev, the parent of that revision will be printed.
2677 If a file argument is given, the revision in which the file was
2680 If a file argument is given, the revision in which the file was
2678 last changed (before the working directory revision or the
2681 last changed (before the working directory revision or the
2679 argument to --rev if given) is printed.
2682 argument to --rev if given) is printed.
2680
2683
2681 Returns 0 on success.
2684 Returns 0 on success.
2682 """
2685 """
2683 rev = opts.get('rev')
2686 rev = opts.get('rev')
2684 if rev:
2687 if rev:
2685 ctx = repo[rev]
2688 ctx = repo[rev]
2686 else:
2689 else:
2687 ctx = repo[None]
2690 ctx = repo[None]
2688
2691
2689 if file_:
2692 if file_:
2690 m = cmdutil.match(repo, (file_,), opts)
2693 m = cmdutil.match(repo, (file_,), opts)
2691 if m.anypats() or len(m.files()) != 1:
2694 if m.anypats() or len(m.files()) != 1:
2692 raise util.Abort(_('can only specify an explicit filename'))
2695 raise util.Abort(_('can only specify an explicit filename'))
2693 file_ = m.files()[0]
2696 file_ = m.files()[0]
2694 filenodes = []
2697 filenodes = []
2695 for cp in ctx.parents():
2698 for cp in ctx.parents():
2696 if not cp:
2699 if not cp:
2697 continue
2700 continue
2698 try:
2701 try:
2699 filenodes.append(cp.filenode(file_))
2702 filenodes.append(cp.filenode(file_))
2700 except error.LookupError:
2703 except error.LookupError:
2701 pass
2704 pass
2702 if not filenodes:
2705 if not filenodes:
2703 raise util.Abort(_("'%s' not found in manifest!") % file_)
2706 raise util.Abort(_("'%s' not found in manifest!") % file_)
2704 fl = repo.file(file_)
2707 fl = repo.file(file_)
2705 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2708 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2706 else:
2709 else:
2707 p = [cp.node() for cp in ctx.parents()]
2710 p = [cp.node() for cp in ctx.parents()]
2708
2711
2709 displayer = cmdutil.show_changeset(ui, repo, opts)
2712 displayer = cmdutil.show_changeset(ui, repo, opts)
2710 for n in p:
2713 for n in p:
2711 if n != nullid:
2714 if n != nullid:
2712 displayer.show(repo[n])
2715 displayer.show(repo[n])
2713 displayer.close()
2716 displayer.close()
2714
2717
2715 def paths(ui, repo, search=None):
2718 def paths(ui, repo, search=None):
2716 """show aliases for remote repositories
2719 """show aliases for remote repositories
2717
2720
2718 Show definition of symbolic path name NAME. If no name is given,
2721 Show definition of symbolic path name NAME. If no name is given,
2719 show definition of all available names.
2722 show definition of all available names.
2720
2723
2721 Path names are defined in the [paths] section of
2724 Path names are defined in the [paths] section of
2722 ``/etc/mercurial/hgrc`` and ``$HOME/.hgrc``. If run inside a
2725 ``/etc/mercurial/hgrc`` and ``$HOME/.hgrc``. If run inside a
2723 repository, ``.hg/hgrc`` is used, too.
2726 repository, ``.hg/hgrc`` is used, too.
2724
2727
2725 The path names ``default`` and ``default-push`` have a special
2728 The path names ``default`` and ``default-push`` have a special
2726 meaning. When performing a push or pull operation, they are used
2729 meaning. When performing a push or pull operation, they are used
2727 as fallbacks if no location is specified on the command-line.
2730 as fallbacks if no location is specified on the command-line.
2728 When ``default-push`` is set, it will be used for push and
2731 When ``default-push`` is set, it will be used for push and
2729 ``default`` will be used for pull; otherwise ``default`` is used
2732 ``default`` will be used for pull; otherwise ``default`` is used
2730 as the fallback for both. When cloning a repository, the clone
2733 as the fallback for both. When cloning a repository, the clone
2731 source is written as ``default`` in ``.hg/hgrc``. Note that
2734 source is written as ``default`` in ``.hg/hgrc``. Note that
2732 ``default`` and ``default-push`` apply to all inbound (e.g.
2735 ``default`` and ``default-push`` apply to all inbound (e.g.
2733 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2736 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2734 :hg:`bundle`) operations.
2737 :hg:`bundle`) operations.
2735
2738
2736 See :hg:`help urls` for more information.
2739 See :hg:`help urls` for more information.
2737
2740
2738 Returns 0 on success.
2741 Returns 0 on success.
2739 """
2742 """
2740 if search:
2743 if search:
2741 for name, path in ui.configitems("paths"):
2744 for name, path in ui.configitems("paths"):
2742 if name == search:
2745 if name == search:
2743 ui.write("%s\n" % url.hidepassword(path))
2746 ui.write("%s\n" % url.hidepassword(path))
2744 return
2747 return
2745 ui.warn(_("not found!\n"))
2748 ui.warn(_("not found!\n"))
2746 return 1
2749 return 1
2747 else:
2750 else:
2748 for name, path in ui.configitems("paths"):
2751 for name, path in ui.configitems("paths"):
2749 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2752 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2750
2753
2751 def postincoming(ui, repo, modheads, optupdate, checkout):
2754 def postincoming(ui, repo, modheads, optupdate, checkout):
2752 if modheads == 0:
2755 if modheads == 0:
2753 return
2756 return
2754 if optupdate:
2757 if optupdate:
2755 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2758 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2756 return hg.update(repo, checkout)
2759 return hg.update(repo, checkout)
2757 else:
2760 else:
2758 ui.status(_("not updating, since new heads added\n"))
2761 ui.status(_("not updating, since new heads added\n"))
2759 if modheads > 1:
2762 if modheads > 1:
2760 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2763 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2761 else:
2764 else:
2762 ui.status(_("(run 'hg update' to get a working copy)\n"))
2765 ui.status(_("(run 'hg update' to get a working copy)\n"))
2763
2766
2764 def pull(ui, repo, source="default", **opts):
2767 def pull(ui, repo, source="default", **opts):
2765 """pull changes from the specified source
2768 """pull changes from the specified source
2766
2769
2767 Pull changes from a remote repository to a local one.
2770 Pull changes from a remote repository to a local one.
2768
2771
2769 This finds all changes from the repository at the specified path
2772 This finds all changes from the repository at the specified path
2770 or URL and adds them to a local repository (the current one unless
2773 or URL and adds them to a local repository (the current one unless
2771 -R is specified). By default, this does not update the copy of the
2774 -R is specified). By default, this does not update the copy of the
2772 project in the working directory.
2775 project in the working directory.
2773
2776
2774 Use :hg:`incoming` if you want to see what would have been added
2777 Use :hg:`incoming` if you want to see what would have been added
2775 by a pull at the time you issued this command. If you then decide
2778 by a pull at the time you issued this command. If you then decide
2776 to add those changes to the repository, you should use :hg:`pull
2779 to add those changes to the repository, you should use :hg:`pull
2777 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2780 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2778
2781
2779 If SOURCE is omitted, the 'default' path will be used.
2782 If SOURCE is omitted, the 'default' path will be used.
2780 See :hg:`help urls` for more information.
2783 See :hg:`help urls` for more information.
2781
2784
2782 Returns 0 on success, 1 if an update had unresolved files.
2785 Returns 0 on success, 1 if an update had unresolved files.
2783 """
2786 """
2784 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2787 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2785 other = hg.repository(hg.remoteui(repo, opts), source)
2788 other = hg.repository(hg.remoteui(repo, opts), source)
2786 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2789 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2787 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2790 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2788 if revs:
2791 if revs:
2789 try:
2792 try:
2790 revs = [other.lookup(rev) for rev in revs]
2793 revs = [other.lookup(rev) for rev in revs]
2791 except error.CapabilityError:
2794 except error.CapabilityError:
2792 err = _("Other repository doesn't support revision lookup, "
2795 err = _("Other repository doesn't support revision lookup, "
2793 "so a rev cannot be specified.")
2796 "so a rev cannot be specified.")
2794 raise util.Abort(err)
2797 raise util.Abort(err)
2795
2798
2796 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2799 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2797 if checkout:
2800 if checkout:
2798 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2801 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2799 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2802 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2800
2803
2801 def push(ui, repo, dest=None, **opts):
2804 def push(ui, repo, dest=None, **opts):
2802 """push changes to the specified destination
2805 """push changes to the specified destination
2803
2806
2804 Push changesets from the local repository to the specified
2807 Push changesets from the local repository to the specified
2805 destination.
2808 destination.
2806
2809
2807 This operation is symmetrical to pull: it is identical to a pull
2810 This operation is symmetrical to pull: it is identical to a pull
2808 in the destination repository from the current one.
2811 in the destination repository from the current one.
2809
2812
2810 By default, push will not allow creation of new heads at the
2813 By default, push will not allow creation of new heads at the
2811 destination, since multiple heads would make it unclear which head
2814 destination, since multiple heads would make it unclear which head
2812 to use. In this situation, it is recommended to pull and merge
2815 to use. In this situation, it is recommended to pull and merge
2813 before pushing.
2816 before pushing.
2814
2817
2815 Use --new-branch if you want to allow push to create a new named
2818 Use --new-branch if you want to allow push to create a new named
2816 branch that is not present at the destination. This allows you to
2819 branch that is not present at the destination. This allows you to
2817 only create a new branch without forcing other changes.
2820 only create a new branch without forcing other changes.
2818
2821
2819 Use -f/--force to override the default behavior and push all
2822 Use -f/--force to override the default behavior and push all
2820 changesets on all branches.
2823 changesets on all branches.
2821
2824
2822 If -r/--rev is used, the specified revision and all its ancestors
2825 If -r/--rev is used, the specified revision and all its ancestors
2823 will be pushed to the remote repository.
2826 will be pushed to the remote repository.
2824
2827
2825 Please see :hg:`help urls` for important details about ``ssh://``
2828 Please see :hg:`help urls` for important details about ``ssh://``
2826 URLs. If DESTINATION is omitted, a default path will be used.
2829 URLs. If DESTINATION is omitted, a default path will be used.
2827
2830
2828 Returns 0 if push was successful, 1 if nothing to push.
2831 Returns 0 if push was successful, 1 if nothing to push.
2829 """
2832 """
2830 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2833 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2831 dest, branches = hg.parseurl(dest, opts.get('branch'))
2834 dest, branches = hg.parseurl(dest, opts.get('branch'))
2832 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2835 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2833 other = hg.repository(hg.remoteui(repo, opts), dest)
2836 other = hg.repository(hg.remoteui(repo, opts), dest)
2834 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2837 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2835 if revs:
2838 if revs:
2836 revs = [repo.lookup(rev) for rev in revs]
2839 revs = [repo.lookup(rev) for rev in revs]
2837
2840
2838 # push subrepos depth-first for coherent ordering
2841 # push subrepos depth-first for coherent ordering
2839 c = repo['']
2842 c = repo['']
2840 subs = c.substate # only repos that are committed
2843 subs = c.substate # only repos that are committed
2841 for s in sorted(subs):
2844 for s in sorted(subs):
2842 if not c.sub(s).push(opts.get('force')):
2845 if not c.sub(s).push(opts.get('force')):
2843 return False
2846 return False
2844
2847
2845 r = repo.push(other, opts.get('force'), revs=revs,
2848 r = repo.push(other, opts.get('force'), revs=revs,
2846 newbranch=opts.get('new_branch'))
2849 newbranch=opts.get('new_branch'))
2847 return r == 0
2850 return r == 0
2848
2851
2849 def recover(ui, repo):
2852 def recover(ui, repo):
2850 """roll back an interrupted transaction
2853 """roll back an interrupted transaction
2851
2854
2852 Recover from an interrupted commit or pull.
2855 Recover from an interrupted commit or pull.
2853
2856
2854 This command tries to fix the repository status after an
2857 This command tries to fix the repository status after an
2855 interrupted operation. It should only be necessary when Mercurial
2858 interrupted operation. It should only be necessary when Mercurial
2856 suggests it.
2859 suggests it.
2857
2860
2858 Returns 0 if successful, 1 if nothing to recover or verify fails.
2861 Returns 0 if successful, 1 if nothing to recover or verify fails.
2859 """
2862 """
2860 if repo.recover():
2863 if repo.recover():
2861 return hg.verify(repo)
2864 return hg.verify(repo)
2862 return 1
2865 return 1
2863
2866
2864 def remove(ui, repo, *pats, **opts):
2867 def remove(ui, repo, *pats, **opts):
2865 """remove the specified files on the next commit
2868 """remove the specified files on the next commit
2866
2869
2867 Schedule the indicated files for removal from the repository.
2870 Schedule the indicated files for removal from the repository.
2868
2871
2869 This only removes files from the current branch, not from the
2872 This only removes files from the current branch, not from the
2870 entire project history. -A/--after can be used to remove only
2873 entire project history. -A/--after can be used to remove only
2871 files that have already been deleted, -f/--force can be used to
2874 files that have already been deleted, -f/--force can be used to
2872 force deletion, and -Af can be used to remove files from the next
2875 force deletion, and -Af can be used to remove files from the next
2873 revision without deleting them from the working directory.
2876 revision without deleting them from the working directory.
2874
2877
2875 The following table details the behavior of remove for different
2878 The following table details the behavior of remove for different
2876 file states (columns) and option combinations (rows). The file
2879 file states (columns) and option combinations (rows). The file
2877 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2880 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2878 reported by :hg:`status`). The actions are Warn, Remove (from
2881 reported by :hg:`status`). The actions are Warn, Remove (from
2879 branch) and Delete (from disk)::
2882 branch) and Delete (from disk)::
2880
2883
2881 A C M !
2884 A C M !
2882 none W RD W R
2885 none W RD W R
2883 -f R RD RD R
2886 -f R RD RD R
2884 -A W W W R
2887 -A W W W R
2885 -Af R R R R
2888 -Af R R R R
2886
2889
2887 This command schedules the files to be removed at the next commit.
2890 This command schedules the files to be removed at the next commit.
2888 To undo a remove before that, see :hg:`revert`.
2891 To undo a remove before that, see :hg:`revert`.
2889
2892
2890 Returns 0 on success, 1 if any warnings encountered.
2893 Returns 0 on success, 1 if any warnings encountered.
2891 """
2894 """
2892
2895
2893 ret = 0
2896 ret = 0
2894 after, force = opts.get('after'), opts.get('force')
2897 after, force = opts.get('after'), opts.get('force')
2895 if not pats and not after:
2898 if not pats and not after:
2896 raise util.Abort(_('no files specified'))
2899 raise util.Abort(_('no files specified'))
2897
2900
2898 m = cmdutil.match(repo, pats, opts)
2901 m = cmdutil.match(repo, pats, opts)
2899 s = repo.status(match=m, clean=True)
2902 s = repo.status(match=m, clean=True)
2900 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2903 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2901
2904
2902 for f in m.files():
2905 for f in m.files():
2903 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2906 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2904 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2907 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2905 ret = 1
2908 ret = 1
2906
2909
2907 def warn(files, reason):
2910 def warn(files, reason):
2908 for f in files:
2911 for f in files:
2909 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2912 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2910 % (m.rel(f), reason))
2913 % (m.rel(f), reason))
2911 ret = 1
2914 ret = 1
2912
2915
2913 if force:
2916 if force:
2914 remove, forget = modified + deleted + clean, added
2917 remove, forget = modified + deleted + clean, added
2915 elif after:
2918 elif after:
2916 remove, forget = deleted, []
2919 remove, forget = deleted, []
2917 warn(modified + added + clean, _('still exists'))
2920 warn(modified + added + clean, _('still exists'))
2918 else:
2921 else:
2919 remove, forget = deleted + clean, []
2922 remove, forget = deleted + clean, []
2920 warn(modified, _('is modified'))
2923 warn(modified, _('is modified'))
2921 warn(added, _('has been marked for add'))
2924 warn(added, _('has been marked for add'))
2922
2925
2923 for f in sorted(remove + forget):
2926 for f in sorted(remove + forget):
2924 if ui.verbose or not m.exact(f):
2927 if ui.verbose or not m.exact(f):
2925 ui.status(_('removing %s\n') % m.rel(f))
2928 ui.status(_('removing %s\n') % m.rel(f))
2926
2929
2927 repo[None].forget(forget)
2930 repo[None].forget(forget)
2928 repo[None].remove(remove, unlink=not after)
2931 repo[None].remove(remove, unlink=not after)
2929 return ret
2932 return ret
2930
2933
2931 def rename(ui, repo, *pats, **opts):
2934 def rename(ui, repo, *pats, **opts):
2932 """rename files; equivalent of copy + remove
2935 """rename files; equivalent of copy + remove
2933
2936
2934 Mark dest as copies of sources; mark sources for deletion. If dest
2937 Mark dest as copies of sources; mark sources for deletion. If dest
2935 is a directory, copies are put in that directory. If dest is a
2938 is a directory, copies are put in that directory. If dest is a
2936 file, there can only be one source.
2939 file, there can only be one source.
2937
2940
2938 By default, this command copies the contents of files as they
2941 By default, this command copies the contents of files as they
2939 exist in the working directory. If invoked with -A/--after, the
2942 exist in the working directory. If invoked with -A/--after, the
2940 operation is recorded, but no copying is performed.
2943 operation is recorded, but no copying is performed.
2941
2944
2942 This command takes effect at the next commit. To undo a rename
2945 This command takes effect at the next commit. To undo a rename
2943 before that, see :hg:`revert`.
2946 before that, see :hg:`revert`.
2944
2947
2945 Returns 0 on success, 1 if errors are encountered.
2948 Returns 0 on success, 1 if errors are encountered.
2946 """
2949 """
2947 wlock = repo.wlock(False)
2950 wlock = repo.wlock(False)
2948 try:
2951 try:
2949 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2952 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2950 finally:
2953 finally:
2951 wlock.release()
2954 wlock.release()
2952
2955
2953 def resolve(ui, repo, *pats, **opts):
2956 def resolve(ui, repo, *pats, **opts):
2954 """various operations to help finish a merge
2957 """various operations to help finish a merge
2955
2958
2956 This command includes several actions that are often useful while
2959 This command includes several actions that are often useful while
2957 performing a merge, after running ``merge`` but before running
2960 performing a merge, after running ``merge`` but before running
2958 ``commit``. (It is only meaningful if your working directory has
2961 ``commit``. (It is only meaningful if your working directory has
2959 two parents.) It is most relevant for merges with unresolved
2962 two parents.) It is most relevant for merges with unresolved
2960 conflicts, which are typically a result of non-interactive merging with
2963 conflicts, which are typically a result of non-interactive merging with
2961 ``internal:merge`` or a command-line merge tool like ``diff3``.
2964 ``internal:merge`` or a command-line merge tool like ``diff3``.
2962
2965
2963 The available actions are:
2966 The available actions are:
2964
2967
2965 1) list files that were merged with conflicts (U, for unresolved)
2968 1) list files that were merged with conflicts (U, for unresolved)
2966 and without conflicts (R, for resolved): ``hg resolve -l``
2969 and without conflicts (R, for resolved): ``hg resolve -l``
2967 (this is like ``status`` for merges)
2970 (this is like ``status`` for merges)
2968 2) record that you have resolved conflicts in certain files:
2971 2) record that you have resolved conflicts in certain files:
2969 ``hg resolve -m [file ...]`` (default: mark all unresolved files)
2972 ``hg resolve -m [file ...]`` (default: mark all unresolved files)
2970 3) forget that you have resolved conflicts in certain files:
2973 3) forget that you have resolved conflicts in certain files:
2971 ``hg resolve -u [file ...]`` (default: unmark all resolved files)
2974 ``hg resolve -u [file ...]`` (default: unmark all resolved files)
2972 4) discard your current attempt(s) at resolving conflicts and
2975 4) discard your current attempt(s) at resolving conflicts and
2973 restart the merge from scratch: ``hg resolve file...``
2976 restart the merge from scratch: ``hg resolve file...``
2974 (or ``-a`` for all unresolved files)
2977 (or ``-a`` for all unresolved files)
2975
2978
2976 Note that Mercurial will not let you commit files with unresolved merge
2979 Note that Mercurial will not let you commit files with unresolved merge
2977 conflicts. You must use ``hg resolve -m ...`` before you can commit
2980 conflicts. You must use ``hg resolve -m ...`` before you can commit
2978 after a conflicting merge.
2981 after a conflicting merge.
2979
2982
2980 Returns 0 on success, 1 if any files fail a resolve attempt.
2983 Returns 0 on success, 1 if any files fail a resolve attempt.
2981 """
2984 """
2982
2985
2983 all, mark, unmark, show, nostatus = \
2986 all, mark, unmark, show, nostatus = \
2984 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2987 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2985
2988
2986 if (show and (mark or unmark)) or (mark and unmark):
2989 if (show and (mark or unmark)) or (mark and unmark):
2987 raise util.Abort(_("too many options specified"))
2990 raise util.Abort(_("too many options specified"))
2988 if pats and all:
2991 if pats and all:
2989 raise util.Abort(_("can't specify --all and patterns"))
2992 raise util.Abort(_("can't specify --all and patterns"))
2990 if not (all or pats or show or mark or unmark):
2993 if not (all or pats or show or mark or unmark):
2991 raise util.Abort(_('no files or directories specified; '
2994 raise util.Abort(_('no files or directories specified; '
2992 'use --all to remerge all files'))
2995 'use --all to remerge all files'))
2993
2996
2994 ms = mergemod.mergestate(repo)
2997 ms = mergemod.mergestate(repo)
2995 m = cmdutil.match(repo, pats, opts)
2998 m = cmdutil.match(repo, pats, opts)
2996 ret = 0
2999 ret = 0
2997
3000
2998 for f in ms:
3001 for f in ms:
2999 if m(f):
3002 if m(f):
3000 if show:
3003 if show:
3001 if nostatus:
3004 if nostatus:
3002 ui.write("%s\n" % f)
3005 ui.write("%s\n" % f)
3003 else:
3006 else:
3004 ui.write("%s %s\n" % (ms[f].upper(), f),
3007 ui.write("%s %s\n" % (ms[f].upper(), f),
3005 label='resolve.' +
3008 label='resolve.' +
3006 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3009 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3007 elif mark:
3010 elif mark:
3008 ms.mark(f, "r")
3011 ms.mark(f, "r")
3009 elif unmark:
3012 elif unmark:
3010 ms.mark(f, "u")
3013 ms.mark(f, "u")
3011 else:
3014 else:
3012 wctx = repo[None]
3015 wctx = repo[None]
3013 mctx = wctx.parents()[-1]
3016 mctx = wctx.parents()[-1]
3014
3017
3015 # backup pre-resolve (merge uses .orig for its own purposes)
3018 # backup pre-resolve (merge uses .orig for its own purposes)
3016 a = repo.wjoin(f)
3019 a = repo.wjoin(f)
3017 util.copyfile(a, a + ".resolve")
3020 util.copyfile(a, a + ".resolve")
3018
3021
3019 # resolve file
3022 # resolve file
3020 if ms.resolve(f, wctx, mctx):
3023 if ms.resolve(f, wctx, mctx):
3021 ret = 1
3024 ret = 1
3022
3025
3023 # replace filemerge's .orig file with our resolve file
3026 # replace filemerge's .orig file with our resolve file
3024 util.rename(a + ".resolve", a + ".orig")
3027 util.rename(a + ".resolve", a + ".orig")
3025 return ret
3028 return ret
3026
3029
3027 def revert(ui, repo, *pats, **opts):
3030 def revert(ui, repo, *pats, **opts):
3028 """restore individual files or directories to an earlier state
3031 """restore individual files or directories to an earlier state
3029
3032
3030 NOTE: This command is most likely not what you are looking for. revert
3033 NOTE: This command is most likely not what you are looking for. revert
3031 will partially overwrite content in the working directory without changing
3034 will partially overwrite content in the working directory without changing
3032 the working directory parents. Use :hg:`update -r rev` to check out earlier
3035 the working directory parents. Use :hg:`update -r rev` to check out earlier
3033 revisions, or :hg:`update --clean .` to undo a merge which has added
3036 revisions, or :hg:`update --clean .` to undo a merge which has added
3034 another parent.
3037 another parent.
3035
3038
3036 With no revision specified, revert the named files or directories
3039 With no revision specified, revert the named files or directories
3037 to the contents they had in the parent of the working directory.
3040 to the contents they had in the parent of the working directory.
3038 This restores the contents of the affected files to an unmodified
3041 This restores the contents of the affected files to an unmodified
3039 state and unschedules adds, removes, copies, and renames. If the
3042 state and unschedules adds, removes, copies, and renames. If the
3040 working directory has two parents, you must explicitly specify a
3043 working directory has two parents, you must explicitly specify a
3041 revision.
3044 revision.
3042
3045
3043 Using the -r/--rev option, revert the given files or directories
3046 Using the -r/--rev option, revert the given files or directories
3044 to their contents as of a specific revision. This can be helpful
3047 to their contents as of a specific revision. This can be helpful
3045 to "roll back" some or all of an earlier change. See :hg:`help
3048 to "roll back" some or all of an earlier change. See :hg:`help
3046 dates` for a list of formats valid for -d/--date.
3049 dates` for a list of formats valid for -d/--date.
3047
3050
3048 Revert modifies the working directory. It does not commit any
3051 Revert modifies the working directory. It does not commit any
3049 changes, or change the parent of the working directory. If you
3052 changes, or change the parent of the working directory. If you
3050 revert to a revision other than the parent of the working
3053 revert to a revision other than the parent of the working
3051 directory, the reverted files will thus appear modified
3054 directory, the reverted files will thus appear modified
3052 afterwards.
3055 afterwards.
3053
3056
3054 If a file has been deleted, it is restored. If the executable mode
3057 If a file has been deleted, it is restored. If the executable mode
3055 of a file was changed, it is reset.
3058 of a file was changed, it is reset.
3056
3059
3057 If names are given, all files matching the names are reverted.
3060 If names are given, all files matching the names are reverted.
3058 If no arguments are given, no files are reverted.
3061 If no arguments are given, no files are reverted.
3059
3062
3060 Modified files are saved with a .orig suffix before reverting.
3063 Modified files are saved with a .orig suffix before reverting.
3061 To disable these backups, use --no-backup.
3064 To disable these backups, use --no-backup.
3062
3065
3063 Returns 0 on success.
3066 Returns 0 on success.
3064 """
3067 """
3065
3068
3066 if opts["date"]:
3069 if opts["date"]:
3067 if opts["rev"]:
3070 if opts["rev"]:
3068 raise util.Abort(_("you can't specify a revision and a date"))
3071 raise util.Abort(_("you can't specify a revision and a date"))
3069 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3072 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3070
3073
3071 if not pats and not opts.get('all'):
3074 if not pats and not opts.get('all'):
3072 raise util.Abort(_('no files or directories specified; '
3075 raise util.Abort(_('no files or directories specified; '
3073 'use --all to revert the whole repo'))
3076 'use --all to revert the whole repo'))
3074
3077
3075 parent, p2 = repo.dirstate.parents()
3078 parent, p2 = repo.dirstate.parents()
3076 if not opts.get('rev') and p2 != nullid:
3079 if not opts.get('rev') and p2 != nullid:
3077 raise util.Abort(_('uncommitted merge - please provide a '
3080 raise util.Abort(_('uncommitted merge - please provide a '
3078 'specific revision'))
3081 'specific revision'))
3079 ctx = repo[opts.get('rev')]
3082 ctx = repo[opts.get('rev')]
3080 node = ctx.node()
3083 node = ctx.node()
3081 mf = ctx.manifest()
3084 mf = ctx.manifest()
3082 if node == parent:
3085 if node == parent:
3083 pmf = mf
3086 pmf = mf
3084 else:
3087 else:
3085 pmf = None
3088 pmf = None
3086
3089
3087 # need all matching names in dirstate and manifest of target rev,
3090 # need all matching names in dirstate and manifest of target rev,
3088 # so have to walk both. do not print errors if files exist in one
3091 # so have to walk both. do not print errors if files exist in one
3089 # but not other.
3092 # but not other.
3090
3093
3091 names = {}
3094 names = {}
3092
3095
3093 wlock = repo.wlock()
3096 wlock = repo.wlock()
3094 try:
3097 try:
3095 # walk dirstate.
3098 # walk dirstate.
3096
3099
3097 m = cmdutil.match(repo, pats, opts)
3100 m = cmdutil.match(repo, pats, opts)
3098 m.bad = lambda x, y: False
3101 m.bad = lambda x, y: False
3099 for abs in repo.walk(m):
3102 for abs in repo.walk(m):
3100 names[abs] = m.rel(abs), m.exact(abs)
3103 names[abs] = m.rel(abs), m.exact(abs)
3101
3104
3102 # walk target manifest.
3105 # walk target manifest.
3103
3106
3104 def badfn(path, msg):
3107 def badfn(path, msg):
3105 if path in names:
3108 if path in names:
3106 return
3109 return
3107 path_ = path + '/'
3110 path_ = path + '/'
3108 for f in names:
3111 for f in names:
3109 if f.startswith(path_):
3112 if f.startswith(path_):
3110 return
3113 return
3111 ui.warn("%s: %s\n" % (m.rel(path), msg))
3114 ui.warn("%s: %s\n" % (m.rel(path), msg))
3112
3115
3113 m = cmdutil.match(repo, pats, opts)
3116 m = cmdutil.match(repo, pats, opts)
3114 m.bad = badfn
3117 m.bad = badfn
3115 for abs in repo[node].walk(m):
3118 for abs in repo[node].walk(m):
3116 if abs not in names:
3119 if abs not in names:
3117 names[abs] = m.rel(abs), m.exact(abs)
3120 names[abs] = m.rel(abs), m.exact(abs)
3118
3121
3119 m = cmdutil.matchfiles(repo, names)
3122 m = cmdutil.matchfiles(repo, names)
3120 changes = repo.status(match=m)[:4]
3123 changes = repo.status(match=m)[:4]
3121 modified, added, removed, deleted = map(set, changes)
3124 modified, added, removed, deleted = map(set, changes)
3122
3125
3123 # if f is a rename, also revert the source
3126 # if f is a rename, also revert the source
3124 cwd = repo.getcwd()
3127 cwd = repo.getcwd()
3125 for f in added:
3128 for f in added:
3126 src = repo.dirstate.copied(f)
3129 src = repo.dirstate.copied(f)
3127 if src and src not in names and repo.dirstate[src] == 'r':
3130 if src and src not in names and repo.dirstate[src] == 'r':
3128 removed.add(src)
3131 removed.add(src)
3129 names[src] = (repo.pathto(src, cwd), True)
3132 names[src] = (repo.pathto(src, cwd), True)
3130
3133
3131 def removeforget(abs):
3134 def removeforget(abs):
3132 if repo.dirstate[abs] == 'a':
3135 if repo.dirstate[abs] == 'a':
3133 return _('forgetting %s\n')
3136 return _('forgetting %s\n')
3134 return _('removing %s\n')
3137 return _('removing %s\n')
3135
3138
3136 revert = ([], _('reverting %s\n'))
3139 revert = ([], _('reverting %s\n'))
3137 add = ([], _('adding %s\n'))
3140 add = ([], _('adding %s\n'))
3138 remove = ([], removeforget)
3141 remove = ([], removeforget)
3139 undelete = ([], _('undeleting %s\n'))
3142 undelete = ([], _('undeleting %s\n'))
3140
3143
3141 disptable = (
3144 disptable = (
3142 # dispatch table:
3145 # dispatch table:
3143 # file state
3146 # file state
3144 # action if in target manifest
3147 # action if in target manifest
3145 # action if not in target manifest
3148 # action if not in target manifest
3146 # make backup if in target manifest
3149 # make backup if in target manifest
3147 # make backup if not in target manifest
3150 # make backup if not in target manifest
3148 (modified, revert, remove, True, True),
3151 (modified, revert, remove, True, True),
3149 (added, revert, remove, True, False),
3152 (added, revert, remove, True, False),
3150 (removed, undelete, None, False, False),
3153 (removed, undelete, None, False, False),
3151 (deleted, revert, remove, False, False),
3154 (deleted, revert, remove, False, False),
3152 )
3155 )
3153
3156
3154 for abs, (rel, exact) in sorted(names.items()):
3157 for abs, (rel, exact) in sorted(names.items()):
3155 mfentry = mf.get(abs)
3158 mfentry = mf.get(abs)
3156 target = repo.wjoin(abs)
3159 target = repo.wjoin(abs)
3157 def handle(xlist, dobackup):
3160 def handle(xlist, dobackup):
3158 xlist[0].append(abs)
3161 xlist[0].append(abs)
3159 if dobackup and not opts.get('no_backup') and util.lexists(target):
3162 if dobackup and not opts.get('no_backup') and util.lexists(target):
3160 bakname = "%s.orig" % rel
3163 bakname = "%s.orig" % rel
3161 ui.note(_('saving current version of %s as %s\n') %
3164 ui.note(_('saving current version of %s as %s\n') %
3162 (rel, bakname))
3165 (rel, bakname))
3163 if not opts.get('dry_run'):
3166 if not opts.get('dry_run'):
3164 util.copyfile(target, bakname)
3167 util.copyfile(target, bakname)
3165 if ui.verbose or not exact:
3168 if ui.verbose or not exact:
3166 msg = xlist[1]
3169 msg = xlist[1]
3167 if not isinstance(msg, basestring):
3170 if not isinstance(msg, basestring):
3168 msg = msg(abs)
3171 msg = msg(abs)
3169 ui.status(msg % rel)
3172 ui.status(msg % rel)
3170 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3173 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3171 if abs not in table:
3174 if abs not in table:
3172 continue
3175 continue
3173 # file has changed in dirstate
3176 # file has changed in dirstate
3174 if mfentry:
3177 if mfentry:
3175 handle(hitlist, backuphit)
3178 handle(hitlist, backuphit)
3176 elif misslist is not None:
3179 elif misslist is not None:
3177 handle(misslist, backupmiss)
3180 handle(misslist, backupmiss)
3178 break
3181 break
3179 else:
3182 else:
3180 if abs not in repo.dirstate:
3183 if abs not in repo.dirstate:
3181 if mfentry:
3184 if mfentry:
3182 handle(add, True)
3185 handle(add, True)
3183 elif exact:
3186 elif exact:
3184 ui.warn(_('file not managed: %s\n') % rel)
3187 ui.warn(_('file not managed: %s\n') % rel)
3185 continue
3188 continue
3186 # file has not changed in dirstate
3189 # file has not changed in dirstate
3187 if node == parent:
3190 if node == parent:
3188 if exact:
3191 if exact:
3189 ui.warn(_('no changes needed to %s\n') % rel)
3192 ui.warn(_('no changes needed to %s\n') % rel)
3190 continue
3193 continue
3191 if pmf is None:
3194 if pmf is None:
3192 # only need parent manifest in this unlikely case,
3195 # only need parent manifest in this unlikely case,
3193 # so do not read by default
3196 # so do not read by default
3194 pmf = repo[parent].manifest()
3197 pmf = repo[parent].manifest()
3195 if abs in pmf:
3198 if abs in pmf:
3196 if mfentry:
3199 if mfentry:
3197 # if version of file is same in parent and target
3200 # if version of file is same in parent and target
3198 # manifests, do nothing
3201 # manifests, do nothing
3199 if (pmf[abs] != mfentry or
3202 if (pmf[abs] != mfentry or
3200 pmf.flags(abs) != mf.flags(abs)):
3203 pmf.flags(abs) != mf.flags(abs)):
3201 handle(revert, False)
3204 handle(revert, False)
3202 else:
3205 else:
3203 handle(remove, False)
3206 handle(remove, False)
3204
3207
3205 if not opts.get('dry_run'):
3208 if not opts.get('dry_run'):
3206 def checkout(f):
3209 def checkout(f):
3207 fc = ctx[f]
3210 fc = ctx[f]
3208 repo.wwrite(f, fc.data(), fc.flags())
3211 repo.wwrite(f, fc.data(), fc.flags())
3209
3212
3210 audit_path = util.path_auditor(repo.root)
3213 audit_path = util.path_auditor(repo.root)
3211 for f in remove[0]:
3214 for f in remove[0]:
3212 if repo.dirstate[f] == 'a':
3215 if repo.dirstate[f] == 'a':
3213 repo.dirstate.forget(f)
3216 repo.dirstate.forget(f)
3214 continue
3217 continue
3215 audit_path(f)
3218 audit_path(f)
3216 try:
3219 try:
3217 util.unlink(repo.wjoin(f))
3220 util.unlink(repo.wjoin(f))
3218 except OSError:
3221 except OSError:
3219 pass
3222 pass
3220 repo.dirstate.remove(f)
3223 repo.dirstate.remove(f)
3221
3224
3222 normal = None
3225 normal = None
3223 if node == parent:
3226 if node == parent:
3224 # We're reverting to our parent. If possible, we'd like status
3227 # We're reverting to our parent. If possible, we'd like status
3225 # to report the file as clean. We have to use normallookup for
3228 # to report the file as clean. We have to use normallookup for
3226 # merges to avoid losing information about merged/dirty files.
3229 # merges to avoid losing information about merged/dirty files.
3227 if p2 != nullid:
3230 if p2 != nullid:
3228 normal = repo.dirstate.normallookup
3231 normal = repo.dirstate.normallookup
3229 else:
3232 else:
3230 normal = repo.dirstate.normal
3233 normal = repo.dirstate.normal
3231 for f in revert[0]:
3234 for f in revert[0]:
3232 checkout(f)
3235 checkout(f)
3233 if normal:
3236 if normal:
3234 normal(f)
3237 normal(f)
3235
3238
3236 for f in add[0]:
3239 for f in add[0]:
3237 checkout(f)
3240 checkout(f)
3238 repo.dirstate.add(f)
3241 repo.dirstate.add(f)
3239
3242
3240 normal = repo.dirstate.normallookup
3243 normal = repo.dirstate.normallookup
3241 if node == parent and p2 == nullid:
3244 if node == parent and p2 == nullid:
3242 normal = repo.dirstate.normal
3245 normal = repo.dirstate.normal
3243 for f in undelete[0]:
3246 for f in undelete[0]:
3244 checkout(f)
3247 checkout(f)
3245 normal(f)
3248 normal(f)
3246
3249
3247 finally:
3250 finally:
3248 wlock.release()
3251 wlock.release()
3249
3252
3250 def rollback(ui, repo, **opts):
3253 def rollback(ui, repo, **opts):
3251 """roll back the last transaction (dangerous)
3254 """roll back the last transaction (dangerous)
3252
3255
3253 This command should be used with care. There is only one level of
3256 This command should be used with care. There is only one level of
3254 rollback, and there is no way to undo a rollback. It will also
3257 rollback, and there is no way to undo a rollback. It will also
3255 restore the dirstate at the time of the last transaction, losing
3258 restore the dirstate at the time of the last transaction, losing
3256 any dirstate changes since that time. This command does not alter
3259 any dirstate changes since that time. This command does not alter
3257 the working directory.
3260 the working directory.
3258
3261
3259 Transactions are used to encapsulate the effects of all commands
3262 Transactions are used to encapsulate the effects of all commands
3260 that create new changesets or propagate existing changesets into a
3263 that create new changesets or propagate existing changesets into a
3261 repository. For example, the following commands are transactional,
3264 repository. For example, the following commands are transactional,
3262 and their effects can be rolled back:
3265 and their effects can be rolled back:
3263
3266
3264 - commit
3267 - commit
3265 - import
3268 - import
3266 - pull
3269 - pull
3267 - push (with this repository as the destination)
3270 - push (with this repository as the destination)
3268 - unbundle
3271 - unbundle
3269
3272
3270 This command is not intended for use on public repositories. Once
3273 This command is not intended for use on public repositories. Once
3271 changes are visible for pull by other users, rolling a transaction
3274 changes are visible for pull by other users, rolling a transaction
3272 back locally is ineffective (someone else may already have pulled
3275 back locally is ineffective (someone else may already have pulled
3273 the changes). Furthermore, a race is possible with readers of the
3276 the changes). Furthermore, a race is possible with readers of the
3274 repository; for example an in-progress pull from the repository
3277 repository; for example an in-progress pull from the repository
3275 may fail if a rollback is performed.
3278 may fail if a rollback is performed.
3276
3279
3277 Returns 0 on success, 1 if no rollback data is available.
3280 Returns 0 on success, 1 if no rollback data is available.
3278 """
3281 """
3279 return repo.rollback(opts.get('dry_run'))
3282 return repo.rollback(opts.get('dry_run'))
3280
3283
3281 def root(ui, repo):
3284 def root(ui, repo):
3282 """print the root (top) of the current working directory
3285 """print the root (top) of the current working directory
3283
3286
3284 Print the root directory of the current repository.
3287 Print the root directory of the current repository.
3285
3288
3286 Returns 0 on success.
3289 Returns 0 on success.
3287 """
3290 """
3288 ui.write(repo.root + "\n")
3291 ui.write(repo.root + "\n")
3289
3292
3290 def serve(ui, repo, **opts):
3293 def serve(ui, repo, **opts):
3291 """start stand-alone webserver
3294 """start stand-alone webserver
3292
3295
3293 Start a local HTTP repository browser and pull server. You can use
3296 Start a local HTTP repository browser and pull server. You can use
3294 this for ad-hoc sharing and browing of repositories. It is
3297 this for ad-hoc sharing and browing of repositories. It is
3295 recommended to use a real web server to serve a repository for
3298 recommended to use a real web server to serve a repository for
3296 longer periods of time.
3299 longer periods of time.
3297
3300
3298 Please note that the server does not implement access control.
3301 Please note that the server does not implement access control.
3299 This means that, by default, anybody can read from the server and
3302 This means that, by default, anybody can read from the server and
3300 nobody can write to it by default. Set the ``web.allow_push``
3303 nobody can write to it by default. Set the ``web.allow_push``
3301 option to ``*`` to allow everybody to push to the server. You
3304 option to ``*`` to allow everybody to push to the server. You
3302 should use a real web server if you need to authenticate users.
3305 should use a real web server if you need to authenticate users.
3303
3306
3304 By default, the server logs accesses to stdout and errors to
3307 By default, the server logs accesses to stdout and errors to
3305 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3308 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3306 files.
3309 files.
3307
3310
3308 To have the server choose a free port number to listen on, specify
3311 To have the server choose a free port number to listen on, specify
3309 a port number of 0; in this case, the server will print the port
3312 a port number of 0; in this case, the server will print the port
3310 number it uses.
3313 number it uses.
3311
3314
3312 Returns 0 on success.
3315 Returns 0 on success.
3313 """
3316 """
3314
3317
3315 if opts["stdio"]:
3318 if opts["stdio"]:
3316 if repo is None:
3319 if repo is None:
3317 raise error.RepoError(_("There is no Mercurial repository here"
3320 raise error.RepoError(_("There is no Mercurial repository here"
3318 " (.hg not found)"))
3321 " (.hg not found)"))
3319 s = sshserver.sshserver(ui, repo)
3322 s = sshserver.sshserver(ui, repo)
3320 s.serve_forever()
3323 s.serve_forever()
3321
3324
3322 # this way we can check if something was given in the command-line
3325 # this way we can check if something was given in the command-line
3323 if opts.get('port'):
3326 if opts.get('port'):
3324 opts['port'] = int(opts.get('port'))
3327 opts['port'] = int(opts.get('port'))
3325
3328
3326 baseui = repo and repo.baseui or ui
3329 baseui = repo and repo.baseui or ui
3327 optlist = ("name templates style address port prefix ipv6"
3330 optlist = ("name templates style address port prefix ipv6"
3328 " accesslog errorlog certificate encoding")
3331 " accesslog errorlog certificate encoding")
3329 for o in optlist.split():
3332 for o in optlist.split():
3330 val = opts.get(o, '')
3333 val = opts.get(o, '')
3331 if val in (None, ''): # should check against default options instead
3334 if val in (None, ''): # should check against default options instead
3332 continue
3335 continue
3333 baseui.setconfig("web", o, val)
3336 baseui.setconfig("web", o, val)
3334 if repo and repo.ui != baseui:
3337 if repo and repo.ui != baseui:
3335 repo.ui.setconfig("web", o, val)
3338 repo.ui.setconfig("web", o, val)
3336
3339
3337 o = opts.get('web_conf') or opts.get('webdir_conf')
3340 o = opts.get('web_conf') or opts.get('webdir_conf')
3338 if not o:
3341 if not o:
3339 if not repo:
3342 if not repo:
3340 raise error.RepoError(_("There is no Mercurial repository"
3343 raise error.RepoError(_("There is no Mercurial repository"
3341 " here (.hg not found)"))
3344 " here (.hg not found)"))
3342 o = repo.root
3345 o = repo.root
3343
3346
3344 app = hgweb.hgweb(o, baseui=ui)
3347 app = hgweb.hgweb(o, baseui=ui)
3345
3348
3346 class service(object):
3349 class service(object):
3347 def init(self):
3350 def init(self):
3348 util.set_signal_handler()
3351 util.set_signal_handler()
3349 self.httpd = hgweb.server.create_server(ui, app)
3352 self.httpd = hgweb.server.create_server(ui, app)
3350
3353
3351 if opts['port'] and not ui.verbose:
3354 if opts['port'] and not ui.verbose:
3352 return
3355 return
3353
3356
3354 if self.httpd.prefix:
3357 if self.httpd.prefix:
3355 prefix = self.httpd.prefix.strip('/') + '/'
3358 prefix = self.httpd.prefix.strip('/') + '/'
3356 else:
3359 else:
3357 prefix = ''
3360 prefix = ''
3358
3361
3359 port = ':%d' % self.httpd.port
3362 port = ':%d' % self.httpd.port
3360 if port == ':80':
3363 if port == ':80':
3361 port = ''
3364 port = ''
3362
3365
3363 bindaddr = self.httpd.addr
3366 bindaddr = self.httpd.addr
3364 if bindaddr == '0.0.0.0':
3367 if bindaddr == '0.0.0.0':
3365 bindaddr = '*'
3368 bindaddr = '*'
3366 elif ':' in bindaddr: # IPv6
3369 elif ':' in bindaddr: # IPv6
3367 bindaddr = '[%s]' % bindaddr
3370 bindaddr = '[%s]' % bindaddr
3368
3371
3369 fqaddr = self.httpd.fqaddr
3372 fqaddr = self.httpd.fqaddr
3370 if ':' in fqaddr:
3373 if ':' in fqaddr:
3371 fqaddr = '[%s]' % fqaddr
3374 fqaddr = '[%s]' % fqaddr
3372 if opts['port']:
3375 if opts['port']:
3373 write = ui.status
3376 write = ui.status
3374 else:
3377 else:
3375 write = ui.write
3378 write = ui.write
3376 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3379 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3377 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3380 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3378
3381
3379 def run(self):
3382 def run(self):
3380 self.httpd.serve_forever()
3383 self.httpd.serve_forever()
3381
3384
3382 service = service()
3385 service = service()
3383
3386
3384 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3387 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3385
3388
3386 def status(ui, repo, *pats, **opts):
3389 def status(ui, repo, *pats, **opts):
3387 """show changed files in the working directory
3390 """show changed files in the working directory
3388
3391
3389 Show status of files in the repository. If names are given, only
3392 Show status of files in the repository. If names are given, only
3390 files that match are shown. Files that are clean or ignored or
3393 files that match are shown. Files that are clean or ignored or
3391 the source of a copy/move operation, are not listed unless
3394 the source of a copy/move operation, are not listed unless
3392 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3395 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3393 Unless options described with "show only ..." are given, the
3396 Unless options described with "show only ..." are given, the
3394 options -mardu are used.
3397 options -mardu are used.
3395
3398
3396 Option -q/--quiet hides untracked (unknown and ignored) files
3399 Option -q/--quiet hides untracked (unknown and ignored) files
3397 unless explicitly requested with -u/--unknown or -i/--ignored.
3400 unless explicitly requested with -u/--unknown or -i/--ignored.
3398
3401
3399 NOTE: status may appear to disagree with diff if permissions have
3402 NOTE: status may appear to disagree with diff if permissions have
3400 changed or a merge has occurred. The standard diff format does not
3403 changed or a merge has occurred. The standard diff format does not
3401 report permission changes and diff only reports changes relative
3404 report permission changes and diff only reports changes relative
3402 to one merge parent.
3405 to one merge parent.
3403
3406
3404 If one revision is given, it is used as the base revision.
3407 If one revision is given, it is used as the base revision.
3405 If two revisions are given, the differences between them are
3408 If two revisions are given, the differences between them are
3406 shown. The --change option can also be used as a shortcut to list
3409 shown. The --change option can also be used as a shortcut to list
3407 the changed files of a revision from its first parent.
3410 the changed files of a revision from its first parent.
3408
3411
3409 The codes used to show the status of files are::
3412 The codes used to show the status of files are::
3410
3413
3411 M = modified
3414 M = modified
3412 A = added
3415 A = added
3413 R = removed
3416 R = removed
3414 C = clean
3417 C = clean
3415 ! = missing (deleted by non-hg command, but still tracked)
3418 ! = missing (deleted by non-hg command, but still tracked)
3416 ? = not tracked
3419 ? = not tracked
3417 I = ignored
3420 I = ignored
3418 = origin of the previous file listed as A (added)
3421 = origin of the previous file listed as A (added)
3419
3422
3420 Returns 0 on success.
3423 Returns 0 on success.
3421 """
3424 """
3422
3425
3423 revs = opts.get('rev')
3426 revs = opts.get('rev')
3424 change = opts.get('change')
3427 change = opts.get('change')
3425
3428
3426 if revs and change:
3429 if revs and change:
3427 msg = _('cannot specify --rev and --change at the same time')
3430 msg = _('cannot specify --rev and --change at the same time')
3428 raise util.Abort(msg)
3431 raise util.Abort(msg)
3429 elif change:
3432 elif change:
3430 node2 = repo.lookup(change)
3433 node2 = repo.lookup(change)
3431 node1 = repo[node2].parents()[0].node()
3434 node1 = repo[node2].parents()[0].node()
3432 else:
3435 else:
3433 node1, node2 = cmdutil.revpair(repo, revs)
3436 node1, node2 = cmdutil.revpair(repo, revs)
3434
3437
3435 cwd = (pats and repo.getcwd()) or ''
3438 cwd = (pats and repo.getcwd()) or ''
3436 end = opts.get('print0') and '\0' or '\n'
3439 end = opts.get('print0') and '\0' or '\n'
3437 copy = {}
3440 copy = {}
3438 states = 'modified added removed deleted unknown ignored clean'.split()
3441 states = 'modified added removed deleted unknown ignored clean'.split()
3439 show = [k for k in states if opts.get(k)]
3442 show = [k for k in states if opts.get(k)]
3440 if opts.get('all'):
3443 if opts.get('all'):
3441 show += ui.quiet and (states[:4] + ['clean']) or states
3444 show += ui.quiet and (states[:4] + ['clean']) or states
3442 if not show:
3445 if not show:
3443 show = ui.quiet and states[:4] or states[:5]
3446 show = ui.quiet and states[:4] or states[:5]
3444
3447
3445 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3448 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3446 'ignored' in show, 'clean' in show, 'unknown' in show)
3449 'ignored' in show, 'clean' in show, 'unknown' in show)
3447 changestates = zip(states, 'MAR!?IC', stat)
3450 changestates = zip(states, 'MAR!?IC', stat)
3448
3451
3449 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3452 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3450 ctxn = repo[nullid]
3453 ctxn = repo[nullid]
3451 ctx1 = repo[node1]
3454 ctx1 = repo[node1]
3452 ctx2 = repo[node2]
3455 ctx2 = repo[node2]
3453 added = stat[1]
3456 added = stat[1]
3454 if node2 is None:
3457 if node2 is None:
3455 added = stat[0] + stat[1] # merged?
3458 added = stat[0] + stat[1] # merged?
3456
3459
3457 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3460 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3458 if k in added:
3461 if k in added:
3459 copy[k] = v
3462 copy[k] = v
3460 elif v in added:
3463 elif v in added:
3461 copy[v] = k
3464 copy[v] = k
3462
3465
3463 for state, char, files in changestates:
3466 for state, char, files in changestates:
3464 if state in show:
3467 if state in show:
3465 format = "%s %%s%s" % (char, end)
3468 format = "%s %%s%s" % (char, end)
3466 if opts.get('no_status'):
3469 if opts.get('no_status'):
3467 format = "%%s%s" % end
3470 format = "%%s%s" % end
3468
3471
3469 for f in files:
3472 for f in files:
3470 ui.write(format % repo.pathto(f, cwd),
3473 ui.write(format % repo.pathto(f, cwd),
3471 label='status.' + state)
3474 label='status.' + state)
3472 if f in copy:
3475 if f in copy:
3473 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3476 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3474 label='status.copied')
3477 label='status.copied')
3475
3478
3476 def summary(ui, repo, **opts):
3479 def summary(ui, repo, **opts):
3477 """summarize working directory state
3480 """summarize working directory state
3478
3481
3479 This generates a brief summary of the working directory state,
3482 This generates a brief summary of the working directory state,
3480 including parents, branch, commit status, and available updates.
3483 including parents, branch, commit status, and available updates.
3481
3484
3482 With the --remote option, this will check the default paths for
3485 With the --remote option, this will check the default paths for
3483 incoming and outgoing changes. This can be time-consuming.
3486 incoming and outgoing changes. This can be time-consuming.
3484
3487
3485 Returns 0 on success.
3488 Returns 0 on success.
3486 """
3489 """
3487
3490
3488 ctx = repo[None]
3491 ctx = repo[None]
3489 parents = ctx.parents()
3492 parents = ctx.parents()
3490 pnode = parents[0].node()
3493 pnode = parents[0].node()
3491
3494
3492 for p in parents:
3495 for p in parents:
3493 # label with log.changeset (instead of log.parent) since this
3496 # label with log.changeset (instead of log.parent) since this
3494 # shows a working directory parent *changeset*:
3497 # shows a working directory parent *changeset*:
3495 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3498 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3496 label='log.changeset')
3499 label='log.changeset')
3497 ui.write(' '.join(p.tags()), label='log.tag')
3500 ui.write(' '.join(p.tags()), label='log.tag')
3498 if p.rev() == -1:
3501 if p.rev() == -1:
3499 if not len(repo):
3502 if not len(repo):
3500 ui.write(_(' (empty repository)'))
3503 ui.write(_(' (empty repository)'))
3501 else:
3504 else:
3502 ui.write(_(' (no revision checked out)'))
3505 ui.write(_(' (no revision checked out)'))
3503 ui.write('\n')
3506 ui.write('\n')
3504 if p.description():
3507 if p.description():
3505 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3508 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3506 label='log.summary')
3509 label='log.summary')
3507
3510
3508 branch = ctx.branch()
3511 branch = ctx.branch()
3509 bheads = repo.branchheads(branch)
3512 bheads = repo.branchheads(branch)
3510 m = _('branch: %s\n') % branch
3513 m = _('branch: %s\n') % branch
3511 if branch != 'default':
3514 if branch != 'default':
3512 ui.write(m, label='log.branch')
3515 ui.write(m, label='log.branch')
3513 else:
3516 else:
3514 ui.status(m, label='log.branch')
3517 ui.status(m, label='log.branch')
3515
3518
3516 st = list(repo.status(unknown=True))[:6]
3519 st = list(repo.status(unknown=True))[:6]
3517
3520
3518 c = repo.dirstate.copies()
3521 c = repo.dirstate.copies()
3519 copied, renamed = [], []
3522 copied, renamed = [], []
3520 for d, s in c.iteritems():
3523 for d, s in c.iteritems():
3521 if s in st[2]:
3524 if s in st[2]:
3522 st[2].remove(s)
3525 st[2].remove(s)
3523 renamed.append(d)
3526 renamed.append(d)
3524 else:
3527 else:
3525 copied.append(d)
3528 copied.append(d)
3526 if d in st[1]:
3529 if d in st[1]:
3527 st[1].remove(d)
3530 st[1].remove(d)
3528 st.insert(3, renamed)
3531 st.insert(3, renamed)
3529 st.insert(4, copied)
3532 st.insert(4, copied)
3530
3533
3531 ms = mergemod.mergestate(repo)
3534 ms = mergemod.mergestate(repo)
3532 st.append([f for f in ms if ms[f] == 'u'])
3535 st.append([f for f in ms if ms[f] == 'u'])
3533
3536
3534 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3537 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3535 st.append(subs)
3538 st.append(subs)
3536
3539
3537 labels = [ui.label(_('%d modified'), 'status.modified'),
3540 labels = [ui.label(_('%d modified'), 'status.modified'),
3538 ui.label(_('%d added'), 'status.added'),
3541 ui.label(_('%d added'), 'status.added'),
3539 ui.label(_('%d removed'), 'status.removed'),
3542 ui.label(_('%d removed'), 'status.removed'),
3540 ui.label(_('%d renamed'), 'status.copied'),
3543 ui.label(_('%d renamed'), 'status.copied'),
3541 ui.label(_('%d copied'), 'status.copied'),
3544 ui.label(_('%d copied'), 'status.copied'),
3542 ui.label(_('%d deleted'), 'status.deleted'),
3545 ui.label(_('%d deleted'), 'status.deleted'),
3543 ui.label(_('%d unknown'), 'status.unknown'),
3546 ui.label(_('%d unknown'), 'status.unknown'),
3544 ui.label(_('%d ignored'), 'status.ignored'),
3547 ui.label(_('%d ignored'), 'status.ignored'),
3545 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3548 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3546 ui.label(_('%d subrepos'), 'status.modified')]
3549 ui.label(_('%d subrepos'), 'status.modified')]
3547 t = []
3550 t = []
3548 for s, l in zip(st, labels):
3551 for s, l in zip(st, labels):
3549 if s:
3552 if s:
3550 t.append(l % len(s))
3553 t.append(l % len(s))
3551
3554
3552 t = ', '.join(t)
3555 t = ', '.join(t)
3553 cleanworkdir = False
3556 cleanworkdir = False
3554
3557
3555 if len(parents) > 1:
3558 if len(parents) > 1:
3556 t += _(' (merge)')
3559 t += _(' (merge)')
3557 elif branch != parents[0].branch():
3560 elif branch != parents[0].branch():
3558 t += _(' (new branch)')
3561 t += _(' (new branch)')
3559 elif (parents[0].extra().get('close') and
3562 elif (parents[0].extra().get('close') and
3560 pnode in repo.branchheads(branch, closed=True)):
3563 pnode in repo.branchheads(branch, closed=True)):
3561 t += _(' (head closed)')
3564 t += _(' (head closed)')
3562 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3565 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3563 t += _(' (clean)')
3566 t += _(' (clean)')
3564 cleanworkdir = True
3567 cleanworkdir = True
3565 elif pnode not in bheads:
3568 elif pnode not in bheads:
3566 t += _(' (new branch head)')
3569 t += _(' (new branch head)')
3567
3570
3568 if cleanworkdir:
3571 if cleanworkdir:
3569 ui.status(_('commit: %s\n') % t.strip())
3572 ui.status(_('commit: %s\n') % t.strip())
3570 else:
3573 else:
3571 ui.write(_('commit: %s\n') % t.strip())
3574 ui.write(_('commit: %s\n') % t.strip())
3572
3575
3573 # all ancestors of branch heads - all ancestors of parent = new csets
3576 # all ancestors of branch heads - all ancestors of parent = new csets
3574 new = [0] * len(repo)
3577 new = [0] * len(repo)
3575 cl = repo.changelog
3578 cl = repo.changelog
3576 for a in [cl.rev(n) for n in bheads]:
3579 for a in [cl.rev(n) for n in bheads]:
3577 new[a] = 1
3580 new[a] = 1
3578 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3581 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3579 new[a] = 1
3582 new[a] = 1
3580 for a in [p.rev() for p in parents]:
3583 for a in [p.rev() for p in parents]:
3581 if a >= 0:
3584 if a >= 0:
3582 new[a] = 0
3585 new[a] = 0
3583 for a in cl.ancestors(*[p.rev() for p in parents]):
3586 for a in cl.ancestors(*[p.rev() for p in parents]):
3584 new[a] = 0
3587 new[a] = 0
3585 new = sum(new)
3588 new = sum(new)
3586
3589
3587 if new == 0:
3590 if new == 0:
3588 ui.status(_('update: (current)\n'))
3591 ui.status(_('update: (current)\n'))
3589 elif pnode not in bheads:
3592 elif pnode not in bheads:
3590 ui.write(_('update: %d new changesets (update)\n') % new)
3593 ui.write(_('update: %d new changesets (update)\n') % new)
3591 else:
3594 else:
3592 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3595 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3593 (new, len(bheads)))
3596 (new, len(bheads)))
3594
3597
3595 if opts.get('remote'):
3598 if opts.get('remote'):
3596 t = []
3599 t = []
3597 source, branches = hg.parseurl(ui.expandpath('default'))
3600 source, branches = hg.parseurl(ui.expandpath('default'))
3598 other = hg.repository(hg.remoteui(repo, {}), source)
3601 other = hg.repository(hg.remoteui(repo, {}), source)
3599 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3602 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3600 ui.debug('comparing with %s\n' % url.hidepassword(source))
3603 ui.debug('comparing with %s\n' % url.hidepassword(source))
3601 repo.ui.pushbuffer()
3604 repo.ui.pushbuffer()
3602 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3605 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3603 repo.ui.popbuffer()
3606 repo.ui.popbuffer()
3604 if incoming:
3607 if incoming:
3605 t.append(_('1 or more incoming'))
3608 t.append(_('1 or more incoming'))
3606
3609
3607 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3610 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3608 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3611 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3609 other = hg.repository(hg.remoteui(repo, {}), dest)
3612 other = hg.repository(hg.remoteui(repo, {}), dest)
3610 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3613 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3611 repo.ui.pushbuffer()
3614 repo.ui.pushbuffer()
3612 o = discovery.findoutgoing(repo, other)
3615 o = discovery.findoutgoing(repo, other)
3613 repo.ui.popbuffer()
3616 repo.ui.popbuffer()
3614 o = repo.changelog.nodesbetween(o, None)[0]
3617 o = repo.changelog.nodesbetween(o, None)[0]
3615 if o:
3618 if o:
3616 t.append(_('%d outgoing') % len(o))
3619 t.append(_('%d outgoing') % len(o))
3617
3620
3618 if t:
3621 if t:
3619 ui.write(_('remote: %s\n') % (', '.join(t)))
3622 ui.write(_('remote: %s\n') % (', '.join(t)))
3620 else:
3623 else:
3621 ui.status(_('remote: (synced)\n'))
3624 ui.status(_('remote: (synced)\n'))
3622
3625
3623 def tag(ui, repo, name1, *names, **opts):
3626 def tag(ui, repo, name1, *names, **opts):
3624 """add one or more tags for the current or given revision
3627 """add one or more tags for the current or given revision
3625
3628
3626 Name a particular revision using <name>.
3629 Name a particular revision using <name>.
3627
3630
3628 Tags are used to name particular revisions of the repository and are
3631 Tags are used to name particular revisions of the repository and are
3629 very useful to compare different revisions, to go back to significant
3632 very useful to compare different revisions, to go back to significant
3630 earlier versions or to mark branch points as releases, etc.
3633 earlier versions or to mark branch points as releases, etc.
3631
3634
3632 If no revision is given, the parent of the working directory is
3635 If no revision is given, the parent of the working directory is
3633 used, or tip if no revision is checked out.
3636 used, or tip if no revision is checked out.
3634
3637
3635 To facilitate version control, distribution, and merging of tags,
3638 To facilitate version control, distribution, and merging of tags,
3636 they are stored as a file named ".hgtags" which is managed
3639 they are stored as a file named ".hgtags" which is managed
3637 similarly to other project files and can be hand-edited if
3640 similarly to other project files and can be hand-edited if
3638 necessary. The file '.hg/localtags' is used for local tags (not
3641 necessary. The file '.hg/localtags' is used for local tags (not
3639 shared among repositories).
3642 shared among repositories).
3640
3643
3641 See :hg:`help dates` for a list of formats valid for -d/--date.
3644 See :hg:`help dates` for a list of formats valid for -d/--date.
3642
3645
3643 Since tag names have priority over branch names during revision
3646 Since tag names have priority over branch names during revision
3644 lookup, using an existing branch name as a tag name is discouraged.
3647 lookup, using an existing branch name as a tag name is discouraged.
3645
3648
3646 Returns 0 on success.
3649 Returns 0 on success.
3647 """
3650 """
3648
3651
3649 rev_ = "."
3652 rev_ = "."
3650 names = [t.strip() for t in (name1,) + names]
3653 names = [t.strip() for t in (name1,) + names]
3651 if len(names) != len(set(names)):
3654 if len(names) != len(set(names)):
3652 raise util.Abort(_('tag names must be unique'))
3655 raise util.Abort(_('tag names must be unique'))
3653 for n in names:
3656 for n in names:
3654 if n in ['tip', '.', 'null']:
3657 if n in ['tip', '.', 'null']:
3655 raise util.Abort(_('the name \'%s\' is reserved') % n)
3658 raise util.Abort(_('the name \'%s\' is reserved') % n)
3656 if opts.get('rev') and opts.get('remove'):
3659 if opts.get('rev') and opts.get('remove'):
3657 raise util.Abort(_("--rev and --remove are incompatible"))
3660 raise util.Abort(_("--rev and --remove are incompatible"))
3658 if opts.get('rev'):
3661 if opts.get('rev'):
3659 rev_ = opts['rev']
3662 rev_ = opts['rev']
3660 message = opts.get('message')
3663 message = opts.get('message')
3661 if opts.get('remove'):
3664 if opts.get('remove'):
3662 expectedtype = opts.get('local') and 'local' or 'global'
3665 expectedtype = opts.get('local') and 'local' or 'global'
3663 for n in names:
3666 for n in names:
3664 if not repo.tagtype(n):
3667 if not repo.tagtype(n):
3665 raise util.Abort(_('tag \'%s\' does not exist') % n)
3668 raise util.Abort(_('tag \'%s\' does not exist') % n)
3666 if repo.tagtype(n) != expectedtype:
3669 if repo.tagtype(n) != expectedtype:
3667 if expectedtype == 'global':
3670 if expectedtype == 'global':
3668 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3671 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3669 else:
3672 else:
3670 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3673 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3671 rev_ = nullid
3674 rev_ = nullid
3672 if not message:
3675 if not message:
3673 # we don't translate commit messages
3676 # we don't translate commit messages
3674 message = 'Removed tag %s' % ', '.join(names)
3677 message = 'Removed tag %s' % ', '.join(names)
3675 elif not opts.get('force'):
3678 elif not opts.get('force'):
3676 for n in names:
3679 for n in names:
3677 if n in repo.tags():
3680 if n in repo.tags():
3678 raise util.Abort(_('tag \'%s\' already exists '
3681 raise util.Abort(_('tag \'%s\' already exists '
3679 '(use -f to force)') % n)
3682 '(use -f to force)') % n)
3680 if not rev_ and repo.dirstate.parents()[1] != nullid:
3683 if not rev_ and repo.dirstate.parents()[1] != nullid:
3681 raise util.Abort(_('uncommitted merge - please provide a '
3684 raise util.Abort(_('uncommitted merge - please provide a '
3682 'specific revision'))
3685 'specific revision'))
3683 r = repo[rev_].node()
3686 r = repo[rev_].node()
3684
3687
3685 if not message:
3688 if not message:
3686 # we don't translate commit messages
3689 # we don't translate commit messages
3687 message = ('Added tag %s for changeset %s' %
3690 message = ('Added tag %s for changeset %s' %
3688 (', '.join(names), short(r)))
3691 (', '.join(names), short(r)))
3689
3692
3690 date = opts.get('date')
3693 date = opts.get('date')
3691 if date:
3694 if date:
3692 date = util.parsedate(date)
3695 date = util.parsedate(date)
3693
3696
3694 if opts.get('edit'):
3697 if opts.get('edit'):
3695 message = ui.edit(message, ui.username())
3698 message = ui.edit(message, ui.username())
3696
3699
3697 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3700 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3698
3701
3699 def tags(ui, repo):
3702 def tags(ui, repo):
3700 """list repository tags
3703 """list repository tags
3701
3704
3702 This lists both regular and local tags. When the -v/--verbose
3705 This lists both regular and local tags. When the -v/--verbose
3703 switch is used, a third column "local" is printed for local tags.
3706 switch is used, a third column "local" is printed for local tags.
3704
3707
3705 Returns 0 on success.
3708 Returns 0 on success.
3706 """
3709 """
3707
3710
3708 hexfunc = ui.debugflag and hex or short
3711 hexfunc = ui.debugflag and hex or short
3709 tagtype = ""
3712 tagtype = ""
3710
3713
3711 for t, n in reversed(repo.tagslist()):
3714 for t, n in reversed(repo.tagslist()):
3712 if ui.quiet:
3715 if ui.quiet:
3713 ui.write("%s\n" % t)
3716 ui.write("%s\n" % t)
3714 continue
3717 continue
3715
3718
3716 try:
3719 try:
3717 hn = hexfunc(n)
3720 hn = hexfunc(n)
3718 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3721 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3719 except error.LookupError:
3722 except error.LookupError:
3720 r = " ?:%s" % hn
3723 r = " ?:%s" % hn
3721 else:
3724 else:
3722 spaces = " " * (30 - encoding.colwidth(t))
3725 spaces = " " * (30 - encoding.colwidth(t))
3723 if ui.verbose:
3726 if ui.verbose:
3724 if repo.tagtype(t) == 'local':
3727 if repo.tagtype(t) == 'local':
3725 tagtype = " local"
3728 tagtype = " local"
3726 else:
3729 else:
3727 tagtype = ""
3730 tagtype = ""
3728 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3731 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3729
3732
3730 def tip(ui, repo, **opts):
3733 def tip(ui, repo, **opts):
3731 """show the tip revision
3734 """show the tip revision
3732
3735
3733 The tip revision (usually just called the tip) is the changeset
3736 The tip revision (usually just called the tip) is the changeset
3734 most recently added to the repository (and therefore the most
3737 most recently added to the repository (and therefore the most
3735 recently changed head).
3738 recently changed head).
3736
3739
3737 If you have just made a commit, that commit will be the tip. If
3740 If you have just made a commit, that commit will be the tip. If
3738 you have just pulled changes from another repository, the tip of
3741 you have just pulled changes from another repository, the tip of
3739 that repository becomes the current tip. The "tip" tag is special
3742 that repository becomes the current tip. The "tip" tag is special
3740 and cannot be renamed or assigned to a different changeset.
3743 and cannot be renamed or assigned to a different changeset.
3741
3744
3742 Returns 0 on success.
3745 Returns 0 on success.
3743 """
3746 """
3744 displayer = cmdutil.show_changeset(ui, repo, opts)
3747 displayer = cmdutil.show_changeset(ui, repo, opts)
3745 displayer.show(repo[len(repo) - 1])
3748 displayer.show(repo[len(repo) - 1])
3746 displayer.close()
3749 displayer.close()
3747
3750
3748 def unbundle(ui, repo, fname1, *fnames, **opts):
3751 def unbundle(ui, repo, fname1, *fnames, **opts):
3749 """apply one or more changegroup files
3752 """apply one or more changegroup files
3750
3753
3751 Apply one or more compressed changegroup files generated by the
3754 Apply one or more compressed changegroup files generated by the
3752 bundle command.
3755 bundle command.
3753
3756
3754 Returns 0 on success, 1 if an update has unresolved files.
3757 Returns 0 on success, 1 if an update has unresolved files.
3755 """
3758 """
3756 fnames = (fname1,) + fnames
3759 fnames = (fname1,) + fnames
3757
3760
3758 lock = repo.lock()
3761 lock = repo.lock()
3759 try:
3762 try:
3760 for fname in fnames:
3763 for fname in fnames:
3761 f = url.open(ui, fname)
3764 f = url.open(ui, fname)
3762 gen = changegroup.readbundle(f, fname)
3765 gen = changegroup.readbundle(f, fname)
3763 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3766 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3764 lock=lock)
3767 lock=lock)
3765 finally:
3768 finally:
3766 lock.release()
3769 lock.release()
3767
3770
3768 return postincoming(ui, repo, modheads, opts.get('update'), None)
3771 return postincoming(ui, repo, modheads, opts.get('update'), None)
3769
3772
3770 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3773 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3771 """update working directory (or switch revisions)
3774 """update working directory (or switch revisions)
3772
3775
3773 Update the repository's working directory to the specified
3776 Update the repository's working directory to the specified
3774 changeset.
3777 changeset.
3775
3778
3776 If no changeset is specified, attempt to update to the head of the
3779 If no changeset is specified, attempt to update to the head of the
3777 current branch. If this head is a descendant of the working
3780 current branch. If this head is a descendant of the working
3778 directory's parent, update to it, otherwise abort.
3781 directory's parent, update to it, otherwise abort.
3779
3782
3780 The following rules apply when the working directory contains
3783 The following rules apply when the working directory contains
3781 uncommitted changes:
3784 uncommitted changes:
3782
3785
3783 1. If neither -c/--check nor -C/--clean is specified, and if
3786 1. If neither -c/--check nor -C/--clean is specified, and if
3784 the requested changeset is an ancestor or descendant of
3787 the requested changeset is an ancestor or descendant of
3785 the working directory's parent, the uncommitted changes
3788 the working directory's parent, the uncommitted changes
3786 are merged into the requested changeset and the merged
3789 are merged into the requested changeset and the merged
3787 result is left uncommitted. If the requested changeset is
3790 result is left uncommitted. If the requested changeset is
3788 not an ancestor or descendant (that is, it is on another
3791 not an ancestor or descendant (that is, it is on another
3789 branch), the update is aborted and the uncommitted changes
3792 branch), the update is aborted and the uncommitted changes
3790 are preserved.
3793 are preserved.
3791
3794
3792 2. With the -c/--check option, the update is aborted and the
3795 2. With the -c/--check option, the update is aborted and the
3793 uncommitted changes are preserved.
3796 uncommitted changes are preserved.
3794
3797
3795 3. With the -C/--clean option, uncommitted changes are discarded and
3798 3. With the -C/--clean option, uncommitted changes are discarded and
3796 the working directory is updated to the requested changeset.
3799 the working directory is updated to the requested changeset.
3797
3800
3798 Use null as the changeset to remove the working directory (like
3801 Use null as the changeset to remove the working directory (like
3799 :hg:`clone -U`).
3802 :hg:`clone -U`).
3800
3803
3801 If you want to update just one file to an older changeset, use :hg:`revert`.
3804 If you want to update just one file to an older changeset, use :hg:`revert`.
3802
3805
3803 See :hg:`help dates` for a list of formats valid for -d/--date.
3806 See :hg:`help dates` for a list of formats valid for -d/--date.
3804
3807
3805 Returns 0 on success, 1 if there are unresolved files.
3808 Returns 0 on success, 1 if there are unresolved files.
3806 """
3809 """
3807 if rev and node:
3810 if rev and node:
3808 raise util.Abort(_("please specify just one revision"))
3811 raise util.Abort(_("please specify just one revision"))
3809
3812
3810 if not rev:
3813 if not rev:
3811 rev = node
3814 rev = node
3812
3815
3813 if check and clean:
3816 if check and clean:
3814 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3817 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3815
3818
3816 if check:
3819 if check:
3817 # we could use dirty() but we can ignore merge and branch trivia
3820 # we could use dirty() but we can ignore merge and branch trivia
3818 c = repo[None]
3821 c = repo[None]
3819 if c.modified() or c.added() or c.removed():
3822 if c.modified() or c.added() or c.removed():
3820 raise util.Abort(_("uncommitted local changes"))
3823 raise util.Abort(_("uncommitted local changes"))
3821
3824
3822 if date:
3825 if date:
3823 if rev:
3826 if rev:
3824 raise util.Abort(_("you can't specify a revision and a date"))
3827 raise util.Abort(_("you can't specify a revision and a date"))
3825 rev = cmdutil.finddate(ui, repo, date)
3828 rev = cmdutil.finddate(ui, repo, date)
3826
3829
3827 if clean or check:
3830 if clean or check:
3828 return hg.clean(repo, rev)
3831 return hg.clean(repo, rev)
3829 else:
3832 else:
3830 return hg.update(repo, rev)
3833 return hg.update(repo, rev)
3831
3834
3832 def verify(ui, repo):
3835 def verify(ui, repo):
3833 """verify the integrity of the repository
3836 """verify the integrity of the repository
3834
3837
3835 Verify the integrity of the current repository.
3838 Verify the integrity of the current repository.
3836
3839
3837 This will perform an extensive check of the repository's
3840 This will perform an extensive check of the repository's
3838 integrity, validating the hashes and checksums of each entry in
3841 integrity, validating the hashes and checksums of each entry in
3839 the changelog, manifest, and tracked files, as well as the
3842 the changelog, manifest, and tracked files, as well as the
3840 integrity of their crosslinks and indices.
3843 integrity of their crosslinks and indices.
3841
3844
3842 Returns 0 on success, 1 if errors are encountered.
3845 Returns 0 on success, 1 if errors are encountered.
3843 """
3846 """
3844 return hg.verify(repo)
3847 return hg.verify(repo)
3845
3848
3846 def version_(ui):
3849 def version_(ui):
3847 """output version and copyright information"""
3850 """output version and copyright information"""
3848 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3851 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3849 % util.version())
3852 % util.version())
3850 ui.status(_(
3853 ui.status(_(
3851 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3854 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3852 "This is free software; see the source for copying conditions. "
3855 "This is free software; see the source for copying conditions. "
3853 "There is NO\nwarranty; "
3856 "There is NO\nwarranty; "
3854 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3857 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3855 ))
3858 ))
3856
3859
3857 # Command options and aliases are listed here, alphabetically
3860 # Command options and aliases are listed here, alphabetically
3858
3861
3859 globalopts = [
3862 globalopts = [
3860 ('R', 'repository', '',
3863 ('R', 'repository', '',
3861 _('repository root directory or name of overlay bundle file'),
3864 _('repository root directory or name of overlay bundle file'),
3862 _('REPO')),
3865 _('REPO')),
3863 ('', 'cwd', '',
3866 ('', 'cwd', '',
3864 _('change working directory'), _('DIR')),
3867 _('change working directory'), _('DIR')),
3865 ('y', 'noninteractive', None,
3868 ('y', 'noninteractive', None,
3866 _('do not prompt, assume \'yes\' for any required answers')),
3869 _('do not prompt, assume \'yes\' for any required answers')),
3867 ('q', 'quiet', None, _('suppress output')),
3870 ('q', 'quiet', None, _('suppress output')),
3868 ('v', 'verbose', None, _('enable additional output')),
3871 ('v', 'verbose', None, _('enable additional output')),
3869 ('', 'config', [],
3872 ('', 'config', [],
3870 _('set/override config option (use \'section.name=value\')'),
3873 _('set/override config option (use \'section.name=value\')'),
3871 _('CONFIG')),
3874 _('CONFIG')),
3872 ('', 'debug', None, _('enable debugging output')),
3875 ('', 'debug', None, _('enable debugging output')),
3873 ('', 'debugger', None, _('start debugger')),
3876 ('', 'debugger', None, _('start debugger')),
3874 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3877 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3875 _('ENCODE')),
3878 _('ENCODE')),
3876 ('', 'encodingmode', encoding.encodingmode,
3879 ('', 'encodingmode', encoding.encodingmode,
3877 _('set the charset encoding mode'), _('MODE')),
3880 _('set the charset encoding mode'), _('MODE')),
3878 ('', 'traceback', None, _('always print a traceback on exception')),
3881 ('', 'traceback', None, _('always print a traceback on exception')),
3879 ('', 'time', None, _('time how long the command takes')),
3882 ('', 'time', None, _('time how long the command takes')),
3880 ('', 'profile', None, _('print command execution profile')),
3883 ('', 'profile', None, _('print command execution profile')),
3881 ('', 'version', None, _('output version information and exit')),
3884 ('', 'version', None, _('output version information and exit')),
3882 ('h', 'help', None, _('display help and exit')),
3885 ('h', 'help', None, _('display help and exit')),
3883 ]
3886 ]
3884
3887
3885 dryrunopts = [('n', 'dry-run', None,
3888 dryrunopts = [('n', 'dry-run', None,
3886 _('do not perform actions, just print output'))]
3889 _('do not perform actions, just print output'))]
3887
3890
3888 remoteopts = [
3891 remoteopts = [
3889 ('e', 'ssh', '',
3892 ('e', 'ssh', '',
3890 _('specify ssh command to use'), _('CMD')),
3893 _('specify ssh command to use'), _('CMD')),
3891 ('', 'remotecmd', '',
3894 ('', 'remotecmd', '',
3892 _('specify hg command to run on the remote side'), _('CMD')),
3895 _('specify hg command to run on the remote side'), _('CMD')),
3893 ]
3896 ]
3894
3897
3895 walkopts = [
3898 walkopts = [
3896 ('I', 'include', [],
3899 ('I', 'include', [],
3897 _('include names matching the given patterns'), _('PATTERN')),
3900 _('include names matching the given patterns'), _('PATTERN')),
3898 ('X', 'exclude', [],
3901 ('X', 'exclude', [],
3899 _('exclude names matching the given patterns'), _('PATTERN')),
3902 _('exclude names matching the given patterns'), _('PATTERN')),
3900 ]
3903 ]
3901
3904
3902 commitopts = [
3905 commitopts = [
3903 ('m', 'message', '',
3906 ('m', 'message', '',
3904 _('use text as commit message'), _('TEXT')),
3907 _('use text as commit message'), _('TEXT')),
3905 ('l', 'logfile', '',
3908 ('l', 'logfile', '',
3906 _('read commit message from file'), _('FILE')),
3909 _('read commit message from file'), _('FILE')),
3907 ]
3910 ]
3908
3911
3909 commitopts2 = [
3912 commitopts2 = [
3910 ('d', 'date', '',
3913 ('d', 'date', '',
3911 _('record datecode as commit date'), _('DATE')),
3914 _('record datecode as commit date'), _('DATE')),
3912 ('u', 'user', '',
3915 ('u', 'user', '',
3913 _('record the specified user as committer'), _('USER')),
3916 _('record the specified user as committer'), _('USER')),
3914 ]
3917 ]
3915
3918
3916 templateopts = [
3919 templateopts = [
3917 ('', 'style', '',
3920 ('', 'style', '',
3918 _('display using template map file'), _('STYLE')),
3921 _('display using template map file'), _('STYLE')),
3919 ('', 'template', '',
3922 ('', 'template', '',
3920 _('display with template'), _('TEMPLATE')),
3923 _('display with template'), _('TEMPLATE')),
3921 ]
3924 ]
3922
3925
3923 logopts = [
3926 logopts = [
3924 ('p', 'patch', None, _('show patch')),
3927 ('p', 'patch', None, _('show patch')),
3925 ('g', 'git', None, _('use git extended diff format')),
3928 ('g', 'git', None, _('use git extended diff format')),
3926 ('l', 'limit', '',
3929 ('l', 'limit', '',
3927 _('limit number of changes displayed'), _('NUM')),
3930 _('limit number of changes displayed'), _('NUM')),
3928 ('M', 'no-merges', None, _('do not show merges')),
3931 ('M', 'no-merges', None, _('do not show merges')),
3929 ('', 'stat', None, _('output diffstat-style summary of changes')),
3932 ('', 'stat', None, _('output diffstat-style summary of changes')),
3930 ] + templateopts
3933 ] + templateopts
3931
3934
3932 diffopts = [
3935 diffopts = [
3933 ('a', 'text', None, _('treat all files as text')),
3936 ('a', 'text', None, _('treat all files as text')),
3934 ('g', 'git', None, _('use git extended diff format')),
3937 ('g', 'git', None, _('use git extended diff format')),
3935 ('', 'nodates', None, _('omit dates from diff headers'))
3938 ('', 'nodates', None, _('omit dates from diff headers'))
3936 ]
3939 ]
3937
3940
3938 diffopts2 = [
3941 diffopts2 = [
3939 ('p', 'show-function', None, _('show which function each change is in')),
3942 ('p', 'show-function', None, _('show which function each change is in')),
3940 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3943 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3941 ('w', 'ignore-all-space', None,
3944 ('w', 'ignore-all-space', None,
3942 _('ignore white space when comparing lines')),
3945 _('ignore white space when comparing lines')),
3943 ('b', 'ignore-space-change', None,
3946 ('b', 'ignore-space-change', None,
3944 _('ignore changes in the amount of white space')),
3947 _('ignore changes in the amount of white space')),
3945 ('B', 'ignore-blank-lines', None,
3948 ('B', 'ignore-blank-lines', None,
3946 _('ignore changes whose lines are all blank')),
3949 _('ignore changes whose lines are all blank')),
3947 ('U', 'unified', '',
3950 ('U', 'unified', '',
3948 _('number of lines of context to show'), _('NUM')),
3951 _('number of lines of context to show'), _('NUM')),
3949 ('', 'stat', None, _('output diffstat-style summary of changes')),
3952 ('', 'stat', None, _('output diffstat-style summary of changes')),
3950 ]
3953 ]
3951
3954
3952 similarityopts = [
3955 similarityopts = [
3953 ('s', 'similarity', '',
3956 ('s', 'similarity', '',
3954 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3957 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3955 ]
3958 ]
3956
3959
3957 table = {
3960 table = {
3958 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3961 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3959 "addremove":
3962 "addremove":
3960 (addremove, similarityopts + walkopts + dryrunopts,
3963 (addremove, similarityopts + walkopts + dryrunopts,
3961 _('[OPTION]... [FILE]...')),
3964 _('[OPTION]... [FILE]...')),
3962 "^annotate|blame":
3965 "^annotate|blame":
3963 (annotate,
3966 (annotate,
3964 [('r', 'rev', '',
3967 [('r', 'rev', '',
3965 _('annotate the specified revision'), _('REV')),
3968 _('annotate the specified revision'), _('REV')),
3966 ('', 'follow', None,
3969 ('', 'follow', None,
3967 _('follow copies/renames and list the filename (DEPRECATED)')),
3970 _('follow copies/renames and list the filename (DEPRECATED)')),
3968 ('', 'no-follow', None, _("don't follow copies and renames")),
3971 ('', 'no-follow', None, _("don't follow copies and renames")),
3969 ('a', 'text', None, _('treat all files as text')),
3972 ('a', 'text', None, _('treat all files as text')),
3970 ('u', 'user', None, _('list the author (long with -v)')),
3973 ('u', 'user', None, _('list the author (long with -v)')),
3971 ('f', 'file', None, _('list the filename')),
3974 ('f', 'file', None, _('list the filename')),
3972 ('d', 'date', None, _('list the date (short with -q)')),
3975 ('d', 'date', None, _('list the date (short with -q)')),
3973 ('n', 'number', None, _('list the revision number (default)')),
3976 ('n', 'number', None, _('list the revision number (default)')),
3974 ('c', 'changeset', None, _('list the changeset')),
3977 ('c', 'changeset', None, _('list the changeset')),
3975 ('l', 'line-number', None,
3978 ('l', 'line-number', None,
3976 _('show line number at the first appearance'))
3979 _('show line number at the first appearance'))
3977 ] + walkopts,
3980 ] + walkopts,
3978 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3981 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3979 "archive":
3982 "archive":
3980 (archive,
3983 (archive,
3981 [('', 'no-decode', None, _('do not pass files through decoders')),
3984 [('', 'no-decode', None, _('do not pass files through decoders')),
3982 ('p', 'prefix', '',
3985 ('p', 'prefix', '',
3983 _('directory prefix for files in archive'), _('PREFIX')),
3986 _('directory prefix for files in archive'), _('PREFIX')),
3984 ('r', 'rev', '',
3987 ('r', 'rev', '',
3985 _('revision to distribute'), _('REV')),
3988 _('revision to distribute'), _('REV')),
3986 ('t', 'type', '',
3989 ('t', 'type', '',
3987 _('type of distribution to create'), _('TYPE')),
3990 _('type of distribution to create'), _('TYPE')),
3988 ] + walkopts,
3991 ] + walkopts,
3989 _('[OPTION]... DEST')),
3992 _('[OPTION]... DEST')),
3990 "backout":
3993 "backout":
3991 (backout,
3994 (backout,
3992 [('', 'merge', None,
3995 [('', 'merge', None,
3993 _('merge with old dirstate parent after backout')),
3996 _('merge with old dirstate parent after backout')),
3994 ('', 'parent', '',
3997 ('', 'parent', '',
3995 _('parent to choose when backing out merge'), _('REV')),
3998 _('parent to choose when backing out merge'), _('REV')),
3996 ('r', 'rev', '',
3999 ('r', 'rev', '',
3997 _('revision to backout'), _('REV')),
4000 _('revision to backout'), _('REV')),
3998 ] + walkopts + commitopts + commitopts2,
4001 ] + walkopts + commitopts + commitopts2,
3999 _('[OPTION]... [-r] REV')),
4002 _('[OPTION]... [-r] REV')),
4000 "bisect":
4003 "bisect":
4001 (bisect,
4004 (bisect,
4002 [('r', 'reset', False, _('reset bisect state')),
4005 [('r', 'reset', False, _('reset bisect state')),
4003 ('g', 'good', False, _('mark changeset good')),
4006 ('g', 'good', False, _('mark changeset good')),
4004 ('b', 'bad', False, _('mark changeset bad')),
4007 ('b', 'bad', False, _('mark changeset bad')),
4005 ('s', 'skip', False, _('skip testing changeset')),
4008 ('s', 'skip', False, _('skip testing changeset')),
4006 ('c', 'command', '',
4009 ('c', 'command', '',
4007 _('use command to check changeset state'), _('CMD')),
4010 _('use command to check changeset state'), _('CMD')),
4008 ('U', 'noupdate', False, _('do not update to target'))],
4011 ('U', 'noupdate', False, _('do not update to target'))],
4009 _("[-gbsr] [-U] [-c CMD] [REV]")),
4012 _("[-gbsr] [-U] [-c CMD] [REV]")),
4010 "branch":
4013 "branch":
4011 (branch,
4014 (branch,
4012 [('f', 'force', None,
4015 [('f', 'force', None,
4013 _('set branch name even if it shadows an existing branch')),
4016 _('set branch name even if it shadows an existing branch')),
4014 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4017 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4015 _('[-fC] [NAME]')),
4018 _('[-fC] [NAME]')),
4016 "branches":
4019 "branches":
4017 (branches,
4020 (branches,
4018 [('a', 'active', False,
4021 [('a', 'active', False,
4019 _('show only branches that have unmerged heads')),
4022 _('show only branches that have unmerged heads')),
4020 ('c', 'closed', False,
4023 ('c', 'closed', False,
4021 _('show normal and closed branches'))],
4024 _('show normal and closed branches'))],
4022 _('[-ac]')),
4025 _('[-ac]')),
4023 "bundle":
4026 "bundle":
4024 (bundle,
4027 (bundle,
4025 [('f', 'force', None,
4028 [('f', 'force', None,
4026 _('run even when the destination is unrelated')),
4029 _('run even when the destination is unrelated')),
4027 ('r', 'rev', [],
4030 ('r', 'rev', [],
4028 _('a changeset intended to be added to the destination'),
4031 _('a changeset intended to be added to the destination'),
4029 _('REV')),
4032 _('REV')),
4030 ('b', 'branch', [],
4033 ('b', 'branch', [],
4031 _('a specific branch you would like to bundle'),
4034 _('a specific branch you would like to bundle'),
4032 _('BRANCH')),
4035 _('BRANCH')),
4033 ('', 'base', [],
4036 ('', 'base', [],
4034 _('a base changeset assumed to be available at the destination'),
4037 _('a base changeset assumed to be available at the destination'),
4035 _('REV')),
4038 _('REV')),
4036 ('a', 'all', None, _('bundle all changesets in the repository')),
4039 ('a', 'all', None, _('bundle all changesets in the repository')),
4037 ('t', 'type', 'bzip2',
4040 ('t', 'type', 'bzip2',
4038 _('bundle compression type to use'), _('TYPE')),
4041 _('bundle compression type to use'), _('TYPE')),
4039 ] + remoteopts,
4042 ] + remoteopts,
4040 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4043 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4041 "cat":
4044 "cat":
4042 (cat,
4045 (cat,
4043 [('o', 'output', '',
4046 [('o', 'output', '',
4044 _('print output to file with formatted name'), _('FORMAT')),
4047 _('print output to file with formatted name'), _('FORMAT')),
4045 ('r', 'rev', '',
4048 ('r', 'rev', '',
4046 _('print the given revision'), _('REV')),
4049 _('print the given revision'), _('REV')),
4047 ('', 'decode', None, _('apply any matching decode filter')),
4050 ('', 'decode', None, _('apply any matching decode filter')),
4048 ] + walkopts,
4051 ] + walkopts,
4049 _('[OPTION]... FILE...')),
4052 _('[OPTION]... FILE...')),
4050 "^clone":
4053 "^clone":
4051 (clone,
4054 (clone,
4052 [('U', 'noupdate', None,
4055 [('U', 'noupdate', None,
4053 _('the clone will include an empty working copy (only a repository)')),
4056 _('the clone will include an empty working copy (only a repository)')),
4054 ('u', 'updaterev', '',
4057 ('u', 'updaterev', '',
4055 _('revision, tag or branch to check out'), _('REV')),
4058 _('revision, tag or branch to check out'), _('REV')),
4056 ('r', 'rev', [],
4059 ('r', 'rev', [],
4057 _('include the specified changeset'), _('REV')),
4060 _('include the specified changeset'), _('REV')),
4058 ('b', 'branch', [],
4061 ('b', 'branch', [],
4059 _('clone only the specified branch'), _('BRANCH')),
4062 _('clone only the specified branch'), _('BRANCH')),
4060 ('', 'pull', None, _('use pull protocol to copy metadata')),
4063 ('', 'pull', None, _('use pull protocol to copy metadata')),
4061 ('', 'uncompressed', None,
4064 ('', 'uncompressed', None,
4062 _('use uncompressed transfer (fast over LAN)')),
4065 _('use uncompressed transfer (fast over LAN)')),
4063 ] + remoteopts,
4066 ] + remoteopts,
4064 _('[OPTION]... SOURCE [DEST]')),
4067 _('[OPTION]... SOURCE [DEST]')),
4065 "^commit|ci":
4068 "^commit|ci":
4066 (commit,
4069 (commit,
4067 [('A', 'addremove', None,
4070 [('A', 'addremove', None,
4068 _('mark new/missing files as added/removed before committing')),
4071 _('mark new/missing files as added/removed before committing')),
4069 ('', 'close-branch', None,
4072 ('', 'close-branch', None,
4070 _('mark a branch as closed, hiding it from the branch list')),
4073 _('mark a branch as closed, hiding it from the branch list')),
4071 ] + walkopts + commitopts + commitopts2,
4074 ] + walkopts + commitopts + commitopts2,
4072 _('[OPTION]... [FILE]...')),
4075 _('[OPTION]... [FILE]...')),
4073 "copy|cp":
4076 "copy|cp":
4074 (copy,
4077 (copy,
4075 [('A', 'after', None, _('record a copy that has already occurred')),
4078 [('A', 'after', None, _('record a copy that has already occurred')),
4076 ('f', 'force', None,
4079 ('f', 'force', None,
4077 _('forcibly copy over an existing managed file')),
4080 _('forcibly copy over an existing managed file')),
4078 ] + walkopts + dryrunopts,
4081 ] + walkopts + dryrunopts,
4079 _('[OPTION]... [SOURCE]... DEST')),
4082 _('[OPTION]... [SOURCE]... DEST')),
4080 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4083 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4081 "debugbuilddag":
4084 "debugbuilddag":
4082 (debugbuilddag,
4085 (debugbuilddag,
4083 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4086 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4084 ('a', 'appended-file', None, _('add single file all revs append to')),
4087 ('a', 'appended-file', None, _('add single file all revs append to')),
4085 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4088 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4086 ('n', 'new-file', None, _('add new file at each rev')),
4089 ('n', 'new-file', None, _('add new file at each rev')),
4087 ],
4090 ],
4088 _('[OPTION]... TEXT')),
4091 _('[OPTION]... TEXT')),
4089 "debugcheckstate": (debugcheckstate, [], ''),
4092 "debugcheckstate": (debugcheckstate, [], ''),
4090 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4093 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4091 "debugcomplete":
4094 "debugcomplete":
4092 (debugcomplete,
4095 (debugcomplete,
4093 [('o', 'options', None, _('show the command options'))],
4096 [('o', 'options', None, _('show the command options'))],
4094 _('[-o] CMD')),
4097 _('[-o] CMD')),
4095 "debugdag":
4098 "debugdag":
4096 (debugdag,
4099 (debugdag,
4097 [('t', 'tags', None, _('use tags as labels')),
4100 [('t', 'tags', None, _('use tags as labels')),
4098 ('b', 'branches', None, _('annotate with branch names')),
4101 ('b', 'branches', None, _('annotate with branch names')),
4099 ('', 'dots', None, _('use dots for runs')),
4102 ('', 'dots', None, _('use dots for runs')),
4100 ('s', 'spaces', None, _('separate elements by spaces')),
4103 ('s', 'spaces', None, _('separate elements by spaces')),
4101 ],
4104 ],
4102 _('[OPTION]... [FILE [REV]...]')),
4105 _('[OPTION]... [FILE [REV]...]')),
4103 "debugdate":
4106 "debugdate":
4104 (debugdate,
4107 (debugdate,
4105 [('e', 'extended', None, _('try extended date formats'))],
4108 [('e', 'extended', None, _('try extended date formats'))],
4106 _('[-e] DATE [RANGE]')),
4109 _('[-e] DATE [RANGE]')),
4107 "debugdata": (debugdata, [], _('FILE REV')),
4110 "debugdata": (debugdata, [], _('FILE REV')),
4108 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4111 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4109 "debugindex": (debugindex, [], _('FILE')),
4112 "debugindex": (debugindex, [], _('FILE')),
4110 "debugindexdot": (debugindexdot, [], _('FILE')),
4113 "debugindexdot": (debugindexdot, [], _('FILE')),
4111 "debuginstall": (debuginstall, [], ''),
4114 "debuginstall": (debuginstall, [], ''),
4112 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4115 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4113 "debugrebuildstate":
4116 "debugrebuildstate":
4114 (debugrebuildstate,
4117 (debugrebuildstate,
4115 [('r', 'rev', '',
4118 [('r', 'rev', '',
4116 _('revision to rebuild to'), _('REV'))],
4119 _('revision to rebuild to'), _('REV'))],
4117 _('[-r REV] [REV]')),
4120 _('[-r REV] [REV]')),
4118 "debugrename":
4121 "debugrename":
4119 (debugrename,
4122 (debugrename,
4120 [('r', 'rev', '',
4123 [('r', 'rev', '',
4121 _('revision to debug'), _('REV'))],
4124 _('revision to debug'), _('REV'))],
4122 _('[-r REV] FILE')),
4125 _('[-r REV] FILE')),
4123 "debugrevspec":
4126 "debugrevspec":
4124 (debugrevspec, [], ('REVSPEC')),
4127 (debugrevspec, [], ('REVSPEC')),
4125 "debugsetparents":
4128 "debugsetparents":
4126 (debugsetparents, [], _('REV1 [REV2]')),
4129 (debugsetparents, [], _('REV1 [REV2]')),
4127 "debugstate":
4130 "debugstate":
4128 (debugstate,
4131 (debugstate,
4129 [('', 'nodates', None, _('do not display the saved mtime'))],
4132 [('', 'nodates', None, _('do not display the saved mtime'))],
4130 _('[OPTION]...')),
4133 _('[OPTION]...')),
4131 "debugsub":
4134 "debugsub":
4132 (debugsub,
4135 (debugsub,
4133 [('r', 'rev', '',
4136 [('r', 'rev', '',
4134 _('revision to check'), _('REV'))],
4137 _('revision to check'), _('REV'))],
4135 _('[-r REV] [REV]')),
4138 _('[-r REV] [REV]')),
4136 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4139 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4137 "^diff":
4140 "^diff":
4138 (diff,
4141 (diff,
4139 [('r', 'rev', [],
4142 [('r', 'rev', [],
4140 _('revision'), _('REV')),
4143 _('revision'), _('REV')),
4141 ('c', 'change', '',
4144 ('c', 'change', '',
4142 _('change made by revision'), _('REV'))
4145 _('change made by revision'), _('REV'))
4143 ] + diffopts + diffopts2 + walkopts,
4146 ] + diffopts + diffopts2 + walkopts,
4144 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4147 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4145 "^export":
4148 "^export":
4146 (export,
4149 (export,
4147 [('o', 'output', '',
4150 [('o', 'output', '',
4148 _('print output to file with formatted name'), _('FORMAT')),
4151 _('print output to file with formatted name'), _('FORMAT')),
4149 ('', 'switch-parent', None, _('diff against the second parent')),
4152 ('', 'switch-parent', None, _('diff against the second parent')),
4150 ('r', 'rev', [],
4153 ('r', 'rev', [],
4151 _('revisions to export'), _('REV')),
4154 _('revisions to export'), _('REV')),
4152 ] + diffopts,
4155 ] + diffopts,
4153 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4156 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4154 "^forget":
4157 "^forget":
4155 (forget,
4158 (forget,
4156 [] + walkopts,
4159 [] + walkopts,
4157 _('[OPTION]... FILE...')),
4160 _('[OPTION]... FILE...')),
4158 "grep":
4161 "grep":
4159 (grep,
4162 (grep,
4160 [('0', 'print0', None, _('end fields with NUL')),
4163 [('0', 'print0', None, _('end fields with NUL')),
4161 ('', 'all', None, _('print all revisions that match')),
4164 ('', 'all', None, _('print all revisions that match')),
4162 ('f', 'follow', None,
4165 ('f', 'follow', None,
4163 _('follow changeset history,'
4166 _('follow changeset history,'
4164 ' or file history across copies and renames')),
4167 ' or file history across copies and renames')),
4165 ('i', 'ignore-case', None, _('ignore case when matching')),
4168 ('i', 'ignore-case', None, _('ignore case when matching')),
4166 ('l', 'files-with-matches', None,
4169 ('l', 'files-with-matches', None,
4167 _('print only filenames and revisions that match')),
4170 _('print only filenames and revisions that match')),
4168 ('n', 'line-number', None, _('print matching line numbers')),
4171 ('n', 'line-number', None, _('print matching line numbers')),
4169 ('r', 'rev', [],
4172 ('r', 'rev', [],
4170 _('only search files changed within revision range'), _('REV')),
4173 _('only search files changed within revision range'), _('REV')),
4171 ('u', 'user', None, _('list the author (long with -v)')),
4174 ('u', 'user', None, _('list the author (long with -v)')),
4172 ('d', 'date', None, _('list the date (short with -q)')),
4175 ('d', 'date', None, _('list the date (short with -q)')),
4173 ] + walkopts,
4176 ] + walkopts,
4174 _('[OPTION]... PATTERN [FILE]...')),
4177 _('[OPTION]... PATTERN [FILE]...')),
4175 "heads":
4178 "heads":
4176 (heads,
4179 (heads,
4177 [('r', 'rev', '',
4180 [('r', 'rev', '',
4178 _('show only heads which are descendants of REV'), _('REV')),
4181 _('show only heads which are descendants of REV'), _('REV')),
4179 ('t', 'topo', False, _('show topological heads only')),
4182 ('t', 'topo', False, _('show topological heads only')),
4180 ('a', 'active', False,
4183 ('a', 'active', False,
4181 _('show active branchheads only [DEPRECATED]')),
4184 _('show active branchheads only [DEPRECATED]')),
4182 ('c', 'closed', False,
4185 ('c', 'closed', False,
4183 _('show normal and closed branch heads')),
4186 _('show normal and closed branch heads')),
4184 ] + templateopts,
4187 ] + templateopts,
4185 _('[-ac] [-r REV] [REV]...')),
4188 _('[-ac] [-r REV] [REV]...')),
4186 "help": (help_, [], _('[TOPIC]')),
4189 "help": (help_, [], _('[TOPIC]')),
4187 "identify|id":
4190 "identify|id":
4188 (identify,
4191 (identify,
4189 [('r', 'rev', '',
4192 [('r', 'rev', '',
4190 _('identify the specified revision'), _('REV')),
4193 _('identify the specified revision'), _('REV')),
4191 ('n', 'num', None, _('show local revision number')),
4194 ('n', 'num', None, _('show local revision number')),
4192 ('i', 'id', None, _('show global revision id')),
4195 ('i', 'id', None, _('show global revision id')),
4193 ('b', 'branch', None, _('show branch')),
4196 ('b', 'branch', None, _('show branch')),
4194 ('t', 'tags', None, _('show tags'))],
4197 ('t', 'tags', None, _('show tags'))],
4195 _('[-nibt] [-r REV] [SOURCE]')),
4198 _('[-nibt] [-r REV] [SOURCE]')),
4196 "import|patch":
4199 "import|patch":
4197 (import_,
4200 (import_,
4198 [('p', 'strip', 1,
4201 [('p', 'strip', 1,
4199 _('directory strip option for patch. This has the same '
4202 _('directory strip option for patch. This has the same '
4200 'meaning as the corresponding patch option'),
4203 'meaning as the corresponding patch option'),
4201 _('NUM')),
4204 _('NUM')),
4202 ('b', 'base', '',
4205 ('b', 'base', '',
4203 _('base path'), _('PATH')),
4206 _('base path'), _('PATH')),
4204 ('f', 'force', None,
4207 ('f', 'force', None,
4205 _('skip check for outstanding uncommitted changes')),
4208 _('skip check for outstanding uncommitted changes')),
4206 ('', 'no-commit', None,
4209 ('', 'no-commit', None,
4207 _("don't commit, just update the working directory")),
4210 _("don't commit, just update the working directory")),
4208 ('', 'exact', None,
4211 ('', 'exact', None,
4209 _('apply patch to the nodes from which it was generated')),
4212 _('apply patch to the nodes from which it was generated')),
4210 ('', 'import-branch', None,
4213 ('', 'import-branch', None,
4211 _('use any branch information in patch (implied by --exact)'))] +
4214 _('use any branch information in patch (implied by --exact)'))] +
4212 commitopts + commitopts2 + similarityopts,
4215 commitopts + commitopts2 + similarityopts,
4213 _('[OPTION]... PATCH...')),
4216 _('[OPTION]... PATCH...')),
4214 "incoming|in":
4217 "incoming|in":
4215 (incoming,
4218 (incoming,
4216 [('f', 'force', None,
4219 [('f', 'force', None,
4217 _('run even if remote repository is unrelated')),
4220 _('run even if remote repository is unrelated')),
4218 ('n', 'newest-first', None, _('show newest record first')),
4221 ('n', 'newest-first', None, _('show newest record first')),
4219 ('', 'bundle', '',
4222 ('', 'bundle', '',
4220 _('file to store the bundles into'), _('FILE')),
4223 _('file to store the bundles into'), _('FILE')),
4221 ('r', 'rev', [],
4224 ('r', 'rev', [],
4222 _('a remote changeset intended to be added'), _('REV')),
4225 _('a remote changeset intended to be added'), _('REV')),
4223 ('b', 'branch', [],
4226 ('b', 'branch', [],
4224 _('a specific branch you would like to pull'), _('BRANCH')),
4227 _('a specific branch you would like to pull'), _('BRANCH')),
4225 ] + logopts + remoteopts,
4228 ] + logopts + remoteopts,
4226 _('[-p] [-n] [-M] [-f] [-r REV]...'
4229 _('[-p] [-n] [-M] [-f] [-r REV]...'
4227 ' [--bundle FILENAME] [SOURCE]')),
4230 ' [--bundle FILENAME] [SOURCE]')),
4228 "^init":
4231 "^init":
4229 (init,
4232 (init,
4230 remoteopts,
4233 remoteopts,
4231 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4234 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4232 "locate":
4235 "locate":
4233 (locate,
4236 (locate,
4234 [('r', 'rev', '',
4237 [('r', 'rev', '',
4235 _('search the repository as it is in REV'), _('REV')),
4238 _('search the repository as it is in REV'), _('REV')),
4236 ('0', 'print0', None,
4239 ('0', 'print0', None,
4237 _('end filenames with NUL, for use with xargs')),
4240 _('end filenames with NUL, for use with xargs')),
4238 ('f', 'fullpath', None,
4241 ('f', 'fullpath', None,
4239 _('print complete paths from the filesystem root')),
4242 _('print complete paths from the filesystem root')),
4240 ] + walkopts,
4243 ] + walkopts,
4241 _('[OPTION]... [PATTERN]...')),
4244 _('[OPTION]... [PATTERN]...')),
4242 "^log|history":
4245 "^log|history":
4243 (log,
4246 (log,
4244 [('f', 'follow', None,
4247 [('f', 'follow', None,
4245 _('follow changeset history,'
4248 _('follow changeset history,'
4246 ' or file history across copies and renames')),
4249 ' or file history across copies and renames')),
4247 ('', 'follow-first', None,
4250 ('', 'follow-first', None,
4248 _('only follow the first parent of merge changesets')),
4251 _('only follow the first parent of merge changesets')),
4249 ('d', 'date', '',
4252 ('d', 'date', '',
4250 _('show revisions matching date spec'), _('DATE')),
4253 _('show revisions matching date spec'), _('DATE')),
4251 ('C', 'copies', None, _('show copied files')),
4254 ('C', 'copies', None, _('show copied files')),
4252 ('k', 'keyword', [],
4255 ('k', 'keyword', [],
4253 _('do case-insensitive search for a given text'), _('TEXT')),
4256 _('do case-insensitive search for a given text'), _('TEXT')),
4254 ('r', 'rev', [],
4257 ('r', 'rev', [],
4255 _('show the specified revision or range'), _('REV')),
4258 _('show the specified revision or range'), _('REV')),
4256 ('', 'removed', None, _('include revisions where files were removed')),
4259 ('', 'removed', None, _('include revisions where files were removed')),
4257 ('m', 'only-merges', None, _('show only merges')),
4260 ('m', 'only-merges', None, _('show only merges')),
4258 ('u', 'user', [],
4261 ('u', 'user', [],
4259 _('revisions committed by user'), _('USER')),
4262 _('revisions committed by user'), _('USER')),
4260 ('', 'only-branch', [],
4263 ('', 'only-branch', [],
4261 _('show only changesets within the given named branch (DEPRECATED)'),
4264 _('show only changesets within the given named branch (DEPRECATED)'),
4262 _('BRANCH')),
4265 _('BRANCH')),
4263 ('b', 'branch', [],
4266 ('b', 'branch', [],
4264 _('show changesets within the given named branch'), _('BRANCH')),
4267 _('show changesets within the given named branch'), _('BRANCH')),
4265 ('P', 'prune', [],
4268 ('P', 'prune', [],
4266 _('do not display revision or any of its ancestors'), _('REV')),
4269 _('do not display revision or any of its ancestors'), _('REV')),
4267 ] + logopts + walkopts,
4270 ] + logopts + walkopts,
4268 _('[OPTION]... [FILE]')),
4271 _('[OPTION]... [FILE]')),
4269 "manifest":
4272 "manifest":
4270 (manifest,
4273 (manifest,
4271 [('r', 'rev', '',
4274 [('r', 'rev', '',
4272 _('revision to display'), _('REV'))],
4275 _('revision to display'), _('REV'))],
4273 _('[-r REV]')),
4276 _('[-r REV]')),
4274 "^merge":
4277 "^merge":
4275 (merge,
4278 (merge,
4276 [('f', 'force', None, _('force a merge with outstanding changes')),
4279 [('f', 'force', None, _('force a merge with outstanding changes')),
4277 ('r', 'rev', '',
4280 ('r', 'rev', '',
4278 _('revision to merge'), _('REV')),
4281 _('revision to merge'), _('REV')),
4279 ('P', 'preview', None,
4282 ('P', 'preview', None,
4280 _('review revisions to merge (no merge is performed)'))],
4283 _('review revisions to merge (no merge is performed)'))],
4281 _('[-P] [-f] [[-r] REV]')),
4284 _('[-P] [-f] [[-r] REV]')),
4282 "outgoing|out":
4285 "outgoing|out":
4283 (outgoing,
4286 (outgoing,
4284 [('f', 'force', None,
4287 [('f', 'force', None,
4285 _('run even when the destination is unrelated')),
4288 _('run even when the destination is unrelated')),
4286 ('r', 'rev', [],
4289 ('r', 'rev', [],
4287 _('a changeset intended to be included in the destination'),
4290 _('a changeset intended to be included in the destination'),
4288 _('REV')),
4291 _('REV')),
4289 ('n', 'newest-first', None, _('show newest record first')),
4292 ('n', 'newest-first', None, _('show newest record first')),
4290 ('b', 'branch', [],
4293 ('b', 'branch', [],
4291 _('a specific branch you would like to push'), _('BRANCH')),
4294 _('a specific branch you would like to push'), _('BRANCH')),
4292 ] + logopts + remoteopts,
4295 ] + logopts + remoteopts,
4293 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4296 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4294 "parents":
4297 "parents":
4295 (parents,
4298 (parents,
4296 [('r', 'rev', '',
4299 [('r', 'rev', '',
4297 _('show parents of the specified revision'), _('REV')),
4300 _('show parents of the specified revision'), _('REV')),
4298 ] + templateopts,
4301 ] + templateopts,
4299 _('[-r REV] [FILE]')),
4302 _('[-r REV] [FILE]')),
4300 "paths": (paths, [], _('[NAME]')),
4303 "paths": (paths, [], _('[NAME]')),
4301 "^pull":
4304 "^pull":
4302 (pull,
4305 (pull,
4303 [('u', 'update', None,
4306 [('u', 'update', None,
4304 _('update to new branch head if changesets were pulled')),
4307 _('update to new branch head if changesets were pulled')),
4305 ('f', 'force', None,
4308 ('f', 'force', None,
4306 _('run even when remote repository is unrelated')),
4309 _('run even when remote repository is unrelated')),
4307 ('r', 'rev', [],
4310 ('r', 'rev', [],
4308 _('a remote changeset intended to be added'), _('REV')),
4311 _('a remote changeset intended to be added'), _('REV')),
4309 ('b', 'branch', [],
4312 ('b', 'branch', [],
4310 _('a specific branch you would like to pull'), _('BRANCH')),
4313 _('a specific branch you would like to pull'), _('BRANCH')),
4311 ] + remoteopts,
4314 ] + remoteopts,
4312 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4315 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4313 "^push":
4316 "^push":
4314 (push,
4317 (push,
4315 [('f', 'force', None, _('force push')),
4318 [('f', 'force', None, _('force push')),
4316 ('r', 'rev', [],
4319 ('r', 'rev', [],
4317 _('a changeset intended to be included in the destination'),
4320 _('a changeset intended to be included in the destination'),
4318 _('REV')),
4321 _('REV')),
4319 ('b', 'branch', [],
4322 ('b', 'branch', [],
4320 _('a specific branch you would like to push'), _('BRANCH')),
4323 _('a specific branch you would like to push'), _('BRANCH')),
4321 ('', 'new-branch', False, _('allow pushing a new branch')),
4324 ('', 'new-branch', False, _('allow pushing a new branch')),
4322 ] + remoteopts,
4325 ] + remoteopts,
4323 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4326 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4324 "recover": (recover, []),
4327 "recover": (recover, []),
4325 "^remove|rm":
4328 "^remove|rm":
4326 (remove,
4329 (remove,
4327 [('A', 'after', None, _('record delete for missing files')),
4330 [('A', 'after', None, _('record delete for missing files')),
4328 ('f', 'force', None,
4331 ('f', 'force', None,
4329 _('remove (and delete) file even if added or modified')),
4332 _('remove (and delete) file even if added or modified')),
4330 ] + walkopts,
4333 ] + walkopts,
4331 _('[OPTION]... FILE...')),
4334 _('[OPTION]... FILE...')),
4332 "rename|mv":
4335 "rename|mv":
4333 (rename,
4336 (rename,
4334 [('A', 'after', None, _('record a rename that has already occurred')),
4337 [('A', 'after', None, _('record a rename that has already occurred')),
4335 ('f', 'force', None,
4338 ('f', 'force', None,
4336 _('forcibly copy over an existing managed file')),
4339 _('forcibly copy over an existing managed file')),
4337 ] + walkopts + dryrunopts,
4340 ] + walkopts + dryrunopts,
4338 _('[OPTION]... SOURCE... DEST')),
4341 _('[OPTION]... SOURCE... DEST')),
4339 "resolve":
4342 "resolve":
4340 (resolve,
4343 (resolve,
4341 [('a', 'all', None, _('select all unresolved files')),
4344 [('a', 'all', None, _('select all unresolved files')),
4342 ('l', 'list', None, _('list state of files needing merge')),
4345 ('l', 'list', None, _('list state of files needing merge')),
4343 ('m', 'mark', None, _('mark files as resolved')),
4346 ('m', 'mark', None, _('mark files as resolved')),
4344 ('u', 'unmark', None, _('unmark files as resolved')),
4347 ('u', 'unmark', None, _('unmark files as resolved')),
4345 ('n', 'no-status', None, _('hide status prefix'))]
4348 ('n', 'no-status', None, _('hide status prefix'))]
4346 + walkopts,
4349 + walkopts,
4347 _('[OPTION]... [FILE]...')),
4350 _('[OPTION]... [FILE]...')),
4348 "revert":
4351 "revert":
4349 (revert,
4352 (revert,
4350 [('a', 'all', None, _('revert all changes when no arguments given')),
4353 [('a', 'all', None, _('revert all changes when no arguments given')),
4351 ('d', 'date', '',
4354 ('d', 'date', '',
4352 _('tipmost revision matching date'), _('DATE')),
4355 _('tipmost revision matching date'), _('DATE')),
4353 ('r', 'rev', '',
4356 ('r', 'rev', '',
4354 _('revert to the specified revision'), _('REV')),
4357 _('revert to the specified revision'), _('REV')),
4355 ('', 'no-backup', None, _('do not save backup copies of files')),
4358 ('', 'no-backup', None, _('do not save backup copies of files')),
4356 ] + walkopts + dryrunopts,
4359 ] + walkopts + dryrunopts,
4357 _('[OPTION]... [-r REV] [NAME]...')),
4360 _('[OPTION]... [-r REV] [NAME]...')),
4358 "rollback": (rollback, dryrunopts),
4361 "rollback": (rollback, dryrunopts),
4359 "root": (root, []),
4362 "root": (root, []),
4360 "^serve":
4363 "^serve":
4361 (serve,
4364 (serve,
4362 [('A', 'accesslog', '',
4365 [('A', 'accesslog', '',
4363 _('name of access log file to write to'), _('FILE')),
4366 _('name of access log file to write to'), _('FILE')),
4364 ('d', 'daemon', None, _('run server in background')),
4367 ('d', 'daemon', None, _('run server in background')),
4365 ('', 'daemon-pipefds', '',
4368 ('', 'daemon-pipefds', '',
4366 _('used internally by daemon mode'), _('NUM')),
4369 _('used internally by daemon mode'), _('NUM')),
4367 ('E', 'errorlog', '',
4370 ('E', 'errorlog', '',
4368 _('name of error log file to write to'), _('FILE')),
4371 _('name of error log file to write to'), _('FILE')),
4369 # use string type, then we can check if something was passed
4372 # use string type, then we can check if something was passed
4370 ('p', 'port', '',
4373 ('p', 'port', '',
4371 _('port to listen on (default: 8000)'), _('PORT')),
4374 _('port to listen on (default: 8000)'), _('PORT')),
4372 ('a', 'address', '',
4375 ('a', 'address', '',
4373 _('address to listen on (default: all interfaces)'), _('ADDR')),
4376 _('address to listen on (default: all interfaces)'), _('ADDR')),
4374 ('', 'prefix', '',
4377 ('', 'prefix', '',
4375 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4378 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4376 ('n', 'name', '',
4379 ('n', 'name', '',
4377 _('name to show in web pages (default: working directory)'),
4380 _('name to show in web pages (default: working directory)'),
4378 _('NAME')),
4381 _('NAME')),
4379 ('', 'web-conf', '',
4382 ('', 'web-conf', '',
4380 _('name of the hgweb config file (serve more than one repository)'),
4383 _('name of the hgweb config file (serve more than one repository)'),
4381 _('FILE')),
4384 _('FILE')),
4382 ('', 'webdir-conf', '',
4385 ('', 'webdir-conf', '',
4383 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4386 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4384 ('', 'pid-file', '',
4387 ('', 'pid-file', '',
4385 _('name of file to write process ID to'), _('FILE')),
4388 _('name of file to write process ID to'), _('FILE')),
4386 ('', 'stdio', None, _('for remote clients')),
4389 ('', 'stdio', None, _('for remote clients')),
4387 ('t', 'templates', '',
4390 ('t', 'templates', '',
4388 _('web templates to use'), _('TEMPLATE')),
4391 _('web templates to use'), _('TEMPLATE')),
4389 ('', 'style', '',
4392 ('', 'style', '',
4390 _('template style to use'), _('STYLE')),
4393 _('template style to use'), _('STYLE')),
4391 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4394 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4392 ('', 'certificate', '',
4395 ('', 'certificate', '',
4393 _('SSL certificate file'), _('FILE'))],
4396 _('SSL certificate file'), _('FILE'))],
4394 _('[OPTION]...')),
4397 _('[OPTION]...')),
4395 "showconfig|debugconfig":
4398 "showconfig|debugconfig":
4396 (showconfig,
4399 (showconfig,
4397 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4400 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4398 _('[-u] [NAME]...')),
4401 _('[-u] [NAME]...')),
4399 "^summary|sum":
4402 "^summary|sum":
4400 (summary,
4403 (summary,
4401 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4404 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4402 "^status|st":
4405 "^status|st":
4403 (status,
4406 (status,
4404 [('A', 'all', None, _('show status of all files')),
4407 [('A', 'all', None, _('show status of all files')),
4405 ('m', 'modified', None, _('show only modified files')),
4408 ('m', 'modified', None, _('show only modified files')),
4406 ('a', 'added', None, _('show only added files')),
4409 ('a', 'added', None, _('show only added files')),
4407 ('r', 'removed', None, _('show only removed files')),
4410 ('r', 'removed', None, _('show only removed files')),
4408 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4411 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4409 ('c', 'clean', None, _('show only files without changes')),
4412 ('c', 'clean', None, _('show only files without changes')),
4410 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4413 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4411 ('i', 'ignored', None, _('show only ignored files')),
4414 ('i', 'ignored', None, _('show only ignored files')),
4412 ('n', 'no-status', None, _('hide status prefix')),
4415 ('n', 'no-status', None, _('hide status prefix')),
4413 ('C', 'copies', None, _('show source of copied files')),
4416 ('C', 'copies', None, _('show source of copied files')),
4414 ('0', 'print0', None,
4417 ('0', 'print0', None,
4415 _('end filenames with NUL, for use with xargs')),
4418 _('end filenames with NUL, for use with xargs')),
4416 ('', 'rev', [],
4419 ('', 'rev', [],
4417 _('show difference from revision'), _('REV')),
4420 _('show difference from revision'), _('REV')),
4418 ('', 'change', '',
4421 ('', 'change', '',
4419 _('list the changed files of a revision'), _('REV')),
4422 _('list the changed files of a revision'), _('REV')),
4420 ] + walkopts,
4423 ] + walkopts,
4421 _('[OPTION]... [FILE]...')),
4424 _('[OPTION]... [FILE]...')),
4422 "tag":
4425 "tag":
4423 (tag,
4426 (tag,
4424 [('f', 'force', None, _('replace existing tag')),
4427 [('f', 'force', None, _('replace existing tag')),
4425 ('l', 'local', None, _('make the tag local')),
4428 ('l', 'local', None, _('make the tag local')),
4426 ('r', 'rev', '',
4429 ('r', 'rev', '',
4427 _('revision to tag'), _('REV')),
4430 _('revision to tag'), _('REV')),
4428 ('', 'remove', None, _('remove a tag')),
4431 ('', 'remove', None, _('remove a tag')),
4429 # -l/--local is already there, commitopts cannot be used
4432 # -l/--local is already there, commitopts cannot be used
4430 ('e', 'edit', None, _('edit commit message')),
4433 ('e', 'edit', None, _('edit commit message')),
4431 ('m', 'message', '',
4434 ('m', 'message', '',
4432 _('use <text> as commit message'), _('TEXT')),
4435 _('use <text> as commit message'), _('TEXT')),
4433 ] + commitopts2,
4436 ] + commitopts2,
4434 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4437 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4435 "tags": (tags, [], ''),
4438 "tags": (tags, [], ''),
4436 "tip":
4439 "tip":
4437 (tip,
4440 (tip,
4438 [('p', 'patch', None, _('show patch')),
4441 [('p', 'patch', None, _('show patch')),
4439 ('g', 'git', None, _('use git extended diff format')),
4442 ('g', 'git', None, _('use git extended diff format')),
4440 ] + templateopts,
4443 ] + templateopts,
4441 _('[-p] [-g]')),
4444 _('[-p] [-g]')),
4442 "unbundle":
4445 "unbundle":
4443 (unbundle,
4446 (unbundle,
4444 [('u', 'update', None,
4447 [('u', 'update', None,
4445 _('update to new branch head if changesets were unbundled'))],
4448 _('update to new branch head if changesets were unbundled'))],
4446 _('[-u] FILE...')),
4449 _('[-u] FILE...')),
4447 "^update|up|checkout|co":
4450 "^update|up|checkout|co":
4448 (update,
4451 (update,
4449 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4452 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4450 ('c', 'check', None, _('check for uncommitted changes')),
4453 ('c', 'check', None, _('check for uncommitted changes')),
4451 ('d', 'date', '',
4454 ('d', 'date', '',
4452 _('tipmost revision matching date'), _('DATE')),
4455 _('tipmost revision matching date'), _('DATE')),
4453 ('r', 'rev', '',
4456 ('r', 'rev', '',
4454 _('revision'), _('REV'))],
4457 _('revision'), _('REV'))],
4455 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4458 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4456 "verify": (verify, []),
4459 "verify": (verify, []),
4457 "version": (version_, []),
4460 "version": (version_, []),
4458 }
4461 }
4459
4462
4460 norepo = ("clone init version help debugcommands debugcomplete debugdata"
4463 norepo = ("clone init version help debugcommands debugcomplete debugdata"
4461 " debugindex debugindexdot debugdate debuginstall debugfsinfo"
4464 " debugindex debugindexdot debugdate debuginstall debugfsinfo"
4462 " debugpushkey")
4465 " debugpushkey")
4463 optionalrepo = ("identify paths serve showconfig debugancestor debugdag")
4466 optionalrepo = ("identify paths serve showconfig debugancestor debugdag")
@@ -1,537 +1,544 b''
1 # dispatch.py - command dispatching for mercurial
1 # dispatch.py - command dispatching for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback
10 import util, commands, hg, fancyopts, extensions, hook, error
10 import util, commands, hg, fancyopts, extensions, hook, error
11 import cmdutil, encoding
11 import cmdutil, encoding
12 import ui as uimod
12 import ui as uimod
13
13
14 def run():
14 def run():
15 "run the command in sys.argv"
15 "run the command in sys.argv"
16 sys.exit(dispatch(sys.argv[1:]))
16 sys.exit(dispatch(sys.argv[1:]))
17
17
18 def dispatch(args):
18 def dispatch(args):
19 "run the command specified in args"
19 "run the command specified in args"
20 try:
20 try:
21 u = uimod.ui()
21 u = uimod.ui()
22 if '--traceback' in args:
22 if '--traceback' in args:
23 u.setconfig('ui', 'traceback', 'on')
23 u.setconfig('ui', 'traceback', 'on')
24 except util.Abort, inst:
24 except util.Abort, inst:
25 sys.stderr.write(_("abort: %s\n") % inst)
25 sys.stderr.write(_("abort: %s\n") % inst)
26 return -1
26 return -1
27 except error.ParseError, inst:
27 except error.ParseError, inst:
28 if len(inst.args) > 1:
28 if len(inst.args) > 1:
29 sys.stderr.write(_("hg: parse error at %s: %s\n") %
29 sys.stderr.write(_("hg: parse error at %s: %s\n") %
30 (inst.args[1], inst.args[0]))
30 (inst.args[1], inst.args[0]))
31 else:
31 else:
32 sys.stderr.write(_("hg: parse error: %s\n") % inst.args[0])
32 sys.stderr.write(_("hg: parse error: %s\n") % inst.args[0])
33 return -1
33 return -1
34 return _runcatch(u, args)
34 return _runcatch(u, args)
35
35
36 def _runcatch(ui, args):
36 def _runcatch(ui, args):
37 def catchterm(*args):
37 def catchterm(*args):
38 raise error.SignalInterrupt
38 raise error.SignalInterrupt
39
39
40 try:
40 try:
41 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
41 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
42 num = getattr(signal, name, None)
42 num = getattr(signal, name, None)
43 if num:
43 if num:
44 signal.signal(num, catchterm)
44 signal.signal(num, catchterm)
45 except ValueError:
45 except ValueError:
46 pass # happens if called in a thread
46 pass # happens if called in a thread
47
47
48 try:
48 try:
49 try:
49 try:
50 # enter the debugger before command execution
50 # enter the debugger before command execution
51 if '--debugger' in args:
51 if '--debugger' in args:
52 ui.warn(_("entering debugger - "
52 ui.warn(_("entering debugger - "
53 "type c to continue starting hg or h for help\n"))
53 "type c to continue starting hg or h for help\n"))
54 pdb.set_trace()
54 pdb.set_trace()
55 try:
55 try:
56 return _dispatch(ui, args)
56 return _dispatch(ui, args)
57 finally:
57 finally:
58 ui.flush()
58 ui.flush()
59 except:
59 except:
60 # enter the debugger when we hit an exception
60 # enter the debugger when we hit an exception
61 if '--debugger' in args:
61 if '--debugger' in args:
62 traceback.print_exc()
62 traceback.print_exc()
63 pdb.post_mortem(sys.exc_info()[2])
63 pdb.post_mortem(sys.exc_info()[2])
64 ui.traceback()
64 ui.traceback()
65 raise
65 raise
66
66
67 # Global exception handling, alphabetically
67 # Global exception handling, alphabetically
68 # Mercurial-specific first, followed by built-in and library exceptions
68 # Mercurial-specific first, followed by built-in and library exceptions
69 except error.AmbiguousCommand, inst:
69 except error.AmbiguousCommand, inst:
70 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
70 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
71 (inst.args[0], " ".join(inst.args[1])))
71 (inst.args[0], " ".join(inst.args[1])))
72 except error.ParseError, inst:
72 except error.ParseError, inst:
73 if len(inst.args) > 1:
73 if len(inst.args) > 1:
74 ui.warn(_("hg: parse error at %s: %s\n") %
74 ui.warn(_("hg: parse error at %s: %s\n") %
75 (inst.args[1], inst.args[0]))
75 (inst.args[1], inst.args[0]))
76 else:
76 else:
77 ui.warn(_("hg: parse error: %s\n") % inst.args[0])
77 ui.warn(_("hg: parse error: %s\n") % inst.args[0])
78 return -1
78 return -1
79 except error.LockHeld, inst:
79 except error.LockHeld, inst:
80 if inst.errno == errno.ETIMEDOUT:
80 if inst.errno == errno.ETIMEDOUT:
81 reason = _('timed out waiting for lock held by %s') % inst.locker
81 reason = _('timed out waiting for lock held by %s') % inst.locker
82 else:
82 else:
83 reason = _('lock held by %s') % inst.locker
83 reason = _('lock held by %s') % inst.locker
84 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
84 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
85 except error.LockUnavailable, inst:
85 except error.LockUnavailable, inst:
86 ui.warn(_("abort: could not lock %s: %s\n") %
86 ui.warn(_("abort: could not lock %s: %s\n") %
87 (inst.desc or inst.filename, inst.strerror))
87 (inst.desc or inst.filename, inst.strerror))
88 except error.CommandError, inst:
88 except error.CommandError, inst:
89 if inst.args[0]:
89 if inst.args[0]:
90 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
90 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
91 commands.help_(ui, inst.args[0])
91 commands.help_(ui, inst.args[0])
92 else:
92 else:
93 ui.warn(_("hg: %s\n") % inst.args[1])
93 ui.warn(_("hg: %s\n") % inst.args[1])
94 commands.help_(ui, 'shortlist')
94 commands.help_(ui, 'shortlist')
95 except error.RepoError, inst:
95 except error.RepoError, inst:
96 ui.warn(_("abort: %s!\n") % inst)
96 ui.warn(_("abort: %s!\n") % inst)
97 except error.ResponseError, inst:
97 except error.ResponseError, inst:
98 ui.warn(_("abort: %s") % inst.args[0])
98 ui.warn(_("abort: %s") % inst.args[0])
99 if not isinstance(inst.args[1], basestring):
99 if not isinstance(inst.args[1], basestring):
100 ui.warn(" %r\n" % (inst.args[1],))
100 ui.warn(" %r\n" % (inst.args[1],))
101 elif not inst.args[1]:
101 elif not inst.args[1]:
102 ui.warn(_(" empty string\n"))
102 ui.warn(_(" empty string\n"))
103 else:
103 else:
104 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
104 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
105 except error.RevlogError, inst:
105 except error.RevlogError, inst:
106 ui.warn(_("abort: %s!\n") % inst)
106 ui.warn(_("abort: %s!\n") % inst)
107 except error.SignalInterrupt:
107 except error.SignalInterrupt:
108 ui.warn(_("killed!\n"))
108 ui.warn(_("killed!\n"))
109 except error.UnknownCommand, inst:
109 except error.UnknownCommand, inst:
110 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
110 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
111 try:
111 try:
112 # check if the command is in a disabled extension
112 # check if the command is in a disabled extension
113 # (but don't check for extensions themselves)
113 # (but don't check for extensions themselves)
114 commands.help_(ui, inst.args[0], unknowncmd=True)
114 commands.help_(ui, inst.args[0], unknowncmd=True)
115 except error.UnknownCommand:
115 except error.UnknownCommand:
116 commands.help_(ui, 'shortlist')
116 commands.help_(ui, 'shortlist')
117 except util.Abort, inst:
117 except util.Abort, inst:
118 ui.warn(_("abort: %s\n") % inst)
118 ui.warn(_("abort: %s\n") % inst)
119 except ImportError, inst:
119 except ImportError, inst:
120 ui.warn(_("abort: %s!\n") % inst)
120 ui.warn(_("abort: %s!\n") % inst)
121 m = str(inst).split()[-1]
121 m = str(inst).split()[-1]
122 if m in "mpatch bdiff".split():
122 if m in "mpatch bdiff".split():
123 ui.warn(_("(did you forget to compile extensions?)\n"))
123 ui.warn(_("(did you forget to compile extensions?)\n"))
124 elif m in "zlib".split():
124 elif m in "zlib".split():
125 ui.warn(_("(is your Python install correct?)\n"))
125 ui.warn(_("(is your Python install correct?)\n"))
126 except IOError, inst:
126 except IOError, inst:
127 if hasattr(inst, "code"):
127 if hasattr(inst, "code"):
128 ui.warn(_("abort: %s\n") % inst)
128 ui.warn(_("abort: %s\n") % inst)
129 elif hasattr(inst, "reason"):
129 elif hasattr(inst, "reason"):
130 try: # usually it is in the form (errno, strerror)
130 try: # usually it is in the form (errno, strerror)
131 reason = inst.reason.args[1]
131 reason = inst.reason.args[1]
132 except: # it might be anything, for example a string
132 except: # it might be anything, for example a string
133 reason = inst.reason
133 reason = inst.reason
134 ui.warn(_("abort: error: %s\n") % reason)
134 ui.warn(_("abort: error: %s\n") % reason)
135 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
135 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
136 if ui.debugflag:
136 if ui.debugflag:
137 ui.warn(_("broken pipe\n"))
137 ui.warn(_("broken pipe\n"))
138 elif getattr(inst, "strerror", None):
138 elif getattr(inst, "strerror", None):
139 if getattr(inst, "filename", None):
139 if getattr(inst, "filename", None):
140 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
140 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
141 else:
141 else:
142 ui.warn(_("abort: %s\n") % inst.strerror)
142 ui.warn(_("abort: %s\n") % inst.strerror)
143 else:
143 else:
144 raise
144 raise
145 except OSError, inst:
145 except OSError, inst:
146 if getattr(inst, "filename", None):
146 if getattr(inst, "filename", None):
147 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
147 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
148 else:
148 else:
149 ui.warn(_("abort: %s\n") % inst.strerror)
149 ui.warn(_("abort: %s\n") % inst.strerror)
150 except KeyboardInterrupt:
150 except KeyboardInterrupt:
151 try:
151 try:
152 ui.warn(_("interrupted!\n"))
152 ui.warn(_("interrupted!\n"))
153 except IOError, inst:
153 except IOError, inst:
154 if inst.errno == errno.EPIPE:
154 if inst.errno == errno.EPIPE:
155 if ui.debugflag:
155 if ui.debugflag:
156 ui.warn(_("\nbroken pipe\n"))
156 ui.warn(_("\nbroken pipe\n"))
157 else:
157 else:
158 raise
158 raise
159 except MemoryError:
159 except MemoryError:
160 ui.warn(_("abort: out of memory\n"))
160 ui.warn(_("abort: out of memory\n"))
161 except SystemExit, inst:
161 except SystemExit, inst:
162 # Commands shouldn't sys.exit directly, but give a return code.
162 # Commands shouldn't sys.exit directly, but give a return code.
163 # Just in case catch this and and pass exit code to caller.
163 # Just in case catch this and and pass exit code to caller.
164 return inst.code
164 return inst.code
165 except socket.error, inst:
165 except socket.error, inst:
166 ui.warn(_("abort: %s\n") % inst.args[-1])
166 ui.warn(_("abort: %s\n") % inst.args[-1])
167 except:
167 except:
168 ui.warn(_("** unknown exception encountered, details follow\n"))
168 ui.warn(_("** unknown exception encountered, details follow\n"))
169 ui.warn(_("** report bug details to "
169 ui.warn(_("** report bug details to "
170 "http://mercurial.selenic.com/bts/\n"))
170 "http://mercurial.selenic.com/bts/\n"))
171 ui.warn(_("** or mercurial@selenic.com\n"))
171 ui.warn(_("** or mercurial@selenic.com\n"))
172 ui.warn(_("** Python %s\n") % sys.version.replace('\n', ''))
172 ui.warn(_("** Python %s\n") % sys.version.replace('\n', ''))
173 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
173 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
174 % util.version())
174 % util.version())
175 ui.warn(_("** Extensions loaded: %s\n")
175 ui.warn(_("** Extensions loaded: %s\n")
176 % ", ".join([x[0] for x in extensions.extensions()]))
176 % ", ".join([x[0] for x in extensions.extensions()]))
177 raise
177 raise
178
178
179 return -1
179 return -1
180
180
181 def aliasargs(fn):
181 def aliasargs(fn):
182 if hasattr(fn, 'args'):
182 if hasattr(fn, 'args'):
183 return fn.args
183 return fn.args
184 return []
184 return []
185
185
186 class cmdalias(object):
186 class cmdalias(object):
187 def __init__(self, name, definition, cmdtable):
187 def __init__(self, name, definition, cmdtable):
188 self.name = name
188 self.name = name
189 self.definition = definition
189 self.definition = definition
190 self.args = []
190 self.args = []
191 self.opts = []
191 self.opts = []
192 self.help = ''
192 self.help = ''
193 self.norepo = True
193 self.norepo = True
194 self.badalias = False
194 self.badalias = False
195
195
196 try:
196 try:
197 cmdutil.findcmd(self.name, cmdtable, True)
197 cmdutil.findcmd(self.name, cmdtable, True)
198 self.shadows = True
198 self.shadows = True
199 except error.UnknownCommand:
199 except error.UnknownCommand:
200 self.shadows = False
200 self.shadows = False
201
201
202 if not self.definition:
202 if not self.definition:
203 def fn(ui, *args):
203 def fn(ui, *args):
204 ui.warn(_("no definition for alias '%s'\n") % self.name)
204 ui.warn(_("no definition for alias '%s'\n") % self.name)
205 return 1
205 return 1
206 self.fn = fn
206 self.fn = fn
207 self.badalias = True
207 self.badalias = True
208
208
209 return
209 return
210
210
211 if self.definition.startswith('!'):
212 def fn(ui, *args):
213 cmd = '%s %s' % (self.definition[1:], ' '.join(args))
214 return util.system(cmd)
215 self.fn = fn
216 return
217
211 args = shlex.split(self.definition)
218 args = shlex.split(self.definition)
212 cmd = args.pop(0)
219 cmd = args.pop(0)
213 args = map(util.expandpath, args)
220 args = map(util.expandpath, args)
214
221
215 try:
222 try:
216 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
223 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
217 if len(tableentry) > 2:
224 if len(tableentry) > 2:
218 self.fn, self.opts, self.help = tableentry
225 self.fn, self.opts, self.help = tableentry
219 else:
226 else:
220 self.fn, self.opts = tableentry
227 self.fn, self.opts = tableentry
221
228
222 self.args = aliasargs(self.fn) + args
229 self.args = aliasargs(self.fn) + args
223 if cmd not in commands.norepo.split(' '):
230 if cmd not in commands.norepo.split(' '):
224 self.norepo = False
231 self.norepo = False
225 if self.help.startswith("hg " + cmd):
232 if self.help.startswith("hg " + cmd):
226 # drop prefix in old-style help lines so hg shows the alias
233 # drop prefix in old-style help lines so hg shows the alias
227 self.help = self.help[4 + len(cmd):]
234 self.help = self.help[4 + len(cmd):]
228 self.__doc__ = self.fn.__doc__
235 self.__doc__ = self.fn.__doc__
229
236
230 except error.UnknownCommand:
237 except error.UnknownCommand:
231 def fn(ui, *args):
238 def fn(ui, *args):
232 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
239 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
233 % (self.name, cmd))
240 % (self.name, cmd))
234 try:
241 try:
235 # check if the command is in a disabled extension
242 # check if the command is in a disabled extension
236 commands.help_(ui, cmd, unknowncmd=True)
243 commands.help_(ui, cmd, unknowncmd=True)
237 except error.UnknownCommand:
244 except error.UnknownCommand:
238 pass
245 pass
239 return 1
246 return 1
240 self.fn = fn
247 self.fn = fn
241 self.badalias = True
248 self.badalias = True
242 except error.AmbiguousCommand:
249 except error.AmbiguousCommand:
243 def fn(ui, *args):
250 def fn(ui, *args):
244 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
251 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
245 % (self.name, cmd))
252 % (self.name, cmd))
246 return 1
253 return 1
247 self.fn = fn
254 self.fn = fn
248 self.badalias = True
255 self.badalias = True
249
256
250 def __call__(self, ui, *args, **opts):
257 def __call__(self, ui, *args, **opts):
251 if self.shadows:
258 if self.shadows:
252 ui.debug("alias '%s' shadows command\n" % self.name)
259 ui.debug("alias '%s' shadows command\n" % self.name)
253
260
254 return self.fn(ui, *args, **opts)
261 return self.fn(ui, *args, **opts)
255
262
256 def addaliases(ui, cmdtable):
263 def addaliases(ui, cmdtable):
257 # aliases are processed after extensions have been loaded, so they
264 # aliases are processed after extensions have been loaded, so they
258 # may use extension commands. Aliases can also use other alias definitions,
265 # may use extension commands. Aliases can also use other alias definitions,
259 # but only if they have been defined prior to the current definition.
266 # but only if they have been defined prior to the current definition.
260 for alias, definition in ui.configitems('alias'):
267 for alias, definition in ui.configitems('alias'):
261 aliasdef = cmdalias(alias, definition, cmdtable)
268 aliasdef = cmdalias(alias, definition, cmdtable)
262 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
269 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
263 if aliasdef.norepo:
270 if aliasdef.norepo:
264 commands.norepo += ' %s' % alias
271 commands.norepo += ' %s' % alias
265
272
266 def _parse(ui, args):
273 def _parse(ui, args):
267 options = {}
274 options = {}
268 cmdoptions = {}
275 cmdoptions = {}
269
276
270 try:
277 try:
271 args = fancyopts.fancyopts(args, commands.globalopts, options)
278 args = fancyopts.fancyopts(args, commands.globalopts, options)
272 except fancyopts.getopt.GetoptError, inst:
279 except fancyopts.getopt.GetoptError, inst:
273 raise error.CommandError(None, inst)
280 raise error.CommandError(None, inst)
274
281
275 if args:
282 if args:
276 cmd, args = args[0], args[1:]
283 cmd, args = args[0], args[1:]
277 aliases, entry = cmdutil.findcmd(cmd, commands.table,
284 aliases, entry = cmdutil.findcmd(cmd, commands.table,
278 ui.config("ui", "strict"))
285 ui.config("ui", "strict"))
279 cmd = aliases[0]
286 cmd = aliases[0]
280 args = aliasargs(entry[0]) + args
287 args = aliasargs(entry[0]) + args
281 defaults = ui.config("defaults", cmd)
288 defaults = ui.config("defaults", cmd)
282 if defaults:
289 if defaults:
283 args = map(util.expandpath, shlex.split(defaults)) + args
290 args = map(util.expandpath, shlex.split(defaults)) + args
284 c = list(entry[1])
291 c = list(entry[1])
285 else:
292 else:
286 cmd = None
293 cmd = None
287 c = []
294 c = []
288
295
289 # combine global options into local
296 # combine global options into local
290 for o in commands.globalopts:
297 for o in commands.globalopts:
291 c.append((o[0], o[1], options[o[1]], o[3]))
298 c.append((o[0], o[1], options[o[1]], o[3]))
292
299
293 try:
300 try:
294 args = fancyopts.fancyopts(args, c, cmdoptions, True)
301 args = fancyopts.fancyopts(args, c, cmdoptions, True)
295 except fancyopts.getopt.GetoptError, inst:
302 except fancyopts.getopt.GetoptError, inst:
296 raise error.CommandError(cmd, inst)
303 raise error.CommandError(cmd, inst)
297
304
298 # separate global options back out
305 # separate global options back out
299 for o in commands.globalopts:
306 for o in commands.globalopts:
300 n = o[1]
307 n = o[1]
301 options[n] = cmdoptions[n]
308 options[n] = cmdoptions[n]
302 del cmdoptions[n]
309 del cmdoptions[n]
303
310
304 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
311 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
305
312
306 def _parseconfig(ui, config):
313 def _parseconfig(ui, config):
307 """parse the --config options from the command line"""
314 """parse the --config options from the command line"""
308 for cfg in config:
315 for cfg in config:
309 try:
316 try:
310 name, value = cfg.split('=', 1)
317 name, value = cfg.split('=', 1)
311 section, name = name.split('.', 1)
318 section, name = name.split('.', 1)
312 if not section or not name:
319 if not section or not name:
313 raise IndexError
320 raise IndexError
314 ui.setconfig(section, name, value)
321 ui.setconfig(section, name, value)
315 except (IndexError, ValueError):
322 except (IndexError, ValueError):
316 raise util.Abort(_('malformed --config option: %r '
323 raise util.Abort(_('malformed --config option: %r '
317 '(use --config section.name=value)') % cfg)
324 '(use --config section.name=value)') % cfg)
318
325
319 def _earlygetopt(aliases, args):
326 def _earlygetopt(aliases, args):
320 """Return list of values for an option (or aliases).
327 """Return list of values for an option (or aliases).
321
328
322 The values are listed in the order they appear in args.
329 The values are listed in the order they appear in args.
323 The options and values are removed from args.
330 The options and values are removed from args.
324 """
331 """
325 try:
332 try:
326 argcount = args.index("--")
333 argcount = args.index("--")
327 except ValueError:
334 except ValueError:
328 argcount = len(args)
335 argcount = len(args)
329 shortopts = [opt for opt in aliases if len(opt) == 2]
336 shortopts = [opt for opt in aliases if len(opt) == 2]
330 values = []
337 values = []
331 pos = 0
338 pos = 0
332 while pos < argcount:
339 while pos < argcount:
333 if args[pos] in aliases:
340 if args[pos] in aliases:
334 if pos + 1 >= argcount:
341 if pos + 1 >= argcount:
335 # ignore and let getopt report an error if there is no value
342 # ignore and let getopt report an error if there is no value
336 break
343 break
337 del args[pos]
344 del args[pos]
338 values.append(args.pop(pos))
345 values.append(args.pop(pos))
339 argcount -= 2
346 argcount -= 2
340 elif args[pos][:2] in shortopts:
347 elif args[pos][:2] in shortopts:
341 # short option can have no following space, e.g. hg log -Rfoo
348 # short option can have no following space, e.g. hg log -Rfoo
342 values.append(args.pop(pos)[2:])
349 values.append(args.pop(pos)[2:])
343 argcount -= 1
350 argcount -= 1
344 else:
351 else:
345 pos += 1
352 pos += 1
346 return values
353 return values
347
354
348 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
355 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
349 # run pre-hook, and abort if it fails
356 # run pre-hook, and abort if it fails
350 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
357 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
351 pats=cmdpats, opts=cmdoptions)
358 pats=cmdpats, opts=cmdoptions)
352 if ret:
359 if ret:
353 return ret
360 return ret
354 ret = _runcommand(ui, options, cmd, d)
361 ret = _runcommand(ui, options, cmd, d)
355 # run post-hook, passing command result
362 # run post-hook, passing command result
356 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
363 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
357 result=ret, pats=cmdpats, opts=cmdoptions)
364 result=ret, pats=cmdpats, opts=cmdoptions)
358 return ret
365 return ret
359
366
360 _loaded = set()
367 _loaded = set()
361 def _dispatch(ui, args):
368 def _dispatch(ui, args):
362 # read --config before doing anything else
369 # read --config before doing anything else
363 # (e.g. to change trust settings for reading .hg/hgrc)
370 # (e.g. to change trust settings for reading .hg/hgrc)
364 _parseconfig(ui, _earlygetopt(['--config'], args))
371 _parseconfig(ui, _earlygetopt(['--config'], args))
365
372
366 # check for cwd
373 # check for cwd
367 cwd = _earlygetopt(['--cwd'], args)
374 cwd = _earlygetopt(['--cwd'], args)
368 if cwd:
375 if cwd:
369 os.chdir(cwd[-1])
376 os.chdir(cwd[-1])
370
377
371 # read the local repository .hgrc into a local ui object
378 # read the local repository .hgrc into a local ui object
372 path = cmdutil.findrepo(os.getcwd()) or ""
379 path = cmdutil.findrepo(os.getcwd()) or ""
373 if not path:
380 if not path:
374 lui = ui
381 lui = ui
375 else:
382 else:
376 try:
383 try:
377 lui = ui.copy()
384 lui = ui.copy()
378 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
385 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
379 except IOError:
386 except IOError:
380 pass
387 pass
381
388
382 # now we can expand paths, even ones in .hg/hgrc
389 # now we can expand paths, even ones in .hg/hgrc
383 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
390 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
384 if rpath:
391 if rpath:
385 path = lui.expandpath(rpath[-1])
392 path = lui.expandpath(rpath[-1])
386 lui = ui.copy()
393 lui = ui.copy()
387 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
394 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
388
395
389 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
396 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
390 # reposetup. Programs like TortoiseHg will call _dispatch several
397 # reposetup. Programs like TortoiseHg will call _dispatch several
391 # times so we keep track of configured extensions in _loaded.
398 # times so we keep track of configured extensions in _loaded.
392 extensions.loadall(lui)
399 extensions.loadall(lui)
393 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
400 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
394
401
395 # (uisetup and extsetup are handled in extensions.loadall)
402 # (uisetup and extsetup are handled in extensions.loadall)
396
403
397 for name, module in exts:
404 for name, module in exts:
398 cmdtable = getattr(module, 'cmdtable', {})
405 cmdtable = getattr(module, 'cmdtable', {})
399 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
406 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
400 if overrides:
407 if overrides:
401 ui.warn(_("extension '%s' overrides commands: %s\n")
408 ui.warn(_("extension '%s' overrides commands: %s\n")
402 % (name, " ".join(overrides)))
409 % (name, " ".join(overrides)))
403 commands.table.update(cmdtable)
410 commands.table.update(cmdtable)
404 _loaded.add(name)
411 _loaded.add(name)
405
412
406 # (reposetup is handled in hg.repository)
413 # (reposetup is handled in hg.repository)
407
414
408 addaliases(lui, commands.table)
415 addaliases(lui, commands.table)
409
416
410 # check for fallback encoding
417 # check for fallback encoding
411 fallback = lui.config('ui', 'fallbackencoding')
418 fallback = lui.config('ui', 'fallbackencoding')
412 if fallback:
419 if fallback:
413 encoding.fallbackencoding = fallback
420 encoding.fallbackencoding = fallback
414
421
415 fullargs = args
422 fullargs = args
416 cmd, func, args, options, cmdoptions = _parse(lui, args)
423 cmd, func, args, options, cmdoptions = _parse(lui, args)
417
424
418 if options["config"]:
425 if options["config"]:
419 raise util.Abort(_("Option --config may not be abbreviated!"))
426 raise util.Abort(_("Option --config may not be abbreviated!"))
420 if options["cwd"]:
427 if options["cwd"]:
421 raise util.Abort(_("Option --cwd may not be abbreviated!"))
428 raise util.Abort(_("Option --cwd may not be abbreviated!"))
422 if options["repository"]:
429 if options["repository"]:
423 raise util.Abort(_(
430 raise util.Abort(_(
424 "Option -R has to be separated from other options (e.g. not -qR) "
431 "Option -R has to be separated from other options (e.g. not -qR) "
425 "and --repository may only be abbreviated as --repo!"))
432 "and --repository may only be abbreviated as --repo!"))
426
433
427 if options["encoding"]:
434 if options["encoding"]:
428 encoding.encoding = options["encoding"]
435 encoding.encoding = options["encoding"]
429 if options["encodingmode"]:
436 if options["encodingmode"]:
430 encoding.encodingmode = options["encodingmode"]
437 encoding.encodingmode = options["encodingmode"]
431 if options["time"]:
438 if options["time"]:
432 def get_times():
439 def get_times():
433 t = os.times()
440 t = os.times()
434 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
441 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
435 t = (t[0], t[1], t[2], t[3], time.clock())
442 t = (t[0], t[1], t[2], t[3], time.clock())
436 return t
443 return t
437 s = get_times()
444 s = get_times()
438 def print_time():
445 def print_time():
439 t = get_times()
446 t = get_times()
440 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
447 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
441 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
448 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
442 atexit.register(print_time)
449 atexit.register(print_time)
443
450
444 if options['verbose'] or options['debug'] or options['quiet']:
451 if options['verbose'] or options['debug'] or options['quiet']:
445 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
452 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
446 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
453 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
447 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
454 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
448 if options['traceback']:
455 if options['traceback']:
449 ui.setconfig('ui', 'traceback', 'on')
456 ui.setconfig('ui', 'traceback', 'on')
450 if options['noninteractive']:
457 if options['noninteractive']:
451 ui.setconfig('ui', 'interactive', 'off')
458 ui.setconfig('ui', 'interactive', 'off')
452
459
453 if options['help']:
460 if options['help']:
454 return commands.help_(ui, cmd, options['version'])
461 return commands.help_(ui, cmd, options['version'])
455 elif options['version']:
462 elif options['version']:
456 return commands.version_(ui)
463 return commands.version_(ui)
457 elif not cmd:
464 elif not cmd:
458 return commands.help_(ui, 'shortlist')
465 return commands.help_(ui, 'shortlist')
459
466
460 repo = None
467 repo = None
461 cmdpats = args[:]
468 cmdpats = args[:]
462 if cmd not in commands.norepo.split():
469 if cmd not in commands.norepo.split():
463 try:
470 try:
464 repo = hg.repository(ui, path=path)
471 repo = hg.repository(ui, path=path)
465 ui = repo.ui
472 ui = repo.ui
466 if not repo.local():
473 if not repo.local():
467 raise util.Abort(_("repository '%s' is not local") % path)
474 raise util.Abort(_("repository '%s' is not local") % path)
468 ui.setconfig("bundle", "mainreporoot", repo.root)
475 ui.setconfig("bundle", "mainreporoot", repo.root)
469 except error.RepoError:
476 except error.RepoError:
470 if cmd not in commands.optionalrepo.split():
477 if cmd not in commands.optionalrepo.split():
471 if args and not path: # try to infer -R from command args
478 if args and not path: # try to infer -R from command args
472 repos = map(cmdutil.findrepo, args)
479 repos = map(cmdutil.findrepo, args)
473 guess = repos[0]
480 guess = repos[0]
474 if guess and repos.count(guess) == len(repos):
481 if guess and repos.count(guess) == len(repos):
475 return _dispatch(ui, ['--repository', guess] + fullargs)
482 return _dispatch(ui, ['--repository', guess] + fullargs)
476 if not path:
483 if not path:
477 raise error.RepoError(_("There is no Mercurial repository"
484 raise error.RepoError(_("There is no Mercurial repository"
478 " here (.hg not found)"))
485 " here (.hg not found)"))
479 raise
486 raise
480 args.insert(0, repo)
487 args.insert(0, repo)
481 elif rpath:
488 elif rpath:
482 ui.warn("warning: --repository ignored\n")
489 ui.warn("warning: --repository ignored\n")
483
490
484 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
491 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
485 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
492 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
486 cmdpats, cmdoptions)
493 cmdpats, cmdoptions)
487
494
488 def _runcommand(ui, options, cmd, cmdfunc):
495 def _runcommand(ui, options, cmd, cmdfunc):
489 def checkargs():
496 def checkargs():
490 try:
497 try:
491 return cmdfunc()
498 return cmdfunc()
492 except error.SignatureError:
499 except error.SignatureError:
493 raise error.CommandError(cmd, _("invalid arguments"))
500 raise error.CommandError(cmd, _("invalid arguments"))
494
501
495 if options['profile']:
502 if options['profile']:
496 format = ui.config('profiling', 'format', default='text')
503 format = ui.config('profiling', 'format', default='text')
497
504
498 if not format in ['text', 'kcachegrind']:
505 if not format in ['text', 'kcachegrind']:
499 ui.warn(_("unrecognized profiling format '%s'"
506 ui.warn(_("unrecognized profiling format '%s'"
500 " - Ignored\n") % format)
507 " - Ignored\n") % format)
501 format = 'text'
508 format = 'text'
502
509
503 output = ui.config('profiling', 'output')
510 output = ui.config('profiling', 'output')
504
511
505 if output:
512 if output:
506 path = ui.expandpath(output)
513 path = ui.expandpath(output)
507 ostream = open(path, 'wb')
514 ostream = open(path, 'wb')
508 else:
515 else:
509 ostream = sys.stderr
516 ostream = sys.stderr
510
517
511 try:
518 try:
512 from mercurial import lsprof
519 from mercurial import lsprof
513 except ImportError:
520 except ImportError:
514 raise util.Abort(_(
521 raise util.Abort(_(
515 'lsprof not available - install from '
522 'lsprof not available - install from '
516 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
523 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
517 p = lsprof.Profiler()
524 p = lsprof.Profiler()
518 p.enable(subcalls=True)
525 p.enable(subcalls=True)
519 try:
526 try:
520 return checkargs()
527 return checkargs()
521 finally:
528 finally:
522 p.disable()
529 p.disable()
523
530
524 if format == 'kcachegrind':
531 if format == 'kcachegrind':
525 import lsprofcalltree
532 import lsprofcalltree
526 calltree = lsprofcalltree.KCacheGrind(p)
533 calltree = lsprofcalltree.KCacheGrind(p)
527 calltree.output(ostream)
534 calltree.output(ostream)
528 else:
535 else:
529 # format == 'text'
536 # format == 'text'
530 stats = lsprof.Stats(p.getstats())
537 stats = lsprof.Stats(p.getstats())
531 stats.sort()
538 stats.sort()
532 stats.pprint(top=10, file=ostream, climit=5)
539 stats.pprint(top=10, file=ostream, climit=5)
533
540
534 if output:
541 if output:
535 ostream.close()
542 ostream.close()
536 else:
543 else:
537 return checkargs()
544 return checkargs()
@@ -1,66 +1,70 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 cat >> $HGRCPATH <<EOF
3 cat >> $HGRCPATH <<EOF
4 [alias]
4 [alias]
5 myinit = init
5 myinit = init
6 cleanstatus = status -c
6 cleanstatus = status -c
7 unknown = bargle
7 unknown = bargle
8 ambiguous = s
8 ambiguous = s
9 recursive = recursive
9 recursive = recursive
10 nodefinition =
10 nodefinition =
11 mylog = log
11 mylog = log
12 lognull = log -r null
12 lognull = log -r null
13 shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
13 shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
14 dln = lognull --debug
14 dln = lognull --debug
15 nousage = rollback
15 nousage = rollback
16 put = export -r 0 -o "\$FOO/%R.diff"
16 put = export -r 0 -o "\$FOO/%R.diff"
17 echo = !echo
17
18
18 [defaults]
19 [defaults]
19 mylog = -q
20 mylog = -q
20 lognull = -q
21 lognull = -q
21 log = -v
22 log = -v
22 EOF
23 EOF
23
24
24 echo '% basic'
25 echo '% basic'
25 hg myinit alias
26 hg myinit alias
26
27
27 echo '% unknown'
28 echo '% unknown'
28 hg unknown
29 hg unknown
29 hg help unknown
30 hg help unknown
30
31
31 echo '% ambiguous'
32 echo '% ambiguous'
32 hg ambiguous
33 hg ambiguous
33 hg help ambiguous
34 hg help ambiguous
34
35
35 echo '% recursive'
36 echo '% recursive'
36 hg recursive
37 hg recursive
37 hg help recursive
38 hg help recursive
38
39
39 echo '% no definition'
40 echo '% no definition'
40 hg nodef
41 hg nodef
41 hg help nodef
42 hg help nodef
42
43
43 cd alias
44 cd alias
44
45
45 echo '% no usage'
46 echo '% no usage'
46 hg nousage
47 hg nousage
47
48
48 echo foo > foo
49 echo foo > foo
49 hg ci -Amfoo
50 hg ci -Amfoo
50
51
51 echo '% with opts'
52 echo '% with opts'
52 hg cleanst
53 hg cleanst
53
54
54 echo '% with opts and whitespace'
55 echo '% with opts and whitespace'
55 hg shortlog
56 hg shortlog
56
57
57 echo '% interaction with defaults'
58 echo '% interaction with defaults'
58 hg mylog
59 hg mylog
59 hg lognull
60 hg lognull
60
61
61 echo '% properly recursive'
62 echo '% properly recursive'
62 hg dln
63 hg dln
63
64
64 echo '% path expanding'
65 echo '% path expanding'
65 FOO=`pwd` hg put
66 FOO=`pwd` hg put
66 cat 0.diff
67 cat 0.diff
68
69 echo '% shell aliases'
70 hg echo foo
@@ -1,45 +1,47 b''
1 % basic
1 % basic
2 % unknown
2 % unknown
3 alias 'unknown' resolves to unknown command 'bargle'
3 alias 'unknown' resolves to unknown command 'bargle'
4 alias 'unknown' resolves to unknown command 'bargle'
4 alias 'unknown' resolves to unknown command 'bargle'
5 % ambiguous
5 % ambiguous
6 alias 'ambiguous' resolves to ambiguous command 's'
6 alias 'ambiguous' resolves to ambiguous command 's'
7 alias 'ambiguous' resolves to ambiguous command 's'
7 alias 'ambiguous' resolves to ambiguous command 's'
8 % recursive
8 % recursive
9 alias 'recursive' resolves to unknown command 'recursive'
9 alias 'recursive' resolves to unknown command 'recursive'
10 alias 'recursive' resolves to unknown command 'recursive'
10 alias 'recursive' resolves to unknown command 'recursive'
11 % no definition
11 % no definition
12 no definition for alias 'nodefinition'
12 no definition for alias 'nodefinition'
13 no definition for alias 'nodefinition'
13 no definition for alias 'nodefinition'
14 % no usage
14 % no usage
15 no rollback information available
15 no rollback information available
16 adding foo
16 adding foo
17 % with opts
17 % with opts
18 C foo
18 C foo
19 % with opts and whitespace
19 % with opts and whitespace
20 0 e63c23eaa88a | 1970-01-01 00:00 +0000
20 0 e63c23eaa88a | 1970-01-01 00:00 +0000
21 % interaction with defaults
21 % interaction with defaults
22 0:e63c23eaa88a
22 0:e63c23eaa88a
23 -1:000000000000
23 -1:000000000000
24 % properly recursive
24 % properly recursive
25 changeset: -1:0000000000000000000000000000000000000000
25 changeset: -1:0000000000000000000000000000000000000000
26 parent: -1:0000000000000000000000000000000000000000
26 parent: -1:0000000000000000000000000000000000000000
27 parent: -1:0000000000000000000000000000000000000000
27 parent: -1:0000000000000000000000000000000000000000
28 manifest: -1:0000000000000000000000000000000000000000
28 manifest: -1:0000000000000000000000000000000000000000
29 user:
29 user:
30 date: Thu Jan 01 00:00:00 1970 +0000
30 date: Thu Jan 01 00:00:00 1970 +0000
31 extra: branch=default
31 extra: branch=default
32
32
33 % path expanding
33 % path expanding
34 # HG changeset patch
34 # HG changeset patch
35 # User test
35 # User test
36 # Date 0 0
36 # Date 0 0
37 # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
37 # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
38 # Parent 0000000000000000000000000000000000000000
38 # Parent 0000000000000000000000000000000000000000
39 foo
39 foo
40
40
41 diff -r 000000000000 -r e63c23eaa88a foo
41 diff -r 000000000000 -r e63c23eaa88a foo
42 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
43 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
44 @@ -0,0 +1,1 @@
44 @@ -0,0 +1,1 @@
45 +foo
45 +foo
46 % shell aliases
47 foo
General Comments 0
You need to be logged in to leave comments. Login now