##// END OF EJS Templates
merge with stable
Martin Geisler -
r13343:69e69b13 merge default
parent child Browse files
Show More
@@ -1,4537 +1,4533
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, extensions, copies, error
12 import hg, util, revlog, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 opts.get('subrepos'), prefix="")
51 opts.get('subrepos'), prefix="")
52 return rejected and 1 or 0
52 return rejected and 1 or 0
53
53
54 def addremove(ui, repo, *pats, **opts):
54 def addremove(ui, repo, *pats, **opts):
55 """add all new files, delete all missing files
55 """add all new files, delete all missing files
56
56
57 Add all new files and remove all missing files from the
57 Add all new files and remove all missing files from the
58 repository.
58 repository.
59
59
60 New files are ignored if they match any of the patterns in
60 New files are ignored if they match any of the patterns in
61 .hgignore. As with add, these changes take effect at the next
61 .hgignore. As with add, these changes take effect at the next
62 commit.
62 commit.
63
63
64 Use the -s/--similarity option to detect renamed files. With a
64 Use the -s/--similarity option to detect renamed files. With a
65 parameter greater than 0, this compares every removed file with
65 parameter greater than 0, this compares every removed file with
66 every added file and records those similar enough as renames. This
66 every added file and records those similar enough as renames. This
67 option takes a percentage between 0 (disabled) and 100 (files must
67 option takes a percentage between 0 (disabled) and 100 (files must
68 be identical) as its parameter. Detecting renamed files this way
68 be identical) as its parameter. Detecting renamed files this way
69 can be expensive. After using this option, :hg:`status -C` can be
69 can be expensive. After using this option, :hg:`status -C` can be
70 used to check which files were identified as moved or renamed.
70 used to check which files were identified as moved or renamed.
71
71
72 Returns 0 if all files are successfully added.
72 Returns 0 if all files are successfully added.
73 """
73 """
74 try:
74 try:
75 sim = float(opts.get('similarity') or 100)
75 sim = float(opts.get('similarity') or 100)
76 except ValueError:
76 except ValueError:
77 raise util.Abort(_('similarity must be a number'))
77 raise util.Abort(_('similarity must be a number'))
78 if sim < 0 or sim > 100:
78 if sim < 0 or sim > 100:
79 raise util.Abort(_('similarity must be between 0 and 100'))
79 raise util.Abort(_('similarity must be between 0 and 100'))
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81
81
82 def annotate(ui, repo, *pats, **opts):
82 def annotate(ui, repo, *pats, **opts):
83 """show changeset information by line for each file
83 """show changeset information by line for each file
84
84
85 List changes in files, showing the revision id responsible for
85 List changes in files, showing the revision id responsible for
86 each line
86 each line
87
87
88 This command is useful for discovering when a change was made and
88 This command is useful for discovering when a change was made and
89 by whom.
89 by whom.
90
90
91 Without the -a/--text option, annotate will avoid processing files
91 Without the -a/--text option, annotate will avoid processing files
92 it detects as binary. With -a, annotate will annotate the file
92 it detects as binary. With -a, annotate will annotate the file
93 anyway, although the results will probably be neither useful
93 anyway, although the results will probably be neither useful
94 nor desirable.
94 nor desirable.
95
95
96 Returns 0 on success.
96 Returns 0 on success.
97 """
97 """
98 if opts.get('follow'):
98 if opts.get('follow'):
99 # --follow is deprecated and now just an alias for -f/--file
99 # --follow is deprecated and now just an alias for -f/--file
100 # to mimic the behavior of Mercurial before version 1.5
100 # to mimic the behavior of Mercurial before version 1.5
101 opts['file'] = 1
101 opts['file'] = 1
102
102
103 datefunc = ui.quiet and util.shortdate or util.datestr
103 datefunc = ui.quiet and util.shortdate or util.datestr
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105
105
106 if not pats:
106 if not pats:
107 raise util.Abort(_('at least one filename or pattern is required'))
107 raise util.Abort(_('at least one filename or pattern is required'))
108
108
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 ('number', lambda x: str(x[0].rev())),
110 ('number', lambda x: str(x[0].rev())),
111 ('changeset', lambda x: short(x[0].node())),
111 ('changeset', lambda x: short(x[0].node())),
112 ('date', getdate),
112 ('date', getdate),
113 ('file', lambda x: x[0].path()),
113 ('file', lambda x: x[0].path()),
114 ]
114 ]
115
115
116 if (not opts.get('user') and not opts.get('changeset')
116 if (not opts.get('user') and not opts.get('changeset')
117 and not opts.get('date') and not opts.get('file')):
117 and not opts.get('date') and not opts.get('file')):
118 opts['number'] = 1
118 opts['number'] = 1
119
119
120 linenumber = opts.get('line_number') is not None
120 linenumber = opts.get('line_number') is not None
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123
123
124 funcmap = [func for op, func in opmap if opts.get(op)]
124 funcmap = [func for op, func in opmap if opts.get(op)]
125 if linenumber:
125 if linenumber:
126 lastfunc = funcmap[-1]
126 lastfunc = funcmap[-1]
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128
128
129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
130 m = cmdutil.match(repo, pats, opts)
130 m = cmdutil.match(repo, pats, opts)
131 follow = not opts.get('no_follow')
131 follow = not opts.get('no_follow')
132 for abs in ctx.walk(m):
132 for abs in ctx.walk(m):
133 fctx = ctx[abs]
133 fctx = ctx[abs]
134 if not opts.get('text') and util.binary(fctx.data()):
134 if not opts.get('text') and util.binary(fctx.data()):
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 continue
136 continue
137
137
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 pieces = []
139 pieces = []
140
140
141 for f in funcmap:
141 for f in funcmap:
142 l = [f(n) for n, dummy in lines]
142 l = [f(n) for n, dummy in lines]
143 if l:
143 if l:
144 sized = [(x, encoding.colwidth(x)) for x in l]
144 sized = [(x, encoding.colwidth(x)) for x in l]
145 ml = max([w for x, w in sized])
145 ml = max([w for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147
147
148 if pieces:
148 if pieces:
149 for p, l in zip(zip(*pieces), lines):
149 for p, l in zip(zip(*pieces), lines):
150 ui.write("%s: %s" % (" ".join(p), l[1]))
150 ui.write("%s: %s" % (" ".join(p), l[1]))
151
151
152 def archive(ui, repo, dest, **opts):
152 def archive(ui, repo, dest, **opts):
153 '''create an unversioned archive of a repository revision
153 '''create an unversioned archive of a repository revision
154
154
155 By default, the revision used is the parent of the working
155 By default, the revision used is the parent of the working
156 directory; use -r/--rev to specify a different revision.
156 directory; use -r/--rev to specify a different revision.
157
157
158 The archive type is automatically detected based on file
158 The archive type is automatically detected based on file
159 extension (or override using -t/--type).
159 extension (or override using -t/--type).
160
160
161 Valid types are:
161 Valid types are:
162
162
163 :``files``: a directory full of files (default)
163 :``files``: a directory full of files (default)
164 :``tar``: tar archive, uncompressed
164 :``tar``: tar archive, uncompressed
165 :``tbz2``: tar archive, compressed using bzip2
165 :``tbz2``: tar archive, compressed using bzip2
166 :``tgz``: tar archive, compressed using gzip
166 :``tgz``: tar archive, compressed using gzip
167 :``uzip``: zip archive, uncompressed
167 :``uzip``: zip archive, uncompressed
168 :``zip``: zip archive, compressed using deflate
168 :``zip``: zip archive, compressed using deflate
169
169
170 The exact name of the destination archive or directory is given
170 The exact name of the destination archive or directory is given
171 using a format string; see :hg:`help export` for details.
171 using a format string; see :hg:`help export` for details.
172
172
173 Each member added to an archive file has a directory prefix
173 Each member added to an archive file has a directory prefix
174 prepended. Use -p/--prefix to specify a format string for the
174 prepended. Use -p/--prefix to specify a format string for the
175 prefix. The default is the basename of the archive, with suffixes
175 prefix. The default is the basename of the archive, with suffixes
176 removed.
176 removed.
177
177
178 Returns 0 on success.
178 Returns 0 on success.
179 '''
179 '''
180
180
181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
182 if not ctx:
182 if not ctx:
183 raise util.Abort(_('no working directory: please specify a revision'))
183 raise util.Abort(_('no working directory: please specify a revision'))
184 node = ctx.node()
184 node = ctx.node()
185 dest = cmdutil.make_filename(repo, dest, node)
185 dest = cmdutil.make_filename(repo, dest, node)
186 if os.path.realpath(dest) == repo.root:
186 if os.path.realpath(dest) == repo.root:
187 raise util.Abort(_('repository root cannot be destination'))
187 raise util.Abort(_('repository root cannot be destination'))
188
188
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 prefix = opts.get('prefix')
190 prefix = opts.get('prefix')
191
191
192 if dest == '-':
192 if dest == '-':
193 if kind == 'files':
193 if kind == 'files':
194 raise util.Abort(_('cannot archive plain files to stdout'))
194 raise util.Abort(_('cannot archive plain files to stdout'))
195 dest = sys.stdout
195 dest = sys.stdout
196 if not prefix:
196 if not prefix:
197 prefix = os.path.basename(repo.root) + '-%h'
197 prefix = os.path.basename(repo.root) + '-%h'
198
198
199 prefix = cmdutil.make_filename(repo, prefix, node)
199 prefix = cmdutil.make_filename(repo, prefix, node)
200 matchfn = cmdutil.match(repo, [], opts)
200 matchfn = cmdutil.match(repo, [], opts)
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 matchfn, prefix, subrepos=opts.get('subrepos'))
202 matchfn, prefix, subrepos=opts.get('subrepos'))
203
203
204 def backout(ui, repo, node=None, rev=None, **opts):
204 def backout(ui, repo, node=None, rev=None, **opts):
205 '''reverse effect of earlier changeset
205 '''reverse effect of earlier changeset
206
206
207 The backout command merges the reverse effect of the reverted
207 Prepare a new changeset with the effect of REV undone in the
208 changeset into the working directory.
208 current working directory.
209
209
210 With the --merge option, it first commits the reverted changes
210 If REV is the parent of the working directory, then this changeset
211 as a new changeset. This new changeset is a child of the reverted
211 is committed automatically. Otherwise, hg needs to merge the
212 changeset.
212 changes and the merged result is left uncommitted.
213 The --merge option remembers the parent of the working directory
213
214 before starting the backout, then merges the new head with that
214 By default, the pending changeset will have one parent,
215 changeset afterwards.
215 maintaining a linear history. With --merge, the pending changeset
216 This will result in an explicit merge in the history.
216 will instead have two parents: the old parent of the working
217
217 directory and a child of REV that simply undoes REV.
218 If you backout a changeset other than the original parent of the
218
219 working directory, the result of this merge is not committed,
219 Before version 1.7, the default behavior was equivalent to
220 as with a normal merge. Otherwise, no merge is needed and the
220 specifying --merge followed by :hg:`update --clean .` to cancel
221 commit is automatic.
221 the merge and leave the child of REV as a head to be merged
222
222 separately.
223 Note that the default behavior (without --merge) has changed in
224 version 1.7. To restore the previous default behavior, use
225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
226 the ongoing merge.
227
223
228 See :hg:`help dates` for a list of formats valid for -d/--date.
224 See :hg:`help dates` for a list of formats valid for -d/--date.
229
225
230 Returns 0 on success.
226 Returns 0 on success.
231 '''
227 '''
232 if rev and node:
228 if rev and node:
233 raise util.Abort(_("please specify just one revision"))
229 raise util.Abort(_("please specify just one revision"))
234
230
235 if not rev:
231 if not rev:
236 rev = node
232 rev = node
237
233
238 if not rev:
234 if not rev:
239 raise util.Abort(_("please specify a revision to backout"))
235 raise util.Abort(_("please specify a revision to backout"))
240
236
241 date = opts.get('date')
237 date = opts.get('date')
242 if date:
238 if date:
243 opts['date'] = util.parsedate(date)
239 opts['date'] = util.parsedate(date)
244
240
245 cmdutil.bail_if_changed(repo)
241 cmdutil.bail_if_changed(repo)
246 node = cmdutil.revsingle(repo, rev).node()
242 node = cmdutil.revsingle(repo, rev).node()
247
243
248 op1, op2 = repo.dirstate.parents()
244 op1, op2 = repo.dirstate.parents()
249 a = repo.changelog.ancestor(op1, node)
245 a = repo.changelog.ancestor(op1, node)
250 if a != node:
246 if a != node:
251 raise util.Abort(_('cannot backout change on a different branch'))
247 raise util.Abort(_('cannot backout change on a different branch'))
252
248
253 p1, p2 = repo.changelog.parents(node)
249 p1, p2 = repo.changelog.parents(node)
254 if p1 == nullid:
250 if p1 == nullid:
255 raise util.Abort(_('cannot backout a change with no parents'))
251 raise util.Abort(_('cannot backout a change with no parents'))
256 if p2 != nullid:
252 if p2 != nullid:
257 if not opts.get('parent'):
253 if not opts.get('parent'):
258 raise util.Abort(_('cannot backout a merge changeset without '
254 raise util.Abort(_('cannot backout a merge changeset without '
259 '--parent'))
255 '--parent'))
260 p = repo.lookup(opts['parent'])
256 p = repo.lookup(opts['parent'])
261 if p not in (p1, p2):
257 if p not in (p1, p2):
262 raise util.Abort(_('%s is not a parent of %s') %
258 raise util.Abort(_('%s is not a parent of %s') %
263 (short(p), short(node)))
259 (short(p), short(node)))
264 parent = p
260 parent = p
265 else:
261 else:
266 if opts.get('parent'):
262 if opts.get('parent'):
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
263 raise util.Abort(_('cannot use --parent on non-merge changeset'))
268 parent = p1
264 parent = p1
269
265
270 # the backout should appear on the same branch
266 # the backout should appear on the same branch
271 branch = repo.dirstate.branch()
267 branch = repo.dirstate.branch()
272 hg.clean(repo, node, show_stats=False)
268 hg.clean(repo, node, show_stats=False)
273 repo.dirstate.setbranch(branch)
269 repo.dirstate.setbranch(branch)
274 revert_opts = opts.copy()
270 revert_opts = opts.copy()
275 revert_opts['date'] = None
271 revert_opts['date'] = None
276 revert_opts['all'] = True
272 revert_opts['all'] = True
277 revert_opts['rev'] = hex(parent)
273 revert_opts['rev'] = hex(parent)
278 revert_opts['no_backup'] = None
274 revert_opts['no_backup'] = None
279 revert(ui, repo, **revert_opts)
275 revert(ui, repo, **revert_opts)
280 if not opts.get('merge') and op1 != node:
276 if not opts.get('merge') and op1 != node:
281 try:
277 try:
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
278 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
283 return hg.update(repo, op1)
279 return hg.update(repo, op1)
284 finally:
280 finally:
285 ui.setconfig('ui', 'forcemerge', '')
281 ui.setconfig('ui', 'forcemerge', '')
286
282
287 commit_opts = opts.copy()
283 commit_opts = opts.copy()
288 commit_opts['addremove'] = False
284 commit_opts['addremove'] = False
289 if not commit_opts['message'] and not commit_opts['logfile']:
285 if not commit_opts['message'] and not commit_opts['logfile']:
290 # we don't translate commit messages
286 # we don't translate commit messages
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
287 commit_opts['message'] = "Backed out changeset %s" % short(node)
292 commit_opts['force_editor'] = True
288 commit_opts['force_editor'] = True
293 commit(ui, repo, **commit_opts)
289 commit(ui, repo, **commit_opts)
294 def nice(node):
290 def nice(node):
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
291 return '%d:%s' % (repo.changelog.rev(node), short(node))
296 ui.status(_('changeset %s backs out changeset %s\n') %
292 ui.status(_('changeset %s backs out changeset %s\n') %
297 (nice(repo.changelog.tip()), nice(node)))
293 (nice(repo.changelog.tip()), nice(node)))
298 if opts.get('merge') and op1 != node:
294 if opts.get('merge') and op1 != node:
299 hg.clean(repo, op1, show_stats=False)
295 hg.clean(repo, op1, show_stats=False)
300 ui.status(_('merging with changeset %s\n')
296 ui.status(_('merging with changeset %s\n')
301 % nice(repo.changelog.tip()))
297 % nice(repo.changelog.tip()))
302 try:
298 try:
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
299 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
304 return hg.merge(repo, hex(repo.changelog.tip()))
300 return hg.merge(repo, hex(repo.changelog.tip()))
305 finally:
301 finally:
306 ui.setconfig('ui', 'forcemerge', '')
302 ui.setconfig('ui', 'forcemerge', '')
307 return 0
303 return 0
308
304
309 def bisect(ui, repo, rev=None, extra=None, command=None,
305 def bisect(ui, repo, rev=None, extra=None, command=None,
310 reset=None, good=None, bad=None, skip=None, noupdate=None):
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
311 """subdivision search of changesets
307 """subdivision search of changesets
312
308
313 This command helps to find changesets which introduce problems. To
309 This command helps to find changesets which introduce problems. To
314 use, mark the earliest changeset you know exhibits the problem as
310 use, mark the earliest changeset you know exhibits the problem as
315 bad, then mark the latest changeset which is free from the problem
311 bad, then mark the latest changeset which is free from the problem
316 as good. Bisect will update your working directory to a revision
312 as good. Bisect will update your working directory to a revision
317 for testing (unless the -U/--noupdate option is specified). Once
313 for testing (unless the -U/--noupdate option is specified). Once
318 you have performed tests, mark the working directory as good or
314 you have performed tests, mark the working directory as good or
319 bad, and bisect will either update to another candidate changeset
315 bad, and bisect will either update to another candidate changeset
320 or announce that it has found the bad revision.
316 or announce that it has found the bad revision.
321
317
322 As a shortcut, you can also use the revision argument to mark a
318 As a shortcut, you can also use the revision argument to mark a
323 revision as good or bad without checking it out first.
319 revision as good or bad without checking it out first.
324
320
325 If you supply a command, it will be used for automatic bisection.
321 If you supply a command, it will be used for automatic bisection.
326 Its exit status will be used to mark revisions as good or bad:
322 Its exit status will be used to mark revisions as good or bad:
327 status 0 means good, 125 means to skip the revision, 127
323 status 0 means good, 125 means to skip the revision, 127
328 (command not found) will abort the bisection, and any other
324 (command not found) will abort the bisection, and any other
329 non-zero exit status means the revision is bad.
325 non-zero exit status means the revision is bad.
330
326
331 Returns 0 on success.
327 Returns 0 on success.
332 """
328 """
333 def print_result(nodes, good):
329 def print_result(nodes, good):
334 displayer = cmdutil.show_changeset(ui, repo, {})
330 displayer = cmdutil.show_changeset(ui, repo, {})
335 if len(nodes) == 1:
331 if len(nodes) == 1:
336 # narrowed it down to a single revision
332 # narrowed it down to a single revision
337 if good:
333 if good:
338 ui.write(_("The first good revision is:\n"))
334 ui.write(_("The first good revision is:\n"))
339 else:
335 else:
340 ui.write(_("The first bad revision is:\n"))
336 ui.write(_("The first bad revision is:\n"))
341 displayer.show(repo[nodes[0]])
337 displayer.show(repo[nodes[0]])
342 parents = repo[nodes[0]].parents()
338 parents = repo[nodes[0]].parents()
343 if len(parents) > 1:
339 if len(parents) > 1:
344 side = good and state['bad'] or state['good']
340 side = good and state['bad'] or state['good']
345 num = len(set(i.node() for i in parents) & set(side))
341 num = len(set(i.node() for i in parents) & set(side))
346 if num == 1:
342 if num == 1:
347 common = parents[0].ancestor(parents[1])
343 common = parents[0].ancestor(parents[1])
348 ui.write(_('Not all ancestors of this changeset have been'
344 ui.write(_('Not all ancestors of this changeset have been'
349 ' checked.\nTo check the other ancestors, start'
345 ' checked.\nTo check the other ancestors, start'
350 ' from the common ancestor, %s.\n' % common))
346 ' from the common ancestor, %s.\n' % common))
351 else:
347 else:
352 # multiple possible revisions
348 # multiple possible revisions
353 if good:
349 if good:
354 ui.write(_("Due to skipped revisions, the first "
350 ui.write(_("Due to skipped revisions, the first "
355 "good revision could be any of:\n"))
351 "good revision could be any of:\n"))
356 else:
352 else:
357 ui.write(_("Due to skipped revisions, the first "
353 ui.write(_("Due to skipped revisions, the first "
358 "bad revision could be any of:\n"))
354 "bad revision could be any of:\n"))
359 for n in nodes:
355 for n in nodes:
360 displayer.show(repo[n])
356 displayer.show(repo[n])
361 displayer.close()
357 displayer.close()
362
358
363 def check_state(state, interactive=True):
359 def check_state(state, interactive=True):
364 if not state['good'] or not state['bad']:
360 if not state['good'] or not state['bad']:
365 if (good or bad or skip or reset) and interactive:
361 if (good or bad or skip or reset) and interactive:
366 return
362 return
367 if not state['good']:
363 if not state['good']:
368 raise util.Abort(_('cannot bisect (no known good revisions)'))
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
369 else:
365 else:
370 raise util.Abort(_('cannot bisect (no known bad revisions)'))
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
371 return True
367 return True
372
368
373 # backward compatibility
369 # backward compatibility
374 if rev in "good bad reset init".split():
370 if rev in "good bad reset init".split():
375 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
376 cmd, rev, extra = rev, extra, None
372 cmd, rev, extra = rev, extra, None
377 if cmd == "good":
373 if cmd == "good":
378 good = True
374 good = True
379 elif cmd == "bad":
375 elif cmd == "bad":
380 bad = True
376 bad = True
381 else:
377 else:
382 reset = True
378 reset = True
383 elif extra or good + bad + skip + reset + bool(command) > 1:
379 elif extra or good + bad + skip + reset + bool(command) > 1:
384 raise util.Abort(_('incompatible arguments'))
380 raise util.Abort(_('incompatible arguments'))
385
381
386 if reset:
382 if reset:
387 p = repo.join("bisect.state")
383 p = repo.join("bisect.state")
388 if os.path.exists(p):
384 if os.path.exists(p):
389 os.unlink(p)
385 os.unlink(p)
390 return
386 return
391
387
392 state = hbisect.load_state(repo)
388 state = hbisect.load_state(repo)
393
389
394 if command:
390 if command:
395 changesets = 1
391 changesets = 1
396 try:
392 try:
397 while changesets:
393 while changesets:
398 # update state
394 # update state
399 status = util.system(command)
395 status = util.system(command)
400 if status == 125:
396 if status == 125:
401 transition = "skip"
397 transition = "skip"
402 elif status == 0:
398 elif status == 0:
403 transition = "good"
399 transition = "good"
404 # status < 0 means process was killed
400 # status < 0 means process was killed
405 elif status == 127:
401 elif status == 127:
406 raise util.Abort(_("failed to execute %s") % command)
402 raise util.Abort(_("failed to execute %s") % command)
407 elif status < 0:
403 elif status < 0:
408 raise util.Abort(_("%s killed") % command)
404 raise util.Abort(_("%s killed") % command)
409 else:
405 else:
410 transition = "bad"
406 transition = "bad"
411 ctx = cmdutil.revsingle(repo, rev)
407 ctx = cmdutil.revsingle(repo, rev)
412 rev = None # clear for future iterations
408 rev = None # clear for future iterations
413 state[transition].append(ctx.node())
409 state[transition].append(ctx.node())
414 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
410 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
415 check_state(state, interactive=False)
411 check_state(state, interactive=False)
416 # bisect
412 # bisect
417 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
413 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
418 # update to next check
414 # update to next check
419 cmdutil.bail_if_changed(repo)
415 cmdutil.bail_if_changed(repo)
420 hg.clean(repo, nodes[0], show_stats=False)
416 hg.clean(repo, nodes[0], show_stats=False)
421 finally:
417 finally:
422 hbisect.save_state(repo, state)
418 hbisect.save_state(repo, state)
423 print_result(nodes, good)
419 print_result(nodes, good)
424 return
420 return
425
421
426 # update state
422 # update state
427
423
428 if rev:
424 if rev:
429 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
425 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
430 else:
426 else:
431 nodes = [repo.lookup('.')]
427 nodes = [repo.lookup('.')]
432
428
433 if good or bad or skip:
429 if good or bad or skip:
434 if good:
430 if good:
435 state['good'] += nodes
431 state['good'] += nodes
436 elif bad:
432 elif bad:
437 state['bad'] += nodes
433 state['bad'] += nodes
438 elif skip:
434 elif skip:
439 state['skip'] += nodes
435 state['skip'] += nodes
440 hbisect.save_state(repo, state)
436 hbisect.save_state(repo, state)
441
437
442 if not check_state(state):
438 if not check_state(state):
443 return
439 return
444
440
445 # actually bisect
441 # actually bisect
446 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
442 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
447 if changesets == 0:
443 if changesets == 0:
448 print_result(nodes, good)
444 print_result(nodes, good)
449 else:
445 else:
450 assert len(nodes) == 1 # only a single node can be tested next
446 assert len(nodes) == 1 # only a single node can be tested next
451 node = nodes[0]
447 node = nodes[0]
452 # compute the approximate number of remaining tests
448 # compute the approximate number of remaining tests
453 tests, size = 0, 2
449 tests, size = 0, 2
454 while size <= changesets:
450 while size <= changesets:
455 tests, size = tests + 1, size * 2
451 tests, size = tests + 1, size * 2
456 rev = repo.changelog.rev(node)
452 rev = repo.changelog.rev(node)
457 ui.write(_("Testing changeset %d:%s "
453 ui.write(_("Testing changeset %d:%s "
458 "(%d changesets remaining, ~%d tests)\n")
454 "(%d changesets remaining, ~%d tests)\n")
459 % (rev, short(node), changesets, tests))
455 % (rev, short(node), changesets, tests))
460 if not noupdate:
456 if not noupdate:
461 cmdutil.bail_if_changed(repo)
457 cmdutil.bail_if_changed(repo)
462 return hg.clean(repo, node)
458 return hg.clean(repo, node)
463
459
464 def branch(ui, repo, label=None, **opts):
460 def branch(ui, repo, label=None, **opts):
465 """set or show the current branch name
461 """set or show the current branch name
466
462
467 With no argument, show the current branch name. With one argument,
463 With no argument, show the current branch name. With one argument,
468 set the working directory branch name (the branch will not exist
464 set the working directory branch name (the branch will not exist
469 in the repository until the next commit). Standard practice
465 in the repository until the next commit). Standard practice
470 recommends that primary development take place on the 'default'
466 recommends that primary development take place on the 'default'
471 branch.
467 branch.
472
468
473 Unless -f/--force is specified, branch will not let you set a
469 Unless -f/--force is specified, branch will not let you set a
474 branch name that already exists, even if it's inactive.
470 branch name that already exists, even if it's inactive.
475
471
476 Use -C/--clean to reset the working directory branch to that of
472 Use -C/--clean to reset the working directory branch to that of
477 the parent of the working directory, negating a previous branch
473 the parent of the working directory, negating a previous branch
478 change.
474 change.
479
475
480 Use the command :hg:`update` to switch to an existing branch. Use
476 Use the command :hg:`update` to switch to an existing branch. Use
481 :hg:`commit --close-branch` to mark this branch as closed.
477 :hg:`commit --close-branch` to mark this branch as closed.
482
478
483 Returns 0 on success.
479 Returns 0 on success.
484 """
480 """
485
481
486 if opts.get('clean'):
482 if opts.get('clean'):
487 label = repo[None].parents()[0].branch()
483 label = repo[None].parents()[0].branch()
488 repo.dirstate.setbranch(label)
484 repo.dirstate.setbranch(label)
489 ui.status(_('reset working directory to branch %s\n') % label)
485 ui.status(_('reset working directory to branch %s\n') % label)
490 elif label:
486 elif label:
491 if not opts.get('force') and label in repo.branchtags():
487 if not opts.get('force') and label in repo.branchtags():
492 if label not in [p.branch() for p in repo.parents()]:
488 if label not in [p.branch() for p in repo.parents()]:
493 raise util.Abort(_('a branch of the same name already exists'
489 raise util.Abort(_('a branch of the same name already exists'
494 " (use 'hg update' to switch to it)"))
490 " (use 'hg update' to switch to it)"))
495 repo.dirstate.setbranch(label)
491 repo.dirstate.setbranch(label)
496 ui.status(_('marked working directory as branch %s\n') % label)
492 ui.status(_('marked working directory as branch %s\n') % label)
497 else:
493 else:
498 ui.write("%s\n" % repo.dirstate.branch())
494 ui.write("%s\n" % repo.dirstate.branch())
499
495
500 def branches(ui, repo, active=False, closed=False):
496 def branches(ui, repo, active=False, closed=False):
501 """list repository named branches
497 """list repository named branches
502
498
503 List the repository's named branches, indicating which ones are
499 List the repository's named branches, indicating which ones are
504 inactive. If -c/--closed is specified, also list branches which have
500 inactive. If -c/--closed is specified, also list branches which have
505 been marked closed (see :hg:`commit --close-branch`).
501 been marked closed (see :hg:`commit --close-branch`).
506
502
507 If -a/--active is specified, only show active branches. A branch
503 If -a/--active is specified, only show active branches. A branch
508 is considered active if it contains repository heads.
504 is considered active if it contains repository heads.
509
505
510 Use the command :hg:`update` to switch to an existing branch.
506 Use the command :hg:`update` to switch to an existing branch.
511
507
512 Returns 0.
508 Returns 0.
513 """
509 """
514
510
515 hexfunc = ui.debugflag and hex or short
511 hexfunc = ui.debugflag and hex or short
516 activebranches = [repo[n].branch() for n in repo.heads()]
512 activebranches = [repo[n].branch() for n in repo.heads()]
517 def testactive(tag, node):
513 def testactive(tag, node):
518 realhead = tag in activebranches
514 realhead = tag in activebranches
519 open = node in repo.branchheads(tag, closed=False)
515 open = node in repo.branchheads(tag, closed=False)
520 return realhead and open
516 return realhead and open
521 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
517 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
522 for tag, node in repo.branchtags().items()],
518 for tag, node in repo.branchtags().items()],
523 reverse=True)
519 reverse=True)
524
520
525 for isactive, node, tag in branches:
521 for isactive, node, tag in branches:
526 if (not active) or isactive:
522 if (not active) or isactive:
527 if ui.quiet:
523 if ui.quiet:
528 ui.write("%s\n" % tag)
524 ui.write("%s\n" % tag)
529 else:
525 else:
530 hn = repo.lookup(node)
526 hn = repo.lookup(node)
531 if isactive:
527 if isactive:
532 label = 'branches.active'
528 label = 'branches.active'
533 notice = ''
529 notice = ''
534 elif hn not in repo.branchheads(tag, closed=False):
530 elif hn not in repo.branchheads(tag, closed=False):
535 if not closed:
531 if not closed:
536 continue
532 continue
537 label = 'branches.closed'
533 label = 'branches.closed'
538 notice = _(' (closed)')
534 notice = _(' (closed)')
539 else:
535 else:
540 label = 'branches.inactive'
536 label = 'branches.inactive'
541 notice = _(' (inactive)')
537 notice = _(' (inactive)')
542 if tag == repo.dirstate.branch():
538 if tag == repo.dirstate.branch():
543 label = 'branches.current'
539 label = 'branches.current'
544 rev = str(node).rjust(31 - encoding.colwidth(tag))
540 rev = str(node).rjust(31 - encoding.colwidth(tag))
545 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
541 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
546 tag = ui.label(tag, label)
542 tag = ui.label(tag, label)
547 ui.write("%s %s%s\n" % (tag, rev, notice))
543 ui.write("%s %s%s\n" % (tag, rev, notice))
548
544
549 def bundle(ui, repo, fname, dest=None, **opts):
545 def bundle(ui, repo, fname, dest=None, **opts):
550 """create a changegroup file
546 """create a changegroup file
551
547
552 Generate a compressed changegroup file collecting changesets not
548 Generate a compressed changegroup file collecting changesets not
553 known to be in another repository.
549 known to be in another repository.
554
550
555 If you omit the destination repository, then hg assumes the
551 If you omit the destination repository, then hg assumes the
556 destination will have all the nodes you specify with --base
552 destination will have all the nodes you specify with --base
557 parameters. To create a bundle containing all changesets, use
553 parameters. To create a bundle containing all changesets, use
558 -a/--all (or --base null).
554 -a/--all (or --base null).
559
555
560 You can change compression method with the -t/--type option.
556 You can change compression method with the -t/--type option.
561 The available compression methods are: none, bzip2, and
557 The available compression methods are: none, bzip2, and
562 gzip (by default, bundles are compressed using bzip2).
558 gzip (by default, bundles are compressed using bzip2).
563
559
564 The bundle file can then be transferred using conventional means
560 The bundle file can then be transferred using conventional means
565 and applied to another repository with the unbundle or pull
561 and applied to another repository with the unbundle or pull
566 command. This is useful when direct push and pull are not
562 command. This is useful when direct push and pull are not
567 available or when exporting an entire repository is undesirable.
563 available or when exporting an entire repository is undesirable.
568
564
569 Applying bundles preserves all changeset contents including
565 Applying bundles preserves all changeset contents including
570 permissions, copy/rename information, and revision history.
566 permissions, copy/rename information, and revision history.
571
567
572 Returns 0 on success, 1 if no changes found.
568 Returns 0 on success, 1 if no changes found.
573 """
569 """
574 revs = None
570 revs = None
575 if 'rev' in opts:
571 if 'rev' in opts:
576 revs = cmdutil.revrange(repo, opts['rev'])
572 revs = cmdutil.revrange(repo, opts['rev'])
577
573
578 if opts.get('all'):
574 if opts.get('all'):
579 base = ['null']
575 base = ['null']
580 else:
576 else:
581 base = cmdutil.revrange(repo, opts.get('base'))
577 base = cmdutil.revrange(repo, opts.get('base'))
582 if base:
578 if base:
583 if dest:
579 if dest:
584 raise util.Abort(_("--base is incompatible with specifying "
580 raise util.Abort(_("--base is incompatible with specifying "
585 "a destination"))
581 "a destination"))
586 base = [repo.lookup(rev) for rev in base]
582 base = [repo.lookup(rev) for rev in base]
587 # create the right base
583 # create the right base
588 # XXX: nodesbetween / changegroup* should be "fixed" instead
584 # XXX: nodesbetween / changegroup* should be "fixed" instead
589 o = []
585 o = []
590 has = set((nullid,))
586 has = set((nullid,))
591 for n in base:
587 for n in base:
592 has.update(repo.changelog.reachable(n))
588 has.update(repo.changelog.reachable(n))
593 if revs:
589 if revs:
594 revs = [repo.lookup(rev) for rev in revs]
590 revs = [repo.lookup(rev) for rev in revs]
595 visit = revs[:]
591 visit = revs[:]
596 has.difference_update(visit)
592 has.difference_update(visit)
597 else:
593 else:
598 visit = repo.changelog.heads()
594 visit = repo.changelog.heads()
599 seen = {}
595 seen = {}
600 while visit:
596 while visit:
601 n = visit.pop(0)
597 n = visit.pop(0)
602 parents = [p for p in repo.changelog.parents(n) if p not in has]
598 parents = [p for p in repo.changelog.parents(n) if p not in has]
603 if len(parents) == 0:
599 if len(parents) == 0:
604 if n not in has:
600 if n not in has:
605 o.append(n)
601 o.append(n)
606 else:
602 else:
607 for p in parents:
603 for p in parents:
608 if p not in seen:
604 if p not in seen:
609 seen[p] = 1
605 seen[p] = 1
610 visit.append(p)
606 visit.append(p)
611 else:
607 else:
612 dest = ui.expandpath(dest or 'default-push', dest or 'default')
608 dest = ui.expandpath(dest or 'default-push', dest or 'default')
613 dest, branches = hg.parseurl(dest, opts.get('branch'))
609 dest, branches = hg.parseurl(dest, opts.get('branch'))
614 other = hg.repository(hg.remoteui(repo, opts), dest)
610 other = hg.repository(hg.remoteui(repo, opts), dest)
615 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
611 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
616 if revs:
612 if revs:
617 revs = [repo.lookup(rev) for rev in revs]
613 revs = [repo.lookup(rev) for rev in revs]
618 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
614 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
619
615
620 if not o:
616 if not o:
621 ui.status(_("no changes found\n"))
617 ui.status(_("no changes found\n"))
622 return 1
618 return 1
623
619
624 if revs:
620 if revs:
625 cg = repo.changegroupsubset(o, revs, 'bundle')
621 cg = repo.changegroupsubset(o, revs, 'bundle')
626 else:
622 else:
627 cg = repo.changegroup(o, 'bundle')
623 cg = repo.changegroup(o, 'bundle')
628
624
629 bundletype = opts.get('type', 'bzip2').lower()
625 bundletype = opts.get('type', 'bzip2').lower()
630 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
626 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
631 bundletype = btypes.get(bundletype)
627 bundletype = btypes.get(bundletype)
632 if bundletype not in changegroup.bundletypes:
628 if bundletype not in changegroup.bundletypes:
633 raise util.Abort(_('unknown bundle type specified with --type'))
629 raise util.Abort(_('unknown bundle type specified with --type'))
634
630
635 changegroup.writebundle(cg, fname, bundletype)
631 changegroup.writebundle(cg, fname, bundletype)
636
632
637 def cat(ui, repo, file1, *pats, **opts):
633 def cat(ui, repo, file1, *pats, **opts):
638 """output the current or given revision of files
634 """output the current or given revision of files
639
635
640 Print the specified files as they were at the given revision. If
636 Print the specified files as they were at the given revision. If
641 no revision is given, the parent of the working directory is used,
637 no revision is given, the parent of the working directory is used,
642 or tip if no revision is checked out.
638 or tip if no revision is checked out.
643
639
644 Output may be to a file, in which case the name of the file is
640 Output may be to a file, in which case the name of the file is
645 given using a format string. The formatting rules are the same as
641 given using a format string. The formatting rules are the same as
646 for the export command, with the following additions:
642 for the export command, with the following additions:
647
643
648 :``%s``: basename of file being printed
644 :``%s``: basename of file being printed
649 :``%d``: dirname of file being printed, or '.' if in repository root
645 :``%d``: dirname of file being printed, or '.' if in repository root
650 :``%p``: root-relative path name of file being printed
646 :``%p``: root-relative path name of file being printed
651
647
652 Returns 0 on success.
648 Returns 0 on success.
653 """
649 """
654 ctx = cmdutil.revsingle(repo, opts.get('rev'))
650 ctx = cmdutil.revsingle(repo, opts.get('rev'))
655 err = 1
651 err = 1
656 m = cmdutil.match(repo, (file1,) + pats, opts)
652 m = cmdutil.match(repo, (file1,) + pats, opts)
657 for abs in ctx.walk(m):
653 for abs in ctx.walk(m):
658 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
654 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
659 data = ctx[abs].data()
655 data = ctx[abs].data()
660 if opts.get('decode'):
656 if opts.get('decode'):
661 data = repo.wwritedata(abs, data)
657 data = repo.wwritedata(abs, data)
662 fp.write(data)
658 fp.write(data)
663 err = 0
659 err = 0
664 return err
660 return err
665
661
666 def clone(ui, source, dest=None, **opts):
662 def clone(ui, source, dest=None, **opts):
667 """make a copy of an existing repository
663 """make a copy of an existing repository
668
664
669 Create a copy of an existing repository in a new directory.
665 Create a copy of an existing repository in a new directory.
670
666
671 If no destination directory name is specified, it defaults to the
667 If no destination directory name is specified, it defaults to the
672 basename of the source.
668 basename of the source.
673
669
674 The location of the source is added to the new repository's
670 The location of the source is added to the new repository's
675 .hg/hgrc file, as the default to be used for future pulls.
671 .hg/hgrc file, as the default to be used for future pulls.
676
672
677 See :hg:`help urls` for valid source format details.
673 See :hg:`help urls` for valid source format details.
678
674
679 It is possible to specify an ``ssh://`` URL as the destination, but no
675 It is possible to specify an ``ssh://`` URL as the destination, but no
680 .hg/hgrc and working directory will be created on the remote side.
676 .hg/hgrc and working directory will be created on the remote side.
681 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
677 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
682
678
683 A set of changesets (tags, or branch names) to pull may be specified
679 A set of changesets (tags, or branch names) to pull may be specified
684 by listing each changeset (tag, or branch name) with -r/--rev.
680 by listing each changeset (tag, or branch name) with -r/--rev.
685 If -r/--rev is used, the cloned repository will contain only a subset
681 If -r/--rev is used, the cloned repository will contain only a subset
686 of the changesets of the source repository. Only the set of changesets
682 of the changesets of the source repository. Only the set of changesets
687 defined by all -r/--rev options (including all their ancestors)
683 defined by all -r/--rev options (including all their ancestors)
688 will be pulled into the destination repository.
684 will be pulled into the destination repository.
689 No subsequent changesets (including subsequent tags) will be present
685 No subsequent changesets (including subsequent tags) will be present
690 in the destination.
686 in the destination.
691
687
692 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
688 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
693 local source repositories.
689 local source repositories.
694
690
695 For efficiency, hardlinks are used for cloning whenever the source
691 For efficiency, hardlinks are used for cloning whenever the source
696 and destination are on the same filesystem (note this applies only
692 and destination are on the same filesystem (note this applies only
697 to the repository data, not to the working directory). Some
693 to the repository data, not to the working directory). Some
698 filesystems, such as AFS, implement hardlinking incorrectly, but
694 filesystems, such as AFS, implement hardlinking incorrectly, but
699 do not report errors. In these cases, use the --pull option to
695 do not report errors. In these cases, use the --pull option to
700 avoid hardlinking.
696 avoid hardlinking.
701
697
702 In some cases, you can clone repositories and the working directory
698 In some cases, you can clone repositories and the working directory
703 using full hardlinks with ::
699 using full hardlinks with ::
704
700
705 $ cp -al REPO REPOCLONE
701 $ cp -al REPO REPOCLONE
706
702
707 This is the fastest way to clone, but it is not always safe. The
703 This is the fastest way to clone, but it is not always safe. The
708 operation is not atomic (making sure REPO is not modified during
704 operation is not atomic (making sure REPO is not modified during
709 the operation is up to you) and you have to make sure your editor
705 the operation is up to you) and you have to make sure your editor
710 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
706 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
711 this is not compatible with certain extensions that place their
707 this is not compatible with certain extensions that place their
712 metadata under the .hg directory, such as mq.
708 metadata under the .hg directory, such as mq.
713
709
714 Mercurial will update the working directory to the first applicable
710 Mercurial will update the working directory to the first applicable
715 revision from this list:
711 revision from this list:
716
712
717 a) null if -U or the source repository has no changesets
713 a) null if -U or the source repository has no changesets
718 b) if -u . and the source repository is local, the first parent of
714 b) if -u . and the source repository is local, the first parent of
719 the source repository's working directory
715 the source repository's working directory
720 c) the changeset specified with -u (if a branch name, this means the
716 c) the changeset specified with -u (if a branch name, this means the
721 latest head of that branch)
717 latest head of that branch)
722 d) the changeset specified with -r
718 d) the changeset specified with -r
723 e) the tipmost head specified with -b
719 e) the tipmost head specified with -b
724 f) the tipmost head specified with the url#branch source syntax
720 f) the tipmost head specified with the url#branch source syntax
725 g) the tipmost head of the default branch
721 g) the tipmost head of the default branch
726 h) tip
722 h) tip
727
723
728 Returns 0 on success.
724 Returns 0 on success.
729 """
725 """
730 if opts.get('noupdate') and opts.get('updaterev'):
726 if opts.get('noupdate') and opts.get('updaterev'):
731 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
727 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
732
728
733 r = hg.clone(hg.remoteui(ui, opts), source, dest,
729 r = hg.clone(hg.remoteui(ui, opts), source, dest,
734 pull=opts.get('pull'),
730 pull=opts.get('pull'),
735 stream=opts.get('uncompressed'),
731 stream=opts.get('uncompressed'),
736 rev=opts.get('rev'),
732 rev=opts.get('rev'),
737 update=opts.get('updaterev') or not opts.get('noupdate'),
733 update=opts.get('updaterev') or not opts.get('noupdate'),
738 branch=opts.get('branch'))
734 branch=opts.get('branch'))
739
735
740 return r is None
736 return r is None
741
737
742 def commit(ui, repo, *pats, **opts):
738 def commit(ui, repo, *pats, **opts):
743 """commit the specified files or all outstanding changes
739 """commit the specified files or all outstanding changes
744
740
745 Commit changes to the given files into the repository. Unlike a
741 Commit changes to the given files into the repository. Unlike a
746 centralized SCM, this operation is a local operation. See
742 centralized SCM, this operation is a local operation. See
747 :hg:`push` for a way to actively distribute your changes.
743 :hg:`push` for a way to actively distribute your changes.
748
744
749 If a list of files is omitted, all changes reported by :hg:`status`
745 If a list of files is omitted, all changes reported by :hg:`status`
750 will be committed.
746 will be committed.
751
747
752 If you are committing the result of a merge, do not provide any
748 If you are committing the result of a merge, do not provide any
753 filenames or -I/-X filters.
749 filenames or -I/-X filters.
754
750
755 If no commit message is specified, Mercurial starts your
751 If no commit message is specified, Mercurial starts your
756 configured editor where you can enter a message. In case your
752 configured editor where you can enter a message. In case your
757 commit fails, you will find a backup of your message in
753 commit fails, you will find a backup of your message in
758 ``.hg/last-message.txt``.
754 ``.hg/last-message.txt``.
759
755
760 See :hg:`help dates` for a list of formats valid for -d/--date.
756 See :hg:`help dates` for a list of formats valid for -d/--date.
761
757
762 Returns 0 on success, 1 if nothing changed.
758 Returns 0 on success, 1 if nothing changed.
763 """
759 """
764 extra = {}
760 extra = {}
765 if opts.get('close_branch'):
761 if opts.get('close_branch'):
766 if repo['.'].node() not in repo.branchheads():
762 if repo['.'].node() not in repo.branchheads():
767 # The topo heads set is included in the branch heads set of the
763 # The topo heads set is included in the branch heads set of the
768 # current branch, so it's sufficient to test branchheads
764 # current branch, so it's sufficient to test branchheads
769 raise util.Abort(_('can only close branch heads'))
765 raise util.Abort(_('can only close branch heads'))
770 extra['close'] = 1
766 extra['close'] = 1
771 e = cmdutil.commiteditor
767 e = cmdutil.commiteditor
772 if opts.get('force_editor'):
768 if opts.get('force_editor'):
773 e = cmdutil.commitforceeditor
769 e = cmdutil.commitforceeditor
774
770
775 def commitfunc(ui, repo, message, match, opts):
771 def commitfunc(ui, repo, message, match, opts):
776 return repo.commit(message, opts.get('user'), opts.get('date'), match,
772 return repo.commit(message, opts.get('user'), opts.get('date'), match,
777 editor=e, extra=extra)
773 editor=e, extra=extra)
778
774
779 branch = repo[None].branch()
775 branch = repo[None].branch()
780 bheads = repo.branchheads(branch)
776 bheads = repo.branchheads(branch)
781
777
782 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
778 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
783 if not node:
779 if not node:
784 ui.status(_("nothing changed\n"))
780 ui.status(_("nothing changed\n"))
785 return 1
781 return 1
786
782
787 ctx = repo[node]
783 ctx = repo[node]
788 parents = ctx.parents()
784 parents = ctx.parents()
789
785
790 if bheads and not [x for x in parents
786 if bheads and not [x for x in parents
791 if x.node() in bheads and x.branch() == branch]:
787 if x.node() in bheads and x.branch() == branch]:
792 ui.status(_('created new head\n'))
788 ui.status(_('created new head\n'))
793 # The message is not printed for initial roots. For the other
789 # The message is not printed for initial roots. For the other
794 # changesets, it is printed in the following situations:
790 # changesets, it is printed in the following situations:
795 #
791 #
796 # Par column: for the 2 parents with ...
792 # Par column: for the 2 parents with ...
797 # N: null or no parent
793 # N: null or no parent
798 # B: parent is on another named branch
794 # B: parent is on another named branch
799 # C: parent is a regular non head changeset
795 # C: parent is a regular non head changeset
800 # H: parent was a branch head of the current branch
796 # H: parent was a branch head of the current branch
801 # Msg column: whether we print "created new head" message
797 # Msg column: whether we print "created new head" message
802 # In the following, it is assumed that there already exists some
798 # In the following, it is assumed that there already exists some
803 # initial branch heads of the current branch, otherwise nothing is
799 # initial branch heads of the current branch, otherwise nothing is
804 # printed anyway.
800 # printed anyway.
805 #
801 #
806 # Par Msg Comment
802 # Par Msg Comment
807 # NN y additional topo root
803 # NN y additional topo root
808 #
804 #
809 # BN y additional branch root
805 # BN y additional branch root
810 # CN y additional topo head
806 # CN y additional topo head
811 # HN n usual case
807 # HN n usual case
812 #
808 #
813 # BB y weird additional branch root
809 # BB y weird additional branch root
814 # CB y branch merge
810 # CB y branch merge
815 # HB n merge with named branch
811 # HB n merge with named branch
816 #
812 #
817 # CC y additional head from merge
813 # CC y additional head from merge
818 # CH n merge with a head
814 # CH n merge with a head
819 #
815 #
820 # HH n head merge: head count decreases
816 # HH n head merge: head count decreases
821
817
822 if not opts.get('close_branch'):
818 if not opts.get('close_branch'):
823 for r in parents:
819 for r in parents:
824 if r.extra().get('close') and r.branch() == branch:
820 if r.extra().get('close') and r.branch() == branch:
825 ui.status(_('reopening closed branch head %d\n') % r)
821 ui.status(_('reopening closed branch head %d\n') % r)
826
822
827 if ui.debugflag:
823 if ui.debugflag:
828 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
824 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
829 elif ui.verbose:
825 elif ui.verbose:
830 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
826 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
831
827
832 def copy(ui, repo, *pats, **opts):
828 def copy(ui, repo, *pats, **opts):
833 """mark files as copied for the next commit
829 """mark files as copied for the next commit
834
830
835 Mark dest as having copies of source files. If dest is a
831 Mark dest as having copies of source files. If dest is a
836 directory, copies are put in that directory. If dest is a file,
832 directory, copies are put in that directory. If dest is a file,
837 the source must be a single file.
833 the source must be a single file.
838
834
839 By default, this command copies the contents of files as they
835 By default, this command copies the contents of files as they
840 exist in the working directory. If invoked with -A/--after, the
836 exist in the working directory. If invoked with -A/--after, the
841 operation is recorded, but no copying is performed.
837 operation is recorded, but no copying is performed.
842
838
843 This command takes effect with the next commit. To undo a copy
839 This command takes effect with the next commit. To undo a copy
844 before that, see :hg:`revert`.
840 before that, see :hg:`revert`.
845
841
846 Returns 0 on success, 1 if errors are encountered.
842 Returns 0 on success, 1 if errors are encountered.
847 """
843 """
848 wlock = repo.wlock(False)
844 wlock = repo.wlock(False)
849 try:
845 try:
850 return cmdutil.copy(ui, repo, pats, opts)
846 return cmdutil.copy(ui, repo, pats, opts)
851 finally:
847 finally:
852 wlock.release()
848 wlock.release()
853
849
854 def debugancestor(ui, repo, *args):
850 def debugancestor(ui, repo, *args):
855 """find the ancestor revision of two revisions in a given index"""
851 """find the ancestor revision of two revisions in a given index"""
856 if len(args) == 3:
852 if len(args) == 3:
857 index, rev1, rev2 = args
853 index, rev1, rev2 = args
858 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
854 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
859 lookup = r.lookup
855 lookup = r.lookup
860 elif len(args) == 2:
856 elif len(args) == 2:
861 if not repo:
857 if not repo:
862 raise util.Abort(_("there is no Mercurial repository here "
858 raise util.Abort(_("there is no Mercurial repository here "
863 "(.hg not found)"))
859 "(.hg not found)"))
864 rev1, rev2 = args
860 rev1, rev2 = args
865 r = repo.changelog
861 r = repo.changelog
866 lookup = repo.lookup
862 lookup = repo.lookup
867 else:
863 else:
868 raise util.Abort(_('either two or three arguments required'))
864 raise util.Abort(_('either two or three arguments required'))
869 a = r.ancestor(lookup(rev1), lookup(rev2))
865 a = r.ancestor(lookup(rev1), lookup(rev2))
870 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
866 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
871
867
872 def debugbuilddag(ui, repo, text,
868 def debugbuilddag(ui, repo, text,
873 mergeable_file=False,
869 mergeable_file=False,
874 appended_file=False,
870 appended_file=False,
875 overwritten_file=False,
871 overwritten_file=False,
876 new_file=False):
872 new_file=False):
877 """builds a repo with a given dag from scratch in the current empty repo
873 """builds a repo with a given dag from scratch in the current empty repo
878
874
879 Elements:
875 Elements:
880
876
881 - "+n" is a linear run of n nodes based on the current default parent
877 - "+n" is a linear run of n nodes based on the current default parent
882 - "." is a single node based on the current default parent
878 - "." is a single node based on the current default parent
883 - "$" resets the default parent to null (implied at the start);
879 - "$" resets the default parent to null (implied at the start);
884 otherwise the default parent is always the last node created
880 otherwise the default parent is always the last node created
885 - "<p" sets the default parent to the backref p
881 - "<p" sets the default parent to the backref p
886 - "*p" is a fork at parent p, which is a backref
882 - "*p" is a fork at parent p, which is a backref
887 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
883 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
888 - "/p2" is a merge of the preceding node and p2
884 - "/p2" is a merge of the preceding node and p2
889 - ":tag" defines a local tag for the preceding node
885 - ":tag" defines a local tag for the preceding node
890 - "@branch" sets the named branch for subsequent nodes
886 - "@branch" sets the named branch for subsequent nodes
891 - "!command" runs the command using your shell
887 - "!command" runs the command using your shell
892 - "!!my command\\n" is like "!", but to the end of the line
888 - "!!my command\\n" is like "!", but to the end of the line
893 - "#...\\n" is a comment up to the end of the line
889 - "#...\\n" is a comment up to the end of the line
894
890
895 Whitespace between the above elements is ignored.
891 Whitespace between the above elements is ignored.
896
892
897 A backref is either
893 A backref is either
898
894
899 - a number n, which references the node curr-n, where curr is the current
895 - a number n, which references the node curr-n, where curr is the current
900 node, or
896 node, or
901 - the name of a local tag you placed earlier using ":tag", or
897 - the name of a local tag you placed earlier using ":tag", or
902 - empty to denote the default parent.
898 - empty to denote the default parent.
903
899
904 All string valued-elements are either strictly alphanumeric, or must
900 All string valued-elements are either strictly alphanumeric, or must
905 be enclosed in double quotes ("..."), with "\\" as escape character.
901 be enclosed in double quotes ("..."), with "\\" as escape character.
906
902
907 Note that the --overwritten-file and --appended-file options imply the
903 Note that the --overwritten-file and --appended-file options imply the
908 use of "HGMERGE=internal:local" during DAG buildup.
904 use of "HGMERGE=internal:local" during DAG buildup.
909 """
905 """
910
906
911 if not (mergeable_file or appended_file or overwritten_file or new_file):
907 if not (mergeable_file or appended_file or overwritten_file or new_file):
912 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
908 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
913
909
914 if len(repo.changelog) > 0:
910 if len(repo.changelog) > 0:
915 raise util.Abort(_('repository is not empty'))
911 raise util.Abort(_('repository is not empty'))
916
912
917 if overwritten_file or appended_file:
913 if overwritten_file or appended_file:
918 # we don't want to fail in merges during buildup
914 # we don't want to fail in merges during buildup
919 os.environ['HGMERGE'] = 'internal:local'
915 os.environ['HGMERGE'] = 'internal:local'
920
916
921 def writefile(fname, text, fmode="wb"):
917 def writefile(fname, text, fmode="wb"):
922 f = open(fname, fmode)
918 f = open(fname, fmode)
923 try:
919 try:
924 f.write(text)
920 f.write(text)
925 finally:
921 finally:
926 f.close()
922 f.close()
927
923
928 if mergeable_file:
924 if mergeable_file:
929 linesperrev = 2
925 linesperrev = 2
930 # determine number of revs in DAG
926 # determine number of revs in DAG
931 n = 0
927 n = 0
932 for type, data in dagparser.parsedag(text):
928 for type, data in dagparser.parsedag(text):
933 if type == 'n':
929 if type == 'n':
934 n += 1
930 n += 1
935 # make a file with k lines per rev
931 # make a file with k lines per rev
936 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
932 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
937 + "\n")
933 + "\n")
938
934
939 at = -1
935 at = -1
940 atbranch = 'default'
936 atbranch = 'default'
941 for type, data in dagparser.parsedag(text):
937 for type, data in dagparser.parsedag(text):
942 if type == 'n':
938 if type == 'n':
943 ui.status('node %s\n' % str(data))
939 ui.status('node %s\n' % str(data))
944 id, ps = data
940 id, ps = data
945 p1 = ps[0]
941 p1 = ps[0]
946 if p1 != at:
942 if p1 != at:
947 update(ui, repo, node=str(p1), clean=True)
943 update(ui, repo, node=str(p1), clean=True)
948 at = p1
944 at = p1
949 if repo.dirstate.branch() != atbranch:
945 if repo.dirstate.branch() != atbranch:
950 branch(ui, repo, atbranch, force=True)
946 branch(ui, repo, atbranch, force=True)
951 if len(ps) > 1:
947 if len(ps) > 1:
952 p2 = ps[1]
948 p2 = ps[1]
953 merge(ui, repo, node=p2)
949 merge(ui, repo, node=p2)
954
950
955 if mergeable_file:
951 if mergeable_file:
956 f = open("mf", "rb+")
952 f = open("mf", "rb+")
957 try:
953 try:
958 lines = f.read().split("\n")
954 lines = f.read().split("\n")
959 lines[id * linesperrev] += " r%i" % id
955 lines[id * linesperrev] += " r%i" % id
960 f.seek(0)
956 f.seek(0)
961 f.write("\n".join(lines))
957 f.write("\n".join(lines))
962 finally:
958 finally:
963 f.close()
959 f.close()
964
960
965 if appended_file:
961 if appended_file:
966 writefile("af", "r%i\n" % id, "ab")
962 writefile("af", "r%i\n" % id, "ab")
967
963
968 if overwritten_file:
964 if overwritten_file:
969 writefile("of", "r%i\n" % id)
965 writefile("of", "r%i\n" % id)
970
966
971 if new_file:
967 if new_file:
972 writefile("nf%i" % id, "r%i\n" % id)
968 writefile("nf%i" % id, "r%i\n" % id)
973
969
974 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
970 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
975 at = id
971 at = id
976 elif type == 'l':
972 elif type == 'l':
977 id, name = data
973 id, name = data
978 ui.status('tag %s\n' % name)
974 ui.status('tag %s\n' % name)
979 tag(ui, repo, name, local=True)
975 tag(ui, repo, name, local=True)
980 elif type == 'a':
976 elif type == 'a':
981 ui.status('branch %s\n' % data)
977 ui.status('branch %s\n' % data)
982 atbranch = data
978 atbranch = data
983 elif type in 'cC':
979 elif type in 'cC':
984 r = util.system(data, cwd=repo.root)
980 r = util.system(data, cwd=repo.root)
985 if r:
981 if r:
986 desc, r = util.explain_exit(r)
982 desc, r = util.explain_exit(r)
987 raise util.Abort(_('%s command %s') % (data, desc))
983 raise util.Abort(_('%s command %s') % (data, desc))
988
984
989 def debugcommands(ui, cmd='', *args):
985 def debugcommands(ui, cmd='', *args):
990 """list all available commands and options"""
986 """list all available commands and options"""
991 for cmd, vals in sorted(table.iteritems()):
987 for cmd, vals in sorted(table.iteritems()):
992 cmd = cmd.split('|')[0].strip('^')
988 cmd = cmd.split('|')[0].strip('^')
993 opts = ', '.join([i[1] for i in vals[1]])
989 opts = ', '.join([i[1] for i in vals[1]])
994 ui.write('%s: %s\n' % (cmd, opts))
990 ui.write('%s: %s\n' % (cmd, opts))
995
991
996 def debugcomplete(ui, cmd='', **opts):
992 def debugcomplete(ui, cmd='', **opts):
997 """returns the completion list associated with the given command"""
993 """returns the completion list associated with the given command"""
998
994
999 if opts.get('options'):
995 if opts.get('options'):
1000 options = []
996 options = []
1001 otables = [globalopts]
997 otables = [globalopts]
1002 if cmd:
998 if cmd:
1003 aliases, entry = cmdutil.findcmd(cmd, table, False)
999 aliases, entry = cmdutil.findcmd(cmd, table, False)
1004 otables.append(entry[1])
1000 otables.append(entry[1])
1005 for t in otables:
1001 for t in otables:
1006 for o in t:
1002 for o in t:
1007 if "(DEPRECATED)" in o[3]:
1003 if "(DEPRECATED)" in o[3]:
1008 continue
1004 continue
1009 if o[0]:
1005 if o[0]:
1010 options.append('-%s' % o[0])
1006 options.append('-%s' % o[0])
1011 options.append('--%s' % o[1])
1007 options.append('--%s' % o[1])
1012 ui.write("%s\n" % "\n".join(options))
1008 ui.write("%s\n" % "\n".join(options))
1013 return
1009 return
1014
1010
1015 cmdlist = cmdutil.findpossible(cmd, table)
1011 cmdlist = cmdutil.findpossible(cmd, table)
1016 if ui.verbose:
1012 if ui.verbose:
1017 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1013 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1018 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1014 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1019
1015
1020 def debugfsinfo(ui, path = "."):
1016 def debugfsinfo(ui, path = "."):
1021 """show information detected about current filesystem"""
1017 """show information detected about current filesystem"""
1022 open('.debugfsinfo', 'w').write('')
1018 open('.debugfsinfo', 'w').write('')
1023 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1019 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1024 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1020 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1025 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1021 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1026 and 'yes' or 'no'))
1022 and 'yes' or 'no'))
1027 os.unlink('.debugfsinfo')
1023 os.unlink('.debugfsinfo')
1028
1024
1029 def debugrebuildstate(ui, repo, rev="tip"):
1025 def debugrebuildstate(ui, repo, rev="tip"):
1030 """rebuild the dirstate as it would look like for the given revision"""
1026 """rebuild the dirstate as it would look like for the given revision"""
1031 ctx = cmdutil.revsingle(repo, rev)
1027 ctx = cmdutil.revsingle(repo, rev)
1032 wlock = repo.wlock()
1028 wlock = repo.wlock()
1033 try:
1029 try:
1034 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1030 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1035 finally:
1031 finally:
1036 wlock.release()
1032 wlock.release()
1037
1033
1038 def debugcheckstate(ui, repo):
1034 def debugcheckstate(ui, repo):
1039 """validate the correctness of the current dirstate"""
1035 """validate the correctness of the current dirstate"""
1040 parent1, parent2 = repo.dirstate.parents()
1036 parent1, parent2 = repo.dirstate.parents()
1041 m1 = repo[parent1].manifest()
1037 m1 = repo[parent1].manifest()
1042 m2 = repo[parent2].manifest()
1038 m2 = repo[parent2].manifest()
1043 errors = 0
1039 errors = 0
1044 for f in repo.dirstate:
1040 for f in repo.dirstate:
1045 state = repo.dirstate[f]
1041 state = repo.dirstate[f]
1046 if state in "nr" and f not in m1:
1042 if state in "nr" and f not in m1:
1047 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1043 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1048 errors += 1
1044 errors += 1
1049 if state in "a" and f in m1:
1045 if state in "a" and f in m1:
1050 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1046 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1051 errors += 1
1047 errors += 1
1052 if state in "m" and f not in m1 and f not in m2:
1048 if state in "m" and f not in m1 and f not in m2:
1053 ui.warn(_("%s in state %s, but not in either manifest\n") %
1049 ui.warn(_("%s in state %s, but not in either manifest\n") %
1054 (f, state))
1050 (f, state))
1055 errors += 1
1051 errors += 1
1056 for f in m1:
1052 for f in m1:
1057 state = repo.dirstate[f]
1053 state = repo.dirstate[f]
1058 if state not in "nrm":
1054 if state not in "nrm":
1059 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1055 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1060 errors += 1
1056 errors += 1
1061 if errors:
1057 if errors:
1062 error = _(".hg/dirstate inconsistent with current parent's manifest")
1058 error = _(".hg/dirstate inconsistent with current parent's manifest")
1063 raise util.Abort(error)
1059 raise util.Abort(error)
1064
1060
1065 def showconfig(ui, repo, *values, **opts):
1061 def showconfig(ui, repo, *values, **opts):
1066 """show combined config settings from all hgrc files
1062 """show combined config settings from all hgrc files
1067
1063
1068 With no arguments, print names and values of all config items.
1064 With no arguments, print names and values of all config items.
1069
1065
1070 With one argument of the form section.name, print just the value
1066 With one argument of the form section.name, print just the value
1071 of that config item.
1067 of that config item.
1072
1068
1073 With multiple arguments, print names and values of all config
1069 With multiple arguments, print names and values of all config
1074 items with matching section names.
1070 items with matching section names.
1075
1071
1076 With --debug, the source (filename and line number) is printed
1072 With --debug, the source (filename and line number) is printed
1077 for each config item.
1073 for each config item.
1078
1074
1079 Returns 0 on success.
1075 Returns 0 on success.
1080 """
1076 """
1081
1077
1082 for f in util.rcpath():
1078 for f in util.rcpath():
1083 ui.debug(_('read config from: %s\n') % f)
1079 ui.debug(_('read config from: %s\n') % f)
1084 untrusted = bool(opts.get('untrusted'))
1080 untrusted = bool(opts.get('untrusted'))
1085 if values:
1081 if values:
1086 sections = [v for v in values if '.' not in v]
1082 sections = [v for v in values if '.' not in v]
1087 items = [v for v in values if '.' in v]
1083 items = [v for v in values if '.' in v]
1088 if len(items) > 1 or items and sections:
1084 if len(items) > 1 or items and sections:
1089 raise util.Abort(_('only one config item permitted'))
1085 raise util.Abort(_('only one config item permitted'))
1090 for section, name, value in ui.walkconfig(untrusted=untrusted):
1086 for section, name, value in ui.walkconfig(untrusted=untrusted):
1091 sectname = section + '.' + name
1087 sectname = section + '.' + name
1092 if values:
1088 if values:
1093 for v in values:
1089 for v in values:
1094 if v == section:
1090 if v == section:
1095 ui.debug('%s: ' %
1091 ui.debug('%s: ' %
1096 ui.configsource(section, name, untrusted))
1092 ui.configsource(section, name, untrusted))
1097 ui.write('%s=%s\n' % (sectname, value))
1093 ui.write('%s=%s\n' % (sectname, value))
1098 elif v == sectname:
1094 elif v == sectname:
1099 ui.debug('%s: ' %
1095 ui.debug('%s: ' %
1100 ui.configsource(section, name, untrusted))
1096 ui.configsource(section, name, untrusted))
1101 ui.write(value, '\n')
1097 ui.write(value, '\n')
1102 else:
1098 else:
1103 ui.debug('%s: ' %
1099 ui.debug('%s: ' %
1104 ui.configsource(section, name, untrusted))
1100 ui.configsource(section, name, untrusted))
1105 ui.write('%s=%s\n' % (sectname, value))
1101 ui.write('%s=%s\n' % (sectname, value))
1106
1102
1107 def debugpushkey(ui, repopath, namespace, *keyinfo):
1103 def debugpushkey(ui, repopath, namespace, *keyinfo):
1108 '''access the pushkey key/value protocol
1104 '''access the pushkey key/value protocol
1109
1105
1110 With two args, list the keys in the given namespace.
1106 With two args, list the keys in the given namespace.
1111
1107
1112 With five args, set a key to new if it currently is set to old.
1108 With five args, set a key to new if it currently is set to old.
1113 Reports success or failure.
1109 Reports success or failure.
1114 '''
1110 '''
1115
1111
1116 target = hg.repository(ui, repopath)
1112 target = hg.repository(ui, repopath)
1117 if keyinfo:
1113 if keyinfo:
1118 key, old, new = keyinfo
1114 key, old, new = keyinfo
1119 r = target.pushkey(namespace, key, old, new)
1115 r = target.pushkey(namespace, key, old, new)
1120 ui.status(str(r) + '\n')
1116 ui.status(str(r) + '\n')
1121 return not r
1117 return not r
1122 else:
1118 else:
1123 for k, v in target.listkeys(namespace).iteritems():
1119 for k, v in target.listkeys(namespace).iteritems():
1124 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1120 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1125 v.encode('string-escape')))
1121 v.encode('string-escape')))
1126
1122
1127 def debugrevspec(ui, repo, expr):
1123 def debugrevspec(ui, repo, expr):
1128 '''parse and apply a revision specification'''
1124 '''parse and apply a revision specification'''
1129 if ui.verbose:
1125 if ui.verbose:
1130 tree = revset.parse(expr)
1126 tree = revset.parse(expr)
1131 ui.note(tree, "\n")
1127 ui.note(tree, "\n")
1132 func = revset.match(expr)
1128 func = revset.match(expr)
1133 for c in func(repo, range(len(repo))):
1129 for c in func(repo, range(len(repo))):
1134 ui.write("%s\n" % c)
1130 ui.write("%s\n" % c)
1135
1131
1136 def debugsetparents(ui, repo, rev1, rev2=None):
1132 def debugsetparents(ui, repo, rev1, rev2=None):
1137 """manually set the parents of the current working directory
1133 """manually set the parents of the current working directory
1138
1134
1139 This is useful for writing repository conversion tools, but should
1135 This is useful for writing repository conversion tools, but should
1140 be used with care.
1136 be used with care.
1141
1137
1142 Returns 0 on success.
1138 Returns 0 on success.
1143 """
1139 """
1144
1140
1145 r1 = cmdutil.revsingle(repo, rev1).node()
1141 r1 = cmdutil.revsingle(repo, rev1).node()
1146 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1142 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1147
1143
1148 wlock = repo.wlock()
1144 wlock = repo.wlock()
1149 try:
1145 try:
1150 repo.dirstate.setparents(r1, r2)
1146 repo.dirstate.setparents(r1, r2)
1151 finally:
1147 finally:
1152 wlock.release()
1148 wlock.release()
1153
1149
1154 def debugstate(ui, repo, nodates=None):
1150 def debugstate(ui, repo, nodates=None):
1155 """show the contents of the current dirstate"""
1151 """show the contents of the current dirstate"""
1156 timestr = ""
1152 timestr = ""
1157 showdate = not nodates
1153 showdate = not nodates
1158 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1154 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1159 if showdate:
1155 if showdate:
1160 if ent[3] == -1:
1156 if ent[3] == -1:
1161 # Pad or slice to locale representation
1157 # Pad or slice to locale representation
1162 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1158 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1163 time.localtime(0)))
1159 time.localtime(0)))
1164 timestr = 'unset'
1160 timestr = 'unset'
1165 timestr = (timestr[:locale_len] +
1161 timestr = (timestr[:locale_len] +
1166 ' ' * (locale_len - len(timestr)))
1162 ' ' * (locale_len - len(timestr)))
1167 else:
1163 else:
1168 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1164 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1169 time.localtime(ent[3]))
1165 time.localtime(ent[3]))
1170 if ent[1] & 020000:
1166 if ent[1] & 020000:
1171 mode = 'lnk'
1167 mode = 'lnk'
1172 else:
1168 else:
1173 mode = '%3o' % (ent[1] & 0777)
1169 mode = '%3o' % (ent[1] & 0777)
1174 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1170 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1175 for f in repo.dirstate.copies():
1171 for f in repo.dirstate.copies():
1176 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1172 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1177
1173
1178 def debugsub(ui, repo, rev=None):
1174 def debugsub(ui, repo, rev=None):
1179 ctx = cmdutil.revsingle(repo, rev, None)
1175 ctx = cmdutil.revsingle(repo, rev, None)
1180 for k, v in sorted(ctx.substate.items()):
1176 for k, v in sorted(ctx.substate.items()):
1181 ui.write('path %s\n' % k)
1177 ui.write('path %s\n' % k)
1182 ui.write(' source %s\n' % v[0])
1178 ui.write(' source %s\n' % v[0])
1183 ui.write(' revision %s\n' % v[1])
1179 ui.write(' revision %s\n' % v[1])
1184
1180
1185 def debugdag(ui, repo, file_=None, *revs, **opts):
1181 def debugdag(ui, repo, file_=None, *revs, **opts):
1186 """format the changelog or an index DAG as a concise textual description
1182 """format the changelog or an index DAG as a concise textual description
1187
1183
1188 If you pass a revlog index, the revlog's DAG is emitted. If you list
1184 If you pass a revlog index, the revlog's DAG is emitted. If you list
1189 revision numbers, they get labelled in the output as rN.
1185 revision numbers, they get labelled in the output as rN.
1190
1186
1191 Otherwise, the changelog DAG of the current repo is emitted.
1187 Otherwise, the changelog DAG of the current repo is emitted.
1192 """
1188 """
1193 spaces = opts.get('spaces')
1189 spaces = opts.get('spaces')
1194 dots = opts.get('dots')
1190 dots = opts.get('dots')
1195 if file_:
1191 if file_:
1196 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1192 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1197 revs = set((int(r) for r in revs))
1193 revs = set((int(r) for r in revs))
1198 def events():
1194 def events():
1199 for r in rlog:
1195 for r in rlog:
1200 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1196 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1201 if r in revs:
1197 if r in revs:
1202 yield 'l', (r, "r%i" % r)
1198 yield 'l', (r, "r%i" % r)
1203 elif repo:
1199 elif repo:
1204 cl = repo.changelog
1200 cl = repo.changelog
1205 tags = opts.get('tags')
1201 tags = opts.get('tags')
1206 branches = opts.get('branches')
1202 branches = opts.get('branches')
1207 if tags:
1203 if tags:
1208 labels = {}
1204 labels = {}
1209 for l, n in repo.tags().items():
1205 for l, n in repo.tags().items():
1210 labels.setdefault(cl.rev(n), []).append(l)
1206 labels.setdefault(cl.rev(n), []).append(l)
1211 def events():
1207 def events():
1212 b = "default"
1208 b = "default"
1213 for r in cl:
1209 for r in cl:
1214 if branches:
1210 if branches:
1215 newb = cl.read(cl.node(r))[5]['branch']
1211 newb = cl.read(cl.node(r))[5]['branch']
1216 if newb != b:
1212 if newb != b:
1217 yield 'a', newb
1213 yield 'a', newb
1218 b = newb
1214 b = newb
1219 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1215 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1220 if tags:
1216 if tags:
1221 ls = labels.get(r)
1217 ls = labels.get(r)
1222 if ls:
1218 if ls:
1223 for l in ls:
1219 for l in ls:
1224 yield 'l', (r, l)
1220 yield 'l', (r, l)
1225 else:
1221 else:
1226 raise util.Abort(_('need repo for changelog dag'))
1222 raise util.Abort(_('need repo for changelog dag'))
1227
1223
1228 for line in dagparser.dagtextlines(events(),
1224 for line in dagparser.dagtextlines(events(),
1229 addspaces=spaces,
1225 addspaces=spaces,
1230 wraplabels=True,
1226 wraplabels=True,
1231 wrapannotations=True,
1227 wrapannotations=True,
1232 wrapnonlinear=dots,
1228 wrapnonlinear=dots,
1233 usedots=dots,
1229 usedots=dots,
1234 maxlinewidth=70):
1230 maxlinewidth=70):
1235 ui.write(line)
1231 ui.write(line)
1236 ui.write("\n")
1232 ui.write("\n")
1237
1233
1238 def debugdata(ui, repo, file_, rev):
1234 def debugdata(ui, repo, file_, rev):
1239 """dump the contents of a data file revision"""
1235 """dump the contents of a data file revision"""
1240 r = None
1236 r = None
1241 if repo:
1237 if repo:
1242 filelog = repo.file(file_)
1238 filelog = repo.file(file_)
1243 if len(filelog):
1239 if len(filelog):
1244 r = filelog
1240 r = filelog
1245 if not r:
1241 if not r:
1246 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1242 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1247 try:
1243 try:
1248 ui.write(r.revision(r.lookup(rev)))
1244 ui.write(r.revision(r.lookup(rev)))
1249 except KeyError:
1245 except KeyError:
1250 raise util.Abort(_('invalid revision identifier %s') % rev)
1246 raise util.Abort(_('invalid revision identifier %s') % rev)
1251
1247
1252 def debugdate(ui, date, range=None, **opts):
1248 def debugdate(ui, date, range=None, **opts):
1253 """parse and display a date"""
1249 """parse and display a date"""
1254 if opts["extended"]:
1250 if opts["extended"]:
1255 d = util.parsedate(date, util.extendeddateformats)
1251 d = util.parsedate(date, util.extendeddateformats)
1256 else:
1252 else:
1257 d = util.parsedate(date)
1253 d = util.parsedate(date)
1258 ui.write("internal: %s %s\n" % d)
1254 ui.write("internal: %s %s\n" % d)
1259 ui.write("standard: %s\n" % util.datestr(d))
1255 ui.write("standard: %s\n" % util.datestr(d))
1260 if range:
1256 if range:
1261 m = util.matchdate(range)
1257 m = util.matchdate(range)
1262 ui.write("match: %s\n" % m(d[0]))
1258 ui.write("match: %s\n" % m(d[0]))
1263
1259
1264 def debugindex(ui, repo, file_, **opts):
1260 def debugindex(ui, repo, file_, **opts):
1265 """dump the contents of an index file"""
1261 """dump the contents of an index file"""
1266 r = None
1262 r = None
1267 if repo:
1263 if repo:
1268 filelog = repo.file(file_)
1264 filelog = repo.file(file_)
1269 if len(filelog):
1265 if len(filelog):
1270 r = filelog
1266 r = filelog
1271
1267
1272 format = opts.get('format', 0)
1268 format = opts.get('format', 0)
1273 if format not in (0, 1):
1269 if format not in (0, 1):
1274 raise util.Abort("unknown format %d" % format)
1270 raise util.Abort("unknown format %d" % format)
1275
1271
1276 if not r:
1272 if not r:
1277 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1273 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1278
1274
1279 if format == 0:
1275 if format == 0:
1280 ui.write(" rev offset length base linkrev"
1276 ui.write(" rev offset length base linkrev"
1281 " nodeid p1 p2\n")
1277 " nodeid p1 p2\n")
1282 elif format == 1:
1278 elif format == 1:
1283 ui.write(" rev flag offset length"
1279 ui.write(" rev flag offset length"
1284 " size base link p1 p2 nodeid\n")
1280 " size base link p1 p2 nodeid\n")
1285
1281
1286 for i in r:
1282 for i in r:
1287 node = r.node(i)
1283 node = r.node(i)
1288 if format == 0:
1284 if format == 0:
1289 try:
1285 try:
1290 pp = r.parents(node)
1286 pp = r.parents(node)
1291 except:
1287 except:
1292 pp = [nullid, nullid]
1288 pp = [nullid, nullid]
1293 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1289 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1294 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1290 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1295 short(node), short(pp[0]), short(pp[1])))
1291 short(node), short(pp[0]), short(pp[1])))
1296 elif format == 1:
1292 elif format == 1:
1297 pr = r.parentrevs(i)
1293 pr = r.parentrevs(i)
1298 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1294 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1299 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1295 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1300 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1296 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1301
1297
1302 def debugindexdot(ui, repo, file_):
1298 def debugindexdot(ui, repo, file_):
1303 """dump an index DAG as a graphviz dot file"""
1299 """dump an index DAG as a graphviz dot file"""
1304 r = None
1300 r = None
1305 if repo:
1301 if repo:
1306 filelog = repo.file(file_)
1302 filelog = repo.file(file_)
1307 if len(filelog):
1303 if len(filelog):
1308 r = filelog
1304 r = filelog
1309 if not r:
1305 if not r:
1310 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1306 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1311 ui.write("digraph G {\n")
1307 ui.write("digraph G {\n")
1312 for i in r:
1308 for i in r:
1313 node = r.node(i)
1309 node = r.node(i)
1314 pp = r.parents(node)
1310 pp = r.parents(node)
1315 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1311 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1316 if pp[1] != nullid:
1312 if pp[1] != nullid:
1317 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1313 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1318 ui.write("}\n")
1314 ui.write("}\n")
1319
1315
1320 def debuginstall(ui):
1316 def debuginstall(ui):
1321 '''test Mercurial installation
1317 '''test Mercurial installation
1322
1318
1323 Returns 0 on success.
1319 Returns 0 on success.
1324 '''
1320 '''
1325
1321
1326 def writetemp(contents):
1322 def writetemp(contents):
1327 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1323 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1328 f = os.fdopen(fd, "wb")
1324 f = os.fdopen(fd, "wb")
1329 f.write(contents)
1325 f.write(contents)
1330 f.close()
1326 f.close()
1331 return name
1327 return name
1332
1328
1333 problems = 0
1329 problems = 0
1334
1330
1335 # encoding
1331 # encoding
1336 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1332 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1337 try:
1333 try:
1338 encoding.fromlocal("test")
1334 encoding.fromlocal("test")
1339 except util.Abort, inst:
1335 except util.Abort, inst:
1340 ui.write(" %s\n" % inst)
1336 ui.write(" %s\n" % inst)
1341 ui.write(_(" (check that your locale is properly set)\n"))
1337 ui.write(_(" (check that your locale is properly set)\n"))
1342 problems += 1
1338 problems += 1
1343
1339
1344 # compiled modules
1340 # compiled modules
1345 ui.status(_("Checking installed modules (%s)...\n")
1341 ui.status(_("Checking installed modules (%s)...\n")
1346 % os.path.dirname(__file__))
1342 % os.path.dirname(__file__))
1347 try:
1343 try:
1348 import bdiff, mpatch, base85, osutil
1344 import bdiff, mpatch, base85, osutil
1349 except Exception, inst:
1345 except Exception, inst:
1350 ui.write(" %s\n" % inst)
1346 ui.write(" %s\n" % inst)
1351 ui.write(_(" One or more extensions could not be found"))
1347 ui.write(_(" One or more extensions could not be found"))
1352 ui.write(_(" (check that you compiled the extensions)\n"))
1348 ui.write(_(" (check that you compiled the extensions)\n"))
1353 problems += 1
1349 problems += 1
1354
1350
1355 # templates
1351 # templates
1356 ui.status(_("Checking templates...\n"))
1352 ui.status(_("Checking templates...\n"))
1357 try:
1353 try:
1358 import templater
1354 import templater
1359 templater.templater(templater.templatepath("map-cmdline.default"))
1355 templater.templater(templater.templatepath("map-cmdline.default"))
1360 except Exception, inst:
1356 except Exception, inst:
1361 ui.write(" %s\n" % inst)
1357 ui.write(" %s\n" % inst)
1362 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1358 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1363 problems += 1
1359 problems += 1
1364
1360
1365 # patch
1361 # patch
1366 ui.status(_("Checking patch...\n"))
1362 ui.status(_("Checking patch...\n"))
1367 patchproblems = 0
1363 patchproblems = 0
1368 a = "1\n2\n3\n4\n"
1364 a = "1\n2\n3\n4\n"
1369 b = "1\n2\n3\ninsert\n4\n"
1365 b = "1\n2\n3\ninsert\n4\n"
1370 fa = writetemp(a)
1366 fa = writetemp(a)
1371 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1367 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1372 os.path.basename(fa))
1368 os.path.basename(fa))
1373 fd = writetemp(d)
1369 fd = writetemp(d)
1374
1370
1375 files = {}
1371 files = {}
1376 try:
1372 try:
1377 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1373 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1378 except util.Abort, e:
1374 except util.Abort, e:
1379 ui.write(_(" patch call failed:\n"))
1375 ui.write(_(" patch call failed:\n"))
1380 ui.write(" " + str(e) + "\n")
1376 ui.write(" " + str(e) + "\n")
1381 patchproblems += 1
1377 patchproblems += 1
1382 else:
1378 else:
1383 if list(files) != [os.path.basename(fa)]:
1379 if list(files) != [os.path.basename(fa)]:
1384 ui.write(_(" unexpected patch output!\n"))
1380 ui.write(_(" unexpected patch output!\n"))
1385 patchproblems += 1
1381 patchproblems += 1
1386 a = open(fa).read()
1382 a = open(fa).read()
1387 if a != b:
1383 if a != b:
1388 ui.write(_(" patch test failed!\n"))
1384 ui.write(_(" patch test failed!\n"))
1389 patchproblems += 1
1385 patchproblems += 1
1390
1386
1391 if patchproblems:
1387 if patchproblems:
1392 if ui.config('ui', 'patch'):
1388 if ui.config('ui', 'patch'):
1393 ui.write(_(" (Current patch tool may be incompatible with patch,"
1389 ui.write(_(" (Current patch tool may be incompatible with patch,"
1394 " or misconfigured. Please check your configuration"
1390 " or misconfigured. Please check your configuration"
1395 " file)\n"))
1391 " file)\n"))
1396 else:
1392 else:
1397 ui.write(_(" Internal patcher failure, please report this error"
1393 ui.write(_(" Internal patcher failure, please report this error"
1398 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1394 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1399 problems += patchproblems
1395 problems += patchproblems
1400
1396
1401 os.unlink(fa)
1397 os.unlink(fa)
1402 os.unlink(fd)
1398 os.unlink(fd)
1403
1399
1404 # editor
1400 # editor
1405 ui.status(_("Checking commit editor...\n"))
1401 ui.status(_("Checking commit editor...\n"))
1406 editor = ui.geteditor()
1402 editor = ui.geteditor()
1407 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1403 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1408 if not cmdpath:
1404 if not cmdpath:
1409 if editor == 'vi':
1405 if editor == 'vi':
1410 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1406 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1411 ui.write(_(" (specify a commit editor in your configuration"
1407 ui.write(_(" (specify a commit editor in your configuration"
1412 " file)\n"))
1408 " file)\n"))
1413 else:
1409 else:
1414 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1410 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1415 ui.write(_(" (specify a commit editor in your configuration"
1411 ui.write(_(" (specify a commit editor in your configuration"
1416 " file)\n"))
1412 " file)\n"))
1417 problems += 1
1413 problems += 1
1418
1414
1419 # check username
1415 # check username
1420 ui.status(_("Checking username...\n"))
1416 ui.status(_("Checking username...\n"))
1421 try:
1417 try:
1422 ui.username()
1418 ui.username()
1423 except util.Abort, e:
1419 except util.Abort, e:
1424 ui.write(" %s\n" % e)
1420 ui.write(" %s\n" % e)
1425 ui.write(_(" (specify a username in your configuration file)\n"))
1421 ui.write(_(" (specify a username in your configuration file)\n"))
1426 problems += 1
1422 problems += 1
1427
1423
1428 if not problems:
1424 if not problems:
1429 ui.status(_("No problems detected\n"))
1425 ui.status(_("No problems detected\n"))
1430 else:
1426 else:
1431 ui.write(_("%s problems detected,"
1427 ui.write(_("%s problems detected,"
1432 " please check your install!\n") % problems)
1428 " please check your install!\n") % problems)
1433
1429
1434 return problems
1430 return problems
1435
1431
1436 def debugrename(ui, repo, file1, *pats, **opts):
1432 def debugrename(ui, repo, file1, *pats, **opts):
1437 """dump rename information"""
1433 """dump rename information"""
1438
1434
1439 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1435 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1440 m = cmdutil.match(repo, (file1,) + pats, opts)
1436 m = cmdutil.match(repo, (file1,) + pats, opts)
1441 for abs in ctx.walk(m):
1437 for abs in ctx.walk(m):
1442 fctx = ctx[abs]
1438 fctx = ctx[abs]
1443 o = fctx.filelog().renamed(fctx.filenode())
1439 o = fctx.filelog().renamed(fctx.filenode())
1444 rel = m.rel(abs)
1440 rel = m.rel(abs)
1445 if o:
1441 if o:
1446 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1442 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1447 else:
1443 else:
1448 ui.write(_("%s not renamed\n") % rel)
1444 ui.write(_("%s not renamed\n") % rel)
1449
1445
1450 def debugwalk(ui, repo, *pats, **opts):
1446 def debugwalk(ui, repo, *pats, **opts):
1451 """show how files match on given patterns"""
1447 """show how files match on given patterns"""
1452 m = cmdutil.match(repo, pats, opts)
1448 m = cmdutil.match(repo, pats, opts)
1453 items = list(repo.walk(m))
1449 items = list(repo.walk(m))
1454 if not items:
1450 if not items:
1455 return
1451 return
1456 fmt = 'f %%-%ds %%-%ds %%s' % (
1452 fmt = 'f %%-%ds %%-%ds %%s' % (
1457 max([len(abs) for abs in items]),
1453 max([len(abs) for abs in items]),
1458 max([len(m.rel(abs)) for abs in items]))
1454 max([len(m.rel(abs)) for abs in items]))
1459 for abs in items:
1455 for abs in items:
1460 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1456 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1461 ui.write("%s\n" % line.rstrip())
1457 ui.write("%s\n" % line.rstrip())
1462
1458
1463 def diff(ui, repo, *pats, **opts):
1459 def diff(ui, repo, *pats, **opts):
1464 """diff repository (or selected files)
1460 """diff repository (or selected files)
1465
1461
1466 Show differences between revisions for the specified files.
1462 Show differences between revisions for the specified files.
1467
1463
1468 Differences between files are shown using the unified diff format.
1464 Differences between files are shown using the unified diff format.
1469
1465
1470 .. note::
1466 .. note::
1471 diff may generate unexpected results for merges, as it will
1467 diff may generate unexpected results for merges, as it will
1472 default to comparing against the working directory's first
1468 default to comparing against the working directory's first
1473 parent changeset if no revisions are specified.
1469 parent changeset if no revisions are specified.
1474
1470
1475 When two revision arguments are given, then changes are shown
1471 When two revision arguments are given, then changes are shown
1476 between those revisions. If only one revision is specified then
1472 between those revisions. If only one revision is specified then
1477 that revision is compared to the working directory, and, when no
1473 that revision is compared to the working directory, and, when no
1478 revisions are specified, the working directory files are compared
1474 revisions are specified, the working directory files are compared
1479 to its parent.
1475 to its parent.
1480
1476
1481 Alternatively you can specify -c/--change with a revision to see
1477 Alternatively you can specify -c/--change with a revision to see
1482 the changes in that changeset relative to its first parent.
1478 the changes in that changeset relative to its first parent.
1483
1479
1484 Without the -a/--text option, diff will avoid generating diffs of
1480 Without the -a/--text option, diff will avoid generating diffs of
1485 files it detects as binary. With -a, diff will generate a diff
1481 files it detects as binary. With -a, diff will generate a diff
1486 anyway, probably with undesirable results.
1482 anyway, probably with undesirable results.
1487
1483
1488 Use the -g/--git option to generate diffs in the git extended diff
1484 Use the -g/--git option to generate diffs in the git extended diff
1489 format. For more information, read :hg:`help diffs`.
1485 format. For more information, read :hg:`help diffs`.
1490
1486
1491 Returns 0 on success.
1487 Returns 0 on success.
1492 """
1488 """
1493
1489
1494 revs = opts.get('rev')
1490 revs = opts.get('rev')
1495 change = opts.get('change')
1491 change = opts.get('change')
1496 stat = opts.get('stat')
1492 stat = opts.get('stat')
1497 reverse = opts.get('reverse')
1493 reverse = opts.get('reverse')
1498
1494
1499 if revs and change:
1495 if revs and change:
1500 msg = _('cannot specify --rev and --change at the same time')
1496 msg = _('cannot specify --rev and --change at the same time')
1501 raise util.Abort(msg)
1497 raise util.Abort(msg)
1502 elif change:
1498 elif change:
1503 node2 = repo.lookup(change)
1499 node2 = repo.lookup(change)
1504 node1 = repo[node2].parents()[0].node()
1500 node1 = repo[node2].parents()[0].node()
1505 else:
1501 else:
1506 node1, node2 = cmdutil.revpair(repo, revs)
1502 node1, node2 = cmdutil.revpair(repo, revs)
1507
1503
1508 if reverse:
1504 if reverse:
1509 node1, node2 = node2, node1
1505 node1, node2 = node2, node1
1510
1506
1511 diffopts = patch.diffopts(ui, opts)
1507 diffopts = patch.diffopts(ui, opts)
1512 m = cmdutil.match(repo, pats, opts)
1508 m = cmdutil.match(repo, pats, opts)
1513 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1509 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1514 listsubrepos=opts.get('subrepos'))
1510 listsubrepos=opts.get('subrepos'))
1515
1511
1516 def export(ui, repo, *changesets, **opts):
1512 def export(ui, repo, *changesets, **opts):
1517 """dump the header and diffs for one or more changesets
1513 """dump the header and diffs for one or more changesets
1518
1514
1519 Print the changeset header and diffs for one or more revisions.
1515 Print the changeset header and diffs for one or more revisions.
1520
1516
1521 The information shown in the changeset header is: author, date,
1517 The information shown in the changeset header is: author, date,
1522 branch name (if non-default), changeset hash, parent(s) and commit
1518 branch name (if non-default), changeset hash, parent(s) and commit
1523 comment.
1519 comment.
1524
1520
1525 .. note::
1521 .. note::
1526 export may generate unexpected diff output for merge
1522 export may generate unexpected diff output for merge
1527 changesets, as it will compare the merge changeset against its
1523 changesets, as it will compare the merge changeset against its
1528 first parent only.
1524 first parent only.
1529
1525
1530 Output may be to a file, in which case the name of the file is
1526 Output may be to a file, in which case the name of the file is
1531 given using a format string. The formatting rules are as follows:
1527 given using a format string. The formatting rules are as follows:
1532
1528
1533 :``%%``: literal "%" character
1529 :``%%``: literal "%" character
1534 :``%H``: changeset hash (40 hexadecimal digits)
1530 :``%H``: changeset hash (40 hexadecimal digits)
1535 :``%N``: number of patches being generated
1531 :``%N``: number of patches being generated
1536 :``%R``: changeset revision number
1532 :``%R``: changeset revision number
1537 :``%b``: basename of the exporting repository
1533 :``%b``: basename of the exporting repository
1538 :``%h``: short-form changeset hash (12 hexadecimal digits)
1534 :``%h``: short-form changeset hash (12 hexadecimal digits)
1539 :``%n``: zero-padded sequence number, starting at 1
1535 :``%n``: zero-padded sequence number, starting at 1
1540 :``%r``: zero-padded changeset revision number
1536 :``%r``: zero-padded changeset revision number
1541
1537
1542 Without the -a/--text option, export will avoid generating diffs
1538 Without the -a/--text option, export will avoid generating diffs
1543 of files it detects as binary. With -a, export will generate a
1539 of files it detects as binary. With -a, export will generate a
1544 diff anyway, probably with undesirable results.
1540 diff anyway, probably with undesirable results.
1545
1541
1546 Use the -g/--git option to generate diffs in the git extended diff
1542 Use the -g/--git option to generate diffs in the git extended diff
1547 format. See :hg:`help diffs` for more information.
1543 format. See :hg:`help diffs` for more information.
1548
1544
1549 With the --switch-parent option, the diff will be against the
1545 With the --switch-parent option, the diff will be against the
1550 second parent. It can be useful to review a merge.
1546 second parent. It can be useful to review a merge.
1551
1547
1552 Returns 0 on success.
1548 Returns 0 on success.
1553 """
1549 """
1554 changesets += tuple(opts.get('rev', []))
1550 changesets += tuple(opts.get('rev', []))
1555 if not changesets:
1551 if not changesets:
1556 raise util.Abort(_("export requires at least one changeset"))
1552 raise util.Abort(_("export requires at least one changeset"))
1557 revs = cmdutil.revrange(repo, changesets)
1553 revs = cmdutil.revrange(repo, changesets)
1558 if len(revs) > 1:
1554 if len(revs) > 1:
1559 ui.note(_('exporting patches:\n'))
1555 ui.note(_('exporting patches:\n'))
1560 else:
1556 else:
1561 ui.note(_('exporting patch:\n'))
1557 ui.note(_('exporting patch:\n'))
1562 cmdutil.export(repo, revs, template=opts.get('output'),
1558 cmdutil.export(repo, revs, template=opts.get('output'),
1563 switch_parent=opts.get('switch_parent'),
1559 switch_parent=opts.get('switch_parent'),
1564 opts=patch.diffopts(ui, opts))
1560 opts=patch.diffopts(ui, opts))
1565
1561
1566 def forget(ui, repo, *pats, **opts):
1562 def forget(ui, repo, *pats, **opts):
1567 """forget the specified files on the next commit
1563 """forget the specified files on the next commit
1568
1564
1569 Mark the specified files so they will no longer be tracked
1565 Mark the specified files so they will no longer be tracked
1570 after the next commit.
1566 after the next commit.
1571
1567
1572 This only removes files from the current branch, not from the
1568 This only removes files from the current branch, not from the
1573 entire project history, and it does not delete them from the
1569 entire project history, and it does not delete them from the
1574 working directory.
1570 working directory.
1575
1571
1576 To undo a forget before the next commit, see :hg:`add`.
1572 To undo a forget before the next commit, see :hg:`add`.
1577
1573
1578 Returns 0 on success.
1574 Returns 0 on success.
1579 """
1575 """
1580
1576
1581 if not pats:
1577 if not pats:
1582 raise util.Abort(_('no files specified'))
1578 raise util.Abort(_('no files specified'))
1583
1579
1584 m = cmdutil.match(repo, pats, opts)
1580 m = cmdutil.match(repo, pats, opts)
1585 s = repo.status(match=m, clean=True)
1581 s = repo.status(match=m, clean=True)
1586 forget = sorted(s[0] + s[1] + s[3] + s[6])
1582 forget = sorted(s[0] + s[1] + s[3] + s[6])
1587 errs = 0
1583 errs = 0
1588
1584
1589 for f in m.files():
1585 for f in m.files():
1590 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1586 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1591 ui.warn(_('not removing %s: file is already untracked\n')
1587 ui.warn(_('not removing %s: file is already untracked\n')
1592 % m.rel(f))
1588 % m.rel(f))
1593 errs = 1
1589 errs = 1
1594
1590
1595 for f in forget:
1591 for f in forget:
1596 if ui.verbose or not m.exact(f):
1592 if ui.verbose or not m.exact(f):
1597 ui.status(_('removing %s\n') % m.rel(f))
1593 ui.status(_('removing %s\n') % m.rel(f))
1598
1594
1599 repo[None].remove(forget, unlink=False)
1595 repo[None].remove(forget, unlink=False)
1600 return errs
1596 return errs
1601
1597
1602 def grep(ui, repo, pattern, *pats, **opts):
1598 def grep(ui, repo, pattern, *pats, **opts):
1603 """search for a pattern in specified files and revisions
1599 """search for a pattern in specified files and revisions
1604
1600
1605 Search revisions of files for a regular expression.
1601 Search revisions of files for a regular expression.
1606
1602
1607 This command behaves differently than Unix grep. It only accepts
1603 This command behaves differently than Unix grep. It only accepts
1608 Python/Perl regexps. It searches repository history, not the
1604 Python/Perl regexps. It searches repository history, not the
1609 working directory. It always prints the revision number in which a
1605 working directory. It always prints the revision number in which a
1610 match appears.
1606 match appears.
1611
1607
1612 By default, grep only prints output for the first revision of a
1608 By default, grep only prints output for the first revision of a
1613 file in which it finds a match. To get it to print every revision
1609 file in which it finds a match. To get it to print every revision
1614 that contains a change in match status ("-" for a match that
1610 that contains a change in match status ("-" for a match that
1615 becomes a non-match, or "+" for a non-match that becomes a match),
1611 becomes a non-match, or "+" for a non-match that becomes a match),
1616 use the --all flag.
1612 use the --all flag.
1617
1613
1618 Returns 0 if a match is found, 1 otherwise.
1614 Returns 0 if a match is found, 1 otherwise.
1619 """
1615 """
1620 reflags = 0
1616 reflags = 0
1621 if opts.get('ignore_case'):
1617 if opts.get('ignore_case'):
1622 reflags |= re.I
1618 reflags |= re.I
1623 try:
1619 try:
1624 regexp = re.compile(pattern, reflags)
1620 regexp = re.compile(pattern, reflags)
1625 except re.error, inst:
1621 except re.error, inst:
1626 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1622 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1627 return 1
1623 return 1
1628 sep, eol = ':', '\n'
1624 sep, eol = ':', '\n'
1629 if opts.get('print0'):
1625 if opts.get('print0'):
1630 sep = eol = '\0'
1626 sep = eol = '\0'
1631
1627
1632 getfile = util.lrucachefunc(repo.file)
1628 getfile = util.lrucachefunc(repo.file)
1633
1629
1634 def matchlines(body):
1630 def matchlines(body):
1635 begin = 0
1631 begin = 0
1636 linenum = 0
1632 linenum = 0
1637 while True:
1633 while True:
1638 match = regexp.search(body, begin)
1634 match = regexp.search(body, begin)
1639 if not match:
1635 if not match:
1640 break
1636 break
1641 mstart, mend = match.span()
1637 mstart, mend = match.span()
1642 linenum += body.count('\n', begin, mstart) + 1
1638 linenum += body.count('\n', begin, mstart) + 1
1643 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1639 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1644 begin = body.find('\n', mend) + 1 or len(body)
1640 begin = body.find('\n', mend) + 1 or len(body)
1645 lend = begin - 1
1641 lend = begin - 1
1646 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1642 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1647
1643
1648 class linestate(object):
1644 class linestate(object):
1649 def __init__(self, line, linenum, colstart, colend):
1645 def __init__(self, line, linenum, colstart, colend):
1650 self.line = line
1646 self.line = line
1651 self.linenum = linenum
1647 self.linenum = linenum
1652 self.colstart = colstart
1648 self.colstart = colstart
1653 self.colend = colend
1649 self.colend = colend
1654
1650
1655 def __hash__(self):
1651 def __hash__(self):
1656 return hash((self.linenum, self.line))
1652 return hash((self.linenum, self.line))
1657
1653
1658 def __eq__(self, other):
1654 def __eq__(self, other):
1659 return self.line == other.line
1655 return self.line == other.line
1660
1656
1661 matches = {}
1657 matches = {}
1662 copies = {}
1658 copies = {}
1663 def grepbody(fn, rev, body):
1659 def grepbody(fn, rev, body):
1664 matches[rev].setdefault(fn, [])
1660 matches[rev].setdefault(fn, [])
1665 m = matches[rev][fn]
1661 m = matches[rev][fn]
1666 for lnum, cstart, cend, line in matchlines(body):
1662 for lnum, cstart, cend, line in matchlines(body):
1667 s = linestate(line, lnum, cstart, cend)
1663 s = linestate(line, lnum, cstart, cend)
1668 m.append(s)
1664 m.append(s)
1669
1665
1670 def difflinestates(a, b):
1666 def difflinestates(a, b):
1671 sm = difflib.SequenceMatcher(None, a, b)
1667 sm = difflib.SequenceMatcher(None, a, b)
1672 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1668 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1673 if tag == 'insert':
1669 if tag == 'insert':
1674 for i in xrange(blo, bhi):
1670 for i in xrange(blo, bhi):
1675 yield ('+', b[i])
1671 yield ('+', b[i])
1676 elif tag == 'delete':
1672 elif tag == 'delete':
1677 for i in xrange(alo, ahi):
1673 for i in xrange(alo, ahi):
1678 yield ('-', a[i])
1674 yield ('-', a[i])
1679 elif tag == 'replace':
1675 elif tag == 'replace':
1680 for i in xrange(alo, ahi):
1676 for i in xrange(alo, ahi):
1681 yield ('-', a[i])
1677 yield ('-', a[i])
1682 for i in xrange(blo, bhi):
1678 for i in xrange(blo, bhi):
1683 yield ('+', b[i])
1679 yield ('+', b[i])
1684
1680
1685 def display(fn, ctx, pstates, states):
1681 def display(fn, ctx, pstates, states):
1686 rev = ctx.rev()
1682 rev = ctx.rev()
1687 datefunc = ui.quiet and util.shortdate or util.datestr
1683 datefunc = ui.quiet and util.shortdate or util.datestr
1688 found = False
1684 found = False
1689 filerevmatches = {}
1685 filerevmatches = {}
1690 if opts.get('all'):
1686 if opts.get('all'):
1691 iter = difflinestates(pstates, states)
1687 iter = difflinestates(pstates, states)
1692 else:
1688 else:
1693 iter = [('', l) for l in states]
1689 iter = [('', l) for l in states]
1694 for change, l in iter:
1690 for change, l in iter:
1695 cols = [fn, str(rev)]
1691 cols = [fn, str(rev)]
1696 before, match, after = None, None, None
1692 before, match, after = None, None, None
1697 if opts.get('line_number'):
1693 if opts.get('line_number'):
1698 cols.append(str(l.linenum))
1694 cols.append(str(l.linenum))
1699 if opts.get('all'):
1695 if opts.get('all'):
1700 cols.append(change)
1696 cols.append(change)
1701 if opts.get('user'):
1697 if opts.get('user'):
1702 cols.append(ui.shortuser(ctx.user()))
1698 cols.append(ui.shortuser(ctx.user()))
1703 if opts.get('date'):
1699 if opts.get('date'):
1704 cols.append(datefunc(ctx.date()))
1700 cols.append(datefunc(ctx.date()))
1705 if opts.get('files_with_matches'):
1701 if opts.get('files_with_matches'):
1706 c = (fn, rev)
1702 c = (fn, rev)
1707 if c in filerevmatches:
1703 if c in filerevmatches:
1708 continue
1704 continue
1709 filerevmatches[c] = 1
1705 filerevmatches[c] = 1
1710 else:
1706 else:
1711 before = l.line[:l.colstart]
1707 before = l.line[:l.colstart]
1712 match = l.line[l.colstart:l.colend]
1708 match = l.line[l.colstart:l.colend]
1713 after = l.line[l.colend:]
1709 after = l.line[l.colend:]
1714 ui.write(sep.join(cols))
1710 ui.write(sep.join(cols))
1715 if before is not None:
1711 if before is not None:
1716 ui.write(sep + before)
1712 ui.write(sep + before)
1717 ui.write(match, label='grep.match')
1713 ui.write(match, label='grep.match')
1718 ui.write(after)
1714 ui.write(after)
1719 ui.write(eol)
1715 ui.write(eol)
1720 found = True
1716 found = True
1721 return found
1717 return found
1722
1718
1723 skip = {}
1719 skip = {}
1724 revfiles = {}
1720 revfiles = {}
1725 matchfn = cmdutil.match(repo, pats, opts)
1721 matchfn = cmdutil.match(repo, pats, opts)
1726 found = False
1722 found = False
1727 follow = opts.get('follow')
1723 follow = opts.get('follow')
1728
1724
1729 def prep(ctx, fns):
1725 def prep(ctx, fns):
1730 rev = ctx.rev()
1726 rev = ctx.rev()
1731 pctx = ctx.parents()[0]
1727 pctx = ctx.parents()[0]
1732 parent = pctx.rev()
1728 parent = pctx.rev()
1733 matches.setdefault(rev, {})
1729 matches.setdefault(rev, {})
1734 matches.setdefault(parent, {})
1730 matches.setdefault(parent, {})
1735 files = revfiles.setdefault(rev, [])
1731 files = revfiles.setdefault(rev, [])
1736 for fn in fns:
1732 for fn in fns:
1737 flog = getfile(fn)
1733 flog = getfile(fn)
1738 try:
1734 try:
1739 fnode = ctx.filenode(fn)
1735 fnode = ctx.filenode(fn)
1740 except error.LookupError:
1736 except error.LookupError:
1741 continue
1737 continue
1742
1738
1743 copied = flog.renamed(fnode)
1739 copied = flog.renamed(fnode)
1744 copy = follow and copied and copied[0]
1740 copy = follow and copied and copied[0]
1745 if copy:
1741 if copy:
1746 copies.setdefault(rev, {})[fn] = copy
1742 copies.setdefault(rev, {})[fn] = copy
1747 if fn in skip:
1743 if fn in skip:
1748 if copy:
1744 if copy:
1749 skip[copy] = True
1745 skip[copy] = True
1750 continue
1746 continue
1751 files.append(fn)
1747 files.append(fn)
1752
1748
1753 if fn not in matches[rev]:
1749 if fn not in matches[rev]:
1754 grepbody(fn, rev, flog.read(fnode))
1750 grepbody(fn, rev, flog.read(fnode))
1755
1751
1756 pfn = copy or fn
1752 pfn = copy or fn
1757 if pfn not in matches[parent]:
1753 if pfn not in matches[parent]:
1758 try:
1754 try:
1759 fnode = pctx.filenode(pfn)
1755 fnode = pctx.filenode(pfn)
1760 grepbody(pfn, parent, flog.read(fnode))
1756 grepbody(pfn, parent, flog.read(fnode))
1761 except error.LookupError:
1757 except error.LookupError:
1762 pass
1758 pass
1763
1759
1764 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1760 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1765 rev = ctx.rev()
1761 rev = ctx.rev()
1766 parent = ctx.parents()[0].rev()
1762 parent = ctx.parents()[0].rev()
1767 for fn in sorted(revfiles.get(rev, [])):
1763 for fn in sorted(revfiles.get(rev, [])):
1768 states = matches[rev][fn]
1764 states = matches[rev][fn]
1769 copy = copies.get(rev, {}).get(fn)
1765 copy = copies.get(rev, {}).get(fn)
1770 if fn in skip:
1766 if fn in skip:
1771 if copy:
1767 if copy:
1772 skip[copy] = True
1768 skip[copy] = True
1773 continue
1769 continue
1774 pstates = matches.get(parent, {}).get(copy or fn, [])
1770 pstates = matches.get(parent, {}).get(copy or fn, [])
1775 if pstates or states:
1771 if pstates or states:
1776 r = display(fn, ctx, pstates, states)
1772 r = display(fn, ctx, pstates, states)
1777 found = found or r
1773 found = found or r
1778 if r and not opts.get('all'):
1774 if r and not opts.get('all'):
1779 skip[fn] = True
1775 skip[fn] = True
1780 if copy:
1776 if copy:
1781 skip[copy] = True
1777 skip[copy] = True
1782 del matches[rev]
1778 del matches[rev]
1783 del revfiles[rev]
1779 del revfiles[rev]
1784
1780
1785 return not found
1781 return not found
1786
1782
1787 def heads(ui, repo, *branchrevs, **opts):
1783 def heads(ui, repo, *branchrevs, **opts):
1788 """show current repository heads or show branch heads
1784 """show current repository heads or show branch heads
1789
1785
1790 With no arguments, show all repository branch heads.
1786 With no arguments, show all repository branch heads.
1791
1787
1792 Repository "heads" are changesets with no child changesets. They are
1788 Repository "heads" are changesets with no child changesets. They are
1793 where development generally takes place and are the usual targets
1789 where development generally takes place and are the usual targets
1794 for update and merge operations. Branch heads are changesets that have
1790 for update and merge operations. Branch heads are changesets that have
1795 no child changeset on the same branch.
1791 no child changeset on the same branch.
1796
1792
1797 If one or more REVs are given, only branch heads on the branches
1793 If one or more REVs are given, only branch heads on the branches
1798 associated with the specified changesets are shown.
1794 associated with the specified changesets are shown.
1799
1795
1800 If -c/--closed is specified, also show branch heads marked closed
1796 If -c/--closed is specified, also show branch heads marked closed
1801 (see :hg:`commit --close-branch`).
1797 (see :hg:`commit --close-branch`).
1802
1798
1803 If STARTREV is specified, only those heads that are descendants of
1799 If STARTREV is specified, only those heads that are descendants of
1804 STARTREV will be displayed.
1800 STARTREV will be displayed.
1805
1801
1806 If -t/--topo is specified, named branch mechanics will be ignored and only
1802 If -t/--topo is specified, named branch mechanics will be ignored and only
1807 changesets without children will be shown.
1803 changesets without children will be shown.
1808
1804
1809 Returns 0 if matching heads are found, 1 if not.
1805 Returns 0 if matching heads are found, 1 if not.
1810 """
1806 """
1811
1807
1812 start = None
1808 start = None
1813 if 'rev' in opts:
1809 if 'rev' in opts:
1814 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1810 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1815
1811
1816 if opts.get('topo'):
1812 if opts.get('topo'):
1817 heads = [repo[h] for h in repo.heads(start)]
1813 heads = [repo[h] for h in repo.heads(start)]
1818 else:
1814 else:
1819 heads = []
1815 heads = []
1820 for b, ls in repo.branchmap().iteritems():
1816 for b, ls in repo.branchmap().iteritems():
1821 if start is None:
1817 if start is None:
1822 heads += [repo[h] for h in ls]
1818 heads += [repo[h] for h in ls]
1823 continue
1819 continue
1824 startrev = repo.changelog.rev(start)
1820 startrev = repo.changelog.rev(start)
1825 descendants = set(repo.changelog.descendants(startrev))
1821 descendants = set(repo.changelog.descendants(startrev))
1826 descendants.add(startrev)
1822 descendants.add(startrev)
1827 rev = repo.changelog.rev
1823 rev = repo.changelog.rev
1828 heads += [repo[h] for h in ls if rev(h) in descendants]
1824 heads += [repo[h] for h in ls if rev(h) in descendants]
1829
1825
1830 if branchrevs:
1826 if branchrevs:
1831 branches = set(repo[br].branch() for br in branchrevs)
1827 branches = set(repo[br].branch() for br in branchrevs)
1832 heads = [h for h in heads if h.branch() in branches]
1828 heads = [h for h in heads if h.branch() in branches]
1833
1829
1834 if not opts.get('closed'):
1830 if not opts.get('closed'):
1835 heads = [h for h in heads if not h.extra().get('close')]
1831 heads = [h for h in heads if not h.extra().get('close')]
1836
1832
1837 if opts.get('active') and branchrevs:
1833 if opts.get('active') and branchrevs:
1838 dagheads = repo.heads(start)
1834 dagheads = repo.heads(start)
1839 heads = [h for h in heads if h.node() in dagheads]
1835 heads = [h for h in heads if h.node() in dagheads]
1840
1836
1841 if branchrevs:
1837 if branchrevs:
1842 haveheads = set(h.branch() for h in heads)
1838 haveheads = set(h.branch() for h in heads)
1843 if branches - haveheads:
1839 if branches - haveheads:
1844 headless = ', '.join(b for b in branches - haveheads)
1840 headless = ', '.join(b for b in branches - haveheads)
1845 msg = _('no open branch heads found on branches %s')
1841 msg = _('no open branch heads found on branches %s')
1846 if opts.get('rev'):
1842 if opts.get('rev'):
1847 msg += _(' (started at %s)' % opts['rev'])
1843 msg += _(' (started at %s)' % opts['rev'])
1848 ui.warn((msg + '\n') % headless)
1844 ui.warn((msg + '\n') % headless)
1849
1845
1850 if not heads:
1846 if not heads:
1851 return 1
1847 return 1
1852
1848
1853 heads = sorted(heads, key=lambda x: -x.rev())
1849 heads = sorted(heads, key=lambda x: -x.rev())
1854 displayer = cmdutil.show_changeset(ui, repo, opts)
1850 displayer = cmdutil.show_changeset(ui, repo, opts)
1855 for ctx in heads:
1851 for ctx in heads:
1856 displayer.show(ctx)
1852 displayer.show(ctx)
1857 displayer.close()
1853 displayer.close()
1858
1854
1859 def help_(ui, name=None, with_version=False, unknowncmd=False):
1855 def help_(ui, name=None, with_version=False, unknowncmd=False):
1860 """show help for a given topic or a help overview
1856 """show help for a given topic or a help overview
1861
1857
1862 With no arguments, print a list of commands with short help messages.
1858 With no arguments, print a list of commands with short help messages.
1863
1859
1864 Given a topic, extension, or command name, print help for that
1860 Given a topic, extension, or command name, print help for that
1865 topic.
1861 topic.
1866
1862
1867 Returns 0 if successful.
1863 Returns 0 if successful.
1868 """
1864 """
1869 option_lists = []
1865 option_lists = []
1870 textwidth = ui.termwidth() - 2
1866 textwidth = ui.termwidth() - 2
1871
1867
1872 def addglobalopts(aliases):
1868 def addglobalopts(aliases):
1873 if ui.verbose:
1869 if ui.verbose:
1874 option_lists.append((_("global options:"), globalopts))
1870 option_lists.append((_("global options:"), globalopts))
1875 if name == 'shortlist':
1871 if name == 'shortlist':
1876 option_lists.append((_('use "hg help" for the full list '
1872 option_lists.append((_('use "hg help" for the full list '
1877 'of commands'), ()))
1873 'of commands'), ()))
1878 else:
1874 else:
1879 if name == 'shortlist':
1875 if name == 'shortlist':
1880 msg = _('use "hg help" for the full list of commands '
1876 msg = _('use "hg help" for the full list of commands '
1881 'or "hg -v" for details')
1877 'or "hg -v" for details')
1882 elif aliases:
1878 elif aliases:
1883 msg = _('use "hg -v help%s" to show builtin aliases and '
1879 msg = _('use "hg -v help%s" to show builtin aliases and '
1884 'global options') % (name and " " + name or "")
1880 'global options') % (name and " " + name or "")
1885 else:
1881 else:
1886 msg = _('use "hg -v help %s" to show global options') % name
1882 msg = _('use "hg -v help %s" to show global options') % name
1887 option_lists.append((msg, ()))
1883 option_lists.append((msg, ()))
1888
1884
1889 def helpcmd(name):
1885 def helpcmd(name):
1890 if with_version:
1886 if with_version:
1891 version_(ui)
1887 version_(ui)
1892 ui.write('\n')
1888 ui.write('\n')
1893
1889
1894 try:
1890 try:
1895 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1891 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1896 except error.AmbiguousCommand, inst:
1892 except error.AmbiguousCommand, inst:
1897 # py3k fix: except vars can't be used outside the scope of the
1893 # py3k fix: except vars can't be used outside the scope of the
1898 # except block, nor can be used inside a lambda. python issue4617
1894 # except block, nor can be used inside a lambda. python issue4617
1899 prefix = inst.args[0]
1895 prefix = inst.args[0]
1900 select = lambda c: c.lstrip('^').startswith(prefix)
1896 select = lambda c: c.lstrip('^').startswith(prefix)
1901 helplist(_('list of commands:\n\n'), select)
1897 helplist(_('list of commands:\n\n'), select)
1902 return
1898 return
1903
1899
1904 # check if it's an invalid alias and display its error if it is
1900 # check if it's an invalid alias and display its error if it is
1905 if getattr(entry[0], 'badalias', False):
1901 if getattr(entry[0], 'badalias', False):
1906 if not unknowncmd:
1902 if not unknowncmd:
1907 entry[0](ui)
1903 entry[0](ui)
1908 return
1904 return
1909
1905
1910 # synopsis
1906 # synopsis
1911 if len(entry) > 2:
1907 if len(entry) > 2:
1912 if entry[2].startswith('hg'):
1908 if entry[2].startswith('hg'):
1913 ui.write("%s\n" % entry[2])
1909 ui.write("%s\n" % entry[2])
1914 else:
1910 else:
1915 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1911 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1916 else:
1912 else:
1917 ui.write('hg %s\n' % aliases[0])
1913 ui.write('hg %s\n' % aliases[0])
1918
1914
1919 # aliases
1915 # aliases
1920 if not ui.quiet and len(aliases) > 1:
1916 if not ui.quiet and len(aliases) > 1:
1921 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1917 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1922
1918
1923 # description
1919 # description
1924 doc = gettext(entry[0].__doc__)
1920 doc = gettext(entry[0].__doc__)
1925 if not doc:
1921 if not doc:
1926 doc = _("(no help text available)")
1922 doc = _("(no help text available)")
1927 if hasattr(entry[0], 'definition'): # aliased command
1923 if hasattr(entry[0], 'definition'): # aliased command
1928 if entry[0].definition.startswith('!'): # shell alias
1924 if entry[0].definition.startswith('!'): # shell alias
1929 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1925 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1930 else:
1926 else:
1931 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1927 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1932 if ui.quiet:
1928 if ui.quiet:
1933 doc = doc.splitlines()[0]
1929 doc = doc.splitlines()[0]
1934 keep = ui.verbose and ['verbose'] or []
1930 keep = ui.verbose and ['verbose'] or []
1935 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1931 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1936 ui.write("\n%s\n" % formatted)
1932 ui.write("\n%s\n" % formatted)
1937 if pruned:
1933 if pruned:
1938 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1934 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1939
1935
1940 if not ui.quiet:
1936 if not ui.quiet:
1941 # options
1937 # options
1942 if entry[1]:
1938 if entry[1]:
1943 option_lists.append((_("options:\n"), entry[1]))
1939 option_lists.append((_("options:\n"), entry[1]))
1944
1940
1945 addglobalopts(False)
1941 addglobalopts(False)
1946
1942
1947 def helplist(header, select=None):
1943 def helplist(header, select=None):
1948 h = {}
1944 h = {}
1949 cmds = {}
1945 cmds = {}
1950 for c, e in table.iteritems():
1946 for c, e in table.iteritems():
1951 f = c.split("|", 1)[0]
1947 f = c.split("|", 1)[0]
1952 if select and not select(f):
1948 if select and not select(f):
1953 continue
1949 continue
1954 if (not select and name != 'shortlist' and
1950 if (not select and name != 'shortlist' and
1955 e[0].__module__ != __name__):
1951 e[0].__module__ != __name__):
1956 continue
1952 continue
1957 if name == "shortlist" and not f.startswith("^"):
1953 if name == "shortlist" and not f.startswith("^"):
1958 continue
1954 continue
1959 f = f.lstrip("^")
1955 f = f.lstrip("^")
1960 if not ui.debugflag and f.startswith("debug"):
1956 if not ui.debugflag and f.startswith("debug"):
1961 continue
1957 continue
1962 doc = e[0].__doc__
1958 doc = e[0].__doc__
1963 if doc and 'DEPRECATED' in doc and not ui.verbose:
1959 if doc and 'DEPRECATED' in doc and not ui.verbose:
1964 continue
1960 continue
1965 doc = gettext(doc)
1961 doc = gettext(doc)
1966 if not doc:
1962 if not doc:
1967 doc = _("(no help text available)")
1963 doc = _("(no help text available)")
1968 h[f] = doc.splitlines()[0].rstrip()
1964 h[f] = doc.splitlines()[0].rstrip()
1969 cmds[f] = c.lstrip("^")
1965 cmds[f] = c.lstrip("^")
1970
1966
1971 if not h:
1967 if not h:
1972 ui.status(_('no commands defined\n'))
1968 ui.status(_('no commands defined\n'))
1973 return
1969 return
1974
1970
1975 ui.status(header)
1971 ui.status(header)
1976 fns = sorted(h)
1972 fns = sorted(h)
1977 m = max(map(len, fns))
1973 m = max(map(len, fns))
1978 for f in fns:
1974 for f in fns:
1979 if ui.verbose:
1975 if ui.verbose:
1980 commands = cmds[f].replace("|",", ")
1976 commands = cmds[f].replace("|",", ")
1981 ui.write(" %s:\n %s\n"%(commands, h[f]))
1977 ui.write(" %s:\n %s\n"%(commands, h[f]))
1982 else:
1978 else:
1983 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1979 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1984 initindent=' %-*s ' % (m, f),
1980 initindent=' %-*s ' % (m, f),
1985 hangindent=' ' * (m + 4))))
1981 hangindent=' ' * (m + 4))))
1986
1982
1987 if not ui.quiet:
1983 if not ui.quiet:
1988 addglobalopts(True)
1984 addglobalopts(True)
1989
1985
1990 def helptopic(name):
1986 def helptopic(name):
1991 for names, header, doc in help.helptable:
1987 for names, header, doc in help.helptable:
1992 if name in names:
1988 if name in names:
1993 break
1989 break
1994 else:
1990 else:
1995 raise error.UnknownCommand(name)
1991 raise error.UnknownCommand(name)
1996
1992
1997 # description
1993 # description
1998 if not doc:
1994 if not doc:
1999 doc = _("(no help text available)")
1995 doc = _("(no help text available)")
2000 if hasattr(doc, '__call__'):
1996 if hasattr(doc, '__call__'):
2001 doc = doc()
1997 doc = doc()
2002
1998
2003 ui.write("%s\n\n" % header)
1999 ui.write("%s\n\n" % header)
2004 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2000 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2005
2001
2006 def helpext(name):
2002 def helpext(name):
2007 try:
2003 try:
2008 mod = extensions.find(name)
2004 mod = extensions.find(name)
2009 doc = gettext(mod.__doc__) or _('no help text available')
2005 doc = gettext(mod.__doc__) or _('no help text available')
2010 except KeyError:
2006 except KeyError:
2011 mod = None
2007 mod = None
2012 doc = extensions.disabledext(name)
2008 doc = extensions.disabledext(name)
2013 if not doc:
2009 if not doc:
2014 raise error.UnknownCommand(name)
2010 raise error.UnknownCommand(name)
2015
2011
2016 if '\n' not in doc:
2012 if '\n' not in doc:
2017 head, tail = doc, ""
2013 head, tail = doc, ""
2018 else:
2014 else:
2019 head, tail = doc.split('\n', 1)
2015 head, tail = doc.split('\n', 1)
2020 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2016 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2021 if tail:
2017 if tail:
2022 ui.write(minirst.format(tail, textwidth))
2018 ui.write(minirst.format(tail, textwidth))
2023 ui.status('\n\n')
2019 ui.status('\n\n')
2024
2020
2025 if mod:
2021 if mod:
2026 try:
2022 try:
2027 ct = mod.cmdtable
2023 ct = mod.cmdtable
2028 except AttributeError:
2024 except AttributeError:
2029 ct = {}
2025 ct = {}
2030 modcmds = set([c.split('|', 1)[0] for c in ct])
2026 modcmds = set([c.split('|', 1)[0] for c in ct])
2031 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2027 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2032 else:
2028 else:
2033 ui.write(_('use "hg help extensions" for information on enabling '
2029 ui.write(_('use "hg help extensions" for information on enabling '
2034 'extensions\n'))
2030 'extensions\n'))
2035
2031
2036 def helpextcmd(name):
2032 def helpextcmd(name):
2037 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2033 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2038 doc = gettext(mod.__doc__).splitlines()[0]
2034 doc = gettext(mod.__doc__).splitlines()[0]
2039
2035
2040 msg = help.listexts(_("'%s' is provided by the following "
2036 msg = help.listexts(_("'%s' is provided by the following "
2041 "extension:") % cmd, {ext: doc}, len(ext),
2037 "extension:") % cmd, {ext: doc}, len(ext),
2042 indent=4)
2038 indent=4)
2043 ui.write(minirst.format(msg, textwidth))
2039 ui.write(minirst.format(msg, textwidth))
2044 ui.write('\n\n')
2040 ui.write('\n\n')
2045 ui.write(_('use "hg help extensions" for information on enabling '
2041 ui.write(_('use "hg help extensions" for information on enabling '
2046 'extensions\n'))
2042 'extensions\n'))
2047
2043
2048 help.addtopichook('revsets', revset.makedoc)
2044 help.addtopichook('revsets', revset.makedoc)
2049
2045
2050 if name and name != 'shortlist':
2046 if name and name != 'shortlist':
2051 i = None
2047 i = None
2052 if unknowncmd:
2048 if unknowncmd:
2053 queries = (helpextcmd,)
2049 queries = (helpextcmd,)
2054 else:
2050 else:
2055 queries = (helptopic, helpcmd, helpext, helpextcmd)
2051 queries = (helptopic, helpcmd, helpext, helpextcmd)
2056 for f in queries:
2052 for f in queries:
2057 try:
2053 try:
2058 f(name)
2054 f(name)
2059 i = None
2055 i = None
2060 break
2056 break
2061 except error.UnknownCommand, inst:
2057 except error.UnknownCommand, inst:
2062 i = inst
2058 i = inst
2063 if i:
2059 if i:
2064 raise i
2060 raise i
2065
2061
2066 else:
2062 else:
2067 # program name
2063 # program name
2068 if ui.verbose or with_version:
2064 if ui.verbose or with_version:
2069 version_(ui)
2065 version_(ui)
2070 else:
2066 else:
2071 ui.status(_("Mercurial Distributed SCM\n"))
2067 ui.status(_("Mercurial Distributed SCM\n"))
2072 ui.status('\n')
2068 ui.status('\n')
2073
2069
2074 # list of commands
2070 # list of commands
2075 if name == "shortlist":
2071 if name == "shortlist":
2076 header = _('basic commands:\n\n')
2072 header = _('basic commands:\n\n')
2077 else:
2073 else:
2078 header = _('list of commands:\n\n')
2074 header = _('list of commands:\n\n')
2079
2075
2080 helplist(header)
2076 helplist(header)
2081 if name != 'shortlist':
2077 if name != 'shortlist':
2082 exts, maxlength = extensions.enabled()
2078 exts, maxlength = extensions.enabled()
2083 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2079 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2084 if text:
2080 if text:
2085 ui.write("\n%s\n" % minirst.format(text, textwidth))
2081 ui.write("\n%s\n" % minirst.format(text, textwidth))
2086
2082
2087 # list all option lists
2083 # list all option lists
2088 opt_output = []
2084 opt_output = []
2089 multioccur = False
2085 multioccur = False
2090 for title, options in option_lists:
2086 for title, options in option_lists:
2091 opt_output.append(("\n%s" % title, None))
2087 opt_output.append(("\n%s" % title, None))
2092 for option in options:
2088 for option in options:
2093 if len(option) == 5:
2089 if len(option) == 5:
2094 shortopt, longopt, default, desc, optlabel = option
2090 shortopt, longopt, default, desc, optlabel = option
2095 else:
2091 else:
2096 shortopt, longopt, default, desc = option
2092 shortopt, longopt, default, desc = option
2097 optlabel = _("VALUE") # default label
2093 optlabel = _("VALUE") # default label
2098
2094
2099 if _("DEPRECATED") in desc and not ui.verbose:
2095 if _("DEPRECATED") in desc and not ui.verbose:
2100 continue
2096 continue
2101 if isinstance(default, list):
2097 if isinstance(default, list):
2102 numqualifier = " %s [+]" % optlabel
2098 numqualifier = " %s [+]" % optlabel
2103 multioccur = True
2099 multioccur = True
2104 elif (default is not None) and not isinstance(default, bool):
2100 elif (default is not None) and not isinstance(default, bool):
2105 numqualifier = " %s" % optlabel
2101 numqualifier = " %s" % optlabel
2106 else:
2102 else:
2107 numqualifier = ""
2103 numqualifier = ""
2108 opt_output.append(("%2s%s" %
2104 opt_output.append(("%2s%s" %
2109 (shortopt and "-%s" % shortopt,
2105 (shortopt and "-%s" % shortopt,
2110 longopt and " --%s%s" %
2106 longopt and " --%s%s" %
2111 (longopt, numqualifier)),
2107 (longopt, numqualifier)),
2112 "%s%s" % (desc,
2108 "%s%s" % (desc,
2113 default
2109 default
2114 and _(" (default: %s)") % default
2110 and _(" (default: %s)") % default
2115 or "")))
2111 or "")))
2116 if multioccur:
2112 if multioccur:
2117 msg = _("\n[+] marked option can be specified multiple times")
2113 msg = _("\n[+] marked option can be specified multiple times")
2118 if ui.verbose and name != 'shortlist':
2114 if ui.verbose and name != 'shortlist':
2119 opt_output.append((msg, None))
2115 opt_output.append((msg, None))
2120 else:
2116 else:
2121 opt_output.insert(-1, (msg, None))
2117 opt_output.insert(-1, (msg, None))
2122
2118
2123 if not name:
2119 if not name:
2124 ui.write(_("\nadditional help topics:\n\n"))
2120 ui.write(_("\nadditional help topics:\n\n"))
2125 topics = []
2121 topics = []
2126 for names, header, doc in help.helptable:
2122 for names, header, doc in help.helptable:
2127 topics.append((sorted(names, key=len, reverse=True)[0], header))
2123 topics.append((sorted(names, key=len, reverse=True)[0], header))
2128 topics_len = max([len(s[0]) for s in topics])
2124 topics_len = max([len(s[0]) for s in topics])
2129 for t, desc in topics:
2125 for t, desc in topics:
2130 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2126 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2131
2127
2132 if opt_output:
2128 if opt_output:
2133 colwidth = encoding.colwidth
2129 colwidth = encoding.colwidth
2134 # normalize: (opt or message, desc or None, width of opt)
2130 # normalize: (opt or message, desc or None, width of opt)
2135 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2131 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2136 for opt, desc in opt_output]
2132 for opt, desc in opt_output]
2137 hanging = max([e[2] for e in entries])
2133 hanging = max([e[2] for e in entries])
2138 for opt, desc, width in entries:
2134 for opt, desc, width in entries:
2139 if desc:
2135 if desc:
2140 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2136 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2141 hangindent = ' ' * (hanging + 3)
2137 hangindent = ' ' * (hanging + 3)
2142 ui.write('%s\n' % (util.wrap(desc, textwidth,
2138 ui.write('%s\n' % (util.wrap(desc, textwidth,
2143 initindent=initindent,
2139 initindent=initindent,
2144 hangindent=hangindent)))
2140 hangindent=hangindent)))
2145 else:
2141 else:
2146 ui.write("%s\n" % opt)
2142 ui.write("%s\n" % opt)
2147
2143
2148 def identify(ui, repo, source=None,
2144 def identify(ui, repo, source=None,
2149 rev=None, num=None, id=None, branch=None, tags=None):
2145 rev=None, num=None, id=None, branch=None, tags=None):
2150 """identify the working copy or specified revision
2146 """identify the working copy or specified revision
2151
2147
2152 With no revision, print a summary of the current state of the
2148 With no revision, print a summary of the current state of the
2153 repository.
2149 repository.
2154
2150
2155 Specifying a path to a repository root or Mercurial bundle will
2151 Specifying a path to a repository root or Mercurial bundle will
2156 cause lookup to operate on that repository/bundle.
2152 cause lookup to operate on that repository/bundle.
2157
2153
2158 This summary identifies the repository state using one or two
2154 This summary identifies the repository state using one or two
2159 parent hash identifiers, followed by a "+" if there are
2155 parent hash identifiers, followed by a "+" if there are
2160 uncommitted changes in the working directory, a list of tags for
2156 uncommitted changes in the working directory, a list of tags for
2161 this revision and a branch name for non-default branches.
2157 this revision and a branch name for non-default branches.
2162
2158
2163 Returns 0 if successful.
2159 Returns 0 if successful.
2164 """
2160 """
2165
2161
2166 if not repo and not source:
2162 if not repo and not source:
2167 raise util.Abort(_("there is no Mercurial repository here "
2163 raise util.Abort(_("there is no Mercurial repository here "
2168 "(.hg not found)"))
2164 "(.hg not found)"))
2169
2165
2170 hexfunc = ui.debugflag and hex or short
2166 hexfunc = ui.debugflag and hex or short
2171 default = not (num or id or branch or tags)
2167 default = not (num or id or branch or tags)
2172 output = []
2168 output = []
2173
2169
2174 revs = []
2170 revs = []
2175 if source:
2171 if source:
2176 source, branches = hg.parseurl(ui.expandpath(source))
2172 source, branches = hg.parseurl(ui.expandpath(source))
2177 repo = hg.repository(ui, source)
2173 repo = hg.repository(ui, source)
2178 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2174 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2179
2175
2180 if not repo.local():
2176 if not repo.local():
2181 if not rev and revs:
2177 if not rev and revs:
2182 rev = revs[0]
2178 rev = revs[0]
2183 if not rev:
2179 if not rev:
2184 rev = "tip"
2180 rev = "tip"
2185 if num or branch or tags:
2181 if num or branch or tags:
2186 raise util.Abort(
2182 raise util.Abort(
2187 "can't query remote revision number, branch, or tags")
2183 "can't query remote revision number, branch, or tags")
2188 output = [hexfunc(repo.lookup(rev))]
2184 output = [hexfunc(repo.lookup(rev))]
2189 elif not rev:
2185 elif not rev:
2190 ctx = repo[None]
2186 ctx = repo[None]
2191 parents = ctx.parents()
2187 parents = ctx.parents()
2192 changed = False
2188 changed = False
2193 if default or id or num:
2189 if default or id or num:
2194 changed = util.any(repo.status())
2190 changed = util.any(repo.status())
2195 if default or id:
2191 if default or id:
2196 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2192 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2197 (changed) and "+" or "")]
2193 (changed) and "+" or "")]
2198 if num:
2194 if num:
2199 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2195 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2200 (changed) and "+" or ""))
2196 (changed) and "+" or ""))
2201 else:
2197 else:
2202 ctx = cmdutil.revsingle(repo, rev)
2198 ctx = cmdutil.revsingle(repo, rev)
2203 if default or id:
2199 if default or id:
2204 output = [hexfunc(ctx.node())]
2200 output = [hexfunc(ctx.node())]
2205 if num:
2201 if num:
2206 output.append(str(ctx.rev()))
2202 output.append(str(ctx.rev()))
2207
2203
2208 if repo.local() and default and not ui.quiet:
2204 if repo.local() and default and not ui.quiet:
2209 b = ctx.branch()
2205 b = ctx.branch()
2210 if b != 'default':
2206 if b != 'default':
2211 output.append("(%s)" % b)
2207 output.append("(%s)" % b)
2212
2208
2213 # multiple tags for a single parent separated by '/'
2209 # multiple tags for a single parent separated by '/'
2214 t = "/".join(ctx.tags())
2210 t = "/".join(ctx.tags())
2215 if t:
2211 if t:
2216 output.append(t)
2212 output.append(t)
2217
2213
2218 if branch:
2214 if branch:
2219 output.append(ctx.branch())
2215 output.append(ctx.branch())
2220
2216
2221 if tags:
2217 if tags:
2222 output.extend(ctx.tags())
2218 output.extend(ctx.tags())
2223
2219
2224 ui.write("%s\n" % ' '.join(output))
2220 ui.write("%s\n" % ' '.join(output))
2225
2221
2226 def import_(ui, repo, patch1, *patches, **opts):
2222 def import_(ui, repo, patch1, *patches, **opts):
2227 """import an ordered set of patches
2223 """import an ordered set of patches
2228
2224
2229 Import a list of patches and commit them individually (unless
2225 Import a list of patches and commit them individually (unless
2230 --no-commit is specified).
2226 --no-commit is specified).
2231
2227
2232 If there are outstanding changes in the working directory, import
2228 If there are outstanding changes in the working directory, import
2233 will abort unless given the -f/--force flag.
2229 will abort unless given the -f/--force flag.
2234
2230
2235 You can import a patch straight from a mail message. Even patches
2231 You can import a patch straight from a mail message. Even patches
2236 as attachments work (to use the body part, it must have type
2232 as attachments work (to use the body part, it must have type
2237 text/plain or text/x-patch). From and Subject headers of email
2233 text/plain or text/x-patch). From and Subject headers of email
2238 message are used as default committer and commit message. All
2234 message are used as default committer and commit message. All
2239 text/plain body parts before first diff are added to commit
2235 text/plain body parts before first diff are added to commit
2240 message.
2236 message.
2241
2237
2242 If the imported patch was generated by :hg:`export`, user and
2238 If the imported patch was generated by :hg:`export`, user and
2243 description from patch override values from message headers and
2239 description from patch override values from message headers and
2244 body. Values given on command line with -m/--message and -u/--user
2240 body. Values given on command line with -m/--message and -u/--user
2245 override these.
2241 override these.
2246
2242
2247 If --exact is specified, import will set the working directory to
2243 If --exact is specified, import will set the working directory to
2248 the parent of each patch before applying it, and will abort if the
2244 the parent of each patch before applying it, and will abort if the
2249 resulting changeset has a different ID than the one recorded in
2245 resulting changeset has a different ID than the one recorded in
2250 the patch. This may happen due to character set problems or other
2246 the patch. This may happen due to character set problems or other
2251 deficiencies in the text patch format.
2247 deficiencies in the text patch format.
2252
2248
2253 With -s/--similarity, hg will attempt to discover renames and
2249 With -s/--similarity, hg will attempt to discover renames and
2254 copies in the patch in the same way as 'addremove'.
2250 copies in the patch in the same way as 'addremove'.
2255
2251
2256 To read a patch from standard input, use "-" as the patch name. If
2252 To read a patch from standard input, use "-" as the patch name. If
2257 a URL is specified, the patch will be downloaded from it.
2253 a URL is specified, the patch will be downloaded from it.
2258 See :hg:`help dates` for a list of formats valid for -d/--date.
2254 See :hg:`help dates` for a list of formats valid for -d/--date.
2259
2255
2260 Returns 0 on success.
2256 Returns 0 on success.
2261 """
2257 """
2262 patches = (patch1,) + patches
2258 patches = (patch1,) + patches
2263
2259
2264 date = opts.get('date')
2260 date = opts.get('date')
2265 if date:
2261 if date:
2266 opts['date'] = util.parsedate(date)
2262 opts['date'] = util.parsedate(date)
2267
2263
2268 try:
2264 try:
2269 sim = float(opts.get('similarity') or 0)
2265 sim = float(opts.get('similarity') or 0)
2270 except ValueError:
2266 except ValueError:
2271 raise util.Abort(_('similarity must be a number'))
2267 raise util.Abort(_('similarity must be a number'))
2272 if sim < 0 or sim > 100:
2268 if sim < 0 or sim > 100:
2273 raise util.Abort(_('similarity must be between 0 and 100'))
2269 raise util.Abort(_('similarity must be between 0 and 100'))
2274
2270
2275 if opts.get('exact') or not opts.get('force'):
2271 if opts.get('exact') or not opts.get('force'):
2276 cmdutil.bail_if_changed(repo)
2272 cmdutil.bail_if_changed(repo)
2277
2273
2278 d = opts["base"]
2274 d = opts["base"]
2279 strip = opts["strip"]
2275 strip = opts["strip"]
2280 wlock = lock = None
2276 wlock = lock = None
2281 msgs = []
2277 msgs = []
2282
2278
2283 def tryone(ui, hunk):
2279 def tryone(ui, hunk):
2284 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2280 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2285 patch.extract(ui, hunk)
2281 patch.extract(ui, hunk)
2286
2282
2287 if not tmpname:
2283 if not tmpname:
2288 return None
2284 return None
2289 commitid = _('to working directory')
2285 commitid = _('to working directory')
2290
2286
2291 try:
2287 try:
2292 cmdline_message = cmdutil.logmessage(opts)
2288 cmdline_message = cmdutil.logmessage(opts)
2293 if cmdline_message:
2289 if cmdline_message:
2294 # pickup the cmdline msg
2290 # pickup the cmdline msg
2295 message = cmdline_message
2291 message = cmdline_message
2296 elif message:
2292 elif message:
2297 # pickup the patch msg
2293 # pickup the patch msg
2298 message = message.strip()
2294 message = message.strip()
2299 else:
2295 else:
2300 # launch the editor
2296 # launch the editor
2301 message = None
2297 message = None
2302 ui.debug('message:\n%s\n' % message)
2298 ui.debug('message:\n%s\n' % message)
2303
2299
2304 wp = repo.parents()
2300 wp = repo.parents()
2305 if opts.get('exact'):
2301 if opts.get('exact'):
2306 if not nodeid or not p1:
2302 if not nodeid or not p1:
2307 raise util.Abort(_('not a Mercurial patch'))
2303 raise util.Abort(_('not a Mercurial patch'))
2308 p1 = repo.lookup(p1)
2304 p1 = repo.lookup(p1)
2309 p2 = repo.lookup(p2 or hex(nullid))
2305 p2 = repo.lookup(p2 or hex(nullid))
2310
2306
2311 if p1 != wp[0].node():
2307 if p1 != wp[0].node():
2312 hg.clean(repo, p1)
2308 hg.clean(repo, p1)
2313 repo.dirstate.setparents(p1, p2)
2309 repo.dirstate.setparents(p1, p2)
2314 elif p2:
2310 elif p2:
2315 try:
2311 try:
2316 p1 = repo.lookup(p1)
2312 p1 = repo.lookup(p1)
2317 p2 = repo.lookup(p2)
2313 p2 = repo.lookup(p2)
2318 if p1 == wp[0].node():
2314 if p1 == wp[0].node():
2319 repo.dirstate.setparents(p1, p2)
2315 repo.dirstate.setparents(p1, p2)
2320 except error.RepoError:
2316 except error.RepoError:
2321 pass
2317 pass
2322 if opts.get('exact') or opts.get('import_branch'):
2318 if opts.get('exact') or opts.get('import_branch'):
2323 repo.dirstate.setbranch(branch or 'default')
2319 repo.dirstate.setbranch(branch or 'default')
2324
2320
2325 files = {}
2321 files = {}
2326 try:
2322 try:
2327 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2323 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2328 files=files, eolmode=None)
2324 files=files, eolmode=None)
2329 finally:
2325 finally:
2330 files = cmdutil.updatedir(ui, repo, files,
2326 files = cmdutil.updatedir(ui, repo, files,
2331 similarity=sim / 100.0)
2327 similarity=sim / 100.0)
2332 if opts.get('no_commit'):
2328 if opts.get('no_commit'):
2333 if message:
2329 if message:
2334 msgs.append(message)
2330 msgs.append(message)
2335 else:
2331 else:
2336 if opts.get('exact'):
2332 if opts.get('exact'):
2337 m = None
2333 m = None
2338 else:
2334 else:
2339 m = cmdutil.matchfiles(repo, files or [])
2335 m = cmdutil.matchfiles(repo, files or [])
2340 n = repo.commit(message, opts.get('user') or user,
2336 n = repo.commit(message, opts.get('user') or user,
2341 opts.get('date') or date, match=m,
2337 opts.get('date') or date, match=m,
2342 editor=cmdutil.commiteditor)
2338 editor=cmdutil.commiteditor)
2343 if opts.get('exact'):
2339 if opts.get('exact'):
2344 if hex(n) != nodeid:
2340 if hex(n) != nodeid:
2345 repo.rollback()
2341 repo.rollback()
2346 raise util.Abort(_('patch is damaged'
2342 raise util.Abort(_('patch is damaged'
2347 ' or loses information'))
2343 ' or loses information'))
2348 # Force a dirstate write so that the next transaction
2344 # Force a dirstate write so that the next transaction
2349 # backups an up-do-date file.
2345 # backups an up-do-date file.
2350 repo.dirstate.write()
2346 repo.dirstate.write()
2351 if n:
2347 if n:
2352 commitid = short(n)
2348 commitid = short(n)
2353
2349
2354 return commitid
2350 return commitid
2355 finally:
2351 finally:
2356 os.unlink(tmpname)
2352 os.unlink(tmpname)
2357
2353
2358 try:
2354 try:
2359 wlock = repo.wlock()
2355 wlock = repo.wlock()
2360 lock = repo.lock()
2356 lock = repo.lock()
2361 lastcommit = None
2357 lastcommit = None
2362 for p in patches:
2358 for p in patches:
2363 pf = os.path.join(d, p)
2359 pf = os.path.join(d, p)
2364
2360
2365 if pf == '-':
2361 if pf == '-':
2366 ui.status(_("applying patch from stdin\n"))
2362 ui.status(_("applying patch from stdin\n"))
2367 pf = sys.stdin
2363 pf = sys.stdin
2368 else:
2364 else:
2369 ui.status(_("applying %s\n") % p)
2365 ui.status(_("applying %s\n") % p)
2370 pf = url.open(ui, pf)
2366 pf = url.open(ui, pf)
2371
2367
2372 haspatch = False
2368 haspatch = False
2373 for hunk in patch.split(pf):
2369 for hunk in patch.split(pf):
2374 commitid = tryone(ui, hunk)
2370 commitid = tryone(ui, hunk)
2375 if commitid:
2371 if commitid:
2376 haspatch = True
2372 haspatch = True
2377 if lastcommit:
2373 if lastcommit:
2378 ui.status(_('applied %s\n') % lastcommit)
2374 ui.status(_('applied %s\n') % lastcommit)
2379 lastcommit = commitid
2375 lastcommit = commitid
2380
2376
2381 if not haspatch:
2377 if not haspatch:
2382 raise util.Abort(_('no diffs found'))
2378 raise util.Abort(_('no diffs found'))
2383
2379
2384 if msgs:
2380 if msgs:
2385 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2381 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2386 finally:
2382 finally:
2387 release(lock, wlock)
2383 release(lock, wlock)
2388
2384
2389 def incoming(ui, repo, source="default", **opts):
2385 def incoming(ui, repo, source="default", **opts):
2390 """show new changesets found in source
2386 """show new changesets found in source
2391
2387
2392 Show new changesets found in the specified path/URL or the default
2388 Show new changesets found in the specified path/URL or the default
2393 pull location. These are the changesets that would have been pulled
2389 pull location. These are the changesets that would have been pulled
2394 if a pull at the time you issued this command.
2390 if a pull at the time you issued this command.
2395
2391
2396 For remote repository, using --bundle avoids downloading the
2392 For remote repository, using --bundle avoids downloading the
2397 changesets twice if the incoming is followed by a pull.
2393 changesets twice if the incoming is followed by a pull.
2398
2394
2399 See pull for valid source format details.
2395 See pull for valid source format details.
2400
2396
2401 Returns 0 if there are incoming changes, 1 otherwise.
2397 Returns 0 if there are incoming changes, 1 otherwise.
2402 """
2398 """
2403 if opts.get('bundle') and opts.get('subrepos'):
2399 if opts.get('bundle') and opts.get('subrepos'):
2404 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2400 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2405
2401
2406 ret = hg.incoming(ui, repo, source, opts)
2402 ret = hg.incoming(ui, repo, source, opts)
2407 return ret
2403 return ret
2408
2404
2409 def init(ui, dest=".", **opts):
2405 def init(ui, dest=".", **opts):
2410 """create a new repository in the given directory
2406 """create a new repository in the given directory
2411
2407
2412 Initialize a new repository in the given directory. If the given
2408 Initialize a new repository in the given directory. If the given
2413 directory does not exist, it will be created.
2409 directory does not exist, it will be created.
2414
2410
2415 If no directory is given, the current directory is used.
2411 If no directory is given, the current directory is used.
2416
2412
2417 It is possible to specify an ``ssh://`` URL as the destination.
2413 It is possible to specify an ``ssh://`` URL as the destination.
2418 See :hg:`help urls` for more information.
2414 See :hg:`help urls` for more information.
2419
2415
2420 Returns 0 on success.
2416 Returns 0 on success.
2421 """
2417 """
2422 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2418 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2423
2419
2424 def locate(ui, repo, *pats, **opts):
2420 def locate(ui, repo, *pats, **opts):
2425 """locate files matching specific patterns
2421 """locate files matching specific patterns
2426
2422
2427 Print files under Mercurial control in the working directory whose
2423 Print files under Mercurial control in the working directory whose
2428 names match the given patterns.
2424 names match the given patterns.
2429
2425
2430 By default, this command searches all directories in the working
2426 By default, this command searches all directories in the working
2431 directory. To search just the current directory and its
2427 directory. To search just the current directory and its
2432 subdirectories, use "--include .".
2428 subdirectories, use "--include .".
2433
2429
2434 If no patterns are given to match, this command prints the names
2430 If no patterns are given to match, this command prints the names
2435 of all files under Mercurial control in the working directory.
2431 of all files under Mercurial control in the working directory.
2436
2432
2437 If you want to feed the output of this command into the "xargs"
2433 If you want to feed the output of this command into the "xargs"
2438 command, use the -0 option to both this command and "xargs". This
2434 command, use the -0 option to both this command and "xargs". This
2439 will avoid the problem of "xargs" treating single filenames that
2435 will avoid the problem of "xargs" treating single filenames that
2440 contain whitespace as multiple filenames.
2436 contain whitespace as multiple filenames.
2441
2437
2442 Returns 0 if a match is found, 1 otherwise.
2438 Returns 0 if a match is found, 1 otherwise.
2443 """
2439 """
2444 end = opts.get('print0') and '\0' or '\n'
2440 end = opts.get('print0') and '\0' or '\n'
2445 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2441 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2446
2442
2447 ret = 1
2443 ret = 1
2448 m = cmdutil.match(repo, pats, opts, default='relglob')
2444 m = cmdutil.match(repo, pats, opts, default='relglob')
2449 m.bad = lambda x, y: False
2445 m.bad = lambda x, y: False
2450 for abs in repo[rev].walk(m):
2446 for abs in repo[rev].walk(m):
2451 if not rev and abs not in repo.dirstate:
2447 if not rev and abs not in repo.dirstate:
2452 continue
2448 continue
2453 if opts.get('fullpath'):
2449 if opts.get('fullpath'):
2454 ui.write(repo.wjoin(abs), end)
2450 ui.write(repo.wjoin(abs), end)
2455 else:
2451 else:
2456 ui.write(((pats and m.rel(abs)) or abs), end)
2452 ui.write(((pats and m.rel(abs)) or abs), end)
2457 ret = 0
2453 ret = 0
2458
2454
2459 return ret
2455 return ret
2460
2456
2461 def log(ui, repo, *pats, **opts):
2457 def log(ui, repo, *pats, **opts):
2462 """show revision history of entire repository or files
2458 """show revision history of entire repository or files
2463
2459
2464 Print the revision history of the specified files or the entire
2460 Print the revision history of the specified files or the entire
2465 project.
2461 project.
2466
2462
2467 File history is shown without following rename or copy history of
2463 File history is shown without following rename or copy history of
2468 files. Use -f/--follow with a filename to follow history across
2464 files. Use -f/--follow with a filename to follow history across
2469 renames and copies. --follow without a filename will only show
2465 renames and copies. --follow without a filename will only show
2470 ancestors or descendants of the starting revision. --follow-first
2466 ancestors or descendants of the starting revision. --follow-first
2471 only follows the first parent of merge revisions.
2467 only follows the first parent of merge revisions.
2472
2468
2473 If no revision range is specified, the default is ``tip:0`` unless
2469 If no revision range is specified, the default is ``tip:0`` unless
2474 --follow is set, in which case the working directory parent is
2470 --follow is set, in which case the working directory parent is
2475 used as the starting revision. You can specify a revision set for
2471 used as the starting revision. You can specify a revision set for
2476 log, see :hg:`help revsets` for more information.
2472 log, see :hg:`help revsets` for more information.
2477
2473
2478 See :hg:`help dates` for a list of formats valid for -d/--date.
2474 See :hg:`help dates` for a list of formats valid for -d/--date.
2479
2475
2480 By default this command prints revision number and changeset id,
2476 By default this command prints revision number and changeset id,
2481 tags, non-trivial parents, user, date and time, and a summary for
2477 tags, non-trivial parents, user, date and time, and a summary for
2482 each commit. When the -v/--verbose switch is used, the list of
2478 each commit. When the -v/--verbose switch is used, the list of
2483 changed files and full commit message are shown.
2479 changed files and full commit message are shown.
2484
2480
2485 .. note::
2481 .. note::
2486 log -p/--patch may generate unexpected diff output for merge
2482 log -p/--patch may generate unexpected diff output for merge
2487 changesets, as it will only compare the merge changeset against
2483 changesets, as it will only compare the merge changeset against
2488 its first parent. Also, only files different from BOTH parents
2484 its first parent. Also, only files different from BOTH parents
2489 will appear in files:.
2485 will appear in files:.
2490
2486
2491 Returns 0 on success.
2487 Returns 0 on success.
2492 """
2488 """
2493
2489
2494 matchfn = cmdutil.match(repo, pats, opts)
2490 matchfn = cmdutil.match(repo, pats, opts)
2495 limit = cmdutil.loglimit(opts)
2491 limit = cmdutil.loglimit(opts)
2496 count = 0
2492 count = 0
2497
2493
2498 endrev = None
2494 endrev = None
2499 if opts.get('copies') and opts.get('rev'):
2495 if opts.get('copies') and opts.get('rev'):
2500 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2496 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2501
2497
2502 df = False
2498 df = False
2503 if opts["date"]:
2499 if opts["date"]:
2504 df = util.matchdate(opts["date"])
2500 df = util.matchdate(opts["date"])
2505
2501
2506 branches = opts.get('branch', []) + opts.get('only_branch', [])
2502 branches = opts.get('branch', []) + opts.get('only_branch', [])
2507 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2503 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2508
2504
2509 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2505 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2510 def prep(ctx, fns):
2506 def prep(ctx, fns):
2511 rev = ctx.rev()
2507 rev = ctx.rev()
2512 parents = [p for p in repo.changelog.parentrevs(rev)
2508 parents = [p for p in repo.changelog.parentrevs(rev)
2513 if p != nullrev]
2509 if p != nullrev]
2514 if opts.get('no_merges') and len(parents) == 2:
2510 if opts.get('no_merges') and len(parents) == 2:
2515 return
2511 return
2516 if opts.get('only_merges') and len(parents) != 2:
2512 if opts.get('only_merges') and len(parents) != 2:
2517 return
2513 return
2518 if opts.get('branch') and ctx.branch() not in opts['branch']:
2514 if opts.get('branch') and ctx.branch() not in opts['branch']:
2519 return
2515 return
2520 if df and not df(ctx.date()[0]):
2516 if df and not df(ctx.date()[0]):
2521 return
2517 return
2522 if opts['user'] and not [k for k in opts['user']
2518 if opts['user'] and not [k for k in opts['user']
2523 if k.lower() in ctx.user().lower()]:
2519 if k.lower() in ctx.user().lower()]:
2524 return
2520 return
2525 if opts.get('keyword'):
2521 if opts.get('keyword'):
2526 for k in [kw.lower() for kw in opts['keyword']]:
2522 for k in [kw.lower() for kw in opts['keyword']]:
2527 if (k in ctx.user().lower() or
2523 if (k in ctx.user().lower() or
2528 k in ctx.description().lower() or
2524 k in ctx.description().lower() or
2529 k in " ".join(ctx.files()).lower()):
2525 k in " ".join(ctx.files()).lower()):
2530 break
2526 break
2531 else:
2527 else:
2532 return
2528 return
2533
2529
2534 copies = None
2530 copies = None
2535 if opts.get('copies') and rev:
2531 if opts.get('copies') and rev:
2536 copies = []
2532 copies = []
2537 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2533 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2538 for fn in ctx.files():
2534 for fn in ctx.files():
2539 rename = getrenamed(fn, rev)
2535 rename = getrenamed(fn, rev)
2540 if rename:
2536 if rename:
2541 copies.append((fn, rename[0]))
2537 copies.append((fn, rename[0]))
2542
2538
2543 revmatchfn = None
2539 revmatchfn = None
2544 if opts.get('patch') or opts.get('stat'):
2540 if opts.get('patch') or opts.get('stat'):
2545 if opts.get('follow') or opts.get('follow_first'):
2541 if opts.get('follow') or opts.get('follow_first'):
2546 # note: this might be wrong when following through merges
2542 # note: this might be wrong when following through merges
2547 revmatchfn = cmdutil.match(repo, fns, default='path')
2543 revmatchfn = cmdutil.match(repo, fns, default='path')
2548 else:
2544 else:
2549 revmatchfn = matchfn
2545 revmatchfn = matchfn
2550
2546
2551 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2547 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2552
2548
2553 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2549 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2554 if count == limit:
2550 if count == limit:
2555 break
2551 break
2556 if displayer.flush(ctx.rev()):
2552 if displayer.flush(ctx.rev()):
2557 count += 1
2553 count += 1
2558 displayer.close()
2554 displayer.close()
2559
2555
2560 def manifest(ui, repo, node=None, rev=None):
2556 def manifest(ui, repo, node=None, rev=None):
2561 """output the current or given revision of the project manifest
2557 """output the current or given revision of the project manifest
2562
2558
2563 Print a list of version controlled files for the given revision.
2559 Print a list of version controlled files for the given revision.
2564 If no revision is given, the first parent of the working directory
2560 If no revision is given, the first parent of the working directory
2565 is used, or the null revision if no revision is checked out.
2561 is used, or the null revision if no revision is checked out.
2566
2562
2567 With -v, print file permissions, symlink and executable bits.
2563 With -v, print file permissions, symlink and executable bits.
2568 With --debug, print file revision hashes.
2564 With --debug, print file revision hashes.
2569
2565
2570 Returns 0 on success.
2566 Returns 0 on success.
2571 """
2567 """
2572
2568
2573 if rev and node:
2569 if rev and node:
2574 raise util.Abort(_("please specify just one revision"))
2570 raise util.Abort(_("please specify just one revision"))
2575
2571
2576 if not node:
2572 if not node:
2577 node = rev
2573 node = rev
2578
2574
2579 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2575 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2580 ctx = cmdutil.revsingle(repo, node)
2576 ctx = cmdutil.revsingle(repo, node)
2581 for f in ctx:
2577 for f in ctx:
2582 if ui.debugflag:
2578 if ui.debugflag:
2583 ui.write("%40s " % hex(ctx.manifest()[f]))
2579 ui.write("%40s " % hex(ctx.manifest()[f]))
2584 if ui.verbose:
2580 if ui.verbose:
2585 ui.write(decor[ctx.flags(f)])
2581 ui.write(decor[ctx.flags(f)])
2586 ui.write("%s\n" % f)
2582 ui.write("%s\n" % f)
2587
2583
2588 def merge(ui, repo, node=None, **opts):
2584 def merge(ui, repo, node=None, **opts):
2589 """merge working directory with another revision
2585 """merge working directory with another revision
2590
2586
2591 The current working directory is updated with all changes made in
2587 The current working directory is updated with all changes made in
2592 the requested revision since the last common predecessor revision.
2588 the requested revision since the last common predecessor revision.
2593
2589
2594 Files that changed between either parent are marked as changed for
2590 Files that changed between either parent are marked as changed for
2595 the next commit and a commit must be performed before any further
2591 the next commit and a commit must be performed before any further
2596 updates to the repository are allowed. The next commit will have
2592 updates to the repository are allowed. The next commit will have
2597 two parents.
2593 two parents.
2598
2594
2599 ``--tool`` can be used to specify the merge tool used for file
2595 ``--tool`` can be used to specify the merge tool used for file
2600 merges. It overrides the HGMERGE environment variable and your
2596 merges. It overrides the HGMERGE environment variable and your
2601 configuration files.
2597 configuration files.
2602
2598
2603 If no revision is specified, the working directory's parent is a
2599 If no revision is specified, the working directory's parent is a
2604 head revision, and the current branch contains exactly one other
2600 head revision, and the current branch contains exactly one other
2605 head, the other head is merged with by default. Otherwise, an
2601 head, the other head is merged with by default. Otherwise, an
2606 explicit revision with which to merge with must be provided.
2602 explicit revision with which to merge with must be provided.
2607
2603
2608 :hg:`resolve` must be used to resolve unresolved files.
2604 :hg:`resolve` must be used to resolve unresolved files.
2609
2605
2610 To undo an uncommitted merge, use :hg:`update --clean .` which
2606 To undo an uncommitted merge, use :hg:`update --clean .` which
2611 will check out a clean copy of the original merge parent, losing
2607 will check out a clean copy of the original merge parent, losing
2612 all changes.
2608 all changes.
2613
2609
2614 Returns 0 on success, 1 if there are unresolved files.
2610 Returns 0 on success, 1 if there are unresolved files.
2615 """
2611 """
2616
2612
2617 if opts.get('rev') and node:
2613 if opts.get('rev') and node:
2618 raise util.Abort(_("please specify just one revision"))
2614 raise util.Abort(_("please specify just one revision"))
2619 if not node:
2615 if not node:
2620 node = opts.get('rev')
2616 node = opts.get('rev')
2621
2617
2622 if not node:
2618 if not node:
2623 branch = repo[None].branch()
2619 branch = repo[None].branch()
2624 bheads = repo.branchheads(branch)
2620 bheads = repo.branchheads(branch)
2625 if len(bheads) > 2:
2621 if len(bheads) > 2:
2626 raise util.Abort(_(
2622 raise util.Abort(_(
2627 'branch \'%s\' has %d heads - '
2623 'branch \'%s\' has %d heads - '
2628 'please merge with an explicit rev\n'
2624 'please merge with an explicit rev\n'
2629 '(run \'hg heads .\' to see heads)')
2625 '(run \'hg heads .\' to see heads)')
2630 % (branch, len(bheads)))
2626 % (branch, len(bheads)))
2631
2627
2632 parent = repo.dirstate.parents()[0]
2628 parent = repo.dirstate.parents()[0]
2633 if len(bheads) == 1:
2629 if len(bheads) == 1:
2634 if len(repo.heads()) > 1:
2630 if len(repo.heads()) > 1:
2635 raise util.Abort(_(
2631 raise util.Abort(_(
2636 'branch \'%s\' has one head - '
2632 'branch \'%s\' has one head - '
2637 'please merge with an explicit rev\n'
2633 'please merge with an explicit rev\n'
2638 '(run \'hg heads\' to see all heads)')
2634 '(run \'hg heads\' to see all heads)')
2639 % branch)
2635 % branch)
2640 msg = _('there is nothing to merge')
2636 msg = _('there is nothing to merge')
2641 if parent != repo.lookup(repo[None].branch()):
2637 if parent != repo.lookup(repo[None].branch()):
2642 msg = _('%s - use "hg update" instead') % msg
2638 msg = _('%s - use "hg update" instead') % msg
2643 raise util.Abort(msg)
2639 raise util.Abort(msg)
2644
2640
2645 if parent not in bheads:
2641 if parent not in bheads:
2646 raise util.Abort(_('working dir not at a head rev - '
2642 raise util.Abort(_('working dir not at a head rev - '
2647 'use "hg update" or merge with an explicit rev'))
2643 'use "hg update" or merge with an explicit rev'))
2648 node = parent == bheads[0] and bheads[-1] or bheads[0]
2644 node = parent == bheads[0] and bheads[-1] or bheads[0]
2649 else:
2645 else:
2650 node = cmdutil.revsingle(repo, node).node()
2646 node = cmdutil.revsingle(repo, node).node()
2651
2647
2652 if opts.get('preview'):
2648 if opts.get('preview'):
2653 # find nodes that are ancestors of p2 but not of p1
2649 # find nodes that are ancestors of p2 but not of p1
2654 p1 = repo.lookup('.')
2650 p1 = repo.lookup('.')
2655 p2 = repo.lookup(node)
2651 p2 = repo.lookup(node)
2656 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2652 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2657
2653
2658 displayer = cmdutil.show_changeset(ui, repo, opts)
2654 displayer = cmdutil.show_changeset(ui, repo, opts)
2659 for node in nodes:
2655 for node in nodes:
2660 displayer.show(repo[node])
2656 displayer.show(repo[node])
2661 displayer.close()
2657 displayer.close()
2662 return 0
2658 return 0
2663
2659
2664 try:
2660 try:
2665 # ui.forcemerge is an internal variable, do not document
2661 # ui.forcemerge is an internal variable, do not document
2666 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2662 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2667 return hg.merge(repo, node, force=opts.get('force'))
2663 return hg.merge(repo, node, force=opts.get('force'))
2668 finally:
2664 finally:
2669 ui.setconfig('ui', 'forcemerge', '')
2665 ui.setconfig('ui', 'forcemerge', '')
2670
2666
2671 def outgoing(ui, repo, dest=None, **opts):
2667 def outgoing(ui, repo, dest=None, **opts):
2672 """show changesets not found in the destination
2668 """show changesets not found in the destination
2673
2669
2674 Show changesets not found in the specified destination repository
2670 Show changesets not found in the specified destination repository
2675 or the default push location. These are the changesets that would
2671 or the default push location. These are the changesets that would
2676 be pushed if a push was requested.
2672 be pushed if a push was requested.
2677
2673
2678 See pull for details of valid destination formats.
2674 See pull for details of valid destination formats.
2679
2675
2680 Returns 0 if there are outgoing changes, 1 otherwise.
2676 Returns 0 if there are outgoing changes, 1 otherwise.
2681 """
2677 """
2682 ret = hg.outgoing(ui, repo, dest, opts)
2678 ret = hg.outgoing(ui, repo, dest, opts)
2683 return ret
2679 return ret
2684
2680
2685 def parents(ui, repo, file_=None, **opts):
2681 def parents(ui, repo, file_=None, **opts):
2686 """show the parents of the working directory or revision
2682 """show the parents of the working directory or revision
2687
2683
2688 Print the working directory's parent revisions. If a revision is
2684 Print the working directory's parent revisions. If a revision is
2689 given via -r/--rev, the parent of that revision will be printed.
2685 given via -r/--rev, the parent of that revision will be printed.
2690 If a file argument is given, the revision in which the file was
2686 If a file argument is given, the revision in which the file was
2691 last changed (before the working directory revision or the
2687 last changed (before the working directory revision or the
2692 argument to --rev if given) is printed.
2688 argument to --rev if given) is printed.
2693
2689
2694 Returns 0 on success.
2690 Returns 0 on success.
2695 """
2691 """
2696
2692
2697 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2693 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2698
2694
2699 if file_:
2695 if file_:
2700 m = cmdutil.match(repo, (file_,), opts)
2696 m = cmdutil.match(repo, (file_,), opts)
2701 if m.anypats() or len(m.files()) != 1:
2697 if m.anypats() or len(m.files()) != 1:
2702 raise util.Abort(_('can only specify an explicit filename'))
2698 raise util.Abort(_('can only specify an explicit filename'))
2703 file_ = m.files()[0]
2699 file_ = m.files()[0]
2704 filenodes = []
2700 filenodes = []
2705 for cp in ctx.parents():
2701 for cp in ctx.parents():
2706 if not cp:
2702 if not cp:
2707 continue
2703 continue
2708 try:
2704 try:
2709 filenodes.append(cp.filenode(file_))
2705 filenodes.append(cp.filenode(file_))
2710 except error.LookupError:
2706 except error.LookupError:
2711 pass
2707 pass
2712 if not filenodes:
2708 if not filenodes:
2713 raise util.Abort(_("'%s' not found in manifest!") % file_)
2709 raise util.Abort(_("'%s' not found in manifest!") % file_)
2714 fl = repo.file(file_)
2710 fl = repo.file(file_)
2715 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2711 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2716 else:
2712 else:
2717 p = [cp.node() for cp in ctx.parents()]
2713 p = [cp.node() for cp in ctx.parents()]
2718
2714
2719 displayer = cmdutil.show_changeset(ui, repo, opts)
2715 displayer = cmdutil.show_changeset(ui, repo, opts)
2720 for n in p:
2716 for n in p:
2721 if n != nullid:
2717 if n != nullid:
2722 displayer.show(repo[n])
2718 displayer.show(repo[n])
2723 displayer.close()
2719 displayer.close()
2724
2720
2725 def paths(ui, repo, search=None):
2721 def paths(ui, repo, search=None):
2726 """show aliases for remote repositories
2722 """show aliases for remote repositories
2727
2723
2728 Show definition of symbolic path name NAME. If no name is given,
2724 Show definition of symbolic path name NAME. If no name is given,
2729 show definition of all available names.
2725 show definition of all available names.
2730
2726
2731 Path names are defined in the [paths] section of your
2727 Path names are defined in the [paths] section of your
2732 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2728 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2733 repository, ``.hg/hgrc`` is used, too.
2729 repository, ``.hg/hgrc`` is used, too.
2734
2730
2735 The path names ``default`` and ``default-push`` have a special
2731 The path names ``default`` and ``default-push`` have a special
2736 meaning. When performing a push or pull operation, they are used
2732 meaning. When performing a push or pull operation, they are used
2737 as fallbacks if no location is specified on the command-line.
2733 as fallbacks if no location is specified on the command-line.
2738 When ``default-push`` is set, it will be used for push and
2734 When ``default-push`` is set, it will be used for push and
2739 ``default`` will be used for pull; otherwise ``default`` is used
2735 ``default`` will be used for pull; otherwise ``default`` is used
2740 as the fallback for both. When cloning a repository, the clone
2736 as the fallback for both. When cloning a repository, the clone
2741 source is written as ``default`` in ``.hg/hgrc``. Note that
2737 source is written as ``default`` in ``.hg/hgrc``. Note that
2742 ``default`` and ``default-push`` apply to all inbound (e.g.
2738 ``default`` and ``default-push`` apply to all inbound (e.g.
2743 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2739 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2744 :hg:`bundle`) operations.
2740 :hg:`bundle`) operations.
2745
2741
2746 See :hg:`help urls` for more information.
2742 See :hg:`help urls` for more information.
2747
2743
2748 Returns 0 on success.
2744 Returns 0 on success.
2749 """
2745 """
2750 if search:
2746 if search:
2751 for name, path in ui.configitems("paths"):
2747 for name, path in ui.configitems("paths"):
2752 if name == search:
2748 if name == search:
2753 ui.write("%s\n" % url.hidepassword(path))
2749 ui.write("%s\n" % url.hidepassword(path))
2754 return
2750 return
2755 ui.warn(_("not found!\n"))
2751 ui.warn(_("not found!\n"))
2756 return 1
2752 return 1
2757 else:
2753 else:
2758 for name, path in ui.configitems("paths"):
2754 for name, path in ui.configitems("paths"):
2759 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2755 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2760
2756
2761 def postincoming(ui, repo, modheads, optupdate, checkout):
2757 def postincoming(ui, repo, modheads, optupdate, checkout):
2762 if modheads == 0:
2758 if modheads == 0:
2763 return
2759 return
2764 if optupdate:
2760 if optupdate:
2765 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2761 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2766 return hg.update(repo, checkout)
2762 return hg.update(repo, checkout)
2767 else:
2763 else:
2768 ui.status(_("not updating, since new heads added\n"))
2764 ui.status(_("not updating, since new heads added\n"))
2769 if modheads > 1:
2765 if modheads > 1:
2770 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2766 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2771 else:
2767 else:
2772 ui.status(_("(run 'hg update' to get a working copy)\n"))
2768 ui.status(_("(run 'hg update' to get a working copy)\n"))
2773
2769
2774 def pull(ui, repo, source="default", **opts):
2770 def pull(ui, repo, source="default", **opts):
2775 """pull changes from the specified source
2771 """pull changes from the specified source
2776
2772
2777 Pull changes from a remote repository to a local one.
2773 Pull changes from a remote repository to a local one.
2778
2774
2779 This finds all changes from the repository at the specified path
2775 This finds all changes from the repository at the specified path
2780 or URL and adds them to a local repository (the current one unless
2776 or URL and adds them to a local repository (the current one unless
2781 -R is specified). By default, this does not update the copy of the
2777 -R is specified). By default, this does not update the copy of the
2782 project in the working directory.
2778 project in the working directory.
2783
2779
2784 Use :hg:`incoming` if you want to see what would have been added
2780 Use :hg:`incoming` if you want to see what would have been added
2785 by a pull at the time you issued this command. If you then decide
2781 by a pull at the time you issued this command. If you then decide
2786 to add those changes to the repository, you should use :hg:`pull
2782 to add those changes to the repository, you should use :hg:`pull
2787 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2783 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2788
2784
2789 If SOURCE is omitted, the 'default' path will be used.
2785 If SOURCE is omitted, the 'default' path will be used.
2790 See :hg:`help urls` for more information.
2786 See :hg:`help urls` for more information.
2791
2787
2792 Returns 0 on success, 1 if an update had unresolved files.
2788 Returns 0 on success, 1 if an update had unresolved files.
2793 """
2789 """
2794 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2790 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2795 other = hg.repository(hg.remoteui(repo, opts), source)
2791 other = hg.repository(hg.remoteui(repo, opts), source)
2796 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2792 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2797 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2793 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2798 if revs:
2794 if revs:
2799 try:
2795 try:
2800 revs = [other.lookup(rev) for rev in revs]
2796 revs = [other.lookup(rev) for rev in revs]
2801 except error.CapabilityError:
2797 except error.CapabilityError:
2802 err = _("other repository doesn't support revision lookup, "
2798 err = _("other repository doesn't support revision lookup, "
2803 "so a rev cannot be specified.")
2799 "so a rev cannot be specified.")
2804 raise util.Abort(err)
2800 raise util.Abort(err)
2805
2801
2806 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2802 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2807 if checkout:
2803 if checkout:
2808 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2804 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2809 repo._subtoppath = source
2805 repo._subtoppath = source
2810 try:
2806 try:
2811 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2807 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2812 finally:
2808 finally:
2813 del repo._subtoppath
2809 del repo._subtoppath
2814
2810
2815 def push(ui, repo, dest=None, **opts):
2811 def push(ui, repo, dest=None, **opts):
2816 """push changes to the specified destination
2812 """push changes to the specified destination
2817
2813
2818 Push changesets from the local repository to the specified
2814 Push changesets from the local repository to the specified
2819 destination.
2815 destination.
2820
2816
2821 This operation is symmetrical to pull: it is identical to a pull
2817 This operation is symmetrical to pull: it is identical to a pull
2822 in the destination repository from the current one.
2818 in the destination repository from the current one.
2823
2819
2824 By default, push will not allow creation of new heads at the
2820 By default, push will not allow creation of new heads at the
2825 destination, since multiple heads would make it unclear which head
2821 destination, since multiple heads would make it unclear which head
2826 to use. In this situation, it is recommended to pull and merge
2822 to use. In this situation, it is recommended to pull and merge
2827 before pushing.
2823 before pushing.
2828
2824
2829 Use --new-branch if you want to allow push to create a new named
2825 Use --new-branch if you want to allow push to create a new named
2830 branch that is not present at the destination. This allows you to
2826 branch that is not present at the destination. This allows you to
2831 only create a new branch without forcing other changes.
2827 only create a new branch without forcing other changes.
2832
2828
2833 Use -f/--force to override the default behavior and push all
2829 Use -f/--force to override the default behavior and push all
2834 changesets on all branches.
2830 changesets on all branches.
2835
2831
2836 If -r/--rev is used, the specified revision and all its ancestors
2832 If -r/--rev is used, the specified revision and all its ancestors
2837 will be pushed to the remote repository.
2833 will be pushed to the remote repository.
2838
2834
2839 Please see :hg:`help urls` for important details about ``ssh://``
2835 Please see :hg:`help urls` for important details about ``ssh://``
2840 URLs. If DESTINATION is omitted, a default path will be used.
2836 URLs. If DESTINATION is omitted, a default path will be used.
2841
2837
2842 Returns 0 if push was successful, 1 if nothing to push.
2838 Returns 0 if push was successful, 1 if nothing to push.
2843 """
2839 """
2844 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2840 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2845 dest, branches = hg.parseurl(dest, opts.get('branch'))
2841 dest, branches = hg.parseurl(dest, opts.get('branch'))
2846 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2842 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2847 other = hg.repository(hg.remoteui(repo, opts), dest)
2843 other = hg.repository(hg.remoteui(repo, opts), dest)
2848 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2844 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2849 if revs:
2845 if revs:
2850 revs = [repo.lookup(rev) for rev in revs]
2846 revs = [repo.lookup(rev) for rev in revs]
2851
2847
2852 repo._subtoppath = dest
2848 repo._subtoppath = dest
2853 try:
2849 try:
2854 # push subrepos depth-first for coherent ordering
2850 # push subrepos depth-first for coherent ordering
2855 c = repo['']
2851 c = repo['']
2856 subs = c.substate # only repos that are committed
2852 subs = c.substate # only repos that are committed
2857 for s in sorted(subs):
2853 for s in sorted(subs):
2858 if not c.sub(s).push(opts.get('force')):
2854 if not c.sub(s).push(opts.get('force')):
2859 return False
2855 return False
2860 finally:
2856 finally:
2861 del repo._subtoppath
2857 del repo._subtoppath
2862 r = repo.push(other, opts.get('force'), revs=revs,
2858 r = repo.push(other, opts.get('force'), revs=revs,
2863 newbranch=opts.get('new_branch'))
2859 newbranch=opts.get('new_branch'))
2864 return r == 0
2860 return r == 0
2865
2861
2866 def recover(ui, repo):
2862 def recover(ui, repo):
2867 """roll back an interrupted transaction
2863 """roll back an interrupted transaction
2868
2864
2869 Recover from an interrupted commit or pull.
2865 Recover from an interrupted commit or pull.
2870
2866
2871 This command tries to fix the repository status after an
2867 This command tries to fix the repository status after an
2872 interrupted operation. It should only be necessary when Mercurial
2868 interrupted operation. It should only be necessary when Mercurial
2873 suggests it.
2869 suggests it.
2874
2870
2875 Returns 0 if successful, 1 if nothing to recover or verify fails.
2871 Returns 0 if successful, 1 if nothing to recover or verify fails.
2876 """
2872 """
2877 if repo.recover():
2873 if repo.recover():
2878 return hg.verify(repo)
2874 return hg.verify(repo)
2879 return 1
2875 return 1
2880
2876
2881 def remove(ui, repo, *pats, **opts):
2877 def remove(ui, repo, *pats, **opts):
2882 """remove the specified files on the next commit
2878 """remove the specified files on the next commit
2883
2879
2884 Schedule the indicated files for removal from the repository.
2880 Schedule the indicated files for removal from the repository.
2885
2881
2886 This only removes files from the current branch, not from the
2882 This only removes files from the current branch, not from the
2887 entire project history. -A/--after can be used to remove only
2883 entire project history. -A/--after can be used to remove only
2888 files that have already been deleted, -f/--force can be used to
2884 files that have already been deleted, -f/--force can be used to
2889 force deletion, and -Af can be used to remove files from the next
2885 force deletion, and -Af can be used to remove files from the next
2890 revision without deleting them from the working directory.
2886 revision without deleting them from the working directory.
2891
2887
2892 The following table details the behavior of remove for different
2888 The following table details the behavior of remove for different
2893 file states (columns) and option combinations (rows). The file
2889 file states (columns) and option combinations (rows). The file
2894 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2890 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2895 reported by :hg:`status`). The actions are Warn, Remove (from
2891 reported by :hg:`status`). The actions are Warn, Remove (from
2896 branch) and Delete (from disk)::
2892 branch) and Delete (from disk)::
2897
2893
2898 A C M !
2894 A C M !
2899 none W RD W R
2895 none W RD W R
2900 -f R RD RD R
2896 -f R RD RD R
2901 -A W W W R
2897 -A W W W R
2902 -Af R R R R
2898 -Af R R R R
2903
2899
2904 This command schedules the files to be removed at the next commit.
2900 This command schedules the files to be removed at the next commit.
2905 To undo a remove before that, see :hg:`revert`.
2901 To undo a remove before that, see :hg:`revert`.
2906
2902
2907 Returns 0 on success, 1 if any warnings encountered.
2903 Returns 0 on success, 1 if any warnings encountered.
2908 """
2904 """
2909
2905
2910 ret = 0
2906 ret = 0
2911 after, force = opts.get('after'), opts.get('force')
2907 after, force = opts.get('after'), opts.get('force')
2912 if not pats and not after:
2908 if not pats and not after:
2913 raise util.Abort(_('no files specified'))
2909 raise util.Abort(_('no files specified'))
2914
2910
2915 m = cmdutil.match(repo, pats, opts)
2911 m = cmdutil.match(repo, pats, opts)
2916 s = repo.status(match=m, clean=True)
2912 s = repo.status(match=m, clean=True)
2917 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2913 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2918
2914
2919 for f in m.files():
2915 for f in m.files():
2920 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2916 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2921 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2917 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2922 ret = 1
2918 ret = 1
2923
2919
2924 if force:
2920 if force:
2925 remove, forget = modified + deleted + clean, added
2921 remove, forget = modified + deleted + clean, added
2926 elif after:
2922 elif after:
2927 remove, forget = deleted, []
2923 remove, forget = deleted, []
2928 for f in modified + added + clean:
2924 for f in modified + added + clean:
2929 ui.warn(_('not removing %s: file still exists (use -f'
2925 ui.warn(_('not removing %s: file still exists (use -f'
2930 ' to force removal)\n') % m.rel(f))
2926 ' to force removal)\n') % m.rel(f))
2931 ret = 1
2927 ret = 1
2932 else:
2928 else:
2933 remove, forget = deleted + clean, []
2929 remove, forget = deleted + clean, []
2934 for f in modified:
2930 for f in modified:
2935 ui.warn(_('not removing %s: file is modified (use -f'
2931 ui.warn(_('not removing %s: file is modified (use -f'
2936 ' to force removal)\n') % m.rel(f))
2932 ' to force removal)\n') % m.rel(f))
2937 ret = 1
2933 ret = 1
2938 for f in added:
2934 for f in added:
2939 ui.warn(_('not removing %s: file has been marked for add (use -f'
2935 ui.warn(_('not removing %s: file has been marked for add (use -f'
2940 ' to force removal)\n') % m.rel(f))
2936 ' to force removal)\n') % m.rel(f))
2941 ret = 1
2937 ret = 1
2942
2938
2943 for f in sorted(remove + forget):
2939 for f in sorted(remove + forget):
2944 if ui.verbose or not m.exact(f):
2940 if ui.verbose or not m.exact(f):
2945 ui.status(_('removing %s\n') % m.rel(f))
2941 ui.status(_('removing %s\n') % m.rel(f))
2946
2942
2947 repo[None].forget(forget)
2943 repo[None].forget(forget)
2948 repo[None].remove(remove, unlink=not after)
2944 repo[None].remove(remove, unlink=not after)
2949 return ret
2945 return ret
2950
2946
2951 def rename(ui, repo, *pats, **opts):
2947 def rename(ui, repo, *pats, **opts):
2952 """rename files; equivalent of copy + remove
2948 """rename files; equivalent of copy + remove
2953
2949
2954 Mark dest as copies of sources; mark sources for deletion. If dest
2950 Mark dest as copies of sources; mark sources for deletion. If dest
2955 is a directory, copies are put in that directory. If dest is a
2951 is a directory, copies are put in that directory. If dest is a
2956 file, there can only be one source.
2952 file, there can only be one source.
2957
2953
2958 By default, this command copies the contents of files as they
2954 By default, this command copies the contents of files as they
2959 exist in the working directory. If invoked with -A/--after, the
2955 exist in the working directory. If invoked with -A/--after, the
2960 operation is recorded, but no copying is performed.
2956 operation is recorded, but no copying is performed.
2961
2957
2962 This command takes effect at the next commit. To undo a rename
2958 This command takes effect at the next commit. To undo a rename
2963 before that, see :hg:`revert`.
2959 before that, see :hg:`revert`.
2964
2960
2965 Returns 0 on success, 1 if errors are encountered.
2961 Returns 0 on success, 1 if errors are encountered.
2966 """
2962 """
2967 wlock = repo.wlock(False)
2963 wlock = repo.wlock(False)
2968 try:
2964 try:
2969 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2965 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2970 finally:
2966 finally:
2971 wlock.release()
2967 wlock.release()
2972
2968
2973 def resolve(ui, repo, *pats, **opts):
2969 def resolve(ui, repo, *pats, **opts):
2974 """redo merges or set/view the merge status of files
2970 """redo merges or set/view the merge status of files
2975
2971
2976 Merges with unresolved conflicts are often the result of
2972 Merges with unresolved conflicts are often the result of
2977 non-interactive merging using the ``internal:merge`` configuration
2973 non-interactive merging using the ``internal:merge`` configuration
2978 setting, or a command-line merge tool like ``diff3``. The resolve
2974 setting, or a command-line merge tool like ``diff3``. The resolve
2979 command is used to manage the files involved in a merge, after
2975 command is used to manage the files involved in a merge, after
2980 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2976 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2981 working directory must have two parents).
2977 working directory must have two parents).
2982
2978
2983 The resolve command can be used in the following ways:
2979 The resolve command can be used in the following ways:
2984
2980
2985 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2981 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2986 files, discarding any previous merge attempts. Re-merging is not
2982 files, discarding any previous merge attempts. Re-merging is not
2987 performed for files already marked as resolved. Use ``--all/-a``
2983 performed for files already marked as resolved. Use ``--all/-a``
2988 to selects all unresolved files. ``--tool`` can be used to specify
2984 to selects all unresolved files. ``--tool`` can be used to specify
2989 the merge tool used for the given files. It overrides the HGMERGE
2985 the merge tool used for the given files. It overrides the HGMERGE
2990 environment variable and your configuration files.
2986 environment variable and your configuration files.
2991
2987
2992 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2988 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2993 (e.g. after having manually fixed-up the files). The default is
2989 (e.g. after having manually fixed-up the files). The default is
2994 to mark all unresolved files.
2990 to mark all unresolved files.
2995
2991
2996 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2992 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2997 default is to mark all resolved files.
2993 default is to mark all resolved files.
2998
2994
2999 - :hg:`resolve -l`: list files which had or still have conflicts.
2995 - :hg:`resolve -l`: list files which had or still have conflicts.
3000 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2996 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3001
2997
3002 Note that Mercurial will not let you commit files with unresolved
2998 Note that Mercurial will not let you commit files with unresolved
3003 merge conflicts. You must use :hg:`resolve -m ...` before you can
2999 merge conflicts. You must use :hg:`resolve -m ...` before you can
3004 commit after a conflicting merge.
3000 commit after a conflicting merge.
3005
3001
3006 Returns 0 on success, 1 if any files fail a resolve attempt.
3002 Returns 0 on success, 1 if any files fail a resolve attempt.
3007 """
3003 """
3008
3004
3009 all, mark, unmark, show, nostatus = \
3005 all, mark, unmark, show, nostatus = \
3010 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3006 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3011
3007
3012 if (show and (mark or unmark)) or (mark and unmark):
3008 if (show and (mark or unmark)) or (mark and unmark):
3013 raise util.Abort(_("too many options specified"))
3009 raise util.Abort(_("too many options specified"))
3014 if pats and all:
3010 if pats and all:
3015 raise util.Abort(_("can't specify --all and patterns"))
3011 raise util.Abort(_("can't specify --all and patterns"))
3016 if not (all or pats or show or mark or unmark):
3012 if not (all or pats or show or mark or unmark):
3017 raise util.Abort(_('no files or directories specified; '
3013 raise util.Abort(_('no files or directories specified; '
3018 'use --all to remerge all files'))
3014 'use --all to remerge all files'))
3019
3015
3020 ms = mergemod.mergestate(repo)
3016 ms = mergemod.mergestate(repo)
3021 m = cmdutil.match(repo, pats, opts)
3017 m = cmdutil.match(repo, pats, opts)
3022 ret = 0
3018 ret = 0
3023
3019
3024 for f in ms:
3020 for f in ms:
3025 if m(f):
3021 if m(f):
3026 if show:
3022 if show:
3027 if nostatus:
3023 if nostatus:
3028 ui.write("%s\n" % f)
3024 ui.write("%s\n" % f)
3029 else:
3025 else:
3030 ui.write("%s %s\n" % (ms[f].upper(), f),
3026 ui.write("%s %s\n" % (ms[f].upper(), f),
3031 label='resolve.' +
3027 label='resolve.' +
3032 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3028 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3033 elif mark:
3029 elif mark:
3034 ms.mark(f, "r")
3030 ms.mark(f, "r")
3035 elif unmark:
3031 elif unmark:
3036 ms.mark(f, "u")
3032 ms.mark(f, "u")
3037 else:
3033 else:
3038 wctx = repo[None]
3034 wctx = repo[None]
3039 mctx = wctx.parents()[-1]
3035 mctx = wctx.parents()[-1]
3040
3036
3041 # backup pre-resolve (merge uses .orig for its own purposes)
3037 # backup pre-resolve (merge uses .orig for its own purposes)
3042 a = repo.wjoin(f)
3038 a = repo.wjoin(f)
3043 util.copyfile(a, a + ".resolve")
3039 util.copyfile(a, a + ".resolve")
3044
3040
3045 try:
3041 try:
3046 # resolve file
3042 # resolve file
3047 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3043 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3048 if ms.resolve(f, wctx, mctx):
3044 if ms.resolve(f, wctx, mctx):
3049 ret = 1
3045 ret = 1
3050 finally:
3046 finally:
3051 ui.setconfig('ui', 'forcemerge', '')
3047 ui.setconfig('ui', 'forcemerge', '')
3052
3048
3053 # replace filemerge's .orig file with our resolve file
3049 # replace filemerge's .orig file with our resolve file
3054 util.rename(a + ".resolve", a + ".orig")
3050 util.rename(a + ".resolve", a + ".orig")
3055
3051
3056 ms.commit()
3052 ms.commit()
3057 return ret
3053 return ret
3058
3054
3059 def revert(ui, repo, *pats, **opts):
3055 def revert(ui, repo, *pats, **opts):
3060 """restore individual files or directories to an earlier state
3056 """restore individual files or directories to an earlier state
3061
3057
3062 .. note::
3058 .. note::
3063 This command is most likely not what you are looking for.
3059 This command is most likely not what you are looking for.
3064 Revert will partially overwrite content in the working
3060 Revert will partially overwrite content in the working
3065 directory without changing the working directory parents. Use
3061 directory without changing the working directory parents. Use
3066 :hg:`update -r rev` to check out earlier revisions, or
3062 :hg:`update -r rev` to check out earlier revisions, or
3067 :hg:`update --clean .` to undo a merge which has added another
3063 :hg:`update --clean .` to undo a merge which has added another
3068 parent.
3064 parent.
3069
3065
3070 With no revision specified, revert the named files or directories
3066 With no revision specified, revert the named files or directories
3071 to the contents they had in the parent of the working directory.
3067 to the contents they had in the parent of the working directory.
3072 This restores the contents of the affected files to an unmodified
3068 This restores the contents of the affected files to an unmodified
3073 state and unschedules adds, removes, copies, and renames. If the
3069 state and unschedules adds, removes, copies, and renames. If the
3074 working directory has two parents, you must explicitly specify a
3070 working directory has two parents, you must explicitly specify a
3075 revision.
3071 revision.
3076
3072
3077 Using the -r/--rev option, revert the given files or directories
3073 Using the -r/--rev option, revert the given files or directories
3078 to their contents as of a specific revision. This can be helpful
3074 to their contents as of a specific revision. This can be helpful
3079 to "roll back" some or all of an earlier change. See :hg:`help
3075 to "roll back" some or all of an earlier change. See :hg:`help
3080 dates` for a list of formats valid for -d/--date.
3076 dates` for a list of formats valid for -d/--date.
3081
3077
3082 Revert modifies the working directory. It does not commit any
3078 Revert modifies the working directory. It does not commit any
3083 changes, or change the parent of the working directory. If you
3079 changes, or change the parent of the working directory. If you
3084 revert to a revision other than the parent of the working
3080 revert to a revision other than the parent of the working
3085 directory, the reverted files will thus appear modified
3081 directory, the reverted files will thus appear modified
3086 afterwards.
3082 afterwards.
3087
3083
3088 If a file has been deleted, it is restored. If the executable mode
3084 If a file has been deleted, it is restored. If the executable mode
3089 of a file was changed, it is reset.
3085 of a file was changed, it is reset.
3090
3086
3091 If names are given, all files matching the names are reverted.
3087 If names are given, all files matching the names are reverted.
3092 If no arguments are given, no files are reverted.
3088 If no arguments are given, no files are reverted.
3093
3089
3094 Modified files are saved with a .orig suffix before reverting.
3090 Modified files are saved with a .orig suffix before reverting.
3095 To disable these backups, use --no-backup.
3091 To disable these backups, use --no-backup.
3096
3092
3097 Returns 0 on success.
3093 Returns 0 on success.
3098 """
3094 """
3099
3095
3100 if opts.get("date"):
3096 if opts.get("date"):
3101 if opts.get("rev"):
3097 if opts.get("rev"):
3102 raise util.Abort(_("you can't specify a revision and a date"))
3098 raise util.Abort(_("you can't specify a revision and a date"))
3103 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3099 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3104
3100
3105 parent, p2 = repo.dirstate.parents()
3101 parent, p2 = repo.dirstate.parents()
3106 if not opts.get('rev') and p2 != nullid:
3102 if not opts.get('rev') and p2 != nullid:
3107 raise util.Abort(_('uncommitted merge - '
3103 raise util.Abort(_('uncommitted merge - '
3108 'use "hg update", see "hg help revert"'))
3104 'use "hg update", see "hg help revert"'))
3109
3105
3110 if not pats and not opts.get('all'):
3106 if not pats and not opts.get('all'):
3111 raise util.Abort(_('no files or directories specified; '
3107 raise util.Abort(_('no files or directories specified; '
3112 'use --all to revert the whole repo'))
3108 'use --all to revert the whole repo'))
3113
3109
3114 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3110 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3115 node = ctx.node()
3111 node = ctx.node()
3116 mf = ctx.manifest()
3112 mf = ctx.manifest()
3117 if node == parent:
3113 if node == parent:
3118 pmf = mf
3114 pmf = mf
3119 else:
3115 else:
3120 pmf = None
3116 pmf = None
3121
3117
3122 # need all matching names in dirstate and manifest of target rev,
3118 # need all matching names in dirstate and manifest of target rev,
3123 # so have to walk both. do not print errors if files exist in one
3119 # so have to walk both. do not print errors if files exist in one
3124 # but not other.
3120 # but not other.
3125
3121
3126 names = {}
3122 names = {}
3127
3123
3128 wlock = repo.wlock()
3124 wlock = repo.wlock()
3129 try:
3125 try:
3130 # walk dirstate.
3126 # walk dirstate.
3131
3127
3132 m = cmdutil.match(repo, pats, opts)
3128 m = cmdutil.match(repo, pats, opts)
3133 m.bad = lambda x, y: False
3129 m.bad = lambda x, y: False
3134 for abs in repo.walk(m):
3130 for abs in repo.walk(m):
3135 names[abs] = m.rel(abs), m.exact(abs)
3131 names[abs] = m.rel(abs), m.exact(abs)
3136
3132
3137 # walk target manifest.
3133 # walk target manifest.
3138
3134
3139 def badfn(path, msg):
3135 def badfn(path, msg):
3140 if path in names:
3136 if path in names:
3141 return
3137 return
3142 path_ = path + '/'
3138 path_ = path + '/'
3143 for f in names:
3139 for f in names:
3144 if f.startswith(path_):
3140 if f.startswith(path_):
3145 return
3141 return
3146 ui.warn("%s: %s\n" % (m.rel(path), msg))
3142 ui.warn("%s: %s\n" % (m.rel(path), msg))
3147
3143
3148 m = cmdutil.match(repo, pats, opts)
3144 m = cmdutil.match(repo, pats, opts)
3149 m.bad = badfn
3145 m.bad = badfn
3150 for abs in repo[node].walk(m):
3146 for abs in repo[node].walk(m):
3151 if abs not in names:
3147 if abs not in names:
3152 names[abs] = m.rel(abs), m.exact(abs)
3148 names[abs] = m.rel(abs), m.exact(abs)
3153
3149
3154 m = cmdutil.matchfiles(repo, names)
3150 m = cmdutil.matchfiles(repo, names)
3155 changes = repo.status(match=m)[:4]
3151 changes = repo.status(match=m)[:4]
3156 modified, added, removed, deleted = map(set, changes)
3152 modified, added, removed, deleted = map(set, changes)
3157
3153
3158 # if f is a rename, also revert the source
3154 # if f is a rename, also revert the source
3159 cwd = repo.getcwd()
3155 cwd = repo.getcwd()
3160 for f in added:
3156 for f in added:
3161 src = repo.dirstate.copied(f)
3157 src = repo.dirstate.copied(f)
3162 if src and src not in names and repo.dirstate[src] == 'r':
3158 if src and src not in names and repo.dirstate[src] == 'r':
3163 removed.add(src)
3159 removed.add(src)
3164 names[src] = (repo.pathto(src, cwd), True)
3160 names[src] = (repo.pathto(src, cwd), True)
3165
3161
3166 def removeforget(abs):
3162 def removeforget(abs):
3167 if repo.dirstate[abs] == 'a':
3163 if repo.dirstate[abs] == 'a':
3168 return _('forgetting %s\n')
3164 return _('forgetting %s\n')
3169 return _('removing %s\n')
3165 return _('removing %s\n')
3170
3166
3171 revert = ([], _('reverting %s\n'))
3167 revert = ([], _('reverting %s\n'))
3172 add = ([], _('adding %s\n'))
3168 add = ([], _('adding %s\n'))
3173 remove = ([], removeforget)
3169 remove = ([], removeforget)
3174 undelete = ([], _('undeleting %s\n'))
3170 undelete = ([], _('undeleting %s\n'))
3175
3171
3176 disptable = (
3172 disptable = (
3177 # dispatch table:
3173 # dispatch table:
3178 # file state
3174 # file state
3179 # action if in target manifest
3175 # action if in target manifest
3180 # action if not in target manifest
3176 # action if not in target manifest
3181 # make backup if in target manifest
3177 # make backup if in target manifest
3182 # make backup if not in target manifest
3178 # make backup if not in target manifest
3183 (modified, revert, remove, True, True),
3179 (modified, revert, remove, True, True),
3184 (added, revert, remove, True, False),
3180 (added, revert, remove, True, False),
3185 (removed, undelete, None, False, False),
3181 (removed, undelete, None, False, False),
3186 (deleted, revert, remove, False, False),
3182 (deleted, revert, remove, False, False),
3187 )
3183 )
3188
3184
3189 for abs, (rel, exact) in sorted(names.items()):
3185 for abs, (rel, exact) in sorted(names.items()):
3190 mfentry = mf.get(abs)
3186 mfentry = mf.get(abs)
3191 target = repo.wjoin(abs)
3187 target = repo.wjoin(abs)
3192 def handle(xlist, dobackup):
3188 def handle(xlist, dobackup):
3193 xlist[0].append(abs)
3189 xlist[0].append(abs)
3194 if (dobackup and not opts.get('no_backup') and
3190 if (dobackup and not opts.get('no_backup') and
3195 os.path.lexists(target)):
3191 os.path.lexists(target)):
3196 bakname = "%s.orig" % rel
3192 bakname = "%s.orig" % rel
3197 ui.note(_('saving current version of %s as %s\n') %
3193 ui.note(_('saving current version of %s as %s\n') %
3198 (rel, bakname))
3194 (rel, bakname))
3199 if not opts.get('dry_run'):
3195 if not opts.get('dry_run'):
3200 util.rename(target, bakname)
3196 util.rename(target, bakname)
3201 if ui.verbose or not exact:
3197 if ui.verbose or not exact:
3202 msg = xlist[1]
3198 msg = xlist[1]
3203 if not isinstance(msg, basestring):
3199 if not isinstance(msg, basestring):
3204 msg = msg(abs)
3200 msg = msg(abs)
3205 ui.status(msg % rel)
3201 ui.status(msg % rel)
3206 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3202 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3207 if abs not in table:
3203 if abs not in table:
3208 continue
3204 continue
3209 # file has changed in dirstate
3205 # file has changed in dirstate
3210 if mfentry:
3206 if mfentry:
3211 handle(hitlist, backuphit)
3207 handle(hitlist, backuphit)
3212 elif misslist is not None:
3208 elif misslist is not None:
3213 handle(misslist, backupmiss)
3209 handle(misslist, backupmiss)
3214 break
3210 break
3215 else:
3211 else:
3216 if abs not in repo.dirstate:
3212 if abs not in repo.dirstate:
3217 if mfentry:
3213 if mfentry:
3218 handle(add, True)
3214 handle(add, True)
3219 elif exact:
3215 elif exact:
3220 ui.warn(_('file not managed: %s\n') % rel)
3216 ui.warn(_('file not managed: %s\n') % rel)
3221 continue
3217 continue
3222 # file has not changed in dirstate
3218 # file has not changed in dirstate
3223 if node == parent:
3219 if node == parent:
3224 if exact:
3220 if exact:
3225 ui.warn(_('no changes needed to %s\n') % rel)
3221 ui.warn(_('no changes needed to %s\n') % rel)
3226 continue
3222 continue
3227 if pmf is None:
3223 if pmf is None:
3228 # only need parent manifest in this unlikely case,
3224 # only need parent manifest in this unlikely case,
3229 # so do not read by default
3225 # so do not read by default
3230 pmf = repo[parent].manifest()
3226 pmf = repo[parent].manifest()
3231 if abs in pmf:
3227 if abs in pmf:
3232 if mfentry:
3228 if mfentry:
3233 # if version of file is same in parent and target
3229 # if version of file is same in parent and target
3234 # manifests, do nothing
3230 # manifests, do nothing
3235 if (pmf[abs] != mfentry or
3231 if (pmf[abs] != mfentry or
3236 pmf.flags(abs) != mf.flags(abs)):
3232 pmf.flags(abs) != mf.flags(abs)):
3237 handle(revert, False)
3233 handle(revert, False)
3238 else:
3234 else:
3239 handle(remove, False)
3235 handle(remove, False)
3240
3236
3241 if not opts.get('dry_run'):
3237 if not opts.get('dry_run'):
3242 def checkout(f):
3238 def checkout(f):
3243 fc = ctx[f]
3239 fc = ctx[f]
3244 repo.wwrite(f, fc.data(), fc.flags())
3240 repo.wwrite(f, fc.data(), fc.flags())
3245
3241
3246 audit_path = util.path_auditor(repo.root)
3242 audit_path = util.path_auditor(repo.root)
3247 for f in remove[0]:
3243 for f in remove[0]:
3248 if repo.dirstate[f] == 'a':
3244 if repo.dirstate[f] == 'a':
3249 repo.dirstate.forget(f)
3245 repo.dirstate.forget(f)
3250 continue
3246 continue
3251 audit_path(f)
3247 audit_path(f)
3252 try:
3248 try:
3253 util.unlinkpath(repo.wjoin(f))
3249 util.unlinkpath(repo.wjoin(f))
3254 except OSError:
3250 except OSError:
3255 pass
3251 pass
3256 repo.dirstate.remove(f)
3252 repo.dirstate.remove(f)
3257
3253
3258 normal = None
3254 normal = None
3259 if node == parent:
3255 if node == parent:
3260 # We're reverting to our parent. If possible, we'd like status
3256 # We're reverting to our parent. If possible, we'd like status
3261 # to report the file as clean. We have to use normallookup for
3257 # to report the file as clean. We have to use normallookup for
3262 # merges to avoid losing information about merged/dirty files.
3258 # merges to avoid losing information about merged/dirty files.
3263 if p2 != nullid:
3259 if p2 != nullid:
3264 normal = repo.dirstate.normallookup
3260 normal = repo.dirstate.normallookup
3265 else:
3261 else:
3266 normal = repo.dirstate.normal
3262 normal = repo.dirstate.normal
3267 for f in revert[0]:
3263 for f in revert[0]:
3268 checkout(f)
3264 checkout(f)
3269 if normal:
3265 if normal:
3270 normal(f)
3266 normal(f)
3271
3267
3272 for f in add[0]:
3268 for f in add[0]:
3273 checkout(f)
3269 checkout(f)
3274 repo.dirstate.add(f)
3270 repo.dirstate.add(f)
3275
3271
3276 normal = repo.dirstate.normallookup
3272 normal = repo.dirstate.normallookup
3277 if node == parent and p2 == nullid:
3273 if node == parent and p2 == nullid:
3278 normal = repo.dirstate.normal
3274 normal = repo.dirstate.normal
3279 for f in undelete[0]:
3275 for f in undelete[0]:
3280 checkout(f)
3276 checkout(f)
3281 normal(f)
3277 normal(f)
3282
3278
3283 finally:
3279 finally:
3284 wlock.release()
3280 wlock.release()
3285
3281
3286 def rollback(ui, repo, **opts):
3282 def rollback(ui, repo, **opts):
3287 """roll back the last transaction (dangerous)
3283 """roll back the last transaction (dangerous)
3288
3284
3289 This command should be used with care. There is only one level of
3285 This command should be used with care. There is only one level of
3290 rollback, and there is no way to undo a rollback. It will also
3286 rollback, and there is no way to undo a rollback. It will also
3291 restore the dirstate at the time of the last transaction, losing
3287 restore the dirstate at the time of the last transaction, losing
3292 any dirstate changes since that time. This command does not alter
3288 any dirstate changes since that time. This command does not alter
3293 the working directory.
3289 the working directory.
3294
3290
3295 Transactions are used to encapsulate the effects of all commands
3291 Transactions are used to encapsulate the effects of all commands
3296 that create new changesets or propagate existing changesets into a
3292 that create new changesets or propagate existing changesets into a
3297 repository. For example, the following commands are transactional,
3293 repository. For example, the following commands are transactional,
3298 and their effects can be rolled back:
3294 and their effects can be rolled back:
3299
3295
3300 - commit
3296 - commit
3301 - import
3297 - import
3302 - pull
3298 - pull
3303 - push (with this repository as the destination)
3299 - push (with this repository as the destination)
3304 - unbundle
3300 - unbundle
3305
3301
3306 This command is not intended for use on public repositories. Once
3302 This command is not intended for use on public repositories. Once
3307 changes are visible for pull by other users, rolling a transaction
3303 changes are visible for pull by other users, rolling a transaction
3308 back locally is ineffective (someone else may already have pulled
3304 back locally is ineffective (someone else may already have pulled
3309 the changes). Furthermore, a race is possible with readers of the
3305 the changes). Furthermore, a race is possible with readers of the
3310 repository; for example an in-progress pull from the repository
3306 repository; for example an in-progress pull from the repository
3311 may fail if a rollback is performed.
3307 may fail if a rollback is performed.
3312
3308
3313 Returns 0 on success, 1 if no rollback data is available.
3309 Returns 0 on success, 1 if no rollback data is available.
3314 """
3310 """
3315 return repo.rollback(opts.get('dry_run'))
3311 return repo.rollback(opts.get('dry_run'))
3316
3312
3317 def root(ui, repo):
3313 def root(ui, repo):
3318 """print the root (top) of the current working directory
3314 """print the root (top) of the current working directory
3319
3315
3320 Print the root directory of the current repository.
3316 Print the root directory of the current repository.
3321
3317
3322 Returns 0 on success.
3318 Returns 0 on success.
3323 """
3319 """
3324 ui.write(repo.root + "\n")
3320 ui.write(repo.root + "\n")
3325
3321
3326 def serve(ui, repo, **opts):
3322 def serve(ui, repo, **opts):
3327 """start stand-alone webserver
3323 """start stand-alone webserver
3328
3324
3329 Start a local HTTP repository browser and pull server. You can use
3325 Start a local HTTP repository browser and pull server. You can use
3330 this for ad-hoc sharing and browsing of repositories. It is
3326 this for ad-hoc sharing and browsing of repositories. It is
3331 recommended to use a real web server to serve a repository for
3327 recommended to use a real web server to serve a repository for
3332 longer periods of time.
3328 longer periods of time.
3333
3329
3334 Please note that the server does not implement access control.
3330 Please note that the server does not implement access control.
3335 This means that, by default, anybody can read from the server and
3331 This means that, by default, anybody can read from the server and
3336 nobody can write to it by default. Set the ``web.allow_push``
3332 nobody can write to it by default. Set the ``web.allow_push``
3337 option to ``*`` to allow everybody to push to the server. You
3333 option to ``*`` to allow everybody to push to the server. You
3338 should use a real web server if you need to authenticate users.
3334 should use a real web server if you need to authenticate users.
3339
3335
3340 By default, the server logs accesses to stdout and errors to
3336 By default, the server logs accesses to stdout and errors to
3341 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3337 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3342 files.
3338 files.
3343
3339
3344 To have the server choose a free port number to listen on, specify
3340 To have the server choose a free port number to listen on, specify
3345 a port number of 0; in this case, the server will print the port
3341 a port number of 0; in this case, the server will print the port
3346 number it uses.
3342 number it uses.
3347
3343
3348 Returns 0 on success.
3344 Returns 0 on success.
3349 """
3345 """
3350
3346
3351 if opts["stdio"]:
3347 if opts["stdio"]:
3352 if repo is None:
3348 if repo is None:
3353 raise error.RepoError(_("There is no Mercurial repository here"
3349 raise error.RepoError(_("There is no Mercurial repository here"
3354 " (.hg not found)"))
3350 " (.hg not found)"))
3355 s = sshserver.sshserver(ui, repo)
3351 s = sshserver.sshserver(ui, repo)
3356 s.serve_forever()
3352 s.serve_forever()
3357
3353
3358 # this way we can check if something was given in the command-line
3354 # this way we can check if something was given in the command-line
3359 if opts.get('port'):
3355 if opts.get('port'):
3360 opts['port'] = util.getport(opts.get('port'))
3356 opts['port'] = util.getport(opts.get('port'))
3361
3357
3362 baseui = repo and repo.baseui or ui
3358 baseui = repo and repo.baseui or ui
3363 optlist = ("name templates style address port prefix ipv6"
3359 optlist = ("name templates style address port prefix ipv6"
3364 " accesslog errorlog certificate encoding")
3360 " accesslog errorlog certificate encoding")
3365 for o in optlist.split():
3361 for o in optlist.split():
3366 val = opts.get(o, '')
3362 val = opts.get(o, '')
3367 if val in (None, ''): # should check against default options instead
3363 if val in (None, ''): # should check against default options instead
3368 continue
3364 continue
3369 baseui.setconfig("web", o, val)
3365 baseui.setconfig("web", o, val)
3370 if repo and repo.ui != baseui:
3366 if repo and repo.ui != baseui:
3371 repo.ui.setconfig("web", o, val)
3367 repo.ui.setconfig("web", o, val)
3372
3368
3373 o = opts.get('web_conf') or opts.get('webdir_conf')
3369 o = opts.get('web_conf') or opts.get('webdir_conf')
3374 if not o:
3370 if not o:
3375 if not repo:
3371 if not repo:
3376 raise error.RepoError(_("There is no Mercurial repository"
3372 raise error.RepoError(_("There is no Mercurial repository"
3377 " here (.hg not found)"))
3373 " here (.hg not found)"))
3378 o = repo.root
3374 o = repo.root
3379
3375
3380 app = hgweb.hgweb(o, baseui=ui)
3376 app = hgweb.hgweb(o, baseui=ui)
3381
3377
3382 class service(object):
3378 class service(object):
3383 def init(self):
3379 def init(self):
3384 util.set_signal_handler()
3380 util.set_signal_handler()
3385 self.httpd = hgweb.server.create_server(ui, app)
3381 self.httpd = hgweb.server.create_server(ui, app)
3386
3382
3387 if opts['port'] and not ui.verbose:
3383 if opts['port'] and not ui.verbose:
3388 return
3384 return
3389
3385
3390 if self.httpd.prefix:
3386 if self.httpd.prefix:
3391 prefix = self.httpd.prefix.strip('/') + '/'
3387 prefix = self.httpd.prefix.strip('/') + '/'
3392 else:
3388 else:
3393 prefix = ''
3389 prefix = ''
3394
3390
3395 port = ':%d' % self.httpd.port
3391 port = ':%d' % self.httpd.port
3396 if port == ':80':
3392 if port == ':80':
3397 port = ''
3393 port = ''
3398
3394
3399 bindaddr = self.httpd.addr
3395 bindaddr = self.httpd.addr
3400 if bindaddr == '0.0.0.0':
3396 if bindaddr == '0.0.0.0':
3401 bindaddr = '*'
3397 bindaddr = '*'
3402 elif ':' in bindaddr: # IPv6
3398 elif ':' in bindaddr: # IPv6
3403 bindaddr = '[%s]' % bindaddr
3399 bindaddr = '[%s]' % bindaddr
3404
3400
3405 fqaddr = self.httpd.fqaddr
3401 fqaddr = self.httpd.fqaddr
3406 if ':' in fqaddr:
3402 if ':' in fqaddr:
3407 fqaddr = '[%s]' % fqaddr
3403 fqaddr = '[%s]' % fqaddr
3408 if opts['port']:
3404 if opts['port']:
3409 write = ui.status
3405 write = ui.status
3410 else:
3406 else:
3411 write = ui.write
3407 write = ui.write
3412 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3408 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3413 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3409 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3414
3410
3415 def run(self):
3411 def run(self):
3416 self.httpd.serve_forever()
3412 self.httpd.serve_forever()
3417
3413
3418 service = service()
3414 service = service()
3419
3415
3420 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3416 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3421
3417
3422 def status(ui, repo, *pats, **opts):
3418 def status(ui, repo, *pats, **opts):
3423 """show changed files in the working directory
3419 """show changed files in the working directory
3424
3420
3425 Show status of files in the repository. If names are given, only
3421 Show status of files in the repository. If names are given, only
3426 files that match are shown. Files that are clean or ignored or
3422 files that match are shown. Files that are clean or ignored or
3427 the source of a copy/move operation, are not listed unless
3423 the source of a copy/move operation, are not listed unless
3428 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3424 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3429 Unless options described with "show only ..." are given, the
3425 Unless options described with "show only ..." are given, the
3430 options -mardu are used.
3426 options -mardu are used.
3431
3427
3432 Option -q/--quiet hides untracked (unknown and ignored) files
3428 Option -q/--quiet hides untracked (unknown and ignored) files
3433 unless explicitly requested with -u/--unknown or -i/--ignored.
3429 unless explicitly requested with -u/--unknown or -i/--ignored.
3434
3430
3435 .. note::
3431 .. note::
3436 status may appear to disagree with diff if permissions have
3432 status may appear to disagree with diff if permissions have
3437 changed or a merge has occurred. The standard diff format does
3433 changed or a merge has occurred. The standard diff format does
3438 not report permission changes and diff only reports changes
3434 not report permission changes and diff only reports changes
3439 relative to one merge parent.
3435 relative to one merge parent.
3440
3436
3441 If one revision is given, it is used as the base revision.
3437 If one revision is given, it is used as the base revision.
3442 If two revisions are given, the differences between them are
3438 If two revisions are given, the differences between them are
3443 shown. The --change option can also be used as a shortcut to list
3439 shown. The --change option can also be used as a shortcut to list
3444 the changed files of a revision from its first parent.
3440 the changed files of a revision from its first parent.
3445
3441
3446 The codes used to show the status of files are::
3442 The codes used to show the status of files are::
3447
3443
3448 M = modified
3444 M = modified
3449 A = added
3445 A = added
3450 R = removed
3446 R = removed
3451 C = clean
3447 C = clean
3452 ! = missing (deleted by non-hg command, but still tracked)
3448 ! = missing (deleted by non-hg command, but still tracked)
3453 ? = not tracked
3449 ? = not tracked
3454 I = ignored
3450 I = ignored
3455 = origin of the previous file listed as A (added)
3451 = origin of the previous file listed as A (added)
3456
3452
3457 Returns 0 on success.
3453 Returns 0 on success.
3458 """
3454 """
3459
3455
3460 revs = opts.get('rev')
3456 revs = opts.get('rev')
3461 change = opts.get('change')
3457 change = opts.get('change')
3462
3458
3463 if revs and change:
3459 if revs and change:
3464 msg = _('cannot specify --rev and --change at the same time')
3460 msg = _('cannot specify --rev and --change at the same time')
3465 raise util.Abort(msg)
3461 raise util.Abort(msg)
3466 elif change:
3462 elif change:
3467 node2 = repo.lookup(change)
3463 node2 = repo.lookup(change)
3468 node1 = repo[node2].parents()[0].node()
3464 node1 = repo[node2].parents()[0].node()
3469 else:
3465 else:
3470 node1, node2 = cmdutil.revpair(repo, revs)
3466 node1, node2 = cmdutil.revpair(repo, revs)
3471
3467
3472 cwd = (pats and repo.getcwd()) or ''
3468 cwd = (pats and repo.getcwd()) or ''
3473 end = opts.get('print0') and '\0' or '\n'
3469 end = opts.get('print0') and '\0' or '\n'
3474 copy = {}
3470 copy = {}
3475 states = 'modified added removed deleted unknown ignored clean'.split()
3471 states = 'modified added removed deleted unknown ignored clean'.split()
3476 show = [k for k in states if opts.get(k)]
3472 show = [k for k in states if opts.get(k)]
3477 if opts.get('all'):
3473 if opts.get('all'):
3478 show += ui.quiet and (states[:4] + ['clean']) or states
3474 show += ui.quiet and (states[:4] + ['clean']) or states
3479 if not show:
3475 if not show:
3480 show = ui.quiet and states[:4] or states[:5]
3476 show = ui.quiet and states[:4] or states[:5]
3481
3477
3482 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3478 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3483 'ignored' in show, 'clean' in show, 'unknown' in show,
3479 'ignored' in show, 'clean' in show, 'unknown' in show,
3484 opts.get('subrepos'))
3480 opts.get('subrepos'))
3485 changestates = zip(states, 'MAR!?IC', stat)
3481 changestates = zip(states, 'MAR!?IC', stat)
3486
3482
3487 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3483 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3488 ctxn = repo[nullid]
3484 ctxn = repo[nullid]
3489 ctx1 = repo[node1]
3485 ctx1 = repo[node1]
3490 ctx2 = repo[node2]
3486 ctx2 = repo[node2]
3491 added = stat[1]
3487 added = stat[1]
3492 if node2 is None:
3488 if node2 is None:
3493 added = stat[0] + stat[1] # merged?
3489 added = stat[0] + stat[1] # merged?
3494
3490
3495 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3491 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3496 if k in added:
3492 if k in added:
3497 copy[k] = v
3493 copy[k] = v
3498 elif v in added:
3494 elif v in added:
3499 copy[v] = k
3495 copy[v] = k
3500
3496
3501 for state, char, files in changestates:
3497 for state, char, files in changestates:
3502 if state in show:
3498 if state in show:
3503 format = "%s %%s%s" % (char, end)
3499 format = "%s %%s%s" % (char, end)
3504 if opts.get('no_status'):
3500 if opts.get('no_status'):
3505 format = "%%s%s" % end
3501 format = "%%s%s" % end
3506
3502
3507 for f in files:
3503 for f in files:
3508 ui.write(format % repo.pathto(f, cwd),
3504 ui.write(format % repo.pathto(f, cwd),
3509 label='status.' + state)
3505 label='status.' + state)
3510 if f in copy:
3506 if f in copy:
3511 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3507 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3512 label='status.copied')
3508 label='status.copied')
3513
3509
3514 def summary(ui, repo, **opts):
3510 def summary(ui, repo, **opts):
3515 """summarize working directory state
3511 """summarize working directory state
3516
3512
3517 This generates a brief summary of the working directory state,
3513 This generates a brief summary of the working directory state,
3518 including parents, branch, commit status, and available updates.
3514 including parents, branch, commit status, and available updates.
3519
3515
3520 With the --remote option, this will check the default paths for
3516 With the --remote option, this will check the default paths for
3521 incoming and outgoing changes. This can be time-consuming.
3517 incoming and outgoing changes. This can be time-consuming.
3522
3518
3523 Returns 0 on success.
3519 Returns 0 on success.
3524 """
3520 """
3525
3521
3526 ctx = repo[None]
3522 ctx = repo[None]
3527 parents = ctx.parents()
3523 parents = ctx.parents()
3528 pnode = parents[0].node()
3524 pnode = parents[0].node()
3529
3525
3530 for p in parents:
3526 for p in parents:
3531 # label with log.changeset (instead of log.parent) since this
3527 # label with log.changeset (instead of log.parent) since this
3532 # shows a working directory parent *changeset*:
3528 # shows a working directory parent *changeset*:
3533 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3529 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3534 label='log.changeset')
3530 label='log.changeset')
3535 ui.write(' '.join(p.tags()), label='log.tag')
3531 ui.write(' '.join(p.tags()), label='log.tag')
3536 if p.rev() == -1:
3532 if p.rev() == -1:
3537 if not len(repo):
3533 if not len(repo):
3538 ui.write(_(' (empty repository)'))
3534 ui.write(_(' (empty repository)'))
3539 else:
3535 else:
3540 ui.write(_(' (no revision checked out)'))
3536 ui.write(_(' (no revision checked out)'))
3541 ui.write('\n')
3537 ui.write('\n')
3542 if p.description():
3538 if p.description():
3543 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3539 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3544 label='log.summary')
3540 label='log.summary')
3545
3541
3546 branch = ctx.branch()
3542 branch = ctx.branch()
3547 bheads = repo.branchheads(branch)
3543 bheads = repo.branchheads(branch)
3548 m = _('branch: %s\n') % branch
3544 m = _('branch: %s\n') % branch
3549 if branch != 'default':
3545 if branch != 'default':
3550 ui.write(m, label='log.branch')
3546 ui.write(m, label='log.branch')
3551 else:
3547 else:
3552 ui.status(m, label='log.branch')
3548 ui.status(m, label='log.branch')
3553
3549
3554 st = list(repo.status(unknown=True))[:6]
3550 st = list(repo.status(unknown=True))[:6]
3555
3551
3556 c = repo.dirstate.copies()
3552 c = repo.dirstate.copies()
3557 copied, renamed = [], []
3553 copied, renamed = [], []
3558 for d, s in c.iteritems():
3554 for d, s in c.iteritems():
3559 if s in st[2]:
3555 if s in st[2]:
3560 st[2].remove(s)
3556 st[2].remove(s)
3561 renamed.append(d)
3557 renamed.append(d)
3562 else:
3558 else:
3563 copied.append(d)
3559 copied.append(d)
3564 if d in st[1]:
3560 if d in st[1]:
3565 st[1].remove(d)
3561 st[1].remove(d)
3566 st.insert(3, renamed)
3562 st.insert(3, renamed)
3567 st.insert(4, copied)
3563 st.insert(4, copied)
3568
3564
3569 ms = mergemod.mergestate(repo)
3565 ms = mergemod.mergestate(repo)
3570 st.append([f for f in ms if ms[f] == 'u'])
3566 st.append([f for f in ms if ms[f] == 'u'])
3571
3567
3572 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3568 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3573 st.append(subs)
3569 st.append(subs)
3574
3570
3575 labels = [ui.label(_('%d modified'), 'status.modified'),
3571 labels = [ui.label(_('%d modified'), 'status.modified'),
3576 ui.label(_('%d added'), 'status.added'),
3572 ui.label(_('%d added'), 'status.added'),
3577 ui.label(_('%d removed'), 'status.removed'),
3573 ui.label(_('%d removed'), 'status.removed'),
3578 ui.label(_('%d renamed'), 'status.copied'),
3574 ui.label(_('%d renamed'), 'status.copied'),
3579 ui.label(_('%d copied'), 'status.copied'),
3575 ui.label(_('%d copied'), 'status.copied'),
3580 ui.label(_('%d deleted'), 'status.deleted'),
3576 ui.label(_('%d deleted'), 'status.deleted'),
3581 ui.label(_('%d unknown'), 'status.unknown'),
3577 ui.label(_('%d unknown'), 'status.unknown'),
3582 ui.label(_('%d ignored'), 'status.ignored'),
3578 ui.label(_('%d ignored'), 'status.ignored'),
3583 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3579 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3584 ui.label(_('%d subrepos'), 'status.modified')]
3580 ui.label(_('%d subrepos'), 'status.modified')]
3585 t = []
3581 t = []
3586 for s, l in zip(st, labels):
3582 for s, l in zip(st, labels):
3587 if s:
3583 if s:
3588 t.append(l % len(s))
3584 t.append(l % len(s))
3589
3585
3590 t = ', '.join(t)
3586 t = ', '.join(t)
3591 cleanworkdir = False
3587 cleanworkdir = False
3592
3588
3593 if len(parents) > 1:
3589 if len(parents) > 1:
3594 t += _(' (merge)')
3590 t += _(' (merge)')
3595 elif branch != parents[0].branch():
3591 elif branch != parents[0].branch():
3596 t += _(' (new branch)')
3592 t += _(' (new branch)')
3597 elif (parents[0].extra().get('close') and
3593 elif (parents[0].extra().get('close') and
3598 pnode in repo.branchheads(branch, closed=True)):
3594 pnode in repo.branchheads(branch, closed=True)):
3599 t += _(' (head closed)')
3595 t += _(' (head closed)')
3600 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3596 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3601 t += _(' (clean)')
3597 t += _(' (clean)')
3602 cleanworkdir = True
3598 cleanworkdir = True
3603 elif pnode not in bheads:
3599 elif pnode not in bheads:
3604 t += _(' (new branch head)')
3600 t += _(' (new branch head)')
3605
3601
3606 if cleanworkdir:
3602 if cleanworkdir:
3607 ui.status(_('commit: %s\n') % t.strip())
3603 ui.status(_('commit: %s\n') % t.strip())
3608 else:
3604 else:
3609 ui.write(_('commit: %s\n') % t.strip())
3605 ui.write(_('commit: %s\n') % t.strip())
3610
3606
3611 # all ancestors of branch heads - all ancestors of parent = new csets
3607 # all ancestors of branch heads - all ancestors of parent = new csets
3612 new = [0] * len(repo)
3608 new = [0] * len(repo)
3613 cl = repo.changelog
3609 cl = repo.changelog
3614 for a in [cl.rev(n) for n in bheads]:
3610 for a in [cl.rev(n) for n in bheads]:
3615 new[a] = 1
3611 new[a] = 1
3616 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3612 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3617 new[a] = 1
3613 new[a] = 1
3618 for a in [p.rev() for p in parents]:
3614 for a in [p.rev() for p in parents]:
3619 if a >= 0:
3615 if a >= 0:
3620 new[a] = 0
3616 new[a] = 0
3621 for a in cl.ancestors(*[p.rev() for p in parents]):
3617 for a in cl.ancestors(*[p.rev() for p in parents]):
3622 new[a] = 0
3618 new[a] = 0
3623 new = sum(new)
3619 new = sum(new)
3624
3620
3625 if new == 0:
3621 if new == 0:
3626 ui.status(_('update: (current)\n'))
3622 ui.status(_('update: (current)\n'))
3627 elif pnode not in bheads:
3623 elif pnode not in bheads:
3628 ui.write(_('update: %d new changesets (update)\n') % new)
3624 ui.write(_('update: %d new changesets (update)\n') % new)
3629 else:
3625 else:
3630 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3626 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3631 (new, len(bheads)))
3627 (new, len(bheads)))
3632
3628
3633 if opts.get('remote'):
3629 if opts.get('remote'):
3634 t = []
3630 t = []
3635 source, branches = hg.parseurl(ui.expandpath('default'))
3631 source, branches = hg.parseurl(ui.expandpath('default'))
3636 other = hg.repository(hg.remoteui(repo, {}), source)
3632 other = hg.repository(hg.remoteui(repo, {}), source)
3637 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3633 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3638 ui.debug('comparing with %s\n' % url.hidepassword(source))
3634 ui.debug('comparing with %s\n' % url.hidepassword(source))
3639 repo.ui.pushbuffer()
3635 repo.ui.pushbuffer()
3640 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3636 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3641 repo.ui.popbuffer()
3637 repo.ui.popbuffer()
3642 if incoming:
3638 if incoming:
3643 t.append(_('1 or more incoming'))
3639 t.append(_('1 or more incoming'))
3644
3640
3645 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3641 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3646 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3642 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3647 other = hg.repository(hg.remoteui(repo, {}), dest)
3643 other = hg.repository(hg.remoteui(repo, {}), dest)
3648 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3644 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3649 repo.ui.pushbuffer()
3645 repo.ui.pushbuffer()
3650 o = discovery.findoutgoing(repo, other)
3646 o = discovery.findoutgoing(repo, other)
3651 repo.ui.popbuffer()
3647 repo.ui.popbuffer()
3652 o = repo.changelog.nodesbetween(o, None)[0]
3648 o = repo.changelog.nodesbetween(o, None)[0]
3653 if o:
3649 if o:
3654 t.append(_('%d outgoing') % len(o))
3650 t.append(_('%d outgoing') % len(o))
3655
3651
3656 if t:
3652 if t:
3657 ui.write(_('remote: %s\n') % (', '.join(t)))
3653 ui.write(_('remote: %s\n') % (', '.join(t)))
3658 else:
3654 else:
3659 ui.status(_('remote: (synced)\n'))
3655 ui.status(_('remote: (synced)\n'))
3660
3656
3661 def tag(ui, repo, name1, *names, **opts):
3657 def tag(ui, repo, name1, *names, **opts):
3662 """add one or more tags for the current or given revision
3658 """add one or more tags for the current or given revision
3663
3659
3664 Name a particular revision using <name>.
3660 Name a particular revision using <name>.
3665
3661
3666 Tags are used to name particular revisions of the repository and are
3662 Tags are used to name particular revisions of the repository and are
3667 very useful to compare different revisions, to go back to significant
3663 very useful to compare different revisions, to go back to significant
3668 earlier versions or to mark branch points as releases, etc. Changing
3664 earlier versions or to mark branch points as releases, etc. Changing
3669 an existing tag is normally disallowed; use -f/--force to override.
3665 an existing tag is normally disallowed; use -f/--force to override.
3670
3666
3671 If no revision is given, the parent of the working directory is
3667 If no revision is given, the parent of the working directory is
3672 used, or tip if no revision is checked out.
3668 used, or tip if no revision is checked out.
3673
3669
3674 To facilitate version control, distribution, and merging of tags,
3670 To facilitate version control, distribution, and merging of tags,
3675 they are stored as a file named ".hgtags" which is managed similarly
3671 they are stored as a file named ".hgtags" which is managed similarly
3676 to other project files and can be hand-edited if necessary. This
3672 to other project files and can be hand-edited if necessary. This
3677 also means that tagging creates a new commit. The file
3673 also means that tagging creates a new commit. The file
3678 ".hg/localtags" is used for local tags (not shared among
3674 ".hg/localtags" is used for local tags (not shared among
3679 repositories).
3675 repositories).
3680
3676
3681 Tag commits are usually made at the head of a branch. If the parent
3677 Tag commits are usually made at the head of a branch. If the parent
3682 of the working directory is not a branch head, :hg:`tag` aborts; use
3678 of the working directory is not a branch head, :hg:`tag` aborts; use
3683 -f/--force to force the tag commit to be based on a non-head
3679 -f/--force to force the tag commit to be based on a non-head
3684 changeset.
3680 changeset.
3685
3681
3686 See :hg:`help dates` for a list of formats valid for -d/--date.
3682 See :hg:`help dates` for a list of formats valid for -d/--date.
3687
3683
3688 Since tag names have priority over branch names during revision
3684 Since tag names have priority over branch names during revision
3689 lookup, using an existing branch name as a tag name is discouraged.
3685 lookup, using an existing branch name as a tag name is discouraged.
3690
3686
3691 Returns 0 on success.
3687 Returns 0 on success.
3692 """
3688 """
3693
3689
3694 rev_ = "."
3690 rev_ = "."
3695 names = [t.strip() for t in (name1,) + names]
3691 names = [t.strip() for t in (name1,) + names]
3696 if len(names) != len(set(names)):
3692 if len(names) != len(set(names)):
3697 raise util.Abort(_('tag names must be unique'))
3693 raise util.Abort(_('tag names must be unique'))
3698 for n in names:
3694 for n in names:
3699 if n in ['tip', '.', 'null']:
3695 if n in ['tip', '.', 'null']:
3700 raise util.Abort(_('the name \'%s\' is reserved') % n)
3696 raise util.Abort(_('the name \'%s\' is reserved') % n)
3701 if not n:
3697 if not n:
3702 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3698 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3703 if opts.get('rev') and opts.get('remove'):
3699 if opts.get('rev') and opts.get('remove'):
3704 raise util.Abort(_("--rev and --remove are incompatible"))
3700 raise util.Abort(_("--rev and --remove are incompatible"))
3705 if opts.get('rev'):
3701 if opts.get('rev'):
3706 rev_ = opts['rev']
3702 rev_ = opts['rev']
3707 message = opts.get('message')
3703 message = opts.get('message')
3708 if opts.get('remove'):
3704 if opts.get('remove'):
3709 expectedtype = opts.get('local') and 'local' or 'global'
3705 expectedtype = opts.get('local') and 'local' or 'global'
3710 for n in names:
3706 for n in names:
3711 if not repo.tagtype(n):
3707 if not repo.tagtype(n):
3712 raise util.Abort(_('tag \'%s\' does not exist') % n)
3708 raise util.Abort(_('tag \'%s\' does not exist') % n)
3713 if repo.tagtype(n) != expectedtype:
3709 if repo.tagtype(n) != expectedtype:
3714 if expectedtype == 'global':
3710 if expectedtype == 'global':
3715 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3711 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3716 else:
3712 else:
3717 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3713 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3718 rev_ = nullid
3714 rev_ = nullid
3719 if not message:
3715 if not message:
3720 # we don't translate commit messages
3716 # we don't translate commit messages
3721 message = 'Removed tag %s' % ', '.join(names)
3717 message = 'Removed tag %s' % ', '.join(names)
3722 elif not opts.get('force'):
3718 elif not opts.get('force'):
3723 for n in names:
3719 for n in names:
3724 if n in repo.tags():
3720 if n in repo.tags():
3725 raise util.Abort(_('tag \'%s\' already exists '
3721 raise util.Abort(_('tag \'%s\' already exists '
3726 '(use -f to force)') % n)
3722 '(use -f to force)') % n)
3727 if not opts.get('local'):
3723 if not opts.get('local'):
3728 p1, p2 = repo.dirstate.parents()
3724 p1, p2 = repo.dirstate.parents()
3729 if p2 != nullid:
3725 if p2 != nullid:
3730 raise util.Abort(_('uncommitted merge'))
3726 raise util.Abort(_('uncommitted merge'))
3731 bheads = repo.branchheads()
3727 bheads = repo.branchheads()
3732 if not opts.get('force') and bheads and p1 not in bheads:
3728 if not opts.get('force') and bheads and p1 not in bheads:
3733 raise util.Abort(_('not at a branch head (use -f to force)'))
3729 raise util.Abort(_('not at a branch head (use -f to force)'))
3734 r = cmdutil.revsingle(repo, rev_).node()
3730 r = cmdutil.revsingle(repo, rev_).node()
3735
3731
3736 if not message:
3732 if not message:
3737 # we don't translate commit messages
3733 # we don't translate commit messages
3738 message = ('Added tag %s for changeset %s' %
3734 message = ('Added tag %s for changeset %s' %
3739 (', '.join(names), short(r)))
3735 (', '.join(names), short(r)))
3740
3736
3741 date = opts.get('date')
3737 date = opts.get('date')
3742 if date:
3738 if date:
3743 date = util.parsedate(date)
3739 date = util.parsedate(date)
3744
3740
3745 if opts.get('edit'):
3741 if opts.get('edit'):
3746 message = ui.edit(message, ui.username())
3742 message = ui.edit(message, ui.username())
3747
3743
3748 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3744 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3749
3745
3750 def tags(ui, repo):
3746 def tags(ui, repo):
3751 """list repository tags
3747 """list repository tags
3752
3748
3753 This lists both regular and local tags. When the -v/--verbose
3749 This lists both regular and local tags. When the -v/--verbose
3754 switch is used, a third column "local" is printed for local tags.
3750 switch is used, a third column "local" is printed for local tags.
3755
3751
3756 Returns 0 on success.
3752 Returns 0 on success.
3757 """
3753 """
3758
3754
3759 hexfunc = ui.debugflag and hex or short
3755 hexfunc = ui.debugflag and hex or short
3760 tagtype = ""
3756 tagtype = ""
3761
3757
3762 for t, n in reversed(repo.tagslist()):
3758 for t, n in reversed(repo.tagslist()):
3763 if ui.quiet:
3759 if ui.quiet:
3764 ui.write("%s\n" % t)
3760 ui.write("%s\n" % t)
3765 continue
3761 continue
3766
3762
3767 try:
3763 try:
3768 hn = hexfunc(n)
3764 hn = hexfunc(n)
3769 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3765 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3770 except error.LookupError:
3766 except error.LookupError:
3771 r = " ?:%s" % hn
3767 r = " ?:%s" % hn
3772 else:
3768 else:
3773 spaces = " " * (30 - encoding.colwidth(t))
3769 spaces = " " * (30 - encoding.colwidth(t))
3774 if ui.verbose:
3770 if ui.verbose:
3775 if repo.tagtype(t) == 'local':
3771 if repo.tagtype(t) == 'local':
3776 tagtype = " local"
3772 tagtype = " local"
3777 else:
3773 else:
3778 tagtype = ""
3774 tagtype = ""
3779 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3775 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3780
3776
3781 def tip(ui, repo, **opts):
3777 def tip(ui, repo, **opts):
3782 """show the tip revision
3778 """show the tip revision
3783
3779
3784 The tip revision (usually just called the tip) is the changeset
3780 The tip revision (usually just called the tip) is the changeset
3785 most recently added to the repository (and therefore the most
3781 most recently added to the repository (and therefore the most
3786 recently changed head).
3782 recently changed head).
3787
3783
3788 If you have just made a commit, that commit will be the tip. If
3784 If you have just made a commit, that commit will be the tip. If
3789 you have just pulled changes from another repository, the tip of
3785 you have just pulled changes from another repository, the tip of
3790 that repository becomes the current tip. The "tip" tag is special
3786 that repository becomes the current tip. The "tip" tag is special
3791 and cannot be renamed or assigned to a different changeset.
3787 and cannot be renamed or assigned to a different changeset.
3792
3788
3793 Returns 0 on success.
3789 Returns 0 on success.
3794 """
3790 """
3795 displayer = cmdutil.show_changeset(ui, repo, opts)
3791 displayer = cmdutil.show_changeset(ui, repo, opts)
3796 displayer.show(repo[len(repo) - 1])
3792 displayer.show(repo[len(repo) - 1])
3797 displayer.close()
3793 displayer.close()
3798
3794
3799 def unbundle(ui, repo, fname1, *fnames, **opts):
3795 def unbundle(ui, repo, fname1, *fnames, **opts):
3800 """apply one or more changegroup files
3796 """apply one or more changegroup files
3801
3797
3802 Apply one or more compressed changegroup files generated by the
3798 Apply one or more compressed changegroup files generated by the
3803 bundle command.
3799 bundle command.
3804
3800
3805 Returns 0 on success, 1 if an update has unresolved files.
3801 Returns 0 on success, 1 if an update has unresolved files.
3806 """
3802 """
3807 fnames = (fname1,) + fnames
3803 fnames = (fname1,) + fnames
3808
3804
3809 lock = repo.lock()
3805 lock = repo.lock()
3810 try:
3806 try:
3811 for fname in fnames:
3807 for fname in fnames:
3812 f = url.open(ui, fname)
3808 f = url.open(ui, fname)
3813 gen = changegroup.readbundle(f, fname)
3809 gen = changegroup.readbundle(f, fname)
3814 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3810 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3815 lock=lock)
3811 lock=lock)
3816 finally:
3812 finally:
3817 lock.release()
3813 lock.release()
3818
3814
3819 return postincoming(ui, repo, modheads, opts.get('update'), None)
3815 return postincoming(ui, repo, modheads, opts.get('update'), None)
3820
3816
3821 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3817 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3822 """update working directory (or switch revisions)
3818 """update working directory (or switch revisions)
3823
3819
3824 Update the repository's working directory to the specified
3820 Update the repository's working directory to the specified
3825 changeset. If no changeset is specified, update to the tip of the
3821 changeset. If no changeset is specified, update to the tip of the
3826 current named branch.
3822 current named branch.
3827
3823
3828 If the changeset is not a descendant of the working directory's
3824 If the changeset is not a descendant of the working directory's
3829 parent, the update is aborted. With the -c/--check option, the
3825 parent, the update is aborted. With the -c/--check option, the
3830 working directory is checked for uncommitted changes; if none are
3826 working directory is checked for uncommitted changes; if none are
3831 found, the working directory is updated to the specified
3827 found, the working directory is updated to the specified
3832 changeset.
3828 changeset.
3833
3829
3834 The following rules apply when the working directory contains
3830 The following rules apply when the working directory contains
3835 uncommitted changes:
3831 uncommitted changes:
3836
3832
3837 1. If neither -c/--check nor -C/--clean is specified, and if
3833 1. If neither -c/--check nor -C/--clean is specified, and if
3838 the requested changeset is an ancestor or descendant of
3834 the requested changeset is an ancestor or descendant of
3839 the working directory's parent, the uncommitted changes
3835 the working directory's parent, the uncommitted changes
3840 are merged into the requested changeset and the merged
3836 are merged into the requested changeset and the merged
3841 result is left uncommitted. If the requested changeset is
3837 result is left uncommitted. If the requested changeset is
3842 not an ancestor or descendant (that is, it is on another
3838 not an ancestor or descendant (that is, it is on another
3843 branch), the update is aborted and the uncommitted changes
3839 branch), the update is aborted and the uncommitted changes
3844 are preserved.
3840 are preserved.
3845
3841
3846 2. With the -c/--check option, the update is aborted and the
3842 2. With the -c/--check option, the update is aborted and the
3847 uncommitted changes are preserved.
3843 uncommitted changes are preserved.
3848
3844
3849 3. With the -C/--clean option, uncommitted changes are discarded and
3845 3. With the -C/--clean option, uncommitted changes are discarded and
3850 the working directory is updated to the requested changeset.
3846 the working directory is updated to the requested changeset.
3851
3847
3852 Use null as the changeset to remove the working directory (like
3848 Use null as the changeset to remove the working directory (like
3853 :hg:`clone -U`).
3849 :hg:`clone -U`).
3854
3850
3855 If you want to update just one file to an older changeset, use
3851 If you want to update just one file to an older changeset, use
3856 :hg:`revert`.
3852 :hg:`revert`.
3857
3853
3858 See :hg:`help dates` for a list of formats valid for -d/--date.
3854 See :hg:`help dates` for a list of formats valid for -d/--date.
3859
3855
3860 Returns 0 on success, 1 if there are unresolved files.
3856 Returns 0 on success, 1 if there are unresolved files.
3861 """
3857 """
3862 if rev and node:
3858 if rev and node:
3863 raise util.Abort(_("please specify just one revision"))
3859 raise util.Abort(_("please specify just one revision"))
3864
3860
3865 if not rev:
3861 if not rev:
3866 rev = node
3862 rev = node
3867
3863
3868 rev = cmdutil.revsingle(repo, rev, rev).rev()
3864 rev = cmdutil.revsingle(repo, rev, rev).rev()
3869
3865
3870 if check and clean:
3866 if check and clean:
3871 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3867 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3872
3868
3873 if check:
3869 if check:
3874 # we could use dirty() but we can ignore merge and branch trivia
3870 # we could use dirty() but we can ignore merge and branch trivia
3875 c = repo[None]
3871 c = repo[None]
3876 if c.modified() or c.added() or c.removed():
3872 if c.modified() or c.added() or c.removed():
3877 raise util.Abort(_("uncommitted local changes"))
3873 raise util.Abort(_("uncommitted local changes"))
3878
3874
3879 if date:
3875 if date:
3880 if rev:
3876 if rev:
3881 raise util.Abort(_("you can't specify a revision and a date"))
3877 raise util.Abort(_("you can't specify a revision and a date"))
3882 rev = cmdutil.finddate(ui, repo, date)
3878 rev = cmdutil.finddate(ui, repo, date)
3883
3879
3884 if clean or check:
3880 if clean or check:
3885 return hg.clean(repo, rev)
3881 return hg.clean(repo, rev)
3886 else:
3882 else:
3887 return hg.update(repo, rev)
3883 return hg.update(repo, rev)
3888
3884
3889 def verify(ui, repo):
3885 def verify(ui, repo):
3890 """verify the integrity of the repository
3886 """verify the integrity of the repository
3891
3887
3892 Verify the integrity of the current repository.
3888 Verify the integrity of the current repository.
3893
3889
3894 This will perform an extensive check of the repository's
3890 This will perform an extensive check of the repository's
3895 integrity, validating the hashes and checksums of each entry in
3891 integrity, validating the hashes and checksums of each entry in
3896 the changelog, manifest, and tracked files, as well as the
3892 the changelog, manifest, and tracked files, as well as the
3897 integrity of their crosslinks and indices.
3893 integrity of their crosslinks and indices.
3898
3894
3899 Returns 0 on success, 1 if errors are encountered.
3895 Returns 0 on success, 1 if errors are encountered.
3900 """
3896 """
3901 return hg.verify(repo)
3897 return hg.verify(repo)
3902
3898
3903 def version_(ui):
3899 def version_(ui):
3904 """output version and copyright information"""
3900 """output version and copyright information"""
3905 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3901 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3906 % util.version())
3902 % util.version())
3907 ui.status(_(
3903 ui.status(_(
3908 "(see http://mercurial.selenic.com for more information)\n"
3904 "(see http://mercurial.selenic.com for more information)\n"
3909 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3905 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3910 "This is free software; see the source for copying conditions. "
3906 "This is free software; see the source for copying conditions. "
3911 "There is NO\nwarranty; "
3907 "There is NO\nwarranty; "
3912 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3908 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3913 ))
3909 ))
3914
3910
3915 # Command options and aliases are listed here, alphabetically
3911 # Command options and aliases are listed here, alphabetically
3916
3912
3917 globalopts = [
3913 globalopts = [
3918 ('R', 'repository', '',
3914 ('R', 'repository', '',
3919 _('repository root directory or name of overlay bundle file'),
3915 _('repository root directory or name of overlay bundle file'),
3920 _('REPO')),
3916 _('REPO')),
3921 ('', 'cwd', '',
3917 ('', 'cwd', '',
3922 _('change working directory'), _('DIR')),
3918 _('change working directory'), _('DIR')),
3923 ('y', 'noninteractive', None,
3919 ('y', 'noninteractive', None,
3924 _('do not prompt, assume \'yes\' for any required answers')),
3920 _('do not prompt, assume \'yes\' for any required answers')),
3925 ('q', 'quiet', None, _('suppress output')),
3921 ('q', 'quiet', None, _('suppress output')),
3926 ('v', 'verbose', None, _('enable additional output')),
3922 ('v', 'verbose', None, _('enable additional output')),
3927 ('', 'config', [],
3923 ('', 'config', [],
3928 _('set/override config option (use \'section.name=value\')'),
3924 _('set/override config option (use \'section.name=value\')'),
3929 _('CONFIG')),
3925 _('CONFIG')),
3930 ('', 'debug', None, _('enable debugging output')),
3926 ('', 'debug', None, _('enable debugging output')),
3931 ('', 'debugger', None, _('start debugger')),
3927 ('', 'debugger', None, _('start debugger')),
3932 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3928 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3933 _('ENCODE')),
3929 _('ENCODE')),
3934 ('', 'encodingmode', encoding.encodingmode,
3930 ('', 'encodingmode', encoding.encodingmode,
3935 _('set the charset encoding mode'), _('MODE')),
3931 _('set the charset encoding mode'), _('MODE')),
3936 ('', 'traceback', None, _('always print a traceback on exception')),
3932 ('', 'traceback', None, _('always print a traceback on exception')),
3937 ('', 'time', None, _('time how long the command takes')),
3933 ('', 'time', None, _('time how long the command takes')),
3938 ('', 'profile', None, _('print command execution profile')),
3934 ('', 'profile', None, _('print command execution profile')),
3939 ('', 'version', None, _('output version information and exit')),
3935 ('', 'version', None, _('output version information and exit')),
3940 ('h', 'help', None, _('display help and exit')),
3936 ('h', 'help', None, _('display help and exit')),
3941 ]
3937 ]
3942
3938
3943 dryrunopts = [('n', 'dry-run', None,
3939 dryrunopts = [('n', 'dry-run', None,
3944 _('do not perform actions, just print output'))]
3940 _('do not perform actions, just print output'))]
3945
3941
3946 remoteopts = [
3942 remoteopts = [
3947 ('e', 'ssh', '',
3943 ('e', 'ssh', '',
3948 _('specify ssh command to use'), _('CMD')),
3944 _('specify ssh command to use'), _('CMD')),
3949 ('', 'remotecmd', '',
3945 ('', 'remotecmd', '',
3950 _('specify hg command to run on the remote side'), _('CMD')),
3946 _('specify hg command to run on the remote side'), _('CMD')),
3951 ('', 'insecure', None,
3947 ('', 'insecure', None,
3952 _('do not verify server certificate (ignoring web.cacerts config)')),
3948 _('do not verify server certificate (ignoring web.cacerts config)')),
3953 ]
3949 ]
3954
3950
3955 walkopts = [
3951 walkopts = [
3956 ('I', 'include', [],
3952 ('I', 'include', [],
3957 _('include names matching the given patterns'), _('PATTERN')),
3953 _('include names matching the given patterns'), _('PATTERN')),
3958 ('X', 'exclude', [],
3954 ('X', 'exclude', [],
3959 _('exclude names matching the given patterns'), _('PATTERN')),
3955 _('exclude names matching the given patterns'), _('PATTERN')),
3960 ]
3956 ]
3961
3957
3962 commitopts = [
3958 commitopts = [
3963 ('m', 'message', '',
3959 ('m', 'message', '',
3964 _('use text as commit message'), _('TEXT')),
3960 _('use text as commit message'), _('TEXT')),
3965 ('l', 'logfile', '',
3961 ('l', 'logfile', '',
3966 _('read commit message from file'), _('FILE')),
3962 _('read commit message from file'), _('FILE')),
3967 ]
3963 ]
3968
3964
3969 commitopts2 = [
3965 commitopts2 = [
3970 ('d', 'date', '',
3966 ('d', 'date', '',
3971 _('record datecode as commit date'), _('DATE')),
3967 _('record datecode as commit date'), _('DATE')),
3972 ('u', 'user', '',
3968 ('u', 'user', '',
3973 _('record the specified user as committer'), _('USER')),
3969 _('record the specified user as committer'), _('USER')),
3974 ]
3970 ]
3975
3971
3976 templateopts = [
3972 templateopts = [
3977 ('', 'style', '',
3973 ('', 'style', '',
3978 _('display using template map file'), _('STYLE')),
3974 _('display using template map file'), _('STYLE')),
3979 ('', 'template', '',
3975 ('', 'template', '',
3980 _('display with template'), _('TEMPLATE')),
3976 _('display with template'), _('TEMPLATE')),
3981 ]
3977 ]
3982
3978
3983 logopts = [
3979 logopts = [
3984 ('p', 'patch', None, _('show patch')),
3980 ('p', 'patch', None, _('show patch')),
3985 ('g', 'git', None, _('use git extended diff format')),
3981 ('g', 'git', None, _('use git extended diff format')),
3986 ('l', 'limit', '',
3982 ('l', 'limit', '',
3987 _('limit number of changes displayed'), _('NUM')),
3983 _('limit number of changes displayed'), _('NUM')),
3988 ('M', 'no-merges', None, _('do not show merges')),
3984 ('M', 'no-merges', None, _('do not show merges')),
3989 ('', 'stat', None, _('output diffstat-style summary of changes')),
3985 ('', 'stat', None, _('output diffstat-style summary of changes')),
3990 ] + templateopts
3986 ] + templateopts
3991
3987
3992 diffopts = [
3988 diffopts = [
3993 ('a', 'text', None, _('treat all files as text')),
3989 ('a', 'text', None, _('treat all files as text')),
3994 ('g', 'git', None, _('use git extended diff format')),
3990 ('g', 'git', None, _('use git extended diff format')),
3995 ('', 'nodates', None, _('omit dates from diff headers'))
3991 ('', 'nodates', None, _('omit dates from diff headers'))
3996 ]
3992 ]
3997
3993
3998 diffopts2 = [
3994 diffopts2 = [
3999 ('p', 'show-function', None, _('show which function each change is in')),
3995 ('p', 'show-function', None, _('show which function each change is in')),
4000 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3996 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4001 ('w', 'ignore-all-space', None,
3997 ('w', 'ignore-all-space', None,
4002 _('ignore white space when comparing lines')),
3998 _('ignore white space when comparing lines')),
4003 ('b', 'ignore-space-change', None,
3999 ('b', 'ignore-space-change', None,
4004 _('ignore changes in the amount of white space')),
4000 _('ignore changes in the amount of white space')),
4005 ('B', 'ignore-blank-lines', None,
4001 ('B', 'ignore-blank-lines', None,
4006 _('ignore changes whose lines are all blank')),
4002 _('ignore changes whose lines are all blank')),
4007 ('U', 'unified', '',
4003 ('U', 'unified', '',
4008 _('number of lines of context to show'), _('NUM')),
4004 _('number of lines of context to show'), _('NUM')),
4009 ('', 'stat', None, _('output diffstat-style summary of changes')),
4005 ('', 'stat', None, _('output diffstat-style summary of changes')),
4010 ]
4006 ]
4011
4007
4012 similarityopts = [
4008 similarityopts = [
4013 ('s', 'similarity', '',
4009 ('s', 'similarity', '',
4014 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4010 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4015 ]
4011 ]
4016
4012
4017 subrepoopts = [
4013 subrepoopts = [
4018 ('S', 'subrepos', None,
4014 ('S', 'subrepos', None,
4019 _('recurse into subrepositories'))
4015 _('recurse into subrepositories'))
4020 ]
4016 ]
4021
4017
4022 table = {
4018 table = {
4023 "^add": (add, walkopts + subrepoopts + dryrunopts,
4019 "^add": (add, walkopts + subrepoopts + dryrunopts,
4024 _('[OPTION]... [FILE]...')),
4020 _('[OPTION]... [FILE]...')),
4025 "addremove":
4021 "addremove":
4026 (addremove, similarityopts + walkopts + dryrunopts,
4022 (addremove, similarityopts + walkopts + dryrunopts,
4027 _('[OPTION]... [FILE]...')),
4023 _('[OPTION]... [FILE]...')),
4028 "^annotate|blame":
4024 "^annotate|blame":
4029 (annotate,
4025 (annotate,
4030 [('r', 'rev', '',
4026 [('r', 'rev', '',
4031 _('annotate the specified revision'), _('REV')),
4027 _('annotate the specified revision'), _('REV')),
4032 ('', 'follow', None,
4028 ('', 'follow', None,
4033 _('follow copies/renames and list the filename (DEPRECATED)')),
4029 _('follow copies/renames and list the filename (DEPRECATED)')),
4034 ('', 'no-follow', None, _("don't follow copies and renames")),
4030 ('', 'no-follow', None, _("don't follow copies and renames")),
4035 ('a', 'text', None, _('treat all files as text')),
4031 ('a', 'text', None, _('treat all files as text')),
4036 ('u', 'user', None, _('list the author (long with -v)')),
4032 ('u', 'user', None, _('list the author (long with -v)')),
4037 ('f', 'file', None, _('list the filename')),
4033 ('f', 'file', None, _('list the filename')),
4038 ('d', 'date', None, _('list the date (short with -q)')),
4034 ('d', 'date', None, _('list the date (short with -q)')),
4039 ('n', 'number', None, _('list the revision number (default)')),
4035 ('n', 'number', None, _('list the revision number (default)')),
4040 ('c', 'changeset', None, _('list the changeset')),
4036 ('c', 'changeset', None, _('list the changeset')),
4041 ('l', 'line-number', None,
4037 ('l', 'line-number', None,
4042 _('show line number at the first appearance'))
4038 _('show line number at the first appearance'))
4043 ] + walkopts,
4039 ] + walkopts,
4044 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4040 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4045 "archive":
4041 "archive":
4046 (archive,
4042 (archive,
4047 [('', 'no-decode', None, _('do not pass files through decoders')),
4043 [('', 'no-decode', None, _('do not pass files through decoders')),
4048 ('p', 'prefix', '',
4044 ('p', 'prefix', '',
4049 _('directory prefix for files in archive'), _('PREFIX')),
4045 _('directory prefix for files in archive'), _('PREFIX')),
4050 ('r', 'rev', '',
4046 ('r', 'rev', '',
4051 _('revision to distribute'), _('REV')),
4047 _('revision to distribute'), _('REV')),
4052 ('t', 'type', '',
4048 ('t', 'type', '',
4053 _('type of distribution to create'), _('TYPE')),
4049 _('type of distribution to create'), _('TYPE')),
4054 ] + subrepoopts + walkopts,
4050 ] + subrepoopts + walkopts,
4055 _('[OPTION]... DEST')),
4051 _('[OPTION]... DEST')),
4056 "backout":
4052 "backout":
4057 (backout,
4053 (backout,
4058 [('', 'merge', None,
4054 [('', 'merge', None,
4059 _('merge with old dirstate parent after backout')),
4055 _('merge with old dirstate parent after backout')),
4060 ('', 'parent', '',
4056 ('', 'parent', '',
4061 _('parent to choose when backing out merge'), _('REV')),
4057 _('parent to choose when backing out merge'), _('REV')),
4062 ('t', 'tool', '',
4058 ('t', 'tool', '',
4063 _('specify merge tool')),
4059 _('specify merge tool')),
4064 ('r', 'rev', '',
4060 ('r', 'rev', '',
4065 _('revision to backout'), _('REV')),
4061 _('revision to backout'), _('REV')),
4066 ] + walkopts + commitopts + commitopts2,
4062 ] + walkopts + commitopts + commitopts2,
4067 _('[OPTION]... [-r] REV')),
4063 _('[OPTION]... [-r] REV')),
4068 "bisect":
4064 "bisect":
4069 (bisect,
4065 (bisect,
4070 [('r', 'reset', False, _('reset bisect state')),
4066 [('r', 'reset', False, _('reset bisect state')),
4071 ('g', 'good', False, _('mark changeset good')),
4067 ('g', 'good', False, _('mark changeset good')),
4072 ('b', 'bad', False, _('mark changeset bad')),
4068 ('b', 'bad', False, _('mark changeset bad')),
4073 ('s', 'skip', False, _('skip testing changeset')),
4069 ('s', 'skip', False, _('skip testing changeset')),
4074 ('c', 'command', '',
4070 ('c', 'command', '',
4075 _('use command to check changeset state'), _('CMD')),
4071 _('use command to check changeset state'), _('CMD')),
4076 ('U', 'noupdate', False, _('do not update to target'))],
4072 ('U', 'noupdate', False, _('do not update to target'))],
4077 _("[-gbsr] [-U] [-c CMD] [REV]")),
4073 _("[-gbsr] [-U] [-c CMD] [REV]")),
4078 "branch":
4074 "branch":
4079 (branch,
4075 (branch,
4080 [('f', 'force', None,
4076 [('f', 'force', None,
4081 _('set branch name even if it shadows an existing branch')),
4077 _('set branch name even if it shadows an existing branch')),
4082 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4078 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4083 _('[-fC] [NAME]')),
4079 _('[-fC] [NAME]')),
4084 "branches":
4080 "branches":
4085 (branches,
4081 (branches,
4086 [('a', 'active', False,
4082 [('a', 'active', False,
4087 _('show only branches that have unmerged heads')),
4083 _('show only branches that have unmerged heads')),
4088 ('c', 'closed', False,
4084 ('c', 'closed', False,
4089 _('show normal and closed branches'))],
4085 _('show normal and closed branches'))],
4090 _('[-ac]')),
4086 _('[-ac]')),
4091 "bundle":
4087 "bundle":
4092 (bundle,
4088 (bundle,
4093 [('f', 'force', None,
4089 [('f', 'force', None,
4094 _('run even when the destination is unrelated')),
4090 _('run even when the destination is unrelated')),
4095 ('r', 'rev', [],
4091 ('r', 'rev', [],
4096 _('a changeset intended to be added to the destination'),
4092 _('a changeset intended to be added to the destination'),
4097 _('REV')),
4093 _('REV')),
4098 ('b', 'branch', [],
4094 ('b', 'branch', [],
4099 _('a specific branch you would like to bundle'),
4095 _('a specific branch you would like to bundle'),
4100 _('BRANCH')),
4096 _('BRANCH')),
4101 ('', 'base', [],
4097 ('', 'base', [],
4102 _('a base changeset assumed to be available at the destination'),
4098 _('a base changeset assumed to be available at the destination'),
4103 _('REV')),
4099 _('REV')),
4104 ('a', 'all', None, _('bundle all changesets in the repository')),
4100 ('a', 'all', None, _('bundle all changesets in the repository')),
4105 ('t', 'type', 'bzip2',
4101 ('t', 'type', 'bzip2',
4106 _('bundle compression type to use'), _('TYPE')),
4102 _('bundle compression type to use'), _('TYPE')),
4107 ] + remoteopts,
4103 ] + remoteopts,
4108 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4104 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4109 "cat":
4105 "cat":
4110 (cat,
4106 (cat,
4111 [('o', 'output', '',
4107 [('o', 'output', '',
4112 _('print output to file with formatted name'), _('FORMAT')),
4108 _('print output to file with formatted name'), _('FORMAT')),
4113 ('r', 'rev', '',
4109 ('r', 'rev', '',
4114 _('print the given revision'), _('REV')),
4110 _('print the given revision'), _('REV')),
4115 ('', 'decode', None, _('apply any matching decode filter')),
4111 ('', 'decode', None, _('apply any matching decode filter')),
4116 ] + walkopts,
4112 ] + walkopts,
4117 _('[OPTION]... FILE...')),
4113 _('[OPTION]... FILE...')),
4118 "^clone":
4114 "^clone":
4119 (clone,
4115 (clone,
4120 [('U', 'noupdate', None,
4116 [('U', 'noupdate', None,
4121 _('the clone will include an empty working copy (only a repository)')),
4117 _('the clone will include an empty working copy (only a repository)')),
4122 ('u', 'updaterev', '',
4118 ('u', 'updaterev', '',
4123 _('revision, tag or branch to check out'), _('REV')),
4119 _('revision, tag or branch to check out'), _('REV')),
4124 ('r', 'rev', [],
4120 ('r', 'rev', [],
4125 _('include the specified changeset'), _('REV')),
4121 _('include the specified changeset'), _('REV')),
4126 ('b', 'branch', [],
4122 ('b', 'branch', [],
4127 _('clone only the specified branch'), _('BRANCH')),
4123 _('clone only the specified branch'), _('BRANCH')),
4128 ('', 'pull', None, _('use pull protocol to copy metadata')),
4124 ('', 'pull', None, _('use pull protocol to copy metadata')),
4129 ('', 'uncompressed', None,
4125 ('', 'uncompressed', None,
4130 _('use uncompressed transfer (fast over LAN)')),
4126 _('use uncompressed transfer (fast over LAN)')),
4131 ] + remoteopts,
4127 ] + remoteopts,
4132 _('[OPTION]... SOURCE [DEST]')),
4128 _('[OPTION]... SOURCE [DEST]')),
4133 "^commit|ci":
4129 "^commit|ci":
4134 (commit,
4130 (commit,
4135 [('A', 'addremove', None,
4131 [('A', 'addremove', None,
4136 _('mark new/missing files as added/removed before committing')),
4132 _('mark new/missing files as added/removed before committing')),
4137 ('', 'close-branch', None,
4133 ('', 'close-branch', None,
4138 _('mark a branch as closed, hiding it from the branch list')),
4134 _('mark a branch as closed, hiding it from the branch list')),
4139 ] + walkopts + commitopts + commitopts2,
4135 ] + walkopts + commitopts + commitopts2,
4140 _('[OPTION]... [FILE]...')),
4136 _('[OPTION]... [FILE]...')),
4141 "copy|cp":
4137 "copy|cp":
4142 (copy,
4138 (copy,
4143 [('A', 'after', None, _('record a copy that has already occurred')),
4139 [('A', 'after', None, _('record a copy that has already occurred')),
4144 ('f', 'force', None,
4140 ('f', 'force', None,
4145 _('forcibly copy over an existing managed file')),
4141 _('forcibly copy over an existing managed file')),
4146 ] + walkopts + dryrunopts,
4142 ] + walkopts + dryrunopts,
4147 _('[OPTION]... [SOURCE]... DEST')),
4143 _('[OPTION]... [SOURCE]... DEST')),
4148 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4144 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4149 "debugbuilddag":
4145 "debugbuilddag":
4150 (debugbuilddag,
4146 (debugbuilddag,
4151 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4147 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4152 ('a', 'appended-file', None, _('add single file all revs append to')),
4148 ('a', 'appended-file', None, _('add single file all revs append to')),
4153 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4149 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4154 ('n', 'new-file', None, _('add new file at each rev')),
4150 ('n', 'new-file', None, _('add new file at each rev')),
4155 ],
4151 ],
4156 _('[OPTION]... TEXT')),
4152 _('[OPTION]... TEXT')),
4157 "debugcheckstate": (debugcheckstate, [], ''),
4153 "debugcheckstate": (debugcheckstate, [], ''),
4158 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4154 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4159 "debugcomplete":
4155 "debugcomplete":
4160 (debugcomplete,
4156 (debugcomplete,
4161 [('o', 'options', None, _('show the command options'))],
4157 [('o', 'options', None, _('show the command options'))],
4162 _('[-o] CMD')),
4158 _('[-o] CMD')),
4163 "debugdag":
4159 "debugdag":
4164 (debugdag,
4160 (debugdag,
4165 [('t', 'tags', None, _('use tags as labels')),
4161 [('t', 'tags', None, _('use tags as labels')),
4166 ('b', 'branches', None, _('annotate with branch names')),
4162 ('b', 'branches', None, _('annotate with branch names')),
4167 ('', 'dots', None, _('use dots for runs')),
4163 ('', 'dots', None, _('use dots for runs')),
4168 ('s', 'spaces', None, _('separate elements by spaces')),
4164 ('s', 'spaces', None, _('separate elements by spaces')),
4169 ],
4165 ],
4170 _('[OPTION]... [FILE [REV]...]')),
4166 _('[OPTION]... [FILE [REV]...]')),
4171 "debugdate":
4167 "debugdate":
4172 (debugdate,
4168 (debugdate,
4173 [('e', 'extended', None, _('try extended date formats'))],
4169 [('e', 'extended', None, _('try extended date formats'))],
4174 _('[-e] DATE [RANGE]')),
4170 _('[-e] DATE [RANGE]')),
4175 "debugdata": (debugdata, [], _('FILE REV')),
4171 "debugdata": (debugdata, [], _('FILE REV')),
4176 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4172 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4177 "debugindex": (debugindex,
4173 "debugindex": (debugindex,
4178 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4174 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4179 _('FILE')),
4175 _('FILE')),
4180 "debugindexdot": (debugindexdot, [], _('FILE')),
4176 "debugindexdot": (debugindexdot, [], _('FILE')),
4181 "debuginstall": (debuginstall, [], ''),
4177 "debuginstall": (debuginstall, [], ''),
4182 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4178 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4183 "debugrebuildstate":
4179 "debugrebuildstate":
4184 (debugrebuildstate,
4180 (debugrebuildstate,
4185 [('r', 'rev', '',
4181 [('r', 'rev', '',
4186 _('revision to rebuild to'), _('REV'))],
4182 _('revision to rebuild to'), _('REV'))],
4187 _('[-r REV] [REV]')),
4183 _('[-r REV] [REV]')),
4188 "debugrename":
4184 "debugrename":
4189 (debugrename,
4185 (debugrename,
4190 [('r', 'rev', '',
4186 [('r', 'rev', '',
4191 _('revision to debug'), _('REV'))],
4187 _('revision to debug'), _('REV'))],
4192 _('[-r REV] FILE')),
4188 _('[-r REV] FILE')),
4193 "debugrevspec":
4189 "debugrevspec":
4194 (debugrevspec, [], ('REVSPEC')),
4190 (debugrevspec, [], ('REVSPEC')),
4195 "debugsetparents":
4191 "debugsetparents":
4196 (debugsetparents, [], _('REV1 [REV2]')),
4192 (debugsetparents, [], _('REV1 [REV2]')),
4197 "debugstate":
4193 "debugstate":
4198 (debugstate,
4194 (debugstate,
4199 [('', 'nodates', None, _('do not display the saved mtime'))],
4195 [('', 'nodates', None, _('do not display the saved mtime'))],
4200 _('[OPTION]...')),
4196 _('[OPTION]...')),
4201 "debugsub":
4197 "debugsub":
4202 (debugsub,
4198 (debugsub,
4203 [('r', 'rev', '',
4199 [('r', 'rev', '',
4204 _('revision to check'), _('REV'))],
4200 _('revision to check'), _('REV'))],
4205 _('[-r REV] [REV]')),
4201 _('[-r REV] [REV]')),
4206 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4202 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4207 "^diff":
4203 "^diff":
4208 (diff,
4204 (diff,
4209 [('r', 'rev', [],
4205 [('r', 'rev', [],
4210 _('revision'), _('REV')),
4206 _('revision'), _('REV')),
4211 ('c', 'change', '',
4207 ('c', 'change', '',
4212 _('change made by revision'), _('REV'))
4208 _('change made by revision'), _('REV'))
4213 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4209 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4214 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4210 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4215 "^export":
4211 "^export":
4216 (export,
4212 (export,
4217 [('o', 'output', '',
4213 [('o', 'output', '',
4218 _('print output to file with formatted name'), _('FORMAT')),
4214 _('print output to file with formatted name'), _('FORMAT')),
4219 ('', 'switch-parent', None, _('diff against the second parent')),
4215 ('', 'switch-parent', None, _('diff against the second parent')),
4220 ('r', 'rev', [],
4216 ('r', 'rev', [],
4221 _('revisions to export'), _('REV')),
4217 _('revisions to export'), _('REV')),
4222 ] + diffopts,
4218 ] + diffopts,
4223 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4219 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4224 "^forget":
4220 "^forget":
4225 (forget,
4221 (forget,
4226 [] + walkopts,
4222 [] + walkopts,
4227 _('[OPTION]... FILE...')),
4223 _('[OPTION]... FILE...')),
4228 "grep":
4224 "grep":
4229 (grep,
4225 (grep,
4230 [('0', 'print0', None, _('end fields with NUL')),
4226 [('0', 'print0', None, _('end fields with NUL')),
4231 ('', 'all', None, _('print all revisions that match')),
4227 ('', 'all', None, _('print all revisions that match')),
4232 ('f', 'follow', None,
4228 ('f', 'follow', None,
4233 _('follow changeset history,'
4229 _('follow changeset history,'
4234 ' or file history across copies and renames')),
4230 ' or file history across copies and renames')),
4235 ('i', 'ignore-case', None, _('ignore case when matching')),
4231 ('i', 'ignore-case', None, _('ignore case when matching')),
4236 ('l', 'files-with-matches', None,
4232 ('l', 'files-with-matches', None,
4237 _('print only filenames and revisions that match')),
4233 _('print only filenames and revisions that match')),
4238 ('n', 'line-number', None, _('print matching line numbers')),
4234 ('n', 'line-number', None, _('print matching line numbers')),
4239 ('r', 'rev', [],
4235 ('r', 'rev', [],
4240 _('only search files changed within revision range'), _('REV')),
4236 _('only search files changed within revision range'), _('REV')),
4241 ('u', 'user', None, _('list the author (long with -v)')),
4237 ('u', 'user', None, _('list the author (long with -v)')),
4242 ('d', 'date', None, _('list the date (short with -q)')),
4238 ('d', 'date', None, _('list the date (short with -q)')),
4243 ] + walkopts,
4239 ] + walkopts,
4244 _('[OPTION]... PATTERN [FILE]...')),
4240 _('[OPTION]... PATTERN [FILE]...')),
4245 "heads":
4241 "heads":
4246 (heads,
4242 (heads,
4247 [('r', 'rev', '',
4243 [('r', 'rev', '',
4248 _('show only heads which are descendants of STARTREV'),
4244 _('show only heads which are descendants of STARTREV'),
4249 _('STARTREV')),
4245 _('STARTREV')),
4250 ('t', 'topo', False, _('show topological heads only')),
4246 ('t', 'topo', False, _('show topological heads only')),
4251 ('a', 'active', False,
4247 ('a', 'active', False,
4252 _('show active branchheads only (DEPRECATED)')),
4248 _('show active branchheads only (DEPRECATED)')),
4253 ('c', 'closed', False,
4249 ('c', 'closed', False,
4254 _('show normal and closed branch heads')),
4250 _('show normal and closed branch heads')),
4255 ] + templateopts,
4251 ] + templateopts,
4256 _('[-ac] [-r STARTREV] [REV]...')),
4252 _('[-ac] [-r STARTREV] [REV]...')),
4257 "help": (help_, [], _('[TOPIC]')),
4253 "help": (help_, [], _('[TOPIC]')),
4258 "identify|id":
4254 "identify|id":
4259 (identify,
4255 (identify,
4260 [('r', 'rev', '',
4256 [('r', 'rev', '',
4261 _('identify the specified revision'), _('REV')),
4257 _('identify the specified revision'), _('REV')),
4262 ('n', 'num', None, _('show local revision number')),
4258 ('n', 'num', None, _('show local revision number')),
4263 ('i', 'id', None, _('show global revision id')),
4259 ('i', 'id', None, _('show global revision id')),
4264 ('b', 'branch', None, _('show branch')),
4260 ('b', 'branch', None, _('show branch')),
4265 ('t', 'tags', None, _('show tags'))],
4261 ('t', 'tags', None, _('show tags'))],
4266 _('[-nibt] [-r REV] [SOURCE]')),
4262 _('[-nibt] [-r REV] [SOURCE]')),
4267 "import|patch":
4263 "import|patch":
4268 (import_,
4264 (import_,
4269 [('p', 'strip', 1,
4265 [('p', 'strip', 1,
4270 _('directory strip option for patch. This has the same '
4266 _('directory strip option for patch. This has the same '
4271 'meaning as the corresponding patch option'),
4267 'meaning as the corresponding patch option'),
4272 _('NUM')),
4268 _('NUM')),
4273 ('b', 'base', '',
4269 ('b', 'base', '',
4274 _('base path'), _('PATH')),
4270 _('base path'), _('PATH')),
4275 ('f', 'force', None,
4271 ('f', 'force', None,
4276 _('skip check for outstanding uncommitted changes')),
4272 _('skip check for outstanding uncommitted changes')),
4277 ('', 'no-commit', None,
4273 ('', 'no-commit', None,
4278 _("don't commit, just update the working directory")),
4274 _("don't commit, just update the working directory")),
4279 ('', 'exact', None,
4275 ('', 'exact', None,
4280 _('apply patch to the nodes from which it was generated')),
4276 _('apply patch to the nodes from which it was generated')),
4281 ('', 'import-branch', None,
4277 ('', 'import-branch', None,
4282 _('use any branch information in patch (implied by --exact)'))] +
4278 _('use any branch information in patch (implied by --exact)'))] +
4283 commitopts + commitopts2 + similarityopts,
4279 commitopts + commitopts2 + similarityopts,
4284 _('[OPTION]... PATCH...')),
4280 _('[OPTION]... PATCH...')),
4285 "incoming|in":
4281 "incoming|in":
4286 (incoming,
4282 (incoming,
4287 [('f', 'force', None,
4283 [('f', 'force', None,
4288 _('run even if remote repository is unrelated')),
4284 _('run even if remote repository is unrelated')),
4289 ('n', 'newest-first', None, _('show newest record first')),
4285 ('n', 'newest-first', None, _('show newest record first')),
4290 ('', 'bundle', '',
4286 ('', 'bundle', '',
4291 _('file to store the bundles into'), _('FILE')),
4287 _('file to store the bundles into'), _('FILE')),
4292 ('r', 'rev', [],
4288 ('r', 'rev', [],
4293 _('a remote changeset intended to be added'), _('REV')),
4289 _('a remote changeset intended to be added'), _('REV')),
4294 ('b', 'branch', [],
4290 ('b', 'branch', [],
4295 _('a specific branch you would like to pull'), _('BRANCH')),
4291 _('a specific branch you would like to pull'), _('BRANCH')),
4296 ] + logopts + remoteopts + subrepoopts,
4292 ] + logopts + remoteopts + subrepoopts,
4297 _('[-p] [-n] [-M] [-f] [-r REV]...'
4293 _('[-p] [-n] [-M] [-f] [-r REV]...'
4298 ' [--bundle FILENAME] [SOURCE]')),
4294 ' [--bundle FILENAME] [SOURCE]')),
4299 "^init":
4295 "^init":
4300 (init,
4296 (init,
4301 remoteopts,
4297 remoteopts,
4302 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4298 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4303 "locate":
4299 "locate":
4304 (locate,
4300 (locate,
4305 [('r', 'rev', '',
4301 [('r', 'rev', '',
4306 _('search the repository as it is in REV'), _('REV')),
4302 _('search the repository as it is in REV'), _('REV')),
4307 ('0', 'print0', None,
4303 ('0', 'print0', None,
4308 _('end filenames with NUL, for use with xargs')),
4304 _('end filenames with NUL, for use with xargs')),
4309 ('f', 'fullpath', None,
4305 ('f', 'fullpath', None,
4310 _('print complete paths from the filesystem root')),
4306 _('print complete paths from the filesystem root')),
4311 ] + walkopts,
4307 ] + walkopts,
4312 _('[OPTION]... [PATTERN]...')),
4308 _('[OPTION]... [PATTERN]...')),
4313 "^log|history":
4309 "^log|history":
4314 (log,
4310 (log,
4315 [('f', 'follow', None,
4311 [('f', 'follow', None,
4316 _('follow changeset history,'
4312 _('follow changeset history,'
4317 ' or file history across copies and renames')),
4313 ' or file history across copies and renames')),
4318 ('', 'follow-first', None,
4314 ('', 'follow-first', None,
4319 _('only follow the first parent of merge changesets')),
4315 _('only follow the first parent of merge changesets')),
4320 ('d', 'date', '',
4316 ('d', 'date', '',
4321 _('show revisions matching date spec'), _('DATE')),
4317 _('show revisions matching date spec'), _('DATE')),
4322 ('C', 'copies', None, _('show copied files')),
4318 ('C', 'copies', None, _('show copied files')),
4323 ('k', 'keyword', [],
4319 ('k', 'keyword', [],
4324 _('do case-insensitive search for a given text'), _('TEXT')),
4320 _('do case-insensitive search for a given text'), _('TEXT')),
4325 ('r', 'rev', [],
4321 ('r', 'rev', [],
4326 _('show the specified revision or range'), _('REV')),
4322 _('show the specified revision or range'), _('REV')),
4327 ('', 'removed', None, _('include revisions where files were removed')),
4323 ('', 'removed', None, _('include revisions where files were removed')),
4328 ('m', 'only-merges', None, _('show only merges')),
4324 ('m', 'only-merges', None, _('show only merges')),
4329 ('u', 'user', [],
4325 ('u', 'user', [],
4330 _('revisions committed by user'), _('USER')),
4326 _('revisions committed by user'), _('USER')),
4331 ('', 'only-branch', [],
4327 ('', 'only-branch', [],
4332 _('show only changesets within the given named branch (DEPRECATED)'),
4328 _('show only changesets within the given named branch (DEPRECATED)'),
4333 _('BRANCH')),
4329 _('BRANCH')),
4334 ('b', 'branch', [],
4330 ('b', 'branch', [],
4335 _('show changesets within the given named branch'), _('BRANCH')),
4331 _('show changesets within the given named branch'), _('BRANCH')),
4336 ('P', 'prune', [],
4332 ('P', 'prune', [],
4337 _('do not display revision or any of its ancestors'), _('REV')),
4333 _('do not display revision or any of its ancestors'), _('REV')),
4338 ] + logopts + walkopts,
4334 ] + logopts + walkopts,
4339 _('[OPTION]... [FILE]')),
4335 _('[OPTION]... [FILE]')),
4340 "manifest":
4336 "manifest":
4341 (manifest,
4337 (manifest,
4342 [('r', 'rev', '',
4338 [('r', 'rev', '',
4343 _('revision to display'), _('REV'))],
4339 _('revision to display'), _('REV'))],
4344 _('[-r REV]')),
4340 _('[-r REV]')),
4345 "^merge":
4341 "^merge":
4346 (merge,
4342 (merge,
4347 [('f', 'force', None, _('force a merge with outstanding changes')),
4343 [('f', 'force', None, _('force a merge with outstanding changes')),
4348 ('t', 'tool', '', _('specify merge tool')),
4344 ('t', 'tool', '', _('specify merge tool')),
4349 ('r', 'rev', '',
4345 ('r', 'rev', '',
4350 _('revision to merge'), _('REV')),
4346 _('revision to merge'), _('REV')),
4351 ('P', 'preview', None,
4347 ('P', 'preview', None,
4352 _('review revisions to merge (no merge is performed)'))],
4348 _('review revisions to merge (no merge is performed)'))],
4353 _('[-P] [-f] [[-r] REV]')),
4349 _('[-P] [-f] [[-r] REV]')),
4354 "outgoing|out":
4350 "outgoing|out":
4355 (outgoing,
4351 (outgoing,
4356 [('f', 'force', None,
4352 [('f', 'force', None,
4357 _('run even when the destination is unrelated')),
4353 _('run even when the destination is unrelated')),
4358 ('r', 'rev', [],
4354 ('r', 'rev', [],
4359 _('a changeset intended to be included in the destination'),
4355 _('a changeset intended to be included in the destination'),
4360 _('REV')),
4356 _('REV')),
4361 ('n', 'newest-first', None, _('show newest record first')),
4357 ('n', 'newest-first', None, _('show newest record first')),
4362 ('b', 'branch', [],
4358 ('b', 'branch', [],
4363 _('a specific branch you would like to push'), _('BRANCH')),
4359 _('a specific branch you would like to push'), _('BRANCH')),
4364 ] + logopts + remoteopts + subrepoopts,
4360 ] + logopts + remoteopts + subrepoopts,
4365 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4361 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4366 "parents":
4362 "parents":
4367 (parents,
4363 (parents,
4368 [('r', 'rev', '',
4364 [('r', 'rev', '',
4369 _('show parents of the specified revision'), _('REV')),
4365 _('show parents of the specified revision'), _('REV')),
4370 ] + templateopts,
4366 ] + templateopts,
4371 _('[-r REV] [FILE]')),
4367 _('[-r REV] [FILE]')),
4372 "paths": (paths, [], _('[NAME]')),
4368 "paths": (paths, [], _('[NAME]')),
4373 "^pull":
4369 "^pull":
4374 (pull,
4370 (pull,
4375 [('u', 'update', None,
4371 [('u', 'update', None,
4376 _('update to new branch head if changesets were pulled')),
4372 _('update to new branch head if changesets were pulled')),
4377 ('f', 'force', None,
4373 ('f', 'force', None,
4378 _('run even when remote repository is unrelated')),
4374 _('run even when remote repository is unrelated')),
4379 ('r', 'rev', [],
4375 ('r', 'rev', [],
4380 _('a remote changeset intended to be added'), _('REV')),
4376 _('a remote changeset intended to be added'), _('REV')),
4381 ('b', 'branch', [],
4377 ('b', 'branch', [],
4382 _('a specific branch you would like to pull'), _('BRANCH')),
4378 _('a specific branch you would like to pull'), _('BRANCH')),
4383 ] + remoteopts,
4379 ] + remoteopts,
4384 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4380 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4385 "^push":
4381 "^push":
4386 (push,
4382 (push,
4387 [('f', 'force', None, _('force push')),
4383 [('f', 'force', None, _('force push')),
4388 ('r', 'rev', [],
4384 ('r', 'rev', [],
4389 _('a changeset intended to be included in the destination'),
4385 _('a changeset intended to be included in the destination'),
4390 _('REV')),
4386 _('REV')),
4391 ('b', 'branch', [],
4387 ('b', 'branch', [],
4392 _('a specific branch you would like to push'), _('BRANCH')),
4388 _('a specific branch you would like to push'), _('BRANCH')),
4393 ('', 'new-branch', False, _('allow pushing a new branch')),
4389 ('', 'new-branch', False, _('allow pushing a new branch')),
4394 ] + remoteopts,
4390 ] + remoteopts,
4395 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4391 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4396 "recover": (recover, []),
4392 "recover": (recover, []),
4397 "^remove|rm":
4393 "^remove|rm":
4398 (remove,
4394 (remove,
4399 [('A', 'after', None, _('record delete for missing files')),
4395 [('A', 'after', None, _('record delete for missing files')),
4400 ('f', 'force', None,
4396 ('f', 'force', None,
4401 _('remove (and delete) file even if added or modified')),
4397 _('remove (and delete) file even if added or modified')),
4402 ] + walkopts,
4398 ] + walkopts,
4403 _('[OPTION]... FILE...')),
4399 _('[OPTION]... FILE...')),
4404 "rename|move|mv":
4400 "rename|move|mv":
4405 (rename,
4401 (rename,
4406 [('A', 'after', None, _('record a rename that has already occurred')),
4402 [('A', 'after', None, _('record a rename that has already occurred')),
4407 ('f', 'force', None,
4403 ('f', 'force', None,
4408 _('forcibly copy over an existing managed file')),
4404 _('forcibly copy over an existing managed file')),
4409 ] + walkopts + dryrunopts,
4405 ] + walkopts + dryrunopts,
4410 _('[OPTION]... SOURCE... DEST')),
4406 _('[OPTION]... SOURCE... DEST')),
4411 "resolve":
4407 "resolve":
4412 (resolve,
4408 (resolve,
4413 [('a', 'all', None, _('select all unresolved files')),
4409 [('a', 'all', None, _('select all unresolved files')),
4414 ('l', 'list', None, _('list state of files needing merge')),
4410 ('l', 'list', None, _('list state of files needing merge')),
4415 ('m', 'mark', None, _('mark files as resolved')),
4411 ('m', 'mark', None, _('mark files as resolved')),
4416 ('u', 'unmark', None, _('mark files as unresolved')),
4412 ('u', 'unmark', None, _('mark files as unresolved')),
4417 ('t', 'tool', '', _('specify merge tool')),
4413 ('t', 'tool', '', _('specify merge tool')),
4418 ('n', 'no-status', None, _('hide status prefix'))]
4414 ('n', 'no-status', None, _('hide status prefix'))]
4419 + walkopts,
4415 + walkopts,
4420 _('[OPTION]... [FILE]...')),
4416 _('[OPTION]... [FILE]...')),
4421 "revert":
4417 "revert":
4422 (revert,
4418 (revert,
4423 [('a', 'all', None, _('revert all changes when no arguments given')),
4419 [('a', 'all', None, _('revert all changes when no arguments given')),
4424 ('d', 'date', '',
4420 ('d', 'date', '',
4425 _('tipmost revision matching date'), _('DATE')),
4421 _('tipmost revision matching date'), _('DATE')),
4426 ('r', 'rev', '',
4422 ('r', 'rev', '',
4427 _('revert to the specified revision'), _('REV')),
4423 _('revert to the specified revision'), _('REV')),
4428 ('', 'no-backup', None, _('do not save backup copies of files')),
4424 ('', 'no-backup', None, _('do not save backup copies of files')),
4429 ] + walkopts + dryrunopts,
4425 ] + walkopts + dryrunopts,
4430 _('[OPTION]... [-r REV] [NAME]...')),
4426 _('[OPTION]... [-r REV] [NAME]...')),
4431 "rollback": (rollback, dryrunopts),
4427 "rollback": (rollback, dryrunopts),
4432 "root": (root, []),
4428 "root": (root, []),
4433 "^serve":
4429 "^serve":
4434 (serve,
4430 (serve,
4435 [('A', 'accesslog', '',
4431 [('A', 'accesslog', '',
4436 _('name of access log file to write to'), _('FILE')),
4432 _('name of access log file to write to'), _('FILE')),
4437 ('d', 'daemon', None, _('run server in background')),
4433 ('d', 'daemon', None, _('run server in background')),
4438 ('', 'daemon-pipefds', '',
4434 ('', 'daemon-pipefds', '',
4439 _('used internally by daemon mode'), _('NUM')),
4435 _('used internally by daemon mode'), _('NUM')),
4440 ('E', 'errorlog', '',
4436 ('E', 'errorlog', '',
4441 _('name of error log file to write to'), _('FILE')),
4437 _('name of error log file to write to'), _('FILE')),
4442 # use string type, then we can check if something was passed
4438 # use string type, then we can check if something was passed
4443 ('p', 'port', '',
4439 ('p', 'port', '',
4444 _('port to listen on (default: 8000)'), _('PORT')),
4440 _('port to listen on (default: 8000)'), _('PORT')),
4445 ('a', 'address', '',
4441 ('a', 'address', '',
4446 _('address to listen on (default: all interfaces)'), _('ADDR')),
4442 _('address to listen on (default: all interfaces)'), _('ADDR')),
4447 ('', 'prefix', '',
4443 ('', 'prefix', '',
4448 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4444 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4449 ('n', 'name', '',
4445 ('n', 'name', '',
4450 _('name to show in web pages (default: working directory)'),
4446 _('name to show in web pages (default: working directory)'),
4451 _('NAME')),
4447 _('NAME')),
4452 ('', 'web-conf', '',
4448 ('', 'web-conf', '',
4453 _('name of the hgweb config file (see "hg help hgweb")'),
4449 _('name of the hgweb config file (see "hg help hgweb")'),
4454 _('FILE')),
4450 _('FILE')),
4455 ('', 'webdir-conf', '',
4451 ('', 'webdir-conf', '',
4456 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4452 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4457 ('', 'pid-file', '',
4453 ('', 'pid-file', '',
4458 _('name of file to write process ID to'), _('FILE')),
4454 _('name of file to write process ID to'), _('FILE')),
4459 ('', 'stdio', None, _('for remote clients')),
4455 ('', 'stdio', None, _('for remote clients')),
4460 ('t', 'templates', '',
4456 ('t', 'templates', '',
4461 _('web templates to use'), _('TEMPLATE')),
4457 _('web templates to use'), _('TEMPLATE')),
4462 ('', 'style', '',
4458 ('', 'style', '',
4463 _('template style to use'), _('STYLE')),
4459 _('template style to use'), _('STYLE')),
4464 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4460 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4465 ('', 'certificate', '',
4461 ('', 'certificate', '',
4466 _('SSL certificate file'), _('FILE'))],
4462 _('SSL certificate file'), _('FILE'))],
4467 _('[OPTION]...')),
4463 _('[OPTION]...')),
4468 "showconfig|debugconfig":
4464 "showconfig|debugconfig":
4469 (showconfig,
4465 (showconfig,
4470 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4466 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4471 _('[-u] [NAME]...')),
4467 _('[-u] [NAME]...')),
4472 "^summary|sum":
4468 "^summary|sum":
4473 (summary,
4469 (summary,
4474 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4470 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4475 "^status|st":
4471 "^status|st":
4476 (status,
4472 (status,
4477 [('A', 'all', None, _('show status of all files')),
4473 [('A', 'all', None, _('show status of all files')),
4478 ('m', 'modified', None, _('show only modified files')),
4474 ('m', 'modified', None, _('show only modified files')),
4479 ('a', 'added', None, _('show only added files')),
4475 ('a', 'added', None, _('show only added files')),
4480 ('r', 'removed', None, _('show only removed files')),
4476 ('r', 'removed', None, _('show only removed files')),
4481 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4477 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4482 ('c', 'clean', None, _('show only files without changes')),
4478 ('c', 'clean', None, _('show only files without changes')),
4483 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4479 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4484 ('i', 'ignored', None, _('show only ignored files')),
4480 ('i', 'ignored', None, _('show only ignored files')),
4485 ('n', 'no-status', None, _('hide status prefix')),
4481 ('n', 'no-status', None, _('hide status prefix')),
4486 ('C', 'copies', None, _('show source of copied files')),
4482 ('C', 'copies', None, _('show source of copied files')),
4487 ('0', 'print0', None,
4483 ('0', 'print0', None,
4488 _('end filenames with NUL, for use with xargs')),
4484 _('end filenames with NUL, for use with xargs')),
4489 ('', 'rev', [],
4485 ('', 'rev', [],
4490 _('show difference from revision'), _('REV')),
4486 _('show difference from revision'), _('REV')),
4491 ('', 'change', '',
4487 ('', 'change', '',
4492 _('list the changed files of a revision'), _('REV')),
4488 _('list the changed files of a revision'), _('REV')),
4493 ] + walkopts + subrepoopts,
4489 ] + walkopts + subrepoopts,
4494 _('[OPTION]... [FILE]...')),
4490 _('[OPTION]... [FILE]...')),
4495 "tag":
4491 "tag":
4496 (tag,
4492 (tag,
4497 [('f', 'force', None, _('force tag')),
4493 [('f', 'force', None, _('force tag')),
4498 ('l', 'local', None, _('make the tag local')),
4494 ('l', 'local', None, _('make the tag local')),
4499 ('r', 'rev', '',
4495 ('r', 'rev', '',
4500 _('revision to tag'), _('REV')),
4496 _('revision to tag'), _('REV')),
4501 ('', 'remove', None, _('remove a tag')),
4497 ('', 'remove', None, _('remove a tag')),
4502 # -l/--local is already there, commitopts cannot be used
4498 # -l/--local is already there, commitopts cannot be used
4503 ('e', 'edit', None, _('edit commit message')),
4499 ('e', 'edit', None, _('edit commit message')),
4504 ('m', 'message', '',
4500 ('m', 'message', '',
4505 _('use <text> as commit message'), _('TEXT')),
4501 _('use <text> as commit message'), _('TEXT')),
4506 ] + commitopts2,
4502 ] + commitopts2,
4507 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4503 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4508 "tags": (tags, [], ''),
4504 "tags": (tags, [], ''),
4509 "tip":
4505 "tip":
4510 (tip,
4506 (tip,
4511 [('p', 'patch', None, _('show patch')),
4507 [('p', 'patch', None, _('show patch')),
4512 ('g', 'git', None, _('use git extended diff format')),
4508 ('g', 'git', None, _('use git extended diff format')),
4513 ] + templateopts,
4509 ] + templateopts,
4514 _('[-p] [-g]')),
4510 _('[-p] [-g]')),
4515 "unbundle":
4511 "unbundle":
4516 (unbundle,
4512 (unbundle,
4517 [('u', 'update', None,
4513 [('u', 'update', None,
4518 _('update to new branch head if changesets were unbundled'))],
4514 _('update to new branch head if changesets were unbundled'))],
4519 _('[-u] FILE...')),
4515 _('[-u] FILE...')),
4520 "^update|up|checkout|co":
4516 "^update|up|checkout|co":
4521 (update,
4517 (update,
4522 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4518 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4523 ('c', 'check', None,
4519 ('c', 'check', None,
4524 _('update across branches if no uncommitted changes')),
4520 _('update across branches if no uncommitted changes')),
4525 ('d', 'date', '',
4521 ('d', 'date', '',
4526 _('tipmost revision matching date'), _('DATE')),
4522 _('tipmost revision matching date'), _('DATE')),
4527 ('r', 'rev', '',
4523 ('r', 'rev', '',
4528 _('revision'), _('REV'))],
4524 _('revision'), _('REV'))],
4529 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4525 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4530 "verify": (verify, []),
4526 "verify": (verify, []),
4531 "version": (version_, []),
4527 "version": (version_, []),
4532 }
4528 }
4533
4529
4534 norepo = ("clone init version help debugcommands debugcomplete"
4530 norepo = ("clone init version help debugcommands debugcomplete"
4535 " debugdate debuginstall debugfsinfo debugpushkey")
4531 " debugdate debuginstall debugfsinfo debugpushkey")
4536 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4532 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4537 " debugdata debugindex debugindexdot")
4533 " debugdata debugindex debugindexdot")
@@ -1,683 +1,683
1 # dirstate.py - working directory tracking for mercurial
1 # dirstate.py - working directory tracking 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 nullid
8 from node import nullid
9 from i18n import _
9 from i18n import _
10 import util, ignore, osutil, parsers, encoding
10 import util, ignore, osutil, parsers, encoding
11 import struct, os, stat, errno
11 import struct, os, stat, errno
12 import cStringIO
12 import cStringIO
13
13
14 _format = ">cllll"
14 _format = ">cllll"
15 propertycache = util.propertycache
15 propertycache = util.propertycache
16
16
17 def _finddirs(path):
17 def _finddirs(path):
18 pos = path.rfind('/')
18 pos = path.rfind('/')
19 while pos != -1:
19 while pos != -1:
20 yield path[:pos]
20 yield path[:pos]
21 pos = path.rfind('/', 0, pos)
21 pos = path.rfind('/', 0, pos)
22
22
23 def _incdirs(dirs, path):
23 def _incdirs(dirs, path):
24 for base in _finddirs(path):
24 for base in _finddirs(path):
25 if base in dirs:
25 if base in dirs:
26 dirs[base] += 1
26 dirs[base] += 1
27 return
27 return
28 dirs[base] = 1
28 dirs[base] = 1
29
29
30 def _decdirs(dirs, path):
30 def _decdirs(dirs, path):
31 for base in _finddirs(path):
31 for base in _finddirs(path):
32 if dirs[base] > 1:
32 if dirs[base] > 1:
33 dirs[base] -= 1
33 dirs[base] -= 1
34 return
34 return
35 del dirs[base]
35 del dirs[base]
36
36
37 class dirstate(object):
37 class dirstate(object):
38
38
39 def __init__(self, opener, ui, root, validate):
39 def __init__(self, opener, ui, root, validate):
40 '''Create a new dirstate object.
40 '''Create a new dirstate object.
41
41
42 opener is an open()-like callable that can be used to open the
42 opener is an open()-like callable that can be used to open the
43 dirstate file; root is the root of the directory tracked by
43 dirstate file; root is the root of the directory tracked by
44 the dirstate.
44 the dirstate.
45 '''
45 '''
46 self._opener = opener
46 self._opener = opener
47 self._validate = validate
47 self._validate = validate
48 self._root = root
48 self._root = root
49 self._rootdir = os.path.join(root, '')
49 self._rootdir = os.path.join(root, '')
50 self._dirty = False
50 self._dirty = False
51 self._dirtypl = False
51 self._dirtypl = False
52 self._ui = ui
52 self._ui = ui
53
53
54 @propertycache
54 @propertycache
55 def _map(self):
55 def _map(self):
56 '''Return the dirstate contents as a map from filename to
56 '''Return the dirstate contents as a map from filename to
57 (state, mode, size, time).'''
57 (state, mode, size, time).'''
58 self._read()
58 self._read()
59 return self._map
59 return self._map
60
60
61 @propertycache
61 @propertycache
62 def _copymap(self):
62 def _copymap(self):
63 self._read()
63 self._read()
64 return self._copymap
64 return self._copymap
65
65
66 @propertycache
66 @propertycache
67 def _foldmap(self):
67 def _foldmap(self):
68 f = {}
68 f = {}
69 for name in self._map:
69 for name in self._map:
70 f[os.path.normcase(name)] = name
70 f[os.path.normcase(name)] = name
71 return f
71 return f
72
72
73 @propertycache
73 @propertycache
74 def _branch(self):
74 def _branch(self):
75 try:
75 try:
76 return self._opener("branch").read().strip() or "default"
76 return self._opener("branch").read().strip() or "default"
77 except IOError:
77 except IOError:
78 return "default"
78 return "default"
79
79
80 @propertycache
80 @propertycache
81 def _pl(self):
81 def _pl(self):
82 try:
82 try:
83 st = self._opener("dirstate").read(40)
83 st = self._opener("dirstate").read(40)
84 l = len(st)
84 l = len(st)
85 if l == 40:
85 if l == 40:
86 return st[:20], st[20:40]
86 return st[:20], st[20:40]
87 elif l > 0 and l < 40:
87 elif l > 0 and l < 40:
88 raise util.Abort(_('working directory state appears damaged!'))
88 raise util.Abort(_('working directory state appears damaged!'))
89 except IOError, err:
89 except IOError, err:
90 if err.errno != errno.ENOENT:
90 if err.errno != errno.ENOENT:
91 raise
91 raise
92 return [nullid, nullid]
92 return [nullid, nullid]
93
93
94 @propertycache
94 @propertycache
95 def _dirs(self):
95 def _dirs(self):
96 dirs = {}
96 dirs = {}
97 for f, s in self._map.iteritems():
97 for f, s in self._map.iteritems():
98 if s[0] != 'r':
98 if s[0] != 'r':
99 _incdirs(dirs, f)
99 _incdirs(dirs, f)
100 return dirs
100 return dirs
101
101
102 @propertycache
102 @propertycache
103 def _ignore(self):
103 def _ignore(self):
104 files = [self._join('.hgignore')]
104 files = [self._join('.hgignore')]
105 for name, path in self._ui.configitems("ui"):
105 for name, path in self._ui.configitems("ui"):
106 if name == 'ignore' or name.startswith('ignore.'):
106 if name == 'ignore' or name.startswith('ignore.'):
107 files.append(util.expandpath(path))
107 files.append(util.expandpath(path))
108 return ignore.ignore(self._root, files, self._ui.warn)
108 return ignore.ignore(self._root, files, self._ui.warn)
109
109
110 @propertycache
110 @propertycache
111 def _slash(self):
111 def _slash(self):
112 return self._ui.configbool('ui', 'slash') and os.sep != '/'
112 return self._ui.configbool('ui', 'slash') and os.sep != '/'
113
113
114 @propertycache
114 @propertycache
115 def _checklink(self):
115 def _checklink(self):
116 return util.checklink(self._root)
116 return util.checklink(self._root)
117
117
118 @propertycache
118 @propertycache
119 def _checkexec(self):
119 def _checkexec(self):
120 return util.checkexec(self._root)
120 return util.checkexec(self._root)
121
121
122 @propertycache
122 @propertycache
123 def _checkcase(self):
123 def _checkcase(self):
124 return not util.checkcase(self._join('.hg'))
124 return not util.checkcase(self._join('.hg'))
125
125
126 def _join(self, f):
126 def _join(self, f):
127 # much faster than os.path.join()
127 # much faster than os.path.join()
128 # it's safe because f is always a relative path
128 # it's safe because f is always a relative path
129 return self._rootdir + f
129 return self._rootdir + f
130
130
131 def flagfunc(self, fallback):
131 def flagfunc(self, fallback):
132 if self._checklink:
132 if self._checklink:
133 if self._checkexec:
133 if self._checkexec:
134 def f(x):
134 def f(x):
135 p = self._join(x)
135 p = self._join(x)
136 if os.path.islink(p):
136 if os.path.islink(p):
137 return 'l'
137 return 'l'
138 if util.is_exec(p):
138 if util.is_exec(p):
139 return 'x'
139 return 'x'
140 return ''
140 return ''
141 return f
141 return f
142 def f(x):
142 def f(x):
143 if os.path.islink(self._join(x)):
143 if os.path.islink(self._join(x)):
144 return 'l'
144 return 'l'
145 if 'x' in fallback(x):
145 if 'x' in fallback(x):
146 return 'x'
146 return 'x'
147 return ''
147 return ''
148 return f
148 return f
149 if self._checkexec:
149 if self._checkexec:
150 def f(x):
150 def f(x):
151 if 'l' in fallback(x):
151 if 'l' in fallback(x):
152 return 'l'
152 return 'l'
153 if util.is_exec(self._join(x)):
153 if util.is_exec(self._join(x)):
154 return 'x'
154 return 'x'
155 return ''
155 return ''
156 return f
156 return f
157 return fallback
157 return fallback
158
158
159 def getcwd(self):
159 def getcwd(self):
160 cwd = os.getcwd()
160 cwd = os.getcwd()
161 if cwd == self._root:
161 if cwd == self._root:
162 return ''
162 return ''
163 # self._root ends with a path separator if self._root is '/' or 'C:\'
163 # self._root ends with a path separator if self._root is '/' or 'C:\'
164 rootsep = self._root
164 rootsep = self._root
165 if not util.endswithsep(rootsep):
165 if not util.endswithsep(rootsep):
166 rootsep += os.sep
166 rootsep += os.sep
167 if cwd.startswith(rootsep):
167 if cwd.startswith(rootsep):
168 return cwd[len(rootsep):]
168 return cwd[len(rootsep):]
169 else:
169 else:
170 # we're outside the repo. return an absolute path.
170 # we're outside the repo. return an absolute path.
171 return cwd
171 return cwd
172
172
173 def pathto(self, f, cwd=None):
173 def pathto(self, f, cwd=None):
174 if cwd is None:
174 if cwd is None:
175 cwd = self.getcwd()
175 cwd = self.getcwd()
176 path = util.pathto(self._root, cwd, f)
176 path = util.pathto(self._root, cwd, f)
177 if self._slash:
177 if self._slash:
178 return util.normpath(path)
178 return util.normpath(path)
179 return path
179 return path
180
180
181 def __getitem__(self, key):
181 def __getitem__(self, key):
182 '''Return the current state of key (a filename) in the dirstate.
182 '''Return the current state of key (a filename) in the dirstate.
183
183
184 States are:
184 States are:
185 n normal
185 n normal
186 m needs merging
186 m needs merging
187 r marked for removal
187 r marked for removal
188 a marked for addition
188 a marked for addition
189 ? not tracked
189 ? not tracked
190 '''
190 '''
191 return self._map.get(key, ("?",))[0]
191 return self._map.get(key, ("?",))[0]
192
192
193 def __contains__(self, key):
193 def __contains__(self, key):
194 return key in self._map
194 return key in self._map
195
195
196 def __iter__(self):
196 def __iter__(self):
197 for x in sorted(self._map):
197 for x in sorted(self._map):
198 yield x
198 yield x
199
199
200 def parents(self):
200 def parents(self):
201 return [self._validate(p) for p in self._pl]
201 return [self._validate(p) for p in self._pl]
202
202
203 def branch(self):
203 def branch(self):
204 return encoding.tolocal(self._branch)
204 return encoding.tolocal(self._branch)
205
205
206 def setparents(self, p1, p2=nullid):
206 def setparents(self, p1, p2=nullid):
207 self._dirty = self._dirtypl = True
207 self._dirty = self._dirtypl = True
208 self._pl = p1, p2
208 self._pl = p1, p2
209
209
210 def setbranch(self, branch):
210 def setbranch(self, branch):
211 if branch in ['tip', '.', 'null']:
211 if branch in ['tip', '.', 'null']:
212 raise util.Abort(_('the name \'%s\' is reserved') % branch)
212 raise util.Abort(_('the name \'%s\' is reserved') % branch)
213 self._branch = encoding.fromlocal(branch)
213 self._branch = encoding.fromlocal(branch)
214 self._opener("branch", "w").write(self._branch + '\n')
214 self._opener("branch", "w").write(self._branch + '\n')
215
215
216 def _read(self):
216 def _read(self):
217 self._map = {}
217 self._map = {}
218 self._copymap = {}
218 self._copymap = {}
219 try:
219 try:
220 st = self._opener("dirstate").read()
220 st = self._opener("dirstate").read()
221 except IOError, err:
221 except IOError, err:
222 if err.errno != errno.ENOENT:
222 if err.errno != errno.ENOENT:
223 raise
223 raise
224 return
224 return
225 if not st:
225 if not st:
226 return
226 return
227
227
228 p = parsers.parse_dirstate(self._map, self._copymap, st)
228 p = parsers.parse_dirstate(self._map, self._copymap, st)
229 if not self._dirtypl:
229 if not self._dirtypl:
230 self._pl = p
230 self._pl = p
231
231
232 def invalidate(self):
232 def invalidate(self):
233 for a in ("_map", "_copymap", "_foldmap", "_branch", "_pl", "_dirs",
233 for a in ("_map", "_copymap", "_foldmap", "_branch", "_pl", "_dirs",
234 "_ignore"):
234 "_ignore"):
235 if a in self.__dict__:
235 if a in self.__dict__:
236 delattr(self, a)
236 delattr(self, a)
237 self._dirty = False
237 self._dirty = False
238
238
239 def copy(self, source, dest):
239 def copy(self, source, dest):
240 """Mark dest as a copy of source. Unmark dest if source is None."""
240 """Mark dest as a copy of source. Unmark dest if source is None."""
241 if source == dest:
241 if source == dest:
242 return
242 return
243 self._dirty = True
243 self._dirty = True
244 if source is not None:
244 if source is not None:
245 self._copymap[dest] = source
245 self._copymap[dest] = source
246 elif dest in self._copymap:
246 elif dest in self._copymap:
247 del self._copymap[dest]
247 del self._copymap[dest]
248
248
249 def copied(self, file):
249 def copied(self, file):
250 return self._copymap.get(file, None)
250 return self._copymap.get(file, None)
251
251
252 def copies(self):
252 def copies(self):
253 return self._copymap
253 return self._copymap
254
254
255 def _droppath(self, f):
255 def _droppath(self, f):
256 if self[f] not in "?r" and "_dirs" in self.__dict__:
256 if self[f] not in "?r" and "_dirs" in self.__dict__:
257 _decdirs(self._dirs, f)
257 _decdirs(self._dirs, f)
258
258
259 def _addpath(self, f, check=False):
259 def _addpath(self, f, check=False):
260 oldstate = self[f]
260 oldstate = self[f]
261 if check or oldstate == "r":
261 if check or oldstate == "r":
262 if '\r' in f or '\n' in f:
262 if '\r' in f or '\n' in f:
263 raise util.Abort(
263 raise util.Abort(
264 _("'\\n' and '\\r' disallowed in filenames: %r") % f)
264 _("'\\n' and '\\r' disallowed in filenames: %r") % f)
265 if f in self._dirs:
265 if f in self._dirs:
266 raise util.Abort(_('directory %r already in dirstate') % f)
266 raise util.Abort(_('directory %r already in dirstate') % f)
267 # shadows
267 # shadows
268 for d in _finddirs(f):
268 for d in _finddirs(f):
269 if d in self._dirs:
269 if d in self._dirs:
270 break
270 break
271 if d in self._map and self[d] != 'r':
271 if d in self._map and self[d] != 'r':
272 raise util.Abort(
272 raise util.Abort(
273 _('file %r in dirstate clashes with %r') % (d, f))
273 _('file %r in dirstate clashes with %r') % (d, f))
274 if oldstate in "?r" and "_dirs" in self.__dict__:
274 if oldstate in "?r" and "_dirs" in self.__dict__:
275 _incdirs(self._dirs, f)
275 _incdirs(self._dirs, f)
276
276
277 def normal(self, f):
277 def normal(self, f):
278 '''Mark a file normal and clean.'''
278 '''Mark a file normal and clean.'''
279 self._dirty = True
279 self._dirty = True
280 self._addpath(f)
280 self._addpath(f)
281 s = os.lstat(self._join(f))
281 s = os.lstat(self._join(f))
282 self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
282 self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
283 if f in self._copymap:
283 if f in self._copymap:
284 del self._copymap[f]
284 del self._copymap[f]
285
285
286 def normallookup(self, f):
286 def normallookup(self, f):
287 '''Mark a file normal, but possibly dirty.'''
287 '''Mark a file normal, but possibly dirty.'''
288 if self._pl[1] != nullid and f in self._map:
288 if self._pl[1] != nullid and f in self._map:
289 # if there is a merge going on and the file was either
289 # if there is a merge going on and the file was either
290 # in state 'm' (-1) or coming from other parent (-2) before
290 # in state 'm' (-1) or coming from other parent (-2) before
291 # being removed, restore that state.
291 # being removed, restore that state.
292 entry = self._map[f]
292 entry = self._map[f]
293 if entry[0] == 'r' and entry[2] in (-1, -2):
293 if entry[0] == 'r' and entry[2] in (-1, -2):
294 source = self._copymap.get(f)
294 source = self._copymap.get(f)
295 if entry[2] == -1:
295 if entry[2] == -1:
296 self.merge(f)
296 self.merge(f)
297 elif entry[2] == -2:
297 elif entry[2] == -2:
298 self.otherparent(f)
298 self.otherparent(f)
299 if source:
299 if source:
300 self.copy(source, f)
300 self.copy(source, f)
301 return
301 return
302 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
302 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
303 return
303 return
304 self._dirty = True
304 self._dirty = True
305 self._addpath(f)
305 self._addpath(f)
306 self._map[f] = ('n', 0, -1, -1)
306 self._map[f] = ('n', 0, -1, -1)
307 if f in self._copymap:
307 if f in self._copymap:
308 del self._copymap[f]
308 del self._copymap[f]
309
309
310 def otherparent(self, f):
310 def otherparent(self, f):
311 '''Mark as coming from the other parent, always dirty.'''
311 '''Mark as coming from the other parent, always dirty.'''
312 if self._pl[1] == nullid:
312 if self._pl[1] == nullid:
313 raise util.Abort(_("setting %r to other parent "
313 raise util.Abort(_("setting %r to other parent "
314 "only allowed in merges") % f)
314 "only allowed in merges") % f)
315 self._dirty = True
315 self._dirty = True
316 self._addpath(f)
316 self._addpath(f)
317 self._map[f] = ('n', 0, -2, -1)
317 self._map[f] = ('n', 0, -2, -1)
318 if f in self._copymap:
318 if f in self._copymap:
319 del self._copymap[f]
319 del self._copymap[f]
320
320
321 def add(self, f):
321 def add(self, f):
322 '''Mark a file added.'''
322 '''Mark a file added.'''
323 self._dirty = True
323 self._dirty = True
324 self._addpath(f, True)
324 self._addpath(f, True)
325 self._map[f] = ('a', 0, -1, -1)
325 self._map[f] = ('a', 0, -1, -1)
326 if f in self._copymap:
326 if f in self._copymap:
327 del self._copymap[f]
327 del self._copymap[f]
328
328
329 def remove(self, f):
329 def remove(self, f):
330 '''Mark a file removed.'''
330 '''Mark a file removed.'''
331 self._dirty = True
331 self._dirty = True
332 self._droppath(f)
332 self._droppath(f)
333 size = 0
333 size = 0
334 if self._pl[1] != nullid and f in self._map:
334 if self._pl[1] != nullid and f in self._map:
335 # backup the previous state
335 # backup the previous state
336 entry = self._map[f]
336 entry = self._map[f]
337 if entry[0] == 'm': # merge
337 if entry[0] == 'm': # merge
338 size = -1
338 size = -1
339 elif entry[0] == 'n' and entry[2] == -2: # other parent
339 elif entry[0] == 'n' and entry[2] == -2: # other parent
340 size = -2
340 size = -2
341 self._map[f] = ('r', 0, size, 0)
341 self._map[f] = ('r', 0, size, 0)
342 if size == 0 and f in self._copymap:
342 if size == 0 and f in self._copymap:
343 del self._copymap[f]
343 del self._copymap[f]
344
344
345 def merge(self, f):
345 def merge(self, f):
346 '''Mark a file merged.'''
346 '''Mark a file merged.'''
347 self._dirty = True
347 self._dirty = True
348 s = os.lstat(self._join(f))
348 s = os.lstat(self._join(f))
349 self._addpath(f)
349 self._addpath(f)
350 self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
350 self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
351 if f in self._copymap:
351 if f in self._copymap:
352 del self._copymap[f]
352 del self._copymap[f]
353
353
354 def forget(self, f):
354 def forget(self, f):
355 '''Forget a file.'''
355 '''Forget a file.'''
356 self._dirty = True
356 self._dirty = True
357 try:
357 try:
358 self._droppath(f)
358 self._droppath(f)
359 del self._map[f]
359 del self._map[f]
360 except KeyError:
360 except KeyError:
361 self._ui.warn(_("not in dirstate: %s\n") % f)
361 self._ui.warn(_("not in dirstate: %s\n") % f)
362
362
363 def _normalize(self, path, knownpath):
363 def _normalize(self, path, knownpath):
364 norm_path = os.path.normcase(path)
364 norm_path = os.path.normcase(path)
365 fold_path = self._foldmap.get(norm_path, None)
365 fold_path = self._foldmap.get(norm_path, None)
366 if fold_path is None:
366 if fold_path is None:
367 if knownpath or not os.path.lexists(os.path.join(self._root, path)):
367 if knownpath or not os.path.lexists(os.path.join(self._root, path)):
368 fold_path = path
368 fold_path = path
369 else:
369 else:
370 fold_path = self._foldmap.setdefault(norm_path,
370 fold_path = self._foldmap.setdefault(norm_path,
371 util.fspath(path, self._root))
371 util.fspath(path, self._root))
372 return fold_path
372 return fold_path
373
373
374 def clear(self):
374 def clear(self):
375 self._map = {}
375 self._map = {}
376 if "_dirs" in self.__dict__:
376 if "_dirs" in self.__dict__:
377 delattr(self, "_dirs")
377 delattr(self, "_dirs")
378 self._copymap = {}
378 self._copymap = {}
379 self._pl = [nullid, nullid]
379 self._pl = [nullid, nullid]
380 self._dirty = True
380 self._dirty = True
381
381
382 def rebuild(self, parent, files):
382 def rebuild(self, parent, files):
383 self.clear()
383 self.clear()
384 for f in files:
384 for f in files:
385 if 'x' in files.flags(f):
385 if 'x' in files.flags(f):
386 self._map[f] = ('n', 0777, -1, 0)
386 self._map[f] = ('n', 0777, -1, 0)
387 else:
387 else:
388 self._map[f] = ('n', 0666, -1, 0)
388 self._map[f] = ('n', 0666, -1, 0)
389 self._pl = (parent, nullid)
389 self._pl = (parent, nullid)
390 self._dirty = True
390 self._dirty = True
391
391
392 def write(self):
392 def write(self):
393 if not self._dirty:
393 if not self._dirty:
394 return
394 return
395 st = self._opener("dirstate", "w", atomictemp=True)
395 st = self._opener("dirstate", "w", atomictemp=True)
396
396
397 # use the modification time of the newly created temporary file as the
397 # use the modification time of the newly created temporary file as the
398 # filesystem's notion of 'now'
398 # filesystem's notion of 'now'
399 now = int(util.fstat(st).st_mtime)
399 now = int(util.fstat(st).st_mtime)
400
400
401 cs = cStringIO.StringIO()
401 cs = cStringIO.StringIO()
402 copymap = self._copymap
402 copymap = self._copymap
403 pack = struct.pack
403 pack = struct.pack
404 write = cs.write
404 write = cs.write
405 write("".join(self._pl))
405 write("".join(self._pl))
406 for f, e in self._map.iteritems():
406 for f, e in self._map.iteritems():
407 if e[0] == 'n' and e[3] == now:
407 if e[0] == 'n' and e[3] == now:
408 # The file was last modified "simultaneously" with the current
408 # The file was last modified "simultaneously" with the current
409 # write to dirstate (i.e. within the same second for file-
409 # write to dirstate (i.e. within the same second for file-
410 # systems with a granularity of 1 sec). This commonly happens
410 # systems with a granularity of 1 sec). This commonly happens
411 # for at least a couple of files on 'update'.
411 # for at least a couple of files on 'update'.
412 # The user could change the file without changing its size
412 # The user could change the file without changing its size
413 # within the same second. Invalidate the file's stat data in
413 # within the same second. Invalidate the file's stat data in
414 # dirstate, forcing future 'status' calls to compare the
414 # dirstate, forcing future 'status' calls to compare the
415 # contents of the file. This prevents mistakenly treating such
415 # contents of the file. This prevents mistakenly treating such
416 # files as clean.
416 # files as clean.
417 e = (e[0], 0, -1, -1) # mark entry as 'unset'
417 e = (e[0], 0, -1, -1) # mark entry as 'unset'
418 self._map[f] = e
418 self._map[f] = e
419
419
420 if f in copymap:
420 if f in copymap:
421 f = "%s\0%s" % (f, copymap[f])
421 f = "%s\0%s" % (f, copymap[f])
422 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
422 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
423 write(e)
423 write(e)
424 write(f)
424 write(f)
425 st.write(cs.getvalue())
425 st.write(cs.getvalue())
426 st.rename()
426 st.rename()
427 self._dirty = self._dirtypl = False
427 self._dirty = self._dirtypl = False
428
428
429 def _dirignore(self, f):
429 def _dirignore(self, f):
430 if f == '.':
430 if f == '.':
431 return False
431 return False
432 if self._ignore(f):
432 if self._ignore(f):
433 return True
433 return True
434 for p in _finddirs(f):
434 for p in _finddirs(f):
435 if self._ignore(p):
435 if self._ignore(p):
436 return True
436 return True
437 return False
437 return False
438
438
439 def walk(self, match, subrepos, unknown, ignored):
439 def walk(self, match, subrepos, unknown, ignored):
440 '''
440 '''
441 Walk recursively through the directory tree, finding all files
441 Walk recursively through the directory tree, finding all files
442 matched by match.
442 matched by match.
443
443
444 Return a dict mapping filename to stat-like object (either
444 Return a dict mapping filename to stat-like object (either
445 mercurial.osutil.stat instance or return value of os.stat()).
445 mercurial.osutil.stat instance or return value of os.stat()).
446 '''
446 '''
447
447
448 def fwarn(f, msg):
448 def fwarn(f, msg):
449 self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
449 self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
450 return False
450 return False
451
451
452 def badtype(mode):
452 def badtype(mode):
453 kind = _('unknown')
453 kind = _('unknown')
454 if stat.S_ISCHR(mode):
454 if stat.S_ISCHR(mode):
455 kind = _('character device')
455 kind = _('character device')
456 elif stat.S_ISBLK(mode):
456 elif stat.S_ISBLK(mode):
457 kind = _('block device')
457 kind = _('block device')
458 elif stat.S_ISFIFO(mode):
458 elif stat.S_ISFIFO(mode):
459 kind = _('fifo')
459 kind = _('fifo')
460 elif stat.S_ISSOCK(mode):
460 elif stat.S_ISSOCK(mode):
461 kind = _('socket')
461 kind = _('socket')
462 elif stat.S_ISDIR(mode):
462 elif stat.S_ISDIR(mode):
463 kind = _('directory')
463 kind = _('directory')
464 return _('unsupported file type (type is %s)') % kind
464 return _('unsupported file type (type is %s)') % kind
465
465
466 ignore = self._ignore
466 ignore = self._ignore
467 dirignore = self._dirignore
467 dirignore = self._dirignore
468 if ignored:
468 if ignored:
469 ignore = util.never
469 ignore = util.never
470 dirignore = util.never
470 dirignore = util.never
471 elif not unknown:
471 elif not unknown:
472 # if unknown and ignored are False, skip step 2
472 # if unknown and ignored are False, skip step 2
473 ignore = util.always
473 ignore = util.always
474 dirignore = util.always
474 dirignore = util.always
475
475
476 matchfn = match.matchfn
476 matchfn = match.matchfn
477 badfn = match.bad
477 badfn = match.bad
478 dmap = self._map
478 dmap = self._map
479 normpath = util.normpath
479 normpath = util.normpath
480 listdir = osutil.listdir
480 listdir = osutil.listdir
481 lstat = os.lstat
481 lstat = os.lstat
482 getkind = stat.S_IFMT
482 getkind = stat.S_IFMT
483 dirkind = stat.S_IFDIR
483 dirkind = stat.S_IFDIR
484 regkind = stat.S_IFREG
484 regkind = stat.S_IFREG
485 lnkkind = stat.S_IFLNK
485 lnkkind = stat.S_IFLNK
486 join = self._join
486 join = self._join
487 work = []
487 work = []
488 wadd = work.append
488 wadd = work.append
489
489
490 exact = skipstep3 = False
490 exact = skipstep3 = False
491 if matchfn == match.exact: # match.exact
491 if matchfn == match.exact: # match.exact
492 exact = True
492 exact = True
493 dirignore = util.always # skip step 2
493 dirignore = util.always # skip step 2
494 elif match.files() and not match.anypats(): # match.match, no patterns
494 elif match.files() and not match.anypats(): # match.match, no patterns
495 skipstep3 = True
495 skipstep3 = True
496
496
497 if self._checkcase:
497 if self._checkcase:
498 normalize = self._normalize
498 normalize = self._normalize
499 skipstep3 = False
499 skipstep3 = False
500 else:
500 else:
501 normalize = lambda x, y: x
501 normalize = lambda x, y: x
502
502
503 files = sorted(match.files())
503 files = sorted(match.files())
504 subrepos.sort()
504 subrepos.sort()
505 i, j = 0, 0
505 i, j = 0, 0
506 while i < len(files) and j < len(subrepos):
506 while i < len(files) and j < len(subrepos):
507 subpath = subrepos[j] + "/"
507 subpath = subrepos[j] + "/"
508 if files[i] < subpath:
508 if files[i] < subpath:
509 i += 1
509 i += 1
510 continue
510 continue
511 while files and files[i].startswith(subpath):
511 while i < len(files) and files[i].startswith(subpath):
512 del files[i]
512 del files[i]
513 j += 1
513 j += 1
514
514
515 if not files or '.' in files:
515 if not files or '.' in files:
516 files = ['']
516 files = ['']
517 results = dict.fromkeys(subrepos)
517 results = dict.fromkeys(subrepos)
518 results['.hg'] = None
518 results['.hg'] = None
519
519
520 # step 1: find all explicit files
520 # step 1: find all explicit files
521 for ff in files:
521 for ff in files:
522 nf = normalize(normpath(ff), False)
522 nf = normalize(normpath(ff), False)
523 if nf in results:
523 if nf in results:
524 continue
524 continue
525
525
526 try:
526 try:
527 st = lstat(join(nf))
527 st = lstat(join(nf))
528 kind = getkind(st.st_mode)
528 kind = getkind(st.st_mode)
529 if kind == dirkind:
529 if kind == dirkind:
530 skipstep3 = False
530 skipstep3 = False
531 if nf in dmap:
531 if nf in dmap:
532 #file deleted on disk but still in dirstate
532 #file deleted on disk but still in dirstate
533 results[nf] = None
533 results[nf] = None
534 match.dir(nf)
534 match.dir(nf)
535 if not dirignore(nf):
535 if not dirignore(nf):
536 wadd(nf)
536 wadd(nf)
537 elif kind == regkind or kind == lnkkind:
537 elif kind == regkind or kind == lnkkind:
538 results[nf] = st
538 results[nf] = st
539 else:
539 else:
540 badfn(ff, badtype(kind))
540 badfn(ff, badtype(kind))
541 if nf in dmap:
541 if nf in dmap:
542 results[nf] = None
542 results[nf] = None
543 except OSError, inst:
543 except OSError, inst:
544 if nf in dmap: # does it exactly match a file?
544 if nf in dmap: # does it exactly match a file?
545 results[nf] = None
545 results[nf] = None
546 else: # does it match a directory?
546 else: # does it match a directory?
547 prefix = nf + "/"
547 prefix = nf + "/"
548 for fn in dmap:
548 for fn in dmap:
549 if fn.startswith(prefix):
549 if fn.startswith(prefix):
550 match.dir(nf)
550 match.dir(nf)
551 skipstep3 = False
551 skipstep3 = False
552 break
552 break
553 else:
553 else:
554 badfn(ff, inst.strerror)
554 badfn(ff, inst.strerror)
555
555
556 # step 2: visit subdirectories
556 # step 2: visit subdirectories
557 while work:
557 while work:
558 nd = work.pop()
558 nd = work.pop()
559 skip = None
559 skip = None
560 if nd == '.':
560 if nd == '.':
561 nd = ''
561 nd = ''
562 else:
562 else:
563 skip = '.hg'
563 skip = '.hg'
564 try:
564 try:
565 entries = listdir(join(nd), stat=True, skip=skip)
565 entries = listdir(join(nd), stat=True, skip=skip)
566 except OSError, inst:
566 except OSError, inst:
567 if inst.errno == errno.EACCES:
567 if inst.errno == errno.EACCES:
568 fwarn(nd, inst.strerror)
568 fwarn(nd, inst.strerror)
569 continue
569 continue
570 raise
570 raise
571 for f, kind, st in entries:
571 for f, kind, st in entries:
572 nf = normalize(nd and (nd + "/" + f) or f, True)
572 nf = normalize(nd and (nd + "/" + f) or f, True)
573 if nf not in results:
573 if nf not in results:
574 if kind == dirkind:
574 if kind == dirkind:
575 if not ignore(nf):
575 if not ignore(nf):
576 match.dir(nf)
576 match.dir(nf)
577 wadd(nf)
577 wadd(nf)
578 if nf in dmap and matchfn(nf):
578 if nf in dmap and matchfn(nf):
579 results[nf] = None
579 results[nf] = None
580 elif kind == regkind or kind == lnkkind:
580 elif kind == regkind or kind == lnkkind:
581 if nf in dmap:
581 if nf in dmap:
582 if matchfn(nf):
582 if matchfn(nf):
583 results[nf] = st
583 results[nf] = st
584 elif matchfn(nf) and not ignore(nf):
584 elif matchfn(nf) and not ignore(nf):
585 results[nf] = st
585 results[nf] = st
586 elif nf in dmap and matchfn(nf):
586 elif nf in dmap and matchfn(nf):
587 results[nf] = None
587 results[nf] = None
588
588
589 # step 3: report unseen items in the dmap hash
589 # step 3: report unseen items in the dmap hash
590 if not skipstep3 and not exact:
590 if not skipstep3 and not exact:
591 visit = sorted([f for f in dmap if f not in results and matchfn(f)])
591 visit = sorted([f for f in dmap if f not in results and matchfn(f)])
592 for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
592 for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
593 if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
593 if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
594 st = None
594 st = None
595 results[nf] = st
595 results[nf] = st
596 for s in subrepos:
596 for s in subrepos:
597 del results[s]
597 del results[s]
598 del results['.hg']
598 del results['.hg']
599 return results
599 return results
600
600
601 def status(self, match, subrepos, ignored, clean, unknown):
601 def status(self, match, subrepos, ignored, clean, unknown):
602 '''Determine the status of the working copy relative to the
602 '''Determine the status of the working copy relative to the
603 dirstate and return a tuple of lists (unsure, modified, added,
603 dirstate and return a tuple of lists (unsure, modified, added,
604 removed, deleted, unknown, ignored, clean), where:
604 removed, deleted, unknown, ignored, clean), where:
605
605
606 unsure:
606 unsure:
607 files that might have been modified since the dirstate was
607 files that might have been modified since the dirstate was
608 written, but need to be read to be sure (size is the same
608 written, but need to be read to be sure (size is the same
609 but mtime differs)
609 but mtime differs)
610 modified:
610 modified:
611 files that have definitely been modified since the dirstate
611 files that have definitely been modified since the dirstate
612 was written (different size or mode)
612 was written (different size or mode)
613 added:
613 added:
614 files that have been explicitly added with hg add
614 files that have been explicitly added with hg add
615 removed:
615 removed:
616 files that have been explicitly removed with hg remove
616 files that have been explicitly removed with hg remove
617 deleted:
617 deleted:
618 files that have been deleted through other means ("missing")
618 files that have been deleted through other means ("missing")
619 unknown:
619 unknown:
620 files not in the dirstate that are not ignored
620 files not in the dirstate that are not ignored
621 ignored:
621 ignored:
622 files not in the dirstate that are ignored
622 files not in the dirstate that are ignored
623 (by _dirignore())
623 (by _dirignore())
624 clean:
624 clean:
625 files that have definitely not been modified since the
625 files that have definitely not been modified since the
626 dirstate was written
626 dirstate was written
627 '''
627 '''
628 listignored, listclean, listunknown = ignored, clean, unknown
628 listignored, listclean, listunknown = ignored, clean, unknown
629 lookup, modified, added, unknown, ignored = [], [], [], [], []
629 lookup, modified, added, unknown, ignored = [], [], [], [], []
630 removed, deleted, clean = [], [], []
630 removed, deleted, clean = [], [], []
631
631
632 dmap = self._map
632 dmap = self._map
633 ladd = lookup.append # aka "unsure"
633 ladd = lookup.append # aka "unsure"
634 madd = modified.append
634 madd = modified.append
635 aadd = added.append
635 aadd = added.append
636 uadd = unknown.append
636 uadd = unknown.append
637 iadd = ignored.append
637 iadd = ignored.append
638 radd = removed.append
638 radd = removed.append
639 dadd = deleted.append
639 dadd = deleted.append
640 cadd = clean.append
640 cadd = clean.append
641
641
642 lnkkind = stat.S_IFLNK
642 lnkkind = stat.S_IFLNK
643
643
644 for fn, st in self.walk(match, subrepos, listunknown,
644 for fn, st in self.walk(match, subrepos, listunknown,
645 listignored).iteritems():
645 listignored).iteritems():
646 if fn not in dmap:
646 if fn not in dmap:
647 if (listignored or match.exact(fn)) and self._dirignore(fn):
647 if (listignored or match.exact(fn)) and self._dirignore(fn):
648 if listignored:
648 if listignored:
649 iadd(fn)
649 iadd(fn)
650 elif listunknown:
650 elif listunknown:
651 uadd(fn)
651 uadd(fn)
652 continue
652 continue
653
653
654 state, mode, size, time = dmap[fn]
654 state, mode, size, time = dmap[fn]
655
655
656 if not st and state in "nma":
656 if not st and state in "nma":
657 dadd(fn)
657 dadd(fn)
658 elif state == 'n':
658 elif state == 'n':
659 # The "mode & lnkkind != lnkkind or self._checklink"
659 # The "mode & lnkkind != lnkkind or self._checklink"
660 # lines are an expansion of "islink => checklink"
660 # lines are an expansion of "islink => checklink"
661 # where islink means "is this a link?" and checklink
661 # where islink means "is this a link?" and checklink
662 # means "can we check links?".
662 # means "can we check links?".
663 if (size >= 0 and
663 if (size >= 0 and
664 (size != st.st_size
664 (size != st.st_size
665 or ((mode ^ st.st_mode) & 0100 and self._checkexec))
665 or ((mode ^ st.st_mode) & 0100 and self._checkexec))
666 and (mode & lnkkind != lnkkind or self._checklink)
666 and (mode & lnkkind != lnkkind or self._checklink)
667 or size == -2 # other parent
667 or size == -2 # other parent
668 or fn in self._copymap):
668 or fn in self._copymap):
669 madd(fn)
669 madd(fn)
670 elif (time != int(st.st_mtime)
670 elif (time != int(st.st_mtime)
671 and (mode & lnkkind != lnkkind or self._checklink)):
671 and (mode & lnkkind != lnkkind or self._checklink)):
672 ladd(fn)
672 ladd(fn)
673 elif listclean:
673 elif listclean:
674 cadd(fn)
674 cadd(fn)
675 elif state == 'm':
675 elif state == 'm':
676 madd(fn)
676 madd(fn)
677 elif state == 'a':
677 elif state == 'a':
678 aadd(fn)
678 aadd(fn)
679 elif state == 'r':
679 elif state == 'r':
680 radd(fn)
680 radd(fn)
681
681
682 return (lookup, modified, added, removed, deleted, unknown, ignored,
682 return (lookup, modified, added, removed, deleted, unknown, ignored,
683 clean)
683 clean)
@@ -1,415 +1,427
1 Create test repository:
1 Create test repository:
2
2
3 $ hg init repo
3 $ hg init repo
4 $ cd repo
4 $ cd repo
5 $ echo x1 > x.txt
5 $ echo x1 > x.txt
6
6
7 $ hg init foo
7 $ hg init foo
8 $ cd foo
8 $ cd foo
9 $ echo y1 > y.txt
9 $ echo y1 > y.txt
10
10
11 $ hg init bar
11 $ hg init bar
12 $ cd bar
12 $ cd bar
13 $ echo z1 > z.txt
13 $ echo z1 > z.txt
14
14
15 $ cd ..
15 $ cd ..
16 $ echo 'bar = bar' > .hgsub
16 $ echo 'bar = bar' > .hgsub
17
17
18 $ cd ..
18 $ cd ..
19 $ echo 'foo = foo' > .hgsub
19 $ echo 'foo = foo' > .hgsub
20
20
21 Add files --- .hgsub files must go first to trigger subrepos:
21 Add files --- .hgsub files must go first to trigger subrepos:
22
22
23 $ hg add -S .hgsub
23 $ hg add -S .hgsub
24 $ hg add -S foo/.hgsub
24 $ hg add -S foo/.hgsub
25 $ hg add -S foo/bar
25 $ hg add -S foo/bar
26 adding foo/bar/z.txt
26 adding foo/bar/z.txt
27 $ hg add -S
27 $ hg add -S
28 adding x.txt
28 adding x.txt
29 adding foo/y.txt
29 adding foo/y.txt
30
30
31 Test recursive status without committing anything:
31 Test recursive status without committing anything:
32
32
33 $ hg status -S
33 $ hg status -S
34 A .hgsub
34 A .hgsub
35 A foo/.hgsub
35 A foo/.hgsub
36 A foo/bar/z.txt
36 A foo/bar/z.txt
37 A foo/y.txt
37 A foo/y.txt
38 A x.txt
38 A x.txt
39
39
40 Test recursive diff without committing anything:
40 Test recursive diff without committing anything:
41
41
42 $ hg diff --nodates -S foo
42 $ hg diff --nodates -S foo
43 diff -r 000000000000 foo/.hgsub
43 diff -r 000000000000 foo/.hgsub
44 --- /dev/null
44 --- /dev/null
45 +++ b/foo/.hgsub
45 +++ b/foo/.hgsub
46 @@ -0,0 +1,1 @@
46 @@ -0,0 +1,1 @@
47 +bar = bar
47 +bar = bar
48 diff -r 000000000000 foo/y.txt
48 diff -r 000000000000 foo/y.txt
49 --- /dev/null
49 --- /dev/null
50 +++ b/foo/y.txt
50 +++ b/foo/y.txt
51 @@ -0,0 +1,1 @@
51 @@ -0,0 +1,1 @@
52 +y1
52 +y1
53 diff -r 000000000000 foo/bar/z.txt
53 diff -r 000000000000 foo/bar/z.txt
54 --- /dev/null
54 --- /dev/null
55 +++ b/foo/bar/z.txt
55 +++ b/foo/bar/z.txt
56 @@ -0,0 +1,1 @@
56 @@ -0,0 +1,1 @@
57 +z1
57 +z1
58
58
59 Commits:
59 Commits:
60
60
61 $ hg commit -m 0-0-0
61 $ hg commit -m 0-0-0
62 committing subrepository foo
62 committing subrepository foo
63 committing subrepository foo/bar
63 committing subrepository foo/bar
64
64
65 $ cd foo
65 $ cd foo
66 $ echo y2 >> y.txt
66 $ echo y2 >> y.txt
67 $ hg commit -m 0-1-0
67 $ hg commit -m 0-1-0
68
68
69 $ cd bar
69 $ cd bar
70 $ echo z2 >> z.txt
70 $ echo z2 >> z.txt
71 $ hg commit -m 0-1-1
71 $ hg commit -m 0-1-1
72
72
73 $ cd ..
73 $ cd ..
74 $ hg commit -m 0-2-1
74 $ hg commit -m 0-2-1
75 committing subrepository bar
75 committing subrepository bar
76
76
77 $ cd ..
77 $ cd ..
78 $ hg commit -m 1-2-1
78 $ hg commit -m 1-2-1
79 committing subrepository foo
79 committing subrepository foo
80
80
81 Change working directory:
81 Change working directory:
82
82
83 $ echo y3 >> foo/y.txt
83 $ echo y3 >> foo/y.txt
84 $ echo z3 >> foo/bar/z.txt
84 $ echo z3 >> foo/bar/z.txt
85 $ hg status -S
85 $ hg status -S
86 M foo/bar/z.txt
86 M foo/bar/z.txt
87 M foo/y.txt
87 M foo/y.txt
88 $ hg diff --nodates -S
88 $ hg diff --nodates -S
89 diff -r d254738c5f5e foo/y.txt
89 diff -r d254738c5f5e foo/y.txt
90 --- a/foo/y.txt
90 --- a/foo/y.txt
91 +++ b/foo/y.txt
91 +++ b/foo/y.txt
92 @@ -1,2 +1,3 @@
92 @@ -1,2 +1,3 @@
93 y1
93 y1
94 y2
94 y2
95 +y3
95 +y3
96 diff -r 9647f22de499 foo/bar/z.txt
96 diff -r 9647f22de499 foo/bar/z.txt
97 --- a/foo/bar/z.txt
97 --- a/foo/bar/z.txt
98 +++ b/foo/bar/z.txt
98 +++ b/foo/bar/z.txt
99 @@ -1,2 +1,3 @@
99 @@ -1,2 +1,3 @@
100 z1
100 z1
101 z2
101 z2
102 +z3
102 +z3
103
103
104 Status call crossing repository boundaries:
104 Status call crossing repository boundaries:
105
105
106 $ hg status -S foo/bar/z.txt
106 $ hg status -S foo/bar/z.txt
107 M foo/bar/z.txt
107 M foo/bar/z.txt
108 $ hg status -S -I 'foo/?.txt'
108 $ hg status -S -I 'foo/?.txt'
109 M foo/y.txt
109 M foo/y.txt
110 $ hg status -S -I '**/?.txt'
110 $ hg status -S -I '**/?.txt'
111 M foo/bar/z.txt
111 M foo/bar/z.txt
112 M foo/y.txt
112 M foo/y.txt
113 $ hg diff --nodates -S -I '**/?.txt'
113 $ hg diff --nodates -S -I '**/?.txt'
114 diff -r d254738c5f5e foo/y.txt
114 diff -r d254738c5f5e foo/y.txt
115 --- a/foo/y.txt
115 --- a/foo/y.txt
116 +++ b/foo/y.txt
116 +++ b/foo/y.txt
117 @@ -1,2 +1,3 @@
117 @@ -1,2 +1,3 @@
118 y1
118 y1
119 y2
119 y2
120 +y3
120 +y3
121 diff -r 9647f22de499 foo/bar/z.txt
121 diff -r 9647f22de499 foo/bar/z.txt
122 --- a/foo/bar/z.txt
122 --- a/foo/bar/z.txt
123 +++ b/foo/bar/z.txt
123 +++ b/foo/bar/z.txt
124 @@ -1,2 +1,3 @@
124 @@ -1,2 +1,3 @@
125 z1
125 z1
126 z2
126 z2
127 +z3
127 +z3
128
128
129 Status from within a subdirectory:
129 Status from within a subdirectory:
130
130
131 $ mkdir dir
131 $ mkdir dir
132 $ cd dir
132 $ cd dir
133 $ echo a1 > a.txt
133 $ echo a1 > a.txt
134 $ hg status -S
134 $ hg status -S
135 M foo/bar/z.txt
135 M foo/bar/z.txt
136 M foo/y.txt
136 M foo/y.txt
137 ? dir/a.txt
137 ? dir/a.txt
138 $ hg diff --nodates -S
138 $ hg diff --nodates -S
139 diff -r d254738c5f5e foo/y.txt
139 diff -r d254738c5f5e foo/y.txt
140 --- a/foo/y.txt
140 --- a/foo/y.txt
141 +++ b/foo/y.txt
141 +++ b/foo/y.txt
142 @@ -1,2 +1,3 @@
142 @@ -1,2 +1,3 @@
143 y1
143 y1
144 y2
144 y2
145 +y3
145 +y3
146 diff -r 9647f22de499 foo/bar/z.txt
146 diff -r 9647f22de499 foo/bar/z.txt
147 --- a/foo/bar/z.txt
147 --- a/foo/bar/z.txt
148 +++ b/foo/bar/z.txt
148 +++ b/foo/bar/z.txt
149 @@ -1,2 +1,3 @@
149 @@ -1,2 +1,3 @@
150 z1
150 z1
151 z2
151 z2
152 +z3
152 +z3
153
153
154 Status with relative path:
154 Status with relative path:
155
155
156 $ hg status -S ..
156 $ hg status -S ..
157 M ../foo/bar/z.txt
157 M ../foo/bar/z.txt
158 M ../foo/y.txt
158 M ../foo/y.txt
159 ? a.txt
159 ? a.txt
160 $ hg diff --nodates -S ..
160 $ hg diff --nodates -S ..
161 diff -r d254738c5f5e foo/y.txt
161 diff -r d254738c5f5e foo/y.txt
162 --- a/foo/y.txt
162 --- a/foo/y.txt
163 +++ b/foo/y.txt
163 +++ b/foo/y.txt
164 @@ -1,2 +1,3 @@
164 @@ -1,2 +1,3 @@
165 y1
165 y1
166 y2
166 y2
167 +y3
167 +y3
168 diff -r 9647f22de499 foo/bar/z.txt
168 diff -r 9647f22de499 foo/bar/z.txt
169 --- a/foo/bar/z.txt
169 --- a/foo/bar/z.txt
170 +++ b/foo/bar/z.txt
170 +++ b/foo/bar/z.txt
171 @@ -1,2 +1,3 @@
171 @@ -1,2 +1,3 @@
172 z1
172 z1
173 z2
173 z2
174 +z3
174 +z3
175 $ cd ..
175 $ cd ..
176
176
177 Cleanup and final commit:
177 Cleanup and final commit:
178
178
179 $ rm -r dir
179 $ rm -r dir
180 $ hg commit -m 2-3-2
180 $ hg commit -m 2-3-2
181 committing subrepository foo
181 committing subrepository foo
182 committing subrepository foo/bar
182 committing subrepository foo/bar
183
183
184 Log with the relationships between repo and its subrepo:
184 Log with the relationships between repo and its subrepo:
185
185
186 $ hg log --template '{rev}:{node|short} {desc}\n'
186 $ hg log --template '{rev}:{node|short} {desc}\n'
187 2:1326fa26d0c0 2-3-2
187 2:1326fa26d0c0 2-3-2
188 1:4b3c9ff4f66b 1-2-1
188 1:4b3c9ff4f66b 1-2-1
189 0:23376cbba0d8 0-0-0
189 0:23376cbba0d8 0-0-0
190
190
191 $ hg -R foo log --template '{rev}:{node|short} {desc}\n'
191 $ hg -R foo log --template '{rev}:{node|short} {desc}\n'
192 3:65903cebad86 2-3-2
192 3:65903cebad86 2-3-2
193 2:d254738c5f5e 0-2-1
193 2:d254738c5f5e 0-2-1
194 1:8629ce7dcc39 0-1-0
194 1:8629ce7dcc39 0-1-0
195 0:af048e97ade2 0-0-0
195 0:af048e97ade2 0-0-0
196
196
197 $ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
197 $ hg -R foo/bar log --template '{rev}:{node|short} {desc}\n'
198 2:31ecbdafd357 2-3-2
198 2:31ecbdafd357 2-3-2
199 1:9647f22de499 0-1-1
199 1:9647f22de499 0-1-1
200 0:4904098473f9 0-0-0
200 0:4904098473f9 0-0-0
201
201
202 Status between revisions:
202 Status between revisions:
203
203
204 $ hg status -S
204 $ hg status -S
205 $ hg status -S --rev 0:1
205 $ hg status -S --rev 0:1
206 M .hgsubstate
206 M .hgsubstate
207 M foo/.hgsubstate
207 M foo/.hgsubstate
208 M foo/bar/z.txt
208 M foo/bar/z.txt
209 M foo/y.txt
209 M foo/y.txt
210 $ hg diff --nodates -S -I '**/?.txt' --rev 0:1
210 $ hg diff --nodates -S -I '**/?.txt' --rev 0:1
211 diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
211 diff -r af048e97ade2 -r d254738c5f5e foo/y.txt
212 --- a/foo/y.txt
212 --- a/foo/y.txt
213 +++ b/foo/y.txt
213 +++ b/foo/y.txt
214 @@ -1,1 +1,2 @@
214 @@ -1,1 +1,2 @@
215 y1
215 y1
216 +y2
216 +y2
217 diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
217 diff -r 4904098473f9 -r 9647f22de499 foo/bar/z.txt
218 --- a/foo/bar/z.txt
218 --- a/foo/bar/z.txt
219 +++ b/foo/bar/z.txt
219 +++ b/foo/bar/z.txt
220 @@ -1,1 +1,2 @@
220 @@ -1,1 +1,2 @@
221 z1
221 z1
222 +z2
222 +z2
223
223
224 Enable progress extension for archive tests:
224 Enable progress extension for archive tests:
225
225
226 $ cp $HGRCPATH $HGRCPATH.no-progress
226 $ cp $HGRCPATH $HGRCPATH.no-progress
227 $ cat >> $HGRCPATH <<EOF
227 $ cat >> $HGRCPATH <<EOF
228 > [extensions]
228 > [extensions]
229 > progress =
229 > progress =
230 > [progress]
230 > [progress]
231 > assume-tty = 1
231 > assume-tty = 1
232 > delay = 0
232 > delay = 0
233 > format = topic bar number
233 > format = topic bar number
234 > refresh = 0
234 > refresh = 0
235 > width = 60
235 > width = 60
236 > EOF
236 > EOF
237
237
238 Test archiving to a directory tree (the doubled lines in the output
238 Test archiving to a directory tree (the doubled lines in the output
239 only show up in the test output, not in real usage):
239 only show up in the test output, not in real usage):
240
240
241 $ hg archive --subrepos ../archive 2>&1 | $TESTDIR/filtercr.py
241 $ hg archive --subrepos ../archive 2>&1 | $TESTDIR/filtercr.py
242
242
243 archiving [ ] 0/3
243 archiving [ ] 0/3
244 archiving [ ] 0/3
244 archiving [ ] 0/3
245 archiving [=============> ] 1/3
245 archiving [=============> ] 1/3
246 archiving [=============> ] 1/3
246 archiving [=============> ] 1/3
247 archiving [===========================> ] 2/3
247 archiving [===========================> ] 2/3
248 archiving [===========================> ] 2/3
248 archiving [===========================> ] 2/3
249 archiving [==========================================>] 3/3
249 archiving [==========================================>] 3/3
250 archiving [==========================================>] 3/3
250 archiving [==========================================>] 3/3
251
251
252 archiving (foo) [ ] 0/3
252 archiving (foo) [ ] 0/3
253 archiving (foo) [ ] 0/3
253 archiving (foo) [ ] 0/3
254 archiving (foo) [===========> ] 1/3
254 archiving (foo) [===========> ] 1/3
255 archiving (foo) [===========> ] 1/3
255 archiving (foo) [===========> ] 1/3
256 archiving (foo) [=======================> ] 2/3
256 archiving (foo) [=======================> ] 2/3
257 archiving (foo) [=======================> ] 2/3
257 archiving (foo) [=======================> ] 2/3
258 archiving (foo) [====================================>] 3/3
258 archiving (foo) [====================================>] 3/3
259 archiving (foo) [====================================>] 3/3
259 archiving (foo) [====================================>] 3/3
260
260
261 archiving (foo/bar) [ ] 0/1
261 archiving (foo/bar) [ ] 0/1
262 archiving (foo/bar) [ ] 0/1
262 archiving (foo/bar) [ ] 0/1
263 archiving (foo/bar) [================================>] 1/1
263 archiving (foo/bar) [================================>] 1/1
264 archiving (foo/bar) [================================>] 1/1
264 archiving (foo/bar) [================================>] 1/1
265 \r (esc)
265 \r (esc)
266 $ find ../archive | sort
266 $ find ../archive | sort
267 ../archive
267 ../archive
268 ../archive/.hg_archival.txt
268 ../archive/.hg_archival.txt
269 ../archive/.hgsub
269 ../archive/.hgsub
270 ../archive/.hgsubstate
270 ../archive/.hgsubstate
271 ../archive/foo
271 ../archive/foo
272 ../archive/foo/.hgsub
272 ../archive/foo/.hgsub
273 ../archive/foo/.hgsubstate
273 ../archive/foo/.hgsubstate
274 ../archive/foo/bar
274 ../archive/foo/bar
275 ../archive/foo/bar/z.txt
275 ../archive/foo/bar/z.txt
276 ../archive/foo/y.txt
276 ../archive/foo/y.txt
277 ../archive/x.txt
277 ../archive/x.txt
278
278
279 Test archiving to zip file (unzip output is unstable):
279 Test archiving to zip file (unzip output is unstable):
280
280
281 $ hg archive --subrepos ../archive.zip 2>&1 | $TESTDIR/filtercr.py
281 $ hg archive --subrepos ../archive.zip 2>&1 | $TESTDIR/filtercr.py
282
282
283 archiving [ ] 0/3
283 archiving [ ] 0/3
284 archiving [ ] 0/3
284 archiving [ ] 0/3
285 archiving [=============> ] 1/3
285 archiving [=============> ] 1/3
286 archiving [=============> ] 1/3
286 archiving [=============> ] 1/3
287 archiving [===========================> ] 2/3
287 archiving [===========================> ] 2/3
288 archiving [===========================> ] 2/3
288 archiving [===========================> ] 2/3
289 archiving [==========================================>] 3/3
289 archiving [==========================================>] 3/3
290 archiving [==========================================>] 3/3
290 archiving [==========================================>] 3/3
291
291
292 archiving (foo) [ ] 0/3
292 archiving (foo) [ ] 0/3
293 archiving (foo) [ ] 0/3
293 archiving (foo) [ ] 0/3
294 archiving (foo) [===========> ] 1/3
294 archiving (foo) [===========> ] 1/3
295 archiving (foo) [===========> ] 1/3
295 archiving (foo) [===========> ] 1/3
296 archiving (foo) [=======================> ] 2/3
296 archiving (foo) [=======================> ] 2/3
297 archiving (foo) [=======================> ] 2/3
297 archiving (foo) [=======================> ] 2/3
298 archiving (foo) [====================================>] 3/3
298 archiving (foo) [====================================>] 3/3
299 archiving (foo) [====================================>] 3/3
299 archiving (foo) [====================================>] 3/3
300
300
301 archiving (foo/bar) [ ] 0/1
301 archiving (foo/bar) [ ] 0/1
302 archiving (foo/bar) [ ] 0/1
302 archiving (foo/bar) [ ] 0/1
303 archiving (foo/bar) [================================>] 1/1
303 archiving (foo/bar) [================================>] 1/1
304 archiving (foo/bar) [================================>] 1/1
304 archiving (foo/bar) [================================>] 1/1
305 \r (esc)
305 \r (esc)
306
306
307 Disable progress extension and cleanup:
307 Disable progress extension and cleanup:
308
308
309 $ mv $HGRCPATH.no-progress $HGRCPATH
309 $ mv $HGRCPATH.no-progress $HGRCPATH
310
310
311 Clone and test outgoing:
311 Clone and test outgoing:
312
312
313 $ cd ..
313 $ cd ..
314 $ hg clone repo repo2
314 $ hg clone repo repo2
315 updating to branch default
315 updating to branch default
316 pulling subrepo foo from $TESTTMP/repo/foo
316 pulling subrepo foo from $TESTTMP/repo/foo
317 requesting all changes
317 requesting all changes
318 adding changesets
318 adding changesets
319 adding manifests
319 adding manifests
320 adding file changes
320 adding file changes
321 added 4 changesets with 7 changes to 3 files
321 added 4 changesets with 7 changes to 3 files
322 pulling subrepo foo/bar from $TESTTMP/repo/foo/bar
322 pulling subrepo foo/bar from $TESTTMP/repo/foo/bar
323 requesting all changes
323 requesting all changes
324 adding changesets
324 adding changesets
325 adding manifests
325 adding manifests
326 adding file changes
326 adding file changes
327 added 3 changesets with 3 changes to 1 files
327 added 3 changesets with 3 changes to 1 files
328 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
328 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 $ cd repo2
329 $ cd repo2
330 $ hg outgoing -S
330 $ hg outgoing -S
331 comparing with $TESTTMP/repo
331 comparing with $TESTTMP/repo
332 searching for changes
332 searching for changes
333 no changes found
333 no changes found
334 comparing with $TESTTMP/repo/foo
334 comparing with $TESTTMP/repo/foo
335 searching for changes
335 searching for changes
336 no changes found
336 no changes found
337 comparing with $TESTTMP/repo/foo/bar
337 comparing with $TESTTMP/repo/foo/bar
338 searching for changes
338 searching for changes
339 no changes found
339 no changes found
340 [1]
340 [1]
341
341
342 Make nested change:
342 Make nested change:
343
343
344 $ echo y4 >> foo/y.txt
344 $ echo y4 >> foo/y.txt
345 $ hg diff --nodates -S
345 $ hg diff --nodates -S
346 diff -r 65903cebad86 foo/y.txt
346 diff -r 65903cebad86 foo/y.txt
347 --- a/foo/y.txt
347 --- a/foo/y.txt
348 +++ b/foo/y.txt
348 +++ b/foo/y.txt
349 @@ -1,3 +1,4 @@
349 @@ -1,3 +1,4 @@
350 y1
350 y1
351 y2
351 y2
352 y3
352 y3
353 +y4
353 +y4
354 $ hg commit -m 3-4-2
354 $ hg commit -m 3-4-2
355 committing subrepository foo
355 committing subrepository foo
356 $ hg outgoing -S
356 $ hg outgoing -S
357 comparing with $TESTTMP/repo
357 comparing with $TESTTMP/repo
358 searching for changes
358 searching for changes
359 changeset: 3:2655b8ecc4ee
359 changeset: 3:2655b8ecc4ee
360 tag: tip
360 tag: tip
361 user: test
361 user: test
362 date: Thu Jan 01 00:00:00 1970 +0000
362 date: Thu Jan 01 00:00:00 1970 +0000
363 summary: 3-4-2
363 summary: 3-4-2
364
364
365 comparing with $TESTTMP/repo/foo
365 comparing with $TESTTMP/repo/foo
366 searching for changes
366 searching for changes
367 changeset: 4:e96193d6cb36
367 changeset: 4:e96193d6cb36
368 tag: tip
368 tag: tip
369 user: test
369 user: test
370 date: Thu Jan 01 00:00:00 1970 +0000
370 date: Thu Jan 01 00:00:00 1970 +0000
371 summary: 3-4-2
371 summary: 3-4-2
372
372
373 comparing with $TESTTMP/repo/foo/bar
373 comparing with $TESTTMP/repo/foo/bar
374 searching for changes
374 searching for changes
375 no changes found
375 no changes found
376
376
377
377
378 Switch to original repo and setup default path:
378 Switch to original repo and setup default path:
379
379
380 $ cd ../repo
380 $ cd ../repo
381 $ echo '[paths]' >> .hg/hgrc
381 $ echo '[paths]' >> .hg/hgrc
382 $ echo 'default = ../repo2' >> .hg/hgrc
382 $ echo 'default = ../repo2' >> .hg/hgrc
383
383
384 Test incoming:
384 Test incoming:
385
385
386 $ hg incoming -S
386 $ hg incoming -S
387 comparing with $TESTTMP/repo2
387 comparing with $TESTTMP/repo2
388 searching for changes
388 searching for changes
389 changeset: 3:2655b8ecc4ee
389 changeset: 3:2655b8ecc4ee
390 tag: tip
390 tag: tip
391 user: test
391 user: test
392 date: Thu Jan 01 00:00:00 1970 +0000
392 date: Thu Jan 01 00:00:00 1970 +0000
393 summary: 3-4-2
393 summary: 3-4-2
394
394
395 comparing with $TESTTMP/repo2/foo
395 comparing with $TESTTMP/repo2/foo
396 searching for changes
396 searching for changes
397 changeset: 4:e96193d6cb36
397 changeset: 4:e96193d6cb36
398 tag: tip
398 tag: tip
399 user: test
399 user: test
400 date: Thu Jan 01 00:00:00 1970 +0000
400 date: Thu Jan 01 00:00:00 1970 +0000
401 summary: 3-4-2
401 summary: 3-4-2
402
402
403 comparing with $TESTTMP/repo2/foo/bar
403 comparing with $TESTTMP/repo2/foo/bar
404 searching for changes
404 searching for changes
405 no changes found
405 no changes found
406
406
407 $ hg incoming -S --bundle incoming.hg
407 $ hg incoming -S --bundle incoming.hg
408 abort: cannot combine --bundle and --subrepos
408 abort: cannot combine --bundle and --subrepos
409 [255]
409 [255]
410
410
411 Test missing subrepo:
411 Test missing subrepo:
412
412
413 $ rm -r foo
413 $ rm -r foo
414 $ hg status -S
414 $ hg status -S
415 warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
415 warning: error "unknown revision '65903cebad86f1a84bd4f1134f62fa7dcb7a1c98'" in subrepository "foo"
416
417 Issue2619: IndexError: list index out of range on hg add with subrepos
418 The subrepo must sorts after the explicit filename.
419
420 $ cd ..
421 $ hg init test
422 $ cd test
423 $ hg init x
424 $ echo "x = x" >> .hgsub
425 $ hg add .hgsub
426 $ touch a x/a
427 $ hg add a x/a
General Comments 0
You need to be logged in to leave comments. Login now