##// END OF EJS Templates
bundle: treat branches created newly on the local correctly (issue3828)...
FUJIWARA Katsunori -
r18701:61c8327c stable
parent child Browse files
Show More
@@ -1,6054 +1,6054 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, 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, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 hg.clean(repo, node, show_stats=False)
459 hg.clean(repo, node, show_stats=False)
460 repo.dirstate.setbranch(branch)
460 repo.dirstate.setbranch(branch)
461 revert_opts = opts.copy()
461 revert_opts = opts.copy()
462 revert_opts['date'] = None
462 revert_opts['date'] = None
463 revert_opts['all'] = True
463 revert_opts['all'] = True
464 revert_opts['rev'] = hex(parent)
464 revert_opts['rev'] = hex(parent)
465 revert_opts['no_backup'] = None
465 revert_opts['no_backup'] = None
466 revert(ui, repo, **revert_opts)
466 revert(ui, repo, **revert_opts)
467 if not opts.get('merge') and op1 != node:
467 if not opts.get('merge') and op1 != node:
468 try:
468 try:
469 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
469 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
470 return hg.update(repo, op1)
470 return hg.update(repo, op1)
471 finally:
471 finally:
472 ui.setconfig('ui', 'forcemerge', '')
472 ui.setconfig('ui', 'forcemerge', '')
473
473
474 commit_opts = opts.copy()
474 commit_opts = opts.copy()
475 commit_opts['addremove'] = False
475 commit_opts['addremove'] = False
476 if not commit_opts['message'] and not commit_opts['logfile']:
476 if not commit_opts['message'] and not commit_opts['logfile']:
477 # we don't translate commit messages
477 # we don't translate commit messages
478 commit_opts['message'] = "Backed out changeset %s" % short(node)
478 commit_opts['message'] = "Backed out changeset %s" % short(node)
479 commit_opts['force_editor'] = True
479 commit_opts['force_editor'] = True
480 commit(ui, repo, **commit_opts)
480 commit(ui, repo, **commit_opts)
481 def nice(node):
481 def nice(node):
482 return '%d:%s' % (repo.changelog.rev(node), short(node))
482 return '%d:%s' % (repo.changelog.rev(node), short(node))
483 ui.status(_('changeset %s backs out changeset %s\n') %
483 ui.status(_('changeset %s backs out changeset %s\n') %
484 (nice(repo.changelog.tip()), nice(node)))
484 (nice(repo.changelog.tip()), nice(node)))
485 if opts.get('merge') and op1 != node:
485 if opts.get('merge') and op1 != node:
486 hg.clean(repo, op1, show_stats=False)
486 hg.clean(repo, op1, show_stats=False)
487 ui.status(_('merging with changeset %s\n')
487 ui.status(_('merging with changeset %s\n')
488 % nice(repo.changelog.tip()))
488 % nice(repo.changelog.tip()))
489 try:
489 try:
490 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
490 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
491 return hg.merge(repo, hex(repo.changelog.tip()))
491 return hg.merge(repo, hex(repo.changelog.tip()))
492 finally:
492 finally:
493 ui.setconfig('ui', 'forcemerge', '')
493 ui.setconfig('ui', 'forcemerge', '')
494 finally:
494 finally:
495 wlock.release()
495 wlock.release()
496 return 0
496 return 0
497
497
498 @command('bisect',
498 @command('bisect',
499 [('r', 'reset', False, _('reset bisect state')),
499 [('r', 'reset', False, _('reset bisect state')),
500 ('g', 'good', False, _('mark changeset good')),
500 ('g', 'good', False, _('mark changeset good')),
501 ('b', 'bad', False, _('mark changeset bad')),
501 ('b', 'bad', False, _('mark changeset bad')),
502 ('s', 'skip', False, _('skip testing changeset')),
502 ('s', 'skip', False, _('skip testing changeset')),
503 ('e', 'extend', False, _('extend the bisect range')),
503 ('e', 'extend', False, _('extend the bisect range')),
504 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
504 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
505 ('U', 'noupdate', False, _('do not update to target'))],
505 ('U', 'noupdate', False, _('do not update to target'))],
506 _("[-gbsr] [-U] [-c CMD] [REV]"))
506 _("[-gbsr] [-U] [-c CMD] [REV]"))
507 def bisect(ui, repo, rev=None, extra=None, command=None,
507 def bisect(ui, repo, rev=None, extra=None, command=None,
508 reset=None, good=None, bad=None, skip=None, extend=None,
508 reset=None, good=None, bad=None, skip=None, extend=None,
509 noupdate=None):
509 noupdate=None):
510 """subdivision search of changesets
510 """subdivision search of changesets
511
511
512 This command helps to find changesets which introduce problems. To
512 This command helps to find changesets which introduce problems. To
513 use, mark the earliest changeset you know exhibits the problem as
513 use, mark the earliest changeset you know exhibits the problem as
514 bad, then mark the latest changeset which is free from the problem
514 bad, then mark the latest changeset which is free from the problem
515 as good. Bisect will update your working directory to a revision
515 as good. Bisect will update your working directory to a revision
516 for testing (unless the -U/--noupdate option is specified). Once
516 for testing (unless the -U/--noupdate option is specified). Once
517 you have performed tests, mark the working directory as good or
517 you have performed tests, mark the working directory as good or
518 bad, and bisect will either update to another candidate changeset
518 bad, and bisect will either update to another candidate changeset
519 or announce that it has found the bad revision.
519 or announce that it has found the bad revision.
520
520
521 As a shortcut, you can also use the revision argument to mark a
521 As a shortcut, you can also use the revision argument to mark a
522 revision as good or bad without checking it out first.
522 revision as good or bad without checking it out first.
523
523
524 If you supply a command, it will be used for automatic bisection.
524 If you supply a command, it will be used for automatic bisection.
525 The environment variable HG_NODE will contain the ID of the
525 The environment variable HG_NODE will contain the ID of the
526 changeset being tested. The exit status of the command will be
526 changeset being tested. The exit status of the command will be
527 used to mark revisions as good or bad: status 0 means good, 125
527 used to mark revisions as good or bad: status 0 means good, 125
528 means to skip the revision, 127 (command not found) will abort the
528 means to skip the revision, 127 (command not found) will abort the
529 bisection, and any other non-zero exit status means the revision
529 bisection, and any other non-zero exit status means the revision
530 is bad.
530 is bad.
531
531
532 .. container:: verbose
532 .. container:: verbose
533
533
534 Some examples:
534 Some examples:
535
535
536 - start a bisection with known bad revision 12, and good revision 34::
536 - start a bisection with known bad revision 12, and good revision 34::
537
537
538 hg bisect --bad 34
538 hg bisect --bad 34
539 hg bisect --good 12
539 hg bisect --good 12
540
540
541 - advance the current bisection by marking current revision as good or
541 - advance the current bisection by marking current revision as good or
542 bad::
542 bad::
543
543
544 hg bisect --good
544 hg bisect --good
545 hg bisect --bad
545 hg bisect --bad
546
546
547 - mark the current revision, or a known revision, to be skipped (e.g. if
547 - mark the current revision, or a known revision, to be skipped (e.g. if
548 that revision is not usable because of another issue)::
548 that revision is not usable because of another issue)::
549
549
550 hg bisect --skip
550 hg bisect --skip
551 hg bisect --skip 23
551 hg bisect --skip 23
552
552
553 - skip all revisions that do not touch directories ``foo`` or ``bar``
553 - skip all revisions that do not touch directories ``foo`` or ``bar``
554
554
555 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
555 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
556
556
557 - forget the current bisection::
557 - forget the current bisection::
558
558
559 hg bisect --reset
559 hg bisect --reset
560
560
561 - use 'make && make tests' to automatically find the first broken
561 - use 'make && make tests' to automatically find the first broken
562 revision::
562 revision::
563
563
564 hg bisect --reset
564 hg bisect --reset
565 hg bisect --bad 34
565 hg bisect --bad 34
566 hg bisect --good 12
566 hg bisect --good 12
567 hg bisect --command 'make && make tests'
567 hg bisect --command 'make && make tests'
568
568
569 - see all changesets whose states are already known in the current
569 - see all changesets whose states are already known in the current
570 bisection::
570 bisection::
571
571
572 hg log -r "bisect(pruned)"
572 hg log -r "bisect(pruned)"
573
573
574 - see the changeset currently being bisected (especially useful
574 - see the changeset currently being bisected (especially useful
575 if running with -U/--noupdate)::
575 if running with -U/--noupdate)::
576
576
577 hg log -r "bisect(current)"
577 hg log -r "bisect(current)"
578
578
579 - see all changesets that took part in the current bisection::
579 - see all changesets that took part in the current bisection::
580
580
581 hg log -r "bisect(range)"
581 hg log -r "bisect(range)"
582
582
583 - with the graphlog extension, you can even get a nice graph::
583 - with the graphlog extension, you can even get a nice graph::
584
584
585 hg log --graph -r "bisect(range)"
585 hg log --graph -r "bisect(range)"
586
586
587 See :hg:`help revsets` for more about the `bisect()` keyword.
587 See :hg:`help revsets` for more about the `bisect()` keyword.
588
588
589 Returns 0 on success.
589 Returns 0 on success.
590 """
590 """
591 def extendbisectrange(nodes, good):
591 def extendbisectrange(nodes, good):
592 # bisect is incomplete when it ends on a merge node and
592 # bisect is incomplete when it ends on a merge node and
593 # one of the parent was not checked.
593 # one of the parent was not checked.
594 parents = repo[nodes[0]].parents()
594 parents = repo[nodes[0]].parents()
595 if len(parents) > 1:
595 if len(parents) > 1:
596 side = good and state['bad'] or state['good']
596 side = good and state['bad'] or state['good']
597 num = len(set(i.node() for i in parents) & set(side))
597 num = len(set(i.node() for i in parents) & set(side))
598 if num == 1:
598 if num == 1:
599 return parents[0].ancestor(parents[1])
599 return parents[0].ancestor(parents[1])
600 return None
600 return None
601
601
602 def print_result(nodes, good):
602 def print_result(nodes, good):
603 displayer = cmdutil.show_changeset(ui, repo, {})
603 displayer = cmdutil.show_changeset(ui, repo, {})
604 if len(nodes) == 1:
604 if len(nodes) == 1:
605 # narrowed it down to a single revision
605 # narrowed it down to a single revision
606 if good:
606 if good:
607 ui.write(_("The first good revision is:\n"))
607 ui.write(_("The first good revision is:\n"))
608 else:
608 else:
609 ui.write(_("The first bad revision is:\n"))
609 ui.write(_("The first bad revision is:\n"))
610 displayer.show(repo[nodes[0]])
610 displayer.show(repo[nodes[0]])
611 extendnode = extendbisectrange(nodes, good)
611 extendnode = extendbisectrange(nodes, good)
612 if extendnode is not None:
612 if extendnode is not None:
613 ui.write(_('Not all ancestors of this changeset have been'
613 ui.write(_('Not all ancestors of this changeset have been'
614 ' checked.\nUse bisect --extend to continue the '
614 ' checked.\nUse bisect --extend to continue the '
615 'bisection from\nthe common ancestor, %s.\n')
615 'bisection from\nthe common ancestor, %s.\n')
616 % extendnode)
616 % extendnode)
617 else:
617 else:
618 # multiple possible revisions
618 # multiple possible revisions
619 if good:
619 if good:
620 ui.write(_("Due to skipped revisions, the first "
620 ui.write(_("Due to skipped revisions, the first "
621 "good revision could be any of:\n"))
621 "good revision could be any of:\n"))
622 else:
622 else:
623 ui.write(_("Due to skipped revisions, the first "
623 ui.write(_("Due to skipped revisions, the first "
624 "bad revision could be any of:\n"))
624 "bad revision could be any of:\n"))
625 for n in nodes:
625 for n in nodes:
626 displayer.show(repo[n])
626 displayer.show(repo[n])
627 displayer.close()
627 displayer.close()
628
628
629 def check_state(state, interactive=True):
629 def check_state(state, interactive=True):
630 if not state['good'] or not state['bad']:
630 if not state['good'] or not state['bad']:
631 if (good or bad or skip or reset) and interactive:
631 if (good or bad or skip or reset) and interactive:
632 return
632 return
633 if not state['good']:
633 if not state['good']:
634 raise util.Abort(_('cannot bisect (no known good revisions)'))
634 raise util.Abort(_('cannot bisect (no known good revisions)'))
635 else:
635 else:
636 raise util.Abort(_('cannot bisect (no known bad revisions)'))
636 raise util.Abort(_('cannot bisect (no known bad revisions)'))
637 return True
637 return True
638
638
639 # backward compatibility
639 # backward compatibility
640 if rev in "good bad reset init".split():
640 if rev in "good bad reset init".split():
641 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
641 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
642 cmd, rev, extra = rev, extra, None
642 cmd, rev, extra = rev, extra, None
643 if cmd == "good":
643 if cmd == "good":
644 good = True
644 good = True
645 elif cmd == "bad":
645 elif cmd == "bad":
646 bad = True
646 bad = True
647 else:
647 else:
648 reset = True
648 reset = True
649 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
649 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
650 raise util.Abort(_('incompatible arguments'))
650 raise util.Abort(_('incompatible arguments'))
651
651
652 if reset:
652 if reset:
653 p = repo.join("bisect.state")
653 p = repo.join("bisect.state")
654 if os.path.exists(p):
654 if os.path.exists(p):
655 os.unlink(p)
655 os.unlink(p)
656 return
656 return
657
657
658 state = hbisect.load_state(repo)
658 state = hbisect.load_state(repo)
659
659
660 if command:
660 if command:
661 changesets = 1
661 changesets = 1
662 try:
662 try:
663 node = state['current'][0]
663 node = state['current'][0]
664 except LookupError:
664 except LookupError:
665 if noupdate:
665 if noupdate:
666 raise util.Abort(_('current bisect revision is unknown - '
666 raise util.Abort(_('current bisect revision is unknown - '
667 'start a new bisect to fix'))
667 'start a new bisect to fix'))
668 node, p2 = repo.dirstate.parents()
668 node, p2 = repo.dirstate.parents()
669 if p2 != nullid:
669 if p2 != nullid:
670 raise util.Abort(_('current bisect revision is a merge'))
670 raise util.Abort(_('current bisect revision is a merge'))
671 try:
671 try:
672 while changesets:
672 while changesets:
673 # update state
673 # update state
674 state['current'] = [node]
674 state['current'] = [node]
675 hbisect.save_state(repo, state)
675 hbisect.save_state(repo, state)
676 status = util.system(command,
676 status = util.system(command,
677 environ={'HG_NODE': hex(node)},
677 environ={'HG_NODE': hex(node)},
678 out=ui.fout)
678 out=ui.fout)
679 if status == 125:
679 if status == 125:
680 transition = "skip"
680 transition = "skip"
681 elif status == 0:
681 elif status == 0:
682 transition = "good"
682 transition = "good"
683 # status < 0 means process was killed
683 # status < 0 means process was killed
684 elif status == 127:
684 elif status == 127:
685 raise util.Abort(_("failed to execute %s") % command)
685 raise util.Abort(_("failed to execute %s") % command)
686 elif status < 0:
686 elif status < 0:
687 raise util.Abort(_("%s killed") % command)
687 raise util.Abort(_("%s killed") % command)
688 else:
688 else:
689 transition = "bad"
689 transition = "bad"
690 ctx = scmutil.revsingle(repo, rev, node)
690 ctx = scmutil.revsingle(repo, rev, node)
691 rev = None # clear for future iterations
691 rev = None # clear for future iterations
692 state[transition].append(ctx.node())
692 state[transition].append(ctx.node())
693 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
693 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
694 check_state(state, interactive=False)
694 check_state(state, interactive=False)
695 # bisect
695 # bisect
696 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
696 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
697 # update to next check
697 # update to next check
698 node = nodes[0]
698 node = nodes[0]
699 if not noupdate:
699 if not noupdate:
700 cmdutil.bailifchanged(repo)
700 cmdutil.bailifchanged(repo)
701 hg.clean(repo, node, show_stats=False)
701 hg.clean(repo, node, show_stats=False)
702 finally:
702 finally:
703 state['current'] = [node]
703 state['current'] = [node]
704 hbisect.save_state(repo, state)
704 hbisect.save_state(repo, state)
705 print_result(nodes, good)
705 print_result(nodes, good)
706 return
706 return
707
707
708 # update state
708 # update state
709
709
710 if rev:
710 if rev:
711 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
711 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
712 else:
712 else:
713 nodes = [repo.lookup('.')]
713 nodes = [repo.lookup('.')]
714
714
715 if good or bad or skip:
715 if good or bad or skip:
716 if good:
716 if good:
717 state['good'] += nodes
717 state['good'] += nodes
718 elif bad:
718 elif bad:
719 state['bad'] += nodes
719 state['bad'] += nodes
720 elif skip:
720 elif skip:
721 state['skip'] += nodes
721 state['skip'] += nodes
722 hbisect.save_state(repo, state)
722 hbisect.save_state(repo, state)
723
723
724 if not check_state(state):
724 if not check_state(state):
725 return
725 return
726
726
727 # actually bisect
727 # actually bisect
728 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
728 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
729 if extend:
729 if extend:
730 if not changesets:
730 if not changesets:
731 extendnode = extendbisectrange(nodes, good)
731 extendnode = extendbisectrange(nodes, good)
732 if extendnode is not None:
732 if extendnode is not None:
733 ui.write(_("Extending search to changeset %d:%s\n"
733 ui.write(_("Extending search to changeset %d:%s\n"
734 % (extendnode.rev(), extendnode)))
734 % (extendnode.rev(), extendnode)))
735 state['current'] = [extendnode.node()]
735 state['current'] = [extendnode.node()]
736 hbisect.save_state(repo, state)
736 hbisect.save_state(repo, state)
737 if noupdate:
737 if noupdate:
738 return
738 return
739 cmdutil.bailifchanged(repo)
739 cmdutil.bailifchanged(repo)
740 return hg.clean(repo, extendnode.node())
740 return hg.clean(repo, extendnode.node())
741 raise util.Abort(_("nothing to extend"))
741 raise util.Abort(_("nothing to extend"))
742
742
743 if changesets == 0:
743 if changesets == 0:
744 print_result(nodes, good)
744 print_result(nodes, good)
745 else:
745 else:
746 assert len(nodes) == 1 # only a single node can be tested next
746 assert len(nodes) == 1 # only a single node can be tested next
747 node = nodes[0]
747 node = nodes[0]
748 # compute the approximate number of remaining tests
748 # compute the approximate number of remaining tests
749 tests, size = 0, 2
749 tests, size = 0, 2
750 while size <= changesets:
750 while size <= changesets:
751 tests, size = tests + 1, size * 2
751 tests, size = tests + 1, size * 2
752 rev = repo.changelog.rev(node)
752 rev = repo.changelog.rev(node)
753 ui.write(_("Testing changeset %d:%s "
753 ui.write(_("Testing changeset %d:%s "
754 "(%d changesets remaining, ~%d tests)\n")
754 "(%d changesets remaining, ~%d tests)\n")
755 % (rev, short(node), changesets, tests))
755 % (rev, short(node), changesets, tests))
756 state['current'] = [node]
756 state['current'] = [node]
757 hbisect.save_state(repo, state)
757 hbisect.save_state(repo, state)
758 if not noupdate:
758 if not noupdate:
759 cmdutil.bailifchanged(repo)
759 cmdutil.bailifchanged(repo)
760 return hg.clean(repo, node)
760 return hg.clean(repo, node)
761
761
762 @command('bookmarks|bookmark',
762 @command('bookmarks|bookmark',
763 [('f', 'force', False, _('force')),
763 [('f', 'force', False, _('force')),
764 ('r', 'rev', '', _('revision'), _('REV')),
764 ('r', 'rev', '', _('revision'), _('REV')),
765 ('d', 'delete', False, _('delete a given bookmark')),
765 ('d', 'delete', False, _('delete a given bookmark')),
766 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
766 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
767 ('i', 'inactive', False, _('mark a bookmark inactive'))],
767 ('i', 'inactive', False, _('mark a bookmark inactive'))],
768 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
768 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
769 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
769 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
770 rename=None, inactive=False):
770 rename=None, inactive=False):
771 '''track a line of development with movable markers
771 '''track a line of development with movable markers
772
772
773 Bookmarks are pointers to certain commits that move when committing.
773 Bookmarks are pointers to certain commits that move when committing.
774 Bookmarks are local. They can be renamed, copied and deleted. It is
774 Bookmarks are local. They can be renamed, copied and deleted. It is
775 possible to use :hg:`merge NAME` to merge from a given bookmark, and
775 possible to use :hg:`merge NAME` to merge from a given bookmark, and
776 :hg:`update NAME` to update to a given bookmark.
776 :hg:`update NAME` to update to a given bookmark.
777
777
778 You can use :hg:`bookmark NAME` to set a bookmark on the working
778 You can use :hg:`bookmark NAME` to set a bookmark on the working
779 directory's parent revision with the given name. If you specify
779 directory's parent revision with the given name. If you specify
780 a revision using -r REV (where REV may be an existing bookmark),
780 a revision using -r REV (where REV may be an existing bookmark),
781 the bookmark is assigned to that revision.
781 the bookmark is assigned to that revision.
782
782
783 Bookmarks can be pushed and pulled between repositories (see :hg:`help
783 Bookmarks can be pushed and pulled between repositories (see :hg:`help
784 push` and :hg:`help pull`). This requires both the local and remote
784 push` and :hg:`help pull`). This requires both the local and remote
785 repositories to support bookmarks. For versions prior to 1.8, this means
785 repositories to support bookmarks. For versions prior to 1.8, this means
786 the bookmarks extension must be enabled.
786 the bookmarks extension must be enabled.
787
787
788 If you set a bookmark called '@', new clones of the repository will
788 If you set a bookmark called '@', new clones of the repository will
789 have that revision checked out (and the bookmark made active) by
789 have that revision checked out (and the bookmark made active) by
790 default.
790 default.
791
791
792 With -i/--inactive, the new bookmark will not be made the active
792 With -i/--inactive, the new bookmark will not be made the active
793 bookmark. If -r/--rev is given, the new bookmark will not be made
793 bookmark. If -r/--rev is given, the new bookmark will not be made
794 active even if -i/--inactive is not given. If no NAME is given, the
794 active even if -i/--inactive is not given. If no NAME is given, the
795 current active bookmark will be marked inactive.
795 current active bookmark will be marked inactive.
796 '''
796 '''
797 hexfn = ui.debugflag and hex or short
797 hexfn = ui.debugflag and hex or short
798 marks = repo._bookmarks
798 marks = repo._bookmarks
799 cur = repo.changectx('.').node()
799 cur = repo.changectx('.').node()
800
800
801 def checkformat(mark):
801 def checkformat(mark):
802 mark = mark.strip()
802 mark = mark.strip()
803 if not mark:
803 if not mark:
804 raise util.Abort(_("bookmark names cannot consist entirely of "
804 raise util.Abort(_("bookmark names cannot consist entirely of "
805 "whitespace"))
805 "whitespace"))
806 scmutil.checknewlabel(repo, mark, 'bookmark')
806 scmutil.checknewlabel(repo, mark, 'bookmark')
807 return mark
807 return mark
808
808
809 def checkconflict(repo, mark, force=False):
809 def checkconflict(repo, mark, force=False):
810 if mark in marks and not force:
810 if mark in marks and not force:
811 raise util.Abort(_("bookmark '%s' already exists "
811 raise util.Abort(_("bookmark '%s' already exists "
812 "(use -f to force)") % mark)
812 "(use -f to force)") % mark)
813 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
813 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
814 and not force):
814 and not force):
815 raise util.Abort(
815 raise util.Abort(
816 _("a bookmark cannot have the name of an existing branch"))
816 _("a bookmark cannot have the name of an existing branch"))
817
817
818 if delete and rename:
818 if delete and rename:
819 raise util.Abort(_("--delete and --rename are incompatible"))
819 raise util.Abort(_("--delete and --rename are incompatible"))
820 if delete and rev:
820 if delete and rev:
821 raise util.Abort(_("--rev is incompatible with --delete"))
821 raise util.Abort(_("--rev is incompatible with --delete"))
822 if rename and rev:
822 if rename and rev:
823 raise util.Abort(_("--rev is incompatible with --rename"))
823 raise util.Abort(_("--rev is incompatible with --rename"))
824 if mark is None and (delete or rev):
824 if mark is None and (delete or rev):
825 raise util.Abort(_("bookmark name required"))
825 raise util.Abort(_("bookmark name required"))
826
826
827 if delete:
827 if delete:
828 if mark not in marks:
828 if mark not in marks:
829 raise util.Abort(_("bookmark '%s' does not exist") % mark)
829 raise util.Abort(_("bookmark '%s' does not exist") % mark)
830 if mark == repo._bookmarkcurrent:
830 if mark == repo._bookmarkcurrent:
831 bookmarks.setcurrent(repo, None)
831 bookmarks.setcurrent(repo, None)
832 del marks[mark]
832 del marks[mark]
833 marks.write()
833 marks.write()
834
834
835 elif rename:
835 elif rename:
836 if mark is None:
836 if mark is None:
837 raise util.Abort(_("new bookmark name required"))
837 raise util.Abort(_("new bookmark name required"))
838 mark = checkformat(mark)
838 mark = checkformat(mark)
839 if rename not in marks:
839 if rename not in marks:
840 raise util.Abort(_("bookmark '%s' does not exist") % rename)
840 raise util.Abort(_("bookmark '%s' does not exist") % rename)
841 checkconflict(repo, mark, force)
841 checkconflict(repo, mark, force)
842 marks[mark] = marks[rename]
842 marks[mark] = marks[rename]
843 if repo._bookmarkcurrent == rename and not inactive:
843 if repo._bookmarkcurrent == rename and not inactive:
844 bookmarks.setcurrent(repo, mark)
844 bookmarks.setcurrent(repo, mark)
845 del marks[rename]
845 del marks[rename]
846 marks.write()
846 marks.write()
847
847
848 elif mark is not None:
848 elif mark is not None:
849 mark = checkformat(mark)
849 mark = checkformat(mark)
850 if inactive and mark == repo._bookmarkcurrent:
850 if inactive and mark == repo._bookmarkcurrent:
851 bookmarks.setcurrent(repo, None)
851 bookmarks.setcurrent(repo, None)
852 return
852 return
853 checkconflict(repo, mark, force)
853 checkconflict(repo, mark, force)
854 if rev:
854 if rev:
855 marks[mark] = scmutil.revsingle(repo, rev).node()
855 marks[mark] = scmutil.revsingle(repo, rev).node()
856 else:
856 else:
857 marks[mark] = cur
857 marks[mark] = cur
858 if not inactive and cur == marks[mark]:
858 if not inactive and cur == marks[mark]:
859 bookmarks.setcurrent(repo, mark)
859 bookmarks.setcurrent(repo, mark)
860 marks.write()
860 marks.write()
861
861
862 # Same message whether trying to deactivate the current bookmark (-i
862 # Same message whether trying to deactivate the current bookmark (-i
863 # with no NAME) or listing bookmarks
863 # with no NAME) or listing bookmarks
864 elif len(marks) == 0:
864 elif len(marks) == 0:
865 ui.status(_("no bookmarks set\n"))
865 ui.status(_("no bookmarks set\n"))
866
866
867 elif inactive:
867 elif inactive:
868 if not repo._bookmarkcurrent:
868 if not repo._bookmarkcurrent:
869 ui.status(_("no active bookmark\n"))
869 ui.status(_("no active bookmark\n"))
870 else:
870 else:
871 bookmarks.setcurrent(repo, None)
871 bookmarks.setcurrent(repo, None)
872
872
873 else: # show bookmarks
873 else: # show bookmarks
874 for bmark, n in sorted(marks.iteritems()):
874 for bmark, n in sorted(marks.iteritems()):
875 current = repo._bookmarkcurrent
875 current = repo._bookmarkcurrent
876 if bmark == current:
876 if bmark == current:
877 prefix, label = '*', 'bookmarks.current'
877 prefix, label = '*', 'bookmarks.current'
878 else:
878 else:
879 prefix, label = ' ', ''
879 prefix, label = ' ', ''
880
880
881 if ui.quiet:
881 if ui.quiet:
882 ui.write("%s\n" % bmark, label=label)
882 ui.write("%s\n" % bmark, label=label)
883 else:
883 else:
884 ui.write(" %s %-25s %d:%s\n" % (
884 ui.write(" %s %-25s %d:%s\n" % (
885 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
885 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
886 label=label)
886 label=label)
887
887
888 @command('branch',
888 @command('branch',
889 [('f', 'force', None,
889 [('f', 'force', None,
890 _('set branch name even if it shadows an existing branch')),
890 _('set branch name even if it shadows an existing branch')),
891 ('C', 'clean', None, _('reset branch name to parent branch name'))],
891 ('C', 'clean', None, _('reset branch name to parent branch name'))],
892 _('[-fC] [NAME]'))
892 _('[-fC] [NAME]'))
893 def branch(ui, repo, label=None, **opts):
893 def branch(ui, repo, label=None, **opts):
894 """set or show the current branch name
894 """set or show the current branch name
895
895
896 .. note::
896 .. note::
897 Branch names are permanent and global. Use :hg:`bookmark` to create a
897 Branch names are permanent and global. Use :hg:`bookmark` to create a
898 light-weight bookmark instead. See :hg:`help glossary` for more
898 light-weight bookmark instead. See :hg:`help glossary` for more
899 information about named branches and bookmarks.
899 information about named branches and bookmarks.
900
900
901 With no argument, show the current branch name. With one argument,
901 With no argument, show the current branch name. With one argument,
902 set the working directory branch name (the branch will not exist
902 set the working directory branch name (the branch will not exist
903 in the repository until the next commit). Standard practice
903 in the repository until the next commit). Standard practice
904 recommends that primary development take place on the 'default'
904 recommends that primary development take place on the 'default'
905 branch.
905 branch.
906
906
907 Unless -f/--force is specified, branch will not let you set a
907 Unless -f/--force is specified, branch will not let you set a
908 branch name that already exists, even if it's inactive.
908 branch name that already exists, even if it's inactive.
909
909
910 Use -C/--clean to reset the working directory branch to that of
910 Use -C/--clean to reset the working directory branch to that of
911 the parent of the working directory, negating a previous branch
911 the parent of the working directory, negating a previous branch
912 change.
912 change.
913
913
914 Use the command :hg:`update` to switch to an existing branch. Use
914 Use the command :hg:`update` to switch to an existing branch. Use
915 :hg:`commit --close-branch` to mark this branch as closed.
915 :hg:`commit --close-branch` to mark this branch as closed.
916
916
917 Returns 0 on success.
917 Returns 0 on success.
918 """
918 """
919 if not opts.get('clean') and not label:
919 if not opts.get('clean') and not label:
920 ui.write("%s\n" % repo.dirstate.branch())
920 ui.write("%s\n" % repo.dirstate.branch())
921 return
921 return
922
922
923 wlock = repo.wlock()
923 wlock = repo.wlock()
924 try:
924 try:
925 if opts.get('clean'):
925 if opts.get('clean'):
926 label = repo[None].p1().branch()
926 label = repo[None].p1().branch()
927 repo.dirstate.setbranch(label)
927 repo.dirstate.setbranch(label)
928 ui.status(_('reset working directory to branch %s\n') % label)
928 ui.status(_('reset working directory to branch %s\n') % label)
929 elif label:
929 elif label:
930 if not opts.get('force') and label in repo.branchmap():
930 if not opts.get('force') and label in repo.branchmap():
931 if label not in [p.branch() for p in repo.parents()]:
931 if label not in [p.branch() for p in repo.parents()]:
932 raise util.Abort(_('a branch of the same name already'
932 raise util.Abort(_('a branch of the same name already'
933 ' exists'),
933 ' exists'),
934 # i18n: "it" refers to an existing branch
934 # i18n: "it" refers to an existing branch
935 hint=_("use 'hg update' to switch to it"))
935 hint=_("use 'hg update' to switch to it"))
936 scmutil.checknewlabel(repo, label, 'branch')
936 scmutil.checknewlabel(repo, label, 'branch')
937 repo.dirstate.setbranch(label)
937 repo.dirstate.setbranch(label)
938 ui.status(_('marked working directory as branch %s\n') % label)
938 ui.status(_('marked working directory as branch %s\n') % label)
939 ui.status(_('(branches are permanent and global, '
939 ui.status(_('(branches are permanent and global, '
940 'did you want a bookmark?)\n'))
940 'did you want a bookmark?)\n'))
941 finally:
941 finally:
942 wlock.release()
942 wlock.release()
943
943
944 @command('branches',
944 @command('branches',
945 [('a', 'active', False, _('show only branches that have unmerged heads')),
945 [('a', 'active', False, _('show only branches that have unmerged heads')),
946 ('c', 'closed', False, _('show normal and closed branches'))],
946 ('c', 'closed', False, _('show normal and closed branches'))],
947 _('[-ac]'))
947 _('[-ac]'))
948 def branches(ui, repo, active=False, closed=False):
948 def branches(ui, repo, active=False, closed=False):
949 """list repository named branches
949 """list repository named branches
950
950
951 List the repository's named branches, indicating which ones are
951 List the repository's named branches, indicating which ones are
952 inactive. If -c/--closed is specified, also list branches which have
952 inactive. If -c/--closed is specified, also list branches which have
953 been marked closed (see :hg:`commit --close-branch`).
953 been marked closed (see :hg:`commit --close-branch`).
954
954
955 If -a/--active is specified, only show active branches. A branch
955 If -a/--active is specified, only show active branches. A branch
956 is considered active if it contains repository heads.
956 is considered active if it contains repository heads.
957
957
958 Use the command :hg:`update` to switch to an existing branch.
958 Use the command :hg:`update` to switch to an existing branch.
959
959
960 Returns 0.
960 Returns 0.
961 """
961 """
962
962
963 hexfunc = ui.debugflag and hex or short
963 hexfunc = ui.debugflag and hex or short
964
964
965 activebranches = set([repo[n].branch() for n in repo.heads()])
965 activebranches = set([repo[n].branch() for n in repo.heads()])
966 branches = []
966 branches = []
967 for tag, heads in repo.branchmap().iteritems():
967 for tag, heads in repo.branchmap().iteritems():
968 for h in reversed(heads):
968 for h in reversed(heads):
969 ctx = repo[h]
969 ctx = repo[h]
970 isopen = not ctx.closesbranch()
970 isopen = not ctx.closesbranch()
971 if isopen:
971 if isopen:
972 tip = ctx
972 tip = ctx
973 break
973 break
974 else:
974 else:
975 tip = repo[heads[-1]]
975 tip = repo[heads[-1]]
976 isactive = tag in activebranches and isopen
976 isactive = tag in activebranches and isopen
977 branches.append((tip, isactive, isopen))
977 branches.append((tip, isactive, isopen))
978 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
978 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
979 reverse=True)
979 reverse=True)
980
980
981 for ctx, isactive, isopen in branches:
981 for ctx, isactive, isopen in branches:
982 if (not active) or isactive:
982 if (not active) or isactive:
983 if isactive:
983 if isactive:
984 label = 'branches.active'
984 label = 'branches.active'
985 notice = ''
985 notice = ''
986 elif not isopen:
986 elif not isopen:
987 if not closed:
987 if not closed:
988 continue
988 continue
989 label = 'branches.closed'
989 label = 'branches.closed'
990 notice = _(' (closed)')
990 notice = _(' (closed)')
991 else:
991 else:
992 label = 'branches.inactive'
992 label = 'branches.inactive'
993 notice = _(' (inactive)')
993 notice = _(' (inactive)')
994 if ctx.branch() == repo.dirstate.branch():
994 if ctx.branch() == repo.dirstate.branch():
995 label = 'branches.current'
995 label = 'branches.current'
996 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
996 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
997 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
997 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
998 'log.changeset changeset.%s' % ctx.phasestr())
998 'log.changeset changeset.%s' % ctx.phasestr())
999 tag = ui.label(ctx.branch(), label)
999 tag = ui.label(ctx.branch(), label)
1000 if ui.quiet:
1000 if ui.quiet:
1001 ui.write("%s\n" % tag)
1001 ui.write("%s\n" % tag)
1002 else:
1002 else:
1003 ui.write("%s %s%s\n" % (tag, rev, notice))
1003 ui.write("%s %s%s\n" % (tag, rev, notice))
1004
1004
1005 @command('bundle',
1005 @command('bundle',
1006 [('f', 'force', None, _('run even when the destination is unrelated')),
1006 [('f', 'force', None, _('run even when the destination is unrelated')),
1007 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1007 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1008 _('REV')),
1008 _('REV')),
1009 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1009 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1010 _('BRANCH')),
1010 _('BRANCH')),
1011 ('', 'base', [],
1011 ('', 'base', [],
1012 _('a base changeset assumed to be available at the destination'),
1012 _('a base changeset assumed to be available at the destination'),
1013 _('REV')),
1013 _('REV')),
1014 ('a', 'all', None, _('bundle all changesets in the repository')),
1014 ('a', 'all', None, _('bundle all changesets in the repository')),
1015 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1015 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1016 ] + remoteopts,
1016 ] + remoteopts,
1017 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1017 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1018 def bundle(ui, repo, fname, dest=None, **opts):
1018 def bundle(ui, repo, fname, dest=None, **opts):
1019 """create a changegroup file
1019 """create a changegroup file
1020
1020
1021 Generate a compressed changegroup file collecting changesets not
1021 Generate a compressed changegroup file collecting changesets not
1022 known to be in another repository.
1022 known to be in another repository.
1023
1023
1024 If you omit the destination repository, then hg assumes the
1024 If you omit the destination repository, then hg assumes the
1025 destination will have all the nodes you specify with --base
1025 destination will have all the nodes you specify with --base
1026 parameters. To create a bundle containing all changesets, use
1026 parameters. To create a bundle containing all changesets, use
1027 -a/--all (or --base null).
1027 -a/--all (or --base null).
1028
1028
1029 You can change compression method with the -t/--type option.
1029 You can change compression method with the -t/--type option.
1030 The available compression methods are: none, bzip2, and
1030 The available compression methods are: none, bzip2, and
1031 gzip (by default, bundles are compressed using bzip2).
1031 gzip (by default, bundles are compressed using bzip2).
1032
1032
1033 The bundle file can then be transferred using conventional means
1033 The bundle file can then be transferred using conventional means
1034 and applied to another repository with the unbundle or pull
1034 and applied to another repository with the unbundle or pull
1035 command. This is useful when direct push and pull are not
1035 command. This is useful when direct push and pull are not
1036 available or when exporting an entire repository is undesirable.
1036 available or when exporting an entire repository is undesirable.
1037
1037
1038 Applying bundles preserves all changeset contents including
1038 Applying bundles preserves all changeset contents including
1039 permissions, copy/rename information, and revision history.
1039 permissions, copy/rename information, and revision history.
1040
1040
1041 Returns 0 on success, 1 if no changes found.
1041 Returns 0 on success, 1 if no changes found.
1042 """
1042 """
1043 revs = None
1043 revs = None
1044 if 'rev' in opts:
1044 if 'rev' in opts:
1045 revs = scmutil.revrange(repo, opts['rev'])
1045 revs = scmutil.revrange(repo, opts['rev'])
1046
1046
1047 bundletype = opts.get('type', 'bzip2').lower()
1047 bundletype = opts.get('type', 'bzip2').lower()
1048 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1048 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1049 bundletype = btypes.get(bundletype)
1049 bundletype = btypes.get(bundletype)
1050 if bundletype not in changegroup.bundletypes:
1050 if bundletype not in changegroup.bundletypes:
1051 raise util.Abort(_('unknown bundle type specified with --type'))
1051 raise util.Abort(_('unknown bundle type specified with --type'))
1052
1052
1053 if opts.get('all'):
1053 if opts.get('all'):
1054 base = ['null']
1054 base = ['null']
1055 else:
1055 else:
1056 base = scmutil.revrange(repo, opts.get('base'))
1056 base = scmutil.revrange(repo, opts.get('base'))
1057 if base:
1057 if base:
1058 if dest:
1058 if dest:
1059 raise util.Abort(_("--base is incompatible with specifying "
1059 raise util.Abort(_("--base is incompatible with specifying "
1060 "a destination"))
1060 "a destination"))
1061 common = [repo.lookup(rev) for rev in base]
1061 common = [repo.lookup(rev) for rev in base]
1062 heads = revs and map(repo.lookup, revs) or revs
1062 heads = revs and map(repo.lookup, revs) or revs
1063 cg = repo.getbundle('bundle', heads=heads, common=common)
1063 cg = repo.getbundle('bundle', heads=heads, common=common)
1064 outgoing = None
1064 outgoing = None
1065 else:
1065 else:
1066 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1066 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1067 dest, branches = hg.parseurl(dest, opts.get('branch'))
1067 dest, branches = hg.parseurl(dest, opts.get('branch'))
1068 other = hg.peer(repo, opts, dest)
1068 other = hg.peer(repo, opts, dest)
1069 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1069 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1070 heads = revs and map(repo.lookup, revs) or revs
1070 heads = revs and map(repo.lookup, revs) or revs
1071 outgoing = discovery.findcommonoutgoing(repo, other,
1071 outgoing = discovery.findcommonoutgoing(repo, other,
1072 onlyheads=heads,
1072 onlyheads=heads,
1073 force=opts.get('force'),
1073 force=opts.get('force'),
1074 portable=True)
1074 portable=True)
1075 cg = repo.getlocalbundle('bundle', outgoing)
1075 cg = repo.getlocalbundle('bundle', outgoing)
1076 if not cg:
1076 if not cg:
1077 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1077 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1078 return 1
1078 return 1
1079
1079
1080 changegroup.writebundle(cg, fname, bundletype)
1080 changegroup.writebundle(cg, fname, bundletype)
1081
1081
1082 @command('cat',
1082 @command('cat',
1083 [('o', 'output', '',
1083 [('o', 'output', '',
1084 _('print output to file with formatted name'), _('FORMAT')),
1084 _('print output to file with formatted name'), _('FORMAT')),
1085 ('r', 'rev', '', _('print the given revision'), _('REV')),
1085 ('r', 'rev', '', _('print the given revision'), _('REV')),
1086 ('', 'decode', None, _('apply any matching decode filter')),
1086 ('', 'decode', None, _('apply any matching decode filter')),
1087 ] + walkopts,
1087 ] + walkopts,
1088 _('[OPTION]... FILE...'))
1088 _('[OPTION]... FILE...'))
1089 def cat(ui, repo, file1, *pats, **opts):
1089 def cat(ui, repo, file1, *pats, **opts):
1090 """output the current or given revision of files
1090 """output the current or given revision of files
1091
1091
1092 Print the specified files as they were at the given revision. If
1092 Print the specified files as they were at the given revision. If
1093 no revision is given, the parent of the working directory is used,
1093 no revision is given, the parent of the working directory is used,
1094 or tip if no revision is checked out.
1094 or tip if no revision is checked out.
1095
1095
1096 Output may be to a file, in which case the name of the file is
1096 Output may be to a file, in which case the name of the file is
1097 given using a format string. The formatting rules are the same as
1097 given using a format string. The formatting rules are the same as
1098 for the export command, with the following additions:
1098 for the export command, with the following additions:
1099
1099
1100 :``%s``: basename of file being printed
1100 :``%s``: basename of file being printed
1101 :``%d``: dirname of file being printed, or '.' if in repository root
1101 :``%d``: dirname of file being printed, or '.' if in repository root
1102 :``%p``: root-relative path name of file being printed
1102 :``%p``: root-relative path name of file being printed
1103
1103
1104 Returns 0 on success.
1104 Returns 0 on success.
1105 """
1105 """
1106 ctx = scmutil.revsingle(repo, opts.get('rev'))
1106 ctx = scmutil.revsingle(repo, opts.get('rev'))
1107 err = 1
1107 err = 1
1108 m = scmutil.match(ctx, (file1,) + pats, opts)
1108 m = scmutil.match(ctx, (file1,) + pats, opts)
1109 for abs in ctx.walk(m):
1109 for abs in ctx.walk(m):
1110 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1110 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1111 pathname=abs)
1111 pathname=abs)
1112 data = ctx[abs].data()
1112 data = ctx[abs].data()
1113 if opts.get('decode'):
1113 if opts.get('decode'):
1114 data = repo.wwritedata(abs, data)
1114 data = repo.wwritedata(abs, data)
1115 fp.write(data)
1115 fp.write(data)
1116 fp.close()
1116 fp.close()
1117 err = 0
1117 err = 0
1118 return err
1118 return err
1119
1119
1120 @command('^clone',
1120 @command('^clone',
1121 [('U', 'noupdate', None,
1121 [('U', 'noupdate', None,
1122 _('the clone will include an empty working copy (only a repository)')),
1122 _('the clone will include an empty working copy (only a repository)')),
1123 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1123 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1124 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1124 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1125 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1125 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1126 ('', 'pull', None, _('use pull protocol to copy metadata')),
1126 ('', 'pull', None, _('use pull protocol to copy metadata')),
1127 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1127 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1128 ] + remoteopts,
1128 ] + remoteopts,
1129 _('[OPTION]... SOURCE [DEST]'))
1129 _('[OPTION]... SOURCE [DEST]'))
1130 def clone(ui, source, dest=None, **opts):
1130 def clone(ui, source, dest=None, **opts):
1131 """make a copy of an existing repository
1131 """make a copy of an existing repository
1132
1132
1133 Create a copy of an existing repository in a new directory.
1133 Create a copy of an existing repository in a new directory.
1134
1134
1135 If no destination directory name is specified, it defaults to the
1135 If no destination directory name is specified, it defaults to the
1136 basename of the source.
1136 basename of the source.
1137
1137
1138 The location of the source is added to the new repository's
1138 The location of the source is added to the new repository's
1139 ``.hg/hgrc`` file, as the default to be used for future pulls.
1139 ``.hg/hgrc`` file, as the default to be used for future pulls.
1140
1140
1141 Only local paths and ``ssh://`` URLs are supported as
1141 Only local paths and ``ssh://`` URLs are supported as
1142 destinations. For ``ssh://`` destinations, no working directory or
1142 destinations. For ``ssh://`` destinations, no working directory or
1143 ``.hg/hgrc`` will be created on the remote side.
1143 ``.hg/hgrc`` will be created on the remote side.
1144
1144
1145 To pull only a subset of changesets, specify one or more revisions
1145 To pull only a subset of changesets, specify one or more revisions
1146 identifiers with -r/--rev or branches with -b/--branch. The
1146 identifiers with -r/--rev or branches with -b/--branch. The
1147 resulting clone will contain only the specified changesets and
1147 resulting clone will contain only the specified changesets and
1148 their ancestors. These options (or 'clone src#rev dest') imply
1148 their ancestors. These options (or 'clone src#rev dest') imply
1149 --pull, even for local source repositories. Note that specifying a
1149 --pull, even for local source repositories. Note that specifying a
1150 tag will include the tagged changeset but not the changeset
1150 tag will include the tagged changeset but not the changeset
1151 containing the tag.
1151 containing the tag.
1152
1152
1153 If the source repository has a bookmark called '@' set, that
1153 If the source repository has a bookmark called '@' set, that
1154 revision will be checked out in the new repository by default.
1154 revision will be checked out in the new repository by default.
1155
1155
1156 To check out a particular version, use -u/--update, or
1156 To check out a particular version, use -u/--update, or
1157 -U/--noupdate to create a clone with no working directory.
1157 -U/--noupdate to create a clone with no working directory.
1158
1158
1159 .. container:: verbose
1159 .. container:: verbose
1160
1160
1161 For efficiency, hardlinks are used for cloning whenever the
1161 For efficiency, hardlinks are used for cloning whenever the
1162 source and destination are on the same filesystem (note this
1162 source and destination are on the same filesystem (note this
1163 applies only to the repository data, not to the working
1163 applies only to the repository data, not to the working
1164 directory). Some filesystems, such as AFS, implement hardlinking
1164 directory). Some filesystems, such as AFS, implement hardlinking
1165 incorrectly, but do not report errors. In these cases, use the
1165 incorrectly, but do not report errors. In these cases, use the
1166 --pull option to avoid hardlinking.
1166 --pull option to avoid hardlinking.
1167
1167
1168 In some cases, you can clone repositories and the working
1168 In some cases, you can clone repositories and the working
1169 directory using full hardlinks with ::
1169 directory using full hardlinks with ::
1170
1170
1171 $ cp -al REPO REPOCLONE
1171 $ cp -al REPO REPOCLONE
1172
1172
1173 This is the fastest way to clone, but it is not always safe. The
1173 This is the fastest way to clone, but it is not always safe. The
1174 operation is not atomic (making sure REPO is not modified during
1174 operation is not atomic (making sure REPO is not modified during
1175 the operation is up to you) and you have to make sure your
1175 the operation is up to you) and you have to make sure your
1176 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1176 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1177 so). Also, this is not compatible with certain extensions that
1177 so). Also, this is not compatible with certain extensions that
1178 place their metadata under the .hg directory, such as mq.
1178 place their metadata under the .hg directory, such as mq.
1179
1179
1180 Mercurial will update the working directory to the first applicable
1180 Mercurial will update the working directory to the first applicable
1181 revision from this list:
1181 revision from this list:
1182
1182
1183 a) null if -U or the source repository has no changesets
1183 a) null if -U or the source repository has no changesets
1184 b) if -u . and the source repository is local, the first parent of
1184 b) if -u . and the source repository is local, the first parent of
1185 the source repository's working directory
1185 the source repository's working directory
1186 c) the changeset specified with -u (if a branch name, this means the
1186 c) the changeset specified with -u (if a branch name, this means the
1187 latest head of that branch)
1187 latest head of that branch)
1188 d) the changeset specified with -r
1188 d) the changeset specified with -r
1189 e) the tipmost head specified with -b
1189 e) the tipmost head specified with -b
1190 f) the tipmost head specified with the url#branch source syntax
1190 f) the tipmost head specified with the url#branch source syntax
1191 g) the revision marked with the '@' bookmark, if present
1191 g) the revision marked with the '@' bookmark, if present
1192 h) the tipmost head of the default branch
1192 h) the tipmost head of the default branch
1193 i) tip
1193 i) tip
1194
1194
1195 Examples:
1195 Examples:
1196
1196
1197 - clone a remote repository to a new directory named hg/::
1197 - clone a remote repository to a new directory named hg/::
1198
1198
1199 hg clone http://selenic.com/hg
1199 hg clone http://selenic.com/hg
1200
1200
1201 - create a lightweight local clone::
1201 - create a lightweight local clone::
1202
1202
1203 hg clone project/ project-feature/
1203 hg clone project/ project-feature/
1204
1204
1205 - clone from an absolute path on an ssh server (note double-slash)::
1205 - clone from an absolute path on an ssh server (note double-slash)::
1206
1206
1207 hg clone ssh://user@server//home/projects/alpha/
1207 hg clone ssh://user@server//home/projects/alpha/
1208
1208
1209 - do a high-speed clone over a LAN while checking out a
1209 - do a high-speed clone over a LAN while checking out a
1210 specified version::
1210 specified version::
1211
1211
1212 hg clone --uncompressed http://server/repo -u 1.5
1212 hg clone --uncompressed http://server/repo -u 1.5
1213
1213
1214 - create a repository without changesets after a particular revision::
1214 - create a repository without changesets after a particular revision::
1215
1215
1216 hg clone -r 04e544 experimental/ good/
1216 hg clone -r 04e544 experimental/ good/
1217
1217
1218 - clone (and track) a particular named branch::
1218 - clone (and track) a particular named branch::
1219
1219
1220 hg clone http://selenic.com/hg#stable
1220 hg clone http://selenic.com/hg#stable
1221
1221
1222 See :hg:`help urls` for details on specifying URLs.
1222 See :hg:`help urls` for details on specifying URLs.
1223
1223
1224 Returns 0 on success.
1224 Returns 0 on success.
1225 """
1225 """
1226 if opts.get('noupdate') and opts.get('updaterev'):
1226 if opts.get('noupdate') and opts.get('updaterev'):
1227 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1227 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1228
1228
1229 r = hg.clone(ui, opts, source, dest,
1229 r = hg.clone(ui, opts, source, dest,
1230 pull=opts.get('pull'),
1230 pull=opts.get('pull'),
1231 stream=opts.get('uncompressed'),
1231 stream=opts.get('uncompressed'),
1232 rev=opts.get('rev'),
1232 rev=opts.get('rev'),
1233 update=opts.get('updaterev') or not opts.get('noupdate'),
1233 update=opts.get('updaterev') or not opts.get('noupdate'),
1234 branch=opts.get('branch'))
1234 branch=opts.get('branch'))
1235
1235
1236 return r is None
1236 return r is None
1237
1237
1238 @command('^commit|ci',
1238 @command('^commit|ci',
1239 [('A', 'addremove', None,
1239 [('A', 'addremove', None,
1240 _('mark new/missing files as added/removed before committing')),
1240 _('mark new/missing files as added/removed before committing')),
1241 ('', 'close-branch', None,
1241 ('', 'close-branch', None,
1242 _('mark a branch as closed, hiding it from the branch list')),
1242 _('mark a branch as closed, hiding it from the branch list')),
1243 ('', 'amend', None, _('amend the parent of the working dir')),
1243 ('', 'amend', None, _('amend the parent of the working dir')),
1244 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1244 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1245 _('[OPTION]... [FILE]...'))
1245 _('[OPTION]... [FILE]...'))
1246 def commit(ui, repo, *pats, **opts):
1246 def commit(ui, repo, *pats, **opts):
1247 """commit the specified files or all outstanding changes
1247 """commit the specified files or all outstanding changes
1248
1248
1249 Commit changes to the given files into the repository. Unlike a
1249 Commit changes to the given files into the repository. Unlike a
1250 centralized SCM, this operation is a local operation. See
1250 centralized SCM, this operation is a local operation. See
1251 :hg:`push` for a way to actively distribute your changes.
1251 :hg:`push` for a way to actively distribute your changes.
1252
1252
1253 If a list of files is omitted, all changes reported by :hg:`status`
1253 If a list of files is omitted, all changes reported by :hg:`status`
1254 will be committed.
1254 will be committed.
1255
1255
1256 If you are committing the result of a merge, do not provide any
1256 If you are committing the result of a merge, do not provide any
1257 filenames or -I/-X filters.
1257 filenames or -I/-X filters.
1258
1258
1259 If no commit message is specified, Mercurial starts your
1259 If no commit message is specified, Mercurial starts your
1260 configured editor where you can enter a message. In case your
1260 configured editor where you can enter a message. In case your
1261 commit fails, you will find a backup of your message in
1261 commit fails, you will find a backup of your message in
1262 ``.hg/last-message.txt``.
1262 ``.hg/last-message.txt``.
1263
1263
1264 The --amend flag can be used to amend the parent of the
1264 The --amend flag can be used to amend the parent of the
1265 working directory with a new commit that contains the changes
1265 working directory with a new commit that contains the changes
1266 in the parent in addition to those currently reported by :hg:`status`,
1266 in the parent in addition to those currently reported by :hg:`status`,
1267 if there are any. The old commit is stored in a backup bundle in
1267 if there are any. The old commit is stored in a backup bundle in
1268 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1268 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1269 on how to restore it).
1269 on how to restore it).
1270
1270
1271 Message, user and date are taken from the amended commit unless
1271 Message, user and date are taken from the amended commit unless
1272 specified. When a message isn't specified on the command line,
1272 specified. When a message isn't specified on the command line,
1273 the editor will open with the message of the amended commit.
1273 the editor will open with the message of the amended commit.
1274
1274
1275 It is not possible to amend public changesets (see :hg:`help phases`)
1275 It is not possible to amend public changesets (see :hg:`help phases`)
1276 or changesets that have children.
1276 or changesets that have children.
1277
1277
1278 See :hg:`help dates` for a list of formats valid for -d/--date.
1278 See :hg:`help dates` for a list of formats valid for -d/--date.
1279
1279
1280 Returns 0 on success, 1 if nothing changed.
1280 Returns 0 on success, 1 if nothing changed.
1281 """
1281 """
1282 if opts.get('subrepos'):
1282 if opts.get('subrepos'):
1283 # Let --subrepos on the command line override config setting.
1283 # Let --subrepos on the command line override config setting.
1284 ui.setconfig('ui', 'commitsubrepos', True)
1284 ui.setconfig('ui', 'commitsubrepos', True)
1285
1285
1286 extra = {}
1286 extra = {}
1287 if opts.get('close_branch'):
1287 if opts.get('close_branch'):
1288 if repo['.'].node() not in repo.branchheads():
1288 if repo['.'].node() not in repo.branchheads():
1289 # The topo heads set is included in the branch heads set of the
1289 # The topo heads set is included in the branch heads set of the
1290 # current branch, so it's sufficient to test branchheads
1290 # current branch, so it's sufficient to test branchheads
1291 raise util.Abort(_('can only close branch heads'))
1291 raise util.Abort(_('can only close branch heads'))
1292 extra['close'] = 1
1292 extra['close'] = 1
1293
1293
1294 branch = repo[None].branch()
1294 branch = repo[None].branch()
1295 bheads = repo.branchheads(branch)
1295 bheads = repo.branchheads(branch)
1296
1296
1297 if opts.get('amend'):
1297 if opts.get('amend'):
1298 if ui.configbool('ui', 'commitsubrepos'):
1298 if ui.configbool('ui', 'commitsubrepos'):
1299 raise util.Abort(_('cannot amend recursively'))
1299 raise util.Abort(_('cannot amend recursively'))
1300
1300
1301 old = repo['.']
1301 old = repo['.']
1302 if old.phase() == phases.public:
1302 if old.phase() == phases.public:
1303 raise util.Abort(_('cannot amend public changesets'))
1303 raise util.Abort(_('cannot amend public changesets'))
1304 if len(old.parents()) > 1:
1304 if len(old.parents()) > 1:
1305 raise util.Abort(_('cannot amend merge changesets'))
1305 raise util.Abort(_('cannot amend merge changesets'))
1306 if len(repo[None].parents()) > 1:
1306 if len(repo[None].parents()) > 1:
1307 raise util.Abort(_('cannot amend while merging'))
1307 raise util.Abort(_('cannot amend while merging'))
1308 if (not obsolete._enabled) and old.children():
1308 if (not obsolete._enabled) and old.children():
1309 raise util.Abort(_('cannot amend changeset with children'))
1309 raise util.Abort(_('cannot amend changeset with children'))
1310
1310
1311 e = cmdutil.commiteditor
1311 e = cmdutil.commiteditor
1312 if opts.get('force_editor'):
1312 if opts.get('force_editor'):
1313 e = cmdutil.commitforceeditor
1313 e = cmdutil.commitforceeditor
1314
1314
1315 def commitfunc(ui, repo, message, match, opts):
1315 def commitfunc(ui, repo, message, match, opts):
1316 editor = e
1316 editor = e
1317 # message contains text from -m or -l, if it's empty,
1317 # message contains text from -m or -l, if it's empty,
1318 # open the editor with the old message
1318 # open the editor with the old message
1319 if not message:
1319 if not message:
1320 message = old.description()
1320 message = old.description()
1321 editor = cmdutil.commitforceeditor
1321 editor = cmdutil.commitforceeditor
1322 return repo.commit(message,
1322 return repo.commit(message,
1323 opts.get('user') or old.user(),
1323 opts.get('user') or old.user(),
1324 opts.get('date') or old.date(),
1324 opts.get('date') or old.date(),
1325 match,
1325 match,
1326 editor=editor,
1326 editor=editor,
1327 extra=extra)
1327 extra=extra)
1328
1328
1329 current = repo._bookmarkcurrent
1329 current = repo._bookmarkcurrent
1330 marks = old.bookmarks()
1330 marks = old.bookmarks()
1331 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1331 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1332 if node == old.node():
1332 if node == old.node():
1333 ui.status(_("nothing changed\n"))
1333 ui.status(_("nothing changed\n"))
1334 return 1
1334 return 1
1335 elif marks:
1335 elif marks:
1336 ui.debug('moving bookmarks %r from %s to %s\n' %
1336 ui.debug('moving bookmarks %r from %s to %s\n' %
1337 (marks, old.hex(), hex(node)))
1337 (marks, old.hex(), hex(node)))
1338 newmarks = repo._bookmarks
1338 newmarks = repo._bookmarks
1339 for bm in marks:
1339 for bm in marks:
1340 newmarks[bm] = node
1340 newmarks[bm] = node
1341 if bm == current:
1341 if bm == current:
1342 bookmarks.setcurrent(repo, bm)
1342 bookmarks.setcurrent(repo, bm)
1343 newmarks.write()
1343 newmarks.write()
1344 else:
1344 else:
1345 e = cmdutil.commiteditor
1345 e = cmdutil.commiteditor
1346 if opts.get('force_editor'):
1346 if opts.get('force_editor'):
1347 e = cmdutil.commitforceeditor
1347 e = cmdutil.commitforceeditor
1348
1348
1349 def commitfunc(ui, repo, message, match, opts):
1349 def commitfunc(ui, repo, message, match, opts):
1350 return repo.commit(message, opts.get('user'), opts.get('date'),
1350 return repo.commit(message, opts.get('user'), opts.get('date'),
1351 match, editor=e, extra=extra)
1351 match, editor=e, extra=extra)
1352
1352
1353 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1353 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1354
1354
1355 if not node:
1355 if not node:
1356 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1356 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1357 if stat[3]:
1357 if stat[3]:
1358 ui.status(_("nothing changed (%d missing files, see "
1358 ui.status(_("nothing changed (%d missing files, see "
1359 "'hg status')\n") % len(stat[3]))
1359 "'hg status')\n") % len(stat[3]))
1360 else:
1360 else:
1361 ui.status(_("nothing changed\n"))
1361 ui.status(_("nothing changed\n"))
1362 return 1
1362 return 1
1363
1363
1364 ctx = repo[node]
1364 ctx = repo[node]
1365 parents = ctx.parents()
1365 parents = ctx.parents()
1366
1366
1367 if (not opts.get('amend') and bheads and node not in bheads and not
1367 if (not opts.get('amend') and bheads and node not in bheads and not
1368 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1368 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1369 ui.status(_('created new head\n'))
1369 ui.status(_('created new head\n'))
1370 # The message is not printed for initial roots. For the other
1370 # The message is not printed for initial roots. For the other
1371 # changesets, it is printed in the following situations:
1371 # changesets, it is printed in the following situations:
1372 #
1372 #
1373 # Par column: for the 2 parents with ...
1373 # Par column: for the 2 parents with ...
1374 # N: null or no parent
1374 # N: null or no parent
1375 # B: parent is on another named branch
1375 # B: parent is on another named branch
1376 # C: parent is a regular non head changeset
1376 # C: parent is a regular non head changeset
1377 # H: parent was a branch head of the current branch
1377 # H: parent was a branch head of the current branch
1378 # Msg column: whether we print "created new head" message
1378 # Msg column: whether we print "created new head" message
1379 # In the following, it is assumed that there already exists some
1379 # In the following, it is assumed that there already exists some
1380 # initial branch heads of the current branch, otherwise nothing is
1380 # initial branch heads of the current branch, otherwise nothing is
1381 # printed anyway.
1381 # printed anyway.
1382 #
1382 #
1383 # Par Msg Comment
1383 # Par Msg Comment
1384 # N N y additional topo root
1384 # N N y additional topo root
1385 #
1385 #
1386 # B N y additional branch root
1386 # B N y additional branch root
1387 # C N y additional topo head
1387 # C N y additional topo head
1388 # H N n usual case
1388 # H N n usual case
1389 #
1389 #
1390 # B B y weird additional branch root
1390 # B B y weird additional branch root
1391 # C B y branch merge
1391 # C B y branch merge
1392 # H B n merge with named branch
1392 # H B n merge with named branch
1393 #
1393 #
1394 # C C y additional head from merge
1394 # C C y additional head from merge
1395 # C H n merge with a head
1395 # C H n merge with a head
1396 #
1396 #
1397 # H H n head merge: head count decreases
1397 # H H n head merge: head count decreases
1398
1398
1399 if not opts.get('close_branch'):
1399 if not opts.get('close_branch'):
1400 for r in parents:
1400 for r in parents:
1401 if r.closesbranch() and r.branch() == branch:
1401 if r.closesbranch() and r.branch() == branch:
1402 ui.status(_('reopening closed branch head %d\n') % r)
1402 ui.status(_('reopening closed branch head %d\n') % r)
1403
1403
1404 if ui.debugflag:
1404 if ui.debugflag:
1405 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1405 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1406 elif ui.verbose:
1406 elif ui.verbose:
1407 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1407 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1408
1408
1409 @command('copy|cp',
1409 @command('copy|cp',
1410 [('A', 'after', None, _('record a copy that has already occurred')),
1410 [('A', 'after', None, _('record a copy that has already occurred')),
1411 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1411 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1412 ] + walkopts + dryrunopts,
1412 ] + walkopts + dryrunopts,
1413 _('[OPTION]... [SOURCE]... DEST'))
1413 _('[OPTION]... [SOURCE]... DEST'))
1414 def copy(ui, repo, *pats, **opts):
1414 def copy(ui, repo, *pats, **opts):
1415 """mark files as copied for the next commit
1415 """mark files as copied for the next commit
1416
1416
1417 Mark dest as having copies of source files. If dest is a
1417 Mark dest as having copies of source files. If dest is a
1418 directory, copies are put in that directory. If dest is a file,
1418 directory, copies are put in that directory. If dest is a file,
1419 the source must be a single file.
1419 the source must be a single file.
1420
1420
1421 By default, this command copies the contents of files as they
1421 By default, this command copies the contents of files as they
1422 exist in the working directory. If invoked with -A/--after, the
1422 exist in the working directory. If invoked with -A/--after, the
1423 operation is recorded, but no copying is performed.
1423 operation is recorded, but no copying is performed.
1424
1424
1425 This command takes effect with the next commit. To undo a copy
1425 This command takes effect with the next commit. To undo a copy
1426 before that, see :hg:`revert`.
1426 before that, see :hg:`revert`.
1427
1427
1428 Returns 0 on success, 1 if errors are encountered.
1428 Returns 0 on success, 1 if errors are encountered.
1429 """
1429 """
1430 wlock = repo.wlock(False)
1430 wlock = repo.wlock(False)
1431 try:
1431 try:
1432 return cmdutil.copy(ui, repo, pats, opts)
1432 return cmdutil.copy(ui, repo, pats, opts)
1433 finally:
1433 finally:
1434 wlock.release()
1434 wlock.release()
1435
1435
1436 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1436 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1437 def debugancestor(ui, repo, *args):
1437 def debugancestor(ui, repo, *args):
1438 """find the ancestor revision of two revisions in a given index"""
1438 """find the ancestor revision of two revisions in a given index"""
1439 if len(args) == 3:
1439 if len(args) == 3:
1440 index, rev1, rev2 = args
1440 index, rev1, rev2 = args
1441 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1441 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1442 lookup = r.lookup
1442 lookup = r.lookup
1443 elif len(args) == 2:
1443 elif len(args) == 2:
1444 if not repo:
1444 if not repo:
1445 raise util.Abort(_("there is no Mercurial repository here "
1445 raise util.Abort(_("there is no Mercurial repository here "
1446 "(.hg not found)"))
1446 "(.hg not found)"))
1447 rev1, rev2 = args
1447 rev1, rev2 = args
1448 r = repo.changelog
1448 r = repo.changelog
1449 lookup = repo.lookup
1449 lookup = repo.lookup
1450 else:
1450 else:
1451 raise util.Abort(_('either two or three arguments required'))
1451 raise util.Abort(_('either two or three arguments required'))
1452 a = r.ancestor(lookup(rev1), lookup(rev2))
1452 a = r.ancestor(lookup(rev1), lookup(rev2))
1453 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1453 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1454
1454
1455 @command('debugbuilddag',
1455 @command('debugbuilddag',
1456 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1456 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1457 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1457 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1458 ('n', 'new-file', None, _('add new file at each rev'))],
1458 ('n', 'new-file', None, _('add new file at each rev'))],
1459 _('[OPTION]... [TEXT]'))
1459 _('[OPTION]... [TEXT]'))
1460 def debugbuilddag(ui, repo, text=None,
1460 def debugbuilddag(ui, repo, text=None,
1461 mergeable_file=False,
1461 mergeable_file=False,
1462 overwritten_file=False,
1462 overwritten_file=False,
1463 new_file=False):
1463 new_file=False):
1464 """builds a repo with a given DAG from scratch in the current empty repo
1464 """builds a repo with a given DAG from scratch in the current empty repo
1465
1465
1466 The description of the DAG is read from stdin if not given on the
1466 The description of the DAG is read from stdin if not given on the
1467 command line.
1467 command line.
1468
1468
1469 Elements:
1469 Elements:
1470
1470
1471 - "+n" is a linear run of n nodes based on the current default parent
1471 - "+n" is a linear run of n nodes based on the current default parent
1472 - "." is a single node based on the current default parent
1472 - "." is a single node based on the current default parent
1473 - "$" resets the default parent to null (implied at the start);
1473 - "$" resets the default parent to null (implied at the start);
1474 otherwise the default parent is always the last node created
1474 otherwise the default parent is always the last node created
1475 - "<p" sets the default parent to the backref p
1475 - "<p" sets the default parent to the backref p
1476 - "*p" is a fork at parent p, which is a backref
1476 - "*p" is a fork at parent p, which is a backref
1477 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1477 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1478 - "/p2" is a merge of the preceding node and p2
1478 - "/p2" is a merge of the preceding node and p2
1479 - ":tag" defines a local tag for the preceding node
1479 - ":tag" defines a local tag for the preceding node
1480 - "@branch" sets the named branch for subsequent nodes
1480 - "@branch" sets the named branch for subsequent nodes
1481 - "#...\\n" is a comment up to the end of the line
1481 - "#...\\n" is a comment up to the end of the line
1482
1482
1483 Whitespace between the above elements is ignored.
1483 Whitespace between the above elements is ignored.
1484
1484
1485 A backref is either
1485 A backref is either
1486
1486
1487 - a number n, which references the node curr-n, where curr is the current
1487 - a number n, which references the node curr-n, where curr is the current
1488 node, or
1488 node, or
1489 - the name of a local tag you placed earlier using ":tag", or
1489 - the name of a local tag you placed earlier using ":tag", or
1490 - empty to denote the default parent.
1490 - empty to denote the default parent.
1491
1491
1492 All string valued-elements are either strictly alphanumeric, or must
1492 All string valued-elements are either strictly alphanumeric, or must
1493 be enclosed in double quotes ("..."), with "\\" as escape character.
1493 be enclosed in double quotes ("..."), with "\\" as escape character.
1494 """
1494 """
1495
1495
1496 if text is None:
1496 if text is None:
1497 ui.status(_("reading DAG from stdin\n"))
1497 ui.status(_("reading DAG from stdin\n"))
1498 text = ui.fin.read()
1498 text = ui.fin.read()
1499
1499
1500 cl = repo.changelog
1500 cl = repo.changelog
1501 if len(cl) > 0:
1501 if len(cl) > 0:
1502 raise util.Abort(_('repository is not empty'))
1502 raise util.Abort(_('repository is not empty'))
1503
1503
1504 # determine number of revs in DAG
1504 # determine number of revs in DAG
1505 total = 0
1505 total = 0
1506 for type, data in dagparser.parsedag(text):
1506 for type, data in dagparser.parsedag(text):
1507 if type == 'n':
1507 if type == 'n':
1508 total += 1
1508 total += 1
1509
1509
1510 if mergeable_file:
1510 if mergeable_file:
1511 linesperrev = 2
1511 linesperrev = 2
1512 # make a file with k lines per rev
1512 # make a file with k lines per rev
1513 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1513 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1514 initialmergedlines.append("")
1514 initialmergedlines.append("")
1515
1515
1516 tags = []
1516 tags = []
1517
1517
1518 lock = tr = None
1518 lock = tr = None
1519 try:
1519 try:
1520 lock = repo.lock()
1520 lock = repo.lock()
1521 tr = repo.transaction("builddag")
1521 tr = repo.transaction("builddag")
1522
1522
1523 at = -1
1523 at = -1
1524 atbranch = 'default'
1524 atbranch = 'default'
1525 nodeids = []
1525 nodeids = []
1526 id = 0
1526 id = 0
1527 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1527 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1528 for type, data in dagparser.parsedag(text):
1528 for type, data in dagparser.parsedag(text):
1529 if type == 'n':
1529 if type == 'n':
1530 ui.note(('node %s\n' % str(data)))
1530 ui.note(('node %s\n' % str(data)))
1531 id, ps = data
1531 id, ps = data
1532
1532
1533 files = []
1533 files = []
1534 fctxs = {}
1534 fctxs = {}
1535
1535
1536 p2 = None
1536 p2 = None
1537 if mergeable_file:
1537 if mergeable_file:
1538 fn = "mf"
1538 fn = "mf"
1539 p1 = repo[ps[0]]
1539 p1 = repo[ps[0]]
1540 if len(ps) > 1:
1540 if len(ps) > 1:
1541 p2 = repo[ps[1]]
1541 p2 = repo[ps[1]]
1542 pa = p1.ancestor(p2)
1542 pa = p1.ancestor(p2)
1543 base, local, other = [x[fn].data() for x in (pa, p1,
1543 base, local, other = [x[fn].data() for x in (pa, p1,
1544 p2)]
1544 p2)]
1545 m3 = simplemerge.Merge3Text(base, local, other)
1545 m3 = simplemerge.Merge3Text(base, local, other)
1546 ml = [l.strip() for l in m3.merge_lines()]
1546 ml = [l.strip() for l in m3.merge_lines()]
1547 ml.append("")
1547 ml.append("")
1548 elif at > 0:
1548 elif at > 0:
1549 ml = p1[fn].data().split("\n")
1549 ml = p1[fn].data().split("\n")
1550 else:
1550 else:
1551 ml = initialmergedlines
1551 ml = initialmergedlines
1552 ml[id * linesperrev] += " r%i" % id
1552 ml[id * linesperrev] += " r%i" % id
1553 mergedtext = "\n".join(ml)
1553 mergedtext = "\n".join(ml)
1554 files.append(fn)
1554 files.append(fn)
1555 fctxs[fn] = context.memfilectx(fn, mergedtext)
1555 fctxs[fn] = context.memfilectx(fn, mergedtext)
1556
1556
1557 if overwritten_file:
1557 if overwritten_file:
1558 fn = "of"
1558 fn = "of"
1559 files.append(fn)
1559 files.append(fn)
1560 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1560 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1561
1561
1562 if new_file:
1562 if new_file:
1563 fn = "nf%i" % id
1563 fn = "nf%i" % id
1564 files.append(fn)
1564 files.append(fn)
1565 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1565 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1566 if len(ps) > 1:
1566 if len(ps) > 1:
1567 if not p2:
1567 if not p2:
1568 p2 = repo[ps[1]]
1568 p2 = repo[ps[1]]
1569 for fn in p2:
1569 for fn in p2:
1570 if fn.startswith("nf"):
1570 if fn.startswith("nf"):
1571 files.append(fn)
1571 files.append(fn)
1572 fctxs[fn] = p2[fn]
1572 fctxs[fn] = p2[fn]
1573
1573
1574 def fctxfn(repo, cx, path):
1574 def fctxfn(repo, cx, path):
1575 return fctxs.get(path)
1575 return fctxs.get(path)
1576
1576
1577 if len(ps) == 0 or ps[0] < 0:
1577 if len(ps) == 0 or ps[0] < 0:
1578 pars = [None, None]
1578 pars = [None, None]
1579 elif len(ps) == 1:
1579 elif len(ps) == 1:
1580 pars = [nodeids[ps[0]], None]
1580 pars = [nodeids[ps[0]], None]
1581 else:
1581 else:
1582 pars = [nodeids[p] for p in ps]
1582 pars = [nodeids[p] for p in ps]
1583 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1583 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1584 date=(id, 0),
1584 date=(id, 0),
1585 user="debugbuilddag",
1585 user="debugbuilddag",
1586 extra={'branch': atbranch})
1586 extra={'branch': atbranch})
1587 nodeid = repo.commitctx(cx)
1587 nodeid = repo.commitctx(cx)
1588 nodeids.append(nodeid)
1588 nodeids.append(nodeid)
1589 at = id
1589 at = id
1590 elif type == 'l':
1590 elif type == 'l':
1591 id, name = data
1591 id, name = data
1592 ui.note(('tag %s\n' % name))
1592 ui.note(('tag %s\n' % name))
1593 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1593 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1594 elif type == 'a':
1594 elif type == 'a':
1595 ui.note(('branch %s\n' % data))
1595 ui.note(('branch %s\n' % data))
1596 atbranch = data
1596 atbranch = data
1597 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1597 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1598 tr.close()
1598 tr.close()
1599
1599
1600 if tags:
1600 if tags:
1601 repo.opener.write("localtags", "".join(tags))
1601 repo.opener.write("localtags", "".join(tags))
1602 finally:
1602 finally:
1603 ui.progress(_('building'), None)
1603 ui.progress(_('building'), None)
1604 release(tr, lock)
1604 release(tr, lock)
1605
1605
1606 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1606 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1607 def debugbundle(ui, bundlepath, all=None, **opts):
1607 def debugbundle(ui, bundlepath, all=None, **opts):
1608 """lists the contents of a bundle"""
1608 """lists the contents of a bundle"""
1609 f = hg.openpath(ui, bundlepath)
1609 f = hg.openpath(ui, bundlepath)
1610 try:
1610 try:
1611 gen = changegroup.readbundle(f, bundlepath)
1611 gen = changegroup.readbundle(f, bundlepath)
1612 if all:
1612 if all:
1613 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1613 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1614
1614
1615 def showchunks(named):
1615 def showchunks(named):
1616 ui.write("\n%s\n" % named)
1616 ui.write("\n%s\n" % named)
1617 chain = None
1617 chain = None
1618 while True:
1618 while True:
1619 chunkdata = gen.deltachunk(chain)
1619 chunkdata = gen.deltachunk(chain)
1620 if not chunkdata:
1620 if not chunkdata:
1621 break
1621 break
1622 node = chunkdata['node']
1622 node = chunkdata['node']
1623 p1 = chunkdata['p1']
1623 p1 = chunkdata['p1']
1624 p2 = chunkdata['p2']
1624 p2 = chunkdata['p2']
1625 cs = chunkdata['cs']
1625 cs = chunkdata['cs']
1626 deltabase = chunkdata['deltabase']
1626 deltabase = chunkdata['deltabase']
1627 delta = chunkdata['delta']
1627 delta = chunkdata['delta']
1628 ui.write("%s %s %s %s %s %s\n" %
1628 ui.write("%s %s %s %s %s %s\n" %
1629 (hex(node), hex(p1), hex(p2),
1629 (hex(node), hex(p1), hex(p2),
1630 hex(cs), hex(deltabase), len(delta)))
1630 hex(cs), hex(deltabase), len(delta)))
1631 chain = node
1631 chain = node
1632
1632
1633 chunkdata = gen.changelogheader()
1633 chunkdata = gen.changelogheader()
1634 showchunks("changelog")
1634 showchunks("changelog")
1635 chunkdata = gen.manifestheader()
1635 chunkdata = gen.manifestheader()
1636 showchunks("manifest")
1636 showchunks("manifest")
1637 while True:
1637 while True:
1638 chunkdata = gen.filelogheader()
1638 chunkdata = gen.filelogheader()
1639 if not chunkdata:
1639 if not chunkdata:
1640 break
1640 break
1641 fname = chunkdata['filename']
1641 fname = chunkdata['filename']
1642 showchunks(fname)
1642 showchunks(fname)
1643 else:
1643 else:
1644 chunkdata = gen.changelogheader()
1644 chunkdata = gen.changelogheader()
1645 chain = None
1645 chain = None
1646 while True:
1646 while True:
1647 chunkdata = gen.deltachunk(chain)
1647 chunkdata = gen.deltachunk(chain)
1648 if not chunkdata:
1648 if not chunkdata:
1649 break
1649 break
1650 node = chunkdata['node']
1650 node = chunkdata['node']
1651 ui.write("%s\n" % hex(node))
1651 ui.write("%s\n" % hex(node))
1652 chain = node
1652 chain = node
1653 finally:
1653 finally:
1654 f.close()
1654 f.close()
1655
1655
1656 @command('debugcheckstate', [], '')
1656 @command('debugcheckstate', [], '')
1657 def debugcheckstate(ui, repo):
1657 def debugcheckstate(ui, repo):
1658 """validate the correctness of the current dirstate"""
1658 """validate the correctness of the current dirstate"""
1659 parent1, parent2 = repo.dirstate.parents()
1659 parent1, parent2 = repo.dirstate.parents()
1660 m1 = repo[parent1].manifest()
1660 m1 = repo[parent1].manifest()
1661 m2 = repo[parent2].manifest()
1661 m2 = repo[parent2].manifest()
1662 errors = 0
1662 errors = 0
1663 for f in repo.dirstate:
1663 for f in repo.dirstate:
1664 state = repo.dirstate[f]
1664 state = repo.dirstate[f]
1665 if state in "nr" and f not in m1:
1665 if state in "nr" and f not in m1:
1666 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1666 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1667 errors += 1
1667 errors += 1
1668 if state in "a" and f in m1:
1668 if state in "a" and f in m1:
1669 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1669 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1670 errors += 1
1670 errors += 1
1671 if state in "m" and f not in m1 and f not in m2:
1671 if state in "m" and f not in m1 and f not in m2:
1672 ui.warn(_("%s in state %s, but not in either manifest\n") %
1672 ui.warn(_("%s in state %s, but not in either manifest\n") %
1673 (f, state))
1673 (f, state))
1674 errors += 1
1674 errors += 1
1675 for f in m1:
1675 for f in m1:
1676 state = repo.dirstate[f]
1676 state = repo.dirstate[f]
1677 if state not in "nrm":
1677 if state not in "nrm":
1678 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1678 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1679 errors += 1
1679 errors += 1
1680 if errors:
1680 if errors:
1681 error = _(".hg/dirstate inconsistent with current parent's manifest")
1681 error = _(".hg/dirstate inconsistent with current parent's manifest")
1682 raise util.Abort(error)
1682 raise util.Abort(error)
1683
1683
1684 @command('debugcommands', [], _('[COMMAND]'))
1684 @command('debugcommands', [], _('[COMMAND]'))
1685 def debugcommands(ui, cmd='', *args):
1685 def debugcommands(ui, cmd='', *args):
1686 """list all available commands and options"""
1686 """list all available commands and options"""
1687 for cmd, vals in sorted(table.iteritems()):
1687 for cmd, vals in sorted(table.iteritems()):
1688 cmd = cmd.split('|')[0].strip('^')
1688 cmd = cmd.split('|')[0].strip('^')
1689 opts = ', '.join([i[1] for i in vals[1]])
1689 opts = ', '.join([i[1] for i in vals[1]])
1690 ui.write('%s: %s\n' % (cmd, opts))
1690 ui.write('%s: %s\n' % (cmd, opts))
1691
1691
1692 @command('debugcomplete',
1692 @command('debugcomplete',
1693 [('o', 'options', None, _('show the command options'))],
1693 [('o', 'options', None, _('show the command options'))],
1694 _('[-o] CMD'))
1694 _('[-o] CMD'))
1695 def debugcomplete(ui, cmd='', **opts):
1695 def debugcomplete(ui, cmd='', **opts):
1696 """returns the completion list associated with the given command"""
1696 """returns the completion list associated with the given command"""
1697
1697
1698 if opts.get('options'):
1698 if opts.get('options'):
1699 options = []
1699 options = []
1700 otables = [globalopts]
1700 otables = [globalopts]
1701 if cmd:
1701 if cmd:
1702 aliases, entry = cmdutil.findcmd(cmd, table, False)
1702 aliases, entry = cmdutil.findcmd(cmd, table, False)
1703 otables.append(entry[1])
1703 otables.append(entry[1])
1704 for t in otables:
1704 for t in otables:
1705 for o in t:
1705 for o in t:
1706 if "(DEPRECATED)" in o[3]:
1706 if "(DEPRECATED)" in o[3]:
1707 continue
1707 continue
1708 if o[0]:
1708 if o[0]:
1709 options.append('-%s' % o[0])
1709 options.append('-%s' % o[0])
1710 options.append('--%s' % o[1])
1710 options.append('--%s' % o[1])
1711 ui.write("%s\n" % "\n".join(options))
1711 ui.write("%s\n" % "\n".join(options))
1712 return
1712 return
1713
1713
1714 cmdlist = cmdutil.findpossible(cmd, table)
1714 cmdlist = cmdutil.findpossible(cmd, table)
1715 if ui.verbose:
1715 if ui.verbose:
1716 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1716 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1717 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1717 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1718
1718
1719 @command('debugdag',
1719 @command('debugdag',
1720 [('t', 'tags', None, _('use tags as labels')),
1720 [('t', 'tags', None, _('use tags as labels')),
1721 ('b', 'branches', None, _('annotate with branch names')),
1721 ('b', 'branches', None, _('annotate with branch names')),
1722 ('', 'dots', None, _('use dots for runs')),
1722 ('', 'dots', None, _('use dots for runs')),
1723 ('s', 'spaces', None, _('separate elements by spaces'))],
1723 ('s', 'spaces', None, _('separate elements by spaces'))],
1724 _('[OPTION]... [FILE [REV]...]'))
1724 _('[OPTION]... [FILE [REV]...]'))
1725 def debugdag(ui, repo, file_=None, *revs, **opts):
1725 def debugdag(ui, repo, file_=None, *revs, **opts):
1726 """format the changelog or an index DAG as a concise textual description
1726 """format the changelog or an index DAG as a concise textual description
1727
1727
1728 If you pass a revlog index, the revlog's DAG is emitted. If you list
1728 If you pass a revlog index, the revlog's DAG is emitted. If you list
1729 revision numbers, they get labeled in the output as rN.
1729 revision numbers, they get labeled in the output as rN.
1730
1730
1731 Otherwise, the changelog DAG of the current repo is emitted.
1731 Otherwise, the changelog DAG of the current repo is emitted.
1732 """
1732 """
1733 spaces = opts.get('spaces')
1733 spaces = opts.get('spaces')
1734 dots = opts.get('dots')
1734 dots = opts.get('dots')
1735 if file_:
1735 if file_:
1736 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1736 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1737 revs = set((int(r) for r in revs))
1737 revs = set((int(r) for r in revs))
1738 def events():
1738 def events():
1739 for r in rlog:
1739 for r in rlog:
1740 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1740 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1741 if p != -1)))
1741 if p != -1)))
1742 if r in revs:
1742 if r in revs:
1743 yield 'l', (r, "r%i" % r)
1743 yield 'l', (r, "r%i" % r)
1744 elif repo:
1744 elif repo:
1745 cl = repo.changelog
1745 cl = repo.changelog
1746 tags = opts.get('tags')
1746 tags = opts.get('tags')
1747 branches = opts.get('branches')
1747 branches = opts.get('branches')
1748 if tags:
1748 if tags:
1749 labels = {}
1749 labels = {}
1750 for l, n in repo.tags().items():
1750 for l, n in repo.tags().items():
1751 labels.setdefault(cl.rev(n), []).append(l)
1751 labels.setdefault(cl.rev(n), []).append(l)
1752 def events():
1752 def events():
1753 b = "default"
1753 b = "default"
1754 for r in cl:
1754 for r in cl:
1755 if branches:
1755 if branches:
1756 newb = cl.read(cl.node(r))[5]['branch']
1756 newb = cl.read(cl.node(r))[5]['branch']
1757 if newb != b:
1757 if newb != b:
1758 yield 'a', newb
1758 yield 'a', newb
1759 b = newb
1759 b = newb
1760 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1760 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1761 if p != -1)))
1761 if p != -1)))
1762 if tags:
1762 if tags:
1763 ls = labels.get(r)
1763 ls = labels.get(r)
1764 if ls:
1764 if ls:
1765 for l in ls:
1765 for l in ls:
1766 yield 'l', (r, l)
1766 yield 'l', (r, l)
1767 else:
1767 else:
1768 raise util.Abort(_('need repo for changelog dag'))
1768 raise util.Abort(_('need repo for changelog dag'))
1769
1769
1770 for line in dagparser.dagtextlines(events(),
1770 for line in dagparser.dagtextlines(events(),
1771 addspaces=spaces,
1771 addspaces=spaces,
1772 wraplabels=True,
1772 wraplabels=True,
1773 wrapannotations=True,
1773 wrapannotations=True,
1774 wrapnonlinear=dots,
1774 wrapnonlinear=dots,
1775 usedots=dots,
1775 usedots=dots,
1776 maxlinewidth=70):
1776 maxlinewidth=70):
1777 ui.write(line)
1777 ui.write(line)
1778 ui.write("\n")
1778 ui.write("\n")
1779
1779
1780 @command('debugdata',
1780 @command('debugdata',
1781 [('c', 'changelog', False, _('open changelog')),
1781 [('c', 'changelog', False, _('open changelog')),
1782 ('m', 'manifest', False, _('open manifest'))],
1782 ('m', 'manifest', False, _('open manifest'))],
1783 _('-c|-m|FILE REV'))
1783 _('-c|-m|FILE REV'))
1784 def debugdata(ui, repo, file_, rev = None, **opts):
1784 def debugdata(ui, repo, file_, rev = None, **opts):
1785 """dump the contents of a data file revision"""
1785 """dump the contents of a data file revision"""
1786 if opts.get('changelog') or opts.get('manifest'):
1786 if opts.get('changelog') or opts.get('manifest'):
1787 file_, rev = None, file_
1787 file_, rev = None, file_
1788 elif rev is None:
1788 elif rev is None:
1789 raise error.CommandError('debugdata', _('invalid arguments'))
1789 raise error.CommandError('debugdata', _('invalid arguments'))
1790 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1790 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1791 try:
1791 try:
1792 ui.write(r.revision(r.lookup(rev)))
1792 ui.write(r.revision(r.lookup(rev)))
1793 except KeyError:
1793 except KeyError:
1794 raise util.Abort(_('invalid revision identifier %s') % rev)
1794 raise util.Abort(_('invalid revision identifier %s') % rev)
1795
1795
1796 @command('debugdate',
1796 @command('debugdate',
1797 [('e', 'extended', None, _('try extended date formats'))],
1797 [('e', 'extended', None, _('try extended date formats'))],
1798 _('[-e] DATE [RANGE]'))
1798 _('[-e] DATE [RANGE]'))
1799 def debugdate(ui, date, range=None, **opts):
1799 def debugdate(ui, date, range=None, **opts):
1800 """parse and display a date"""
1800 """parse and display a date"""
1801 if opts["extended"]:
1801 if opts["extended"]:
1802 d = util.parsedate(date, util.extendeddateformats)
1802 d = util.parsedate(date, util.extendeddateformats)
1803 else:
1803 else:
1804 d = util.parsedate(date)
1804 d = util.parsedate(date)
1805 ui.write(("internal: %s %s\n") % d)
1805 ui.write(("internal: %s %s\n") % d)
1806 ui.write(("standard: %s\n") % util.datestr(d))
1806 ui.write(("standard: %s\n") % util.datestr(d))
1807 if range:
1807 if range:
1808 m = util.matchdate(range)
1808 m = util.matchdate(range)
1809 ui.write(("match: %s\n") % m(d[0]))
1809 ui.write(("match: %s\n") % m(d[0]))
1810
1810
1811 @command('debugdiscovery',
1811 @command('debugdiscovery',
1812 [('', 'old', None, _('use old-style discovery')),
1812 [('', 'old', None, _('use old-style discovery')),
1813 ('', 'nonheads', None,
1813 ('', 'nonheads', None,
1814 _('use old-style discovery with non-heads included')),
1814 _('use old-style discovery with non-heads included')),
1815 ] + remoteopts,
1815 ] + remoteopts,
1816 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1816 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1817 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1817 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1818 """runs the changeset discovery protocol in isolation"""
1818 """runs the changeset discovery protocol in isolation"""
1819 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1819 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1820 opts.get('branch'))
1820 opts.get('branch'))
1821 remote = hg.peer(repo, opts, remoteurl)
1821 remote = hg.peer(repo, opts, remoteurl)
1822 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1822 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1823
1823
1824 # make sure tests are repeatable
1824 # make sure tests are repeatable
1825 random.seed(12323)
1825 random.seed(12323)
1826
1826
1827 def doit(localheads, remoteheads, remote=remote):
1827 def doit(localheads, remoteheads, remote=remote):
1828 if opts.get('old'):
1828 if opts.get('old'):
1829 if localheads:
1829 if localheads:
1830 raise util.Abort('cannot use localheads with old style '
1830 raise util.Abort('cannot use localheads with old style '
1831 'discovery')
1831 'discovery')
1832 if not util.safehasattr(remote, 'branches'):
1832 if not util.safehasattr(remote, 'branches'):
1833 # enable in-client legacy support
1833 # enable in-client legacy support
1834 remote = localrepo.locallegacypeer(remote.local())
1834 remote = localrepo.locallegacypeer(remote.local())
1835 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1835 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1836 force=True)
1836 force=True)
1837 common = set(common)
1837 common = set(common)
1838 if not opts.get('nonheads'):
1838 if not opts.get('nonheads'):
1839 ui.write(("unpruned common: %s\n") %
1839 ui.write(("unpruned common: %s\n") %
1840 " ".join(sorted(short(n) for n in common)))
1840 " ".join(sorted(short(n) for n in common)))
1841 dag = dagutil.revlogdag(repo.changelog)
1841 dag = dagutil.revlogdag(repo.changelog)
1842 all = dag.ancestorset(dag.internalizeall(common))
1842 all = dag.ancestorset(dag.internalizeall(common))
1843 common = dag.externalizeall(dag.headsetofconnecteds(all))
1843 common = dag.externalizeall(dag.headsetofconnecteds(all))
1844 else:
1844 else:
1845 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1845 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1846 common = set(common)
1846 common = set(common)
1847 rheads = set(hds)
1847 rheads = set(hds)
1848 lheads = set(repo.heads())
1848 lheads = set(repo.heads())
1849 ui.write(("common heads: %s\n") %
1849 ui.write(("common heads: %s\n") %
1850 " ".join(sorted(short(n) for n in common)))
1850 " ".join(sorted(short(n) for n in common)))
1851 if lheads <= common:
1851 if lheads <= common:
1852 ui.write(("local is subset\n"))
1852 ui.write(("local is subset\n"))
1853 elif rheads <= common:
1853 elif rheads <= common:
1854 ui.write(("remote is subset\n"))
1854 ui.write(("remote is subset\n"))
1855
1855
1856 serverlogs = opts.get('serverlog')
1856 serverlogs = opts.get('serverlog')
1857 if serverlogs:
1857 if serverlogs:
1858 for filename in serverlogs:
1858 for filename in serverlogs:
1859 logfile = open(filename, 'r')
1859 logfile = open(filename, 'r')
1860 try:
1860 try:
1861 line = logfile.readline()
1861 line = logfile.readline()
1862 while line:
1862 while line:
1863 parts = line.strip().split(';')
1863 parts = line.strip().split(';')
1864 op = parts[1]
1864 op = parts[1]
1865 if op == 'cg':
1865 if op == 'cg':
1866 pass
1866 pass
1867 elif op == 'cgss':
1867 elif op == 'cgss':
1868 doit(parts[2].split(' '), parts[3].split(' '))
1868 doit(parts[2].split(' '), parts[3].split(' '))
1869 elif op == 'unb':
1869 elif op == 'unb':
1870 doit(parts[3].split(' '), parts[2].split(' '))
1870 doit(parts[3].split(' '), parts[2].split(' '))
1871 line = logfile.readline()
1871 line = logfile.readline()
1872 finally:
1872 finally:
1873 logfile.close()
1873 logfile.close()
1874
1874
1875 else:
1875 else:
1876 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1876 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1877 opts.get('remote_head'))
1877 opts.get('remote_head'))
1878 localrevs = opts.get('local_head')
1878 localrevs = opts.get('local_head')
1879 doit(localrevs, remoterevs)
1879 doit(localrevs, remoterevs)
1880
1880
1881 @command('debugfileset',
1881 @command('debugfileset',
1882 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1882 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1883 _('[-r REV] FILESPEC'))
1883 _('[-r REV] FILESPEC'))
1884 def debugfileset(ui, repo, expr, **opts):
1884 def debugfileset(ui, repo, expr, **opts):
1885 '''parse and apply a fileset specification'''
1885 '''parse and apply a fileset specification'''
1886 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1886 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1887 if ui.verbose:
1887 if ui.verbose:
1888 tree = fileset.parse(expr)[0]
1888 tree = fileset.parse(expr)[0]
1889 ui.note(tree, "\n")
1889 ui.note(tree, "\n")
1890
1890
1891 for f in fileset.getfileset(ctx, expr):
1891 for f in fileset.getfileset(ctx, expr):
1892 ui.write("%s\n" % f)
1892 ui.write("%s\n" % f)
1893
1893
1894 @command('debugfsinfo', [], _('[PATH]'))
1894 @command('debugfsinfo', [], _('[PATH]'))
1895 def debugfsinfo(ui, path = "."):
1895 def debugfsinfo(ui, path = "."):
1896 """show information detected about current filesystem"""
1896 """show information detected about current filesystem"""
1897 util.writefile('.debugfsinfo', '')
1897 util.writefile('.debugfsinfo', '')
1898 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1898 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1899 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1899 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1900 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1900 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1901 and 'yes' or 'no'))
1901 and 'yes' or 'no'))
1902 os.unlink('.debugfsinfo')
1902 os.unlink('.debugfsinfo')
1903
1903
1904 @command('debuggetbundle',
1904 @command('debuggetbundle',
1905 [('H', 'head', [], _('id of head node'), _('ID')),
1905 [('H', 'head', [], _('id of head node'), _('ID')),
1906 ('C', 'common', [], _('id of common node'), _('ID')),
1906 ('C', 'common', [], _('id of common node'), _('ID')),
1907 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1907 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1908 _('REPO FILE [-H|-C ID]...'))
1908 _('REPO FILE [-H|-C ID]...'))
1909 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1909 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1910 """retrieves a bundle from a repo
1910 """retrieves a bundle from a repo
1911
1911
1912 Every ID must be a full-length hex node id string. Saves the bundle to the
1912 Every ID must be a full-length hex node id string. Saves the bundle to the
1913 given file.
1913 given file.
1914 """
1914 """
1915 repo = hg.peer(ui, opts, repopath)
1915 repo = hg.peer(ui, opts, repopath)
1916 if not repo.capable('getbundle'):
1916 if not repo.capable('getbundle'):
1917 raise util.Abort("getbundle() not supported by target repository")
1917 raise util.Abort("getbundle() not supported by target repository")
1918 args = {}
1918 args = {}
1919 if common:
1919 if common:
1920 args['common'] = [bin(s) for s in common]
1920 args['common'] = [bin(s) for s in common]
1921 if head:
1921 if head:
1922 args['heads'] = [bin(s) for s in head]
1922 args['heads'] = [bin(s) for s in head]
1923 bundle = repo.getbundle('debug', **args)
1923 bundle = repo.getbundle('debug', **args)
1924
1924
1925 bundletype = opts.get('type', 'bzip2').lower()
1925 bundletype = opts.get('type', 'bzip2').lower()
1926 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1926 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1927 bundletype = btypes.get(bundletype)
1927 bundletype = btypes.get(bundletype)
1928 if bundletype not in changegroup.bundletypes:
1928 if bundletype not in changegroup.bundletypes:
1929 raise util.Abort(_('unknown bundle type specified with --type'))
1929 raise util.Abort(_('unknown bundle type specified with --type'))
1930 changegroup.writebundle(bundle, bundlepath, bundletype)
1930 changegroup.writebundle(bundle, bundlepath, bundletype)
1931
1931
1932 @command('debugignore', [], '')
1932 @command('debugignore', [], '')
1933 def debugignore(ui, repo, *values, **opts):
1933 def debugignore(ui, repo, *values, **opts):
1934 """display the combined ignore pattern"""
1934 """display the combined ignore pattern"""
1935 ignore = repo.dirstate._ignore
1935 ignore = repo.dirstate._ignore
1936 includepat = getattr(ignore, 'includepat', None)
1936 includepat = getattr(ignore, 'includepat', None)
1937 if includepat is not None:
1937 if includepat is not None:
1938 ui.write("%s\n" % includepat)
1938 ui.write("%s\n" % includepat)
1939 else:
1939 else:
1940 raise util.Abort(_("no ignore patterns found"))
1940 raise util.Abort(_("no ignore patterns found"))
1941
1941
1942 @command('debugindex',
1942 @command('debugindex',
1943 [('c', 'changelog', False, _('open changelog')),
1943 [('c', 'changelog', False, _('open changelog')),
1944 ('m', 'manifest', False, _('open manifest')),
1944 ('m', 'manifest', False, _('open manifest')),
1945 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1945 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1946 _('[-f FORMAT] -c|-m|FILE'))
1946 _('[-f FORMAT] -c|-m|FILE'))
1947 def debugindex(ui, repo, file_ = None, **opts):
1947 def debugindex(ui, repo, file_ = None, **opts):
1948 """dump the contents of an index file"""
1948 """dump the contents of an index file"""
1949 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1949 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1950 format = opts.get('format', 0)
1950 format = opts.get('format', 0)
1951 if format not in (0, 1):
1951 if format not in (0, 1):
1952 raise util.Abort(_("unknown format %d") % format)
1952 raise util.Abort(_("unknown format %d") % format)
1953
1953
1954 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1954 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1955 if generaldelta:
1955 if generaldelta:
1956 basehdr = ' delta'
1956 basehdr = ' delta'
1957 else:
1957 else:
1958 basehdr = ' base'
1958 basehdr = ' base'
1959
1959
1960 if format == 0:
1960 if format == 0:
1961 ui.write(" rev offset length " + basehdr + " linkrev"
1961 ui.write(" rev offset length " + basehdr + " linkrev"
1962 " nodeid p1 p2\n")
1962 " nodeid p1 p2\n")
1963 elif format == 1:
1963 elif format == 1:
1964 ui.write(" rev flag offset length"
1964 ui.write(" rev flag offset length"
1965 " size " + basehdr + " link p1 p2"
1965 " size " + basehdr + " link p1 p2"
1966 " nodeid\n")
1966 " nodeid\n")
1967
1967
1968 for i in r:
1968 for i in r:
1969 node = r.node(i)
1969 node = r.node(i)
1970 if generaldelta:
1970 if generaldelta:
1971 base = r.deltaparent(i)
1971 base = r.deltaparent(i)
1972 else:
1972 else:
1973 base = r.chainbase(i)
1973 base = r.chainbase(i)
1974 if format == 0:
1974 if format == 0:
1975 try:
1975 try:
1976 pp = r.parents(node)
1976 pp = r.parents(node)
1977 except Exception:
1977 except Exception:
1978 pp = [nullid, nullid]
1978 pp = [nullid, nullid]
1979 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1979 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1980 i, r.start(i), r.length(i), base, r.linkrev(i),
1980 i, r.start(i), r.length(i), base, r.linkrev(i),
1981 short(node), short(pp[0]), short(pp[1])))
1981 short(node), short(pp[0]), short(pp[1])))
1982 elif format == 1:
1982 elif format == 1:
1983 pr = r.parentrevs(i)
1983 pr = r.parentrevs(i)
1984 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1984 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1985 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1985 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1986 base, r.linkrev(i), pr[0], pr[1], short(node)))
1986 base, r.linkrev(i), pr[0], pr[1], short(node)))
1987
1987
1988 @command('debugindexdot', [], _('FILE'))
1988 @command('debugindexdot', [], _('FILE'))
1989 def debugindexdot(ui, repo, file_):
1989 def debugindexdot(ui, repo, file_):
1990 """dump an index DAG as a graphviz dot file"""
1990 """dump an index DAG as a graphviz dot file"""
1991 r = None
1991 r = None
1992 if repo:
1992 if repo:
1993 filelog = repo.file(file_)
1993 filelog = repo.file(file_)
1994 if len(filelog):
1994 if len(filelog):
1995 r = filelog
1995 r = filelog
1996 if not r:
1996 if not r:
1997 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1997 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1998 ui.write(("digraph G {\n"))
1998 ui.write(("digraph G {\n"))
1999 for i in r:
1999 for i in r:
2000 node = r.node(i)
2000 node = r.node(i)
2001 pp = r.parents(node)
2001 pp = r.parents(node)
2002 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2002 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2003 if pp[1] != nullid:
2003 if pp[1] != nullid:
2004 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2004 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2005 ui.write("}\n")
2005 ui.write("}\n")
2006
2006
2007 @command('debuginstall', [], '')
2007 @command('debuginstall', [], '')
2008 def debuginstall(ui):
2008 def debuginstall(ui):
2009 '''test Mercurial installation
2009 '''test Mercurial installation
2010
2010
2011 Returns 0 on success.
2011 Returns 0 on success.
2012 '''
2012 '''
2013
2013
2014 def writetemp(contents):
2014 def writetemp(contents):
2015 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2015 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2016 f = os.fdopen(fd, "wb")
2016 f = os.fdopen(fd, "wb")
2017 f.write(contents)
2017 f.write(contents)
2018 f.close()
2018 f.close()
2019 return name
2019 return name
2020
2020
2021 problems = 0
2021 problems = 0
2022
2022
2023 # encoding
2023 # encoding
2024 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2024 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2025 try:
2025 try:
2026 encoding.fromlocal("test")
2026 encoding.fromlocal("test")
2027 except util.Abort, inst:
2027 except util.Abort, inst:
2028 ui.write(" %s\n" % inst)
2028 ui.write(" %s\n" % inst)
2029 ui.write(_(" (check that your locale is properly set)\n"))
2029 ui.write(_(" (check that your locale is properly set)\n"))
2030 problems += 1
2030 problems += 1
2031
2031
2032 # Python lib
2032 # Python lib
2033 ui.status(_("checking Python lib (%s)...\n")
2033 ui.status(_("checking Python lib (%s)...\n")
2034 % os.path.dirname(os.__file__))
2034 % os.path.dirname(os.__file__))
2035
2035
2036 # compiled modules
2036 # compiled modules
2037 ui.status(_("checking installed modules (%s)...\n")
2037 ui.status(_("checking installed modules (%s)...\n")
2038 % os.path.dirname(__file__))
2038 % os.path.dirname(__file__))
2039 try:
2039 try:
2040 import bdiff, mpatch, base85, osutil
2040 import bdiff, mpatch, base85, osutil
2041 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2041 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2042 except Exception, inst:
2042 except Exception, inst:
2043 ui.write(" %s\n" % inst)
2043 ui.write(" %s\n" % inst)
2044 ui.write(_(" One or more extensions could not be found"))
2044 ui.write(_(" One or more extensions could not be found"))
2045 ui.write(_(" (check that you compiled the extensions)\n"))
2045 ui.write(_(" (check that you compiled the extensions)\n"))
2046 problems += 1
2046 problems += 1
2047
2047
2048 # templates
2048 # templates
2049 import templater
2049 import templater
2050 p = templater.templatepath()
2050 p = templater.templatepath()
2051 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2051 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2052 try:
2052 try:
2053 templater.templater(templater.templatepath("map-cmdline.default"))
2053 templater.templater(templater.templatepath("map-cmdline.default"))
2054 except Exception, inst:
2054 except Exception, inst:
2055 ui.write(" %s\n" % inst)
2055 ui.write(" %s\n" % inst)
2056 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2056 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2057 problems += 1
2057 problems += 1
2058
2058
2059 # editor
2059 # editor
2060 ui.status(_("checking commit editor...\n"))
2060 ui.status(_("checking commit editor...\n"))
2061 editor = ui.geteditor()
2061 editor = ui.geteditor()
2062 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2062 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2063 if not cmdpath:
2063 if not cmdpath:
2064 if editor == 'vi':
2064 if editor == 'vi':
2065 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2065 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2066 ui.write(_(" (specify a commit editor in your configuration"
2066 ui.write(_(" (specify a commit editor in your configuration"
2067 " file)\n"))
2067 " file)\n"))
2068 else:
2068 else:
2069 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2069 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2070 ui.write(_(" (specify a commit editor in your configuration"
2070 ui.write(_(" (specify a commit editor in your configuration"
2071 " file)\n"))
2071 " file)\n"))
2072 problems += 1
2072 problems += 1
2073
2073
2074 # check username
2074 # check username
2075 ui.status(_("checking username...\n"))
2075 ui.status(_("checking username...\n"))
2076 try:
2076 try:
2077 ui.username()
2077 ui.username()
2078 except util.Abort, e:
2078 except util.Abort, e:
2079 ui.write(" %s\n" % e)
2079 ui.write(" %s\n" % e)
2080 ui.write(_(" (specify a username in your configuration file)\n"))
2080 ui.write(_(" (specify a username in your configuration file)\n"))
2081 problems += 1
2081 problems += 1
2082
2082
2083 if not problems:
2083 if not problems:
2084 ui.status(_("no problems detected\n"))
2084 ui.status(_("no problems detected\n"))
2085 else:
2085 else:
2086 ui.write(_("%s problems detected,"
2086 ui.write(_("%s problems detected,"
2087 " please check your install!\n") % problems)
2087 " please check your install!\n") % problems)
2088
2088
2089 return problems
2089 return problems
2090
2090
2091 @command('debugknown', [], _('REPO ID...'))
2091 @command('debugknown', [], _('REPO ID...'))
2092 def debugknown(ui, repopath, *ids, **opts):
2092 def debugknown(ui, repopath, *ids, **opts):
2093 """test whether node ids are known to a repo
2093 """test whether node ids are known to a repo
2094
2094
2095 Every ID must be a full-length hex node id string. Returns a list of 0s
2095 Every ID must be a full-length hex node id string. Returns a list of 0s
2096 and 1s indicating unknown/known.
2096 and 1s indicating unknown/known.
2097 """
2097 """
2098 repo = hg.peer(ui, opts, repopath)
2098 repo = hg.peer(ui, opts, repopath)
2099 if not repo.capable('known'):
2099 if not repo.capable('known'):
2100 raise util.Abort("known() not supported by target repository")
2100 raise util.Abort("known() not supported by target repository")
2101 flags = repo.known([bin(s) for s in ids])
2101 flags = repo.known([bin(s) for s in ids])
2102 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2102 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2103
2103
2104 @command('debugobsolete',
2104 @command('debugobsolete',
2105 [('', 'flags', 0, _('markers flag')),
2105 [('', 'flags', 0, _('markers flag')),
2106 ] + commitopts2,
2106 ] + commitopts2,
2107 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2107 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2108 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2108 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2109 """create arbitrary obsolete marker
2109 """create arbitrary obsolete marker
2110
2110
2111 With no arguments it it display the list obsolescence marker."""
2111 With no arguments it it display the list obsolescence marker."""
2112 def parsenodeid(s):
2112 def parsenodeid(s):
2113 try:
2113 try:
2114 # We do not use revsingle/revrange functions here to accept
2114 # We do not use revsingle/revrange functions here to accept
2115 # arbitrary node identifiers, possibly not present in the
2115 # arbitrary node identifiers, possibly not present in the
2116 # local repository.
2116 # local repository.
2117 n = bin(s)
2117 n = bin(s)
2118 if len(n) != len(nullid):
2118 if len(n) != len(nullid):
2119 raise TypeError()
2119 raise TypeError()
2120 return n
2120 return n
2121 except TypeError:
2121 except TypeError:
2122 raise util.Abort('changeset references must be full hexadecimal '
2122 raise util.Abort('changeset references must be full hexadecimal '
2123 'node identifiers')
2123 'node identifiers')
2124
2124
2125 if precursor is not None:
2125 if precursor is not None:
2126 metadata = {}
2126 metadata = {}
2127 if 'date' in opts:
2127 if 'date' in opts:
2128 metadata['date'] = opts['date']
2128 metadata['date'] = opts['date']
2129 metadata['user'] = opts['user'] or ui.username()
2129 metadata['user'] = opts['user'] or ui.username()
2130 succs = tuple(parsenodeid(succ) for succ in successors)
2130 succs = tuple(parsenodeid(succ) for succ in successors)
2131 l = repo.lock()
2131 l = repo.lock()
2132 try:
2132 try:
2133 tr = repo.transaction('debugobsolete')
2133 tr = repo.transaction('debugobsolete')
2134 try:
2134 try:
2135 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2135 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2136 opts['flags'], metadata)
2136 opts['flags'], metadata)
2137 tr.close()
2137 tr.close()
2138 finally:
2138 finally:
2139 tr.release()
2139 tr.release()
2140 finally:
2140 finally:
2141 l.release()
2141 l.release()
2142 else:
2142 else:
2143 for m in obsolete.allmarkers(repo):
2143 for m in obsolete.allmarkers(repo):
2144 ui.write(hex(m.precnode()))
2144 ui.write(hex(m.precnode()))
2145 for repl in m.succnodes():
2145 for repl in m.succnodes():
2146 ui.write(' ')
2146 ui.write(' ')
2147 ui.write(hex(repl))
2147 ui.write(hex(repl))
2148 ui.write(' %X ' % m._data[2])
2148 ui.write(' %X ' % m._data[2])
2149 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2149 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2150 sorted(m.metadata().items()))))
2150 sorted(m.metadata().items()))))
2151 ui.write('\n')
2151 ui.write('\n')
2152
2152
2153 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2153 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2154 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2154 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2155 '''access the pushkey key/value protocol
2155 '''access the pushkey key/value protocol
2156
2156
2157 With two args, list the keys in the given namespace.
2157 With two args, list the keys in the given namespace.
2158
2158
2159 With five args, set a key to new if it currently is set to old.
2159 With five args, set a key to new if it currently is set to old.
2160 Reports success or failure.
2160 Reports success or failure.
2161 '''
2161 '''
2162
2162
2163 target = hg.peer(ui, {}, repopath)
2163 target = hg.peer(ui, {}, repopath)
2164 if keyinfo:
2164 if keyinfo:
2165 key, old, new = keyinfo
2165 key, old, new = keyinfo
2166 r = target.pushkey(namespace, key, old, new)
2166 r = target.pushkey(namespace, key, old, new)
2167 ui.status(str(r) + '\n')
2167 ui.status(str(r) + '\n')
2168 return not r
2168 return not r
2169 else:
2169 else:
2170 for k, v in sorted(target.listkeys(namespace).iteritems()):
2170 for k, v in sorted(target.listkeys(namespace).iteritems()):
2171 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2171 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2172 v.encode('string-escape')))
2172 v.encode('string-escape')))
2173
2173
2174 @command('debugpvec', [], _('A B'))
2174 @command('debugpvec', [], _('A B'))
2175 def debugpvec(ui, repo, a, b=None):
2175 def debugpvec(ui, repo, a, b=None):
2176 ca = scmutil.revsingle(repo, a)
2176 ca = scmutil.revsingle(repo, a)
2177 cb = scmutil.revsingle(repo, b)
2177 cb = scmutil.revsingle(repo, b)
2178 pa = pvec.ctxpvec(ca)
2178 pa = pvec.ctxpvec(ca)
2179 pb = pvec.ctxpvec(cb)
2179 pb = pvec.ctxpvec(cb)
2180 if pa == pb:
2180 if pa == pb:
2181 rel = "="
2181 rel = "="
2182 elif pa > pb:
2182 elif pa > pb:
2183 rel = ">"
2183 rel = ">"
2184 elif pa < pb:
2184 elif pa < pb:
2185 rel = "<"
2185 rel = "<"
2186 elif pa | pb:
2186 elif pa | pb:
2187 rel = "|"
2187 rel = "|"
2188 ui.write(_("a: %s\n") % pa)
2188 ui.write(_("a: %s\n") % pa)
2189 ui.write(_("b: %s\n") % pb)
2189 ui.write(_("b: %s\n") % pb)
2190 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2190 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2191 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2191 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2192 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2192 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2193 pa.distance(pb), rel))
2193 pa.distance(pb), rel))
2194
2194
2195 @command('debugrebuildstate',
2195 @command('debugrebuildstate',
2196 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2196 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2197 _('[-r REV] [REV]'))
2197 _('[-r REV] [REV]'))
2198 def debugrebuildstate(ui, repo, rev="tip"):
2198 def debugrebuildstate(ui, repo, rev="tip"):
2199 """rebuild the dirstate as it would look like for the given revision"""
2199 """rebuild the dirstate as it would look like for the given revision"""
2200 ctx = scmutil.revsingle(repo, rev)
2200 ctx = scmutil.revsingle(repo, rev)
2201 wlock = repo.wlock()
2201 wlock = repo.wlock()
2202 try:
2202 try:
2203 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2203 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2204 finally:
2204 finally:
2205 wlock.release()
2205 wlock.release()
2206
2206
2207 @command('debugrename',
2207 @command('debugrename',
2208 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2208 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2209 _('[-r REV] FILE'))
2209 _('[-r REV] FILE'))
2210 def debugrename(ui, repo, file1, *pats, **opts):
2210 def debugrename(ui, repo, file1, *pats, **opts):
2211 """dump rename information"""
2211 """dump rename information"""
2212
2212
2213 ctx = scmutil.revsingle(repo, opts.get('rev'))
2213 ctx = scmutil.revsingle(repo, opts.get('rev'))
2214 m = scmutil.match(ctx, (file1,) + pats, opts)
2214 m = scmutil.match(ctx, (file1,) + pats, opts)
2215 for abs in ctx.walk(m):
2215 for abs in ctx.walk(m):
2216 fctx = ctx[abs]
2216 fctx = ctx[abs]
2217 o = fctx.filelog().renamed(fctx.filenode())
2217 o = fctx.filelog().renamed(fctx.filenode())
2218 rel = m.rel(abs)
2218 rel = m.rel(abs)
2219 if o:
2219 if o:
2220 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2220 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2221 else:
2221 else:
2222 ui.write(_("%s not renamed\n") % rel)
2222 ui.write(_("%s not renamed\n") % rel)
2223
2223
2224 @command('debugrevlog',
2224 @command('debugrevlog',
2225 [('c', 'changelog', False, _('open changelog')),
2225 [('c', 'changelog', False, _('open changelog')),
2226 ('m', 'manifest', False, _('open manifest')),
2226 ('m', 'manifest', False, _('open manifest')),
2227 ('d', 'dump', False, _('dump index data'))],
2227 ('d', 'dump', False, _('dump index data'))],
2228 _('-c|-m|FILE'))
2228 _('-c|-m|FILE'))
2229 def debugrevlog(ui, repo, file_ = None, **opts):
2229 def debugrevlog(ui, repo, file_ = None, **opts):
2230 """show data and statistics about a revlog"""
2230 """show data and statistics about a revlog"""
2231 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2231 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2232
2232
2233 if opts.get("dump"):
2233 if opts.get("dump"):
2234 numrevs = len(r)
2234 numrevs = len(r)
2235 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2235 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2236 " rawsize totalsize compression heads\n")
2236 " rawsize totalsize compression heads\n")
2237 ts = 0
2237 ts = 0
2238 heads = set()
2238 heads = set()
2239 for rev in xrange(numrevs):
2239 for rev in xrange(numrevs):
2240 dbase = r.deltaparent(rev)
2240 dbase = r.deltaparent(rev)
2241 if dbase == -1:
2241 if dbase == -1:
2242 dbase = rev
2242 dbase = rev
2243 cbase = r.chainbase(rev)
2243 cbase = r.chainbase(rev)
2244 p1, p2 = r.parentrevs(rev)
2244 p1, p2 = r.parentrevs(rev)
2245 rs = r.rawsize(rev)
2245 rs = r.rawsize(rev)
2246 ts = ts + rs
2246 ts = ts + rs
2247 heads -= set(r.parentrevs(rev))
2247 heads -= set(r.parentrevs(rev))
2248 heads.add(rev)
2248 heads.add(rev)
2249 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2249 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2250 (rev, p1, p2, r.start(rev), r.end(rev),
2250 (rev, p1, p2, r.start(rev), r.end(rev),
2251 r.start(dbase), r.start(cbase),
2251 r.start(dbase), r.start(cbase),
2252 r.start(p1), r.start(p2),
2252 r.start(p1), r.start(p2),
2253 rs, ts, ts / r.end(rev), len(heads)))
2253 rs, ts, ts / r.end(rev), len(heads)))
2254 return 0
2254 return 0
2255
2255
2256 v = r.version
2256 v = r.version
2257 format = v & 0xFFFF
2257 format = v & 0xFFFF
2258 flags = []
2258 flags = []
2259 gdelta = False
2259 gdelta = False
2260 if v & revlog.REVLOGNGINLINEDATA:
2260 if v & revlog.REVLOGNGINLINEDATA:
2261 flags.append('inline')
2261 flags.append('inline')
2262 if v & revlog.REVLOGGENERALDELTA:
2262 if v & revlog.REVLOGGENERALDELTA:
2263 gdelta = True
2263 gdelta = True
2264 flags.append('generaldelta')
2264 flags.append('generaldelta')
2265 if not flags:
2265 if not flags:
2266 flags = ['(none)']
2266 flags = ['(none)']
2267
2267
2268 nummerges = 0
2268 nummerges = 0
2269 numfull = 0
2269 numfull = 0
2270 numprev = 0
2270 numprev = 0
2271 nump1 = 0
2271 nump1 = 0
2272 nump2 = 0
2272 nump2 = 0
2273 numother = 0
2273 numother = 0
2274 nump1prev = 0
2274 nump1prev = 0
2275 nump2prev = 0
2275 nump2prev = 0
2276 chainlengths = []
2276 chainlengths = []
2277
2277
2278 datasize = [None, 0, 0L]
2278 datasize = [None, 0, 0L]
2279 fullsize = [None, 0, 0L]
2279 fullsize = [None, 0, 0L]
2280 deltasize = [None, 0, 0L]
2280 deltasize = [None, 0, 0L]
2281
2281
2282 def addsize(size, l):
2282 def addsize(size, l):
2283 if l[0] is None or size < l[0]:
2283 if l[0] is None or size < l[0]:
2284 l[0] = size
2284 l[0] = size
2285 if size > l[1]:
2285 if size > l[1]:
2286 l[1] = size
2286 l[1] = size
2287 l[2] += size
2287 l[2] += size
2288
2288
2289 numrevs = len(r)
2289 numrevs = len(r)
2290 for rev in xrange(numrevs):
2290 for rev in xrange(numrevs):
2291 p1, p2 = r.parentrevs(rev)
2291 p1, p2 = r.parentrevs(rev)
2292 delta = r.deltaparent(rev)
2292 delta = r.deltaparent(rev)
2293 if format > 0:
2293 if format > 0:
2294 addsize(r.rawsize(rev), datasize)
2294 addsize(r.rawsize(rev), datasize)
2295 if p2 != nullrev:
2295 if p2 != nullrev:
2296 nummerges += 1
2296 nummerges += 1
2297 size = r.length(rev)
2297 size = r.length(rev)
2298 if delta == nullrev:
2298 if delta == nullrev:
2299 chainlengths.append(0)
2299 chainlengths.append(0)
2300 numfull += 1
2300 numfull += 1
2301 addsize(size, fullsize)
2301 addsize(size, fullsize)
2302 else:
2302 else:
2303 chainlengths.append(chainlengths[delta] + 1)
2303 chainlengths.append(chainlengths[delta] + 1)
2304 addsize(size, deltasize)
2304 addsize(size, deltasize)
2305 if delta == rev - 1:
2305 if delta == rev - 1:
2306 numprev += 1
2306 numprev += 1
2307 if delta == p1:
2307 if delta == p1:
2308 nump1prev += 1
2308 nump1prev += 1
2309 elif delta == p2:
2309 elif delta == p2:
2310 nump2prev += 1
2310 nump2prev += 1
2311 elif delta == p1:
2311 elif delta == p1:
2312 nump1 += 1
2312 nump1 += 1
2313 elif delta == p2:
2313 elif delta == p2:
2314 nump2 += 1
2314 nump2 += 1
2315 elif delta != nullrev:
2315 elif delta != nullrev:
2316 numother += 1
2316 numother += 1
2317
2317
2318 # Adjust size min value for empty cases
2318 # Adjust size min value for empty cases
2319 for size in (datasize, fullsize, deltasize):
2319 for size in (datasize, fullsize, deltasize):
2320 if size[0] is None:
2320 if size[0] is None:
2321 size[0] = 0
2321 size[0] = 0
2322
2322
2323 numdeltas = numrevs - numfull
2323 numdeltas = numrevs - numfull
2324 numoprev = numprev - nump1prev - nump2prev
2324 numoprev = numprev - nump1prev - nump2prev
2325 totalrawsize = datasize[2]
2325 totalrawsize = datasize[2]
2326 datasize[2] /= numrevs
2326 datasize[2] /= numrevs
2327 fulltotal = fullsize[2]
2327 fulltotal = fullsize[2]
2328 fullsize[2] /= numfull
2328 fullsize[2] /= numfull
2329 deltatotal = deltasize[2]
2329 deltatotal = deltasize[2]
2330 if numrevs - numfull > 0:
2330 if numrevs - numfull > 0:
2331 deltasize[2] /= numrevs - numfull
2331 deltasize[2] /= numrevs - numfull
2332 totalsize = fulltotal + deltatotal
2332 totalsize = fulltotal + deltatotal
2333 avgchainlen = sum(chainlengths) / numrevs
2333 avgchainlen = sum(chainlengths) / numrevs
2334 compratio = totalrawsize / totalsize
2334 compratio = totalrawsize / totalsize
2335
2335
2336 basedfmtstr = '%%%dd\n'
2336 basedfmtstr = '%%%dd\n'
2337 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2337 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2338
2338
2339 def dfmtstr(max):
2339 def dfmtstr(max):
2340 return basedfmtstr % len(str(max))
2340 return basedfmtstr % len(str(max))
2341 def pcfmtstr(max, padding=0):
2341 def pcfmtstr(max, padding=0):
2342 return basepcfmtstr % (len(str(max)), ' ' * padding)
2342 return basepcfmtstr % (len(str(max)), ' ' * padding)
2343
2343
2344 def pcfmt(value, total):
2344 def pcfmt(value, total):
2345 return (value, 100 * float(value) / total)
2345 return (value, 100 * float(value) / total)
2346
2346
2347 ui.write(('format : %d\n') % format)
2347 ui.write(('format : %d\n') % format)
2348 ui.write(('flags : %s\n') % ', '.join(flags))
2348 ui.write(('flags : %s\n') % ', '.join(flags))
2349
2349
2350 ui.write('\n')
2350 ui.write('\n')
2351 fmt = pcfmtstr(totalsize)
2351 fmt = pcfmtstr(totalsize)
2352 fmt2 = dfmtstr(totalsize)
2352 fmt2 = dfmtstr(totalsize)
2353 ui.write(('revisions : ') + fmt2 % numrevs)
2353 ui.write(('revisions : ') + fmt2 % numrevs)
2354 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2354 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2355 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2355 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2356 ui.write(('revisions : ') + fmt2 % numrevs)
2356 ui.write(('revisions : ') + fmt2 % numrevs)
2357 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2357 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2358 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2358 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2359 ui.write(('revision size : ') + fmt2 % totalsize)
2359 ui.write(('revision size : ') + fmt2 % totalsize)
2360 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2360 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2361 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2361 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2362
2362
2363 ui.write('\n')
2363 ui.write('\n')
2364 fmt = dfmtstr(max(avgchainlen, compratio))
2364 fmt = dfmtstr(max(avgchainlen, compratio))
2365 ui.write(('avg chain length : ') + fmt % avgchainlen)
2365 ui.write(('avg chain length : ') + fmt % avgchainlen)
2366 ui.write(('compression ratio : ') + fmt % compratio)
2366 ui.write(('compression ratio : ') + fmt % compratio)
2367
2367
2368 if format > 0:
2368 if format > 0:
2369 ui.write('\n')
2369 ui.write('\n')
2370 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2370 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2371 % tuple(datasize))
2371 % tuple(datasize))
2372 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2372 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2373 % tuple(fullsize))
2373 % tuple(fullsize))
2374 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2374 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2375 % tuple(deltasize))
2375 % tuple(deltasize))
2376
2376
2377 if numdeltas > 0:
2377 if numdeltas > 0:
2378 ui.write('\n')
2378 ui.write('\n')
2379 fmt = pcfmtstr(numdeltas)
2379 fmt = pcfmtstr(numdeltas)
2380 fmt2 = pcfmtstr(numdeltas, 4)
2380 fmt2 = pcfmtstr(numdeltas, 4)
2381 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2381 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2382 if numprev > 0:
2382 if numprev > 0:
2383 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2383 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2384 numprev))
2384 numprev))
2385 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2385 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2386 numprev))
2386 numprev))
2387 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2387 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2388 numprev))
2388 numprev))
2389 if gdelta:
2389 if gdelta:
2390 ui.write(('deltas against p1 : ')
2390 ui.write(('deltas against p1 : ')
2391 + fmt % pcfmt(nump1, numdeltas))
2391 + fmt % pcfmt(nump1, numdeltas))
2392 ui.write(('deltas against p2 : ')
2392 ui.write(('deltas against p2 : ')
2393 + fmt % pcfmt(nump2, numdeltas))
2393 + fmt % pcfmt(nump2, numdeltas))
2394 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2394 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2395 numdeltas))
2395 numdeltas))
2396
2396
2397 @command('debugrevspec', [], ('REVSPEC'))
2397 @command('debugrevspec', [], ('REVSPEC'))
2398 def debugrevspec(ui, repo, expr):
2398 def debugrevspec(ui, repo, expr):
2399 """parse and apply a revision specification
2399 """parse and apply a revision specification
2400
2400
2401 Use --verbose to print the parsed tree before and after aliases
2401 Use --verbose to print the parsed tree before and after aliases
2402 expansion.
2402 expansion.
2403 """
2403 """
2404 if ui.verbose:
2404 if ui.verbose:
2405 tree = revset.parse(expr)[0]
2405 tree = revset.parse(expr)[0]
2406 ui.note(revset.prettyformat(tree), "\n")
2406 ui.note(revset.prettyformat(tree), "\n")
2407 newtree = revset.findaliases(ui, tree)
2407 newtree = revset.findaliases(ui, tree)
2408 if newtree != tree:
2408 if newtree != tree:
2409 ui.note(revset.prettyformat(newtree), "\n")
2409 ui.note(revset.prettyformat(newtree), "\n")
2410 func = revset.match(ui, expr)
2410 func = revset.match(ui, expr)
2411 for c in func(repo, range(len(repo))):
2411 for c in func(repo, range(len(repo))):
2412 ui.write("%s\n" % c)
2412 ui.write("%s\n" % c)
2413
2413
2414 @command('debugsetparents', [], _('REV1 [REV2]'))
2414 @command('debugsetparents', [], _('REV1 [REV2]'))
2415 def debugsetparents(ui, repo, rev1, rev2=None):
2415 def debugsetparents(ui, repo, rev1, rev2=None):
2416 """manually set the parents of the current working directory
2416 """manually set the parents of the current working directory
2417
2417
2418 This is useful for writing repository conversion tools, but should
2418 This is useful for writing repository conversion tools, but should
2419 be used with care.
2419 be used with care.
2420
2420
2421 Returns 0 on success.
2421 Returns 0 on success.
2422 """
2422 """
2423
2423
2424 r1 = scmutil.revsingle(repo, rev1).node()
2424 r1 = scmutil.revsingle(repo, rev1).node()
2425 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2425 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2426
2426
2427 wlock = repo.wlock()
2427 wlock = repo.wlock()
2428 try:
2428 try:
2429 repo.setparents(r1, r2)
2429 repo.setparents(r1, r2)
2430 finally:
2430 finally:
2431 wlock.release()
2431 wlock.release()
2432
2432
2433 @command('debugstate',
2433 @command('debugstate',
2434 [('', 'nodates', None, _('do not display the saved mtime')),
2434 [('', 'nodates', None, _('do not display the saved mtime')),
2435 ('', 'datesort', None, _('sort by saved mtime'))],
2435 ('', 'datesort', None, _('sort by saved mtime'))],
2436 _('[OPTION]...'))
2436 _('[OPTION]...'))
2437 def debugstate(ui, repo, nodates=None, datesort=None):
2437 def debugstate(ui, repo, nodates=None, datesort=None):
2438 """show the contents of the current dirstate"""
2438 """show the contents of the current dirstate"""
2439 timestr = ""
2439 timestr = ""
2440 showdate = not nodates
2440 showdate = not nodates
2441 if datesort:
2441 if datesort:
2442 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2442 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2443 else:
2443 else:
2444 keyfunc = None # sort by filename
2444 keyfunc = None # sort by filename
2445 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2445 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2446 if showdate:
2446 if showdate:
2447 if ent[3] == -1:
2447 if ent[3] == -1:
2448 # Pad or slice to locale representation
2448 # Pad or slice to locale representation
2449 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2449 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2450 time.localtime(0)))
2450 time.localtime(0)))
2451 timestr = 'unset'
2451 timestr = 'unset'
2452 timestr = (timestr[:locale_len] +
2452 timestr = (timestr[:locale_len] +
2453 ' ' * (locale_len - len(timestr)))
2453 ' ' * (locale_len - len(timestr)))
2454 else:
2454 else:
2455 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2455 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2456 time.localtime(ent[3]))
2456 time.localtime(ent[3]))
2457 if ent[1] & 020000:
2457 if ent[1] & 020000:
2458 mode = 'lnk'
2458 mode = 'lnk'
2459 else:
2459 else:
2460 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2460 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2461 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2461 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2462 for f in repo.dirstate.copies():
2462 for f in repo.dirstate.copies():
2463 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2463 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2464
2464
2465 @command('debugsub',
2465 @command('debugsub',
2466 [('r', 'rev', '',
2466 [('r', 'rev', '',
2467 _('revision to check'), _('REV'))],
2467 _('revision to check'), _('REV'))],
2468 _('[-r REV] [REV]'))
2468 _('[-r REV] [REV]'))
2469 def debugsub(ui, repo, rev=None):
2469 def debugsub(ui, repo, rev=None):
2470 ctx = scmutil.revsingle(repo, rev, None)
2470 ctx = scmutil.revsingle(repo, rev, None)
2471 for k, v in sorted(ctx.substate.items()):
2471 for k, v in sorted(ctx.substate.items()):
2472 ui.write(('path %s\n') % k)
2472 ui.write(('path %s\n') % k)
2473 ui.write((' source %s\n') % v[0])
2473 ui.write((' source %s\n') % v[0])
2474 ui.write((' revision %s\n') % v[1])
2474 ui.write((' revision %s\n') % v[1])
2475
2475
2476 @command('debugsuccessorssets',
2476 @command('debugsuccessorssets',
2477 [],
2477 [],
2478 _('[REV]'))
2478 _('[REV]'))
2479 def debugsuccessorssets(ui, repo, *revs):
2479 def debugsuccessorssets(ui, repo, *revs):
2480 """show set of successors for revision
2480 """show set of successors for revision
2481
2481
2482 A successors set of changeset A is a consistent group of revisions that
2482 A successors set of changeset A is a consistent group of revisions that
2483 succeed A. It contains non-obsolete changesets only.
2483 succeed A. It contains non-obsolete changesets only.
2484
2484
2485 In most cases a changeset A has a single successors set containing a single
2485 In most cases a changeset A has a single successors set containing a single
2486 successor (changeset A replaced by A').
2486 successor (changeset A replaced by A').
2487
2487
2488 A changeset that is made obsolete with no successors are called "pruned".
2488 A changeset that is made obsolete with no successors are called "pruned".
2489 Such changesets have no successors sets at all.
2489 Such changesets have no successors sets at all.
2490
2490
2491 A changeset that has been "split" will have a successors set containing
2491 A changeset that has been "split" will have a successors set containing
2492 more than one successor.
2492 more than one successor.
2493
2493
2494 A changeset that has been rewritten in multiple different ways is called
2494 A changeset that has been rewritten in multiple different ways is called
2495 "divergent". Such changesets have multiple successor sets (each of which
2495 "divergent". Such changesets have multiple successor sets (each of which
2496 may also be split, i.e. have multiple successors).
2496 may also be split, i.e. have multiple successors).
2497
2497
2498 Results are displayed as follows::
2498 Results are displayed as follows::
2499
2499
2500 <rev1>
2500 <rev1>
2501 <successors-1A>
2501 <successors-1A>
2502 <rev2>
2502 <rev2>
2503 <successors-2A>
2503 <successors-2A>
2504 <successors-2B1> <successors-2B2> <successors-2B3>
2504 <successors-2B1> <successors-2B2> <successors-2B3>
2505
2505
2506 Here rev2 has two possible (i.e. divergent) successors sets. The first
2506 Here rev2 has two possible (i.e. divergent) successors sets. The first
2507 holds one element, whereas the second holds three (i.e. the changeset has
2507 holds one element, whereas the second holds three (i.e. the changeset has
2508 been split).
2508 been split).
2509 """
2509 """
2510 # passed to successorssets caching computation from one call to another
2510 # passed to successorssets caching computation from one call to another
2511 cache = {}
2511 cache = {}
2512 ctx2str = str
2512 ctx2str = str
2513 node2str = short
2513 node2str = short
2514 if ui.debug():
2514 if ui.debug():
2515 def ctx2str(ctx):
2515 def ctx2str(ctx):
2516 return ctx.hex()
2516 return ctx.hex()
2517 node2str = hex
2517 node2str = hex
2518 for rev in scmutil.revrange(repo, revs):
2518 for rev in scmutil.revrange(repo, revs):
2519 ctx = repo[rev]
2519 ctx = repo[rev]
2520 ui.write('%s\n'% ctx2str(ctx))
2520 ui.write('%s\n'% ctx2str(ctx))
2521 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2521 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2522 if succsset:
2522 if succsset:
2523 ui.write(' ')
2523 ui.write(' ')
2524 ui.write(node2str(succsset[0]))
2524 ui.write(node2str(succsset[0]))
2525 for node in succsset[1:]:
2525 for node in succsset[1:]:
2526 ui.write(' ')
2526 ui.write(' ')
2527 ui.write(node2str(node))
2527 ui.write(node2str(node))
2528 ui.write('\n')
2528 ui.write('\n')
2529
2529
2530 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2530 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2531 def debugwalk(ui, repo, *pats, **opts):
2531 def debugwalk(ui, repo, *pats, **opts):
2532 """show how files match on given patterns"""
2532 """show how files match on given patterns"""
2533 m = scmutil.match(repo[None], pats, opts)
2533 m = scmutil.match(repo[None], pats, opts)
2534 items = list(repo.walk(m))
2534 items = list(repo.walk(m))
2535 if not items:
2535 if not items:
2536 return
2536 return
2537 f = lambda fn: fn
2537 f = lambda fn: fn
2538 if ui.configbool('ui', 'slash') and os.sep != '/':
2538 if ui.configbool('ui', 'slash') and os.sep != '/':
2539 f = lambda fn: util.normpath(fn)
2539 f = lambda fn: util.normpath(fn)
2540 fmt = 'f %%-%ds %%-%ds %%s' % (
2540 fmt = 'f %%-%ds %%-%ds %%s' % (
2541 max([len(abs) for abs in items]),
2541 max([len(abs) for abs in items]),
2542 max([len(m.rel(abs)) for abs in items]))
2542 max([len(m.rel(abs)) for abs in items]))
2543 for abs in items:
2543 for abs in items:
2544 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2544 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2545 ui.write("%s\n" % line.rstrip())
2545 ui.write("%s\n" % line.rstrip())
2546
2546
2547 @command('debugwireargs',
2547 @command('debugwireargs',
2548 [('', 'three', '', 'three'),
2548 [('', 'three', '', 'three'),
2549 ('', 'four', '', 'four'),
2549 ('', 'four', '', 'four'),
2550 ('', 'five', '', 'five'),
2550 ('', 'five', '', 'five'),
2551 ] + remoteopts,
2551 ] + remoteopts,
2552 _('REPO [OPTIONS]... [ONE [TWO]]'))
2552 _('REPO [OPTIONS]... [ONE [TWO]]'))
2553 def debugwireargs(ui, repopath, *vals, **opts):
2553 def debugwireargs(ui, repopath, *vals, **opts):
2554 repo = hg.peer(ui, opts, repopath)
2554 repo = hg.peer(ui, opts, repopath)
2555 for opt in remoteopts:
2555 for opt in remoteopts:
2556 del opts[opt[1]]
2556 del opts[opt[1]]
2557 args = {}
2557 args = {}
2558 for k, v in opts.iteritems():
2558 for k, v in opts.iteritems():
2559 if v:
2559 if v:
2560 args[k] = v
2560 args[k] = v
2561 # run twice to check that we don't mess up the stream for the next command
2561 # run twice to check that we don't mess up the stream for the next command
2562 res1 = repo.debugwireargs(*vals, **args)
2562 res1 = repo.debugwireargs(*vals, **args)
2563 res2 = repo.debugwireargs(*vals, **args)
2563 res2 = repo.debugwireargs(*vals, **args)
2564 ui.write("%s\n" % res1)
2564 ui.write("%s\n" % res1)
2565 if res1 != res2:
2565 if res1 != res2:
2566 ui.warn("%s\n" % res2)
2566 ui.warn("%s\n" % res2)
2567
2567
2568 @command('^diff',
2568 @command('^diff',
2569 [('r', 'rev', [], _('revision'), _('REV')),
2569 [('r', 'rev', [], _('revision'), _('REV')),
2570 ('c', 'change', '', _('change made by revision'), _('REV'))
2570 ('c', 'change', '', _('change made by revision'), _('REV'))
2571 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2571 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2572 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2572 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2573 def diff(ui, repo, *pats, **opts):
2573 def diff(ui, repo, *pats, **opts):
2574 """diff repository (or selected files)
2574 """diff repository (or selected files)
2575
2575
2576 Show differences between revisions for the specified files.
2576 Show differences between revisions for the specified files.
2577
2577
2578 Differences between files are shown using the unified diff format.
2578 Differences between files are shown using the unified diff format.
2579
2579
2580 .. note::
2580 .. note::
2581 diff may generate unexpected results for merges, as it will
2581 diff may generate unexpected results for merges, as it will
2582 default to comparing against the working directory's first
2582 default to comparing against the working directory's first
2583 parent changeset if no revisions are specified.
2583 parent changeset if no revisions are specified.
2584
2584
2585 When two revision arguments are given, then changes are shown
2585 When two revision arguments are given, then changes are shown
2586 between those revisions. If only one revision is specified then
2586 between those revisions. If only one revision is specified then
2587 that revision is compared to the working directory, and, when no
2587 that revision is compared to the working directory, and, when no
2588 revisions are specified, the working directory files are compared
2588 revisions are specified, the working directory files are compared
2589 to its parent.
2589 to its parent.
2590
2590
2591 Alternatively you can specify -c/--change with a revision to see
2591 Alternatively you can specify -c/--change with a revision to see
2592 the changes in that changeset relative to its first parent.
2592 the changes in that changeset relative to its first parent.
2593
2593
2594 Without the -a/--text option, diff will avoid generating diffs of
2594 Without the -a/--text option, diff will avoid generating diffs of
2595 files it detects as binary. With -a, diff will generate a diff
2595 files it detects as binary. With -a, diff will generate a diff
2596 anyway, probably with undesirable results.
2596 anyway, probably with undesirable results.
2597
2597
2598 Use the -g/--git option to generate diffs in the git extended diff
2598 Use the -g/--git option to generate diffs in the git extended diff
2599 format. For more information, read :hg:`help diffs`.
2599 format. For more information, read :hg:`help diffs`.
2600
2600
2601 .. container:: verbose
2601 .. container:: verbose
2602
2602
2603 Examples:
2603 Examples:
2604
2604
2605 - compare a file in the current working directory to its parent::
2605 - compare a file in the current working directory to its parent::
2606
2606
2607 hg diff foo.c
2607 hg diff foo.c
2608
2608
2609 - compare two historical versions of a directory, with rename info::
2609 - compare two historical versions of a directory, with rename info::
2610
2610
2611 hg diff --git -r 1.0:1.2 lib/
2611 hg diff --git -r 1.0:1.2 lib/
2612
2612
2613 - get change stats relative to the last change on some date::
2613 - get change stats relative to the last change on some date::
2614
2614
2615 hg diff --stat -r "date('may 2')"
2615 hg diff --stat -r "date('may 2')"
2616
2616
2617 - diff all newly-added files that contain a keyword::
2617 - diff all newly-added files that contain a keyword::
2618
2618
2619 hg diff "set:added() and grep(GNU)"
2619 hg diff "set:added() and grep(GNU)"
2620
2620
2621 - compare a revision and its parents::
2621 - compare a revision and its parents::
2622
2622
2623 hg diff -c 9353 # compare against first parent
2623 hg diff -c 9353 # compare against first parent
2624 hg diff -r 9353^:9353 # same using revset syntax
2624 hg diff -r 9353^:9353 # same using revset syntax
2625 hg diff -r 9353^2:9353 # compare against the second parent
2625 hg diff -r 9353^2:9353 # compare against the second parent
2626
2626
2627 Returns 0 on success.
2627 Returns 0 on success.
2628 """
2628 """
2629
2629
2630 revs = opts.get('rev')
2630 revs = opts.get('rev')
2631 change = opts.get('change')
2631 change = opts.get('change')
2632 stat = opts.get('stat')
2632 stat = opts.get('stat')
2633 reverse = opts.get('reverse')
2633 reverse = opts.get('reverse')
2634
2634
2635 if revs and change:
2635 if revs and change:
2636 msg = _('cannot specify --rev and --change at the same time')
2636 msg = _('cannot specify --rev and --change at the same time')
2637 raise util.Abort(msg)
2637 raise util.Abort(msg)
2638 elif change:
2638 elif change:
2639 node2 = scmutil.revsingle(repo, change, None).node()
2639 node2 = scmutil.revsingle(repo, change, None).node()
2640 node1 = repo[node2].p1().node()
2640 node1 = repo[node2].p1().node()
2641 else:
2641 else:
2642 node1, node2 = scmutil.revpair(repo, revs)
2642 node1, node2 = scmutil.revpair(repo, revs)
2643
2643
2644 if reverse:
2644 if reverse:
2645 node1, node2 = node2, node1
2645 node1, node2 = node2, node1
2646
2646
2647 diffopts = patch.diffopts(ui, opts)
2647 diffopts = patch.diffopts(ui, opts)
2648 m = scmutil.match(repo[node2], pats, opts)
2648 m = scmutil.match(repo[node2], pats, opts)
2649 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2649 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2650 listsubrepos=opts.get('subrepos'))
2650 listsubrepos=opts.get('subrepos'))
2651
2651
2652 @command('^export',
2652 @command('^export',
2653 [('o', 'output', '',
2653 [('o', 'output', '',
2654 _('print output to file with formatted name'), _('FORMAT')),
2654 _('print output to file with formatted name'), _('FORMAT')),
2655 ('', 'switch-parent', None, _('diff against the second parent')),
2655 ('', 'switch-parent', None, _('diff against the second parent')),
2656 ('r', 'rev', [], _('revisions to export'), _('REV')),
2656 ('r', 'rev', [], _('revisions to export'), _('REV')),
2657 ] + diffopts,
2657 ] + diffopts,
2658 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2658 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2659 def export(ui, repo, *changesets, **opts):
2659 def export(ui, repo, *changesets, **opts):
2660 """dump the header and diffs for one or more changesets
2660 """dump the header and diffs for one or more changesets
2661
2661
2662 Print the changeset header and diffs for one or more revisions.
2662 Print the changeset header and diffs for one or more revisions.
2663
2663
2664 The information shown in the changeset header is: author, date,
2664 The information shown in the changeset header is: author, date,
2665 branch name (if non-default), changeset hash, parent(s) and commit
2665 branch name (if non-default), changeset hash, parent(s) and commit
2666 comment.
2666 comment.
2667
2667
2668 .. note::
2668 .. note::
2669 export may generate unexpected diff output for merge
2669 export may generate unexpected diff output for merge
2670 changesets, as it will compare the merge changeset against its
2670 changesets, as it will compare the merge changeset against its
2671 first parent only.
2671 first parent only.
2672
2672
2673 Output may be to a file, in which case the name of the file is
2673 Output may be to a file, in which case the name of the file is
2674 given using a format string. The formatting rules are as follows:
2674 given using a format string. The formatting rules are as follows:
2675
2675
2676 :``%%``: literal "%" character
2676 :``%%``: literal "%" character
2677 :``%H``: changeset hash (40 hexadecimal digits)
2677 :``%H``: changeset hash (40 hexadecimal digits)
2678 :``%N``: number of patches being generated
2678 :``%N``: number of patches being generated
2679 :``%R``: changeset revision number
2679 :``%R``: changeset revision number
2680 :``%b``: basename of the exporting repository
2680 :``%b``: basename of the exporting repository
2681 :``%h``: short-form changeset hash (12 hexadecimal digits)
2681 :``%h``: short-form changeset hash (12 hexadecimal digits)
2682 :``%m``: first line of the commit message (only alphanumeric characters)
2682 :``%m``: first line of the commit message (only alphanumeric characters)
2683 :``%n``: zero-padded sequence number, starting at 1
2683 :``%n``: zero-padded sequence number, starting at 1
2684 :``%r``: zero-padded changeset revision number
2684 :``%r``: zero-padded changeset revision number
2685
2685
2686 Without the -a/--text option, export will avoid generating diffs
2686 Without the -a/--text option, export will avoid generating diffs
2687 of files it detects as binary. With -a, export will generate a
2687 of files it detects as binary. With -a, export will generate a
2688 diff anyway, probably with undesirable results.
2688 diff anyway, probably with undesirable results.
2689
2689
2690 Use the -g/--git option to generate diffs in the git extended diff
2690 Use the -g/--git option to generate diffs in the git extended diff
2691 format. See :hg:`help diffs` for more information.
2691 format. See :hg:`help diffs` for more information.
2692
2692
2693 With the --switch-parent option, the diff will be against the
2693 With the --switch-parent option, the diff will be against the
2694 second parent. It can be useful to review a merge.
2694 second parent. It can be useful to review a merge.
2695
2695
2696 .. container:: verbose
2696 .. container:: verbose
2697
2697
2698 Examples:
2698 Examples:
2699
2699
2700 - use export and import to transplant a bugfix to the current
2700 - use export and import to transplant a bugfix to the current
2701 branch::
2701 branch::
2702
2702
2703 hg export -r 9353 | hg import -
2703 hg export -r 9353 | hg import -
2704
2704
2705 - export all the changesets between two revisions to a file with
2705 - export all the changesets between two revisions to a file with
2706 rename information::
2706 rename information::
2707
2707
2708 hg export --git -r 123:150 > changes.txt
2708 hg export --git -r 123:150 > changes.txt
2709
2709
2710 - split outgoing changes into a series of patches with
2710 - split outgoing changes into a series of patches with
2711 descriptive names::
2711 descriptive names::
2712
2712
2713 hg export -r "outgoing()" -o "%n-%m.patch"
2713 hg export -r "outgoing()" -o "%n-%m.patch"
2714
2714
2715 Returns 0 on success.
2715 Returns 0 on success.
2716 """
2716 """
2717 changesets += tuple(opts.get('rev', []))
2717 changesets += tuple(opts.get('rev', []))
2718 revs = scmutil.revrange(repo, changesets)
2718 revs = scmutil.revrange(repo, changesets)
2719 if not revs:
2719 if not revs:
2720 raise util.Abort(_("export requires at least one changeset"))
2720 raise util.Abort(_("export requires at least one changeset"))
2721 if len(revs) > 1:
2721 if len(revs) > 1:
2722 ui.note(_('exporting patches:\n'))
2722 ui.note(_('exporting patches:\n'))
2723 else:
2723 else:
2724 ui.note(_('exporting patch:\n'))
2724 ui.note(_('exporting patch:\n'))
2725 cmdutil.export(repo, revs, template=opts.get('output'),
2725 cmdutil.export(repo, revs, template=opts.get('output'),
2726 switch_parent=opts.get('switch_parent'),
2726 switch_parent=opts.get('switch_parent'),
2727 opts=patch.diffopts(ui, opts))
2727 opts=patch.diffopts(ui, opts))
2728
2728
2729 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2729 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2730 def forget(ui, repo, *pats, **opts):
2730 def forget(ui, repo, *pats, **opts):
2731 """forget the specified files on the next commit
2731 """forget the specified files on the next commit
2732
2732
2733 Mark the specified files so they will no longer be tracked
2733 Mark the specified files so they will no longer be tracked
2734 after the next commit.
2734 after the next commit.
2735
2735
2736 This only removes files from the current branch, not from the
2736 This only removes files from the current branch, not from the
2737 entire project history, and it does not delete them from the
2737 entire project history, and it does not delete them from the
2738 working directory.
2738 working directory.
2739
2739
2740 To undo a forget before the next commit, see :hg:`add`.
2740 To undo a forget before the next commit, see :hg:`add`.
2741
2741
2742 .. container:: verbose
2742 .. container:: verbose
2743
2743
2744 Examples:
2744 Examples:
2745
2745
2746 - forget newly-added binary files::
2746 - forget newly-added binary files::
2747
2747
2748 hg forget "set:added() and binary()"
2748 hg forget "set:added() and binary()"
2749
2749
2750 - forget files that would be excluded by .hgignore::
2750 - forget files that would be excluded by .hgignore::
2751
2751
2752 hg forget "set:hgignore()"
2752 hg forget "set:hgignore()"
2753
2753
2754 Returns 0 on success.
2754 Returns 0 on success.
2755 """
2755 """
2756
2756
2757 if not pats:
2757 if not pats:
2758 raise util.Abort(_('no files specified'))
2758 raise util.Abort(_('no files specified'))
2759
2759
2760 m = scmutil.match(repo[None], pats, opts)
2760 m = scmutil.match(repo[None], pats, opts)
2761 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2761 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2762 return rejected and 1 or 0
2762 return rejected and 1 or 0
2763
2763
2764 @command(
2764 @command(
2765 'graft',
2765 'graft',
2766 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2766 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2767 ('c', 'continue', False, _('resume interrupted graft')),
2767 ('c', 'continue', False, _('resume interrupted graft')),
2768 ('e', 'edit', False, _('invoke editor on commit messages')),
2768 ('e', 'edit', False, _('invoke editor on commit messages')),
2769 ('', 'log', None, _('append graft info to log message')),
2769 ('', 'log', None, _('append graft info to log message')),
2770 ('D', 'currentdate', False,
2770 ('D', 'currentdate', False,
2771 _('record the current date as commit date')),
2771 _('record the current date as commit date')),
2772 ('U', 'currentuser', False,
2772 ('U', 'currentuser', False,
2773 _('record the current user as committer'), _('DATE'))]
2773 _('record the current user as committer'), _('DATE'))]
2774 + commitopts2 + mergetoolopts + dryrunopts,
2774 + commitopts2 + mergetoolopts + dryrunopts,
2775 _('[OPTION]... [-r] REV...'))
2775 _('[OPTION]... [-r] REV...'))
2776 def graft(ui, repo, *revs, **opts):
2776 def graft(ui, repo, *revs, **opts):
2777 '''copy changes from other branches onto the current branch
2777 '''copy changes from other branches onto the current branch
2778
2778
2779 This command uses Mercurial's merge logic to copy individual
2779 This command uses Mercurial's merge logic to copy individual
2780 changes from other branches without merging branches in the
2780 changes from other branches without merging branches in the
2781 history graph. This is sometimes known as 'backporting' or
2781 history graph. This is sometimes known as 'backporting' or
2782 'cherry-picking'. By default, graft will copy user, date, and
2782 'cherry-picking'. By default, graft will copy user, date, and
2783 description from the source changesets.
2783 description from the source changesets.
2784
2784
2785 Changesets that are ancestors of the current revision, that have
2785 Changesets that are ancestors of the current revision, that have
2786 already been grafted, or that are merges will be skipped.
2786 already been grafted, or that are merges will be skipped.
2787
2787
2788 If --log is specified, log messages will have a comment appended
2788 If --log is specified, log messages will have a comment appended
2789 of the form::
2789 of the form::
2790
2790
2791 (grafted from CHANGESETHASH)
2791 (grafted from CHANGESETHASH)
2792
2792
2793 If a graft merge results in conflicts, the graft process is
2793 If a graft merge results in conflicts, the graft process is
2794 interrupted so that the current merge can be manually resolved.
2794 interrupted so that the current merge can be manually resolved.
2795 Once all conflicts are addressed, the graft process can be
2795 Once all conflicts are addressed, the graft process can be
2796 continued with the -c/--continue option.
2796 continued with the -c/--continue option.
2797
2797
2798 .. note::
2798 .. note::
2799 The -c/--continue option does not reapply earlier options.
2799 The -c/--continue option does not reapply earlier options.
2800
2800
2801 .. container:: verbose
2801 .. container:: verbose
2802
2802
2803 Examples:
2803 Examples:
2804
2804
2805 - copy a single change to the stable branch and edit its description::
2805 - copy a single change to the stable branch and edit its description::
2806
2806
2807 hg update stable
2807 hg update stable
2808 hg graft --edit 9393
2808 hg graft --edit 9393
2809
2809
2810 - graft a range of changesets with one exception, updating dates::
2810 - graft a range of changesets with one exception, updating dates::
2811
2811
2812 hg graft -D "2085::2093 and not 2091"
2812 hg graft -D "2085::2093 and not 2091"
2813
2813
2814 - continue a graft after resolving conflicts::
2814 - continue a graft after resolving conflicts::
2815
2815
2816 hg graft -c
2816 hg graft -c
2817
2817
2818 - show the source of a grafted changeset::
2818 - show the source of a grafted changeset::
2819
2819
2820 hg log --debug -r tip
2820 hg log --debug -r tip
2821
2821
2822 Returns 0 on successful completion.
2822 Returns 0 on successful completion.
2823 '''
2823 '''
2824
2824
2825 revs = list(revs)
2825 revs = list(revs)
2826 revs.extend(opts['rev'])
2826 revs.extend(opts['rev'])
2827
2827
2828 if not opts.get('user') and opts.get('currentuser'):
2828 if not opts.get('user') and opts.get('currentuser'):
2829 opts['user'] = ui.username()
2829 opts['user'] = ui.username()
2830 if not opts.get('date') and opts.get('currentdate'):
2830 if not opts.get('date') and opts.get('currentdate'):
2831 opts['date'] = "%d %d" % util.makedate()
2831 opts['date'] = "%d %d" % util.makedate()
2832
2832
2833 editor = None
2833 editor = None
2834 if opts.get('edit'):
2834 if opts.get('edit'):
2835 editor = cmdutil.commitforceeditor
2835 editor = cmdutil.commitforceeditor
2836
2836
2837 cont = False
2837 cont = False
2838 if opts['continue']:
2838 if opts['continue']:
2839 cont = True
2839 cont = True
2840 if revs:
2840 if revs:
2841 raise util.Abort(_("can't specify --continue and revisions"))
2841 raise util.Abort(_("can't specify --continue and revisions"))
2842 # read in unfinished revisions
2842 # read in unfinished revisions
2843 try:
2843 try:
2844 nodes = repo.opener.read('graftstate').splitlines()
2844 nodes = repo.opener.read('graftstate').splitlines()
2845 revs = [repo[node].rev() for node in nodes]
2845 revs = [repo[node].rev() for node in nodes]
2846 except IOError, inst:
2846 except IOError, inst:
2847 if inst.errno != errno.ENOENT:
2847 if inst.errno != errno.ENOENT:
2848 raise
2848 raise
2849 raise util.Abort(_("no graft state found, can't continue"))
2849 raise util.Abort(_("no graft state found, can't continue"))
2850 else:
2850 else:
2851 cmdutil.bailifchanged(repo)
2851 cmdutil.bailifchanged(repo)
2852 if not revs:
2852 if not revs:
2853 raise util.Abort(_('no revisions specified'))
2853 raise util.Abort(_('no revisions specified'))
2854 revs = scmutil.revrange(repo, revs)
2854 revs = scmutil.revrange(repo, revs)
2855
2855
2856 # check for merges
2856 # check for merges
2857 for rev in repo.revs('%ld and merge()', revs):
2857 for rev in repo.revs('%ld and merge()', revs):
2858 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2858 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2859 revs.remove(rev)
2859 revs.remove(rev)
2860 if not revs:
2860 if not revs:
2861 return -1
2861 return -1
2862
2862
2863 # check for ancestors of dest branch
2863 # check for ancestors of dest branch
2864 for rev in repo.revs('::. and %ld', revs):
2864 for rev in repo.revs('::. and %ld', revs):
2865 ui.warn(_('skipping ancestor revision %s\n') % rev)
2865 ui.warn(_('skipping ancestor revision %s\n') % rev)
2866 revs.remove(rev)
2866 revs.remove(rev)
2867 if not revs:
2867 if not revs:
2868 return -1
2868 return -1
2869
2869
2870 # analyze revs for earlier grafts
2870 # analyze revs for earlier grafts
2871 ids = {}
2871 ids = {}
2872 for ctx in repo.set("%ld", revs):
2872 for ctx in repo.set("%ld", revs):
2873 ids[ctx.hex()] = ctx.rev()
2873 ids[ctx.hex()] = ctx.rev()
2874 n = ctx.extra().get('source')
2874 n = ctx.extra().get('source')
2875 if n:
2875 if n:
2876 ids[n] = ctx.rev()
2876 ids[n] = ctx.rev()
2877
2877
2878 # check ancestors for earlier grafts
2878 # check ancestors for earlier grafts
2879 ui.debug('scanning for duplicate grafts\n')
2879 ui.debug('scanning for duplicate grafts\n')
2880 for ctx in repo.set("::. - ::%ld", revs):
2880 for ctx in repo.set("::. - ::%ld", revs):
2881 n = ctx.extra().get('source')
2881 n = ctx.extra().get('source')
2882 if n in ids:
2882 if n in ids:
2883 r = repo[n].rev()
2883 r = repo[n].rev()
2884 if r in revs:
2884 if r in revs:
2885 ui.warn(_('skipping already grafted revision %s\n') % r)
2885 ui.warn(_('skipping already grafted revision %s\n') % r)
2886 revs.remove(r)
2886 revs.remove(r)
2887 elif ids[n] in revs:
2887 elif ids[n] in revs:
2888 ui.warn(_('skipping already grafted revision %s '
2888 ui.warn(_('skipping already grafted revision %s '
2889 '(same origin %d)\n') % (ids[n], r))
2889 '(same origin %d)\n') % (ids[n], r))
2890 revs.remove(ids[n])
2890 revs.remove(ids[n])
2891 elif ctx.hex() in ids:
2891 elif ctx.hex() in ids:
2892 r = ids[ctx.hex()]
2892 r = ids[ctx.hex()]
2893 ui.warn(_('skipping already grafted revision %s '
2893 ui.warn(_('skipping already grafted revision %s '
2894 '(was grafted from %d)\n') % (r, ctx.rev()))
2894 '(was grafted from %d)\n') % (r, ctx.rev()))
2895 revs.remove(r)
2895 revs.remove(r)
2896 if not revs:
2896 if not revs:
2897 return -1
2897 return -1
2898
2898
2899 wlock = repo.wlock()
2899 wlock = repo.wlock()
2900 try:
2900 try:
2901 current = repo['.']
2901 current = repo['.']
2902 for pos, ctx in enumerate(repo.set("%ld", revs)):
2902 for pos, ctx in enumerate(repo.set("%ld", revs)):
2903
2903
2904 ui.status(_('grafting revision %s\n') % ctx.rev())
2904 ui.status(_('grafting revision %s\n') % ctx.rev())
2905 if opts.get('dry_run'):
2905 if opts.get('dry_run'):
2906 continue
2906 continue
2907
2907
2908 source = ctx.extra().get('source')
2908 source = ctx.extra().get('source')
2909 if not source:
2909 if not source:
2910 source = ctx.hex()
2910 source = ctx.hex()
2911 extra = {'source': source}
2911 extra = {'source': source}
2912 user = ctx.user()
2912 user = ctx.user()
2913 if opts.get('user'):
2913 if opts.get('user'):
2914 user = opts['user']
2914 user = opts['user']
2915 date = ctx.date()
2915 date = ctx.date()
2916 if opts.get('date'):
2916 if opts.get('date'):
2917 date = opts['date']
2917 date = opts['date']
2918 message = ctx.description()
2918 message = ctx.description()
2919 if opts.get('log'):
2919 if opts.get('log'):
2920 message += '\n(grafted from %s)' % ctx.hex()
2920 message += '\n(grafted from %s)' % ctx.hex()
2921
2921
2922 # we don't merge the first commit when continuing
2922 # we don't merge the first commit when continuing
2923 if not cont:
2923 if not cont:
2924 # perform the graft merge with p1(rev) as 'ancestor'
2924 # perform the graft merge with p1(rev) as 'ancestor'
2925 try:
2925 try:
2926 # ui.forcemerge is an internal variable, do not document
2926 # ui.forcemerge is an internal variable, do not document
2927 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2927 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2928 stats = mergemod.update(repo, ctx.node(), True, True, False,
2928 stats = mergemod.update(repo, ctx.node(), True, True, False,
2929 ctx.p1().node())
2929 ctx.p1().node())
2930 finally:
2930 finally:
2931 repo.ui.setconfig('ui', 'forcemerge', '')
2931 repo.ui.setconfig('ui', 'forcemerge', '')
2932 # report any conflicts
2932 # report any conflicts
2933 if stats and stats[3] > 0:
2933 if stats and stats[3] > 0:
2934 # write out state for --continue
2934 # write out state for --continue
2935 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2935 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2936 repo.opener.write('graftstate', ''.join(nodelines))
2936 repo.opener.write('graftstate', ''.join(nodelines))
2937 raise util.Abort(
2937 raise util.Abort(
2938 _("unresolved conflicts, can't continue"),
2938 _("unresolved conflicts, can't continue"),
2939 hint=_('use hg resolve and hg graft --continue'))
2939 hint=_('use hg resolve and hg graft --continue'))
2940 else:
2940 else:
2941 cont = False
2941 cont = False
2942
2942
2943 # drop the second merge parent
2943 # drop the second merge parent
2944 repo.setparents(current.node(), nullid)
2944 repo.setparents(current.node(), nullid)
2945 repo.dirstate.write()
2945 repo.dirstate.write()
2946 # fix up dirstate for copies and renames
2946 # fix up dirstate for copies and renames
2947 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2947 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2948
2948
2949 # commit
2949 # commit
2950 node = repo.commit(text=message, user=user,
2950 node = repo.commit(text=message, user=user,
2951 date=date, extra=extra, editor=editor)
2951 date=date, extra=extra, editor=editor)
2952 if node is None:
2952 if node is None:
2953 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2953 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2954 else:
2954 else:
2955 current = repo[node]
2955 current = repo[node]
2956 finally:
2956 finally:
2957 wlock.release()
2957 wlock.release()
2958
2958
2959 # remove state when we complete successfully
2959 # remove state when we complete successfully
2960 if not opts.get('dry_run'):
2960 if not opts.get('dry_run'):
2961 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2961 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2962
2962
2963 return 0
2963 return 0
2964
2964
2965 @command('grep',
2965 @command('grep',
2966 [('0', 'print0', None, _('end fields with NUL')),
2966 [('0', 'print0', None, _('end fields with NUL')),
2967 ('', 'all', None, _('print all revisions that match')),
2967 ('', 'all', None, _('print all revisions that match')),
2968 ('a', 'text', None, _('treat all files as text')),
2968 ('a', 'text', None, _('treat all files as text')),
2969 ('f', 'follow', None,
2969 ('f', 'follow', None,
2970 _('follow changeset history,'
2970 _('follow changeset history,'
2971 ' or file history across copies and renames')),
2971 ' or file history across copies and renames')),
2972 ('i', 'ignore-case', None, _('ignore case when matching')),
2972 ('i', 'ignore-case', None, _('ignore case when matching')),
2973 ('l', 'files-with-matches', None,
2973 ('l', 'files-with-matches', None,
2974 _('print only filenames and revisions that match')),
2974 _('print only filenames and revisions that match')),
2975 ('n', 'line-number', None, _('print matching line numbers')),
2975 ('n', 'line-number', None, _('print matching line numbers')),
2976 ('r', 'rev', [],
2976 ('r', 'rev', [],
2977 _('only search files changed within revision range'), _('REV')),
2977 _('only search files changed within revision range'), _('REV')),
2978 ('u', 'user', None, _('list the author (long with -v)')),
2978 ('u', 'user', None, _('list the author (long with -v)')),
2979 ('d', 'date', None, _('list the date (short with -q)')),
2979 ('d', 'date', None, _('list the date (short with -q)')),
2980 ] + walkopts,
2980 ] + walkopts,
2981 _('[OPTION]... PATTERN [FILE]...'))
2981 _('[OPTION]... PATTERN [FILE]...'))
2982 def grep(ui, repo, pattern, *pats, **opts):
2982 def grep(ui, repo, pattern, *pats, **opts):
2983 """search for a pattern in specified files and revisions
2983 """search for a pattern in specified files and revisions
2984
2984
2985 Search revisions of files for a regular expression.
2985 Search revisions of files for a regular expression.
2986
2986
2987 This command behaves differently than Unix grep. It only accepts
2987 This command behaves differently than Unix grep. It only accepts
2988 Python/Perl regexps. It searches repository history, not the
2988 Python/Perl regexps. It searches repository history, not the
2989 working directory. It always prints the revision number in which a
2989 working directory. It always prints the revision number in which a
2990 match appears.
2990 match appears.
2991
2991
2992 By default, grep only prints output for the first revision of a
2992 By default, grep only prints output for the first revision of a
2993 file in which it finds a match. To get it to print every revision
2993 file in which it finds a match. To get it to print every revision
2994 that contains a change in match status ("-" for a match that
2994 that contains a change in match status ("-" for a match that
2995 becomes a non-match, or "+" for a non-match that becomes a match),
2995 becomes a non-match, or "+" for a non-match that becomes a match),
2996 use the --all flag.
2996 use the --all flag.
2997
2997
2998 Returns 0 if a match is found, 1 otherwise.
2998 Returns 0 if a match is found, 1 otherwise.
2999 """
2999 """
3000 reflags = re.M
3000 reflags = re.M
3001 if opts.get('ignore_case'):
3001 if opts.get('ignore_case'):
3002 reflags |= re.I
3002 reflags |= re.I
3003 try:
3003 try:
3004 regexp = re.compile(pattern, reflags)
3004 regexp = re.compile(pattern, reflags)
3005 except re.error, inst:
3005 except re.error, inst:
3006 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3006 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3007 return 1
3007 return 1
3008 sep, eol = ':', '\n'
3008 sep, eol = ':', '\n'
3009 if opts.get('print0'):
3009 if opts.get('print0'):
3010 sep = eol = '\0'
3010 sep = eol = '\0'
3011
3011
3012 getfile = util.lrucachefunc(repo.file)
3012 getfile = util.lrucachefunc(repo.file)
3013
3013
3014 def matchlines(body):
3014 def matchlines(body):
3015 begin = 0
3015 begin = 0
3016 linenum = 0
3016 linenum = 0
3017 while begin < len(body):
3017 while begin < len(body):
3018 match = regexp.search(body, begin)
3018 match = regexp.search(body, begin)
3019 if not match:
3019 if not match:
3020 break
3020 break
3021 mstart, mend = match.span()
3021 mstart, mend = match.span()
3022 linenum += body.count('\n', begin, mstart) + 1
3022 linenum += body.count('\n', begin, mstart) + 1
3023 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3023 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3024 begin = body.find('\n', mend) + 1 or len(body) + 1
3024 begin = body.find('\n', mend) + 1 or len(body) + 1
3025 lend = begin - 1
3025 lend = begin - 1
3026 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3026 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3027
3027
3028 class linestate(object):
3028 class linestate(object):
3029 def __init__(self, line, linenum, colstart, colend):
3029 def __init__(self, line, linenum, colstart, colend):
3030 self.line = line
3030 self.line = line
3031 self.linenum = linenum
3031 self.linenum = linenum
3032 self.colstart = colstart
3032 self.colstart = colstart
3033 self.colend = colend
3033 self.colend = colend
3034
3034
3035 def __hash__(self):
3035 def __hash__(self):
3036 return hash((self.linenum, self.line))
3036 return hash((self.linenum, self.line))
3037
3037
3038 def __eq__(self, other):
3038 def __eq__(self, other):
3039 return self.line == other.line
3039 return self.line == other.line
3040
3040
3041 matches = {}
3041 matches = {}
3042 copies = {}
3042 copies = {}
3043 def grepbody(fn, rev, body):
3043 def grepbody(fn, rev, body):
3044 matches[rev].setdefault(fn, [])
3044 matches[rev].setdefault(fn, [])
3045 m = matches[rev][fn]
3045 m = matches[rev][fn]
3046 for lnum, cstart, cend, line in matchlines(body):
3046 for lnum, cstart, cend, line in matchlines(body):
3047 s = linestate(line, lnum, cstart, cend)
3047 s = linestate(line, lnum, cstart, cend)
3048 m.append(s)
3048 m.append(s)
3049
3049
3050 def difflinestates(a, b):
3050 def difflinestates(a, b):
3051 sm = difflib.SequenceMatcher(None, a, b)
3051 sm = difflib.SequenceMatcher(None, a, b)
3052 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3052 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3053 if tag == 'insert':
3053 if tag == 'insert':
3054 for i in xrange(blo, bhi):
3054 for i in xrange(blo, bhi):
3055 yield ('+', b[i])
3055 yield ('+', b[i])
3056 elif tag == 'delete':
3056 elif tag == 'delete':
3057 for i in xrange(alo, ahi):
3057 for i in xrange(alo, ahi):
3058 yield ('-', a[i])
3058 yield ('-', a[i])
3059 elif tag == 'replace':
3059 elif tag == 'replace':
3060 for i in xrange(alo, ahi):
3060 for i in xrange(alo, ahi):
3061 yield ('-', a[i])
3061 yield ('-', a[i])
3062 for i in xrange(blo, bhi):
3062 for i in xrange(blo, bhi):
3063 yield ('+', b[i])
3063 yield ('+', b[i])
3064
3064
3065 def display(fn, ctx, pstates, states):
3065 def display(fn, ctx, pstates, states):
3066 rev = ctx.rev()
3066 rev = ctx.rev()
3067 datefunc = ui.quiet and util.shortdate or util.datestr
3067 datefunc = ui.quiet and util.shortdate or util.datestr
3068 found = False
3068 found = False
3069 filerevmatches = {}
3069 filerevmatches = {}
3070 def binary():
3070 def binary():
3071 flog = getfile(fn)
3071 flog = getfile(fn)
3072 return util.binary(flog.read(ctx.filenode(fn)))
3072 return util.binary(flog.read(ctx.filenode(fn)))
3073
3073
3074 if opts.get('all'):
3074 if opts.get('all'):
3075 iter = difflinestates(pstates, states)
3075 iter = difflinestates(pstates, states)
3076 else:
3076 else:
3077 iter = [('', l) for l in states]
3077 iter = [('', l) for l in states]
3078 for change, l in iter:
3078 for change, l in iter:
3079 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3079 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3080 before, match, after = None, None, None
3080 before, match, after = None, None, None
3081
3081
3082 if opts.get('line_number'):
3082 if opts.get('line_number'):
3083 cols.append((str(l.linenum), 'grep.linenumber'))
3083 cols.append((str(l.linenum), 'grep.linenumber'))
3084 if opts.get('all'):
3084 if opts.get('all'):
3085 cols.append((change, 'grep.change'))
3085 cols.append((change, 'grep.change'))
3086 if opts.get('user'):
3086 if opts.get('user'):
3087 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3087 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3088 if opts.get('date'):
3088 if opts.get('date'):
3089 cols.append((datefunc(ctx.date()), 'grep.date'))
3089 cols.append((datefunc(ctx.date()), 'grep.date'))
3090 if opts.get('files_with_matches'):
3090 if opts.get('files_with_matches'):
3091 c = (fn, rev)
3091 c = (fn, rev)
3092 if c in filerevmatches:
3092 if c in filerevmatches:
3093 continue
3093 continue
3094 filerevmatches[c] = 1
3094 filerevmatches[c] = 1
3095 else:
3095 else:
3096 before = l.line[:l.colstart]
3096 before = l.line[:l.colstart]
3097 match = l.line[l.colstart:l.colend]
3097 match = l.line[l.colstart:l.colend]
3098 after = l.line[l.colend:]
3098 after = l.line[l.colend:]
3099 for col, label in cols[:-1]:
3099 for col, label in cols[:-1]:
3100 ui.write(col, label=label)
3100 ui.write(col, label=label)
3101 ui.write(sep, label='grep.sep')
3101 ui.write(sep, label='grep.sep')
3102 ui.write(cols[-1][0], label=cols[-1][1])
3102 ui.write(cols[-1][0], label=cols[-1][1])
3103 if before is not None:
3103 if before is not None:
3104 ui.write(sep, label='grep.sep')
3104 ui.write(sep, label='grep.sep')
3105 if not opts.get('text') and binary():
3105 if not opts.get('text') and binary():
3106 ui.write(" Binary file matches")
3106 ui.write(" Binary file matches")
3107 else:
3107 else:
3108 ui.write(before)
3108 ui.write(before)
3109 ui.write(match, label='grep.match')
3109 ui.write(match, label='grep.match')
3110 ui.write(after)
3110 ui.write(after)
3111 ui.write(eol)
3111 ui.write(eol)
3112 found = True
3112 found = True
3113 return found
3113 return found
3114
3114
3115 skip = {}
3115 skip = {}
3116 revfiles = {}
3116 revfiles = {}
3117 matchfn = scmutil.match(repo[None], pats, opts)
3117 matchfn = scmutil.match(repo[None], pats, opts)
3118 found = False
3118 found = False
3119 follow = opts.get('follow')
3119 follow = opts.get('follow')
3120
3120
3121 def prep(ctx, fns):
3121 def prep(ctx, fns):
3122 rev = ctx.rev()
3122 rev = ctx.rev()
3123 pctx = ctx.p1()
3123 pctx = ctx.p1()
3124 parent = pctx.rev()
3124 parent = pctx.rev()
3125 matches.setdefault(rev, {})
3125 matches.setdefault(rev, {})
3126 matches.setdefault(parent, {})
3126 matches.setdefault(parent, {})
3127 files = revfiles.setdefault(rev, [])
3127 files = revfiles.setdefault(rev, [])
3128 for fn in fns:
3128 for fn in fns:
3129 flog = getfile(fn)
3129 flog = getfile(fn)
3130 try:
3130 try:
3131 fnode = ctx.filenode(fn)
3131 fnode = ctx.filenode(fn)
3132 except error.LookupError:
3132 except error.LookupError:
3133 continue
3133 continue
3134
3134
3135 copied = flog.renamed(fnode)
3135 copied = flog.renamed(fnode)
3136 copy = follow and copied and copied[0]
3136 copy = follow and copied and copied[0]
3137 if copy:
3137 if copy:
3138 copies.setdefault(rev, {})[fn] = copy
3138 copies.setdefault(rev, {})[fn] = copy
3139 if fn in skip:
3139 if fn in skip:
3140 if copy:
3140 if copy:
3141 skip[copy] = True
3141 skip[copy] = True
3142 continue
3142 continue
3143 files.append(fn)
3143 files.append(fn)
3144
3144
3145 if fn not in matches[rev]:
3145 if fn not in matches[rev]:
3146 grepbody(fn, rev, flog.read(fnode))
3146 grepbody(fn, rev, flog.read(fnode))
3147
3147
3148 pfn = copy or fn
3148 pfn = copy or fn
3149 if pfn not in matches[parent]:
3149 if pfn not in matches[parent]:
3150 try:
3150 try:
3151 fnode = pctx.filenode(pfn)
3151 fnode = pctx.filenode(pfn)
3152 grepbody(pfn, parent, flog.read(fnode))
3152 grepbody(pfn, parent, flog.read(fnode))
3153 except error.LookupError:
3153 except error.LookupError:
3154 pass
3154 pass
3155
3155
3156 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3156 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3157 rev = ctx.rev()
3157 rev = ctx.rev()
3158 parent = ctx.p1().rev()
3158 parent = ctx.p1().rev()
3159 for fn in sorted(revfiles.get(rev, [])):
3159 for fn in sorted(revfiles.get(rev, [])):
3160 states = matches[rev][fn]
3160 states = matches[rev][fn]
3161 copy = copies.get(rev, {}).get(fn)
3161 copy = copies.get(rev, {}).get(fn)
3162 if fn in skip:
3162 if fn in skip:
3163 if copy:
3163 if copy:
3164 skip[copy] = True
3164 skip[copy] = True
3165 continue
3165 continue
3166 pstates = matches.get(parent, {}).get(copy or fn, [])
3166 pstates = matches.get(parent, {}).get(copy or fn, [])
3167 if pstates or states:
3167 if pstates or states:
3168 r = display(fn, ctx, pstates, states)
3168 r = display(fn, ctx, pstates, states)
3169 found = found or r
3169 found = found or r
3170 if r and not opts.get('all'):
3170 if r and not opts.get('all'):
3171 skip[fn] = True
3171 skip[fn] = True
3172 if copy:
3172 if copy:
3173 skip[copy] = True
3173 skip[copy] = True
3174 del matches[rev]
3174 del matches[rev]
3175 del revfiles[rev]
3175 del revfiles[rev]
3176
3176
3177 return not found
3177 return not found
3178
3178
3179 @command('heads',
3179 @command('heads',
3180 [('r', 'rev', '',
3180 [('r', 'rev', '',
3181 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3181 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3182 ('t', 'topo', False, _('show topological heads only')),
3182 ('t', 'topo', False, _('show topological heads only')),
3183 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3183 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3184 ('c', 'closed', False, _('show normal and closed branch heads')),
3184 ('c', 'closed', False, _('show normal and closed branch heads')),
3185 ] + templateopts,
3185 ] + templateopts,
3186 _('[-ct] [-r STARTREV] [REV]...'))
3186 _('[-ct] [-r STARTREV] [REV]...'))
3187 def heads(ui, repo, *branchrevs, **opts):
3187 def heads(ui, repo, *branchrevs, **opts):
3188 """show current repository heads or show branch heads
3188 """show current repository heads or show branch heads
3189
3189
3190 With no arguments, show all repository branch heads.
3190 With no arguments, show all repository branch heads.
3191
3191
3192 Repository "heads" are changesets with no child changesets. They are
3192 Repository "heads" are changesets with no child changesets. They are
3193 where development generally takes place and are the usual targets
3193 where development generally takes place and are the usual targets
3194 for update and merge operations. Branch heads are changesets that have
3194 for update and merge operations. Branch heads are changesets that have
3195 no child changeset on the same branch.
3195 no child changeset on the same branch.
3196
3196
3197 If one or more REVs are given, only branch heads on the branches
3197 If one or more REVs are given, only branch heads on the branches
3198 associated with the specified changesets are shown. This means
3198 associated with the specified changesets are shown. This means
3199 that you can use :hg:`heads foo` to see the heads on a branch
3199 that you can use :hg:`heads foo` to see the heads on a branch
3200 named ``foo``.
3200 named ``foo``.
3201
3201
3202 If -c/--closed is specified, also show branch heads marked closed
3202 If -c/--closed is specified, also show branch heads marked closed
3203 (see :hg:`commit --close-branch`).
3203 (see :hg:`commit --close-branch`).
3204
3204
3205 If STARTREV is specified, only those heads that are descendants of
3205 If STARTREV is specified, only those heads that are descendants of
3206 STARTREV will be displayed.
3206 STARTREV will be displayed.
3207
3207
3208 If -t/--topo is specified, named branch mechanics will be ignored and only
3208 If -t/--topo is specified, named branch mechanics will be ignored and only
3209 changesets without children will be shown.
3209 changesets without children will be shown.
3210
3210
3211 Returns 0 if matching heads are found, 1 if not.
3211 Returns 0 if matching heads are found, 1 if not.
3212 """
3212 """
3213
3213
3214 start = None
3214 start = None
3215 if 'rev' in opts:
3215 if 'rev' in opts:
3216 start = scmutil.revsingle(repo, opts['rev'], None).node()
3216 start = scmutil.revsingle(repo, opts['rev'], None).node()
3217
3217
3218 if opts.get('topo'):
3218 if opts.get('topo'):
3219 heads = [repo[h] for h in repo.heads(start)]
3219 heads = [repo[h] for h in repo.heads(start)]
3220 else:
3220 else:
3221 heads = []
3221 heads = []
3222 for branch in repo.branchmap():
3222 for branch in repo.branchmap():
3223 heads += repo.branchheads(branch, start, opts.get('closed'))
3223 heads += repo.branchheads(branch, start, opts.get('closed'))
3224 heads = [repo[h] for h in heads]
3224 heads = [repo[h] for h in heads]
3225
3225
3226 if branchrevs:
3226 if branchrevs:
3227 branches = set(repo[br].branch() for br in branchrevs)
3227 branches = set(repo[br].branch() for br in branchrevs)
3228 heads = [h for h in heads if h.branch() in branches]
3228 heads = [h for h in heads if h.branch() in branches]
3229
3229
3230 if opts.get('active') and branchrevs:
3230 if opts.get('active') and branchrevs:
3231 dagheads = repo.heads(start)
3231 dagheads = repo.heads(start)
3232 heads = [h for h in heads if h.node() in dagheads]
3232 heads = [h for h in heads if h.node() in dagheads]
3233
3233
3234 if branchrevs:
3234 if branchrevs:
3235 haveheads = set(h.branch() for h in heads)
3235 haveheads = set(h.branch() for h in heads)
3236 if branches - haveheads:
3236 if branches - haveheads:
3237 headless = ', '.join(b for b in branches - haveheads)
3237 headless = ', '.join(b for b in branches - haveheads)
3238 msg = _('no open branch heads found on branches %s')
3238 msg = _('no open branch heads found on branches %s')
3239 if opts.get('rev'):
3239 if opts.get('rev'):
3240 msg += _(' (started at %s)') % opts['rev']
3240 msg += _(' (started at %s)') % opts['rev']
3241 ui.warn((msg + '\n') % headless)
3241 ui.warn((msg + '\n') % headless)
3242
3242
3243 if not heads:
3243 if not heads:
3244 return 1
3244 return 1
3245
3245
3246 heads = sorted(heads, key=lambda x: -x.rev())
3246 heads = sorted(heads, key=lambda x: -x.rev())
3247 displayer = cmdutil.show_changeset(ui, repo, opts)
3247 displayer = cmdutil.show_changeset(ui, repo, opts)
3248 for ctx in heads:
3248 for ctx in heads:
3249 displayer.show(ctx)
3249 displayer.show(ctx)
3250 displayer.close()
3250 displayer.close()
3251
3251
3252 @command('help',
3252 @command('help',
3253 [('e', 'extension', None, _('show only help for extensions')),
3253 [('e', 'extension', None, _('show only help for extensions')),
3254 ('c', 'command', None, _('show only help for commands')),
3254 ('c', 'command', None, _('show only help for commands')),
3255 ('k', 'keyword', '', _('show topics matching keyword')),
3255 ('k', 'keyword', '', _('show topics matching keyword')),
3256 ],
3256 ],
3257 _('[-ec] [TOPIC]'))
3257 _('[-ec] [TOPIC]'))
3258 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3258 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3259 """show help for a given topic or a help overview
3259 """show help for a given topic or a help overview
3260
3260
3261 With no arguments, print a list of commands with short help messages.
3261 With no arguments, print a list of commands with short help messages.
3262
3262
3263 Given a topic, extension, or command name, print help for that
3263 Given a topic, extension, or command name, print help for that
3264 topic.
3264 topic.
3265
3265
3266 Returns 0 if successful.
3266 Returns 0 if successful.
3267 """
3267 """
3268
3268
3269 textwidth = min(ui.termwidth(), 80) - 2
3269 textwidth = min(ui.termwidth(), 80) - 2
3270
3270
3271 def helpcmd(name):
3271 def helpcmd(name):
3272 try:
3272 try:
3273 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3273 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3274 except error.AmbiguousCommand, inst:
3274 except error.AmbiguousCommand, inst:
3275 # py3k fix: except vars can't be used outside the scope of the
3275 # py3k fix: except vars can't be used outside the scope of the
3276 # except block, nor can be used inside a lambda. python issue4617
3276 # except block, nor can be used inside a lambda. python issue4617
3277 prefix = inst.args[0]
3277 prefix = inst.args[0]
3278 select = lambda c: c.lstrip('^').startswith(prefix)
3278 select = lambda c: c.lstrip('^').startswith(prefix)
3279 rst = helplist(select)
3279 rst = helplist(select)
3280 return rst
3280 return rst
3281
3281
3282 rst = []
3282 rst = []
3283
3283
3284 # check if it's an invalid alias and display its error if it is
3284 # check if it's an invalid alias and display its error if it is
3285 if getattr(entry[0], 'badalias', False):
3285 if getattr(entry[0], 'badalias', False):
3286 if not unknowncmd:
3286 if not unknowncmd:
3287 ui.pushbuffer()
3287 ui.pushbuffer()
3288 entry[0](ui)
3288 entry[0](ui)
3289 rst.append(ui.popbuffer())
3289 rst.append(ui.popbuffer())
3290 return rst
3290 return rst
3291
3291
3292 # synopsis
3292 # synopsis
3293 if len(entry) > 2:
3293 if len(entry) > 2:
3294 if entry[2].startswith('hg'):
3294 if entry[2].startswith('hg'):
3295 rst.append("%s\n" % entry[2])
3295 rst.append("%s\n" % entry[2])
3296 else:
3296 else:
3297 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3297 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3298 else:
3298 else:
3299 rst.append('hg %s\n' % aliases[0])
3299 rst.append('hg %s\n' % aliases[0])
3300 # aliases
3300 # aliases
3301 if full and not ui.quiet and len(aliases) > 1:
3301 if full and not ui.quiet and len(aliases) > 1:
3302 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3302 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3303 rst.append('\n')
3303 rst.append('\n')
3304
3304
3305 # description
3305 # description
3306 doc = gettext(entry[0].__doc__)
3306 doc = gettext(entry[0].__doc__)
3307 if not doc:
3307 if not doc:
3308 doc = _("(no help text available)")
3308 doc = _("(no help text available)")
3309 if util.safehasattr(entry[0], 'definition'): # aliased command
3309 if util.safehasattr(entry[0], 'definition'): # aliased command
3310 if entry[0].definition.startswith('!'): # shell alias
3310 if entry[0].definition.startswith('!'): # shell alias
3311 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3311 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3312 else:
3312 else:
3313 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3313 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3314 doc = doc.splitlines(True)
3314 doc = doc.splitlines(True)
3315 if ui.quiet or not full:
3315 if ui.quiet or not full:
3316 rst.append(doc[0])
3316 rst.append(doc[0])
3317 else:
3317 else:
3318 rst.extend(doc)
3318 rst.extend(doc)
3319 rst.append('\n')
3319 rst.append('\n')
3320
3320
3321 # check if this command shadows a non-trivial (multi-line)
3321 # check if this command shadows a non-trivial (multi-line)
3322 # extension help text
3322 # extension help text
3323 try:
3323 try:
3324 mod = extensions.find(name)
3324 mod = extensions.find(name)
3325 doc = gettext(mod.__doc__) or ''
3325 doc = gettext(mod.__doc__) or ''
3326 if '\n' in doc.strip():
3326 if '\n' in doc.strip():
3327 msg = _('use "hg help -e %s" to show help for '
3327 msg = _('use "hg help -e %s" to show help for '
3328 'the %s extension') % (name, name)
3328 'the %s extension') % (name, name)
3329 rst.append('\n%s\n' % msg)
3329 rst.append('\n%s\n' % msg)
3330 except KeyError:
3330 except KeyError:
3331 pass
3331 pass
3332
3332
3333 # options
3333 # options
3334 if not ui.quiet and entry[1]:
3334 if not ui.quiet and entry[1]:
3335 rst.append('\n%s\n\n' % _("options:"))
3335 rst.append('\n%s\n\n' % _("options:"))
3336 rst.append(help.optrst(entry[1], ui.verbose))
3336 rst.append(help.optrst(entry[1], ui.verbose))
3337
3337
3338 if ui.verbose:
3338 if ui.verbose:
3339 rst.append('\n%s\n\n' % _("global options:"))
3339 rst.append('\n%s\n\n' % _("global options:"))
3340 rst.append(help.optrst(globalopts, ui.verbose))
3340 rst.append(help.optrst(globalopts, ui.verbose))
3341
3341
3342 if not ui.verbose:
3342 if not ui.verbose:
3343 if not full:
3343 if not full:
3344 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3344 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3345 % name)
3345 % name)
3346 elif not ui.quiet:
3346 elif not ui.quiet:
3347 omitted = _('use "hg -v help %s" to show more complete'
3347 omitted = _('use "hg -v help %s" to show more complete'
3348 ' help and the global options') % name
3348 ' help and the global options') % name
3349 notomitted = _('use "hg -v help %s" to show'
3349 notomitted = _('use "hg -v help %s" to show'
3350 ' the global options') % name
3350 ' the global options') % name
3351 help.indicateomitted(rst, omitted, notomitted)
3351 help.indicateomitted(rst, omitted, notomitted)
3352
3352
3353 return rst
3353 return rst
3354
3354
3355
3355
3356 def helplist(select=None):
3356 def helplist(select=None):
3357 # list of commands
3357 # list of commands
3358 if name == "shortlist":
3358 if name == "shortlist":
3359 header = _('basic commands:\n\n')
3359 header = _('basic commands:\n\n')
3360 else:
3360 else:
3361 header = _('list of commands:\n\n')
3361 header = _('list of commands:\n\n')
3362
3362
3363 h = {}
3363 h = {}
3364 cmds = {}
3364 cmds = {}
3365 for c, e in table.iteritems():
3365 for c, e in table.iteritems():
3366 f = c.split("|", 1)[0]
3366 f = c.split("|", 1)[0]
3367 if select and not select(f):
3367 if select and not select(f):
3368 continue
3368 continue
3369 if (not select and name != 'shortlist' and
3369 if (not select and name != 'shortlist' and
3370 e[0].__module__ != __name__):
3370 e[0].__module__ != __name__):
3371 continue
3371 continue
3372 if name == "shortlist" and not f.startswith("^"):
3372 if name == "shortlist" and not f.startswith("^"):
3373 continue
3373 continue
3374 f = f.lstrip("^")
3374 f = f.lstrip("^")
3375 if not ui.debugflag and f.startswith("debug"):
3375 if not ui.debugflag and f.startswith("debug"):
3376 continue
3376 continue
3377 doc = e[0].__doc__
3377 doc = e[0].__doc__
3378 if doc and 'DEPRECATED' in doc and not ui.verbose:
3378 if doc and 'DEPRECATED' in doc and not ui.verbose:
3379 continue
3379 continue
3380 doc = gettext(doc)
3380 doc = gettext(doc)
3381 if not doc:
3381 if not doc:
3382 doc = _("(no help text available)")
3382 doc = _("(no help text available)")
3383 h[f] = doc.splitlines()[0].rstrip()
3383 h[f] = doc.splitlines()[0].rstrip()
3384 cmds[f] = c.lstrip("^")
3384 cmds[f] = c.lstrip("^")
3385
3385
3386 rst = []
3386 rst = []
3387 if not h:
3387 if not h:
3388 if not ui.quiet:
3388 if not ui.quiet:
3389 rst.append(_('no commands defined\n'))
3389 rst.append(_('no commands defined\n'))
3390 return rst
3390 return rst
3391
3391
3392 if not ui.quiet:
3392 if not ui.quiet:
3393 rst.append(header)
3393 rst.append(header)
3394 fns = sorted(h)
3394 fns = sorted(h)
3395 for f in fns:
3395 for f in fns:
3396 if ui.verbose:
3396 if ui.verbose:
3397 commands = cmds[f].replace("|",", ")
3397 commands = cmds[f].replace("|",", ")
3398 rst.append(" :%s: %s\n" % (commands, h[f]))
3398 rst.append(" :%s: %s\n" % (commands, h[f]))
3399 else:
3399 else:
3400 rst.append(' :%s: %s\n' % (f, h[f]))
3400 rst.append(' :%s: %s\n' % (f, h[f]))
3401
3401
3402 if not name:
3402 if not name:
3403 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3403 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3404 if exts:
3404 if exts:
3405 rst.append('\n')
3405 rst.append('\n')
3406 rst.extend(exts)
3406 rst.extend(exts)
3407
3407
3408 rst.append(_("\nadditional help topics:\n\n"))
3408 rst.append(_("\nadditional help topics:\n\n"))
3409 topics = []
3409 topics = []
3410 for names, header, doc in help.helptable:
3410 for names, header, doc in help.helptable:
3411 topics.append((names[0], header))
3411 topics.append((names[0], header))
3412 for t, desc in topics:
3412 for t, desc in topics:
3413 rst.append(" :%s: %s\n" % (t, desc))
3413 rst.append(" :%s: %s\n" % (t, desc))
3414
3414
3415 optlist = []
3415 optlist = []
3416 if not ui.quiet:
3416 if not ui.quiet:
3417 if ui.verbose:
3417 if ui.verbose:
3418 optlist.append((_("global options:"), globalopts))
3418 optlist.append((_("global options:"), globalopts))
3419 if name == 'shortlist':
3419 if name == 'shortlist':
3420 optlist.append((_('use "hg help" for the full list '
3420 optlist.append((_('use "hg help" for the full list '
3421 'of commands'), ()))
3421 'of commands'), ()))
3422 else:
3422 else:
3423 if name == 'shortlist':
3423 if name == 'shortlist':
3424 msg = _('use "hg help" for the full list of commands '
3424 msg = _('use "hg help" for the full list of commands '
3425 'or "hg -v" for details')
3425 'or "hg -v" for details')
3426 elif name and not full:
3426 elif name and not full:
3427 msg = _('use "hg help %s" to show the full help '
3427 msg = _('use "hg help %s" to show the full help '
3428 'text') % name
3428 'text') % name
3429 else:
3429 else:
3430 msg = _('use "hg -v help%s" to show builtin aliases and '
3430 msg = _('use "hg -v help%s" to show builtin aliases and '
3431 'global options') % (name and " " + name or "")
3431 'global options') % (name and " " + name or "")
3432 optlist.append((msg, ()))
3432 optlist.append((msg, ()))
3433
3433
3434 if optlist:
3434 if optlist:
3435 for title, options in optlist:
3435 for title, options in optlist:
3436 rst.append('\n%s\n' % title)
3436 rst.append('\n%s\n' % title)
3437 if options:
3437 if options:
3438 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3438 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3439 return rst
3439 return rst
3440
3440
3441 def helptopic(name):
3441 def helptopic(name):
3442 for names, header, doc in help.helptable:
3442 for names, header, doc in help.helptable:
3443 if name in names:
3443 if name in names:
3444 break
3444 break
3445 else:
3445 else:
3446 raise error.UnknownCommand(name)
3446 raise error.UnknownCommand(name)
3447
3447
3448 rst = ["%s\n\n" % header]
3448 rst = ["%s\n\n" % header]
3449 # description
3449 # description
3450 if not doc:
3450 if not doc:
3451 rst.append(" %s\n" % _("(no help text available)"))
3451 rst.append(" %s\n" % _("(no help text available)"))
3452 if util.safehasattr(doc, '__call__'):
3452 if util.safehasattr(doc, '__call__'):
3453 rst += [" %s\n" % l for l in doc().splitlines()]
3453 rst += [" %s\n" % l for l in doc().splitlines()]
3454
3454
3455 if not ui.verbose:
3455 if not ui.verbose:
3456 omitted = (_('use "hg help -v %s" to show more complete help') %
3456 omitted = (_('use "hg help -v %s" to show more complete help') %
3457 name)
3457 name)
3458 help.indicateomitted(rst, omitted)
3458 help.indicateomitted(rst, omitted)
3459
3459
3460 try:
3460 try:
3461 cmdutil.findcmd(name, table)
3461 cmdutil.findcmd(name, table)
3462 rst.append(_('\nuse "hg help -c %s" to see help for '
3462 rst.append(_('\nuse "hg help -c %s" to see help for '
3463 'the %s command\n') % (name, name))
3463 'the %s command\n') % (name, name))
3464 except error.UnknownCommand:
3464 except error.UnknownCommand:
3465 pass
3465 pass
3466 return rst
3466 return rst
3467
3467
3468 def helpext(name):
3468 def helpext(name):
3469 try:
3469 try:
3470 mod = extensions.find(name)
3470 mod = extensions.find(name)
3471 doc = gettext(mod.__doc__) or _('no help text available')
3471 doc = gettext(mod.__doc__) or _('no help text available')
3472 except KeyError:
3472 except KeyError:
3473 mod = None
3473 mod = None
3474 doc = extensions.disabledext(name)
3474 doc = extensions.disabledext(name)
3475 if not doc:
3475 if not doc:
3476 raise error.UnknownCommand(name)
3476 raise error.UnknownCommand(name)
3477
3477
3478 if '\n' not in doc:
3478 if '\n' not in doc:
3479 head, tail = doc, ""
3479 head, tail = doc, ""
3480 else:
3480 else:
3481 head, tail = doc.split('\n', 1)
3481 head, tail = doc.split('\n', 1)
3482 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3482 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3483 if tail:
3483 if tail:
3484 rst.extend(tail.splitlines(True))
3484 rst.extend(tail.splitlines(True))
3485 rst.append('\n')
3485 rst.append('\n')
3486
3486
3487 if not ui.verbose:
3487 if not ui.verbose:
3488 omitted = (_('use "hg help -v %s" to show more complete help') %
3488 omitted = (_('use "hg help -v %s" to show more complete help') %
3489 name)
3489 name)
3490 help.indicateomitted(rst, omitted)
3490 help.indicateomitted(rst, omitted)
3491
3491
3492 if mod:
3492 if mod:
3493 try:
3493 try:
3494 ct = mod.cmdtable
3494 ct = mod.cmdtable
3495 except AttributeError:
3495 except AttributeError:
3496 ct = {}
3496 ct = {}
3497 modcmds = set([c.split('|', 1)[0] for c in ct])
3497 modcmds = set([c.split('|', 1)[0] for c in ct])
3498 rst.extend(helplist(modcmds.__contains__))
3498 rst.extend(helplist(modcmds.__contains__))
3499 else:
3499 else:
3500 rst.append(_('use "hg help extensions" for information on enabling '
3500 rst.append(_('use "hg help extensions" for information on enabling '
3501 'extensions\n'))
3501 'extensions\n'))
3502 return rst
3502 return rst
3503
3503
3504 def helpextcmd(name):
3504 def helpextcmd(name):
3505 cmd, ext, mod = extensions.disabledcmd(ui, name,
3505 cmd, ext, mod = extensions.disabledcmd(ui, name,
3506 ui.configbool('ui', 'strict'))
3506 ui.configbool('ui', 'strict'))
3507 doc = gettext(mod.__doc__).splitlines()[0]
3507 doc = gettext(mod.__doc__).splitlines()[0]
3508
3508
3509 rst = help.listexts(_("'%s' is provided by the following "
3509 rst = help.listexts(_("'%s' is provided by the following "
3510 "extension:") % cmd, {ext: doc}, indent=4)
3510 "extension:") % cmd, {ext: doc}, indent=4)
3511 rst.append('\n')
3511 rst.append('\n')
3512 rst.append(_('use "hg help extensions" for information on enabling '
3512 rst.append(_('use "hg help extensions" for information on enabling '
3513 'extensions\n'))
3513 'extensions\n'))
3514 return rst
3514 return rst
3515
3515
3516
3516
3517 rst = []
3517 rst = []
3518 kw = opts.get('keyword')
3518 kw = opts.get('keyword')
3519 if kw:
3519 if kw:
3520 matches = help.topicmatch(kw)
3520 matches = help.topicmatch(kw)
3521 for t, title in (('topics', _('Topics')),
3521 for t, title in (('topics', _('Topics')),
3522 ('commands', _('Commands')),
3522 ('commands', _('Commands')),
3523 ('extensions', _('Extensions')),
3523 ('extensions', _('Extensions')),
3524 ('extensioncommands', _('Extension Commands'))):
3524 ('extensioncommands', _('Extension Commands'))):
3525 if matches[t]:
3525 if matches[t]:
3526 rst.append('%s:\n\n' % title)
3526 rst.append('%s:\n\n' % title)
3527 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3527 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3528 rst.append('\n')
3528 rst.append('\n')
3529 elif name and name != 'shortlist':
3529 elif name and name != 'shortlist':
3530 i = None
3530 i = None
3531 if unknowncmd:
3531 if unknowncmd:
3532 queries = (helpextcmd,)
3532 queries = (helpextcmd,)
3533 elif opts.get('extension'):
3533 elif opts.get('extension'):
3534 queries = (helpext,)
3534 queries = (helpext,)
3535 elif opts.get('command'):
3535 elif opts.get('command'):
3536 queries = (helpcmd,)
3536 queries = (helpcmd,)
3537 else:
3537 else:
3538 queries = (helptopic, helpcmd, helpext, helpextcmd)
3538 queries = (helptopic, helpcmd, helpext, helpextcmd)
3539 for f in queries:
3539 for f in queries:
3540 try:
3540 try:
3541 rst = f(name)
3541 rst = f(name)
3542 i = None
3542 i = None
3543 break
3543 break
3544 except error.UnknownCommand, inst:
3544 except error.UnknownCommand, inst:
3545 i = inst
3545 i = inst
3546 if i:
3546 if i:
3547 raise i
3547 raise i
3548 else:
3548 else:
3549 # program name
3549 # program name
3550 if not ui.quiet:
3550 if not ui.quiet:
3551 rst = [_("Mercurial Distributed SCM\n"), '\n']
3551 rst = [_("Mercurial Distributed SCM\n"), '\n']
3552 rst.extend(helplist())
3552 rst.extend(helplist())
3553
3553
3554 keep = ui.verbose and ['verbose'] or []
3554 keep = ui.verbose and ['verbose'] or []
3555 text = ''.join(rst)
3555 text = ''.join(rst)
3556 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3556 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3557 if 'verbose' in pruned:
3557 if 'verbose' in pruned:
3558 keep.append('omitted')
3558 keep.append('omitted')
3559 else:
3559 else:
3560 keep.append('notomitted')
3560 keep.append('notomitted')
3561 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3561 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3562 ui.write(formatted)
3562 ui.write(formatted)
3563
3563
3564
3564
3565 @command('identify|id',
3565 @command('identify|id',
3566 [('r', 'rev', '',
3566 [('r', 'rev', '',
3567 _('identify the specified revision'), _('REV')),
3567 _('identify the specified revision'), _('REV')),
3568 ('n', 'num', None, _('show local revision number')),
3568 ('n', 'num', None, _('show local revision number')),
3569 ('i', 'id', None, _('show global revision id')),
3569 ('i', 'id', None, _('show global revision id')),
3570 ('b', 'branch', None, _('show branch')),
3570 ('b', 'branch', None, _('show branch')),
3571 ('t', 'tags', None, _('show tags')),
3571 ('t', 'tags', None, _('show tags')),
3572 ('B', 'bookmarks', None, _('show bookmarks')),
3572 ('B', 'bookmarks', None, _('show bookmarks')),
3573 ] + remoteopts,
3573 ] + remoteopts,
3574 _('[-nibtB] [-r REV] [SOURCE]'))
3574 _('[-nibtB] [-r REV] [SOURCE]'))
3575 def identify(ui, repo, source=None, rev=None,
3575 def identify(ui, repo, source=None, rev=None,
3576 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3576 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3577 """identify the working copy or specified revision
3577 """identify the working copy or specified revision
3578
3578
3579 Print a summary identifying the repository state at REV using one or
3579 Print a summary identifying the repository state at REV using one or
3580 two parent hash identifiers, followed by a "+" if the working
3580 two parent hash identifiers, followed by a "+" if the working
3581 directory has uncommitted changes, the branch name (if not default),
3581 directory has uncommitted changes, the branch name (if not default),
3582 a list of tags, and a list of bookmarks.
3582 a list of tags, and a list of bookmarks.
3583
3583
3584 When REV is not given, print a summary of the current state of the
3584 When REV is not given, print a summary of the current state of the
3585 repository.
3585 repository.
3586
3586
3587 Specifying a path to a repository root or Mercurial bundle will
3587 Specifying a path to a repository root or Mercurial bundle will
3588 cause lookup to operate on that repository/bundle.
3588 cause lookup to operate on that repository/bundle.
3589
3589
3590 .. container:: verbose
3590 .. container:: verbose
3591
3591
3592 Examples:
3592 Examples:
3593
3593
3594 - generate a build identifier for the working directory::
3594 - generate a build identifier for the working directory::
3595
3595
3596 hg id --id > build-id.dat
3596 hg id --id > build-id.dat
3597
3597
3598 - find the revision corresponding to a tag::
3598 - find the revision corresponding to a tag::
3599
3599
3600 hg id -n -r 1.3
3600 hg id -n -r 1.3
3601
3601
3602 - check the most recent revision of a remote repository::
3602 - check the most recent revision of a remote repository::
3603
3603
3604 hg id -r tip http://selenic.com/hg/
3604 hg id -r tip http://selenic.com/hg/
3605
3605
3606 Returns 0 if successful.
3606 Returns 0 if successful.
3607 """
3607 """
3608
3608
3609 if not repo and not source:
3609 if not repo and not source:
3610 raise util.Abort(_("there is no Mercurial repository here "
3610 raise util.Abort(_("there is no Mercurial repository here "
3611 "(.hg not found)"))
3611 "(.hg not found)"))
3612
3612
3613 hexfunc = ui.debugflag and hex or short
3613 hexfunc = ui.debugflag and hex or short
3614 default = not (num or id or branch or tags or bookmarks)
3614 default = not (num or id or branch or tags or bookmarks)
3615 output = []
3615 output = []
3616 revs = []
3616 revs = []
3617
3617
3618 if source:
3618 if source:
3619 source, branches = hg.parseurl(ui.expandpath(source))
3619 source, branches = hg.parseurl(ui.expandpath(source))
3620 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3620 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3621 repo = peer.local()
3621 repo = peer.local()
3622 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3622 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3623
3623
3624 if not repo:
3624 if not repo:
3625 if num or branch or tags:
3625 if num or branch or tags:
3626 raise util.Abort(
3626 raise util.Abort(
3627 _("can't query remote revision number, branch, or tags"))
3627 _("can't query remote revision number, branch, or tags"))
3628 if not rev and revs:
3628 if not rev and revs:
3629 rev = revs[0]
3629 rev = revs[0]
3630 if not rev:
3630 if not rev:
3631 rev = "tip"
3631 rev = "tip"
3632
3632
3633 remoterev = peer.lookup(rev)
3633 remoterev = peer.lookup(rev)
3634 if default or id:
3634 if default or id:
3635 output = [hexfunc(remoterev)]
3635 output = [hexfunc(remoterev)]
3636
3636
3637 def getbms():
3637 def getbms():
3638 bms = []
3638 bms = []
3639
3639
3640 if 'bookmarks' in peer.listkeys('namespaces'):
3640 if 'bookmarks' in peer.listkeys('namespaces'):
3641 hexremoterev = hex(remoterev)
3641 hexremoterev = hex(remoterev)
3642 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3642 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3643 if bmr == hexremoterev]
3643 if bmr == hexremoterev]
3644
3644
3645 return sorted(bms)
3645 return sorted(bms)
3646
3646
3647 if bookmarks:
3647 if bookmarks:
3648 output.extend(getbms())
3648 output.extend(getbms())
3649 elif default and not ui.quiet:
3649 elif default and not ui.quiet:
3650 # multiple bookmarks for a single parent separated by '/'
3650 # multiple bookmarks for a single parent separated by '/'
3651 bm = '/'.join(getbms())
3651 bm = '/'.join(getbms())
3652 if bm:
3652 if bm:
3653 output.append(bm)
3653 output.append(bm)
3654 else:
3654 else:
3655 if not rev:
3655 if not rev:
3656 ctx = repo[None]
3656 ctx = repo[None]
3657 parents = ctx.parents()
3657 parents = ctx.parents()
3658 changed = ""
3658 changed = ""
3659 if default or id or num:
3659 if default or id or num:
3660 if (util.any(repo.status())
3660 if (util.any(repo.status())
3661 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3661 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3662 changed = '+'
3662 changed = '+'
3663 if default or id:
3663 if default or id:
3664 output = ["%s%s" %
3664 output = ["%s%s" %
3665 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3665 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3666 if num:
3666 if num:
3667 output.append("%s%s" %
3667 output.append("%s%s" %
3668 ('+'.join([str(p.rev()) for p in parents]), changed))
3668 ('+'.join([str(p.rev()) for p in parents]), changed))
3669 else:
3669 else:
3670 ctx = scmutil.revsingle(repo, rev)
3670 ctx = scmutil.revsingle(repo, rev)
3671 if default or id:
3671 if default or id:
3672 output = [hexfunc(ctx.node())]
3672 output = [hexfunc(ctx.node())]
3673 if num:
3673 if num:
3674 output.append(str(ctx.rev()))
3674 output.append(str(ctx.rev()))
3675
3675
3676 if default and not ui.quiet:
3676 if default and not ui.quiet:
3677 b = ctx.branch()
3677 b = ctx.branch()
3678 if b != 'default':
3678 if b != 'default':
3679 output.append("(%s)" % b)
3679 output.append("(%s)" % b)
3680
3680
3681 # multiple tags for a single parent separated by '/'
3681 # multiple tags for a single parent separated by '/'
3682 t = '/'.join(ctx.tags())
3682 t = '/'.join(ctx.tags())
3683 if t:
3683 if t:
3684 output.append(t)
3684 output.append(t)
3685
3685
3686 # multiple bookmarks for a single parent separated by '/'
3686 # multiple bookmarks for a single parent separated by '/'
3687 bm = '/'.join(ctx.bookmarks())
3687 bm = '/'.join(ctx.bookmarks())
3688 if bm:
3688 if bm:
3689 output.append(bm)
3689 output.append(bm)
3690 else:
3690 else:
3691 if branch:
3691 if branch:
3692 output.append(ctx.branch())
3692 output.append(ctx.branch())
3693
3693
3694 if tags:
3694 if tags:
3695 output.extend(ctx.tags())
3695 output.extend(ctx.tags())
3696
3696
3697 if bookmarks:
3697 if bookmarks:
3698 output.extend(ctx.bookmarks())
3698 output.extend(ctx.bookmarks())
3699
3699
3700 ui.write("%s\n" % ' '.join(output))
3700 ui.write("%s\n" % ' '.join(output))
3701
3701
3702 @command('import|patch',
3702 @command('import|patch',
3703 [('p', 'strip', 1,
3703 [('p', 'strip', 1,
3704 _('directory strip option for patch. This has the same '
3704 _('directory strip option for patch. This has the same '
3705 'meaning as the corresponding patch option'), _('NUM')),
3705 'meaning as the corresponding patch option'), _('NUM')),
3706 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3706 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3707 ('e', 'edit', False, _('invoke editor on commit messages')),
3707 ('e', 'edit', False, _('invoke editor on commit messages')),
3708 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3708 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3709 ('', 'no-commit', None,
3709 ('', 'no-commit', None,
3710 _("don't commit, just update the working directory")),
3710 _("don't commit, just update the working directory")),
3711 ('', 'bypass', None,
3711 ('', 'bypass', None,
3712 _("apply patch without touching the working directory")),
3712 _("apply patch without touching the working directory")),
3713 ('', 'exact', None,
3713 ('', 'exact', None,
3714 _('apply patch to the nodes from which it was generated')),
3714 _('apply patch to the nodes from which it was generated')),
3715 ('', 'import-branch', None,
3715 ('', 'import-branch', None,
3716 _('use any branch information in patch (implied by --exact)'))] +
3716 _('use any branch information in patch (implied by --exact)'))] +
3717 commitopts + commitopts2 + similarityopts,
3717 commitopts + commitopts2 + similarityopts,
3718 _('[OPTION]... PATCH...'))
3718 _('[OPTION]... PATCH...'))
3719 def import_(ui, repo, patch1=None, *patches, **opts):
3719 def import_(ui, repo, patch1=None, *patches, **opts):
3720 """import an ordered set of patches
3720 """import an ordered set of patches
3721
3721
3722 Import a list of patches and commit them individually (unless
3722 Import a list of patches and commit them individually (unless
3723 --no-commit is specified).
3723 --no-commit is specified).
3724
3724
3725 If there are outstanding changes in the working directory, import
3725 If there are outstanding changes in the working directory, import
3726 will abort unless given the -f/--force flag.
3726 will abort unless given the -f/--force flag.
3727
3727
3728 You can import a patch straight from a mail message. Even patches
3728 You can import a patch straight from a mail message. Even patches
3729 as attachments work (to use the body part, it must have type
3729 as attachments work (to use the body part, it must have type
3730 text/plain or text/x-patch). From and Subject headers of email
3730 text/plain or text/x-patch). From and Subject headers of email
3731 message are used as default committer and commit message. All
3731 message are used as default committer and commit message. All
3732 text/plain body parts before first diff are added to commit
3732 text/plain body parts before first diff are added to commit
3733 message.
3733 message.
3734
3734
3735 If the imported patch was generated by :hg:`export`, user and
3735 If the imported patch was generated by :hg:`export`, user and
3736 description from patch override values from message headers and
3736 description from patch override values from message headers and
3737 body. Values given on command line with -m/--message and -u/--user
3737 body. Values given on command line with -m/--message and -u/--user
3738 override these.
3738 override these.
3739
3739
3740 If --exact is specified, import will set the working directory to
3740 If --exact is specified, import will set the working directory to
3741 the parent of each patch before applying it, and will abort if the
3741 the parent of each patch before applying it, and will abort if the
3742 resulting changeset has a different ID than the one recorded in
3742 resulting changeset has a different ID than the one recorded in
3743 the patch. This may happen due to character set problems or other
3743 the patch. This may happen due to character set problems or other
3744 deficiencies in the text patch format.
3744 deficiencies in the text patch format.
3745
3745
3746 Use --bypass to apply and commit patches directly to the
3746 Use --bypass to apply and commit patches directly to the
3747 repository, not touching the working directory. Without --exact,
3747 repository, not touching the working directory. Without --exact,
3748 patches will be applied on top of the working directory parent
3748 patches will be applied on top of the working directory parent
3749 revision.
3749 revision.
3750
3750
3751 With -s/--similarity, hg will attempt to discover renames and
3751 With -s/--similarity, hg will attempt to discover renames and
3752 copies in the patch in the same way as :hg:`addremove`.
3752 copies in the patch in the same way as :hg:`addremove`.
3753
3753
3754 To read a patch from standard input, use "-" as the patch name. If
3754 To read a patch from standard input, use "-" as the patch name. If
3755 a URL is specified, the patch will be downloaded from it.
3755 a URL is specified, the patch will be downloaded from it.
3756 See :hg:`help dates` for a list of formats valid for -d/--date.
3756 See :hg:`help dates` for a list of formats valid for -d/--date.
3757
3757
3758 .. container:: verbose
3758 .. container:: verbose
3759
3759
3760 Examples:
3760 Examples:
3761
3761
3762 - import a traditional patch from a website and detect renames::
3762 - import a traditional patch from a website and detect renames::
3763
3763
3764 hg import -s 80 http://example.com/bugfix.patch
3764 hg import -s 80 http://example.com/bugfix.patch
3765
3765
3766 - import a changeset from an hgweb server::
3766 - import a changeset from an hgweb server::
3767
3767
3768 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3768 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3769
3769
3770 - import all the patches in an Unix-style mbox::
3770 - import all the patches in an Unix-style mbox::
3771
3771
3772 hg import incoming-patches.mbox
3772 hg import incoming-patches.mbox
3773
3773
3774 - attempt to exactly restore an exported changeset (not always
3774 - attempt to exactly restore an exported changeset (not always
3775 possible)::
3775 possible)::
3776
3776
3777 hg import --exact proposed-fix.patch
3777 hg import --exact proposed-fix.patch
3778
3778
3779 Returns 0 on success.
3779 Returns 0 on success.
3780 """
3780 """
3781
3781
3782 if not patch1:
3782 if not patch1:
3783 raise util.Abort(_('need at least one patch to import'))
3783 raise util.Abort(_('need at least one patch to import'))
3784
3784
3785 patches = (patch1,) + patches
3785 patches = (patch1,) + patches
3786
3786
3787 date = opts.get('date')
3787 date = opts.get('date')
3788 if date:
3788 if date:
3789 opts['date'] = util.parsedate(date)
3789 opts['date'] = util.parsedate(date)
3790
3790
3791 editor = cmdutil.commiteditor
3791 editor = cmdutil.commiteditor
3792 if opts.get('edit'):
3792 if opts.get('edit'):
3793 editor = cmdutil.commitforceeditor
3793 editor = cmdutil.commitforceeditor
3794
3794
3795 update = not opts.get('bypass')
3795 update = not opts.get('bypass')
3796 if not update and opts.get('no_commit'):
3796 if not update and opts.get('no_commit'):
3797 raise util.Abort(_('cannot use --no-commit with --bypass'))
3797 raise util.Abort(_('cannot use --no-commit with --bypass'))
3798 try:
3798 try:
3799 sim = float(opts.get('similarity') or 0)
3799 sim = float(opts.get('similarity') or 0)
3800 except ValueError:
3800 except ValueError:
3801 raise util.Abort(_('similarity must be a number'))
3801 raise util.Abort(_('similarity must be a number'))
3802 if sim < 0 or sim > 100:
3802 if sim < 0 or sim > 100:
3803 raise util.Abort(_('similarity must be between 0 and 100'))
3803 raise util.Abort(_('similarity must be between 0 and 100'))
3804 if sim and not update:
3804 if sim and not update:
3805 raise util.Abort(_('cannot use --similarity with --bypass'))
3805 raise util.Abort(_('cannot use --similarity with --bypass'))
3806
3806
3807 if (opts.get('exact') or not opts.get('force')) and update:
3807 if (opts.get('exact') or not opts.get('force')) and update:
3808 cmdutil.bailifchanged(repo)
3808 cmdutil.bailifchanged(repo)
3809
3809
3810 base = opts["base"]
3810 base = opts["base"]
3811 strip = opts["strip"]
3811 strip = opts["strip"]
3812 wlock = lock = tr = None
3812 wlock = lock = tr = None
3813 msgs = []
3813 msgs = []
3814
3814
3815 def checkexact(repo, n, nodeid):
3815 def checkexact(repo, n, nodeid):
3816 if opts.get('exact') and hex(n) != nodeid:
3816 if opts.get('exact') and hex(n) != nodeid:
3817 repo.rollback()
3817 repo.rollback()
3818 raise util.Abort(_('patch is damaged or loses information'))
3818 raise util.Abort(_('patch is damaged or loses information'))
3819
3819
3820 def tryone(ui, hunk, parents):
3820 def tryone(ui, hunk, parents):
3821 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3821 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3822 patch.extract(ui, hunk)
3822 patch.extract(ui, hunk)
3823
3823
3824 if not tmpname:
3824 if not tmpname:
3825 return (None, None)
3825 return (None, None)
3826 msg = _('applied to working directory')
3826 msg = _('applied to working directory')
3827
3827
3828 try:
3828 try:
3829 cmdline_message = cmdutil.logmessage(ui, opts)
3829 cmdline_message = cmdutil.logmessage(ui, opts)
3830 if cmdline_message:
3830 if cmdline_message:
3831 # pickup the cmdline msg
3831 # pickup the cmdline msg
3832 message = cmdline_message
3832 message = cmdline_message
3833 elif message:
3833 elif message:
3834 # pickup the patch msg
3834 # pickup the patch msg
3835 message = message.strip()
3835 message = message.strip()
3836 else:
3836 else:
3837 # launch the editor
3837 # launch the editor
3838 message = None
3838 message = None
3839 ui.debug('message:\n%s\n' % message)
3839 ui.debug('message:\n%s\n' % message)
3840
3840
3841 if len(parents) == 1:
3841 if len(parents) == 1:
3842 parents.append(repo[nullid])
3842 parents.append(repo[nullid])
3843 if opts.get('exact'):
3843 if opts.get('exact'):
3844 if not nodeid or not p1:
3844 if not nodeid or not p1:
3845 raise util.Abort(_('not a Mercurial patch'))
3845 raise util.Abort(_('not a Mercurial patch'))
3846 p1 = repo[p1]
3846 p1 = repo[p1]
3847 p2 = repo[p2 or nullid]
3847 p2 = repo[p2 or nullid]
3848 elif p2:
3848 elif p2:
3849 try:
3849 try:
3850 p1 = repo[p1]
3850 p1 = repo[p1]
3851 p2 = repo[p2]
3851 p2 = repo[p2]
3852 # Without any options, consider p2 only if the
3852 # Without any options, consider p2 only if the
3853 # patch is being applied on top of the recorded
3853 # patch is being applied on top of the recorded
3854 # first parent.
3854 # first parent.
3855 if p1 != parents[0]:
3855 if p1 != parents[0]:
3856 p1 = parents[0]
3856 p1 = parents[0]
3857 p2 = repo[nullid]
3857 p2 = repo[nullid]
3858 except error.RepoError:
3858 except error.RepoError:
3859 p1, p2 = parents
3859 p1, p2 = parents
3860 else:
3860 else:
3861 p1, p2 = parents
3861 p1, p2 = parents
3862
3862
3863 n = None
3863 n = None
3864 if update:
3864 if update:
3865 if p1 != parents[0]:
3865 if p1 != parents[0]:
3866 hg.clean(repo, p1.node())
3866 hg.clean(repo, p1.node())
3867 if p2 != parents[1]:
3867 if p2 != parents[1]:
3868 repo.setparents(p1.node(), p2.node())
3868 repo.setparents(p1.node(), p2.node())
3869
3869
3870 if opts.get('exact') or opts.get('import_branch'):
3870 if opts.get('exact') or opts.get('import_branch'):
3871 repo.dirstate.setbranch(branch or 'default')
3871 repo.dirstate.setbranch(branch or 'default')
3872
3872
3873 files = set()
3873 files = set()
3874 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3874 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3875 eolmode=None, similarity=sim / 100.0)
3875 eolmode=None, similarity=sim / 100.0)
3876 files = list(files)
3876 files = list(files)
3877 if opts.get('no_commit'):
3877 if opts.get('no_commit'):
3878 if message:
3878 if message:
3879 msgs.append(message)
3879 msgs.append(message)
3880 else:
3880 else:
3881 if opts.get('exact') or p2:
3881 if opts.get('exact') or p2:
3882 # If you got here, you either use --force and know what
3882 # If you got here, you either use --force and know what
3883 # you are doing or used --exact or a merge patch while
3883 # you are doing or used --exact or a merge patch while
3884 # being updated to its first parent.
3884 # being updated to its first parent.
3885 m = None
3885 m = None
3886 else:
3886 else:
3887 m = scmutil.matchfiles(repo, files or [])
3887 m = scmutil.matchfiles(repo, files or [])
3888 n = repo.commit(message, opts.get('user') or user,
3888 n = repo.commit(message, opts.get('user') or user,
3889 opts.get('date') or date, match=m,
3889 opts.get('date') or date, match=m,
3890 editor=editor)
3890 editor=editor)
3891 checkexact(repo, n, nodeid)
3891 checkexact(repo, n, nodeid)
3892 else:
3892 else:
3893 if opts.get('exact') or opts.get('import_branch'):
3893 if opts.get('exact') or opts.get('import_branch'):
3894 branch = branch or 'default'
3894 branch = branch or 'default'
3895 else:
3895 else:
3896 branch = p1.branch()
3896 branch = p1.branch()
3897 store = patch.filestore()
3897 store = patch.filestore()
3898 try:
3898 try:
3899 files = set()
3899 files = set()
3900 try:
3900 try:
3901 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3901 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3902 files, eolmode=None)
3902 files, eolmode=None)
3903 except patch.PatchError, e:
3903 except patch.PatchError, e:
3904 raise util.Abort(str(e))
3904 raise util.Abort(str(e))
3905 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3905 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3906 message,
3906 message,
3907 opts.get('user') or user,
3907 opts.get('user') or user,
3908 opts.get('date') or date,
3908 opts.get('date') or date,
3909 branch, files, store,
3909 branch, files, store,
3910 editor=cmdutil.commiteditor)
3910 editor=cmdutil.commiteditor)
3911 repo.savecommitmessage(memctx.description())
3911 repo.savecommitmessage(memctx.description())
3912 n = memctx.commit()
3912 n = memctx.commit()
3913 checkexact(repo, n, nodeid)
3913 checkexact(repo, n, nodeid)
3914 finally:
3914 finally:
3915 store.close()
3915 store.close()
3916 if n:
3916 if n:
3917 # i18n: refers to a short changeset id
3917 # i18n: refers to a short changeset id
3918 msg = _('created %s') % short(n)
3918 msg = _('created %s') % short(n)
3919 return (msg, n)
3919 return (msg, n)
3920 finally:
3920 finally:
3921 os.unlink(tmpname)
3921 os.unlink(tmpname)
3922
3922
3923 try:
3923 try:
3924 try:
3924 try:
3925 wlock = repo.wlock()
3925 wlock = repo.wlock()
3926 if not opts.get('no_commit'):
3926 if not opts.get('no_commit'):
3927 lock = repo.lock()
3927 lock = repo.lock()
3928 tr = repo.transaction('import')
3928 tr = repo.transaction('import')
3929 parents = repo.parents()
3929 parents = repo.parents()
3930 for patchurl in patches:
3930 for patchurl in patches:
3931 if patchurl == '-':
3931 if patchurl == '-':
3932 ui.status(_('applying patch from stdin\n'))
3932 ui.status(_('applying patch from stdin\n'))
3933 patchfile = ui.fin
3933 patchfile = ui.fin
3934 patchurl = 'stdin' # for error message
3934 patchurl = 'stdin' # for error message
3935 else:
3935 else:
3936 patchurl = os.path.join(base, patchurl)
3936 patchurl = os.path.join(base, patchurl)
3937 ui.status(_('applying %s\n') % patchurl)
3937 ui.status(_('applying %s\n') % patchurl)
3938 patchfile = hg.openpath(ui, patchurl)
3938 patchfile = hg.openpath(ui, patchurl)
3939
3939
3940 haspatch = False
3940 haspatch = False
3941 for hunk in patch.split(patchfile):
3941 for hunk in patch.split(patchfile):
3942 (msg, node) = tryone(ui, hunk, parents)
3942 (msg, node) = tryone(ui, hunk, parents)
3943 if msg:
3943 if msg:
3944 haspatch = True
3944 haspatch = True
3945 ui.note(msg + '\n')
3945 ui.note(msg + '\n')
3946 if update or opts.get('exact'):
3946 if update or opts.get('exact'):
3947 parents = repo.parents()
3947 parents = repo.parents()
3948 else:
3948 else:
3949 parents = [repo[node]]
3949 parents = [repo[node]]
3950
3950
3951 if not haspatch:
3951 if not haspatch:
3952 raise util.Abort(_('%s: no diffs found') % patchurl)
3952 raise util.Abort(_('%s: no diffs found') % patchurl)
3953
3953
3954 if tr:
3954 if tr:
3955 tr.close()
3955 tr.close()
3956 if msgs:
3956 if msgs:
3957 repo.savecommitmessage('\n* * *\n'.join(msgs))
3957 repo.savecommitmessage('\n* * *\n'.join(msgs))
3958 except: # re-raises
3958 except: # re-raises
3959 # wlock.release() indirectly calls dirstate.write(): since
3959 # wlock.release() indirectly calls dirstate.write(): since
3960 # we're crashing, we do not want to change the working dir
3960 # we're crashing, we do not want to change the working dir
3961 # parent after all, so make sure it writes nothing
3961 # parent after all, so make sure it writes nothing
3962 repo.dirstate.invalidate()
3962 repo.dirstate.invalidate()
3963 raise
3963 raise
3964 finally:
3964 finally:
3965 if tr:
3965 if tr:
3966 tr.release()
3966 tr.release()
3967 release(lock, wlock)
3967 release(lock, wlock)
3968
3968
3969 @command('incoming|in',
3969 @command('incoming|in',
3970 [('f', 'force', None,
3970 [('f', 'force', None,
3971 _('run even if remote repository is unrelated')),
3971 _('run even if remote repository is unrelated')),
3972 ('n', 'newest-first', None, _('show newest record first')),
3972 ('n', 'newest-first', None, _('show newest record first')),
3973 ('', 'bundle', '',
3973 ('', 'bundle', '',
3974 _('file to store the bundles into'), _('FILE')),
3974 _('file to store the bundles into'), _('FILE')),
3975 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3975 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3976 ('B', 'bookmarks', False, _("compare bookmarks")),
3976 ('B', 'bookmarks', False, _("compare bookmarks")),
3977 ('b', 'branch', [],
3977 ('b', 'branch', [],
3978 _('a specific branch you would like to pull'), _('BRANCH')),
3978 _('a specific branch you would like to pull'), _('BRANCH')),
3979 ] + logopts + remoteopts + subrepoopts,
3979 ] + logopts + remoteopts + subrepoopts,
3980 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3980 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3981 def incoming(ui, repo, source="default", **opts):
3981 def incoming(ui, repo, source="default", **opts):
3982 """show new changesets found in source
3982 """show new changesets found in source
3983
3983
3984 Show new changesets found in the specified path/URL or the default
3984 Show new changesets found in the specified path/URL or the default
3985 pull location. These are the changesets that would have been pulled
3985 pull location. These are the changesets that would have been pulled
3986 if a pull at the time you issued this command.
3986 if a pull at the time you issued this command.
3987
3987
3988 For remote repository, using --bundle avoids downloading the
3988 For remote repository, using --bundle avoids downloading the
3989 changesets twice if the incoming is followed by a pull.
3989 changesets twice if the incoming is followed by a pull.
3990
3990
3991 See pull for valid source format details.
3991 See pull for valid source format details.
3992
3992
3993 Returns 0 if there are incoming changes, 1 otherwise.
3993 Returns 0 if there are incoming changes, 1 otherwise.
3994 """
3994 """
3995 if opts.get('graph'):
3995 if opts.get('graph'):
3996 cmdutil.checkunsupportedgraphflags([], opts)
3996 cmdutil.checkunsupportedgraphflags([], opts)
3997 def display(other, chlist, displayer):
3997 def display(other, chlist, displayer):
3998 revdag = cmdutil.graphrevs(other, chlist, opts)
3998 revdag = cmdutil.graphrevs(other, chlist, opts)
3999 showparents = [ctx.node() for ctx in repo[None].parents()]
3999 showparents = [ctx.node() for ctx in repo[None].parents()]
4000 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4000 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4001 graphmod.asciiedges)
4001 graphmod.asciiedges)
4002
4002
4003 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4003 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4004 return 0
4004 return 0
4005
4005
4006 if opts.get('bundle') and opts.get('subrepos'):
4006 if opts.get('bundle') and opts.get('subrepos'):
4007 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4007 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4008
4008
4009 if opts.get('bookmarks'):
4009 if opts.get('bookmarks'):
4010 source, branches = hg.parseurl(ui.expandpath(source),
4010 source, branches = hg.parseurl(ui.expandpath(source),
4011 opts.get('branch'))
4011 opts.get('branch'))
4012 other = hg.peer(repo, opts, source)
4012 other = hg.peer(repo, opts, source)
4013 if 'bookmarks' not in other.listkeys('namespaces'):
4013 if 'bookmarks' not in other.listkeys('namespaces'):
4014 ui.warn(_("remote doesn't support bookmarks\n"))
4014 ui.warn(_("remote doesn't support bookmarks\n"))
4015 return 0
4015 return 0
4016 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4016 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4017 return bookmarks.diff(ui, repo, other)
4017 return bookmarks.diff(ui, repo, other)
4018
4018
4019 repo._subtoppath = ui.expandpath(source)
4019 repo._subtoppath = ui.expandpath(source)
4020 try:
4020 try:
4021 return hg.incoming(ui, repo, source, opts)
4021 return hg.incoming(ui, repo, source, opts)
4022 finally:
4022 finally:
4023 del repo._subtoppath
4023 del repo._subtoppath
4024
4024
4025
4025
4026 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
4026 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
4027 def init(ui, dest=".", **opts):
4027 def init(ui, dest=".", **opts):
4028 """create a new repository in the given directory
4028 """create a new repository in the given directory
4029
4029
4030 Initialize a new repository in the given directory. If the given
4030 Initialize a new repository in the given directory. If the given
4031 directory does not exist, it will be created.
4031 directory does not exist, it will be created.
4032
4032
4033 If no directory is given, the current directory is used.
4033 If no directory is given, the current directory is used.
4034
4034
4035 It is possible to specify an ``ssh://`` URL as the destination.
4035 It is possible to specify an ``ssh://`` URL as the destination.
4036 See :hg:`help urls` for more information.
4036 See :hg:`help urls` for more information.
4037
4037
4038 Returns 0 on success.
4038 Returns 0 on success.
4039 """
4039 """
4040 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4040 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4041
4041
4042 @command('locate',
4042 @command('locate',
4043 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4043 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4044 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4044 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4045 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4045 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4046 ] + walkopts,
4046 ] + walkopts,
4047 _('[OPTION]... [PATTERN]...'))
4047 _('[OPTION]... [PATTERN]...'))
4048 def locate(ui, repo, *pats, **opts):
4048 def locate(ui, repo, *pats, **opts):
4049 """locate files matching specific patterns
4049 """locate files matching specific patterns
4050
4050
4051 Print files under Mercurial control in the working directory whose
4051 Print files under Mercurial control in the working directory whose
4052 names match the given patterns.
4052 names match the given patterns.
4053
4053
4054 By default, this command searches all directories in the working
4054 By default, this command searches all directories in the working
4055 directory. To search just the current directory and its
4055 directory. To search just the current directory and its
4056 subdirectories, use "--include .".
4056 subdirectories, use "--include .".
4057
4057
4058 If no patterns are given to match, this command prints the names
4058 If no patterns are given to match, this command prints the names
4059 of all files under Mercurial control in the working directory.
4059 of all files under Mercurial control in the working directory.
4060
4060
4061 If you want to feed the output of this command into the "xargs"
4061 If you want to feed the output of this command into the "xargs"
4062 command, use the -0 option to both this command and "xargs". This
4062 command, use the -0 option to both this command and "xargs". This
4063 will avoid the problem of "xargs" treating single filenames that
4063 will avoid the problem of "xargs" treating single filenames that
4064 contain whitespace as multiple filenames.
4064 contain whitespace as multiple filenames.
4065
4065
4066 Returns 0 if a match is found, 1 otherwise.
4066 Returns 0 if a match is found, 1 otherwise.
4067 """
4067 """
4068 end = opts.get('print0') and '\0' or '\n'
4068 end = opts.get('print0') and '\0' or '\n'
4069 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4069 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4070
4070
4071 ret = 1
4071 ret = 1
4072 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4072 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4073 m.bad = lambda x, y: False
4073 m.bad = lambda x, y: False
4074 for abs in repo[rev].walk(m):
4074 for abs in repo[rev].walk(m):
4075 if not rev and abs not in repo.dirstate:
4075 if not rev and abs not in repo.dirstate:
4076 continue
4076 continue
4077 if opts.get('fullpath'):
4077 if opts.get('fullpath'):
4078 ui.write(repo.wjoin(abs), end)
4078 ui.write(repo.wjoin(abs), end)
4079 else:
4079 else:
4080 ui.write(((pats and m.rel(abs)) or abs), end)
4080 ui.write(((pats and m.rel(abs)) or abs), end)
4081 ret = 0
4081 ret = 0
4082
4082
4083 return ret
4083 return ret
4084
4084
4085 @command('^log|history',
4085 @command('^log|history',
4086 [('f', 'follow', None,
4086 [('f', 'follow', None,
4087 _('follow changeset history, or file history across copies and renames')),
4087 _('follow changeset history, or file history across copies and renames')),
4088 ('', 'follow-first', None,
4088 ('', 'follow-first', None,
4089 _('only follow the first parent of merge changesets (DEPRECATED)')),
4089 _('only follow the first parent of merge changesets (DEPRECATED)')),
4090 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4090 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4091 ('C', 'copies', None, _('show copied files')),
4091 ('C', 'copies', None, _('show copied files')),
4092 ('k', 'keyword', [],
4092 ('k', 'keyword', [],
4093 _('do case-insensitive search for a given text'), _('TEXT')),
4093 _('do case-insensitive search for a given text'), _('TEXT')),
4094 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4094 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4095 ('', 'removed', None, _('include revisions where files were removed')),
4095 ('', 'removed', None, _('include revisions where files were removed')),
4096 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4096 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4097 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4097 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4098 ('', 'only-branch', [],
4098 ('', 'only-branch', [],
4099 _('show only changesets within the given named branch (DEPRECATED)'),
4099 _('show only changesets within the given named branch (DEPRECATED)'),
4100 _('BRANCH')),
4100 _('BRANCH')),
4101 ('b', 'branch', [],
4101 ('b', 'branch', [],
4102 _('show changesets within the given named branch'), _('BRANCH')),
4102 _('show changesets within the given named branch'), _('BRANCH')),
4103 ('P', 'prune', [],
4103 ('P', 'prune', [],
4104 _('do not display revision or any of its ancestors'), _('REV')),
4104 _('do not display revision or any of its ancestors'), _('REV')),
4105 ] + logopts + walkopts,
4105 ] + logopts + walkopts,
4106 _('[OPTION]... [FILE]'))
4106 _('[OPTION]... [FILE]'))
4107 def log(ui, repo, *pats, **opts):
4107 def log(ui, repo, *pats, **opts):
4108 """show revision history of entire repository or files
4108 """show revision history of entire repository or files
4109
4109
4110 Print the revision history of the specified files or the entire
4110 Print the revision history of the specified files or the entire
4111 project.
4111 project.
4112
4112
4113 If no revision range is specified, the default is ``tip:0`` unless
4113 If no revision range is specified, the default is ``tip:0`` unless
4114 --follow is set, in which case the working directory parent is
4114 --follow is set, in which case the working directory parent is
4115 used as the starting revision.
4115 used as the starting revision.
4116
4116
4117 File history is shown without following rename or copy history of
4117 File history is shown without following rename or copy history of
4118 files. Use -f/--follow with a filename to follow history across
4118 files. Use -f/--follow with a filename to follow history across
4119 renames and copies. --follow without a filename will only show
4119 renames and copies. --follow without a filename will only show
4120 ancestors or descendants of the starting revision.
4120 ancestors or descendants of the starting revision.
4121
4121
4122 By default this command prints revision number and changeset id,
4122 By default this command prints revision number and changeset id,
4123 tags, non-trivial parents, user, date and time, and a summary for
4123 tags, non-trivial parents, user, date and time, and a summary for
4124 each commit. When the -v/--verbose switch is used, the list of
4124 each commit. When the -v/--verbose switch is used, the list of
4125 changed files and full commit message are shown.
4125 changed files and full commit message are shown.
4126
4126
4127 .. note::
4127 .. note::
4128 log -p/--patch may generate unexpected diff output for merge
4128 log -p/--patch may generate unexpected diff output for merge
4129 changesets, as it will only compare the merge changeset against
4129 changesets, as it will only compare the merge changeset against
4130 its first parent. Also, only files different from BOTH parents
4130 its first parent. Also, only files different from BOTH parents
4131 will appear in files:.
4131 will appear in files:.
4132
4132
4133 .. note::
4133 .. note::
4134 for performance reasons, log FILE may omit duplicate changes
4134 for performance reasons, log FILE may omit duplicate changes
4135 made on branches and will not show deletions. To see all
4135 made on branches and will not show deletions. To see all
4136 changes including duplicates and deletions, use the --removed
4136 changes including duplicates and deletions, use the --removed
4137 switch.
4137 switch.
4138
4138
4139 .. container:: verbose
4139 .. container:: verbose
4140
4140
4141 Some examples:
4141 Some examples:
4142
4142
4143 - changesets with full descriptions and file lists::
4143 - changesets with full descriptions and file lists::
4144
4144
4145 hg log -v
4145 hg log -v
4146
4146
4147 - changesets ancestral to the working directory::
4147 - changesets ancestral to the working directory::
4148
4148
4149 hg log -f
4149 hg log -f
4150
4150
4151 - last 10 commits on the current branch::
4151 - last 10 commits on the current branch::
4152
4152
4153 hg log -l 10 -b .
4153 hg log -l 10 -b .
4154
4154
4155 - changesets showing all modifications of a file, including removals::
4155 - changesets showing all modifications of a file, including removals::
4156
4156
4157 hg log --removed file.c
4157 hg log --removed file.c
4158
4158
4159 - all changesets that touch a directory, with diffs, excluding merges::
4159 - all changesets that touch a directory, with diffs, excluding merges::
4160
4160
4161 hg log -Mp lib/
4161 hg log -Mp lib/
4162
4162
4163 - all revision numbers that match a keyword::
4163 - all revision numbers that match a keyword::
4164
4164
4165 hg log -k bug --template "{rev}\\n"
4165 hg log -k bug --template "{rev}\\n"
4166
4166
4167 - check if a given changeset is included is a tagged release::
4167 - check if a given changeset is included is a tagged release::
4168
4168
4169 hg log -r "a21ccf and ancestor(1.9)"
4169 hg log -r "a21ccf and ancestor(1.9)"
4170
4170
4171 - find all changesets by some user in a date range::
4171 - find all changesets by some user in a date range::
4172
4172
4173 hg log -k alice -d "may 2008 to jul 2008"
4173 hg log -k alice -d "may 2008 to jul 2008"
4174
4174
4175 - summary of all changesets after the last tag::
4175 - summary of all changesets after the last tag::
4176
4176
4177 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4177 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4178
4178
4179 See :hg:`help dates` for a list of formats valid for -d/--date.
4179 See :hg:`help dates` for a list of formats valid for -d/--date.
4180
4180
4181 See :hg:`help revisions` and :hg:`help revsets` for more about
4181 See :hg:`help revisions` and :hg:`help revsets` for more about
4182 specifying revisions.
4182 specifying revisions.
4183
4183
4184 See :hg:`help templates` for more about pre-packaged styles and
4184 See :hg:`help templates` for more about pre-packaged styles and
4185 specifying custom templates.
4185 specifying custom templates.
4186
4186
4187 Returns 0 on success.
4187 Returns 0 on success.
4188 """
4188 """
4189 if opts.get('graph'):
4189 if opts.get('graph'):
4190 return cmdutil.graphlog(ui, repo, *pats, **opts)
4190 return cmdutil.graphlog(ui, repo, *pats, **opts)
4191
4191
4192 matchfn = scmutil.match(repo[None], pats, opts)
4192 matchfn = scmutil.match(repo[None], pats, opts)
4193 limit = cmdutil.loglimit(opts)
4193 limit = cmdutil.loglimit(opts)
4194 count = 0
4194 count = 0
4195
4195
4196 getrenamed, endrev = None, None
4196 getrenamed, endrev = None, None
4197 if opts.get('copies'):
4197 if opts.get('copies'):
4198 if opts.get('rev'):
4198 if opts.get('rev'):
4199 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4199 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4200 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4200 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4201
4201
4202 df = False
4202 df = False
4203 if opts.get("date"):
4203 if opts.get("date"):
4204 df = util.matchdate(opts["date"])
4204 df = util.matchdate(opts["date"])
4205
4205
4206 branches = opts.get('branch', []) + opts.get('only_branch', [])
4206 branches = opts.get('branch', []) + opts.get('only_branch', [])
4207 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4207 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4208
4208
4209 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4209 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4210 def prep(ctx, fns):
4210 def prep(ctx, fns):
4211 rev = ctx.rev()
4211 rev = ctx.rev()
4212 parents = [p for p in repo.changelog.parentrevs(rev)
4212 parents = [p for p in repo.changelog.parentrevs(rev)
4213 if p != nullrev]
4213 if p != nullrev]
4214 if opts.get('no_merges') and len(parents) == 2:
4214 if opts.get('no_merges') and len(parents) == 2:
4215 return
4215 return
4216 if opts.get('only_merges') and len(parents) != 2:
4216 if opts.get('only_merges') and len(parents) != 2:
4217 return
4217 return
4218 if opts.get('branch') and ctx.branch() not in opts['branch']:
4218 if opts.get('branch') and ctx.branch() not in opts['branch']:
4219 return
4219 return
4220 if df and not df(ctx.date()[0]):
4220 if df and not df(ctx.date()[0]):
4221 return
4221 return
4222
4222
4223 lower = encoding.lower
4223 lower = encoding.lower
4224 if opts.get('user'):
4224 if opts.get('user'):
4225 luser = lower(ctx.user())
4225 luser = lower(ctx.user())
4226 for k in [lower(x) for x in opts['user']]:
4226 for k in [lower(x) for x in opts['user']]:
4227 if (k in luser):
4227 if (k in luser):
4228 break
4228 break
4229 else:
4229 else:
4230 return
4230 return
4231 if opts.get('keyword'):
4231 if opts.get('keyword'):
4232 luser = lower(ctx.user())
4232 luser = lower(ctx.user())
4233 ldesc = lower(ctx.description())
4233 ldesc = lower(ctx.description())
4234 lfiles = lower(" ".join(ctx.files()))
4234 lfiles = lower(" ".join(ctx.files()))
4235 for k in [lower(x) for x in opts['keyword']]:
4235 for k in [lower(x) for x in opts['keyword']]:
4236 if (k in luser or k in ldesc or k in lfiles):
4236 if (k in luser or k in ldesc or k in lfiles):
4237 break
4237 break
4238 else:
4238 else:
4239 return
4239 return
4240
4240
4241 copies = None
4241 copies = None
4242 if getrenamed is not None and rev:
4242 if getrenamed is not None and rev:
4243 copies = []
4243 copies = []
4244 for fn in ctx.files():
4244 for fn in ctx.files():
4245 rename = getrenamed(fn, rev)
4245 rename = getrenamed(fn, rev)
4246 if rename:
4246 if rename:
4247 copies.append((fn, rename[0]))
4247 copies.append((fn, rename[0]))
4248
4248
4249 revmatchfn = None
4249 revmatchfn = None
4250 if opts.get('patch') or opts.get('stat'):
4250 if opts.get('patch') or opts.get('stat'):
4251 if opts.get('follow') or opts.get('follow_first'):
4251 if opts.get('follow') or opts.get('follow_first'):
4252 # note: this might be wrong when following through merges
4252 # note: this might be wrong when following through merges
4253 revmatchfn = scmutil.match(repo[None], fns, default='path')
4253 revmatchfn = scmutil.match(repo[None], fns, default='path')
4254 else:
4254 else:
4255 revmatchfn = matchfn
4255 revmatchfn = matchfn
4256
4256
4257 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4257 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4258
4258
4259 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4259 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4260 if count == limit:
4260 if count == limit:
4261 break
4261 break
4262 if displayer.flush(ctx.rev()):
4262 if displayer.flush(ctx.rev()):
4263 count += 1
4263 count += 1
4264 displayer.close()
4264 displayer.close()
4265
4265
4266 @command('manifest',
4266 @command('manifest',
4267 [('r', 'rev', '', _('revision to display'), _('REV')),
4267 [('r', 'rev', '', _('revision to display'), _('REV')),
4268 ('', 'all', False, _("list files from all revisions"))],
4268 ('', 'all', False, _("list files from all revisions"))],
4269 _('[-r REV]'))
4269 _('[-r REV]'))
4270 def manifest(ui, repo, node=None, rev=None, **opts):
4270 def manifest(ui, repo, node=None, rev=None, **opts):
4271 """output the current or given revision of the project manifest
4271 """output the current or given revision of the project manifest
4272
4272
4273 Print a list of version controlled files for the given revision.
4273 Print a list of version controlled files for the given revision.
4274 If no revision is given, the first parent of the working directory
4274 If no revision is given, the first parent of the working directory
4275 is used, or the null revision if no revision is checked out.
4275 is used, or the null revision if no revision is checked out.
4276
4276
4277 With -v, print file permissions, symlink and executable bits.
4277 With -v, print file permissions, symlink and executable bits.
4278 With --debug, print file revision hashes.
4278 With --debug, print file revision hashes.
4279
4279
4280 If option --all is specified, the list of all files from all revisions
4280 If option --all is specified, the list of all files from all revisions
4281 is printed. This includes deleted and renamed files.
4281 is printed. This includes deleted and renamed files.
4282
4282
4283 Returns 0 on success.
4283 Returns 0 on success.
4284 """
4284 """
4285
4285
4286 fm = ui.formatter('manifest', opts)
4286 fm = ui.formatter('manifest', opts)
4287
4287
4288 if opts.get('all'):
4288 if opts.get('all'):
4289 if rev or node:
4289 if rev or node:
4290 raise util.Abort(_("can't specify a revision with --all"))
4290 raise util.Abort(_("can't specify a revision with --all"))
4291
4291
4292 res = []
4292 res = []
4293 prefix = "data/"
4293 prefix = "data/"
4294 suffix = ".i"
4294 suffix = ".i"
4295 plen = len(prefix)
4295 plen = len(prefix)
4296 slen = len(suffix)
4296 slen = len(suffix)
4297 lock = repo.lock()
4297 lock = repo.lock()
4298 try:
4298 try:
4299 for fn, b, size in repo.store.datafiles():
4299 for fn, b, size in repo.store.datafiles():
4300 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4300 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4301 res.append(fn[plen:-slen])
4301 res.append(fn[plen:-slen])
4302 finally:
4302 finally:
4303 lock.release()
4303 lock.release()
4304 for f in res:
4304 for f in res:
4305 fm.startitem()
4305 fm.startitem()
4306 fm.write("path", '%s\n', f)
4306 fm.write("path", '%s\n', f)
4307 fm.end()
4307 fm.end()
4308 return
4308 return
4309
4309
4310 if rev and node:
4310 if rev and node:
4311 raise util.Abort(_("please specify just one revision"))
4311 raise util.Abort(_("please specify just one revision"))
4312
4312
4313 if not node:
4313 if not node:
4314 node = rev
4314 node = rev
4315
4315
4316 char = {'l': '@', 'x': '*', '': ''}
4316 char = {'l': '@', 'x': '*', '': ''}
4317 mode = {'l': '644', 'x': '755', '': '644'}
4317 mode = {'l': '644', 'x': '755', '': '644'}
4318 ctx = scmutil.revsingle(repo, node)
4318 ctx = scmutil.revsingle(repo, node)
4319 mf = ctx.manifest()
4319 mf = ctx.manifest()
4320 for f in ctx:
4320 for f in ctx:
4321 fm.startitem()
4321 fm.startitem()
4322 fl = ctx[f].flags()
4322 fl = ctx[f].flags()
4323 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4323 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4324 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4324 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4325 fm.write('path', '%s\n', f)
4325 fm.write('path', '%s\n', f)
4326 fm.end()
4326 fm.end()
4327
4327
4328 @command('^merge',
4328 @command('^merge',
4329 [('f', 'force', None, _('force a merge with outstanding changes')),
4329 [('f', 'force', None, _('force a merge with outstanding changes')),
4330 ('r', 'rev', '', _('revision to merge'), _('REV')),
4330 ('r', 'rev', '', _('revision to merge'), _('REV')),
4331 ('P', 'preview', None,
4331 ('P', 'preview', None,
4332 _('review revisions to merge (no merge is performed)'))
4332 _('review revisions to merge (no merge is performed)'))
4333 ] + mergetoolopts,
4333 ] + mergetoolopts,
4334 _('[-P] [-f] [[-r] REV]'))
4334 _('[-P] [-f] [[-r] REV]'))
4335 def merge(ui, repo, node=None, **opts):
4335 def merge(ui, repo, node=None, **opts):
4336 """merge working directory with another revision
4336 """merge working directory with another revision
4337
4337
4338 The current working directory is updated with all changes made in
4338 The current working directory is updated with all changes made in
4339 the requested revision since the last common predecessor revision.
4339 the requested revision since the last common predecessor revision.
4340
4340
4341 Files that changed between either parent are marked as changed for
4341 Files that changed between either parent are marked as changed for
4342 the next commit and a commit must be performed before any further
4342 the next commit and a commit must be performed before any further
4343 updates to the repository are allowed. The next commit will have
4343 updates to the repository are allowed. The next commit will have
4344 two parents.
4344 two parents.
4345
4345
4346 ``--tool`` can be used to specify the merge tool used for file
4346 ``--tool`` can be used to specify the merge tool used for file
4347 merges. It overrides the HGMERGE environment variable and your
4347 merges. It overrides the HGMERGE environment variable and your
4348 configuration files. See :hg:`help merge-tools` for options.
4348 configuration files. See :hg:`help merge-tools` for options.
4349
4349
4350 If no revision is specified, the working directory's parent is a
4350 If no revision is specified, the working directory's parent is a
4351 head revision, and the current branch contains exactly one other
4351 head revision, and the current branch contains exactly one other
4352 head, the other head is merged with by default. Otherwise, an
4352 head, the other head is merged with by default. Otherwise, an
4353 explicit revision with which to merge with must be provided.
4353 explicit revision with which to merge with must be provided.
4354
4354
4355 :hg:`resolve` must be used to resolve unresolved files.
4355 :hg:`resolve` must be used to resolve unresolved files.
4356
4356
4357 To undo an uncommitted merge, use :hg:`update --clean .` which
4357 To undo an uncommitted merge, use :hg:`update --clean .` which
4358 will check out a clean copy of the original merge parent, losing
4358 will check out a clean copy of the original merge parent, losing
4359 all changes.
4359 all changes.
4360
4360
4361 Returns 0 on success, 1 if there are unresolved files.
4361 Returns 0 on success, 1 if there are unresolved files.
4362 """
4362 """
4363
4363
4364 if opts.get('rev') and node:
4364 if opts.get('rev') and node:
4365 raise util.Abort(_("please specify just one revision"))
4365 raise util.Abort(_("please specify just one revision"))
4366 if not node:
4366 if not node:
4367 node = opts.get('rev')
4367 node = opts.get('rev')
4368
4368
4369 if node:
4369 if node:
4370 node = scmutil.revsingle(repo, node).node()
4370 node = scmutil.revsingle(repo, node).node()
4371
4371
4372 if not node and repo._bookmarkcurrent:
4372 if not node and repo._bookmarkcurrent:
4373 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4373 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4374 curhead = repo[repo._bookmarkcurrent].node()
4374 curhead = repo[repo._bookmarkcurrent].node()
4375 if len(bmheads) == 2:
4375 if len(bmheads) == 2:
4376 if curhead == bmheads[0]:
4376 if curhead == bmheads[0]:
4377 node = bmheads[1]
4377 node = bmheads[1]
4378 else:
4378 else:
4379 node = bmheads[0]
4379 node = bmheads[0]
4380 elif len(bmheads) > 2:
4380 elif len(bmheads) > 2:
4381 raise util.Abort(_("multiple matching bookmarks to merge - "
4381 raise util.Abort(_("multiple matching bookmarks to merge - "
4382 "please merge with an explicit rev or bookmark"),
4382 "please merge with an explicit rev or bookmark"),
4383 hint=_("run 'hg heads' to see all heads"))
4383 hint=_("run 'hg heads' to see all heads"))
4384 elif len(bmheads) <= 1:
4384 elif len(bmheads) <= 1:
4385 raise util.Abort(_("no matching bookmark to merge - "
4385 raise util.Abort(_("no matching bookmark to merge - "
4386 "please merge with an explicit rev or bookmark"),
4386 "please merge with an explicit rev or bookmark"),
4387 hint=_("run 'hg heads' to see all heads"))
4387 hint=_("run 'hg heads' to see all heads"))
4388
4388
4389 if not node and not repo._bookmarkcurrent:
4389 if not node and not repo._bookmarkcurrent:
4390 branch = repo[None].branch()
4390 branch = repo[None].branch()
4391 bheads = repo.branchheads(branch)
4391 bheads = repo.branchheads(branch)
4392 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4392 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4393
4393
4394 if len(nbhs) > 2:
4394 if len(nbhs) > 2:
4395 raise util.Abort(_("branch '%s' has %d heads - "
4395 raise util.Abort(_("branch '%s' has %d heads - "
4396 "please merge with an explicit rev")
4396 "please merge with an explicit rev")
4397 % (branch, len(bheads)),
4397 % (branch, len(bheads)),
4398 hint=_("run 'hg heads .' to see heads"))
4398 hint=_("run 'hg heads .' to see heads"))
4399
4399
4400 parent = repo.dirstate.p1()
4400 parent = repo.dirstate.p1()
4401 if len(nbhs) <= 1:
4401 if len(nbhs) <= 1:
4402 if len(bheads) > 1:
4402 if len(bheads) > 1:
4403 raise util.Abort(_("heads are bookmarked - "
4403 raise util.Abort(_("heads are bookmarked - "
4404 "please merge with an explicit rev"),
4404 "please merge with an explicit rev"),
4405 hint=_("run 'hg heads' to see all heads"))
4405 hint=_("run 'hg heads' to see all heads"))
4406 if len(repo.heads()) > 1:
4406 if len(repo.heads()) > 1:
4407 raise util.Abort(_("branch '%s' has one head - "
4407 raise util.Abort(_("branch '%s' has one head - "
4408 "please merge with an explicit rev")
4408 "please merge with an explicit rev")
4409 % branch,
4409 % branch,
4410 hint=_("run 'hg heads' to see all heads"))
4410 hint=_("run 'hg heads' to see all heads"))
4411 msg, hint = _('nothing to merge'), None
4411 msg, hint = _('nothing to merge'), None
4412 if parent != repo.lookup(branch):
4412 if parent != repo.lookup(branch):
4413 hint = _("use 'hg update' instead")
4413 hint = _("use 'hg update' instead")
4414 raise util.Abort(msg, hint=hint)
4414 raise util.Abort(msg, hint=hint)
4415
4415
4416 if parent not in bheads:
4416 if parent not in bheads:
4417 raise util.Abort(_('working directory not at a head revision'),
4417 raise util.Abort(_('working directory not at a head revision'),
4418 hint=_("use 'hg update' or merge with an "
4418 hint=_("use 'hg update' or merge with an "
4419 "explicit revision"))
4419 "explicit revision"))
4420 if parent == nbhs[0]:
4420 if parent == nbhs[0]:
4421 node = nbhs[-1]
4421 node = nbhs[-1]
4422 else:
4422 else:
4423 node = nbhs[0]
4423 node = nbhs[0]
4424
4424
4425 if opts.get('preview'):
4425 if opts.get('preview'):
4426 # find nodes that are ancestors of p2 but not of p1
4426 # find nodes that are ancestors of p2 but not of p1
4427 p1 = repo.lookup('.')
4427 p1 = repo.lookup('.')
4428 p2 = repo.lookup(node)
4428 p2 = repo.lookup(node)
4429 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4429 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4430
4430
4431 displayer = cmdutil.show_changeset(ui, repo, opts)
4431 displayer = cmdutil.show_changeset(ui, repo, opts)
4432 for node in nodes:
4432 for node in nodes:
4433 displayer.show(repo[node])
4433 displayer.show(repo[node])
4434 displayer.close()
4434 displayer.close()
4435 return 0
4435 return 0
4436
4436
4437 try:
4437 try:
4438 # ui.forcemerge is an internal variable, do not document
4438 # ui.forcemerge is an internal variable, do not document
4439 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4439 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4440 return hg.merge(repo, node, force=opts.get('force'))
4440 return hg.merge(repo, node, force=opts.get('force'))
4441 finally:
4441 finally:
4442 ui.setconfig('ui', 'forcemerge', '')
4442 ui.setconfig('ui', 'forcemerge', '')
4443
4443
4444 @command('outgoing|out',
4444 @command('outgoing|out',
4445 [('f', 'force', None, _('run even when the destination is unrelated')),
4445 [('f', 'force', None, _('run even when the destination is unrelated')),
4446 ('r', 'rev', [],
4446 ('r', 'rev', [],
4447 _('a changeset intended to be included in the destination'), _('REV')),
4447 _('a changeset intended to be included in the destination'), _('REV')),
4448 ('n', 'newest-first', None, _('show newest record first')),
4448 ('n', 'newest-first', None, _('show newest record first')),
4449 ('B', 'bookmarks', False, _('compare bookmarks')),
4449 ('B', 'bookmarks', False, _('compare bookmarks')),
4450 ('b', 'branch', [], _('a specific branch you would like to push'),
4450 ('b', 'branch', [], _('a specific branch you would like to push'),
4451 _('BRANCH')),
4451 _('BRANCH')),
4452 ] + logopts + remoteopts + subrepoopts,
4452 ] + logopts + remoteopts + subrepoopts,
4453 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4453 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4454 def outgoing(ui, repo, dest=None, **opts):
4454 def outgoing(ui, repo, dest=None, **opts):
4455 """show changesets not found in the destination
4455 """show changesets not found in the destination
4456
4456
4457 Show changesets not found in the specified destination repository
4457 Show changesets not found in the specified destination repository
4458 or the default push location. These are the changesets that would
4458 or the default push location. These are the changesets that would
4459 be pushed if a push was requested.
4459 be pushed if a push was requested.
4460
4460
4461 See pull for details of valid destination formats.
4461 See pull for details of valid destination formats.
4462
4462
4463 Returns 0 if there are outgoing changes, 1 otherwise.
4463 Returns 0 if there are outgoing changes, 1 otherwise.
4464 """
4464 """
4465 if opts.get('graph'):
4465 if opts.get('graph'):
4466 cmdutil.checkunsupportedgraphflags([], opts)
4466 cmdutil.checkunsupportedgraphflags([], opts)
4467 o = hg._outgoing(ui, repo, dest, opts)
4467 o = hg._outgoing(ui, repo, dest, opts)
4468 if o is None:
4468 if o is None:
4469 return
4469 return
4470
4470
4471 revdag = cmdutil.graphrevs(repo, o, opts)
4471 revdag = cmdutil.graphrevs(repo, o, opts)
4472 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4472 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4473 showparents = [ctx.node() for ctx in repo[None].parents()]
4473 showparents = [ctx.node() for ctx in repo[None].parents()]
4474 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4474 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4475 graphmod.asciiedges)
4475 graphmod.asciiedges)
4476 return 0
4476 return 0
4477
4477
4478 if opts.get('bookmarks'):
4478 if opts.get('bookmarks'):
4479 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4479 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4480 dest, branches = hg.parseurl(dest, opts.get('branch'))
4480 dest, branches = hg.parseurl(dest, opts.get('branch'))
4481 other = hg.peer(repo, opts, dest)
4481 other = hg.peer(repo, opts, dest)
4482 if 'bookmarks' not in other.listkeys('namespaces'):
4482 if 'bookmarks' not in other.listkeys('namespaces'):
4483 ui.warn(_("remote doesn't support bookmarks\n"))
4483 ui.warn(_("remote doesn't support bookmarks\n"))
4484 return 0
4484 return 0
4485 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4485 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4486 return bookmarks.diff(ui, other, repo)
4486 return bookmarks.diff(ui, other, repo)
4487
4487
4488 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4488 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4489 try:
4489 try:
4490 return hg.outgoing(ui, repo, dest, opts)
4490 return hg.outgoing(ui, repo, dest, opts)
4491 finally:
4491 finally:
4492 del repo._subtoppath
4492 del repo._subtoppath
4493
4493
4494 @command('parents',
4494 @command('parents',
4495 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4495 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4496 ] + templateopts,
4496 ] + templateopts,
4497 _('[-r REV] [FILE]'))
4497 _('[-r REV] [FILE]'))
4498 def parents(ui, repo, file_=None, **opts):
4498 def parents(ui, repo, file_=None, **opts):
4499 """show the parents of the working directory or revision
4499 """show the parents of the working directory or revision
4500
4500
4501 Print the working directory's parent revisions. If a revision is
4501 Print the working directory's parent revisions. If a revision is
4502 given via -r/--rev, the parent of that revision will be printed.
4502 given via -r/--rev, the parent of that revision will be printed.
4503 If a file argument is given, the revision in which the file was
4503 If a file argument is given, the revision in which the file was
4504 last changed (before the working directory revision or the
4504 last changed (before the working directory revision or the
4505 argument to --rev if given) is printed.
4505 argument to --rev if given) is printed.
4506
4506
4507 Returns 0 on success.
4507 Returns 0 on success.
4508 """
4508 """
4509
4509
4510 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4510 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4511
4511
4512 if file_:
4512 if file_:
4513 m = scmutil.match(ctx, (file_,), opts)
4513 m = scmutil.match(ctx, (file_,), opts)
4514 if m.anypats() or len(m.files()) != 1:
4514 if m.anypats() or len(m.files()) != 1:
4515 raise util.Abort(_('can only specify an explicit filename'))
4515 raise util.Abort(_('can only specify an explicit filename'))
4516 file_ = m.files()[0]
4516 file_ = m.files()[0]
4517 filenodes = []
4517 filenodes = []
4518 for cp in ctx.parents():
4518 for cp in ctx.parents():
4519 if not cp:
4519 if not cp:
4520 continue
4520 continue
4521 try:
4521 try:
4522 filenodes.append(cp.filenode(file_))
4522 filenodes.append(cp.filenode(file_))
4523 except error.LookupError:
4523 except error.LookupError:
4524 pass
4524 pass
4525 if not filenodes:
4525 if not filenodes:
4526 raise util.Abort(_("'%s' not found in manifest!") % file_)
4526 raise util.Abort(_("'%s' not found in manifest!") % file_)
4527 fl = repo.file(file_)
4527 fl = repo.file(file_)
4528 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4528 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4529 else:
4529 else:
4530 p = [cp.node() for cp in ctx.parents()]
4530 p = [cp.node() for cp in ctx.parents()]
4531
4531
4532 displayer = cmdutil.show_changeset(ui, repo, opts)
4532 displayer = cmdutil.show_changeset(ui, repo, opts)
4533 for n in p:
4533 for n in p:
4534 if n != nullid:
4534 if n != nullid:
4535 displayer.show(repo[n])
4535 displayer.show(repo[n])
4536 displayer.close()
4536 displayer.close()
4537
4537
4538 @command('paths', [], _('[NAME]'))
4538 @command('paths', [], _('[NAME]'))
4539 def paths(ui, repo, search=None):
4539 def paths(ui, repo, search=None):
4540 """show aliases for remote repositories
4540 """show aliases for remote repositories
4541
4541
4542 Show definition of symbolic path name NAME. If no name is given,
4542 Show definition of symbolic path name NAME. If no name is given,
4543 show definition of all available names.
4543 show definition of all available names.
4544
4544
4545 Option -q/--quiet suppresses all output when searching for NAME
4545 Option -q/--quiet suppresses all output when searching for NAME
4546 and shows only the path names when listing all definitions.
4546 and shows only the path names when listing all definitions.
4547
4547
4548 Path names are defined in the [paths] section of your
4548 Path names are defined in the [paths] section of your
4549 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4549 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4550 repository, ``.hg/hgrc`` is used, too.
4550 repository, ``.hg/hgrc`` is used, too.
4551
4551
4552 The path names ``default`` and ``default-push`` have a special
4552 The path names ``default`` and ``default-push`` have a special
4553 meaning. When performing a push or pull operation, they are used
4553 meaning. When performing a push or pull operation, they are used
4554 as fallbacks if no location is specified on the command-line.
4554 as fallbacks if no location is specified on the command-line.
4555 When ``default-push`` is set, it will be used for push and
4555 When ``default-push`` is set, it will be used for push and
4556 ``default`` will be used for pull; otherwise ``default`` is used
4556 ``default`` will be used for pull; otherwise ``default`` is used
4557 as the fallback for both. When cloning a repository, the clone
4557 as the fallback for both. When cloning a repository, the clone
4558 source is written as ``default`` in ``.hg/hgrc``. Note that
4558 source is written as ``default`` in ``.hg/hgrc``. Note that
4559 ``default`` and ``default-push`` apply to all inbound (e.g.
4559 ``default`` and ``default-push`` apply to all inbound (e.g.
4560 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4560 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4561 :hg:`bundle`) operations.
4561 :hg:`bundle`) operations.
4562
4562
4563 See :hg:`help urls` for more information.
4563 See :hg:`help urls` for more information.
4564
4564
4565 Returns 0 on success.
4565 Returns 0 on success.
4566 """
4566 """
4567 if search:
4567 if search:
4568 for name, path in ui.configitems("paths"):
4568 for name, path in ui.configitems("paths"):
4569 if name == search:
4569 if name == search:
4570 ui.status("%s\n" % util.hidepassword(path))
4570 ui.status("%s\n" % util.hidepassword(path))
4571 return
4571 return
4572 if not ui.quiet:
4572 if not ui.quiet:
4573 ui.warn(_("not found!\n"))
4573 ui.warn(_("not found!\n"))
4574 return 1
4574 return 1
4575 else:
4575 else:
4576 for name, path in ui.configitems("paths"):
4576 for name, path in ui.configitems("paths"):
4577 if ui.quiet:
4577 if ui.quiet:
4578 ui.write("%s\n" % name)
4578 ui.write("%s\n" % name)
4579 else:
4579 else:
4580 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4580 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4581
4581
4582 @command('phase',
4582 @command('phase',
4583 [('p', 'public', False, _('set changeset phase to public')),
4583 [('p', 'public', False, _('set changeset phase to public')),
4584 ('d', 'draft', False, _('set changeset phase to draft')),
4584 ('d', 'draft', False, _('set changeset phase to draft')),
4585 ('s', 'secret', False, _('set changeset phase to secret')),
4585 ('s', 'secret', False, _('set changeset phase to secret')),
4586 ('f', 'force', False, _('allow to move boundary backward')),
4586 ('f', 'force', False, _('allow to move boundary backward')),
4587 ('r', 'rev', [], _('target revision'), _('REV')),
4587 ('r', 'rev', [], _('target revision'), _('REV')),
4588 ],
4588 ],
4589 _('[-p|-d|-s] [-f] [-r] REV...'))
4589 _('[-p|-d|-s] [-f] [-r] REV...'))
4590 def phase(ui, repo, *revs, **opts):
4590 def phase(ui, repo, *revs, **opts):
4591 """set or show the current phase name
4591 """set or show the current phase name
4592
4592
4593 With no argument, show the phase name of specified revisions.
4593 With no argument, show the phase name of specified revisions.
4594
4594
4595 With one of -p/--public, -d/--draft or -s/--secret, change the
4595 With one of -p/--public, -d/--draft or -s/--secret, change the
4596 phase value of the specified revisions.
4596 phase value of the specified revisions.
4597
4597
4598 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4598 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4599 lower phase to an higher phase. Phases are ordered as follows::
4599 lower phase to an higher phase. Phases are ordered as follows::
4600
4600
4601 public < draft < secret
4601 public < draft < secret
4602
4602
4603 Return 0 on success, 1 if no phases were changed or some could not
4603 Return 0 on success, 1 if no phases were changed or some could not
4604 be changed.
4604 be changed.
4605 """
4605 """
4606 # search for a unique phase argument
4606 # search for a unique phase argument
4607 targetphase = None
4607 targetphase = None
4608 for idx, name in enumerate(phases.phasenames):
4608 for idx, name in enumerate(phases.phasenames):
4609 if opts[name]:
4609 if opts[name]:
4610 if targetphase is not None:
4610 if targetphase is not None:
4611 raise util.Abort(_('only one phase can be specified'))
4611 raise util.Abort(_('only one phase can be specified'))
4612 targetphase = idx
4612 targetphase = idx
4613
4613
4614 # look for specified revision
4614 # look for specified revision
4615 revs = list(revs)
4615 revs = list(revs)
4616 revs.extend(opts['rev'])
4616 revs.extend(opts['rev'])
4617 if not revs:
4617 if not revs:
4618 raise util.Abort(_('no revisions specified'))
4618 raise util.Abort(_('no revisions specified'))
4619
4619
4620 revs = scmutil.revrange(repo, revs)
4620 revs = scmutil.revrange(repo, revs)
4621
4621
4622 lock = None
4622 lock = None
4623 ret = 0
4623 ret = 0
4624 if targetphase is None:
4624 if targetphase is None:
4625 # display
4625 # display
4626 for r in revs:
4626 for r in revs:
4627 ctx = repo[r]
4627 ctx = repo[r]
4628 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4628 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4629 else:
4629 else:
4630 lock = repo.lock()
4630 lock = repo.lock()
4631 try:
4631 try:
4632 # set phase
4632 # set phase
4633 if not revs:
4633 if not revs:
4634 raise util.Abort(_('empty revision set'))
4634 raise util.Abort(_('empty revision set'))
4635 nodes = [repo[r].node() for r in revs]
4635 nodes = [repo[r].node() for r in revs]
4636 olddata = repo._phasecache.getphaserevs(repo)[:]
4636 olddata = repo._phasecache.getphaserevs(repo)[:]
4637 phases.advanceboundary(repo, targetphase, nodes)
4637 phases.advanceboundary(repo, targetphase, nodes)
4638 if opts['force']:
4638 if opts['force']:
4639 phases.retractboundary(repo, targetphase, nodes)
4639 phases.retractboundary(repo, targetphase, nodes)
4640 finally:
4640 finally:
4641 lock.release()
4641 lock.release()
4642 # moving revision from public to draft may hide them
4642 # moving revision from public to draft may hide them
4643 # We have to check result on an unfiltered repository
4643 # We have to check result on an unfiltered repository
4644 unfi = repo.unfiltered()
4644 unfi = repo.unfiltered()
4645 newdata = repo._phasecache.getphaserevs(unfi)
4645 newdata = repo._phasecache.getphaserevs(unfi)
4646 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4646 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4647 cl = unfi.changelog
4647 cl = unfi.changelog
4648 rejected = [n for n in nodes
4648 rejected = [n for n in nodes
4649 if newdata[cl.rev(n)] < targetphase]
4649 if newdata[cl.rev(n)] < targetphase]
4650 if rejected:
4650 if rejected:
4651 ui.warn(_('cannot move %i changesets to a more permissive '
4651 ui.warn(_('cannot move %i changesets to a more permissive '
4652 'phase, use --force\n') % len(rejected))
4652 'phase, use --force\n') % len(rejected))
4653 ret = 1
4653 ret = 1
4654 if changes:
4654 if changes:
4655 msg = _('phase changed for %i changesets\n') % changes
4655 msg = _('phase changed for %i changesets\n') % changes
4656 if ret:
4656 if ret:
4657 ui.status(msg)
4657 ui.status(msg)
4658 else:
4658 else:
4659 ui.note(msg)
4659 ui.note(msg)
4660 else:
4660 else:
4661 ui.warn(_('no phases changed\n'))
4661 ui.warn(_('no phases changed\n'))
4662 ret = 1
4662 ret = 1
4663 return ret
4663 return ret
4664
4664
4665 def postincoming(ui, repo, modheads, optupdate, checkout):
4665 def postincoming(ui, repo, modheads, optupdate, checkout):
4666 if modheads == 0:
4666 if modheads == 0:
4667 return
4667 return
4668 if optupdate:
4668 if optupdate:
4669 movemarkfrom = repo['.'].node()
4669 movemarkfrom = repo['.'].node()
4670 try:
4670 try:
4671 ret = hg.update(repo, checkout)
4671 ret = hg.update(repo, checkout)
4672 except util.Abort, inst:
4672 except util.Abort, inst:
4673 ui.warn(_("not updating: %s\n") % str(inst))
4673 ui.warn(_("not updating: %s\n") % str(inst))
4674 return 0
4674 return 0
4675 if not ret and not checkout:
4675 if not ret and not checkout:
4676 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4676 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4677 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4677 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4678 return ret
4678 return ret
4679 if modheads > 1:
4679 if modheads > 1:
4680 currentbranchheads = len(repo.branchheads())
4680 currentbranchheads = len(repo.branchheads())
4681 if currentbranchheads == modheads:
4681 if currentbranchheads == modheads:
4682 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4682 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4683 elif currentbranchheads > 1:
4683 elif currentbranchheads > 1:
4684 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4684 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4685 "merge)\n"))
4685 "merge)\n"))
4686 else:
4686 else:
4687 ui.status(_("(run 'hg heads' to see heads)\n"))
4687 ui.status(_("(run 'hg heads' to see heads)\n"))
4688 else:
4688 else:
4689 ui.status(_("(run 'hg update' to get a working copy)\n"))
4689 ui.status(_("(run 'hg update' to get a working copy)\n"))
4690
4690
4691 @command('^pull',
4691 @command('^pull',
4692 [('u', 'update', None,
4692 [('u', 'update', None,
4693 _('update to new branch head if changesets were pulled')),
4693 _('update to new branch head if changesets were pulled')),
4694 ('f', 'force', None, _('run even when remote repository is unrelated')),
4694 ('f', 'force', None, _('run even when remote repository is unrelated')),
4695 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4695 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4696 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4696 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4697 ('b', 'branch', [], _('a specific branch you would like to pull'),
4697 ('b', 'branch', [], _('a specific branch you would like to pull'),
4698 _('BRANCH')),
4698 _('BRANCH')),
4699 ] + remoteopts,
4699 ] + remoteopts,
4700 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4700 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4701 def pull(ui, repo, source="default", **opts):
4701 def pull(ui, repo, source="default", **opts):
4702 """pull changes from the specified source
4702 """pull changes from the specified source
4703
4703
4704 Pull changes from a remote repository to a local one.
4704 Pull changes from a remote repository to a local one.
4705
4705
4706 This finds all changes from the repository at the specified path
4706 This finds all changes from the repository at the specified path
4707 or URL and adds them to a local repository (the current one unless
4707 or URL and adds them to a local repository (the current one unless
4708 -R is specified). By default, this does not update the copy of the
4708 -R is specified). By default, this does not update the copy of the
4709 project in the working directory.
4709 project in the working directory.
4710
4710
4711 Use :hg:`incoming` if you want to see what would have been added
4711 Use :hg:`incoming` if you want to see what would have been added
4712 by a pull at the time you issued this command. If you then decide
4712 by a pull at the time you issued this command. If you then decide
4713 to add those changes to the repository, you should use :hg:`pull
4713 to add those changes to the repository, you should use :hg:`pull
4714 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4714 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4715
4715
4716 If SOURCE is omitted, the 'default' path will be used.
4716 If SOURCE is omitted, the 'default' path will be used.
4717 See :hg:`help urls` for more information.
4717 See :hg:`help urls` for more information.
4718
4718
4719 Returns 0 on success, 1 if an update had unresolved files.
4719 Returns 0 on success, 1 if an update had unresolved files.
4720 """
4720 """
4721 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4721 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4722 other = hg.peer(repo, opts, source)
4722 other = hg.peer(repo, opts, source)
4723 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4723 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4724 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4724 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4725
4725
4726 if opts.get('bookmark'):
4726 if opts.get('bookmark'):
4727 if not revs:
4727 if not revs:
4728 revs = []
4728 revs = []
4729 rb = other.listkeys('bookmarks')
4729 rb = other.listkeys('bookmarks')
4730 for b in opts['bookmark']:
4730 for b in opts['bookmark']:
4731 if b not in rb:
4731 if b not in rb:
4732 raise util.Abort(_('remote bookmark %s not found!') % b)
4732 raise util.Abort(_('remote bookmark %s not found!') % b)
4733 revs.append(rb[b])
4733 revs.append(rb[b])
4734
4734
4735 if revs:
4735 if revs:
4736 try:
4736 try:
4737 revs = [other.lookup(rev) for rev in revs]
4737 revs = [other.lookup(rev) for rev in revs]
4738 except error.CapabilityError:
4738 except error.CapabilityError:
4739 err = _("other repository doesn't support revision lookup, "
4739 err = _("other repository doesn't support revision lookup, "
4740 "so a rev cannot be specified.")
4740 "so a rev cannot be specified.")
4741 raise util.Abort(err)
4741 raise util.Abort(err)
4742
4742
4743 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4743 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4744 bookmarks.updatefromremote(ui, repo, other, source)
4744 bookmarks.updatefromremote(ui, repo, other, source)
4745 if checkout:
4745 if checkout:
4746 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4746 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4747 repo._subtoppath = source
4747 repo._subtoppath = source
4748 try:
4748 try:
4749 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4749 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4750
4750
4751 finally:
4751 finally:
4752 del repo._subtoppath
4752 del repo._subtoppath
4753
4753
4754 # update specified bookmarks
4754 # update specified bookmarks
4755 if opts.get('bookmark'):
4755 if opts.get('bookmark'):
4756 marks = repo._bookmarks
4756 marks = repo._bookmarks
4757 for b in opts['bookmark']:
4757 for b in opts['bookmark']:
4758 # explicit pull overrides local bookmark if any
4758 # explicit pull overrides local bookmark if any
4759 ui.status(_("importing bookmark %s\n") % b)
4759 ui.status(_("importing bookmark %s\n") % b)
4760 marks[b] = repo[rb[b]].node()
4760 marks[b] = repo[rb[b]].node()
4761 marks.write()
4761 marks.write()
4762
4762
4763 return ret
4763 return ret
4764
4764
4765 @command('^push',
4765 @command('^push',
4766 [('f', 'force', None, _('force push')),
4766 [('f', 'force', None, _('force push')),
4767 ('r', 'rev', [],
4767 ('r', 'rev', [],
4768 _('a changeset intended to be included in the destination'),
4768 _('a changeset intended to be included in the destination'),
4769 _('REV')),
4769 _('REV')),
4770 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4770 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4771 ('b', 'branch', [],
4771 ('b', 'branch', [],
4772 _('a specific branch you would like to push'), _('BRANCH')),
4772 _('a specific branch you would like to push'), _('BRANCH')),
4773 ('', 'new-branch', False, _('allow pushing a new branch')),
4773 ('', 'new-branch', False, _('allow pushing a new branch')),
4774 ] + remoteopts,
4774 ] + remoteopts,
4775 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4775 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4776 def push(ui, repo, dest=None, **opts):
4776 def push(ui, repo, dest=None, **opts):
4777 """push changes to the specified destination
4777 """push changes to the specified destination
4778
4778
4779 Push changesets from the local repository to the specified
4779 Push changesets from the local repository to the specified
4780 destination.
4780 destination.
4781
4781
4782 This operation is symmetrical to pull: it is identical to a pull
4782 This operation is symmetrical to pull: it is identical to a pull
4783 in the destination repository from the current one.
4783 in the destination repository from the current one.
4784
4784
4785 By default, push will not allow creation of new heads at the
4785 By default, push will not allow creation of new heads at the
4786 destination, since multiple heads would make it unclear which head
4786 destination, since multiple heads would make it unclear which head
4787 to use. In this situation, it is recommended to pull and merge
4787 to use. In this situation, it is recommended to pull and merge
4788 before pushing.
4788 before pushing.
4789
4789
4790 Use --new-branch if you want to allow push to create a new named
4790 Use --new-branch if you want to allow push to create a new named
4791 branch that is not present at the destination. This allows you to
4791 branch that is not present at the destination. This allows you to
4792 only create a new branch without forcing other changes.
4792 only create a new branch without forcing other changes.
4793
4793
4794 Use -f/--force to override the default behavior and push all
4794 Use -f/--force to override the default behavior and push all
4795 changesets on all branches.
4795 changesets on all branches.
4796
4796
4797 If -r/--rev is used, the specified revision and all its ancestors
4797 If -r/--rev is used, the specified revision and all its ancestors
4798 will be pushed to the remote repository.
4798 will be pushed to the remote repository.
4799
4799
4800 If -B/--bookmark is used, the specified bookmarked revision, its
4800 If -B/--bookmark is used, the specified bookmarked revision, its
4801 ancestors, and the bookmark will be pushed to the remote
4801 ancestors, and the bookmark will be pushed to the remote
4802 repository.
4802 repository.
4803
4803
4804 Please see :hg:`help urls` for important details about ``ssh://``
4804 Please see :hg:`help urls` for important details about ``ssh://``
4805 URLs. If DESTINATION is omitted, a default path will be used.
4805 URLs. If DESTINATION is omitted, a default path will be used.
4806
4806
4807 Returns 0 if push was successful, 1 if nothing to push.
4807 Returns 0 if push was successful, 1 if nothing to push.
4808 """
4808 """
4809
4809
4810 if opts.get('bookmark'):
4810 if opts.get('bookmark'):
4811 for b in opts['bookmark']:
4811 for b in opts['bookmark']:
4812 # translate -B options to -r so changesets get pushed
4812 # translate -B options to -r so changesets get pushed
4813 if b in repo._bookmarks:
4813 if b in repo._bookmarks:
4814 opts.setdefault('rev', []).append(b)
4814 opts.setdefault('rev', []).append(b)
4815 else:
4815 else:
4816 # if we try to push a deleted bookmark, translate it to null
4816 # if we try to push a deleted bookmark, translate it to null
4817 # this lets simultaneous -r, -b options continue working
4817 # this lets simultaneous -r, -b options continue working
4818 opts.setdefault('rev', []).append("null")
4818 opts.setdefault('rev', []).append("null")
4819
4819
4820 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4820 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4821 dest, branches = hg.parseurl(dest, opts.get('branch'))
4821 dest, branches = hg.parseurl(dest, opts.get('branch'))
4822 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4822 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4823 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4823 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4824 other = hg.peer(repo, opts, dest)
4824 other = hg.peer(repo, opts, dest)
4825 if revs:
4825 if revs:
4826 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4826 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4827
4827
4828 repo._subtoppath = dest
4828 repo._subtoppath = dest
4829 try:
4829 try:
4830 # push subrepos depth-first for coherent ordering
4830 # push subrepos depth-first for coherent ordering
4831 c = repo['']
4831 c = repo['']
4832 subs = c.substate # only repos that are committed
4832 subs = c.substate # only repos that are committed
4833 for s in sorted(subs):
4833 for s in sorted(subs):
4834 if c.sub(s).push(opts) == 0:
4834 if c.sub(s).push(opts) == 0:
4835 return False
4835 return False
4836 finally:
4836 finally:
4837 del repo._subtoppath
4837 del repo._subtoppath
4838 result = repo.push(other, opts.get('force'), revs=revs,
4838 result = repo.push(other, opts.get('force'), revs=revs,
4839 newbranch=opts.get('new_branch'))
4839 newbranch=opts.get('new_branch'))
4840
4840
4841 result = not result
4841 result = not result
4842
4842
4843 if opts.get('bookmark'):
4843 if opts.get('bookmark'):
4844 rb = other.listkeys('bookmarks')
4844 rb = other.listkeys('bookmarks')
4845 for b in opts['bookmark']:
4845 for b in opts['bookmark']:
4846 # explicit push overrides remote bookmark if any
4846 # explicit push overrides remote bookmark if any
4847 if b in repo._bookmarks:
4847 if b in repo._bookmarks:
4848 ui.status(_("exporting bookmark %s\n") % b)
4848 ui.status(_("exporting bookmark %s\n") % b)
4849 new = repo[b].hex()
4849 new = repo[b].hex()
4850 elif b in rb:
4850 elif b in rb:
4851 ui.status(_("deleting remote bookmark %s\n") % b)
4851 ui.status(_("deleting remote bookmark %s\n") % b)
4852 new = '' # delete
4852 new = '' # delete
4853 else:
4853 else:
4854 ui.warn(_('bookmark %s does not exist on the local '
4854 ui.warn(_('bookmark %s does not exist on the local '
4855 'or remote repository!\n') % b)
4855 'or remote repository!\n') % b)
4856 return 2
4856 return 2
4857 old = rb.get(b, '')
4857 old = rb.get(b, '')
4858 r = other.pushkey('bookmarks', b, old, new)
4858 r = other.pushkey('bookmarks', b, old, new)
4859 if not r:
4859 if not r:
4860 ui.warn(_('updating bookmark %s failed!\n') % b)
4860 ui.warn(_('updating bookmark %s failed!\n') % b)
4861 if not result:
4861 if not result:
4862 result = 2
4862 result = 2
4863
4863
4864 return result
4864 return result
4865
4865
4866 @command('recover', [])
4866 @command('recover', [])
4867 def recover(ui, repo):
4867 def recover(ui, repo):
4868 """roll back an interrupted transaction
4868 """roll back an interrupted transaction
4869
4869
4870 Recover from an interrupted commit or pull.
4870 Recover from an interrupted commit or pull.
4871
4871
4872 This command tries to fix the repository status after an
4872 This command tries to fix the repository status after an
4873 interrupted operation. It should only be necessary when Mercurial
4873 interrupted operation. It should only be necessary when Mercurial
4874 suggests it.
4874 suggests it.
4875
4875
4876 Returns 0 if successful, 1 if nothing to recover or verify fails.
4876 Returns 0 if successful, 1 if nothing to recover or verify fails.
4877 """
4877 """
4878 if repo.recover():
4878 if repo.recover():
4879 return hg.verify(repo)
4879 return hg.verify(repo)
4880 return 1
4880 return 1
4881
4881
4882 @command('^remove|rm',
4882 @command('^remove|rm',
4883 [('A', 'after', None, _('record delete for missing files')),
4883 [('A', 'after', None, _('record delete for missing files')),
4884 ('f', 'force', None,
4884 ('f', 'force', None,
4885 _('remove (and delete) file even if added or modified')),
4885 _('remove (and delete) file even if added or modified')),
4886 ] + walkopts,
4886 ] + walkopts,
4887 _('[OPTION]... FILE...'))
4887 _('[OPTION]... FILE...'))
4888 def remove(ui, repo, *pats, **opts):
4888 def remove(ui, repo, *pats, **opts):
4889 """remove the specified files on the next commit
4889 """remove the specified files on the next commit
4890
4890
4891 Schedule the indicated files for removal from the current branch.
4891 Schedule the indicated files for removal from the current branch.
4892
4892
4893 This command schedules the files to be removed at the next commit.
4893 This command schedules the files to be removed at the next commit.
4894 To undo a remove before that, see :hg:`revert`. To undo added
4894 To undo a remove before that, see :hg:`revert`. To undo added
4895 files, see :hg:`forget`.
4895 files, see :hg:`forget`.
4896
4896
4897 .. container:: verbose
4897 .. container:: verbose
4898
4898
4899 -A/--after can be used to remove only files that have already
4899 -A/--after can be used to remove only files that have already
4900 been deleted, -f/--force can be used to force deletion, and -Af
4900 been deleted, -f/--force can be used to force deletion, and -Af
4901 can be used to remove files from the next revision without
4901 can be used to remove files from the next revision without
4902 deleting them from the working directory.
4902 deleting them from the working directory.
4903
4903
4904 The following table details the behavior of remove for different
4904 The following table details the behavior of remove for different
4905 file states (columns) and option combinations (rows). The file
4905 file states (columns) and option combinations (rows). The file
4906 states are Added [A], Clean [C], Modified [M] and Missing [!]
4906 states are Added [A], Clean [C], Modified [M] and Missing [!]
4907 (as reported by :hg:`status`). The actions are Warn, Remove
4907 (as reported by :hg:`status`). The actions are Warn, Remove
4908 (from branch) and Delete (from disk):
4908 (from branch) and Delete (from disk):
4909
4909
4910 ======= == == == ==
4910 ======= == == == ==
4911 A C M !
4911 A C M !
4912 ======= == == == ==
4912 ======= == == == ==
4913 none W RD W R
4913 none W RD W R
4914 -f R RD RD R
4914 -f R RD RD R
4915 -A W W W R
4915 -A W W W R
4916 -Af R R R R
4916 -Af R R R R
4917 ======= == == == ==
4917 ======= == == == ==
4918
4918
4919 Note that remove never deletes files in Added [A] state from the
4919 Note that remove never deletes files in Added [A] state from the
4920 working directory, not even if option --force is specified.
4920 working directory, not even if option --force is specified.
4921
4921
4922 Returns 0 on success, 1 if any warnings encountered.
4922 Returns 0 on success, 1 if any warnings encountered.
4923 """
4923 """
4924
4924
4925 ret = 0
4925 ret = 0
4926 after, force = opts.get('after'), opts.get('force')
4926 after, force = opts.get('after'), opts.get('force')
4927 if not pats and not after:
4927 if not pats and not after:
4928 raise util.Abort(_('no files specified'))
4928 raise util.Abort(_('no files specified'))
4929
4929
4930 m = scmutil.match(repo[None], pats, opts)
4930 m = scmutil.match(repo[None], pats, opts)
4931 s = repo.status(match=m, clean=True)
4931 s = repo.status(match=m, clean=True)
4932 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4932 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4933
4933
4934 # warn about failure to delete explicit files/dirs
4934 # warn about failure to delete explicit files/dirs
4935 wctx = repo[None]
4935 wctx = repo[None]
4936 for f in m.files():
4936 for f in m.files():
4937 if f in repo.dirstate or f in wctx.dirs():
4937 if f in repo.dirstate or f in wctx.dirs():
4938 continue
4938 continue
4939 if os.path.exists(m.rel(f)):
4939 if os.path.exists(m.rel(f)):
4940 if os.path.isdir(m.rel(f)):
4940 if os.path.isdir(m.rel(f)):
4941 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4941 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4942 else:
4942 else:
4943 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4943 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4944 # missing files will generate a warning elsewhere
4944 # missing files will generate a warning elsewhere
4945 ret = 1
4945 ret = 1
4946
4946
4947 if force:
4947 if force:
4948 list = modified + deleted + clean + added
4948 list = modified + deleted + clean + added
4949 elif after:
4949 elif after:
4950 list = deleted
4950 list = deleted
4951 for f in modified + added + clean:
4951 for f in modified + added + clean:
4952 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4952 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4953 ret = 1
4953 ret = 1
4954 else:
4954 else:
4955 list = deleted + clean
4955 list = deleted + clean
4956 for f in modified:
4956 for f in modified:
4957 ui.warn(_('not removing %s: file is modified (use -f'
4957 ui.warn(_('not removing %s: file is modified (use -f'
4958 ' to force removal)\n') % m.rel(f))
4958 ' to force removal)\n') % m.rel(f))
4959 ret = 1
4959 ret = 1
4960 for f in added:
4960 for f in added:
4961 ui.warn(_('not removing %s: file has been marked for add'
4961 ui.warn(_('not removing %s: file has been marked for add'
4962 ' (use forget to undo)\n') % m.rel(f))
4962 ' (use forget to undo)\n') % m.rel(f))
4963 ret = 1
4963 ret = 1
4964
4964
4965 for f in sorted(list):
4965 for f in sorted(list):
4966 if ui.verbose or not m.exact(f):
4966 if ui.verbose or not m.exact(f):
4967 ui.status(_('removing %s\n') % m.rel(f))
4967 ui.status(_('removing %s\n') % m.rel(f))
4968
4968
4969 wlock = repo.wlock()
4969 wlock = repo.wlock()
4970 try:
4970 try:
4971 if not after:
4971 if not after:
4972 for f in list:
4972 for f in list:
4973 if f in added:
4973 if f in added:
4974 continue # we never unlink added files on remove
4974 continue # we never unlink added files on remove
4975 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4975 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4976 repo[None].forget(list)
4976 repo[None].forget(list)
4977 finally:
4977 finally:
4978 wlock.release()
4978 wlock.release()
4979
4979
4980 return ret
4980 return ret
4981
4981
4982 @command('rename|move|mv',
4982 @command('rename|move|mv',
4983 [('A', 'after', None, _('record a rename that has already occurred')),
4983 [('A', 'after', None, _('record a rename that has already occurred')),
4984 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4984 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4985 ] + walkopts + dryrunopts,
4985 ] + walkopts + dryrunopts,
4986 _('[OPTION]... SOURCE... DEST'))
4986 _('[OPTION]... SOURCE... DEST'))
4987 def rename(ui, repo, *pats, **opts):
4987 def rename(ui, repo, *pats, **opts):
4988 """rename files; equivalent of copy + remove
4988 """rename files; equivalent of copy + remove
4989
4989
4990 Mark dest as copies of sources; mark sources for deletion. If dest
4990 Mark dest as copies of sources; mark sources for deletion. If dest
4991 is a directory, copies are put in that directory. If dest is a
4991 is a directory, copies are put in that directory. If dest is a
4992 file, there can only be one source.
4992 file, there can only be one source.
4993
4993
4994 By default, this command copies the contents of files as they
4994 By default, this command copies the contents of files as they
4995 exist in the working directory. If invoked with -A/--after, the
4995 exist in the working directory. If invoked with -A/--after, the
4996 operation is recorded, but no copying is performed.
4996 operation is recorded, but no copying is performed.
4997
4997
4998 This command takes effect at the next commit. To undo a rename
4998 This command takes effect at the next commit. To undo a rename
4999 before that, see :hg:`revert`.
4999 before that, see :hg:`revert`.
5000
5000
5001 Returns 0 on success, 1 if errors are encountered.
5001 Returns 0 on success, 1 if errors are encountered.
5002 """
5002 """
5003 wlock = repo.wlock(False)
5003 wlock = repo.wlock(False)
5004 try:
5004 try:
5005 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5005 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5006 finally:
5006 finally:
5007 wlock.release()
5007 wlock.release()
5008
5008
5009 @command('resolve',
5009 @command('resolve',
5010 [('a', 'all', None, _('select all unresolved files')),
5010 [('a', 'all', None, _('select all unresolved files')),
5011 ('l', 'list', None, _('list state of files needing merge')),
5011 ('l', 'list', None, _('list state of files needing merge')),
5012 ('m', 'mark', None, _('mark files as resolved')),
5012 ('m', 'mark', None, _('mark files as resolved')),
5013 ('u', 'unmark', None, _('mark files as unresolved')),
5013 ('u', 'unmark', None, _('mark files as unresolved')),
5014 ('n', 'no-status', None, _('hide status prefix'))]
5014 ('n', 'no-status', None, _('hide status prefix'))]
5015 + mergetoolopts + walkopts,
5015 + mergetoolopts + walkopts,
5016 _('[OPTION]... [FILE]...'))
5016 _('[OPTION]... [FILE]...'))
5017 def resolve(ui, repo, *pats, **opts):
5017 def resolve(ui, repo, *pats, **opts):
5018 """redo merges or set/view the merge status of files
5018 """redo merges or set/view the merge status of files
5019
5019
5020 Merges with unresolved conflicts are often the result of
5020 Merges with unresolved conflicts are often the result of
5021 non-interactive merging using the ``internal:merge`` configuration
5021 non-interactive merging using the ``internal:merge`` configuration
5022 setting, or a command-line merge tool like ``diff3``. The resolve
5022 setting, or a command-line merge tool like ``diff3``. The resolve
5023 command is used to manage the files involved in a merge, after
5023 command is used to manage the files involved in a merge, after
5024 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5024 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5025 working directory must have two parents). See :hg:`help
5025 working directory must have two parents). See :hg:`help
5026 merge-tools` for information on configuring merge tools.
5026 merge-tools` for information on configuring merge tools.
5027
5027
5028 The resolve command can be used in the following ways:
5028 The resolve command can be used in the following ways:
5029
5029
5030 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5030 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5031 files, discarding any previous merge attempts. Re-merging is not
5031 files, discarding any previous merge attempts. Re-merging is not
5032 performed for files already marked as resolved. Use ``--all/-a``
5032 performed for files already marked as resolved. Use ``--all/-a``
5033 to select all unresolved files. ``--tool`` can be used to specify
5033 to select all unresolved files. ``--tool`` can be used to specify
5034 the merge tool used for the given files. It overrides the HGMERGE
5034 the merge tool used for the given files. It overrides the HGMERGE
5035 environment variable and your configuration files. Previous file
5035 environment variable and your configuration files. Previous file
5036 contents are saved with a ``.orig`` suffix.
5036 contents are saved with a ``.orig`` suffix.
5037
5037
5038 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5038 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5039 (e.g. after having manually fixed-up the files). The default is
5039 (e.g. after having manually fixed-up the files). The default is
5040 to mark all unresolved files.
5040 to mark all unresolved files.
5041
5041
5042 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5042 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5043 default is to mark all resolved files.
5043 default is to mark all resolved files.
5044
5044
5045 - :hg:`resolve -l`: list files which had or still have conflicts.
5045 - :hg:`resolve -l`: list files which had or still have conflicts.
5046 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5046 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5047
5047
5048 Note that Mercurial will not let you commit files with unresolved
5048 Note that Mercurial will not let you commit files with unresolved
5049 merge conflicts. You must use :hg:`resolve -m ...` before you can
5049 merge conflicts. You must use :hg:`resolve -m ...` before you can
5050 commit after a conflicting merge.
5050 commit after a conflicting merge.
5051
5051
5052 Returns 0 on success, 1 if any files fail a resolve attempt.
5052 Returns 0 on success, 1 if any files fail a resolve attempt.
5053 """
5053 """
5054
5054
5055 all, mark, unmark, show, nostatus = \
5055 all, mark, unmark, show, nostatus = \
5056 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5056 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5057
5057
5058 if (show and (mark or unmark)) or (mark and unmark):
5058 if (show and (mark or unmark)) or (mark and unmark):
5059 raise util.Abort(_("too many options specified"))
5059 raise util.Abort(_("too many options specified"))
5060 if pats and all:
5060 if pats and all:
5061 raise util.Abort(_("can't specify --all and patterns"))
5061 raise util.Abort(_("can't specify --all and patterns"))
5062 if not (all or pats or show or mark or unmark):
5062 if not (all or pats or show or mark or unmark):
5063 raise util.Abort(_('no files or directories specified; '
5063 raise util.Abort(_('no files or directories specified; '
5064 'use --all to remerge all files'))
5064 'use --all to remerge all files'))
5065
5065
5066 ms = mergemod.mergestate(repo)
5066 ms = mergemod.mergestate(repo)
5067 m = scmutil.match(repo[None], pats, opts)
5067 m = scmutil.match(repo[None], pats, opts)
5068 ret = 0
5068 ret = 0
5069
5069
5070 for f in ms:
5070 for f in ms:
5071 if m(f):
5071 if m(f):
5072 if show:
5072 if show:
5073 if nostatus:
5073 if nostatus:
5074 ui.write("%s\n" % f)
5074 ui.write("%s\n" % f)
5075 else:
5075 else:
5076 ui.write("%s %s\n" % (ms[f].upper(), f),
5076 ui.write("%s %s\n" % (ms[f].upper(), f),
5077 label='resolve.' +
5077 label='resolve.' +
5078 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5078 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5079 elif mark:
5079 elif mark:
5080 ms.mark(f, "r")
5080 ms.mark(f, "r")
5081 elif unmark:
5081 elif unmark:
5082 ms.mark(f, "u")
5082 ms.mark(f, "u")
5083 else:
5083 else:
5084 wctx = repo[None]
5084 wctx = repo[None]
5085 mctx = wctx.parents()[-1]
5085 mctx = wctx.parents()[-1]
5086
5086
5087 # backup pre-resolve (merge uses .orig for its own purposes)
5087 # backup pre-resolve (merge uses .orig for its own purposes)
5088 a = repo.wjoin(f)
5088 a = repo.wjoin(f)
5089 util.copyfile(a, a + ".resolve")
5089 util.copyfile(a, a + ".resolve")
5090
5090
5091 try:
5091 try:
5092 # resolve file
5092 # resolve file
5093 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5093 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5094 if ms.resolve(f, wctx, mctx):
5094 if ms.resolve(f, wctx, mctx):
5095 ret = 1
5095 ret = 1
5096 finally:
5096 finally:
5097 ui.setconfig('ui', 'forcemerge', '')
5097 ui.setconfig('ui', 'forcemerge', '')
5098 ms.commit()
5098 ms.commit()
5099
5099
5100 # replace filemerge's .orig file with our resolve file
5100 # replace filemerge's .orig file with our resolve file
5101 util.rename(a + ".resolve", a + ".orig")
5101 util.rename(a + ".resolve", a + ".orig")
5102
5102
5103 ms.commit()
5103 ms.commit()
5104 return ret
5104 return ret
5105
5105
5106 @command('revert',
5106 @command('revert',
5107 [('a', 'all', None, _('revert all changes when no arguments given')),
5107 [('a', 'all', None, _('revert all changes when no arguments given')),
5108 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5108 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5109 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5109 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5110 ('C', 'no-backup', None, _('do not save backup copies of files')),
5110 ('C', 'no-backup', None, _('do not save backup copies of files')),
5111 ] + walkopts + dryrunopts,
5111 ] + walkopts + dryrunopts,
5112 _('[OPTION]... [-r REV] [NAME]...'))
5112 _('[OPTION]... [-r REV] [NAME]...'))
5113 def revert(ui, repo, *pats, **opts):
5113 def revert(ui, repo, *pats, **opts):
5114 """restore files to their checkout state
5114 """restore files to their checkout state
5115
5115
5116 .. note::
5116 .. note::
5117
5117
5118 To check out earlier revisions, you should use :hg:`update REV`.
5118 To check out earlier revisions, you should use :hg:`update REV`.
5119 To cancel an uncommitted merge (and lose your changes), use
5119 To cancel an uncommitted merge (and lose your changes), use
5120 :hg:`update --clean .`.
5120 :hg:`update --clean .`.
5121
5121
5122 With no revision specified, revert the specified files or directories
5122 With no revision specified, revert the specified files or directories
5123 to the contents they had in the parent of the working directory.
5123 to the contents they had in the parent of the working directory.
5124 This restores the contents of files to an unmodified
5124 This restores the contents of files to an unmodified
5125 state and unschedules adds, removes, copies, and renames. If the
5125 state and unschedules adds, removes, copies, and renames. If the
5126 working directory has two parents, you must explicitly specify a
5126 working directory has two parents, you must explicitly specify a
5127 revision.
5127 revision.
5128
5128
5129 Using the -r/--rev or -d/--date options, revert the given files or
5129 Using the -r/--rev or -d/--date options, revert the given files or
5130 directories to their states as of a specific revision. Because
5130 directories to their states as of a specific revision. Because
5131 revert does not change the working directory parents, this will
5131 revert does not change the working directory parents, this will
5132 cause these files to appear modified. This can be helpful to "back
5132 cause these files to appear modified. This can be helpful to "back
5133 out" some or all of an earlier change. See :hg:`backout` for a
5133 out" some or all of an earlier change. See :hg:`backout` for a
5134 related method.
5134 related method.
5135
5135
5136 Modified files are saved with a .orig suffix before reverting.
5136 Modified files are saved with a .orig suffix before reverting.
5137 To disable these backups, use --no-backup.
5137 To disable these backups, use --no-backup.
5138
5138
5139 See :hg:`help dates` for a list of formats valid for -d/--date.
5139 See :hg:`help dates` for a list of formats valid for -d/--date.
5140
5140
5141 Returns 0 on success.
5141 Returns 0 on success.
5142 """
5142 """
5143
5143
5144 if opts.get("date"):
5144 if opts.get("date"):
5145 if opts.get("rev"):
5145 if opts.get("rev"):
5146 raise util.Abort(_("you can't specify a revision and a date"))
5146 raise util.Abort(_("you can't specify a revision and a date"))
5147 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5147 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5148
5148
5149 parent, p2 = repo.dirstate.parents()
5149 parent, p2 = repo.dirstate.parents()
5150 if not opts.get('rev') and p2 != nullid:
5150 if not opts.get('rev') and p2 != nullid:
5151 # revert after merge is a trap for new users (issue2915)
5151 # revert after merge is a trap for new users (issue2915)
5152 raise util.Abort(_('uncommitted merge with no revision specified'),
5152 raise util.Abort(_('uncommitted merge with no revision specified'),
5153 hint=_('use "hg update" or see "hg help revert"'))
5153 hint=_('use "hg update" or see "hg help revert"'))
5154
5154
5155 ctx = scmutil.revsingle(repo, opts.get('rev'))
5155 ctx = scmutil.revsingle(repo, opts.get('rev'))
5156
5156
5157 if not pats and not opts.get('all'):
5157 if not pats and not opts.get('all'):
5158 msg = _("no files or directories specified")
5158 msg = _("no files or directories specified")
5159 if p2 != nullid:
5159 if p2 != nullid:
5160 hint = _("uncommitted merge, use --all to discard all changes,"
5160 hint = _("uncommitted merge, use --all to discard all changes,"
5161 " or 'hg update -C .' to abort the merge")
5161 " or 'hg update -C .' to abort the merge")
5162 raise util.Abort(msg, hint=hint)
5162 raise util.Abort(msg, hint=hint)
5163 dirty = util.any(repo.status())
5163 dirty = util.any(repo.status())
5164 node = ctx.node()
5164 node = ctx.node()
5165 if node != parent:
5165 if node != parent:
5166 if dirty:
5166 if dirty:
5167 hint = _("uncommitted changes, use --all to discard all"
5167 hint = _("uncommitted changes, use --all to discard all"
5168 " changes, or 'hg update %s' to update") % ctx.rev()
5168 " changes, or 'hg update %s' to update") % ctx.rev()
5169 else:
5169 else:
5170 hint = _("use --all to revert all files,"
5170 hint = _("use --all to revert all files,"
5171 " or 'hg update %s' to update") % ctx.rev()
5171 " or 'hg update %s' to update") % ctx.rev()
5172 elif dirty:
5172 elif dirty:
5173 hint = _("uncommitted changes, use --all to discard all changes")
5173 hint = _("uncommitted changes, use --all to discard all changes")
5174 else:
5174 else:
5175 hint = _("use --all to revert all files")
5175 hint = _("use --all to revert all files")
5176 raise util.Abort(msg, hint=hint)
5176 raise util.Abort(msg, hint=hint)
5177
5177
5178 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5178 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5179
5179
5180 @command('rollback', dryrunopts +
5180 @command('rollback', dryrunopts +
5181 [('f', 'force', False, _('ignore safety measures'))])
5181 [('f', 'force', False, _('ignore safety measures'))])
5182 def rollback(ui, repo, **opts):
5182 def rollback(ui, repo, **opts):
5183 """roll back the last transaction (dangerous)
5183 """roll back the last transaction (dangerous)
5184
5184
5185 This command should be used with care. There is only one level of
5185 This command should be used with care. There is only one level of
5186 rollback, and there is no way to undo a rollback. It will also
5186 rollback, and there is no way to undo a rollback. It will also
5187 restore the dirstate at the time of the last transaction, losing
5187 restore the dirstate at the time of the last transaction, losing
5188 any dirstate changes since that time. This command does not alter
5188 any dirstate changes since that time. This command does not alter
5189 the working directory.
5189 the working directory.
5190
5190
5191 Transactions are used to encapsulate the effects of all commands
5191 Transactions are used to encapsulate the effects of all commands
5192 that create new changesets or propagate existing changesets into a
5192 that create new changesets or propagate existing changesets into a
5193 repository.
5193 repository.
5194
5194
5195 .. container:: verbose
5195 .. container:: verbose
5196
5196
5197 For example, the following commands are transactional, and their
5197 For example, the following commands are transactional, and their
5198 effects can be rolled back:
5198 effects can be rolled back:
5199
5199
5200 - commit
5200 - commit
5201 - import
5201 - import
5202 - pull
5202 - pull
5203 - push (with this repository as the destination)
5203 - push (with this repository as the destination)
5204 - unbundle
5204 - unbundle
5205
5205
5206 To avoid permanent data loss, rollback will refuse to rollback a
5206 To avoid permanent data loss, rollback will refuse to rollback a
5207 commit transaction if it isn't checked out. Use --force to
5207 commit transaction if it isn't checked out. Use --force to
5208 override this protection.
5208 override this protection.
5209
5209
5210 This command is not intended for use on public repositories. Once
5210 This command is not intended for use on public repositories. Once
5211 changes are visible for pull by other users, rolling a transaction
5211 changes are visible for pull by other users, rolling a transaction
5212 back locally is ineffective (someone else may already have pulled
5212 back locally is ineffective (someone else may already have pulled
5213 the changes). Furthermore, a race is possible with readers of the
5213 the changes). Furthermore, a race is possible with readers of the
5214 repository; for example an in-progress pull from the repository
5214 repository; for example an in-progress pull from the repository
5215 may fail if a rollback is performed.
5215 may fail if a rollback is performed.
5216
5216
5217 Returns 0 on success, 1 if no rollback data is available.
5217 Returns 0 on success, 1 if no rollback data is available.
5218 """
5218 """
5219 return repo.rollback(dryrun=opts.get('dry_run'),
5219 return repo.rollback(dryrun=opts.get('dry_run'),
5220 force=opts.get('force'))
5220 force=opts.get('force'))
5221
5221
5222 @command('root', [])
5222 @command('root', [])
5223 def root(ui, repo):
5223 def root(ui, repo):
5224 """print the root (top) of the current working directory
5224 """print the root (top) of the current working directory
5225
5225
5226 Print the root directory of the current repository.
5226 Print the root directory of the current repository.
5227
5227
5228 Returns 0 on success.
5228 Returns 0 on success.
5229 """
5229 """
5230 ui.write(repo.root + "\n")
5230 ui.write(repo.root + "\n")
5231
5231
5232 @command('^serve',
5232 @command('^serve',
5233 [('A', 'accesslog', '', _('name of access log file to write to'),
5233 [('A', 'accesslog', '', _('name of access log file to write to'),
5234 _('FILE')),
5234 _('FILE')),
5235 ('d', 'daemon', None, _('run server in background')),
5235 ('d', 'daemon', None, _('run server in background')),
5236 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5236 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5237 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5237 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5238 # use string type, then we can check if something was passed
5238 # use string type, then we can check if something was passed
5239 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5239 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5240 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5240 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5241 _('ADDR')),
5241 _('ADDR')),
5242 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5242 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5243 _('PREFIX')),
5243 _('PREFIX')),
5244 ('n', 'name', '',
5244 ('n', 'name', '',
5245 _('name to show in web pages (default: working directory)'), _('NAME')),
5245 _('name to show in web pages (default: working directory)'), _('NAME')),
5246 ('', 'web-conf', '',
5246 ('', 'web-conf', '',
5247 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5247 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5248 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5248 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5249 _('FILE')),
5249 _('FILE')),
5250 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5250 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5251 ('', 'stdio', None, _('for remote clients')),
5251 ('', 'stdio', None, _('for remote clients')),
5252 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5252 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5253 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5253 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5254 ('', 'style', '', _('template style to use'), _('STYLE')),
5254 ('', 'style', '', _('template style to use'), _('STYLE')),
5255 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5255 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5256 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5256 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5257 _('[OPTION]...'))
5257 _('[OPTION]...'))
5258 def serve(ui, repo, **opts):
5258 def serve(ui, repo, **opts):
5259 """start stand-alone webserver
5259 """start stand-alone webserver
5260
5260
5261 Start a local HTTP repository browser and pull server. You can use
5261 Start a local HTTP repository browser and pull server. You can use
5262 this for ad-hoc sharing and browsing of repositories. It is
5262 this for ad-hoc sharing and browsing of repositories. It is
5263 recommended to use a real web server to serve a repository for
5263 recommended to use a real web server to serve a repository for
5264 longer periods of time.
5264 longer periods of time.
5265
5265
5266 Please note that the server does not implement access control.
5266 Please note that the server does not implement access control.
5267 This means that, by default, anybody can read from the server and
5267 This means that, by default, anybody can read from the server and
5268 nobody can write to it by default. Set the ``web.allow_push``
5268 nobody can write to it by default. Set the ``web.allow_push``
5269 option to ``*`` to allow everybody to push to the server. You
5269 option to ``*`` to allow everybody to push to the server. You
5270 should use a real web server if you need to authenticate users.
5270 should use a real web server if you need to authenticate users.
5271
5271
5272 By default, the server logs accesses to stdout and errors to
5272 By default, the server logs accesses to stdout and errors to
5273 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5273 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5274 files.
5274 files.
5275
5275
5276 To have the server choose a free port number to listen on, specify
5276 To have the server choose a free port number to listen on, specify
5277 a port number of 0; in this case, the server will print the port
5277 a port number of 0; in this case, the server will print the port
5278 number it uses.
5278 number it uses.
5279
5279
5280 Returns 0 on success.
5280 Returns 0 on success.
5281 """
5281 """
5282
5282
5283 if opts["stdio"] and opts["cmdserver"]:
5283 if opts["stdio"] and opts["cmdserver"]:
5284 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5284 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5285
5285
5286 def checkrepo():
5286 def checkrepo():
5287 if repo is None:
5287 if repo is None:
5288 raise error.RepoError(_("there is no Mercurial repository here"
5288 raise error.RepoError(_("there is no Mercurial repository here"
5289 " (.hg not found)"))
5289 " (.hg not found)"))
5290
5290
5291 if opts["stdio"]:
5291 if opts["stdio"]:
5292 checkrepo()
5292 checkrepo()
5293 s = sshserver.sshserver(ui, repo)
5293 s = sshserver.sshserver(ui, repo)
5294 s.serve_forever()
5294 s.serve_forever()
5295
5295
5296 if opts["cmdserver"]:
5296 if opts["cmdserver"]:
5297 checkrepo()
5297 checkrepo()
5298 s = commandserver.server(ui, repo, opts["cmdserver"])
5298 s = commandserver.server(ui, repo, opts["cmdserver"])
5299 return s.serve()
5299 return s.serve()
5300
5300
5301 # this way we can check if something was given in the command-line
5301 # this way we can check if something was given in the command-line
5302 if opts.get('port'):
5302 if opts.get('port'):
5303 opts['port'] = util.getport(opts.get('port'))
5303 opts['port'] = util.getport(opts.get('port'))
5304
5304
5305 baseui = repo and repo.baseui or ui
5305 baseui = repo and repo.baseui or ui
5306 optlist = ("name templates style address port prefix ipv6"
5306 optlist = ("name templates style address port prefix ipv6"
5307 " accesslog errorlog certificate encoding")
5307 " accesslog errorlog certificate encoding")
5308 for o in optlist.split():
5308 for o in optlist.split():
5309 val = opts.get(o, '')
5309 val = opts.get(o, '')
5310 if val in (None, ''): # should check against default options instead
5310 if val in (None, ''): # should check against default options instead
5311 continue
5311 continue
5312 baseui.setconfig("web", o, val)
5312 baseui.setconfig("web", o, val)
5313 if repo and repo.ui != baseui:
5313 if repo and repo.ui != baseui:
5314 repo.ui.setconfig("web", o, val)
5314 repo.ui.setconfig("web", o, val)
5315
5315
5316 o = opts.get('web_conf') or opts.get('webdir_conf')
5316 o = opts.get('web_conf') or opts.get('webdir_conf')
5317 if not o:
5317 if not o:
5318 if not repo:
5318 if not repo:
5319 raise error.RepoError(_("there is no Mercurial repository"
5319 raise error.RepoError(_("there is no Mercurial repository"
5320 " here (.hg not found)"))
5320 " here (.hg not found)"))
5321 o = repo.root
5321 o = repo.root
5322
5322
5323 app = hgweb.hgweb(o, baseui=ui)
5323 app = hgweb.hgweb(o, baseui=ui)
5324
5324
5325 class service(object):
5325 class service(object):
5326 def init(self):
5326 def init(self):
5327 util.setsignalhandler()
5327 util.setsignalhandler()
5328 self.httpd = hgweb.server.create_server(ui, app)
5328 self.httpd = hgweb.server.create_server(ui, app)
5329
5329
5330 if opts['port'] and not ui.verbose:
5330 if opts['port'] and not ui.verbose:
5331 return
5331 return
5332
5332
5333 if self.httpd.prefix:
5333 if self.httpd.prefix:
5334 prefix = self.httpd.prefix.strip('/') + '/'
5334 prefix = self.httpd.prefix.strip('/') + '/'
5335 else:
5335 else:
5336 prefix = ''
5336 prefix = ''
5337
5337
5338 port = ':%d' % self.httpd.port
5338 port = ':%d' % self.httpd.port
5339 if port == ':80':
5339 if port == ':80':
5340 port = ''
5340 port = ''
5341
5341
5342 bindaddr = self.httpd.addr
5342 bindaddr = self.httpd.addr
5343 if bindaddr == '0.0.0.0':
5343 if bindaddr == '0.0.0.0':
5344 bindaddr = '*'
5344 bindaddr = '*'
5345 elif ':' in bindaddr: # IPv6
5345 elif ':' in bindaddr: # IPv6
5346 bindaddr = '[%s]' % bindaddr
5346 bindaddr = '[%s]' % bindaddr
5347
5347
5348 fqaddr = self.httpd.fqaddr
5348 fqaddr = self.httpd.fqaddr
5349 if ':' in fqaddr:
5349 if ':' in fqaddr:
5350 fqaddr = '[%s]' % fqaddr
5350 fqaddr = '[%s]' % fqaddr
5351 if opts['port']:
5351 if opts['port']:
5352 write = ui.status
5352 write = ui.status
5353 else:
5353 else:
5354 write = ui.write
5354 write = ui.write
5355 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5355 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5356 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5356 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5357
5357
5358 def run(self):
5358 def run(self):
5359 self.httpd.serve_forever()
5359 self.httpd.serve_forever()
5360
5360
5361 service = service()
5361 service = service()
5362
5362
5363 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5363 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5364
5364
5365 @command('showconfig|debugconfig',
5365 @command('showconfig|debugconfig',
5366 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5366 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5367 _('[-u] [NAME]...'))
5367 _('[-u] [NAME]...'))
5368 def showconfig(ui, repo, *values, **opts):
5368 def showconfig(ui, repo, *values, **opts):
5369 """show combined config settings from all hgrc files
5369 """show combined config settings from all hgrc files
5370
5370
5371 With no arguments, print names and values of all config items.
5371 With no arguments, print names and values of all config items.
5372
5372
5373 With one argument of the form section.name, print just the value
5373 With one argument of the form section.name, print just the value
5374 of that config item.
5374 of that config item.
5375
5375
5376 With multiple arguments, print names and values of all config
5376 With multiple arguments, print names and values of all config
5377 items with matching section names.
5377 items with matching section names.
5378
5378
5379 With --debug, the source (filename and line number) is printed
5379 With --debug, the source (filename and line number) is printed
5380 for each config item.
5380 for each config item.
5381
5381
5382 Returns 0 on success.
5382 Returns 0 on success.
5383 """
5383 """
5384
5384
5385 for f in scmutil.rcpath():
5385 for f in scmutil.rcpath():
5386 ui.debug('read config from: %s\n' % f)
5386 ui.debug('read config from: %s\n' % f)
5387 untrusted = bool(opts.get('untrusted'))
5387 untrusted = bool(opts.get('untrusted'))
5388 if values:
5388 if values:
5389 sections = [v for v in values if '.' not in v]
5389 sections = [v for v in values if '.' not in v]
5390 items = [v for v in values if '.' in v]
5390 items = [v for v in values if '.' in v]
5391 if len(items) > 1 or items and sections:
5391 if len(items) > 1 or items and sections:
5392 raise util.Abort(_('only one config item permitted'))
5392 raise util.Abort(_('only one config item permitted'))
5393 for section, name, value in ui.walkconfig(untrusted=untrusted):
5393 for section, name, value in ui.walkconfig(untrusted=untrusted):
5394 value = str(value).replace('\n', '\\n')
5394 value = str(value).replace('\n', '\\n')
5395 sectname = section + '.' + name
5395 sectname = section + '.' + name
5396 if values:
5396 if values:
5397 for v in values:
5397 for v in values:
5398 if v == section:
5398 if v == section:
5399 ui.debug('%s: ' %
5399 ui.debug('%s: ' %
5400 ui.configsource(section, name, untrusted))
5400 ui.configsource(section, name, untrusted))
5401 ui.write('%s=%s\n' % (sectname, value))
5401 ui.write('%s=%s\n' % (sectname, value))
5402 elif v == sectname:
5402 elif v == sectname:
5403 ui.debug('%s: ' %
5403 ui.debug('%s: ' %
5404 ui.configsource(section, name, untrusted))
5404 ui.configsource(section, name, untrusted))
5405 ui.write(value, '\n')
5405 ui.write(value, '\n')
5406 else:
5406 else:
5407 ui.debug('%s: ' %
5407 ui.debug('%s: ' %
5408 ui.configsource(section, name, untrusted))
5408 ui.configsource(section, name, untrusted))
5409 ui.write('%s=%s\n' % (sectname, value))
5409 ui.write('%s=%s\n' % (sectname, value))
5410
5410
5411 @command('^status|st',
5411 @command('^status|st',
5412 [('A', 'all', None, _('show status of all files')),
5412 [('A', 'all', None, _('show status of all files')),
5413 ('m', 'modified', None, _('show only modified files')),
5413 ('m', 'modified', None, _('show only modified files')),
5414 ('a', 'added', None, _('show only added files')),
5414 ('a', 'added', None, _('show only added files')),
5415 ('r', 'removed', None, _('show only removed files')),
5415 ('r', 'removed', None, _('show only removed files')),
5416 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5416 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5417 ('c', 'clean', None, _('show only files without changes')),
5417 ('c', 'clean', None, _('show only files without changes')),
5418 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5418 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5419 ('i', 'ignored', None, _('show only ignored files')),
5419 ('i', 'ignored', None, _('show only ignored files')),
5420 ('n', 'no-status', None, _('hide status prefix')),
5420 ('n', 'no-status', None, _('hide status prefix')),
5421 ('C', 'copies', None, _('show source of copied files')),
5421 ('C', 'copies', None, _('show source of copied files')),
5422 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5422 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5423 ('', 'rev', [], _('show difference from revision'), _('REV')),
5423 ('', 'rev', [], _('show difference from revision'), _('REV')),
5424 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5424 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5425 ] + walkopts + subrepoopts,
5425 ] + walkopts + subrepoopts,
5426 _('[OPTION]... [FILE]...'))
5426 _('[OPTION]... [FILE]...'))
5427 def status(ui, repo, *pats, **opts):
5427 def status(ui, repo, *pats, **opts):
5428 """show changed files in the working directory
5428 """show changed files in the working directory
5429
5429
5430 Show status of files in the repository. If names are given, only
5430 Show status of files in the repository. If names are given, only
5431 files that match are shown. Files that are clean or ignored or
5431 files that match are shown. Files that are clean or ignored or
5432 the source of a copy/move operation, are not listed unless
5432 the source of a copy/move operation, are not listed unless
5433 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5433 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5434 Unless options described with "show only ..." are given, the
5434 Unless options described with "show only ..." are given, the
5435 options -mardu are used.
5435 options -mardu are used.
5436
5436
5437 Option -q/--quiet hides untracked (unknown and ignored) files
5437 Option -q/--quiet hides untracked (unknown and ignored) files
5438 unless explicitly requested with -u/--unknown or -i/--ignored.
5438 unless explicitly requested with -u/--unknown or -i/--ignored.
5439
5439
5440 .. note::
5440 .. note::
5441 status may appear to disagree with diff if permissions have
5441 status may appear to disagree with diff if permissions have
5442 changed or a merge has occurred. The standard diff format does
5442 changed or a merge has occurred. The standard diff format does
5443 not report permission changes and diff only reports changes
5443 not report permission changes and diff only reports changes
5444 relative to one merge parent.
5444 relative to one merge parent.
5445
5445
5446 If one revision is given, it is used as the base revision.
5446 If one revision is given, it is used as the base revision.
5447 If two revisions are given, the differences between them are
5447 If two revisions are given, the differences between them are
5448 shown. The --change option can also be used as a shortcut to list
5448 shown. The --change option can also be used as a shortcut to list
5449 the changed files of a revision from its first parent.
5449 the changed files of a revision from its first parent.
5450
5450
5451 The codes used to show the status of files are::
5451 The codes used to show the status of files are::
5452
5452
5453 M = modified
5453 M = modified
5454 A = added
5454 A = added
5455 R = removed
5455 R = removed
5456 C = clean
5456 C = clean
5457 ! = missing (deleted by non-hg command, but still tracked)
5457 ! = missing (deleted by non-hg command, but still tracked)
5458 ? = not tracked
5458 ? = not tracked
5459 I = ignored
5459 I = ignored
5460 = origin of the previous file listed as A (added)
5460 = origin of the previous file listed as A (added)
5461
5461
5462 .. container:: verbose
5462 .. container:: verbose
5463
5463
5464 Examples:
5464 Examples:
5465
5465
5466 - show changes in the working directory relative to a
5466 - show changes in the working directory relative to a
5467 changeset::
5467 changeset::
5468
5468
5469 hg status --rev 9353
5469 hg status --rev 9353
5470
5470
5471 - show all changes including copies in an existing changeset::
5471 - show all changes including copies in an existing changeset::
5472
5472
5473 hg status --copies --change 9353
5473 hg status --copies --change 9353
5474
5474
5475 - get a NUL separated list of added files, suitable for xargs::
5475 - get a NUL separated list of added files, suitable for xargs::
5476
5476
5477 hg status -an0
5477 hg status -an0
5478
5478
5479 Returns 0 on success.
5479 Returns 0 on success.
5480 """
5480 """
5481
5481
5482 revs = opts.get('rev')
5482 revs = opts.get('rev')
5483 change = opts.get('change')
5483 change = opts.get('change')
5484
5484
5485 if revs and change:
5485 if revs and change:
5486 msg = _('cannot specify --rev and --change at the same time')
5486 msg = _('cannot specify --rev and --change at the same time')
5487 raise util.Abort(msg)
5487 raise util.Abort(msg)
5488 elif change:
5488 elif change:
5489 node2 = scmutil.revsingle(repo, change, None).node()
5489 node2 = scmutil.revsingle(repo, change, None).node()
5490 node1 = repo[node2].p1().node()
5490 node1 = repo[node2].p1().node()
5491 else:
5491 else:
5492 node1, node2 = scmutil.revpair(repo, revs)
5492 node1, node2 = scmutil.revpair(repo, revs)
5493
5493
5494 cwd = (pats and repo.getcwd()) or ''
5494 cwd = (pats and repo.getcwd()) or ''
5495 end = opts.get('print0') and '\0' or '\n'
5495 end = opts.get('print0') and '\0' or '\n'
5496 copy = {}
5496 copy = {}
5497 states = 'modified added removed deleted unknown ignored clean'.split()
5497 states = 'modified added removed deleted unknown ignored clean'.split()
5498 show = [k for k in states if opts.get(k)]
5498 show = [k for k in states if opts.get(k)]
5499 if opts.get('all'):
5499 if opts.get('all'):
5500 show += ui.quiet and (states[:4] + ['clean']) or states
5500 show += ui.quiet and (states[:4] + ['clean']) or states
5501 if not show:
5501 if not show:
5502 show = ui.quiet and states[:4] or states[:5]
5502 show = ui.quiet and states[:4] or states[:5]
5503
5503
5504 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5504 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5505 'ignored' in show, 'clean' in show, 'unknown' in show,
5505 'ignored' in show, 'clean' in show, 'unknown' in show,
5506 opts.get('subrepos'))
5506 opts.get('subrepos'))
5507 changestates = zip(states, 'MAR!?IC', stat)
5507 changestates = zip(states, 'MAR!?IC', stat)
5508
5508
5509 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5509 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5510 copy = copies.pathcopies(repo[node1], repo[node2])
5510 copy = copies.pathcopies(repo[node1], repo[node2])
5511
5511
5512 fm = ui.formatter('status', opts)
5512 fm = ui.formatter('status', opts)
5513 fmt = '%s' + end
5513 fmt = '%s' + end
5514 showchar = not opts.get('no_status')
5514 showchar = not opts.get('no_status')
5515
5515
5516 for state, char, files in changestates:
5516 for state, char, files in changestates:
5517 if state in show:
5517 if state in show:
5518 label = 'status.' + state
5518 label = 'status.' + state
5519 for f in files:
5519 for f in files:
5520 fm.startitem()
5520 fm.startitem()
5521 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5521 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5522 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5522 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5523 if f in copy:
5523 if f in copy:
5524 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5524 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5525 label='status.copied')
5525 label='status.copied')
5526 fm.end()
5526 fm.end()
5527
5527
5528 @command('^summary|sum',
5528 @command('^summary|sum',
5529 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5529 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5530 def summary(ui, repo, **opts):
5530 def summary(ui, repo, **opts):
5531 """summarize working directory state
5531 """summarize working directory state
5532
5532
5533 This generates a brief summary of the working directory state,
5533 This generates a brief summary of the working directory state,
5534 including parents, branch, commit status, and available updates.
5534 including parents, branch, commit status, and available updates.
5535
5535
5536 With the --remote option, this will check the default paths for
5536 With the --remote option, this will check the default paths for
5537 incoming and outgoing changes. This can be time-consuming.
5537 incoming and outgoing changes. This can be time-consuming.
5538
5538
5539 Returns 0 on success.
5539 Returns 0 on success.
5540 """
5540 """
5541
5541
5542 ctx = repo[None]
5542 ctx = repo[None]
5543 parents = ctx.parents()
5543 parents = ctx.parents()
5544 pnode = parents[0].node()
5544 pnode = parents[0].node()
5545 marks = []
5545 marks = []
5546
5546
5547 for p in parents:
5547 for p in parents:
5548 # label with log.changeset (instead of log.parent) since this
5548 # label with log.changeset (instead of log.parent) since this
5549 # shows a working directory parent *changeset*:
5549 # shows a working directory parent *changeset*:
5550 # i18n: column positioning for "hg summary"
5550 # i18n: column positioning for "hg summary"
5551 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5551 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5552 label='log.changeset changeset.%s' % p.phasestr())
5552 label='log.changeset changeset.%s' % p.phasestr())
5553 ui.write(' '.join(p.tags()), label='log.tag')
5553 ui.write(' '.join(p.tags()), label='log.tag')
5554 if p.bookmarks():
5554 if p.bookmarks():
5555 marks.extend(p.bookmarks())
5555 marks.extend(p.bookmarks())
5556 if p.rev() == -1:
5556 if p.rev() == -1:
5557 if not len(repo):
5557 if not len(repo):
5558 ui.write(_(' (empty repository)'))
5558 ui.write(_(' (empty repository)'))
5559 else:
5559 else:
5560 ui.write(_(' (no revision checked out)'))
5560 ui.write(_(' (no revision checked out)'))
5561 ui.write('\n')
5561 ui.write('\n')
5562 if p.description():
5562 if p.description():
5563 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5563 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5564 label='log.summary')
5564 label='log.summary')
5565
5565
5566 branch = ctx.branch()
5566 branch = ctx.branch()
5567 bheads = repo.branchheads(branch)
5567 bheads = repo.branchheads(branch)
5568 # i18n: column positioning for "hg summary"
5568 # i18n: column positioning for "hg summary"
5569 m = _('branch: %s\n') % branch
5569 m = _('branch: %s\n') % branch
5570 if branch != 'default':
5570 if branch != 'default':
5571 ui.write(m, label='log.branch')
5571 ui.write(m, label='log.branch')
5572 else:
5572 else:
5573 ui.status(m, label='log.branch')
5573 ui.status(m, label='log.branch')
5574
5574
5575 if marks:
5575 if marks:
5576 current = repo._bookmarkcurrent
5576 current = repo._bookmarkcurrent
5577 # i18n: column positioning for "hg summary"
5577 # i18n: column positioning for "hg summary"
5578 ui.write(_('bookmarks:'), label='log.bookmark')
5578 ui.write(_('bookmarks:'), label='log.bookmark')
5579 if current is not None:
5579 if current is not None:
5580 try:
5580 try:
5581 marks.remove(current)
5581 marks.remove(current)
5582 ui.write(' *' + current, label='bookmarks.current')
5582 ui.write(' *' + current, label='bookmarks.current')
5583 except ValueError:
5583 except ValueError:
5584 # current bookmark not in parent ctx marks
5584 # current bookmark not in parent ctx marks
5585 pass
5585 pass
5586 for m in marks:
5586 for m in marks:
5587 ui.write(' ' + m, label='log.bookmark')
5587 ui.write(' ' + m, label='log.bookmark')
5588 ui.write('\n', label='log.bookmark')
5588 ui.write('\n', label='log.bookmark')
5589
5589
5590 st = list(repo.status(unknown=True))[:6]
5590 st = list(repo.status(unknown=True))[:6]
5591
5591
5592 c = repo.dirstate.copies()
5592 c = repo.dirstate.copies()
5593 copied, renamed = [], []
5593 copied, renamed = [], []
5594 for d, s in c.iteritems():
5594 for d, s in c.iteritems():
5595 if s in st[2]:
5595 if s in st[2]:
5596 st[2].remove(s)
5596 st[2].remove(s)
5597 renamed.append(d)
5597 renamed.append(d)
5598 else:
5598 else:
5599 copied.append(d)
5599 copied.append(d)
5600 if d in st[1]:
5600 if d in st[1]:
5601 st[1].remove(d)
5601 st[1].remove(d)
5602 st.insert(3, renamed)
5602 st.insert(3, renamed)
5603 st.insert(4, copied)
5603 st.insert(4, copied)
5604
5604
5605 ms = mergemod.mergestate(repo)
5605 ms = mergemod.mergestate(repo)
5606 st.append([f for f in ms if ms[f] == 'u'])
5606 st.append([f for f in ms if ms[f] == 'u'])
5607
5607
5608 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5608 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5609 st.append(subs)
5609 st.append(subs)
5610
5610
5611 labels = [ui.label(_('%d modified'), 'status.modified'),
5611 labels = [ui.label(_('%d modified'), 'status.modified'),
5612 ui.label(_('%d added'), 'status.added'),
5612 ui.label(_('%d added'), 'status.added'),
5613 ui.label(_('%d removed'), 'status.removed'),
5613 ui.label(_('%d removed'), 'status.removed'),
5614 ui.label(_('%d renamed'), 'status.copied'),
5614 ui.label(_('%d renamed'), 'status.copied'),
5615 ui.label(_('%d copied'), 'status.copied'),
5615 ui.label(_('%d copied'), 'status.copied'),
5616 ui.label(_('%d deleted'), 'status.deleted'),
5616 ui.label(_('%d deleted'), 'status.deleted'),
5617 ui.label(_('%d unknown'), 'status.unknown'),
5617 ui.label(_('%d unknown'), 'status.unknown'),
5618 ui.label(_('%d ignored'), 'status.ignored'),
5618 ui.label(_('%d ignored'), 'status.ignored'),
5619 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5619 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5620 ui.label(_('%d subrepos'), 'status.modified')]
5620 ui.label(_('%d subrepos'), 'status.modified')]
5621 t = []
5621 t = []
5622 for s, l in zip(st, labels):
5622 for s, l in zip(st, labels):
5623 if s:
5623 if s:
5624 t.append(l % len(s))
5624 t.append(l % len(s))
5625
5625
5626 t = ', '.join(t)
5626 t = ', '.join(t)
5627 cleanworkdir = False
5627 cleanworkdir = False
5628
5628
5629 if len(parents) > 1:
5629 if len(parents) > 1:
5630 t += _(' (merge)')
5630 t += _(' (merge)')
5631 elif branch != parents[0].branch():
5631 elif branch != parents[0].branch():
5632 t += _(' (new branch)')
5632 t += _(' (new branch)')
5633 elif (parents[0].closesbranch() and
5633 elif (parents[0].closesbranch() and
5634 pnode in repo.branchheads(branch, closed=True)):
5634 pnode in repo.branchheads(branch, closed=True)):
5635 t += _(' (head closed)')
5635 t += _(' (head closed)')
5636 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5636 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5637 t += _(' (clean)')
5637 t += _(' (clean)')
5638 cleanworkdir = True
5638 cleanworkdir = True
5639 elif pnode not in bheads:
5639 elif pnode not in bheads:
5640 t += _(' (new branch head)')
5640 t += _(' (new branch head)')
5641
5641
5642 if cleanworkdir:
5642 if cleanworkdir:
5643 # i18n: column positioning for "hg summary"
5643 # i18n: column positioning for "hg summary"
5644 ui.status(_('commit: %s\n') % t.strip())
5644 ui.status(_('commit: %s\n') % t.strip())
5645 else:
5645 else:
5646 # i18n: column positioning for "hg summary"
5646 # i18n: column positioning for "hg summary"
5647 ui.write(_('commit: %s\n') % t.strip())
5647 ui.write(_('commit: %s\n') % t.strip())
5648
5648
5649 # all ancestors of branch heads - all ancestors of parent = new csets
5649 # all ancestors of branch heads - all ancestors of parent = new csets
5650 new = [0] * len(repo)
5650 new = [0] * len(repo)
5651 cl = repo.changelog
5651 cl = repo.changelog
5652 for a in [cl.rev(n) for n in bheads]:
5652 for a in [cl.rev(n) for n in bheads]:
5653 new[a] = 1
5653 new[a] = 1
5654 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5654 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5655 new[a] = 1
5655 new[a] = 1
5656 for a in [p.rev() for p in parents]:
5656 for a in [p.rev() for p in parents]:
5657 if a >= 0:
5657 if a >= 0:
5658 new[a] = 0
5658 new[a] = 0
5659 for a in cl.ancestors([p.rev() for p in parents]):
5659 for a in cl.ancestors([p.rev() for p in parents]):
5660 new[a] = 0
5660 new[a] = 0
5661 new = sum(new)
5661 new = sum(new)
5662
5662
5663 if new == 0:
5663 if new == 0:
5664 # i18n: column positioning for "hg summary"
5664 # i18n: column positioning for "hg summary"
5665 ui.status(_('update: (current)\n'))
5665 ui.status(_('update: (current)\n'))
5666 elif pnode not in bheads:
5666 elif pnode not in bheads:
5667 # i18n: column positioning for "hg summary"
5667 # i18n: column positioning for "hg summary"
5668 ui.write(_('update: %d new changesets (update)\n') % new)
5668 ui.write(_('update: %d new changesets (update)\n') % new)
5669 else:
5669 else:
5670 # i18n: column positioning for "hg summary"
5670 # i18n: column positioning for "hg summary"
5671 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5671 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5672 (new, len(bheads)))
5672 (new, len(bheads)))
5673
5673
5674 if opts.get('remote'):
5674 if opts.get('remote'):
5675 t = []
5675 t = []
5676 source, branches = hg.parseurl(ui.expandpath('default'))
5676 source, branches = hg.parseurl(ui.expandpath('default'))
5677 other = hg.peer(repo, {}, source)
5677 other = hg.peer(repo, {}, source)
5678 revs, checkout = hg.addbranchrevs(repo, other, branches,
5678 revs, checkout = hg.addbranchrevs(repo, other, branches,
5679 opts.get('rev'))
5679 opts.get('rev'))
5680 ui.debug('comparing with %s\n' % util.hidepassword(source))
5680 ui.debug('comparing with %s\n' % util.hidepassword(source))
5681 repo.ui.pushbuffer()
5681 repo.ui.pushbuffer()
5682 commoninc = discovery.findcommonincoming(repo, other)
5682 commoninc = discovery.findcommonincoming(repo, other)
5683 _common, incoming, _rheads = commoninc
5683 _common, incoming, _rheads = commoninc
5684 repo.ui.popbuffer()
5684 repo.ui.popbuffer()
5685 if incoming:
5685 if incoming:
5686 t.append(_('1 or more incoming'))
5686 t.append(_('1 or more incoming'))
5687
5687
5688 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5688 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5689 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5689 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5690 if source != dest:
5690 if source != dest:
5691 other = hg.peer(repo, {}, dest)
5691 other = hg.peer(repo, {}, dest)
5692 commoninc = None
5692 commoninc = None
5693 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5693 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5694 repo.ui.pushbuffer()
5694 repo.ui.pushbuffer()
5695 outgoing = discovery.findcommonoutgoing(repo, other,
5695 outgoing = discovery.findcommonoutgoing(repo, other,
5696 commoninc=commoninc)
5696 commoninc=commoninc)
5697 repo.ui.popbuffer()
5697 repo.ui.popbuffer()
5698 o = outgoing.missing
5698 o = outgoing.missing
5699 if o:
5699 if o:
5700 t.append(_('%d outgoing') % len(o))
5700 t.append(_('%d outgoing') % len(o))
5701 if 'bookmarks' in other.listkeys('namespaces'):
5701 if 'bookmarks' in other.listkeys('namespaces'):
5702 lmarks = repo.listkeys('bookmarks')
5702 lmarks = repo.listkeys('bookmarks')
5703 rmarks = other.listkeys('bookmarks')
5703 rmarks = other.listkeys('bookmarks')
5704 diff = set(rmarks) - set(lmarks)
5704 diff = set(rmarks) - set(lmarks)
5705 if len(diff) > 0:
5705 if len(diff) > 0:
5706 t.append(_('%d incoming bookmarks') % len(diff))
5706 t.append(_('%d incoming bookmarks') % len(diff))
5707 diff = set(lmarks) - set(rmarks)
5707 diff = set(lmarks) - set(rmarks)
5708 if len(diff) > 0:
5708 if len(diff) > 0:
5709 t.append(_('%d outgoing bookmarks') % len(diff))
5709 t.append(_('%d outgoing bookmarks') % len(diff))
5710
5710
5711 if t:
5711 if t:
5712 # i18n: column positioning for "hg summary"
5712 # i18n: column positioning for "hg summary"
5713 ui.write(_('remote: %s\n') % (', '.join(t)))
5713 ui.write(_('remote: %s\n') % (', '.join(t)))
5714 else:
5714 else:
5715 # i18n: column positioning for "hg summary"
5715 # i18n: column positioning for "hg summary"
5716 ui.status(_('remote: (synced)\n'))
5716 ui.status(_('remote: (synced)\n'))
5717
5717
5718 @command('tag',
5718 @command('tag',
5719 [('f', 'force', None, _('force tag')),
5719 [('f', 'force', None, _('force tag')),
5720 ('l', 'local', None, _('make the tag local')),
5720 ('l', 'local', None, _('make the tag local')),
5721 ('r', 'rev', '', _('revision to tag'), _('REV')),
5721 ('r', 'rev', '', _('revision to tag'), _('REV')),
5722 ('', 'remove', None, _('remove a tag')),
5722 ('', 'remove', None, _('remove a tag')),
5723 # -l/--local is already there, commitopts cannot be used
5723 # -l/--local is already there, commitopts cannot be used
5724 ('e', 'edit', None, _('edit commit message')),
5724 ('e', 'edit', None, _('edit commit message')),
5725 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5725 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5726 ] + commitopts2,
5726 ] + commitopts2,
5727 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5727 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5728 def tag(ui, repo, name1, *names, **opts):
5728 def tag(ui, repo, name1, *names, **opts):
5729 """add one or more tags for the current or given revision
5729 """add one or more tags for the current or given revision
5730
5730
5731 Name a particular revision using <name>.
5731 Name a particular revision using <name>.
5732
5732
5733 Tags are used to name particular revisions of the repository and are
5733 Tags are used to name particular revisions of the repository and are
5734 very useful to compare different revisions, to go back to significant
5734 very useful to compare different revisions, to go back to significant
5735 earlier versions or to mark branch points as releases, etc. Changing
5735 earlier versions or to mark branch points as releases, etc. Changing
5736 an existing tag is normally disallowed; use -f/--force to override.
5736 an existing tag is normally disallowed; use -f/--force to override.
5737
5737
5738 If no revision is given, the parent of the working directory is
5738 If no revision is given, the parent of the working directory is
5739 used, or tip if no revision is checked out.
5739 used, or tip if no revision is checked out.
5740
5740
5741 To facilitate version control, distribution, and merging of tags,
5741 To facilitate version control, distribution, and merging of tags,
5742 they are stored as a file named ".hgtags" which is managed similarly
5742 they are stored as a file named ".hgtags" which is managed similarly
5743 to other project files and can be hand-edited if necessary. This
5743 to other project files and can be hand-edited if necessary. This
5744 also means that tagging creates a new commit. The file
5744 also means that tagging creates a new commit. The file
5745 ".hg/localtags" is used for local tags (not shared among
5745 ".hg/localtags" is used for local tags (not shared among
5746 repositories).
5746 repositories).
5747
5747
5748 Tag commits are usually made at the head of a branch. If the parent
5748 Tag commits are usually made at the head of a branch. If the parent
5749 of the working directory is not a branch head, :hg:`tag` aborts; use
5749 of the working directory is not a branch head, :hg:`tag` aborts; use
5750 -f/--force to force the tag commit to be based on a non-head
5750 -f/--force to force the tag commit to be based on a non-head
5751 changeset.
5751 changeset.
5752
5752
5753 See :hg:`help dates` for a list of formats valid for -d/--date.
5753 See :hg:`help dates` for a list of formats valid for -d/--date.
5754
5754
5755 Since tag names have priority over branch names during revision
5755 Since tag names have priority over branch names during revision
5756 lookup, using an existing branch name as a tag name is discouraged.
5756 lookup, using an existing branch name as a tag name is discouraged.
5757
5757
5758 Returns 0 on success.
5758 Returns 0 on success.
5759 """
5759 """
5760 wlock = lock = None
5760 wlock = lock = None
5761 try:
5761 try:
5762 wlock = repo.wlock()
5762 wlock = repo.wlock()
5763 lock = repo.lock()
5763 lock = repo.lock()
5764 rev_ = "."
5764 rev_ = "."
5765 names = [t.strip() for t in (name1,) + names]
5765 names = [t.strip() for t in (name1,) + names]
5766 if len(names) != len(set(names)):
5766 if len(names) != len(set(names)):
5767 raise util.Abort(_('tag names must be unique'))
5767 raise util.Abort(_('tag names must be unique'))
5768 for n in names:
5768 for n in names:
5769 scmutil.checknewlabel(repo, n, 'tag')
5769 scmutil.checknewlabel(repo, n, 'tag')
5770 if not n:
5770 if not n:
5771 raise util.Abort(_('tag names cannot consist entirely of '
5771 raise util.Abort(_('tag names cannot consist entirely of '
5772 'whitespace'))
5772 'whitespace'))
5773 if opts.get('rev') and opts.get('remove'):
5773 if opts.get('rev') and opts.get('remove'):
5774 raise util.Abort(_("--rev and --remove are incompatible"))
5774 raise util.Abort(_("--rev and --remove are incompatible"))
5775 if opts.get('rev'):
5775 if opts.get('rev'):
5776 rev_ = opts['rev']
5776 rev_ = opts['rev']
5777 message = opts.get('message')
5777 message = opts.get('message')
5778 if opts.get('remove'):
5778 if opts.get('remove'):
5779 expectedtype = opts.get('local') and 'local' or 'global'
5779 expectedtype = opts.get('local') and 'local' or 'global'
5780 for n in names:
5780 for n in names:
5781 if not repo.tagtype(n):
5781 if not repo.tagtype(n):
5782 raise util.Abort(_("tag '%s' does not exist") % n)
5782 raise util.Abort(_("tag '%s' does not exist") % n)
5783 if repo.tagtype(n) != expectedtype:
5783 if repo.tagtype(n) != expectedtype:
5784 if expectedtype == 'global':
5784 if expectedtype == 'global':
5785 raise util.Abort(_("tag '%s' is not a global tag") % n)
5785 raise util.Abort(_("tag '%s' is not a global tag") % n)
5786 else:
5786 else:
5787 raise util.Abort(_("tag '%s' is not a local tag") % n)
5787 raise util.Abort(_("tag '%s' is not a local tag") % n)
5788 rev_ = nullid
5788 rev_ = nullid
5789 if not message:
5789 if not message:
5790 # we don't translate commit messages
5790 # we don't translate commit messages
5791 message = 'Removed tag %s' % ', '.join(names)
5791 message = 'Removed tag %s' % ', '.join(names)
5792 elif not opts.get('force'):
5792 elif not opts.get('force'):
5793 for n in names:
5793 for n in names:
5794 if n in repo.tags():
5794 if n in repo.tags():
5795 raise util.Abort(_("tag '%s' already exists "
5795 raise util.Abort(_("tag '%s' already exists "
5796 "(use -f to force)") % n)
5796 "(use -f to force)") % n)
5797 if not opts.get('local'):
5797 if not opts.get('local'):
5798 p1, p2 = repo.dirstate.parents()
5798 p1, p2 = repo.dirstate.parents()
5799 if p2 != nullid:
5799 if p2 != nullid:
5800 raise util.Abort(_('uncommitted merge'))
5800 raise util.Abort(_('uncommitted merge'))
5801 bheads = repo.branchheads()
5801 bheads = repo.branchheads()
5802 if not opts.get('force') and bheads and p1 not in bheads:
5802 if not opts.get('force') and bheads and p1 not in bheads:
5803 raise util.Abort(_('not at a branch head (use -f to force)'))
5803 raise util.Abort(_('not at a branch head (use -f to force)'))
5804 r = scmutil.revsingle(repo, rev_).node()
5804 r = scmutil.revsingle(repo, rev_).node()
5805
5805
5806 if not message:
5806 if not message:
5807 # we don't translate commit messages
5807 # we don't translate commit messages
5808 message = ('Added tag %s for changeset %s' %
5808 message = ('Added tag %s for changeset %s' %
5809 (', '.join(names), short(r)))
5809 (', '.join(names), short(r)))
5810
5810
5811 date = opts.get('date')
5811 date = opts.get('date')
5812 if date:
5812 if date:
5813 date = util.parsedate(date)
5813 date = util.parsedate(date)
5814
5814
5815 if opts.get('edit'):
5815 if opts.get('edit'):
5816 message = ui.edit(message, ui.username())
5816 message = ui.edit(message, ui.username())
5817
5817
5818 # don't allow tagging the null rev
5818 # don't allow tagging the null rev
5819 if (not opts.get('remove') and
5819 if (not opts.get('remove') and
5820 scmutil.revsingle(repo, rev_).rev() == nullrev):
5820 scmutil.revsingle(repo, rev_).rev() == nullrev):
5821 raise util.Abort(_("null revision specified"))
5821 raise util.Abort(_("null revision specified"))
5822
5822
5823 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5823 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5824 finally:
5824 finally:
5825 release(lock, wlock)
5825 release(lock, wlock)
5826
5826
5827 @command('tags', [], '')
5827 @command('tags', [], '')
5828 def tags(ui, repo, **opts):
5828 def tags(ui, repo, **opts):
5829 """list repository tags
5829 """list repository tags
5830
5830
5831 This lists both regular and local tags. When the -v/--verbose
5831 This lists both regular and local tags. When the -v/--verbose
5832 switch is used, a third column "local" is printed for local tags.
5832 switch is used, a third column "local" is printed for local tags.
5833
5833
5834 Returns 0 on success.
5834 Returns 0 on success.
5835 """
5835 """
5836
5836
5837 fm = ui.formatter('tags', opts)
5837 fm = ui.formatter('tags', opts)
5838 hexfunc = ui.debugflag and hex or short
5838 hexfunc = ui.debugflag and hex or short
5839 tagtype = ""
5839 tagtype = ""
5840
5840
5841 for t, n in reversed(repo.tagslist()):
5841 for t, n in reversed(repo.tagslist()):
5842 hn = hexfunc(n)
5842 hn = hexfunc(n)
5843 label = 'tags.normal'
5843 label = 'tags.normal'
5844 tagtype = ''
5844 tagtype = ''
5845 if repo.tagtype(t) == 'local':
5845 if repo.tagtype(t) == 'local':
5846 label = 'tags.local'
5846 label = 'tags.local'
5847 tagtype = 'local'
5847 tagtype = 'local'
5848
5848
5849 fm.startitem()
5849 fm.startitem()
5850 fm.write('tag', '%s', t, label=label)
5850 fm.write('tag', '%s', t, label=label)
5851 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5851 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5852 fm.condwrite(not ui.quiet, 'rev id', fmt,
5852 fm.condwrite(not ui.quiet, 'rev id', fmt,
5853 repo.changelog.rev(n), hn, label=label)
5853 repo.changelog.rev(n), hn, label=label)
5854 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5854 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5855 tagtype, label=label)
5855 tagtype, label=label)
5856 fm.plain('\n')
5856 fm.plain('\n')
5857 fm.end()
5857 fm.end()
5858
5858
5859 @command('tip',
5859 @command('tip',
5860 [('p', 'patch', None, _('show patch')),
5860 [('p', 'patch', None, _('show patch')),
5861 ('g', 'git', None, _('use git extended diff format')),
5861 ('g', 'git', None, _('use git extended diff format')),
5862 ] + templateopts,
5862 ] + templateopts,
5863 _('[-p] [-g]'))
5863 _('[-p] [-g]'))
5864 def tip(ui, repo, **opts):
5864 def tip(ui, repo, **opts):
5865 """show the tip revision
5865 """show the tip revision
5866
5866
5867 The tip revision (usually just called the tip) is the changeset
5867 The tip revision (usually just called the tip) is the changeset
5868 most recently added to the repository (and therefore the most
5868 most recently added to the repository (and therefore the most
5869 recently changed head).
5869 recently changed head).
5870
5870
5871 If you have just made a commit, that commit will be the tip. If
5871 If you have just made a commit, that commit will be the tip. If
5872 you have just pulled changes from another repository, the tip of
5872 you have just pulled changes from another repository, the tip of
5873 that repository becomes the current tip. The "tip" tag is special
5873 that repository becomes the current tip. The "tip" tag is special
5874 and cannot be renamed or assigned to a different changeset.
5874 and cannot be renamed or assigned to a different changeset.
5875
5875
5876 Returns 0 on success.
5876 Returns 0 on success.
5877 """
5877 """
5878 displayer = cmdutil.show_changeset(ui, repo, opts)
5878 displayer = cmdutil.show_changeset(ui, repo, opts)
5879 displayer.show(repo['tip'])
5879 displayer.show(repo['tip'])
5880 displayer.close()
5880 displayer.close()
5881
5881
5882 @command('unbundle',
5882 @command('unbundle',
5883 [('u', 'update', None,
5883 [('u', 'update', None,
5884 _('update to new branch head if changesets were unbundled'))],
5884 _('update to new branch head if changesets were unbundled'))],
5885 _('[-u] FILE...'))
5885 _('[-u] FILE...'))
5886 def unbundle(ui, repo, fname1, *fnames, **opts):
5886 def unbundle(ui, repo, fname1, *fnames, **opts):
5887 """apply one or more changegroup files
5887 """apply one or more changegroup files
5888
5888
5889 Apply one or more compressed changegroup files generated by the
5889 Apply one or more compressed changegroup files generated by the
5890 bundle command.
5890 bundle command.
5891
5891
5892 Returns 0 on success, 1 if an update has unresolved files.
5892 Returns 0 on success, 1 if an update has unresolved files.
5893 """
5893 """
5894 fnames = (fname1,) + fnames
5894 fnames = (fname1,) + fnames
5895
5895
5896 lock = repo.lock()
5896 lock = repo.lock()
5897 wc = repo['.']
5897 wc = repo['.']
5898 try:
5898 try:
5899 for fname in fnames:
5899 for fname in fnames:
5900 f = hg.openpath(ui, fname)
5900 f = hg.openpath(ui, fname)
5901 gen = changegroup.readbundle(f, fname)
5901 gen = changegroup.readbundle(f, fname)
5902 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5902 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5903 finally:
5903 finally:
5904 lock.release()
5904 lock.release()
5905 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5905 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5906 return postincoming(ui, repo, modheads, opts.get('update'), None)
5906 return postincoming(ui, repo, modheads, opts.get('update'), None)
5907
5907
5908 @command('^update|up|checkout|co',
5908 @command('^update|up|checkout|co',
5909 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5909 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5910 ('c', 'check', None,
5910 ('c', 'check', None,
5911 _('update across branches if no uncommitted changes')),
5911 _('update across branches if no uncommitted changes')),
5912 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5912 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5913 ('r', 'rev', '', _('revision'), _('REV'))],
5913 ('r', 'rev', '', _('revision'), _('REV'))],
5914 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5914 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5915 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5915 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5916 """update working directory (or switch revisions)
5916 """update working directory (or switch revisions)
5917
5917
5918 Update the repository's working directory to the specified
5918 Update the repository's working directory to the specified
5919 changeset. If no changeset is specified, update to the tip of the
5919 changeset. If no changeset is specified, update to the tip of the
5920 current named branch and move the current bookmark (see :hg:`help
5920 current named branch and move the current bookmark (see :hg:`help
5921 bookmarks`).
5921 bookmarks`).
5922
5922
5923 Update sets the working directory's parent revision to the specified
5923 Update sets the working directory's parent revision to the specified
5924 changeset (see :hg:`help parents`).
5924 changeset (see :hg:`help parents`).
5925
5925
5926 If the changeset is not a descendant or ancestor of the working
5926 If the changeset is not a descendant or ancestor of the working
5927 directory's parent, the update is aborted. With the -c/--check
5927 directory's parent, the update is aborted. With the -c/--check
5928 option, the working directory is checked for uncommitted changes; if
5928 option, the working directory is checked for uncommitted changes; if
5929 none are found, the working directory is updated to the specified
5929 none are found, the working directory is updated to the specified
5930 changeset.
5930 changeset.
5931
5931
5932 .. container:: verbose
5932 .. container:: verbose
5933
5933
5934 The following rules apply when the working directory contains
5934 The following rules apply when the working directory contains
5935 uncommitted changes:
5935 uncommitted changes:
5936
5936
5937 1. If neither -c/--check nor -C/--clean is specified, and if
5937 1. If neither -c/--check nor -C/--clean is specified, and if
5938 the requested changeset is an ancestor or descendant of
5938 the requested changeset is an ancestor or descendant of
5939 the working directory's parent, the uncommitted changes
5939 the working directory's parent, the uncommitted changes
5940 are merged into the requested changeset and the merged
5940 are merged into the requested changeset and the merged
5941 result is left uncommitted. If the requested changeset is
5941 result is left uncommitted. If the requested changeset is
5942 not an ancestor or descendant (that is, it is on another
5942 not an ancestor or descendant (that is, it is on another
5943 branch), the update is aborted and the uncommitted changes
5943 branch), the update is aborted and the uncommitted changes
5944 are preserved.
5944 are preserved.
5945
5945
5946 2. With the -c/--check option, the update is aborted and the
5946 2. With the -c/--check option, the update is aborted and the
5947 uncommitted changes are preserved.
5947 uncommitted changes are preserved.
5948
5948
5949 3. With the -C/--clean option, uncommitted changes are discarded and
5949 3. With the -C/--clean option, uncommitted changes are discarded and
5950 the working directory is updated to the requested changeset.
5950 the working directory is updated to the requested changeset.
5951
5951
5952 To cancel an uncommitted merge (and lose your changes), use
5952 To cancel an uncommitted merge (and lose your changes), use
5953 :hg:`update --clean .`.
5953 :hg:`update --clean .`.
5954
5954
5955 Use null as the changeset to remove the working directory (like
5955 Use null as the changeset to remove the working directory (like
5956 :hg:`clone -U`).
5956 :hg:`clone -U`).
5957
5957
5958 If you want to revert just one file to an older revision, use
5958 If you want to revert just one file to an older revision, use
5959 :hg:`revert [-r REV] NAME`.
5959 :hg:`revert [-r REV] NAME`.
5960
5960
5961 See :hg:`help dates` for a list of formats valid for -d/--date.
5961 See :hg:`help dates` for a list of formats valid for -d/--date.
5962
5962
5963 Returns 0 on success, 1 if there are unresolved files.
5963 Returns 0 on success, 1 if there are unresolved files.
5964 """
5964 """
5965 if rev and node:
5965 if rev and node:
5966 raise util.Abort(_("please specify just one revision"))
5966 raise util.Abort(_("please specify just one revision"))
5967
5967
5968 if rev is None or rev == '':
5968 if rev is None or rev == '':
5969 rev = node
5969 rev = node
5970
5970
5971 # with no argument, we also move the current bookmark, if any
5971 # with no argument, we also move the current bookmark, if any
5972 movemarkfrom = None
5972 movemarkfrom = None
5973 if rev is None:
5973 if rev is None:
5974 curmark = repo._bookmarkcurrent
5974 curmark = repo._bookmarkcurrent
5975 if bookmarks.iscurrent(repo):
5975 if bookmarks.iscurrent(repo):
5976 movemarkfrom = repo['.'].node()
5976 movemarkfrom = repo['.'].node()
5977 elif curmark:
5977 elif curmark:
5978 ui.status(_("updating to active bookmark %s\n") % curmark)
5978 ui.status(_("updating to active bookmark %s\n") % curmark)
5979 rev = curmark
5979 rev = curmark
5980
5980
5981 # if we defined a bookmark, we have to remember the original bookmark name
5981 # if we defined a bookmark, we have to remember the original bookmark name
5982 brev = rev
5982 brev = rev
5983 rev = scmutil.revsingle(repo, rev, rev).rev()
5983 rev = scmutil.revsingle(repo, rev, rev).rev()
5984
5984
5985 if check and clean:
5985 if check and clean:
5986 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5986 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5987
5987
5988 if date:
5988 if date:
5989 if rev is not None:
5989 if rev is not None:
5990 raise util.Abort(_("you can't specify a revision and a date"))
5990 raise util.Abort(_("you can't specify a revision and a date"))
5991 rev = cmdutil.finddate(ui, repo, date)
5991 rev = cmdutil.finddate(ui, repo, date)
5992
5992
5993 if check:
5993 if check:
5994 c = repo[None]
5994 c = repo[None]
5995 if c.dirty(merge=False, branch=False, missing=True):
5995 if c.dirty(merge=False, branch=False, missing=True):
5996 raise util.Abort(_("uncommitted local changes"))
5996 raise util.Abort(_("uncommitted local changes"))
5997 if rev is None:
5997 if rev is None:
5998 rev = repo[repo[None].branch()].rev()
5998 rev = repo[repo[None].branch()].rev()
5999 mergemod._checkunknown(repo, repo[None], repo[rev])
5999 mergemod._checkunknown(repo, repo[None], repo[rev])
6000
6000
6001 if clean:
6001 if clean:
6002 ret = hg.clean(repo, rev)
6002 ret = hg.clean(repo, rev)
6003 else:
6003 else:
6004 ret = hg.update(repo, rev)
6004 ret = hg.update(repo, rev)
6005
6005
6006 if not ret and movemarkfrom:
6006 if not ret and movemarkfrom:
6007 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6007 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6008 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6008 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6009 elif brev in repo._bookmarks:
6009 elif brev in repo._bookmarks:
6010 bookmarks.setcurrent(repo, brev)
6010 bookmarks.setcurrent(repo, brev)
6011 elif brev:
6011 elif brev:
6012 bookmarks.unsetcurrent(repo)
6012 bookmarks.unsetcurrent(repo)
6013
6013
6014 return ret
6014 return ret
6015
6015
6016 @command('verify', [])
6016 @command('verify', [])
6017 def verify(ui, repo):
6017 def verify(ui, repo):
6018 """verify the integrity of the repository
6018 """verify the integrity of the repository
6019
6019
6020 Verify the integrity of the current repository.
6020 Verify the integrity of the current repository.
6021
6021
6022 This will perform an extensive check of the repository's
6022 This will perform an extensive check of the repository's
6023 integrity, validating the hashes and checksums of each entry in
6023 integrity, validating the hashes and checksums of each entry in
6024 the changelog, manifest, and tracked files, as well as the
6024 the changelog, manifest, and tracked files, as well as the
6025 integrity of their crosslinks and indices.
6025 integrity of their crosslinks and indices.
6026
6026
6027 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6027 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6028 for more information about recovery from corruption of the
6028 for more information about recovery from corruption of the
6029 repository.
6029 repository.
6030
6030
6031 Returns 0 on success, 1 if errors are encountered.
6031 Returns 0 on success, 1 if errors are encountered.
6032 """
6032 """
6033 return hg.verify(repo)
6033 return hg.verify(repo)
6034
6034
6035 @command('version', [])
6035 @command('version', [])
6036 def version_(ui):
6036 def version_(ui):
6037 """output version and copyright information"""
6037 """output version and copyright information"""
6038 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6038 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6039 % util.version())
6039 % util.version())
6040 ui.status(_(
6040 ui.status(_(
6041 "(see http://mercurial.selenic.com for more information)\n"
6041 "(see http://mercurial.selenic.com for more information)\n"
6042 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
6042 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
6043 "This is free software; see the source for copying conditions. "
6043 "This is free software; see the source for copying conditions. "
6044 "There is NO\nwarranty; "
6044 "There is NO\nwarranty; "
6045 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6045 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6046 ))
6046 ))
6047
6047
6048 norepo = ("clone init version help debugcommands debugcomplete"
6048 norepo = ("clone init version help debugcommands debugcomplete"
6049 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
6049 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
6050 " debugknown debuggetbundle debugbundle")
6050 " debugknown debuggetbundle debugbundle")
6051 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
6051 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
6052 " debugdata debugindex debugindexdot debugrevlog")
6052 " debugdata debugindex debugindexdot debugrevlog")
6053 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
6053 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
6054 " remove resolve status debugwalk")
6054 " remove resolve status debugwalk")
@@ -1,630 +1,645 b''
1 Setting up test
1 Setting up test
2
2
3 $ hg init test
3 $ hg init test
4 $ cd test
4 $ cd test
5 $ echo 0 > afile
5 $ echo 0 > afile
6 $ hg add afile
6 $ hg add afile
7 $ hg commit -m "0.0"
7 $ hg commit -m "0.0"
8 $ echo 1 >> afile
8 $ echo 1 >> afile
9 $ hg commit -m "0.1"
9 $ hg commit -m "0.1"
10 $ echo 2 >> afile
10 $ echo 2 >> afile
11 $ hg commit -m "0.2"
11 $ hg commit -m "0.2"
12 $ echo 3 >> afile
12 $ echo 3 >> afile
13 $ hg commit -m "0.3"
13 $ hg commit -m "0.3"
14 $ hg update -C 0
14 $ hg update -C 0
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 $ echo 1 >> afile
16 $ echo 1 >> afile
17 $ hg commit -m "1.1"
17 $ hg commit -m "1.1"
18 created new head
18 created new head
19 $ echo 2 >> afile
19 $ echo 2 >> afile
20 $ hg commit -m "1.2"
20 $ hg commit -m "1.2"
21 $ echo "a line" > fred
21 $ echo "a line" > fred
22 $ echo 3 >> afile
22 $ echo 3 >> afile
23 $ hg add fred
23 $ hg add fred
24 $ hg commit -m "1.3"
24 $ hg commit -m "1.3"
25 $ hg mv afile adifferentfile
25 $ hg mv afile adifferentfile
26 $ hg commit -m "1.3m"
26 $ hg commit -m "1.3m"
27 $ hg update -C 3
27 $ hg update -C 3
28 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
28 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
29 $ hg mv afile anotherfile
29 $ hg mv afile anotherfile
30 $ hg commit -m "0.3m"
30 $ hg commit -m "0.3m"
31 $ hg verify
31 $ hg verify
32 checking changesets
32 checking changesets
33 checking manifests
33 checking manifests
34 crosschecking files in changesets and manifests
34 crosschecking files in changesets and manifests
35 checking files
35 checking files
36 4 files, 9 changesets, 7 total revisions
36 4 files, 9 changesets, 7 total revisions
37 $ cd ..
37 $ cd ..
38 $ hg init empty
38 $ hg init empty
39
39
40 Bundle and phase
40 Bundle and phase
41
41
42 $ hg -R test phase --force --secret 0
42 $ hg -R test phase --force --secret 0
43 $ hg -R test bundle phase.hg empty
43 $ hg -R test bundle phase.hg empty
44 searching for changes
44 searching for changes
45 no changes found (ignored 9 secret changesets)
45 no changes found (ignored 9 secret changesets)
46 [1]
46 [1]
47 $ hg -R test phase --draft -r 'head()'
47 $ hg -R test phase --draft -r 'head()'
48
48
49 Bundle --all
49 Bundle --all
50
50
51 $ hg -R test bundle --all all.hg
51 $ hg -R test bundle --all all.hg
52 9 changesets found
52 9 changesets found
53
53
54 Bundle test to full.hg
54 Bundle test to full.hg
55
55
56 $ hg -R test bundle full.hg empty
56 $ hg -R test bundle full.hg empty
57 searching for changes
57 searching for changes
58 9 changesets found
58 9 changesets found
59
59
60 Unbundle full.hg in test
60 Unbundle full.hg in test
61
61
62 $ hg -R test unbundle full.hg
62 $ hg -R test unbundle full.hg
63 adding changesets
63 adding changesets
64 adding manifests
64 adding manifests
65 adding file changes
65 adding file changes
66 added 0 changesets with 0 changes to 4 files
66 added 0 changesets with 0 changes to 4 files
67 (run 'hg update' to get a working copy)
67 (run 'hg update' to get a working copy)
68
68
69 Verify empty
69 Verify empty
70
70
71 $ hg -R empty heads
71 $ hg -R empty heads
72 [1]
72 [1]
73 $ hg -R empty verify
73 $ hg -R empty verify
74 checking changesets
74 checking changesets
75 checking manifests
75 checking manifests
76 crosschecking files in changesets and manifests
76 crosschecking files in changesets and manifests
77 checking files
77 checking files
78 0 files, 0 changesets, 0 total revisions
78 0 files, 0 changesets, 0 total revisions
79
79
80 Pull full.hg into test (using --cwd)
80 Pull full.hg into test (using --cwd)
81
81
82 $ hg --cwd test pull ../full.hg
82 $ hg --cwd test pull ../full.hg
83 pulling from ../full.hg
83 pulling from ../full.hg
84 searching for changes
84 searching for changes
85 no changes found
85 no changes found
86
86
87 Pull full.hg into empty (using --cwd)
87 Pull full.hg into empty (using --cwd)
88
88
89 $ hg --cwd empty pull ../full.hg
89 $ hg --cwd empty pull ../full.hg
90 pulling from ../full.hg
90 pulling from ../full.hg
91 requesting all changes
91 requesting all changes
92 adding changesets
92 adding changesets
93 adding manifests
93 adding manifests
94 adding file changes
94 adding file changes
95 added 9 changesets with 7 changes to 4 files (+1 heads)
95 added 9 changesets with 7 changes to 4 files (+1 heads)
96 (run 'hg heads' to see heads, 'hg merge' to merge)
96 (run 'hg heads' to see heads, 'hg merge' to merge)
97
97
98 Rollback empty
98 Rollback empty
99
99
100 $ hg -R empty rollback
100 $ hg -R empty rollback
101 repository tip rolled back to revision -1 (undo pull)
101 repository tip rolled back to revision -1 (undo pull)
102
102
103 Pull full.hg into empty again (using --cwd)
103 Pull full.hg into empty again (using --cwd)
104
104
105 $ hg --cwd empty pull ../full.hg
105 $ hg --cwd empty pull ../full.hg
106 pulling from ../full.hg
106 pulling from ../full.hg
107 requesting all changes
107 requesting all changes
108 adding changesets
108 adding changesets
109 adding manifests
109 adding manifests
110 adding file changes
110 adding file changes
111 added 9 changesets with 7 changes to 4 files (+1 heads)
111 added 9 changesets with 7 changes to 4 files (+1 heads)
112 (run 'hg heads' to see heads, 'hg merge' to merge)
112 (run 'hg heads' to see heads, 'hg merge' to merge)
113
113
114 Pull full.hg into test (using -R)
114 Pull full.hg into test (using -R)
115
115
116 $ hg -R test pull full.hg
116 $ hg -R test pull full.hg
117 pulling from full.hg
117 pulling from full.hg
118 searching for changes
118 searching for changes
119 no changes found
119 no changes found
120
120
121 Pull full.hg into empty (using -R)
121 Pull full.hg into empty (using -R)
122
122
123 $ hg -R empty pull full.hg
123 $ hg -R empty pull full.hg
124 pulling from full.hg
124 pulling from full.hg
125 searching for changes
125 searching for changes
126 no changes found
126 no changes found
127
127
128 Rollback empty
128 Rollback empty
129
129
130 $ hg -R empty rollback
130 $ hg -R empty rollback
131 repository tip rolled back to revision -1 (undo pull)
131 repository tip rolled back to revision -1 (undo pull)
132
132
133 Pull full.hg into empty again (using -R)
133 Pull full.hg into empty again (using -R)
134
134
135 $ hg -R empty pull full.hg
135 $ hg -R empty pull full.hg
136 pulling from full.hg
136 pulling from full.hg
137 requesting all changes
137 requesting all changes
138 adding changesets
138 adding changesets
139 adding manifests
139 adding manifests
140 adding file changes
140 adding file changes
141 added 9 changesets with 7 changes to 4 files (+1 heads)
141 added 9 changesets with 7 changes to 4 files (+1 heads)
142 (run 'hg heads' to see heads, 'hg merge' to merge)
142 (run 'hg heads' to see heads, 'hg merge' to merge)
143
143
144 Log -R full.hg in fresh empty
144 Log -R full.hg in fresh empty
145
145
146 $ rm -r empty
146 $ rm -r empty
147 $ hg init empty
147 $ hg init empty
148 $ cd empty
148 $ cd empty
149 $ hg -R bundle://../full.hg log
149 $ hg -R bundle://../full.hg log
150 changeset: 8:aa35859c02ea
150 changeset: 8:aa35859c02ea
151 tag: tip
151 tag: tip
152 parent: 3:eebf5a27f8ca
152 parent: 3:eebf5a27f8ca
153 user: test
153 user: test
154 date: Thu Jan 01 00:00:00 1970 +0000
154 date: Thu Jan 01 00:00:00 1970 +0000
155 summary: 0.3m
155 summary: 0.3m
156
156
157 changeset: 7:a6a34bfa0076
157 changeset: 7:a6a34bfa0076
158 user: test
158 user: test
159 date: Thu Jan 01 00:00:00 1970 +0000
159 date: Thu Jan 01 00:00:00 1970 +0000
160 summary: 1.3m
160 summary: 1.3m
161
161
162 changeset: 6:7373c1169842
162 changeset: 6:7373c1169842
163 user: test
163 user: test
164 date: Thu Jan 01 00:00:00 1970 +0000
164 date: Thu Jan 01 00:00:00 1970 +0000
165 summary: 1.3
165 summary: 1.3
166
166
167 changeset: 5:1bb50a9436a7
167 changeset: 5:1bb50a9436a7
168 user: test
168 user: test
169 date: Thu Jan 01 00:00:00 1970 +0000
169 date: Thu Jan 01 00:00:00 1970 +0000
170 summary: 1.2
170 summary: 1.2
171
171
172 changeset: 4:095197eb4973
172 changeset: 4:095197eb4973
173 parent: 0:f9ee2f85a263
173 parent: 0:f9ee2f85a263
174 user: test
174 user: test
175 date: Thu Jan 01 00:00:00 1970 +0000
175 date: Thu Jan 01 00:00:00 1970 +0000
176 summary: 1.1
176 summary: 1.1
177
177
178 changeset: 3:eebf5a27f8ca
178 changeset: 3:eebf5a27f8ca
179 user: test
179 user: test
180 date: Thu Jan 01 00:00:00 1970 +0000
180 date: Thu Jan 01 00:00:00 1970 +0000
181 summary: 0.3
181 summary: 0.3
182
182
183 changeset: 2:e38ba6f5b7e0
183 changeset: 2:e38ba6f5b7e0
184 user: test
184 user: test
185 date: Thu Jan 01 00:00:00 1970 +0000
185 date: Thu Jan 01 00:00:00 1970 +0000
186 summary: 0.2
186 summary: 0.2
187
187
188 changeset: 1:34c2bf6b0626
188 changeset: 1:34c2bf6b0626
189 user: test
189 user: test
190 date: Thu Jan 01 00:00:00 1970 +0000
190 date: Thu Jan 01 00:00:00 1970 +0000
191 summary: 0.1
191 summary: 0.1
192
192
193 changeset: 0:f9ee2f85a263
193 changeset: 0:f9ee2f85a263
194 user: test
194 user: test
195 date: Thu Jan 01 00:00:00 1970 +0000
195 date: Thu Jan 01 00:00:00 1970 +0000
196 summary: 0.0
196 summary: 0.0
197
197
198 Make sure bundlerepo doesn't leak tempfiles (issue2491)
198 Make sure bundlerepo doesn't leak tempfiles (issue2491)
199
199
200 $ ls .hg
200 $ ls .hg
201 00changelog.i
201 00changelog.i
202 cache
202 cache
203 requires
203 requires
204 store
204 store
205
205
206 Pull ../full.hg into empty (with hook)
206 Pull ../full.hg into empty (with hook)
207
207
208 $ echo "[hooks]" >> .hg/hgrc
208 $ echo "[hooks]" >> .hg/hgrc
209 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup" >> .hg/hgrc
209 $ echo "changegroup = python \"$TESTDIR/printenv.py\" changegroup" >> .hg/hgrc
210
210
211 doesn't work (yet ?)
211 doesn't work (yet ?)
212
212
213 hg -R bundle://../full.hg verify
213 hg -R bundle://../full.hg verify
214
214
215 $ hg pull bundle://../full.hg
215 $ hg pull bundle://../full.hg
216 pulling from bundle:../full.hg
216 pulling from bundle:../full.hg
217 requesting all changes
217 requesting all changes
218 adding changesets
218 adding changesets
219 adding manifests
219 adding manifests
220 adding file changes
220 adding file changes
221 added 9 changesets with 7 changes to 4 files (+1 heads)
221 added 9 changesets with 7 changes to 4 files (+1 heads)
222 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:../full.hg
222 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:../full.hg
223 (run 'hg heads' to see heads, 'hg merge' to merge)
223 (run 'hg heads' to see heads, 'hg merge' to merge)
224
224
225 Rollback empty
225 Rollback empty
226
226
227 $ hg rollback
227 $ hg rollback
228 repository tip rolled back to revision -1 (undo pull)
228 repository tip rolled back to revision -1 (undo pull)
229 $ cd ..
229 $ cd ..
230
230
231 Log -R bundle:empty+full.hg
231 Log -R bundle:empty+full.hg
232
232
233 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
233 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
234 8 7 6 5 4 3 2 1 0
234 8 7 6 5 4 3 2 1 0
235
235
236 Pull full.hg into empty again (using -R; with hook)
236 Pull full.hg into empty again (using -R; with hook)
237
237
238 $ hg -R empty pull full.hg
238 $ hg -R empty pull full.hg
239 pulling from full.hg
239 pulling from full.hg
240 requesting all changes
240 requesting all changes
241 adding changesets
241 adding changesets
242 adding manifests
242 adding manifests
243 adding file changes
243 adding file changes
244 added 9 changesets with 7 changes to 4 files (+1 heads)
244 added 9 changesets with 7 changes to 4 files (+1 heads)
245 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:empty+full.hg
245 changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_SOURCE=pull HG_URL=bundle:empty+full.hg
246 (run 'hg heads' to see heads, 'hg merge' to merge)
246 (run 'hg heads' to see heads, 'hg merge' to merge)
247
247
248 Create partial clones
248 Create partial clones
249
249
250 $ rm -r empty
250 $ rm -r empty
251 $ hg init empty
251 $ hg init empty
252 $ hg clone -r 3 test partial
252 $ hg clone -r 3 test partial
253 adding changesets
253 adding changesets
254 adding manifests
254 adding manifests
255 adding file changes
255 adding file changes
256 added 4 changesets with 4 changes to 1 files
256 added 4 changesets with 4 changes to 1 files
257 updating to branch default
257 updating to branch default
258 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
259 $ hg clone partial partial2
259 $ hg clone partial partial2
260 updating to branch default
260 updating to branch default
261 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
261 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
262 $ cd partial
262 $ cd partial
263
263
264 Log -R full.hg in partial
264 Log -R full.hg in partial
265
265
266 $ hg -R bundle://../full.hg log
266 $ hg -R bundle://../full.hg log
267 changeset: 8:aa35859c02ea
267 changeset: 8:aa35859c02ea
268 tag: tip
268 tag: tip
269 parent: 3:eebf5a27f8ca
269 parent: 3:eebf5a27f8ca
270 user: test
270 user: test
271 date: Thu Jan 01 00:00:00 1970 +0000
271 date: Thu Jan 01 00:00:00 1970 +0000
272 summary: 0.3m
272 summary: 0.3m
273
273
274 changeset: 7:a6a34bfa0076
274 changeset: 7:a6a34bfa0076
275 user: test
275 user: test
276 date: Thu Jan 01 00:00:00 1970 +0000
276 date: Thu Jan 01 00:00:00 1970 +0000
277 summary: 1.3m
277 summary: 1.3m
278
278
279 changeset: 6:7373c1169842
279 changeset: 6:7373c1169842
280 user: test
280 user: test
281 date: Thu Jan 01 00:00:00 1970 +0000
281 date: Thu Jan 01 00:00:00 1970 +0000
282 summary: 1.3
282 summary: 1.3
283
283
284 changeset: 5:1bb50a9436a7
284 changeset: 5:1bb50a9436a7
285 user: test
285 user: test
286 date: Thu Jan 01 00:00:00 1970 +0000
286 date: Thu Jan 01 00:00:00 1970 +0000
287 summary: 1.2
287 summary: 1.2
288
288
289 changeset: 4:095197eb4973
289 changeset: 4:095197eb4973
290 parent: 0:f9ee2f85a263
290 parent: 0:f9ee2f85a263
291 user: test
291 user: test
292 date: Thu Jan 01 00:00:00 1970 +0000
292 date: Thu Jan 01 00:00:00 1970 +0000
293 summary: 1.1
293 summary: 1.1
294
294
295 changeset: 3:eebf5a27f8ca
295 changeset: 3:eebf5a27f8ca
296 user: test
296 user: test
297 date: Thu Jan 01 00:00:00 1970 +0000
297 date: Thu Jan 01 00:00:00 1970 +0000
298 summary: 0.3
298 summary: 0.3
299
299
300 changeset: 2:e38ba6f5b7e0
300 changeset: 2:e38ba6f5b7e0
301 user: test
301 user: test
302 date: Thu Jan 01 00:00:00 1970 +0000
302 date: Thu Jan 01 00:00:00 1970 +0000
303 summary: 0.2
303 summary: 0.2
304
304
305 changeset: 1:34c2bf6b0626
305 changeset: 1:34c2bf6b0626
306 user: test
306 user: test
307 date: Thu Jan 01 00:00:00 1970 +0000
307 date: Thu Jan 01 00:00:00 1970 +0000
308 summary: 0.1
308 summary: 0.1
309
309
310 changeset: 0:f9ee2f85a263
310 changeset: 0:f9ee2f85a263
311 user: test
311 user: test
312 date: Thu Jan 01 00:00:00 1970 +0000
312 date: Thu Jan 01 00:00:00 1970 +0000
313 summary: 0.0
313 summary: 0.0
314
314
315
315
316 Incoming full.hg in partial
316 Incoming full.hg in partial
317
317
318 $ hg incoming bundle://../full.hg
318 $ hg incoming bundle://../full.hg
319 comparing with bundle:../full.hg
319 comparing with bundle:../full.hg
320 searching for changes
320 searching for changes
321 changeset: 4:095197eb4973
321 changeset: 4:095197eb4973
322 parent: 0:f9ee2f85a263
322 parent: 0:f9ee2f85a263
323 user: test
323 user: test
324 date: Thu Jan 01 00:00:00 1970 +0000
324 date: Thu Jan 01 00:00:00 1970 +0000
325 summary: 1.1
325 summary: 1.1
326
326
327 changeset: 5:1bb50a9436a7
327 changeset: 5:1bb50a9436a7
328 user: test
328 user: test
329 date: Thu Jan 01 00:00:00 1970 +0000
329 date: Thu Jan 01 00:00:00 1970 +0000
330 summary: 1.2
330 summary: 1.2
331
331
332 changeset: 6:7373c1169842
332 changeset: 6:7373c1169842
333 user: test
333 user: test
334 date: Thu Jan 01 00:00:00 1970 +0000
334 date: Thu Jan 01 00:00:00 1970 +0000
335 summary: 1.3
335 summary: 1.3
336
336
337 changeset: 7:a6a34bfa0076
337 changeset: 7:a6a34bfa0076
338 user: test
338 user: test
339 date: Thu Jan 01 00:00:00 1970 +0000
339 date: Thu Jan 01 00:00:00 1970 +0000
340 summary: 1.3m
340 summary: 1.3m
341
341
342 changeset: 8:aa35859c02ea
342 changeset: 8:aa35859c02ea
343 tag: tip
343 tag: tip
344 parent: 3:eebf5a27f8ca
344 parent: 3:eebf5a27f8ca
345 user: test
345 user: test
346 date: Thu Jan 01 00:00:00 1970 +0000
346 date: Thu Jan 01 00:00:00 1970 +0000
347 summary: 0.3m
347 summary: 0.3m
348
348
349
349
350 Outgoing -R full.hg vs partial2 in partial
350 Outgoing -R full.hg vs partial2 in partial
351
351
352 $ hg -R bundle://../full.hg outgoing ../partial2
352 $ hg -R bundle://../full.hg outgoing ../partial2
353 comparing with ../partial2
353 comparing with ../partial2
354 searching for changes
354 searching for changes
355 changeset: 4:095197eb4973
355 changeset: 4:095197eb4973
356 parent: 0:f9ee2f85a263
356 parent: 0:f9ee2f85a263
357 user: test
357 user: test
358 date: Thu Jan 01 00:00:00 1970 +0000
358 date: Thu Jan 01 00:00:00 1970 +0000
359 summary: 1.1
359 summary: 1.1
360
360
361 changeset: 5:1bb50a9436a7
361 changeset: 5:1bb50a9436a7
362 user: test
362 user: test
363 date: Thu Jan 01 00:00:00 1970 +0000
363 date: Thu Jan 01 00:00:00 1970 +0000
364 summary: 1.2
364 summary: 1.2
365
365
366 changeset: 6:7373c1169842
366 changeset: 6:7373c1169842
367 user: test
367 user: test
368 date: Thu Jan 01 00:00:00 1970 +0000
368 date: Thu Jan 01 00:00:00 1970 +0000
369 summary: 1.3
369 summary: 1.3
370
370
371 changeset: 7:a6a34bfa0076
371 changeset: 7:a6a34bfa0076
372 user: test
372 user: test
373 date: Thu Jan 01 00:00:00 1970 +0000
373 date: Thu Jan 01 00:00:00 1970 +0000
374 summary: 1.3m
374 summary: 1.3m
375
375
376 changeset: 8:aa35859c02ea
376 changeset: 8:aa35859c02ea
377 tag: tip
377 tag: tip
378 parent: 3:eebf5a27f8ca
378 parent: 3:eebf5a27f8ca
379 user: test
379 user: test
380 date: Thu Jan 01 00:00:00 1970 +0000
380 date: Thu Jan 01 00:00:00 1970 +0000
381 summary: 0.3m
381 summary: 0.3m
382
382
383
383
384 Outgoing -R does-not-exist.hg vs partial2 in partial
384 Outgoing -R does-not-exist.hg vs partial2 in partial
385
385
386 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
386 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
387 abort: *../does-not-exist.hg* (glob)
387 abort: *../does-not-exist.hg* (glob)
388 [255]
388 [255]
389 $ cd ..
389 $ cd ..
390
390
391 hide outer repo
391 hide outer repo
392 $ hg init
392 $ hg init
393
393
394 Direct clone from bundle (all-history)
394 Direct clone from bundle (all-history)
395
395
396 $ hg clone full.hg full-clone
396 $ hg clone full.hg full-clone
397 requesting all changes
397 requesting all changes
398 adding changesets
398 adding changesets
399 adding manifests
399 adding manifests
400 adding file changes
400 adding file changes
401 added 9 changesets with 7 changes to 4 files (+1 heads)
401 added 9 changesets with 7 changes to 4 files (+1 heads)
402 updating to branch default
402 updating to branch default
403 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
403 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 $ hg -R full-clone heads
404 $ hg -R full-clone heads
405 changeset: 8:aa35859c02ea
405 changeset: 8:aa35859c02ea
406 tag: tip
406 tag: tip
407 parent: 3:eebf5a27f8ca
407 parent: 3:eebf5a27f8ca
408 user: test
408 user: test
409 date: Thu Jan 01 00:00:00 1970 +0000
409 date: Thu Jan 01 00:00:00 1970 +0000
410 summary: 0.3m
410 summary: 0.3m
411
411
412 changeset: 7:a6a34bfa0076
412 changeset: 7:a6a34bfa0076
413 user: test
413 user: test
414 date: Thu Jan 01 00:00:00 1970 +0000
414 date: Thu Jan 01 00:00:00 1970 +0000
415 summary: 1.3m
415 summary: 1.3m
416
416
417 $ rm -r full-clone
417 $ rm -r full-clone
418
418
419 When cloning from a non-copiable repository into '', do not
419 When cloning from a non-copiable repository into '', do not
420 recurse infinitely (issue 2528)
420 recurse infinitely (issue 2528)
421
421
422 $ hg clone full.hg ''
422 $ hg clone full.hg ''
423 abort: empty destination path is not valid
423 abort: empty destination path is not valid
424 [255]
424 [255]
425
425
426 test for http://mercurial.selenic.com/bts/issue216
426 test for http://mercurial.selenic.com/bts/issue216
427
427
428 Unbundle incremental bundles into fresh empty in one go
428 Unbundle incremental bundles into fresh empty in one go
429
429
430 $ rm -r empty
430 $ rm -r empty
431 $ hg init empty
431 $ hg init empty
432 $ hg -R test bundle --base null -r 0 ../0.hg
432 $ hg -R test bundle --base null -r 0 ../0.hg
433 1 changesets found
433 1 changesets found
434 $ hg -R test bundle --base 0 -r 1 ../1.hg
434 $ hg -R test bundle --base 0 -r 1 ../1.hg
435 1 changesets found
435 1 changesets found
436 $ hg -R empty unbundle -u ../0.hg ../1.hg
436 $ hg -R empty unbundle -u ../0.hg ../1.hg
437 adding changesets
437 adding changesets
438 adding manifests
438 adding manifests
439 adding file changes
439 adding file changes
440 added 1 changesets with 1 changes to 1 files
440 added 1 changesets with 1 changes to 1 files
441 adding changesets
441 adding changesets
442 adding manifests
442 adding manifests
443 adding file changes
443 adding file changes
444 added 1 changesets with 1 changes to 1 files
444 added 1 changesets with 1 changes to 1 files
445 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
445 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
446
446
447 View full contents of the bundle
447 View full contents of the bundle
448 $ hg -R test bundle --base null -r 3 ../partial.hg
448 $ hg -R test bundle --base null -r 3 ../partial.hg
449 4 changesets found
449 4 changesets found
450 $ cd test
450 $ cd test
451 $ hg -R ../../partial.hg log -r "bundle()"
451 $ hg -R ../../partial.hg log -r "bundle()"
452 changeset: 0:f9ee2f85a263
452 changeset: 0:f9ee2f85a263
453 user: test
453 user: test
454 date: Thu Jan 01 00:00:00 1970 +0000
454 date: Thu Jan 01 00:00:00 1970 +0000
455 summary: 0.0
455 summary: 0.0
456
456
457 changeset: 1:34c2bf6b0626
457 changeset: 1:34c2bf6b0626
458 user: test
458 user: test
459 date: Thu Jan 01 00:00:00 1970 +0000
459 date: Thu Jan 01 00:00:00 1970 +0000
460 summary: 0.1
460 summary: 0.1
461
461
462 changeset: 2:e38ba6f5b7e0
462 changeset: 2:e38ba6f5b7e0
463 user: test
463 user: test
464 date: Thu Jan 01 00:00:00 1970 +0000
464 date: Thu Jan 01 00:00:00 1970 +0000
465 summary: 0.2
465 summary: 0.2
466
466
467 changeset: 3:eebf5a27f8ca
467 changeset: 3:eebf5a27f8ca
468 user: test
468 user: test
469 date: Thu Jan 01 00:00:00 1970 +0000
469 date: Thu Jan 01 00:00:00 1970 +0000
470 summary: 0.3
470 summary: 0.3
471
471
472 $ cd ..
472 $ cd ..
473
473
474 test for 540d1059c802
474 test for 540d1059c802
475
475
476 test for 540d1059c802
476 test for 540d1059c802
477
477
478 $ hg init orig
478 $ hg init orig
479 $ cd orig
479 $ cd orig
480 $ echo foo > foo
480 $ echo foo > foo
481 $ hg add foo
481 $ hg add foo
482 $ hg ci -m 'add foo'
482 $ hg ci -m 'add foo'
483
483
484 $ hg clone . ../copy
484 $ hg clone . ../copy
485 updating to branch default
485 updating to branch default
486 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
486 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
487 $ hg tag foo
487 $ hg tag foo
488
488
489 $ cd ../copy
489 $ cd ../copy
490 $ echo >> foo
490 $ echo >> foo
491 $ hg ci -m 'change foo'
491 $ hg ci -m 'change foo'
492 $ hg bundle ../bundle.hg ../orig
492 $ hg bundle ../bundle.hg ../orig
493 searching for changes
493 searching for changes
494 1 changesets found
494 1 changesets found
495
495
496 $ cd ../orig
496 $ cd ../orig
497 $ hg incoming ../bundle.hg
497 $ hg incoming ../bundle.hg
498 comparing with ../bundle.hg
498 comparing with ../bundle.hg
499 searching for changes
499 searching for changes
500 changeset: 2:ed1b79f46b9a
500 changeset: 2:ed1b79f46b9a
501 tag: tip
501 tag: tip
502 parent: 0:bbd179dfa0a7
502 parent: 0:bbd179dfa0a7
503 user: test
503 user: test
504 date: Thu Jan 01 00:00:00 1970 +0000
504 date: Thu Jan 01 00:00:00 1970 +0000
505 summary: change foo
505 summary: change foo
506
506
507 $ cd ..
507 $ cd ..
508
508
509 test bundle with # in the filename (issue2154):
509 test bundle with # in the filename (issue2154):
510
510
511 $ cp bundle.hg 'test#bundle.hg'
511 $ cp bundle.hg 'test#bundle.hg'
512 $ cd orig
512 $ cd orig
513 $ hg incoming '../test#bundle.hg'
513 $ hg incoming '../test#bundle.hg'
514 comparing with ../test
514 comparing with ../test
515 abort: unknown revision 'bundle.hg'!
515 abort: unknown revision 'bundle.hg'!
516 [255]
516 [255]
517
517
518 note that percent encoding is not handled:
518 note that percent encoding is not handled:
519
519
520 $ hg incoming ../test%23bundle.hg
520 $ hg incoming ../test%23bundle.hg
521 abort: repository ../test%23bundle.hg not found!
521 abort: repository ../test%23bundle.hg not found!
522 [255]
522 [255]
523 $ cd ..
523 $ cd ..
524
524
525 test to bundle revisions on the newly created branch (issue3828):
526
527 $ hg -q clone -U test test-clone
528 $ cd test
529
530 $ hg -q branch foo
531 $ hg commit -m "create foo branch"
532 $ hg -q outgoing ../test-clone
533 9:b4f5acb1ee27
534 $ hg -q bundle --branch foo foo.hg ../test-clone
535 $ hg -R foo.hg -q log -r "bundle()"
536 9:b4f5acb1ee27
537
538 $ cd ..
539
525 test for http://mercurial.selenic.com/bts/issue1144
540 test for http://mercurial.selenic.com/bts/issue1144
526
541
527 test that verify bundle does not traceback
542 test that verify bundle does not traceback
528
543
529 partial history bundle, fails w/ unkown parent
544 partial history bundle, fails w/ unkown parent
530
545
531 $ hg -R bundle.hg verify
546 $ hg -R bundle.hg verify
532 abort: 00changelog.i@bbd179dfa0a7: unknown parent!
547 abort: 00changelog.i@bbd179dfa0a7: unknown parent!
533 [255]
548 [255]
534
549
535 full history bundle, refuses to verify non-local repo
550 full history bundle, refuses to verify non-local repo
536
551
537 $ hg -R all.hg verify
552 $ hg -R all.hg verify
538 abort: cannot verify bundle or remote repos
553 abort: cannot verify bundle or remote repos
539 [255]
554 [255]
540
555
541 but, regular verify must continue to work
556 but, regular verify must continue to work
542
557
543 $ hg -R orig verify
558 $ hg -R orig verify
544 checking changesets
559 checking changesets
545 checking manifests
560 checking manifests
546 crosschecking files in changesets and manifests
561 crosschecking files in changesets and manifests
547 checking files
562 checking files
548 2 files, 2 changesets, 2 total revisions
563 2 files, 2 changesets, 2 total revisions
549
564
550 diff against bundle
565 diff against bundle
551
566
552 $ hg init b
567 $ hg init b
553 $ cd b
568 $ cd b
554 $ hg -R ../all.hg diff -r tip
569 $ hg -R ../all.hg diff -r tip
555 diff -r aa35859c02ea anotherfile
570 diff -r aa35859c02ea anotherfile
556 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
571 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
557 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
572 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
558 @@ -1,4 +0,0 @@
573 @@ -1,4 +0,0 @@
559 -0
574 -0
560 -1
575 -1
561 -2
576 -2
562 -3
577 -3
563 $ cd ..
578 $ cd ..
564
579
565 bundle single branch
580 bundle single branch
566
581
567 $ hg init branchy
582 $ hg init branchy
568 $ cd branchy
583 $ cd branchy
569 $ echo a >a
584 $ echo a >a
570 $ echo x >x
585 $ echo x >x
571 $ hg ci -Ama
586 $ hg ci -Ama
572 adding a
587 adding a
573 adding x
588 adding x
574 $ echo c >c
589 $ echo c >c
575 $ echo xx >x
590 $ echo xx >x
576 $ hg ci -Amc
591 $ hg ci -Amc
577 adding c
592 adding c
578 $ echo c1 >c1
593 $ echo c1 >c1
579 $ hg ci -Amc1
594 $ hg ci -Amc1
580 adding c1
595 adding c1
581 $ hg up 0
596 $ hg up 0
582 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
597 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
583 $ echo b >b
598 $ echo b >b
584 $ hg ci -Amb
599 $ hg ci -Amb
585 adding b
600 adding b
586 created new head
601 created new head
587 $ echo b1 >b1
602 $ echo b1 >b1
588 $ echo xx >x
603 $ echo xx >x
589 $ hg ci -Amb1
604 $ hg ci -Amb1
590 adding b1
605 adding b1
591 $ hg clone -q -r2 . part
606 $ hg clone -q -r2 . part
592
607
593 == bundling via incoming
608 == bundling via incoming
594
609
595 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
610 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
596 comparing with .
611 comparing with .
597 searching for changes
612 searching for changes
598 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
613 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
599 057f4db07f61970e1c11e83be79e9d08adc4dc31
614 057f4db07f61970e1c11e83be79e9d08adc4dc31
600
615
601 == bundling
616 == bundling
602
617
603 $ hg bundle bundle.hg part --debug
618 $ hg bundle bundle.hg part --debug
604 query 1; heads
619 query 1; heads
605 searching for changes
620 searching for changes
606 all remote heads known locally
621 all remote heads known locally
607 2 changesets found
622 2 changesets found
608 list of changesets:
623 list of changesets:
609 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
624 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
610 057f4db07f61970e1c11e83be79e9d08adc4dc31
625 057f4db07f61970e1c11e83be79e9d08adc4dc31
611 bundling: 1/2 changesets (50.00%)
626 bundling: 1/2 changesets (50.00%)
612 bundling: 2/2 changesets (100.00%)
627 bundling: 2/2 changesets (100.00%)
613 bundling: 1/2 manifests (50.00%)
628 bundling: 1/2 manifests (50.00%)
614 bundling: 2/2 manifests (100.00%)
629 bundling: 2/2 manifests (100.00%)
615 bundling: b 1/3 files (33.33%)
630 bundling: b 1/3 files (33.33%)
616 bundling: b1 2/3 files (66.67%)
631 bundling: b1 2/3 files (66.67%)
617 bundling: x 3/3 files (100.00%)
632 bundling: x 3/3 files (100.00%)
618
633
619 == Test for issue3441
634 == Test for issue3441
620
635
621 $ hg clone -q -r0 . part2
636 $ hg clone -q -r0 . part2
622 $ hg -q -R part2 pull bundle.hg
637 $ hg -q -R part2 pull bundle.hg
623 $ hg -R part2 verify
638 $ hg -R part2 verify
624 checking changesets
639 checking changesets
625 checking manifests
640 checking manifests
626 crosschecking files in changesets and manifests
641 crosschecking files in changesets and manifests
627 checking files
642 checking files
628 4 files, 3 changesets, 5 total revisions
643 4 files, 3 changesets, 5 total revisions
629
644
630 $ cd ..
645 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now