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