##// END OF EJS Templates
bookmarks: show active bookmark even if not at working dir...
Kevin Bullock -
r18479:0efd5686 stable
parent child Browse files
Show More
@@ -1,6052 +1,6052 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 and n == cur:
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, other, 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 def parsenodeid(s):
2110 def parsenodeid(s):
2111 try:
2111 try:
2112 # We do not use revsingle/revrange functions here to accept
2112 # We do not use revsingle/revrange functions here to accept
2113 # arbitrary node identifiers, possibly not present in the
2113 # arbitrary node identifiers, possibly not present in the
2114 # local repository.
2114 # local repository.
2115 n = bin(s)
2115 n = bin(s)
2116 if len(n) != len(nullid):
2116 if len(n) != len(nullid):
2117 raise TypeError()
2117 raise TypeError()
2118 return n
2118 return n
2119 except TypeError:
2119 except TypeError:
2120 raise util.Abort('changeset references must be full hexadecimal '
2120 raise util.Abort('changeset references must be full hexadecimal '
2121 'node identifiers')
2121 'node identifiers')
2122
2122
2123 if precursor is not None:
2123 if precursor is not None:
2124 metadata = {}
2124 metadata = {}
2125 if 'date' in opts:
2125 if 'date' in opts:
2126 metadata['date'] = opts['date']
2126 metadata['date'] = opts['date']
2127 metadata['user'] = opts['user'] or ui.username()
2127 metadata['user'] = opts['user'] or ui.username()
2128 succs = tuple(parsenodeid(succ) for succ in successors)
2128 succs = tuple(parsenodeid(succ) for succ in successors)
2129 l = repo.lock()
2129 l = repo.lock()
2130 try:
2130 try:
2131 tr = repo.transaction('debugobsolete')
2131 tr = repo.transaction('debugobsolete')
2132 try:
2132 try:
2133 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2133 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2134 opts['flags'], metadata)
2134 opts['flags'], metadata)
2135 tr.close()
2135 tr.close()
2136 finally:
2136 finally:
2137 tr.release()
2137 tr.release()
2138 finally:
2138 finally:
2139 l.release()
2139 l.release()
2140 else:
2140 else:
2141 for m in obsolete.allmarkers(repo):
2141 for m in obsolete.allmarkers(repo):
2142 ui.write(hex(m.precnode()))
2142 ui.write(hex(m.precnode()))
2143 for repl in m.succnodes():
2143 for repl in m.succnodes():
2144 ui.write(' ')
2144 ui.write(' ')
2145 ui.write(hex(repl))
2145 ui.write(hex(repl))
2146 ui.write(' %X ' % m._data[2])
2146 ui.write(' %X ' % m._data[2])
2147 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2147 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2148 sorted(m.metadata().items()))))
2148 sorted(m.metadata().items()))))
2149 ui.write('\n')
2149 ui.write('\n')
2150
2150
2151 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2151 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2152 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2152 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2153 '''access the pushkey key/value protocol
2153 '''access the pushkey key/value protocol
2154
2154
2155 With two args, list the keys in the given namespace.
2155 With two args, list the keys in the given namespace.
2156
2156
2157 With five args, set a key to new if it currently is set to old.
2157 With five args, set a key to new if it currently is set to old.
2158 Reports success or failure.
2158 Reports success or failure.
2159 '''
2159 '''
2160
2160
2161 target = hg.peer(ui, {}, repopath)
2161 target = hg.peer(ui, {}, repopath)
2162 if keyinfo:
2162 if keyinfo:
2163 key, old, new = keyinfo
2163 key, old, new = keyinfo
2164 r = target.pushkey(namespace, key, old, new)
2164 r = target.pushkey(namespace, key, old, new)
2165 ui.status(str(r) + '\n')
2165 ui.status(str(r) + '\n')
2166 return not r
2166 return not r
2167 else:
2167 else:
2168 for k, v in sorted(target.listkeys(namespace).iteritems()):
2168 for k, v in sorted(target.listkeys(namespace).iteritems()):
2169 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2169 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2170 v.encode('string-escape')))
2170 v.encode('string-escape')))
2171
2171
2172 @command('debugpvec', [], _('A B'))
2172 @command('debugpvec', [], _('A B'))
2173 def debugpvec(ui, repo, a, b=None):
2173 def debugpvec(ui, repo, a, b=None):
2174 ca = scmutil.revsingle(repo, a)
2174 ca = scmutil.revsingle(repo, a)
2175 cb = scmutil.revsingle(repo, b)
2175 cb = scmutil.revsingle(repo, b)
2176 pa = pvec.ctxpvec(ca)
2176 pa = pvec.ctxpvec(ca)
2177 pb = pvec.ctxpvec(cb)
2177 pb = pvec.ctxpvec(cb)
2178 if pa == pb:
2178 if pa == pb:
2179 rel = "="
2179 rel = "="
2180 elif pa > pb:
2180 elif 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 ui.write(_("a: %s\n") % pa)
2186 ui.write(_("a: %s\n") % pa)
2187 ui.write(_("b: %s\n") % pb)
2187 ui.write(_("b: %s\n") % pb)
2188 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2188 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2189 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2189 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2190 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2190 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2191 pa.distance(pb), rel))
2191 pa.distance(pb), rel))
2192
2192
2193 @command('debugrebuildstate',
2193 @command('debugrebuildstate',
2194 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2194 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2195 _('[-r REV] [REV]'))
2195 _('[-r REV] [REV]'))
2196 def debugrebuildstate(ui, repo, rev="tip"):
2196 def debugrebuildstate(ui, repo, rev="tip"):
2197 """rebuild the dirstate as it would look like for the given revision"""
2197 """rebuild the dirstate as it would look like for the given revision"""
2198 ctx = scmutil.revsingle(repo, rev)
2198 ctx = scmutil.revsingle(repo, rev)
2199 wlock = repo.wlock()
2199 wlock = repo.wlock()
2200 try:
2200 try:
2201 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2201 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2202 finally:
2202 finally:
2203 wlock.release()
2203 wlock.release()
2204
2204
2205 @command('debugrename',
2205 @command('debugrename',
2206 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2206 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2207 _('[-r REV] FILE'))
2207 _('[-r REV] FILE'))
2208 def debugrename(ui, repo, file1, *pats, **opts):
2208 def debugrename(ui, repo, file1, *pats, **opts):
2209 """dump rename information"""
2209 """dump rename information"""
2210
2210
2211 ctx = scmutil.revsingle(repo, opts.get('rev'))
2211 ctx = scmutil.revsingle(repo, opts.get('rev'))
2212 m = scmutil.match(ctx, (file1,) + pats, opts)
2212 m = scmutil.match(ctx, (file1,) + pats, opts)
2213 for abs in ctx.walk(m):
2213 for abs in ctx.walk(m):
2214 fctx = ctx[abs]
2214 fctx = ctx[abs]
2215 o = fctx.filelog().renamed(fctx.filenode())
2215 o = fctx.filelog().renamed(fctx.filenode())
2216 rel = m.rel(abs)
2216 rel = m.rel(abs)
2217 if o:
2217 if o:
2218 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2218 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2219 else:
2219 else:
2220 ui.write(_("%s not renamed\n") % rel)
2220 ui.write(_("%s not renamed\n") % rel)
2221
2221
2222 @command('debugrevlog',
2222 @command('debugrevlog',
2223 [('c', 'changelog', False, _('open changelog')),
2223 [('c', 'changelog', False, _('open changelog')),
2224 ('m', 'manifest', False, _('open manifest')),
2224 ('m', 'manifest', False, _('open manifest')),
2225 ('d', 'dump', False, _('dump index data'))],
2225 ('d', 'dump', False, _('dump index data'))],
2226 _('-c|-m|FILE'))
2226 _('-c|-m|FILE'))
2227 def debugrevlog(ui, repo, file_ = None, **opts):
2227 def debugrevlog(ui, repo, file_ = None, **opts):
2228 """show data and statistics about a revlog"""
2228 """show data and statistics about a revlog"""
2229 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2229 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2230
2230
2231 if opts.get("dump"):
2231 if opts.get("dump"):
2232 numrevs = len(r)
2232 numrevs = len(r)
2233 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2233 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2234 " rawsize totalsize compression heads\n")
2234 " rawsize totalsize compression heads\n")
2235 ts = 0
2235 ts = 0
2236 heads = set()
2236 heads = set()
2237 for rev in xrange(numrevs):
2237 for rev in xrange(numrevs):
2238 dbase = r.deltaparent(rev)
2238 dbase = r.deltaparent(rev)
2239 if dbase == -1:
2239 if dbase == -1:
2240 dbase = rev
2240 dbase = rev
2241 cbase = r.chainbase(rev)
2241 cbase = r.chainbase(rev)
2242 p1, p2 = r.parentrevs(rev)
2242 p1, p2 = r.parentrevs(rev)
2243 rs = r.rawsize(rev)
2243 rs = r.rawsize(rev)
2244 ts = ts + rs
2244 ts = ts + rs
2245 heads -= set(r.parentrevs(rev))
2245 heads -= set(r.parentrevs(rev))
2246 heads.add(rev)
2246 heads.add(rev)
2247 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2247 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2248 (rev, p1, p2, r.start(rev), r.end(rev),
2248 (rev, p1, p2, r.start(rev), r.end(rev),
2249 r.start(dbase), r.start(cbase),
2249 r.start(dbase), r.start(cbase),
2250 r.start(p1), r.start(p2),
2250 r.start(p1), r.start(p2),
2251 rs, ts, ts / r.end(rev), len(heads)))
2251 rs, ts, ts / r.end(rev), len(heads)))
2252 return 0
2252 return 0
2253
2253
2254 v = r.version
2254 v = r.version
2255 format = v & 0xFFFF
2255 format = v & 0xFFFF
2256 flags = []
2256 flags = []
2257 gdelta = False
2257 gdelta = False
2258 if v & revlog.REVLOGNGINLINEDATA:
2258 if v & revlog.REVLOGNGINLINEDATA:
2259 flags.append('inline')
2259 flags.append('inline')
2260 if v & revlog.REVLOGGENERALDELTA:
2260 if v & revlog.REVLOGGENERALDELTA:
2261 gdelta = True
2261 gdelta = True
2262 flags.append('generaldelta')
2262 flags.append('generaldelta')
2263 if not flags:
2263 if not flags:
2264 flags = ['(none)']
2264 flags = ['(none)']
2265
2265
2266 nummerges = 0
2266 nummerges = 0
2267 numfull = 0
2267 numfull = 0
2268 numprev = 0
2268 numprev = 0
2269 nump1 = 0
2269 nump1 = 0
2270 nump2 = 0
2270 nump2 = 0
2271 numother = 0
2271 numother = 0
2272 nump1prev = 0
2272 nump1prev = 0
2273 nump2prev = 0
2273 nump2prev = 0
2274 chainlengths = []
2274 chainlengths = []
2275
2275
2276 datasize = [None, 0, 0L]
2276 datasize = [None, 0, 0L]
2277 fullsize = [None, 0, 0L]
2277 fullsize = [None, 0, 0L]
2278 deltasize = [None, 0, 0L]
2278 deltasize = [None, 0, 0L]
2279
2279
2280 def addsize(size, l):
2280 def addsize(size, l):
2281 if l[0] is None or size < l[0]:
2281 if l[0] is None or size < l[0]:
2282 l[0] = size
2282 l[0] = size
2283 if size > l[1]:
2283 if size > l[1]:
2284 l[1] = size
2284 l[1] = size
2285 l[2] += size
2285 l[2] += size
2286
2286
2287 numrevs = len(r)
2287 numrevs = len(r)
2288 for rev in xrange(numrevs):
2288 for rev in xrange(numrevs):
2289 p1, p2 = r.parentrevs(rev)
2289 p1, p2 = r.parentrevs(rev)
2290 delta = r.deltaparent(rev)
2290 delta = r.deltaparent(rev)
2291 if format > 0:
2291 if format > 0:
2292 addsize(r.rawsize(rev), datasize)
2292 addsize(r.rawsize(rev), datasize)
2293 if p2 != nullrev:
2293 if p2 != nullrev:
2294 nummerges += 1
2294 nummerges += 1
2295 size = r.length(rev)
2295 size = r.length(rev)
2296 if delta == nullrev:
2296 if delta == nullrev:
2297 chainlengths.append(0)
2297 chainlengths.append(0)
2298 numfull += 1
2298 numfull += 1
2299 addsize(size, fullsize)
2299 addsize(size, fullsize)
2300 else:
2300 else:
2301 chainlengths.append(chainlengths[delta] + 1)
2301 chainlengths.append(chainlengths[delta] + 1)
2302 addsize(size, deltasize)
2302 addsize(size, deltasize)
2303 if delta == rev - 1:
2303 if delta == rev - 1:
2304 numprev += 1
2304 numprev += 1
2305 if delta == p1:
2305 if delta == p1:
2306 nump1prev += 1
2306 nump1prev += 1
2307 elif delta == p2:
2307 elif delta == p2:
2308 nump2prev += 1
2308 nump2prev += 1
2309 elif delta == p1:
2309 elif delta == p1:
2310 nump1 += 1
2310 nump1 += 1
2311 elif delta == p2:
2311 elif delta == p2:
2312 nump2 += 1
2312 nump2 += 1
2313 elif delta != nullrev:
2313 elif delta != nullrev:
2314 numother += 1
2314 numother += 1
2315
2315
2316 # Adjust size min value for empty cases
2316 # Adjust size min value for empty cases
2317 for size in (datasize, fullsize, deltasize):
2317 for size in (datasize, fullsize, deltasize):
2318 if size[0] is None:
2318 if size[0] is None:
2319 size[0] = 0
2319 size[0] = 0
2320
2320
2321 numdeltas = numrevs - numfull
2321 numdeltas = numrevs - numfull
2322 numoprev = numprev - nump1prev - nump2prev
2322 numoprev = numprev - nump1prev - nump2prev
2323 totalrawsize = datasize[2]
2323 totalrawsize = datasize[2]
2324 datasize[2] /= numrevs
2324 datasize[2] /= numrevs
2325 fulltotal = fullsize[2]
2325 fulltotal = fullsize[2]
2326 fullsize[2] /= numfull
2326 fullsize[2] /= numfull
2327 deltatotal = deltasize[2]
2327 deltatotal = deltasize[2]
2328 if numrevs - numfull > 0:
2328 if numrevs - numfull > 0:
2329 deltasize[2] /= numrevs - numfull
2329 deltasize[2] /= numrevs - numfull
2330 totalsize = fulltotal + deltatotal
2330 totalsize = fulltotal + deltatotal
2331 avgchainlen = sum(chainlengths) / numrevs
2331 avgchainlen = sum(chainlengths) / numrevs
2332 compratio = totalrawsize / totalsize
2332 compratio = totalrawsize / totalsize
2333
2333
2334 basedfmtstr = '%%%dd\n'
2334 basedfmtstr = '%%%dd\n'
2335 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2335 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2336
2336
2337 def dfmtstr(max):
2337 def dfmtstr(max):
2338 return basedfmtstr % len(str(max))
2338 return basedfmtstr % len(str(max))
2339 def pcfmtstr(max, padding=0):
2339 def pcfmtstr(max, padding=0):
2340 return basepcfmtstr % (len(str(max)), ' ' * padding)
2340 return basepcfmtstr % (len(str(max)), ' ' * padding)
2341
2341
2342 def pcfmt(value, total):
2342 def pcfmt(value, total):
2343 return (value, 100 * float(value) / total)
2343 return (value, 100 * float(value) / total)
2344
2344
2345 ui.write(('format : %d\n') % format)
2345 ui.write(('format : %d\n') % format)
2346 ui.write(('flags : %s\n') % ', '.join(flags))
2346 ui.write(('flags : %s\n') % ', '.join(flags))
2347
2347
2348 ui.write('\n')
2348 ui.write('\n')
2349 fmt = pcfmtstr(totalsize)
2349 fmt = pcfmtstr(totalsize)
2350 fmt2 = dfmtstr(totalsize)
2350 fmt2 = dfmtstr(totalsize)
2351 ui.write(('revisions : ') + fmt2 % numrevs)
2351 ui.write(('revisions : ') + fmt2 % numrevs)
2352 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2352 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2353 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2353 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2354 ui.write(('revisions : ') + fmt2 % numrevs)
2354 ui.write(('revisions : ') + fmt2 % numrevs)
2355 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2355 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2356 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2356 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2357 ui.write(('revision size : ') + fmt2 % totalsize)
2357 ui.write(('revision size : ') + fmt2 % totalsize)
2358 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2358 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2359 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2359 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2360
2360
2361 ui.write('\n')
2361 ui.write('\n')
2362 fmt = dfmtstr(max(avgchainlen, compratio))
2362 fmt = dfmtstr(max(avgchainlen, compratio))
2363 ui.write(('avg chain length : ') + fmt % avgchainlen)
2363 ui.write(('avg chain length : ') + fmt % avgchainlen)
2364 ui.write(('compression ratio : ') + fmt % compratio)
2364 ui.write(('compression ratio : ') + fmt % compratio)
2365
2365
2366 if format > 0:
2366 if format > 0:
2367 ui.write('\n')
2367 ui.write('\n')
2368 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2368 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2369 % tuple(datasize))
2369 % tuple(datasize))
2370 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2370 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2371 % tuple(fullsize))
2371 % tuple(fullsize))
2372 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2372 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2373 % tuple(deltasize))
2373 % tuple(deltasize))
2374
2374
2375 if numdeltas > 0:
2375 if numdeltas > 0:
2376 ui.write('\n')
2376 ui.write('\n')
2377 fmt = pcfmtstr(numdeltas)
2377 fmt = pcfmtstr(numdeltas)
2378 fmt2 = pcfmtstr(numdeltas, 4)
2378 fmt2 = pcfmtstr(numdeltas, 4)
2379 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2379 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2380 if numprev > 0:
2380 if numprev > 0:
2381 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2381 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2382 numprev))
2382 numprev))
2383 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2383 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2384 numprev))
2384 numprev))
2385 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2385 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2386 numprev))
2386 numprev))
2387 if gdelta:
2387 if gdelta:
2388 ui.write(('deltas against p1 : ')
2388 ui.write(('deltas against p1 : ')
2389 + fmt % pcfmt(nump1, numdeltas))
2389 + fmt % pcfmt(nump1, numdeltas))
2390 ui.write(('deltas against p2 : ')
2390 ui.write(('deltas against p2 : ')
2391 + fmt % pcfmt(nump2, numdeltas))
2391 + fmt % pcfmt(nump2, numdeltas))
2392 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2392 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2393 numdeltas))
2393 numdeltas))
2394
2394
2395 @command('debugrevspec', [], ('REVSPEC'))
2395 @command('debugrevspec', [], ('REVSPEC'))
2396 def debugrevspec(ui, repo, expr):
2396 def debugrevspec(ui, repo, expr):
2397 """parse and apply a revision specification
2397 """parse and apply a revision specification
2398
2398
2399 Use --verbose to print the parsed tree before and after aliases
2399 Use --verbose to print the parsed tree before and after aliases
2400 expansion.
2400 expansion.
2401 """
2401 """
2402 if ui.verbose:
2402 if ui.verbose:
2403 tree = revset.parse(expr)[0]
2403 tree = revset.parse(expr)[0]
2404 ui.note(revset.prettyformat(tree), "\n")
2404 ui.note(revset.prettyformat(tree), "\n")
2405 newtree = revset.findaliases(ui, tree)
2405 newtree = revset.findaliases(ui, tree)
2406 if newtree != tree:
2406 if newtree != tree:
2407 ui.note(revset.prettyformat(newtree), "\n")
2407 ui.note(revset.prettyformat(newtree), "\n")
2408 func = revset.match(ui, expr)
2408 func = revset.match(ui, expr)
2409 for c in func(repo, range(len(repo))):
2409 for c in func(repo, range(len(repo))):
2410 ui.write("%s\n" % c)
2410 ui.write("%s\n" % c)
2411
2411
2412 @command('debugsetparents', [], _('REV1 [REV2]'))
2412 @command('debugsetparents', [], _('REV1 [REV2]'))
2413 def debugsetparents(ui, repo, rev1, rev2=None):
2413 def debugsetparents(ui, repo, rev1, rev2=None):
2414 """manually set the parents of the current working directory
2414 """manually set the parents of the current working directory
2415
2415
2416 This is useful for writing repository conversion tools, but should
2416 This is useful for writing repository conversion tools, but should
2417 be used with care.
2417 be used with care.
2418
2418
2419 Returns 0 on success.
2419 Returns 0 on success.
2420 """
2420 """
2421
2421
2422 r1 = scmutil.revsingle(repo, rev1).node()
2422 r1 = scmutil.revsingle(repo, rev1).node()
2423 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2423 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2424
2424
2425 wlock = repo.wlock()
2425 wlock = repo.wlock()
2426 try:
2426 try:
2427 repo.setparents(r1, r2)
2427 repo.setparents(r1, r2)
2428 finally:
2428 finally:
2429 wlock.release()
2429 wlock.release()
2430
2430
2431 @command('debugstate',
2431 @command('debugstate',
2432 [('', 'nodates', None, _('do not display the saved mtime')),
2432 [('', 'nodates', None, _('do not display the saved mtime')),
2433 ('', 'datesort', None, _('sort by saved mtime'))],
2433 ('', 'datesort', None, _('sort by saved mtime'))],
2434 _('[OPTION]...'))
2434 _('[OPTION]...'))
2435 def debugstate(ui, repo, nodates=None, datesort=None):
2435 def debugstate(ui, repo, nodates=None, datesort=None):
2436 """show the contents of the current dirstate"""
2436 """show the contents of the current dirstate"""
2437 timestr = ""
2437 timestr = ""
2438 showdate = not nodates
2438 showdate = not nodates
2439 if datesort:
2439 if datesort:
2440 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2440 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2441 else:
2441 else:
2442 keyfunc = None # sort by filename
2442 keyfunc = None # sort by filename
2443 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2443 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2444 if showdate:
2444 if showdate:
2445 if ent[3] == -1:
2445 if ent[3] == -1:
2446 # Pad or slice to locale representation
2446 # Pad or slice to locale representation
2447 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2447 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2448 time.localtime(0)))
2448 time.localtime(0)))
2449 timestr = 'unset'
2449 timestr = 'unset'
2450 timestr = (timestr[:locale_len] +
2450 timestr = (timestr[:locale_len] +
2451 ' ' * (locale_len - len(timestr)))
2451 ' ' * (locale_len - len(timestr)))
2452 else:
2452 else:
2453 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2453 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2454 time.localtime(ent[3]))
2454 time.localtime(ent[3]))
2455 if ent[1] & 020000:
2455 if ent[1] & 020000:
2456 mode = 'lnk'
2456 mode = 'lnk'
2457 else:
2457 else:
2458 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2458 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2459 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2459 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2460 for f in repo.dirstate.copies():
2460 for f in repo.dirstate.copies():
2461 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2461 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2462
2462
2463 @command('debugsub',
2463 @command('debugsub',
2464 [('r', 'rev', '',
2464 [('r', 'rev', '',
2465 _('revision to check'), _('REV'))],
2465 _('revision to check'), _('REV'))],
2466 _('[-r REV] [REV]'))
2466 _('[-r REV] [REV]'))
2467 def debugsub(ui, repo, rev=None):
2467 def debugsub(ui, repo, rev=None):
2468 ctx = scmutil.revsingle(repo, rev, None)
2468 ctx = scmutil.revsingle(repo, rev, None)
2469 for k, v in sorted(ctx.substate.items()):
2469 for k, v in sorted(ctx.substate.items()):
2470 ui.write(('path %s\n') % k)
2470 ui.write(('path %s\n') % k)
2471 ui.write((' source %s\n') % v[0])
2471 ui.write((' source %s\n') % v[0])
2472 ui.write((' revision %s\n') % v[1])
2472 ui.write((' revision %s\n') % v[1])
2473
2473
2474 @command('debugsuccessorssets',
2474 @command('debugsuccessorssets',
2475 [],
2475 [],
2476 _('[REV]'))
2476 _('[REV]'))
2477 def debugsuccessorssets(ui, repo, *revs):
2477 def debugsuccessorssets(ui, repo, *revs):
2478 """show set of successors for revision
2478 """show set of successors for revision
2479
2479
2480 A successors set of changeset A is a consistent group of revisions that
2480 A successors set of changeset A is a consistent group of revisions that
2481 succeed A. It contains non-obsolete changesets only.
2481 succeed A. It contains non-obsolete changesets only.
2482
2482
2483 In most cases a changeset A has a single successors set containing a single
2483 In most cases a changeset A has a single successors set containing a single
2484 successor (changeset A replaced by A').
2484 successor (changeset A replaced by A').
2485
2485
2486 A changeset that is made obsolete with no successors are called "pruned".
2486 A changeset that is made obsolete with no successors are called "pruned".
2487 Such changesets have no successors sets at all.
2487 Such changesets have no successors sets at all.
2488
2488
2489 A changeset that has been "split" will have a successors set containing
2489 A changeset that has been "split" will have a successors set containing
2490 more than one successor.
2490 more than one successor.
2491
2491
2492 A changeset that has been rewritten in multiple different ways is called
2492 A changeset that has been rewritten in multiple different ways is called
2493 "divergent". Such changesets have multiple successor sets (each of which
2493 "divergent". Such changesets have multiple successor sets (each of which
2494 may also be split, i.e. have multiple successors).
2494 may also be split, i.e. have multiple successors).
2495
2495
2496 Results are displayed as follows::
2496 Results are displayed as follows::
2497
2497
2498 <rev1>
2498 <rev1>
2499 <successors-1A>
2499 <successors-1A>
2500 <rev2>
2500 <rev2>
2501 <successors-2A>
2501 <successors-2A>
2502 <successors-2B1> <successors-2B2> <successors-2B3>
2502 <successors-2B1> <successors-2B2> <successors-2B3>
2503
2503
2504 Here rev2 has two possible (i.e. divergent) successors sets. The first
2504 Here rev2 has two possible (i.e. divergent) successors sets. The first
2505 holds one element, whereas the second holds three (i.e. the changeset has
2505 holds one element, whereas the second holds three (i.e. the changeset has
2506 been split).
2506 been split).
2507 """
2507 """
2508 # passed to successorssets caching computation from one call to another
2508 # passed to successorssets caching computation from one call to another
2509 cache = {}
2509 cache = {}
2510 ctx2str = str
2510 ctx2str = str
2511 node2str = short
2511 node2str = short
2512 if ui.debug():
2512 if ui.debug():
2513 def ctx2str(ctx):
2513 def ctx2str(ctx):
2514 return ctx.hex()
2514 return ctx.hex()
2515 node2str = hex
2515 node2str = hex
2516 for rev in scmutil.revrange(repo, revs):
2516 for rev in scmutil.revrange(repo, revs):
2517 ctx = repo[rev]
2517 ctx = repo[rev]
2518 ui.write('%s\n'% ctx2str(ctx))
2518 ui.write('%s\n'% ctx2str(ctx))
2519 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2519 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2520 if succsset:
2520 if succsset:
2521 ui.write(' ')
2521 ui.write(' ')
2522 ui.write(node2str(succsset[0]))
2522 ui.write(node2str(succsset[0]))
2523 for node in succsset[1:]:
2523 for node in succsset[1:]:
2524 ui.write(' ')
2524 ui.write(' ')
2525 ui.write(node2str(node))
2525 ui.write(node2str(node))
2526 ui.write('\n')
2526 ui.write('\n')
2527
2527
2528 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2528 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2529 def debugwalk(ui, repo, *pats, **opts):
2529 def debugwalk(ui, repo, *pats, **opts):
2530 """show how files match on given patterns"""
2530 """show how files match on given patterns"""
2531 m = scmutil.match(repo[None], pats, opts)
2531 m = scmutil.match(repo[None], pats, opts)
2532 items = list(repo.walk(m))
2532 items = list(repo.walk(m))
2533 if not items:
2533 if not items:
2534 return
2534 return
2535 f = lambda fn: fn
2535 f = lambda fn: fn
2536 if ui.configbool('ui', 'slash') and os.sep != '/':
2536 if ui.configbool('ui', 'slash') and os.sep != '/':
2537 f = lambda fn: util.normpath(fn)
2537 f = lambda fn: util.normpath(fn)
2538 fmt = 'f %%-%ds %%-%ds %%s' % (
2538 fmt = 'f %%-%ds %%-%ds %%s' % (
2539 max([len(abs) for abs in items]),
2539 max([len(abs) for abs in items]),
2540 max([len(m.rel(abs)) for abs in items]))
2540 max([len(m.rel(abs)) for abs in items]))
2541 for abs in items:
2541 for abs in items:
2542 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2542 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2543 ui.write("%s\n" % line.rstrip())
2543 ui.write("%s\n" % line.rstrip())
2544
2544
2545 @command('debugwireargs',
2545 @command('debugwireargs',
2546 [('', 'three', '', 'three'),
2546 [('', 'three', '', 'three'),
2547 ('', 'four', '', 'four'),
2547 ('', 'four', '', 'four'),
2548 ('', 'five', '', 'five'),
2548 ('', 'five', '', 'five'),
2549 ] + remoteopts,
2549 ] + remoteopts,
2550 _('REPO [OPTIONS]... [ONE [TWO]]'))
2550 _('REPO [OPTIONS]... [ONE [TWO]]'))
2551 def debugwireargs(ui, repopath, *vals, **opts):
2551 def debugwireargs(ui, repopath, *vals, **opts):
2552 repo = hg.peer(ui, opts, repopath)
2552 repo = hg.peer(ui, opts, repopath)
2553 for opt in remoteopts:
2553 for opt in remoteopts:
2554 del opts[opt[1]]
2554 del opts[opt[1]]
2555 args = {}
2555 args = {}
2556 for k, v in opts.iteritems():
2556 for k, v in opts.iteritems():
2557 if v:
2557 if v:
2558 args[k] = v
2558 args[k] = v
2559 # run twice to check that we don't mess up the stream for the next command
2559 # run twice to check that we don't mess up the stream for the next command
2560 res1 = repo.debugwireargs(*vals, **args)
2560 res1 = repo.debugwireargs(*vals, **args)
2561 res2 = repo.debugwireargs(*vals, **args)
2561 res2 = repo.debugwireargs(*vals, **args)
2562 ui.write("%s\n" % res1)
2562 ui.write("%s\n" % res1)
2563 if res1 != res2:
2563 if res1 != res2:
2564 ui.warn("%s\n" % res2)
2564 ui.warn("%s\n" % res2)
2565
2565
2566 @command('^diff',
2566 @command('^diff',
2567 [('r', 'rev', [], _('revision'), _('REV')),
2567 [('r', 'rev', [], _('revision'), _('REV')),
2568 ('c', 'change', '', _('change made by revision'), _('REV'))
2568 ('c', 'change', '', _('change made by revision'), _('REV'))
2569 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2569 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2570 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2570 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2571 def diff(ui, repo, *pats, **opts):
2571 def diff(ui, repo, *pats, **opts):
2572 """diff repository (or selected files)
2572 """diff repository (or selected files)
2573
2573
2574 Show differences between revisions for the specified files.
2574 Show differences between revisions for the specified files.
2575
2575
2576 Differences between files are shown using the unified diff format.
2576 Differences between files are shown using the unified diff format.
2577
2577
2578 .. note::
2578 .. note::
2579 diff may generate unexpected results for merges, as it will
2579 diff may generate unexpected results for merges, as it will
2580 default to comparing against the working directory's first
2580 default to comparing against the working directory's first
2581 parent changeset if no revisions are specified.
2581 parent changeset if no revisions are specified.
2582
2582
2583 When two revision arguments are given, then changes are shown
2583 When two revision arguments are given, then changes are shown
2584 between those revisions. If only one revision is specified then
2584 between those revisions. If only one revision is specified then
2585 that revision is compared to the working directory, and, when no
2585 that revision is compared to the working directory, and, when no
2586 revisions are specified, the working directory files are compared
2586 revisions are specified, the working directory files are compared
2587 to its parent.
2587 to its parent.
2588
2588
2589 Alternatively you can specify -c/--change with a revision to see
2589 Alternatively you can specify -c/--change with a revision to see
2590 the changes in that changeset relative to its first parent.
2590 the changes in that changeset relative to its first parent.
2591
2591
2592 Without the -a/--text option, diff will avoid generating diffs of
2592 Without the -a/--text option, diff will avoid generating diffs of
2593 files it detects as binary. With -a, diff will generate a diff
2593 files it detects as binary. With -a, diff will generate a diff
2594 anyway, probably with undesirable results.
2594 anyway, probably with undesirable results.
2595
2595
2596 Use the -g/--git option to generate diffs in the git extended diff
2596 Use the -g/--git option to generate diffs in the git extended diff
2597 format. For more information, read :hg:`help diffs`.
2597 format. For more information, read :hg:`help diffs`.
2598
2598
2599 .. container:: verbose
2599 .. container:: verbose
2600
2600
2601 Examples:
2601 Examples:
2602
2602
2603 - compare a file in the current working directory to its parent::
2603 - compare a file in the current working directory to its parent::
2604
2604
2605 hg diff foo.c
2605 hg diff foo.c
2606
2606
2607 - compare two historical versions of a directory, with rename info::
2607 - compare two historical versions of a directory, with rename info::
2608
2608
2609 hg diff --git -r 1.0:1.2 lib/
2609 hg diff --git -r 1.0:1.2 lib/
2610
2610
2611 - get change stats relative to the last change on some date::
2611 - get change stats relative to the last change on some date::
2612
2612
2613 hg diff --stat -r "date('may 2')"
2613 hg diff --stat -r "date('may 2')"
2614
2614
2615 - diff all newly-added files that contain a keyword::
2615 - diff all newly-added files that contain a keyword::
2616
2616
2617 hg diff "set:added() and grep(GNU)"
2617 hg diff "set:added() and grep(GNU)"
2618
2618
2619 - compare a revision and its parents::
2619 - compare a revision and its parents::
2620
2620
2621 hg diff -c 9353 # compare against first parent
2621 hg diff -c 9353 # compare against first parent
2622 hg diff -r 9353^:9353 # same using revset syntax
2622 hg diff -r 9353^:9353 # same using revset syntax
2623 hg diff -r 9353^2:9353 # compare against the second parent
2623 hg diff -r 9353^2:9353 # compare against the second parent
2624
2624
2625 Returns 0 on success.
2625 Returns 0 on success.
2626 """
2626 """
2627
2627
2628 revs = opts.get('rev')
2628 revs = opts.get('rev')
2629 change = opts.get('change')
2629 change = opts.get('change')
2630 stat = opts.get('stat')
2630 stat = opts.get('stat')
2631 reverse = opts.get('reverse')
2631 reverse = opts.get('reverse')
2632
2632
2633 if revs and change:
2633 if revs and change:
2634 msg = _('cannot specify --rev and --change at the same time')
2634 msg = _('cannot specify --rev and --change at the same time')
2635 raise util.Abort(msg)
2635 raise util.Abort(msg)
2636 elif change:
2636 elif change:
2637 node2 = scmutil.revsingle(repo, change, None).node()
2637 node2 = scmutil.revsingle(repo, change, None).node()
2638 node1 = repo[node2].p1().node()
2638 node1 = repo[node2].p1().node()
2639 else:
2639 else:
2640 node1, node2 = scmutil.revpair(repo, revs)
2640 node1, node2 = scmutil.revpair(repo, revs)
2641
2641
2642 if reverse:
2642 if reverse:
2643 node1, node2 = node2, node1
2643 node1, node2 = node2, node1
2644
2644
2645 diffopts = patch.diffopts(ui, opts)
2645 diffopts = patch.diffopts(ui, opts)
2646 m = scmutil.match(repo[node2], pats, opts)
2646 m = scmutil.match(repo[node2], pats, opts)
2647 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2647 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2648 listsubrepos=opts.get('subrepos'))
2648 listsubrepos=opts.get('subrepos'))
2649
2649
2650 @command('^export',
2650 @command('^export',
2651 [('o', 'output', '',
2651 [('o', 'output', '',
2652 _('print output to file with formatted name'), _('FORMAT')),
2652 _('print output to file with formatted name'), _('FORMAT')),
2653 ('', 'switch-parent', None, _('diff against the second parent')),
2653 ('', 'switch-parent', None, _('diff against the second parent')),
2654 ('r', 'rev', [], _('revisions to export'), _('REV')),
2654 ('r', 'rev', [], _('revisions to export'), _('REV')),
2655 ] + diffopts,
2655 ] + diffopts,
2656 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2656 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2657 def export(ui, repo, *changesets, **opts):
2657 def export(ui, repo, *changesets, **opts):
2658 """dump the header and diffs for one or more changesets
2658 """dump the header and diffs for one or more changesets
2659
2659
2660 Print the changeset header and diffs for one or more revisions.
2660 Print the changeset header and diffs for one or more revisions.
2661
2661
2662 The information shown in the changeset header is: author, date,
2662 The information shown in the changeset header is: author, date,
2663 branch name (if non-default), changeset hash, parent(s) and commit
2663 branch name (if non-default), changeset hash, parent(s) and commit
2664 comment.
2664 comment.
2665
2665
2666 .. note::
2666 .. note::
2667 export may generate unexpected diff output for merge
2667 export may generate unexpected diff output for merge
2668 changesets, as it will compare the merge changeset against its
2668 changesets, as it will compare the merge changeset against its
2669 first parent only.
2669 first parent only.
2670
2670
2671 Output may be to a file, in which case the name of the file is
2671 Output may be to a file, in which case the name of the file is
2672 given using a format string. The formatting rules are as follows:
2672 given using a format string. The formatting rules are as follows:
2673
2673
2674 :``%%``: literal "%" character
2674 :``%%``: literal "%" character
2675 :``%H``: changeset hash (40 hexadecimal digits)
2675 :``%H``: changeset hash (40 hexadecimal digits)
2676 :``%N``: number of patches being generated
2676 :``%N``: number of patches being generated
2677 :``%R``: changeset revision number
2677 :``%R``: changeset revision number
2678 :``%b``: basename of the exporting repository
2678 :``%b``: basename of the exporting repository
2679 :``%h``: short-form changeset hash (12 hexadecimal digits)
2679 :``%h``: short-form changeset hash (12 hexadecimal digits)
2680 :``%m``: first line of the commit message (only alphanumeric characters)
2680 :``%m``: first line of the commit message (only alphanumeric characters)
2681 :``%n``: zero-padded sequence number, starting at 1
2681 :``%n``: zero-padded sequence number, starting at 1
2682 :``%r``: zero-padded changeset revision number
2682 :``%r``: zero-padded changeset revision number
2683
2683
2684 Without the -a/--text option, export will avoid generating diffs
2684 Without the -a/--text option, export will avoid generating diffs
2685 of files it detects as binary. With -a, export will generate a
2685 of files it detects as binary. With -a, export will generate a
2686 diff anyway, probably with undesirable results.
2686 diff anyway, probably with undesirable results.
2687
2687
2688 Use the -g/--git option to generate diffs in the git extended diff
2688 Use the -g/--git option to generate diffs in the git extended diff
2689 format. See :hg:`help diffs` for more information.
2689 format. See :hg:`help diffs` for more information.
2690
2690
2691 With the --switch-parent option, the diff will be against the
2691 With the --switch-parent option, the diff will be against the
2692 second parent. It can be useful to review a merge.
2692 second parent. It can be useful to review a merge.
2693
2693
2694 .. container:: verbose
2694 .. container:: verbose
2695
2695
2696 Examples:
2696 Examples:
2697
2697
2698 - use export and import to transplant a bugfix to the current
2698 - use export and import to transplant a bugfix to the current
2699 branch::
2699 branch::
2700
2700
2701 hg export -r 9353 | hg import -
2701 hg export -r 9353 | hg import -
2702
2702
2703 - export all the changesets between two revisions to a file with
2703 - export all the changesets between two revisions to a file with
2704 rename information::
2704 rename information::
2705
2705
2706 hg export --git -r 123:150 > changes.txt
2706 hg export --git -r 123:150 > changes.txt
2707
2707
2708 - split outgoing changes into a series of patches with
2708 - split outgoing changes into a series of patches with
2709 descriptive names::
2709 descriptive names::
2710
2710
2711 hg export -r "outgoing()" -o "%n-%m.patch"
2711 hg export -r "outgoing()" -o "%n-%m.patch"
2712
2712
2713 Returns 0 on success.
2713 Returns 0 on success.
2714 """
2714 """
2715 changesets += tuple(opts.get('rev', []))
2715 changesets += tuple(opts.get('rev', []))
2716 revs = scmutil.revrange(repo, changesets)
2716 revs = scmutil.revrange(repo, changesets)
2717 if not revs:
2717 if not revs:
2718 raise util.Abort(_("export requires at least one changeset"))
2718 raise util.Abort(_("export requires at least one changeset"))
2719 if len(revs) > 1:
2719 if len(revs) > 1:
2720 ui.note(_('exporting patches:\n'))
2720 ui.note(_('exporting patches:\n'))
2721 else:
2721 else:
2722 ui.note(_('exporting patch:\n'))
2722 ui.note(_('exporting patch:\n'))
2723 cmdutil.export(repo, revs, template=opts.get('output'),
2723 cmdutil.export(repo, revs, template=opts.get('output'),
2724 switch_parent=opts.get('switch_parent'),
2724 switch_parent=opts.get('switch_parent'),
2725 opts=patch.diffopts(ui, opts))
2725 opts=patch.diffopts(ui, opts))
2726
2726
2727 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2727 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2728 def forget(ui, repo, *pats, **opts):
2728 def forget(ui, repo, *pats, **opts):
2729 """forget the specified files on the next commit
2729 """forget the specified files on the next commit
2730
2730
2731 Mark the specified files so they will no longer be tracked
2731 Mark the specified files so they will no longer be tracked
2732 after the next commit.
2732 after the next commit.
2733
2733
2734 This only removes files from the current branch, not from the
2734 This only removes files from the current branch, not from the
2735 entire project history, and it does not delete them from the
2735 entire project history, and it does not delete them from the
2736 working directory.
2736 working directory.
2737
2737
2738 To undo a forget before the next commit, see :hg:`add`.
2738 To undo a forget before the next commit, see :hg:`add`.
2739
2739
2740 .. container:: verbose
2740 .. container:: verbose
2741
2741
2742 Examples:
2742 Examples:
2743
2743
2744 - forget newly-added binary files::
2744 - forget newly-added binary files::
2745
2745
2746 hg forget "set:added() and binary()"
2746 hg forget "set:added() and binary()"
2747
2747
2748 - forget files that would be excluded by .hgignore::
2748 - forget files that would be excluded by .hgignore::
2749
2749
2750 hg forget "set:hgignore()"
2750 hg forget "set:hgignore()"
2751
2751
2752 Returns 0 on success.
2752 Returns 0 on success.
2753 """
2753 """
2754
2754
2755 if not pats:
2755 if not pats:
2756 raise util.Abort(_('no files specified'))
2756 raise util.Abort(_('no files specified'))
2757
2757
2758 m = scmutil.match(repo[None], pats, opts)
2758 m = scmutil.match(repo[None], pats, opts)
2759 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2759 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2760 return rejected and 1 or 0
2760 return rejected and 1 or 0
2761
2761
2762 @command(
2762 @command(
2763 'graft',
2763 'graft',
2764 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2764 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2765 ('c', 'continue', False, _('resume interrupted graft')),
2765 ('c', 'continue', False, _('resume interrupted graft')),
2766 ('e', 'edit', False, _('invoke editor on commit messages')),
2766 ('e', 'edit', False, _('invoke editor on commit messages')),
2767 ('', 'log', None, _('append graft info to log message')),
2767 ('', 'log', None, _('append graft info to log message')),
2768 ('D', 'currentdate', False,
2768 ('D', 'currentdate', False,
2769 _('record the current date as commit date')),
2769 _('record the current date as commit date')),
2770 ('U', 'currentuser', False,
2770 ('U', 'currentuser', False,
2771 _('record the current user as committer'), _('DATE'))]
2771 _('record the current user as committer'), _('DATE'))]
2772 + commitopts2 + mergetoolopts + dryrunopts,
2772 + commitopts2 + mergetoolopts + dryrunopts,
2773 _('[OPTION]... [-r] REV...'))
2773 _('[OPTION]... [-r] REV...'))
2774 def graft(ui, repo, *revs, **opts):
2774 def graft(ui, repo, *revs, **opts):
2775 '''copy changes from other branches onto the current branch
2775 '''copy changes from other branches onto the current branch
2776
2776
2777 This command uses Mercurial's merge logic to copy individual
2777 This command uses Mercurial's merge logic to copy individual
2778 changes from other branches without merging branches in the
2778 changes from other branches without merging branches in the
2779 history graph. This is sometimes known as 'backporting' or
2779 history graph. This is sometimes known as 'backporting' or
2780 'cherry-picking'. By default, graft will copy user, date, and
2780 'cherry-picking'. By default, graft will copy user, date, and
2781 description from the source changesets.
2781 description from the source changesets.
2782
2782
2783 Changesets that are ancestors of the current revision, that have
2783 Changesets that are ancestors of the current revision, that have
2784 already been grafted, or that are merges will be skipped.
2784 already been grafted, or that are merges will be skipped.
2785
2785
2786 If --log is specified, log messages will have a comment appended
2786 If --log is specified, log messages will have a comment appended
2787 of the form::
2787 of the form::
2788
2788
2789 (grafted from CHANGESETHASH)
2789 (grafted from CHANGESETHASH)
2790
2790
2791 If a graft merge results in conflicts, the graft process is
2791 If a graft merge results in conflicts, the graft process is
2792 interrupted so that the current merge can be manually resolved.
2792 interrupted so that the current merge can be manually resolved.
2793 Once all conflicts are addressed, the graft process can be
2793 Once all conflicts are addressed, the graft process can be
2794 continued with the -c/--continue option.
2794 continued with the -c/--continue option.
2795
2795
2796 .. note::
2796 .. note::
2797 The -c/--continue option does not reapply earlier options.
2797 The -c/--continue option does not reapply earlier options.
2798
2798
2799 .. container:: verbose
2799 .. container:: verbose
2800
2800
2801 Examples:
2801 Examples:
2802
2802
2803 - copy a single change to the stable branch and edit its description::
2803 - copy a single change to the stable branch and edit its description::
2804
2804
2805 hg update stable
2805 hg update stable
2806 hg graft --edit 9393
2806 hg graft --edit 9393
2807
2807
2808 - graft a range of changesets with one exception, updating dates::
2808 - graft a range of changesets with one exception, updating dates::
2809
2809
2810 hg graft -D "2085::2093 and not 2091"
2810 hg graft -D "2085::2093 and not 2091"
2811
2811
2812 - continue a graft after resolving conflicts::
2812 - continue a graft after resolving conflicts::
2813
2813
2814 hg graft -c
2814 hg graft -c
2815
2815
2816 - show the source of a grafted changeset::
2816 - show the source of a grafted changeset::
2817
2817
2818 hg log --debug -r tip
2818 hg log --debug -r tip
2819
2819
2820 Returns 0 on successful completion.
2820 Returns 0 on successful completion.
2821 '''
2821 '''
2822
2822
2823 revs = list(revs)
2823 revs = list(revs)
2824 revs.extend(opts['rev'])
2824 revs.extend(opts['rev'])
2825
2825
2826 if not opts.get('user') and opts.get('currentuser'):
2826 if not opts.get('user') and opts.get('currentuser'):
2827 opts['user'] = ui.username()
2827 opts['user'] = ui.username()
2828 if not opts.get('date') and opts.get('currentdate'):
2828 if not opts.get('date') and opts.get('currentdate'):
2829 opts['date'] = "%d %d" % util.makedate()
2829 opts['date'] = "%d %d" % util.makedate()
2830
2830
2831 editor = None
2831 editor = None
2832 if opts.get('edit'):
2832 if opts.get('edit'):
2833 editor = cmdutil.commitforceeditor
2833 editor = cmdutil.commitforceeditor
2834
2834
2835 cont = False
2835 cont = False
2836 if opts['continue']:
2836 if opts['continue']:
2837 cont = True
2837 cont = True
2838 if revs:
2838 if revs:
2839 raise util.Abort(_("can't specify --continue and revisions"))
2839 raise util.Abort(_("can't specify --continue and revisions"))
2840 # read in unfinished revisions
2840 # read in unfinished revisions
2841 try:
2841 try:
2842 nodes = repo.opener.read('graftstate').splitlines()
2842 nodes = repo.opener.read('graftstate').splitlines()
2843 revs = [repo[node].rev() for node in nodes]
2843 revs = [repo[node].rev() for node in nodes]
2844 except IOError, inst:
2844 except IOError, inst:
2845 if inst.errno != errno.ENOENT:
2845 if inst.errno != errno.ENOENT:
2846 raise
2846 raise
2847 raise util.Abort(_("no graft state found, can't continue"))
2847 raise util.Abort(_("no graft state found, can't continue"))
2848 else:
2848 else:
2849 cmdutil.bailifchanged(repo)
2849 cmdutil.bailifchanged(repo)
2850 if not revs:
2850 if not revs:
2851 raise util.Abort(_('no revisions specified'))
2851 raise util.Abort(_('no revisions specified'))
2852 revs = scmutil.revrange(repo, revs)
2852 revs = scmutil.revrange(repo, revs)
2853
2853
2854 # check for merges
2854 # check for merges
2855 for rev in repo.revs('%ld and merge()', revs):
2855 for rev in repo.revs('%ld and merge()', revs):
2856 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2856 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2857 revs.remove(rev)
2857 revs.remove(rev)
2858 if not revs:
2858 if not revs:
2859 return -1
2859 return -1
2860
2860
2861 # check for ancestors of dest branch
2861 # check for ancestors of dest branch
2862 for rev in repo.revs('::. and %ld', revs):
2862 for rev in repo.revs('::. and %ld', revs):
2863 ui.warn(_('skipping ancestor revision %s\n') % rev)
2863 ui.warn(_('skipping ancestor revision %s\n') % rev)
2864 revs.remove(rev)
2864 revs.remove(rev)
2865 if not revs:
2865 if not revs:
2866 return -1
2866 return -1
2867
2867
2868 # analyze revs for earlier grafts
2868 # analyze revs for earlier grafts
2869 ids = {}
2869 ids = {}
2870 for ctx in repo.set("%ld", revs):
2870 for ctx in repo.set("%ld", revs):
2871 ids[ctx.hex()] = ctx.rev()
2871 ids[ctx.hex()] = ctx.rev()
2872 n = ctx.extra().get('source')
2872 n = ctx.extra().get('source')
2873 if n:
2873 if n:
2874 ids[n] = ctx.rev()
2874 ids[n] = ctx.rev()
2875
2875
2876 # check ancestors for earlier grafts
2876 # check ancestors for earlier grafts
2877 ui.debug('scanning for duplicate grafts\n')
2877 ui.debug('scanning for duplicate grafts\n')
2878 for ctx in repo.set("::. - ::%ld", revs):
2878 for ctx in repo.set("::. - ::%ld", revs):
2879 n = ctx.extra().get('source')
2879 n = ctx.extra().get('source')
2880 if n in ids:
2880 if n in ids:
2881 r = repo[n].rev()
2881 r = repo[n].rev()
2882 if r in revs:
2882 if r in revs:
2883 ui.warn(_('skipping already grafted revision %s\n') % r)
2883 ui.warn(_('skipping already grafted revision %s\n') % r)
2884 revs.remove(r)
2884 revs.remove(r)
2885 elif ids[n] in revs:
2885 elif ids[n] in revs:
2886 ui.warn(_('skipping already grafted revision %s '
2886 ui.warn(_('skipping already grafted revision %s '
2887 '(same origin %d)\n') % (ids[n], r))
2887 '(same origin %d)\n') % (ids[n], r))
2888 revs.remove(ids[n])
2888 revs.remove(ids[n])
2889 elif ctx.hex() in ids:
2889 elif ctx.hex() in ids:
2890 r = ids[ctx.hex()]
2890 r = ids[ctx.hex()]
2891 ui.warn(_('skipping already grafted revision %s '
2891 ui.warn(_('skipping already grafted revision %s '
2892 '(was grafted from %d)\n') % (r, ctx.rev()))
2892 '(was grafted from %d)\n') % (r, ctx.rev()))
2893 revs.remove(r)
2893 revs.remove(r)
2894 if not revs:
2894 if not revs:
2895 return -1
2895 return -1
2896
2896
2897 wlock = repo.wlock()
2897 wlock = repo.wlock()
2898 try:
2898 try:
2899 current = repo['.']
2899 current = repo['.']
2900 for pos, ctx in enumerate(repo.set("%ld", revs)):
2900 for pos, ctx in enumerate(repo.set("%ld", revs)):
2901
2901
2902 ui.status(_('grafting revision %s\n') % ctx.rev())
2902 ui.status(_('grafting revision %s\n') % ctx.rev())
2903 if opts.get('dry_run'):
2903 if opts.get('dry_run'):
2904 continue
2904 continue
2905
2905
2906 source = ctx.extra().get('source')
2906 source = ctx.extra().get('source')
2907 if not source:
2907 if not source:
2908 source = ctx.hex()
2908 source = ctx.hex()
2909 extra = {'source': source}
2909 extra = {'source': source}
2910 user = ctx.user()
2910 user = ctx.user()
2911 if opts.get('user'):
2911 if opts.get('user'):
2912 user = opts['user']
2912 user = opts['user']
2913 date = ctx.date()
2913 date = ctx.date()
2914 if opts.get('date'):
2914 if opts.get('date'):
2915 date = opts['date']
2915 date = opts['date']
2916 message = ctx.description()
2916 message = ctx.description()
2917 if opts.get('log'):
2917 if opts.get('log'):
2918 message += '\n(grafted from %s)' % ctx.hex()
2918 message += '\n(grafted from %s)' % ctx.hex()
2919
2919
2920 # we don't merge the first commit when continuing
2920 # we don't merge the first commit when continuing
2921 if not cont:
2921 if not cont:
2922 # perform the graft merge with p1(rev) as 'ancestor'
2922 # perform the graft merge with p1(rev) as 'ancestor'
2923 try:
2923 try:
2924 # ui.forcemerge is an internal variable, do not document
2924 # ui.forcemerge is an internal variable, do not document
2925 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2925 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2926 stats = mergemod.update(repo, ctx.node(), True, True, False,
2926 stats = mergemod.update(repo, ctx.node(), True, True, False,
2927 ctx.p1().node())
2927 ctx.p1().node())
2928 finally:
2928 finally:
2929 repo.ui.setconfig('ui', 'forcemerge', '')
2929 repo.ui.setconfig('ui', 'forcemerge', '')
2930 # report any conflicts
2930 # report any conflicts
2931 if stats and stats[3] > 0:
2931 if stats and stats[3] > 0:
2932 # write out state for --continue
2932 # write out state for --continue
2933 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2933 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2934 repo.opener.write('graftstate', ''.join(nodelines))
2934 repo.opener.write('graftstate', ''.join(nodelines))
2935 raise util.Abort(
2935 raise util.Abort(
2936 _("unresolved conflicts, can't continue"),
2936 _("unresolved conflicts, can't continue"),
2937 hint=_('use hg resolve and hg graft --continue'))
2937 hint=_('use hg resolve and hg graft --continue'))
2938 else:
2938 else:
2939 cont = False
2939 cont = False
2940
2940
2941 # drop the second merge parent
2941 # drop the second merge parent
2942 repo.setparents(current.node(), nullid)
2942 repo.setparents(current.node(), nullid)
2943 repo.dirstate.write()
2943 repo.dirstate.write()
2944 # fix up dirstate for copies and renames
2944 # fix up dirstate for copies and renames
2945 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2945 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2946
2946
2947 # commit
2947 # commit
2948 node = repo.commit(text=message, user=user,
2948 node = repo.commit(text=message, user=user,
2949 date=date, extra=extra, editor=editor)
2949 date=date, extra=extra, editor=editor)
2950 if node is None:
2950 if node is None:
2951 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2951 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2952 else:
2952 else:
2953 current = repo[node]
2953 current = repo[node]
2954 finally:
2954 finally:
2955 wlock.release()
2955 wlock.release()
2956
2956
2957 # remove state when we complete successfully
2957 # remove state when we complete successfully
2958 if not opts.get('dry_run'):
2958 if not opts.get('dry_run'):
2959 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2959 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2960
2960
2961 return 0
2961 return 0
2962
2962
2963 @command('grep',
2963 @command('grep',
2964 [('0', 'print0', None, _('end fields with NUL')),
2964 [('0', 'print0', None, _('end fields with NUL')),
2965 ('', 'all', None, _('print all revisions that match')),
2965 ('', 'all', None, _('print all revisions that match')),
2966 ('a', 'text', None, _('treat all files as text')),
2966 ('a', 'text', None, _('treat all files as text')),
2967 ('f', 'follow', None,
2967 ('f', 'follow', None,
2968 _('follow changeset history,'
2968 _('follow changeset history,'
2969 ' or file history across copies and renames')),
2969 ' or file history across copies and renames')),
2970 ('i', 'ignore-case', None, _('ignore case when matching')),
2970 ('i', 'ignore-case', None, _('ignore case when matching')),
2971 ('l', 'files-with-matches', None,
2971 ('l', 'files-with-matches', None,
2972 _('print only filenames and revisions that match')),
2972 _('print only filenames and revisions that match')),
2973 ('n', 'line-number', None, _('print matching line numbers')),
2973 ('n', 'line-number', None, _('print matching line numbers')),
2974 ('r', 'rev', [],
2974 ('r', 'rev', [],
2975 _('only search files changed within revision range'), _('REV')),
2975 _('only search files changed within revision range'), _('REV')),
2976 ('u', 'user', None, _('list the author (long with -v)')),
2976 ('u', 'user', None, _('list the author (long with -v)')),
2977 ('d', 'date', None, _('list the date (short with -q)')),
2977 ('d', 'date', None, _('list the date (short with -q)')),
2978 ] + walkopts,
2978 ] + walkopts,
2979 _('[OPTION]... PATTERN [FILE]...'))
2979 _('[OPTION]... PATTERN [FILE]...'))
2980 def grep(ui, repo, pattern, *pats, **opts):
2980 def grep(ui, repo, pattern, *pats, **opts):
2981 """search for a pattern in specified files and revisions
2981 """search for a pattern in specified files and revisions
2982
2982
2983 Search revisions of files for a regular expression.
2983 Search revisions of files for a regular expression.
2984
2984
2985 This command behaves differently than Unix grep. It only accepts
2985 This command behaves differently than Unix grep. It only accepts
2986 Python/Perl regexps. It searches repository history, not the
2986 Python/Perl regexps. It searches repository history, not the
2987 working directory. It always prints the revision number in which a
2987 working directory. It always prints the revision number in which a
2988 match appears.
2988 match appears.
2989
2989
2990 By default, grep only prints output for the first revision of a
2990 By default, grep only prints output for the first revision of a
2991 file in which it finds a match. To get it to print every revision
2991 file in which it finds a match. To get it to print every revision
2992 that contains a change in match status ("-" for a match that
2992 that contains a change in match status ("-" for a match that
2993 becomes a non-match, or "+" for a non-match that becomes a match),
2993 becomes a non-match, or "+" for a non-match that becomes a match),
2994 use the --all flag.
2994 use the --all flag.
2995
2995
2996 Returns 0 if a match is found, 1 otherwise.
2996 Returns 0 if a match is found, 1 otherwise.
2997 """
2997 """
2998 reflags = re.M
2998 reflags = re.M
2999 if opts.get('ignore_case'):
2999 if opts.get('ignore_case'):
3000 reflags |= re.I
3000 reflags |= re.I
3001 try:
3001 try:
3002 regexp = re.compile(pattern, reflags)
3002 regexp = re.compile(pattern, reflags)
3003 except re.error, inst:
3003 except re.error, inst:
3004 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3004 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3005 return 1
3005 return 1
3006 sep, eol = ':', '\n'
3006 sep, eol = ':', '\n'
3007 if opts.get('print0'):
3007 if opts.get('print0'):
3008 sep = eol = '\0'
3008 sep = eol = '\0'
3009
3009
3010 getfile = util.lrucachefunc(repo.file)
3010 getfile = util.lrucachefunc(repo.file)
3011
3011
3012 def matchlines(body):
3012 def matchlines(body):
3013 begin = 0
3013 begin = 0
3014 linenum = 0
3014 linenum = 0
3015 while begin < len(body):
3015 while begin < len(body):
3016 match = regexp.search(body, begin)
3016 match = regexp.search(body, begin)
3017 if not match:
3017 if not match:
3018 break
3018 break
3019 mstart, mend = match.span()
3019 mstart, mend = match.span()
3020 linenum += body.count('\n', begin, mstart) + 1
3020 linenum += body.count('\n', begin, mstart) + 1
3021 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3021 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3022 begin = body.find('\n', mend) + 1 or len(body) + 1
3022 begin = body.find('\n', mend) + 1 or len(body) + 1
3023 lend = begin - 1
3023 lend = begin - 1
3024 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3024 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3025
3025
3026 class linestate(object):
3026 class linestate(object):
3027 def __init__(self, line, linenum, colstart, colend):
3027 def __init__(self, line, linenum, colstart, colend):
3028 self.line = line
3028 self.line = line
3029 self.linenum = linenum
3029 self.linenum = linenum
3030 self.colstart = colstart
3030 self.colstart = colstart
3031 self.colend = colend
3031 self.colend = colend
3032
3032
3033 def __hash__(self):
3033 def __hash__(self):
3034 return hash((self.linenum, self.line))
3034 return hash((self.linenum, self.line))
3035
3035
3036 def __eq__(self, other):
3036 def __eq__(self, other):
3037 return self.line == other.line
3037 return self.line == other.line
3038
3038
3039 matches = {}
3039 matches = {}
3040 copies = {}
3040 copies = {}
3041 def grepbody(fn, rev, body):
3041 def grepbody(fn, rev, body):
3042 matches[rev].setdefault(fn, [])
3042 matches[rev].setdefault(fn, [])
3043 m = matches[rev][fn]
3043 m = matches[rev][fn]
3044 for lnum, cstart, cend, line in matchlines(body):
3044 for lnum, cstart, cend, line in matchlines(body):
3045 s = linestate(line, lnum, cstart, cend)
3045 s = linestate(line, lnum, cstart, cend)
3046 m.append(s)
3046 m.append(s)
3047
3047
3048 def difflinestates(a, b):
3048 def difflinestates(a, b):
3049 sm = difflib.SequenceMatcher(None, a, b)
3049 sm = difflib.SequenceMatcher(None, a, b)
3050 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3050 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3051 if tag == 'insert':
3051 if tag == 'insert':
3052 for i in xrange(blo, bhi):
3052 for i in xrange(blo, bhi):
3053 yield ('+', b[i])
3053 yield ('+', b[i])
3054 elif tag == 'delete':
3054 elif tag == 'delete':
3055 for i in xrange(alo, ahi):
3055 for i in xrange(alo, ahi):
3056 yield ('-', a[i])
3056 yield ('-', a[i])
3057 elif tag == 'replace':
3057 elif tag == 'replace':
3058 for i in xrange(alo, ahi):
3058 for i in xrange(alo, ahi):
3059 yield ('-', a[i])
3059 yield ('-', a[i])
3060 for i in xrange(blo, bhi):
3060 for i in xrange(blo, bhi):
3061 yield ('+', b[i])
3061 yield ('+', b[i])
3062
3062
3063 def display(fn, ctx, pstates, states):
3063 def display(fn, ctx, pstates, states):
3064 rev = ctx.rev()
3064 rev = ctx.rev()
3065 datefunc = ui.quiet and util.shortdate or util.datestr
3065 datefunc = ui.quiet and util.shortdate or util.datestr
3066 found = False
3066 found = False
3067 filerevmatches = {}
3067 filerevmatches = {}
3068 def binary():
3068 def binary():
3069 flog = getfile(fn)
3069 flog = getfile(fn)
3070 return util.binary(flog.read(ctx.filenode(fn)))
3070 return util.binary(flog.read(ctx.filenode(fn)))
3071
3071
3072 if opts.get('all'):
3072 if opts.get('all'):
3073 iter = difflinestates(pstates, states)
3073 iter = difflinestates(pstates, states)
3074 else:
3074 else:
3075 iter = [('', l) for l in states]
3075 iter = [('', l) for l in states]
3076 for change, l in iter:
3076 for change, l in iter:
3077 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3077 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3078 before, match, after = None, None, None
3078 before, match, after = None, None, None
3079
3079
3080 if opts.get('line_number'):
3080 if opts.get('line_number'):
3081 cols.append((str(l.linenum), 'grep.linenumber'))
3081 cols.append((str(l.linenum), 'grep.linenumber'))
3082 if opts.get('all'):
3082 if opts.get('all'):
3083 cols.append((change, 'grep.change'))
3083 cols.append((change, 'grep.change'))
3084 if opts.get('user'):
3084 if opts.get('user'):
3085 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3085 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3086 if opts.get('date'):
3086 if opts.get('date'):
3087 cols.append((datefunc(ctx.date()), 'grep.date'))
3087 cols.append((datefunc(ctx.date()), 'grep.date'))
3088 if opts.get('files_with_matches'):
3088 if opts.get('files_with_matches'):
3089 c = (fn, rev)
3089 c = (fn, rev)
3090 if c in filerevmatches:
3090 if c in filerevmatches:
3091 continue
3091 continue
3092 filerevmatches[c] = 1
3092 filerevmatches[c] = 1
3093 else:
3093 else:
3094 before = l.line[:l.colstart]
3094 before = l.line[:l.colstart]
3095 match = l.line[l.colstart:l.colend]
3095 match = l.line[l.colstart:l.colend]
3096 after = l.line[l.colend:]
3096 after = l.line[l.colend:]
3097 for col, label in cols[:-1]:
3097 for col, label in cols[:-1]:
3098 ui.write(col, label=label)
3098 ui.write(col, label=label)
3099 ui.write(sep, label='grep.sep')
3099 ui.write(sep, label='grep.sep')
3100 ui.write(cols[-1][0], label=cols[-1][1])
3100 ui.write(cols[-1][0], label=cols[-1][1])
3101 if before is not None:
3101 if before is not None:
3102 ui.write(sep, label='grep.sep')
3102 ui.write(sep, label='grep.sep')
3103 if not opts.get('text') and binary():
3103 if not opts.get('text') and binary():
3104 ui.write(" Binary file matches")
3104 ui.write(" Binary file matches")
3105 else:
3105 else:
3106 ui.write(before)
3106 ui.write(before)
3107 ui.write(match, label='grep.match')
3107 ui.write(match, label='grep.match')
3108 ui.write(after)
3108 ui.write(after)
3109 ui.write(eol)
3109 ui.write(eol)
3110 found = True
3110 found = True
3111 return found
3111 return found
3112
3112
3113 skip = {}
3113 skip = {}
3114 revfiles = {}
3114 revfiles = {}
3115 matchfn = scmutil.match(repo[None], pats, opts)
3115 matchfn = scmutil.match(repo[None], pats, opts)
3116 found = False
3116 found = False
3117 follow = opts.get('follow')
3117 follow = opts.get('follow')
3118
3118
3119 def prep(ctx, fns):
3119 def prep(ctx, fns):
3120 rev = ctx.rev()
3120 rev = ctx.rev()
3121 pctx = ctx.p1()
3121 pctx = ctx.p1()
3122 parent = pctx.rev()
3122 parent = pctx.rev()
3123 matches.setdefault(rev, {})
3123 matches.setdefault(rev, {})
3124 matches.setdefault(parent, {})
3124 matches.setdefault(parent, {})
3125 files = revfiles.setdefault(rev, [])
3125 files = revfiles.setdefault(rev, [])
3126 for fn in fns:
3126 for fn in fns:
3127 flog = getfile(fn)
3127 flog = getfile(fn)
3128 try:
3128 try:
3129 fnode = ctx.filenode(fn)
3129 fnode = ctx.filenode(fn)
3130 except error.LookupError:
3130 except error.LookupError:
3131 continue
3131 continue
3132
3132
3133 copied = flog.renamed(fnode)
3133 copied = flog.renamed(fnode)
3134 copy = follow and copied and copied[0]
3134 copy = follow and copied and copied[0]
3135 if copy:
3135 if copy:
3136 copies.setdefault(rev, {})[fn] = copy
3136 copies.setdefault(rev, {})[fn] = copy
3137 if fn in skip:
3137 if fn in skip:
3138 if copy:
3138 if copy:
3139 skip[copy] = True
3139 skip[copy] = True
3140 continue
3140 continue
3141 files.append(fn)
3141 files.append(fn)
3142
3142
3143 if fn not in matches[rev]:
3143 if fn not in matches[rev]:
3144 grepbody(fn, rev, flog.read(fnode))
3144 grepbody(fn, rev, flog.read(fnode))
3145
3145
3146 pfn = copy or fn
3146 pfn = copy or fn
3147 if pfn not in matches[parent]:
3147 if pfn not in matches[parent]:
3148 try:
3148 try:
3149 fnode = pctx.filenode(pfn)
3149 fnode = pctx.filenode(pfn)
3150 grepbody(pfn, parent, flog.read(fnode))
3150 grepbody(pfn, parent, flog.read(fnode))
3151 except error.LookupError:
3151 except error.LookupError:
3152 pass
3152 pass
3153
3153
3154 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3154 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3155 rev = ctx.rev()
3155 rev = ctx.rev()
3156 parent = ctx.p1().rev()
3156 parent = ctx.p1().rev()
3157 for fn in sorted(revfiles.get(rev, [])):
3157 for fn in sorted(revfiles.get(rev, [])):
3158 states = matches[rev][fn]
3158 states = matches[rev][fn]
3159 copy = copies.get(rev, {}).get(fn)
3159 copy = copies.get(rev, {}).get(fn)
3160 if fn in skip:
3160 if fn in skip:
3161 if copy:
3161 if copy:
3162 skip[copy] = True
3162 skip[copy] = True
3163 continue
3163 continue
3164 pstates = matches.get(parent, {}).get(copy or fn, [])
3164 pstates = matches.get(parent, {}).get(copy or fn, [])
3165 if pstates or states:
3165 if pstates or states:
3166 r = display(fn, ctx, pstates, states)
3166 r = display(fn, ctx, pstates, states)
3167 found = found or r
3167 found = found or r
3168 if r and not opts.get('all'):
3168 if r and not opts.get('all'):
3169 skip[fn] = True
3169 skip[fn] = True
3170 if copy:
3170 if copy:
3171 skip[copy] = True
3171 skip[copy] = True
3172 del matches[rev]
3172 del matches[rev]
3173 del revfiles[rev]
3173 del revfiles[rev]
3174
3174
3175 return not found
3175 return not found
3176
3176
3177 @command('heads',
3177 @command('heads',
3178 [('r', 'rev', '',
3178 [('r', 'rev', '',
3179 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3179 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3180 ('t', 'topo', False, _('show topological heads only')),
3180 ('t', 'topo', False, _('show topological heads only')),
3181 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3181 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3182 ('c', 'closed', False, _('show normal and closed branch heads')),
3182 ('c', 'closed', False, _('show normal and closed branch heads')),
3183 ] + templateopts,
3183 ] + templateopts,
3184 _('[-ct] [-r STARTREV] [REV]...'))
3184 _('[-ct] [-r STARTREV] [REV]...'))
3185 def heads(ui, repo, *branchrevs, **opts):
3185 def heads(ui, repo, *branchrevs, **opts):
3186 """show current repository heads or show branch heads
3186 """show current repository heads or show branch heads
3187
3187
3188 With no arguments, show all repository branch heads.
3188 With no arguments, show all repository branch heads.
3189
3189
3190 Repository "heads" are changesets with no child changesets. They are
3190 Repository "heads" are changesets with no child changesets. They are
3191 where development generally takes place and are the usual targets
3191 where development generally takes place and are the usual targets
3192 for update and merge operations. Branch heads are changesets that have
3192 for update and merge operations. Branch heads are changesets that have
3193 no child changeset on the same branch.
3193 no child changeset on the same branch.
3194
3194
3195 If one or more REVs are given, only branch heads on the branches
3195 If one or more REVs are given, only branch heads on the branches
3196 associated with the specified changesets are shown. This means
3196 associated with the specified changesets are shown. This means
3197 that you can use :hg:`heads foo` to see the heads on a branch
3197 that you can use :hg:`heads foo` to see the heads on a branch
3198 named ``foo``.
3198 named ``foo``.
3199
3199
3200 If -c/--closed is specified, also show branch heads marked closed
3200 If -c/--closed is specified, also show branch heads marked closed
3201 (see :hg:`commit --close-branch`).
3201 (see :hg:`commit --close-branch`).
3202
3202
3203 If STARTREV is specified, only those heads that are descendants of
3203 If STARTREV is specified, only those heads that are descendants of
3204 STARTREV will be displayed.
3204 STARTREV will be displayed.
3205
3205
3206 If -t/--topo is specified, named branch mechanics will be ignored and only
3206 If -t/--topo is specified, named branch mechanics will be ignored and only
3207 changesets without children will be shown.
3207 changesets without children will be shown.
3208
3208
3209 Returns 0 if matching heads are found, 1 if not.
3209 Returns 0 if matching heads are found, 1 if not.
3210 """
3210 """
3211
3211
3212 start = None
3212 start = None
3213 if 'rev' in opts:
3213 if 'rev' in opts:
3214 start = scmutil.revsingle(repo, opts['rev'], None).node()
3214 start = scmutil.revsingle(repo, opts['rev'], None).node()
3215
3215
3216 if opts.get('topo'):
3216 if opts.get('topo'):
3217 heads = [repo[h] for h in repo.heads(start)]
3217 heads = [repo[h] for h in repo.heads(start)]
3218 else:
3218 else:
3219 heads = []
3219 heads = []
3220 for branch in repo.branchmap():
3220 for branch in repo.branchmap():
3221 heads += repo.branchheads(branch, start, opts.get('closed'))
3221 heads += repo.branchheads(branch, start, opts.get('closed'))
3222 heads = [repo[h] for h in heads]
3222 heads = [repo[h] for h in heads]
3223
3223
3224 if branchrevs:
3224 if branchrevs:
3225 branches = set(repo[br].branch() for br in branchrevs)
3225 branches = set(repo[br].branch() for br in branchrevs)
3226 heads = [h for h in heads if h.branch() in branches]
3226 heads = [h for h in heads if h.branch() in branches]
3227
3227
3228 if opts.get('active') and branchrevs:
3228 if opts.get('active') and branchrevs:
3229 dagheads = repo.heads(start)
3229 dagheads = repo.heads(start)
3230 heads = [h for h in heads if h.node() in dagheads]
3230 heads = [h for h in heads if h.node() in dagheads]
3231
3231
3232 if branchrevs:
3232 if branchrevs:
3233 haveheads = set(h.branch() for h in heads)
3233 haveheads = set(h.branch() for h in heads)
3234 if branches - haveheads:
3234 if branches - haveheads:
3235 headless = ', '.join(b for b in branches - haveheads)
3235 headless = ', '.join(b for b in branches - haveheads)
3236 msg = _('no open branch heads found on branches %s')
3236 msg = _('no open branch heads found on branches %s')
3237 if opts.get('rev'):
3237 if opts.get('rev'):
3238 msg += _(' (started at %s)') % opts['rev']
3238 msg += _(' (started at %s)') % opts['rev']
3239 ui.warn((msg + '\n') % headless)
3239 ui.warn((msg + '\n') % headless)
3240
3240
3241 if not heads:
3241 if not heads:
3242 return 1
3242 return 1
3243
3243
3244 heads = sorted(heads, key=lambda x: -x.rev())
3244 heads = sorted(heads, key=lambda x: -x.rev())
3245 displayer = cmdutil.show_changeset(ui, repo, opts)
3245 displayer = cmdutil.show_changeset(ui, repo, opts)
3246 for ctx in heads:
3246 for ctx in heads:
3247 displayer.show(ctx)
3247 displayer.show(ctx)
3248 displayer.close()
3248 displayer.close()
3249
3249
3250 @command('help',
3250 @command('help',
3251 [('e', 'extension', None, _('show only help for extensions')),
3251 [('e', 'extension', None, _('show only help for extensions')),
3252 ('c', 'command', None, _('show only help for commands')),
3252 ('c', 'command', None, _('show only help for commands')),
3253 ('k', 'keyword', '', _('show topics matching keyword')),
3253 ('k', 'keyword', '', _('show topics matching keyword')),
3254 ],
3254 ],
3255 _('[-ec] [TOPIC]'))
3255 _('[-ec] [TOPIC]'))
3256 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3256 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3257 """show help for a given topic or a help overview
3257 """show help for a given topic or a help overview
3258
3258
3259 With no arguments, print a list of commands with short help messages.
3259 With no arguments, print a list of commands with short help messages.
3260
3260
3261 Given a topic, extension, or command name, print help for that
3261 Given a topic, extension, or command name, print help for that
3262 topic.
3262 topic.
3263
3263
3264 Returns 0 if successful.
3264 Returns 0 if successful.
3265 """
3265 """
3266
3266
3267 textwidth = min(ui.termwidth(), 80) - 2
3267 textwidth = min(ui.termwidth(), 80) - 2
3268
3268
3269 def helpcmd(name):
3269 def helpcmd(name):
3270 try:
3270 try:
3271 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3271 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3272 except error.AmbiguousCommand, inst:
3272 except error.AmbiguousCommand, inst:
3273 # py3k fix: except vars can't be used outside the scope of the
3273 # py3k fix: except vars can't be used outside the scope of the
3274 # except block, nor can be used inside a lambda. python issue4617
3274 # except block, nor can be used inside a lambda. python issue4617
3275 prefix = inst.args[0]
3275 prefix = inst.args[0]
3276 select = lambda c: c.lstrip('^').startswith(prefix)
3276 select = lambda c: c.lstrip('^').startswith(prefix)
3277 rst = helplist(select)
3277 rst = helplist(select)
3278 return rst
3278 return rst
3279
3279
3280 rst = []
3280 rst = []
3281
3281
3282 # check if it's an invalid alias and display its error if it is
3282 # check if it's an invalid alias and display its error if it is
3283 if getattr(entry[0], 'badalias', False):
3283 if getattr(entry[0], 'badalias', False):
3284 if not unknowncmd:
3284 if not unknowncmd:
3285 ui.pushbuffer()
3285 ui.pushbuffer()
3286 entry[0](ui)
3286 entry[0](ui)
3287 rst.append(ui.popbuffer())
3287 rst.append(ui.popbuffer())
3288 return rst
3288 return rst
3289
3289
3290 # synopsis
3290 # synopsis
3291 if len(entry) > 2:
3291 if len(entry) > 2:
3292 if entry[2].startswith('hg'):
3292 if entry[2].startswith('hg'):
3293 rst.append("%s\n" % entry[2])
3293 rst.append("%s\n" % entry[2])
3294 else:
3294 else:
3295 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3295 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3296 else:
3296 else:
3297 rst.append('hg %s\n' % aliases[0])
3297 rst.append('hg %s\n' % aliases[0])
3298 # aliases
3298 # aliases
3299 if full and not ui.quiet and len(aliases) > 1:
3299 if full and not ui.quiet and len(aliases) > 1:
3300 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3300 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3301 rst.append('\n')
3301 rst.append('\n')
3302
3302
3303 # description
3303 # description
3304 doc = gettext(entry[0].__doc__)
3304 doc = gettext(entry[0].__doc__)
3305 if not doc:
3305 if not doc:
3306 doc = _("(no help text available)")
3306 doc = _("(no help text available)")
3307 if util.safehasattr(entry[0], 'definition'): # aliased command
3307 if util.safehasattr(entry[0], 'definition'): # aliased command
3308 if entry[0].definition.startswith('!'): # shell alias
3308 if entry[0].definition.startswith('!'): # shell alias
3309 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3309 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3310 else:
3310 else:
3311 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3311 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3312 doc = doc.splitlines(True)
3312 doc = doc.splitlines(True)
3313 if ui.quiet or not full:
3313 if ui.quiet or not full:
3314 rst.append(doc[0])
3314 rst.append(doc[0])
3315 else:
3315 else:
3316 rst.extend(doc)
3316 rst.extend(doc)
3317 rst.append('\n')
3317 rst.append('\n')
3318
3318
3319 # check if this command shadows a non-trivial (multi-line)
3319 # check if this command shadows a non-trivial (multi-line)
3320 # extension help text
3320 # extension help text
3321 try:
3321 try:
3322 mod = extensions.find(name)
3322 mod = extensions.find(name)
3323 doc = gettext(mod.__doc__) or ''
3323 doc = gettext(mod.__doc__) or ''
3324 if '\n' in doc.strip():
3324 if '\n' in doc.strip():
3325 msg = _('use "hg help -e %s" to show help for '
3325 msg = _('use "hg help -e %s" to show help for '
3326 'the %s extension') % (name, name)
3326 'the %s extension') % (name, name)
3327 rst.append('\n%s\n' % msg)
3327 rst.append('\n%s\n' % msg)
3328 except KeyError:
3328 except KeyError:
3329 pass
3329 pass
3330
3330
3331 # options
3331 # options
3332 if not ui.quiet and entry[1]:
3332 if not ui.quiet and entry[1]:
3333 rst.append('\n%s\n\n' % _("options:"))
3333 rst.append('\n%s\n\n' % _("options:"))
3334 rst.append(help.optrst(entry[1], ui.verbose))
3334 rst.append(help.optrst(entry[1], ui.verbose))
3335
3335
3336 if ui.verbose:
3336 if ui.verbose:
3337 rst.append('\n%s\n\n' % _("global options:"))
3337 rst.append('\n%s\n\n' % _("global options:"))
3338 rst.append(help.optrst(globalopts, ui.verbose))
3338 rst.append(help.optrst(globalopts, ui.verbose))
3339
3339
3340 if not ui.verbose:
3340 if not ui.verbose:
3341 if not full:
3341 if not full:
3342 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3342 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3343 % name)
3343 % name)
3344 elif not ui.quiet:
3344 elif not ui.quiet:
3345 omitted = _('use "hg -v help %s" to show more complete'
3345 omitted = _('use "hg -v help %s" to show more complete'
3346 ' help and the global options') % name
3346 ' help and the global options') % name
3347 notomitted = _('use "hg -v help %s" to show'
3347 notomitted = _('use "hg -v help %s" to show'
3348 ' the global options') % name
3348 ' the global options') % name
3349 help.indicateomitted(rst, omitted, notomitted)
3349 help.indicateomitted(rst, omitted, notomitted)
3350
3350
3351 return rst
3351 return rst
3352
3352
3353
3353
3354 def helplist(select=None):
3354 def helplist(select=None):
3355 # list of commands
3355 # list of commands
3356 if name == "shortlist":
3356 if name == "shortlist":
3357 header = _('basic commands:\n\n')
3357 header = _('basic commands:\n\n')
3358 else:
3358 else:
3359 header = _('list of commands:\n\n')
3359 header = _('list of commands:\n\n')
3360
3360
3361 h = {}
3361 h = {}
3362 cmds = {}
3362 cmds = {}
3363 for c, e in table.iteritems():
3363 for c, e in table.iteritems():
3364 f = c.split("|", 1)[0]
3364 f = c.split("|", 1)[0]
3365 if select and not select(f):
3365 if select and not select(f):
3366 continue
3366 continue
3367 if (not select and name != 'shortlist' and
3367 if (not select and name != 'shortlist' and
3368 e[0].__module__ != __name__):
3368 e[0].__module__ != __name__):
3369 continue
3369 continue
3370 if name == "shortlist" and not f.startswith("^"):
3370 if name == "shortlist" and not f.startswith("^"):
3371 continue
3371 continue
3372 f = f.lstrip("^")
3372 f = f.lstrip("^")
3373 if not ui.debugflag and f.startswith("debug"):
3373 if not ui.debugflag and f.startswith("debug"):
3374 continue
3374 continue
3375 doc = e[0].__doc__
3375 doc = e[0].__doc__
3376 if doc and 'DEPRECATED' in doc and not ui.verbose:
3376 if doc and 'DEPRECATED' in doc and not ui.verbose:
3377 continue
3377 continue
3378 doc = gettext(doc)
3378 doc = gettext(doc)
3379 if not doc:
3379 if not doc:
3380 doc = _("(no help text available)")
3380 doc = _("(no help text available)")
3381 h[f] = doc.splitlines()[0].rstrip()
3381 h[f] = doc.splitlines()[0].rstrip()
3382 cmds[f] = c.lstrip("^")
3382 cmds[f] = c.lstrip("^")
3383
3383
3384 rst = []
3384 rst = []
3385 if not h:
3385 if not h:
3386 if not ui.quiet:
3386 if not ui.quiet:
3387 rst.append(_('no commands defined\n'))
3387 rst.append(_('no commands defined\n'))
3388 return rst
3388 return rst
3389
3389
3390 if not ui.quiet:
3390 if not ui.quiet:
3391 rst.append(header)
3391 rst.append(header)
3392 fns = sorted(h)
3392 fns = sorted(h)
3393 for f in fns:
3393 for f in fns:
3394 if ui.verbose:
3394 if ui.verbose:
3395 commands = cmds[f].replace("|",", ")
3395 commands = cmds[f].replace("|",", ")
3396 rst.append(" :%s: %s\n" % (commands, h[f]))
3396 rst.append(" :%s: %s\n" % (commands, h[f]))
3397 else:
3397 else:
3398 rst.append(' :%s: %s\n' % (f, h[f]))
3398 rst.append(' :%s: %s\n' % (f, h[f]))
3399
3399
3400 if not name:
3400 if not name:
3401 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3401 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3402 if exts:
3402 if exts:
3403 rst.append('\n')
3403 rst.append('\n')
3404 rst.extend(exts)
3404 rst.extend(exts)
3405
3405
3406 rst.append(_("\nadditional help topics:\n\n"))
3406 rst.append(_("\nadditional help topics:\n\n"))
3407 topics = []
3407 topics = []
3408 for names, header, doc in help.helptable:
3408 for names, header, doc in help.helptable:
3409 topics.append((names[0], header))
3409 topics.append((names[0], header))
3410 for t, desc in topics:
3410 for t, desc in topics:
3411 rst.append(" :%s: %s\n" % (t, desc))
3411 rst.append(" :%s: %s\n" % (t, desc))
3412
3412
3413 optlist = []
3413 optlist = []
3414 if not ui.quiet:
3414 if not ui.quiet:
3415 if ui.verbose:
3415 if ui.verbose:
3416 optlist.append((_("global options:"), globalopts))
3416 optlist.append((_("global options:"), globalopts))
3417 if name == 'shortlist':
3417 if name == 'shortlist':
3418 optlist.append((_('use "hg help" for the full list '
3418 optlist.append((_('use "hg help" for the full list '
3419 'of commands'), ()))
3419 'of commands'), ()))
3420 else:
3420 else:
3421 if name == 'shortlist':
3421 if name == 'shortlist':
3422 msg = _('use "hg help" for the full list of commands '
3422 msg = _('use "hg help" for the full list of commands '
3423 'or "hg -v" for details')
3423 'or "hg -v" for details')
3424 elif name and not full:
3424 elif name and not full:
3425 msg = _('use "hg help %s" to show the full help '
3425 msg = _('use "hg help %s" to show the full help '
3426 'text') % name
3426 'text') % name
3427 else:
3427 else:
3428 msg = _('use "hg -v help%s" to show builtin aliases and '
3428 msg = _('use "hg -v help%s" to show builtin aliases and '
3429 'global options') % (name and " " + name or "")
3429 'global options') % (name and " " + name or "")
3430 optlist.append((msg, ()))
3430 optlist.append((msg, ()))
3431
3431
3432 if optlist:
3432 if optlist:
3433 for title, options in optlist:
3433 for title, options in optlist:
3434 rst.append('\n%s\n' % title)
3434 rst.append('\n%s\n' % title)
3435 if options:
3435 if options:
3436 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3436 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3437 return rst
3437 return rst
3438
3438
3439 def helptopic(name):
3439 def helptopic(name):
3440 for names, header, doc in help.helptable:
3440 for names, header, doc in help.helptable:
3441 if name in names:
3441 if name in names:
3442 break
3442 break
3443 else:
3443 else:
3444 raise error.UnknownCommand(name)
3444 raise error.UnknownCommand(name)
3445
3445
3446 rst = ["%s\n\n" % header]
3446 rst = ["%s\n\n" % header]
3447 # description
3447 # description
3448 if not doc:
3448 if not doc:
3449 rst.append(" %s\n" % _("(no help text available)"))
3449 rst.append(" %s\n" % _("(no help text available)"))
3450 if util.safehasattr(doc, '__call__'):
3450 if util.safehasattr(doc, '__call__'):
3451 rst += [" %s\n" % l for l in doc().splitlines()]
3451 rst += [" %s\n" % l for l in doc().splitlines()]
3452
3452
3453 if not ui.verbose:
3453 if not ui.verbose:
3454 omitted = (_('use "hg help -v %s" to show more complete help') %
3454 omitted = (_('use "hg help -v %s" to show more complete help') %
3455 name)
3455 name)
3456 help.indicateomitted(rst, omitted)
3456 help.indicateomitted(rst, omitted)
3457
3457
3458 try:
3458 try:
3459 cmdutil.findcmd(name, table)
3459 cmdutil.findcmd(name, table)
3460 rst.append(_('\nuse "hg help -c %s" to see help for '
3460 rst.append(_('\nuse "hg help -c %s" to see help for '
3461 'the %s command\n') % (name, name))
3461 'the %s command\n') % (name, name))
3462 except error.UnknownCommand:
3462 except error.UnknownCommand:
3463 pass
3463 pass
3464 return rst
3464 return rst
3465
3465
3466 def helpext(name):
3466 def helpext(name):
3467 try:
3467 try:
3468 mod = extensions.find(name)
3468 mod = extensions.find(name)
3469 doc = gettext(mod.__doc__) or _('no help text available')
3469 doc = gettext(mod.__doc__) or _('no help text available')
3470 except KeyError:
3470 except KeyError:
3471 mod = None
3471 mod = None
3472 doc = extensions.disabledext(name)
3472 doc = extensions.disabledext(name)
3473 if not doc:
3473 if not doc:
3474 raise error.UnknownCommand(name)
3474 raise error.UnknownCommand(name)
3475
3475
3476 if '\n' not in doc:
3476 if '\n' not in doc:
3477 head, tail = doc, ""
3477 head, tail = doc, ""
3478 else:
3478 else:
3479 head, tail = doc.split('\n', 1)
3479 head, tail = doc.split('\n', 1)
3480 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3480 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3481 if tail:
3481 if tail:
3482 rst.extend(tail.splitlines(True))
3482 rst.extend(tail.splitlines(True))
3483 rst.append('\n')
3483 rst.append('\n')
3484
3484
3485 if not ui.verbose:
3485 if not ui.verbose:
3486 omitted = (_('use "hg help -v %s" to show more complete help') %
3486 omitted = (_('use "hg help -v %s" to show more complete help') %
3487 name)
3487 name)
3488 help.indicateomitted(rst, omitted)
3488 help.indicateomitted(rst, omitted)
3489
3489
3490 if mod:
3490 if mod:
3491 try:
3491 try:
3492 ct = mod.cmdtable
3492 ct = mod.cmdtable
3493 except AttributeError:
3493 except AttributeError:
3494 ct = {}
3494 ct = {}
3495 modcmds = set([c.split('|', 1)[0] for c in ct])
3495 modcmds = set([c.split('|', 1)[0] for c in ct])
3496 rst.extend(helplist(modcmds.__contains__))
3496 rst.extend(helplist(modcmds.__contains__))
3497 else:
3497 else:
3498 rst.append(_('use "hg help extensions" for information on enabling '
3498 rst.append(_('use "hg help extensions" for information on enabling '
3499 'extensions\n'))
3499 'extensions\n'))
3500 return rst
3500 return rst
3501
3501
3502 def helpextcmd(name):
3502 def helpextcmd(name):
3503 cmd, ext, mod = extensions.disabledcmd(ui, name,
3503 cmd, ext, mod = extensions.disabledcmd(ui, name,
3504 ui.configbool('ui', 'strict'))
3504 ui.configbool('ui', 'strict'))
3505 doc = gettext(mod.__doc__).splitlines()[0]
3505 doc = gettext(mod.__doc__).splitlines()[0]
3506
3506
3507 rst = help.listexts(_("'%s' is provided by the following "
3507 rst = help.listexts(_("'%s' is provided by the following "
3508 "extension:") % cmd, {ext: doc}, indent=4)
3508 "extension:") % cmd, {ext: doc}, indent=4)
3509 rst.append('\n')
3509 rst.append('\n')
3510 rst.append(_('use "hg help extensions" for information on enabling '
3510 rst.append(_('use "hg help extensions" for information on enabling '
3511 'extensions\n'))
3511 'extensions\n'))
3512 return rst
3512 return rst
3513
3513
3514
3514
3515 rst = []
3515 rst = []
3516 kw = opts.get('keyword')
3516 kw = opts.get('keyword')
3517 if kw:
3517 if kw:
3518 matches = help.topicmatch(kw)
3518 matches = help.topicmatch(kw)
3519 for t, title in (('topics', _('Topics')),
3519 for t, title in (('topics', _('Topics')),
3520 ('commands', _('Commands')),
3520 ('commands', _('Commands')),
3521 ('extensions', _('Extensions')),
3521 ('extensions', _('Extensions')),
3522 ('extensioncommands', _('Extension Commands'))):
3522 ('extensioncommands', _('Extension Commands'))):
3523 if matches[t]:
3523 if matches[t]:
3524 rst.append('%s:\n\n' % title)
3524 rst.append('%s:\n\n' % title)
3525 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3525 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3526 rst.append('\n')
3526 rst.append('\n')
3527 elif name and name != 'shortlist':
3527 elif name and name != 'shortlist':
3528 i = None
3528 i = None
3529 if unknowncmd:
3529 if unknowncmd:
3530 queries = (helpextcmd,)
3530 queries = (helpextcmd,)
3531 elif opts.get('extension'):
3531 elif opts.get('extension'):
3532 queries = (helpext,)
3532 queries = (helpext,)
3533 elif opts.get('command'):
3533 elif opts.get('command'):
3534 queries = (helpcmd,)
3534 queries = (helpcmd,)
3535 else:
3535 else:
3536 queries = (helptopic, helpcmd, helpext, helpextcmd)
3536 queries = (helptopic, helpcmd, helpext, helpextcmd)
3537 for f in queries:
3537 for f in queries:
3538 try:
3538 try:
3539 rst = f(name)
3539 rst = f(name)
3540 i = None
3540 i = None
3541 break
3541 break
3542 except error.UnknownCommand, inst:
3542 except error.UnknownCommand, inst:
3543 i = inst
3543 i = inst
3544 if i:
3544 if i:
3545 raise i
3545 raise i
3546 else:
3546 else:
3547 # program name
3547 # program name
3548 if not ui.quiet:
3548 if not ui.quiet:
3549 rst = [_("Mercurial Distributed SCM\n"), '\n']
3549 rst = [_("Mercurial Distributed SCM\n"), '\n']
3550 rst.extend(helplist())
3550 rst.extend(helplist())
3551
3551
3552 keep = ui.verbose and ['verbose'] or []
3552 keep = ui.verbose and ['verbose'] or []
3553 text = ''.join(rst)
3553 text = ''.join(rst)
3554 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3554 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3555 if 'verbose' in pruned:
3555 if 'verbose' in pruned:
3556 keep.append('omitted')
3556 keep.append('omitted')
3557 else:
3557 else:
3558 keep.append('notomitted')
3558 keep.append('notomitted')
3559 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3559 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3560 ui.write(formatted)
3560 ui.write(formatted)
3561
3561
3562
3562
3563 @command('identify|id',
3563 @command('identify|id',
3564 [('r', 'rev', '',
3564 [('r', 'rev', '',
3565 _('identify the specified revision'), _('REV')),
3565 _('identify the specified revision'), _('REV')),
3566 ('n', 'num', None, _('show local revision number')),
3566 ('n', 'num', None, _('show local revision number')),
3567 ('i', 'id', None, _('show global revision id')),
3567 ('i', 'id', None, _('show global revision id')),
3568 ('b', 'branch', None, _('show branch')),
3568 ('b', 'branch', None, _('show branch')),
3569 ('t', 'tags', None, _('show tags')),
3569 ('t', 'tags', None, _('show tags')),
3570 ('B', 'bookmarks', None, _('show bookmarks')),
3570 ('B', 'bookmarks', None, _('show bookmarks')),
3571 ] + remoteopts,
3571 ] + remoteopts,
3572 _('[-nibtB] [-r REV] [SOURCE]'))
3572 _('[-nibtB] [-r REV] [SOURCE]'))
3573 def identify(ui, repo, source=None, rev=None,
3573 def identify(ui, repo, source=None, rev=None,
3574 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3574 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3575 """identify the working copy or specified revision
3575 """identify the working copy or specified revision
3576
3576
3577 Print a summary identifying the repository state at REV using one or
3577 Print a summary identifying the repository state at REV using one or
3578 two parent hash identifiers, followed by a "+" if the working
3578 two parent hash identifiers, followed by a "+" if the working
3579 directory has uncommitted changes, the branch name (if not default),
3579 directory has uncommitted changes, the branch name (if not default),
3580 a list of tags, and a list of bookmarks.
3580 a list of tags, and a list of bookmarks.
3581
3581
3582 When REV is not given, print a summary of the current state of the
3582 When REV is not given, print a summary of the current state of the
3583 repository.
3583 repository.
3584
3584
3585 Specifying a path to a repository root or Mercurial bundle will
3585 Specifying a path to a repository root or Mercurial bundle will
3586 cause lookup to operate on that repository/bundle.
3586 cause lookup to operate on that repository/bundle.
3587
3587
3588 .. container:: verbose
3588 .. container:: verbose
3589
3589
3590 Examples:
3590 Examples:
3591
3591
3592 - generate a build identifier for the working directory::
3592 - generate a build identifier for the working directory::
3593
3593
3594 hg id --id > build-id.dat
3594 hg id --id > build-id.dat
3595
3595
3596 - find the revision corresponding to a tag::
3596 - find the revision corresponding to a tag::
3597
3597
3598 hg id -n -r 1.3
3598 hg id -n -r 1.3
3599
3599
3600 - check the most recent revision of a remote repository::
3600 - check the most recent revision of a remote repository::
3601
3601
3602 hg id -r tip http://selenic.com/hg/
3602 hg id -r tip http://selenic.com/hg/
3603
3603
3604 Returns 0 if successful.
3604 Returns 0 if successful.
3605 """
3605 """
3606
3606
3607 if not repo and not source:
3607 if not repo and not source:
3608 raise util.Abort(_("there is no Mercurial repository here "
3608 raise util.Abort(_("there is no Mercurial repository here "
3609 "(.hg not found)"))
3609 "(.hg not found)"))
3610
3610
3611 hexfunc = ui.debugflag and hex or short
3611 hexfunc = ui.debugflag and hex or short
3612 default = not (num or id or branch or tags or bookmarks)
3612 default = not (num or id or branch or tags or bookmarks)
3613 output = []
3613 output = []
3614 revs = []
3614 revs = []
3615
3615
3616 if source:
3616 if source:
3617 source, branches = hg.parseurl(ui.expandpath(source))
3617 source, branches = hg.parseurl(ui.expandpath(source))
3618 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3618 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3619 repo = peer.local()
3619 repo = peer.local()
3620 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3620 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3621
3621
3622 if not repo:
3622 if not repo:
3623 if num or branch or tags:
3623 if num or branch or tags:
3624 raise util.Abort(
3624 raise util.Abort(
3625 _("can't query remote revision number, branch, or tags"))
3625 _("can't query remote revision number, branch, or tags"))
3626 if not rev and revs:
3626 if not rev and revs:
3627 rev = revs[0]
3627 rev = revs[0]
3628 if not rev:
3628 if not rev:
3629 rev = "tip"
3629 rev = "tip"
3630
3630
3631 remoterev = peer.lookup(rev)
3631 remoterev = peer.lookup(rev)
3632 if default or id:
3632 if default or id:
3633 output = [hexfunc(remoterev)]
3633 output = [hexfunc(remoterev)]
3634
3634
3635 def getbms():
3635 def getbms():
3636 bms = []
3636 bms = []
3637
3637
3638 if 'bookmarks' in peer.listkeys('namespaces'):
3638 if 'bookmarks' in peer.listkeys('namespaces'):
3639 hexremoterev = hex(remoterev)
3639 hexremoterev = hex(remoterev)
3640 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3640 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3641 if bmr == hexremoterev]
3641 if bmr == hexremoterev]
3642
3642
3643 return sorted(bms)
3643 return sorted(bms)
3644
3644
3645 if bookmarks:
3645 if bookmarks:
3646 output.extend(getbms())
3646 output.extend(getbms())
3647 elif default and not ui.quiet:
3647 elif default and not ui.quiet:
3648 # multiple bookmarks for a single parent separated by '/'
3648 # multiple bookmarks for a single parent separated by '/'
3649 bm = '/'.join(getbms())
3649 bm = '/'.join(getbms())
3650 if bm:
3650 if bm:
3651 output.append(bm)
3651 output.append(bm)
3652 else:
3652 else:
3653 if not rev:
3653 if not rev:
3654 ctx = repo[None]
3654 ctx = repo[None]
3655 parents = ctx.parents()
3655 parents = ctx.parents()
3656 changed = ""
3656 changed = ""
3657 if default or id or num:
3657 if default or id or num:
3658 if (util.any(repo.status())
3658 if (util.any(repo.status())
3659 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3659 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3660 changed = '+'
3660 changed = '+'
3661 if default or id:
3661 if default or id:
3662 output = ["%s%s" %
3662 output = ["%s%s" %
3663 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3663 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3664 if num:
3664 if num:
3665 output.append("%s%s" %
3665 output.append("%s%s" %
3666 ('+'.join([str(p.rev()) for p in parents]), changed))
3666 ('+'.join([str(p.rev()) for p in parents]), changed))
3667 else:
3667 else:
3668 ctx = scmutil.revsingle(repo, rev)
3668 ctx = scmutil.revsingle(repo, rev)
3669 if default or id:
3669 if default or id:
3670 output = [hexfunc(ctx.node())]
3670 output = [hexfunc(ctx.node())]
3671 if num:
3671 if num:
3672 output.append(str(ctx.rev()))
3672 output.append(str(ctx.rev()))
3673
3673
3674 if default and not ui.quiet:
3674 if default and not ui.quiet:
3675 b = ctx.branch()
3675 b = ctx.branch()
3676 if b != 'default':
3676 if b != 'default':
3677 output.append("(%s)" % b)
3677 output.append("(%s)" % b)
3678
3678
3679 # multiple tags for a single parent separated by '/'
3679 # multiple tags for a single parent separated by '/'
3680 t = '/'.join(ctx.tags())
3680 t = '/'.join(ctx.tags())
3681 if t:
3681 if t:
3682 output.append(t)
3682 output.append(t)
3683
3683
3684 # multiple bookmarks for a single parent separated by '/'
3684 # multiple bookmarks for a single parent separated by '/'
3685 bm = '/'.join(ctx.bookmarks())
3685 bm = '/'.join(ctx.bookmarks())
3686 if bm:
3686 if bm:
3687 output.append(bm)
3687 output.append(bm)
3688 else:
3688 else:
3689 if branch:
3689 if branch:
3690 output.append(ctx.branch())
3690 output.append(ctx.branch())
3691
3691
3692 if tags:
3692 if tags:
3693 output.extend(ctx.tags())
3693 output.extend(ctx.tags())
3694
3694
3695 if bookmarks:
3695 if bookmarks:
3696 output.extend(ctx.bookmarks())
3696 output.extend(ctx.bookmarks())
3697
3697
3698 ui.write("%s\n" % ' '.join(output))
3698 ui.write("%s\n" % ' '.join(output))
3699
3699
3700 @command('import|patch',
3700 @command('import|patch',
3701 [('p', 'strip', 1,
3701 [('p', 'strip', 1,
3702 _('directory strip option for patch. This has the same '
3702 _('directory strip option for patch. This has the same '
3703 'meaning as the corresponding patch option'), _('NUM')),
3703 'meaning as the corresponding patch option'), _('NUM')),
3704 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3704 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3705 ('e', 'edit', False, _('invoke editor on commit messages')),
3705 ('e', 'edit', False, _('invoke editor on commit messages')),
3706 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3706 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3707 ('', 'no-commit', None,
3707 ('', 'no-commit', None,
3708 _("don't commit, just update the working directory")),
3708 _("don't commit, just update the working directory")),
3709 ('', 'bypass', None,
3709 ('', 'bypass', None,
3710 _("apply patch without touching the working directory")),
3710 _("apply patch without touching the working directory")),
3711 ('', 'exact', None,
3711 ('', 'exact', None,
3712 _('apply patch to the nodes from which it was generated')),
3712 _('apply patch to the nodes from which it was generated')),
3713 ('', 'import-branch', None,
3713 ('', 'import-branch', None,
3714 _('use any branch information in patch (implied by --exact)'))] +
3714 _('use any branch information in patch (implied by --exact)'))] +
3715 commitopts + commitopts2 + similarityopts,
3715 commitopts + commitopts2 + similarityopts,
3716 _('[OPTION]... PATCH...'))
3716 _('[OPTION]... PATCH...'))
3717 def import_(ui, repo, patch1=None, *patches, **opts):
3717 def import_(ui, repo, patch1=None, *patches, **opts):
3718 """import an ordered set of patches
3718 """import an ordered set of patches
3719
3719
3720 Import a list of patches and commit them individually (unless
3720 Import a list of patches and commit them individually (unless
3721 --no-commit is specified).
3721 --no-commit is specified).
3722
3722
3723 If there are outstanding changes in the working directory, import
3723 If there are outstanding changes in the working directory, import
3724 will abort unless given the -f/--force flag.
3724 will abort unless given the -f/--force flag.
3725
3725
3726 You can import a patch straight from a mail message. Even patches
3726 You can import a patch straight from a mail message. Even patches
3727 as attachments work (to use the body part, it must have type
3727 as attachments work (to use the body part, it must have type
3728 text/plain or text/x-patch). From and Subject headers of email
3728 text/plain or text/x-patch). From and Subject headers of email
3729 message are used as default committer and commit message. All
3729 message are used as default committer and commit message. All
3730 text/plain body parts before first diff are added to commit
3730 text/plain body parts before first diff are added to commit
3731 message.
3731 message.
3732
3732
3733 If the imported patch was generated by :hg:`export`, user and
3733 If the imported patch was generated by :hg:`export`, user and
3734 description from patch override values from message headers and
3734 description from patch override values from message headers and
3735 body. Values given on command line with -m/--message and -u/--user
3735 body. Values given on command line with -m/--message and -u/--user
3736 override these.
3736 override these.
3737
3737
3738 If --exact is specified, import will set the working directory to
3738 If --exact is specified, import will set the working directory to
3739 the parent of each patch before applying it, and will abort if the
3739 the parent of each patch before applying it, and will abort if the
3740 resulting changeset has a different ID than the one recorded in
3740 resulting changeset has a different ID than the one recorded in
3741 the patch. This may happen due to character set problems or other
3741 the patch. This may happen due to character set problems or other
3742 deficiencies in the text patch format.
3742 deficiencies in the text patch format.
3743
3743
3744 Use --bypass to apply and commit patches directly to the
3744 Use --bypass to apply and commit patches directly to the
3745 repository, not touching the working directory. Without --exact,
3745 repository, not touching the working directory. Without --exact,
3746 patches will be applied on top of the working directory parent
3746 patches will be applied on top of the working directory parent
3747 revision.
3747 revision.
3748
3748
3749 With -s/--similarity, hg will attempt to discover renames and
3749 With -s/--similarity, hg will attempt to discover renames and
3750 copies in the patch in the same way as :hg:`addremove`.
3750 copies in the patch in the same way as :hg:`addremove`.
3751
3751
3752 To read a patch from standard input, use "-" as the patch name. If
3752 To read a patch from standard input, use "-" as the patch name. If
3753 a URL is specified, the patch will be downloaded from it.
3753 a URL is specified, the patch will be downloaded from it.
3754 See :hg:`help dates` for a list of formats valid for -d/--date.
3754 See :hg:`help dates` for a list of formats valid for -d/--date.
3755
3755
3756 .. container:: verbose
3756 .. container:: verbose
3757
3757
3758 Examples:
3758 Examples:
3759
3759
3760 - import a traditional patch from a website and detect renames::
3760 - import a traditional patch from a website and detect renames::
3761
3761
3762 hg import -s 80 http://example.com/bugfix.patch
3762 hg import -s 80 http://example.com/bugfix.patch
3763
3763
3764 - import a changeset from an hgweb server::
3764 - import a changeset from an hgweb server::
3765
3765
3766 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3766 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3767
3767
3768 - import all the patches in an Unix-style mbox::
3768 - import all the patches in an Unix-style mbox::
3769
3769
3770 hg import incoming-patches.mbox
3770 hg import incoming-patches.mbox
3771
3771
3772 - attempt to exactly restore an exported changeset (not always
3772 - attempt to exactly restore an exported changeset (not always
3773 possible)::
3773 possible)::
3774
3774
3775 hg import --exact proposed-fix.patch
3775 hg import --exact proposed-fix.patch
3776
3776
3777 Returns 0 on success.
3777 Returns 0 on success.
3778 """
3778 """
3779
3779
3780 if not patch1:
3780 if not patch1:
3781 raise util.Abort(_('need at least one patch to import'))
3781 raise util.Abort(_('need at least one patch to import'))
3782
3782
3783 patches = (patch1,) + patches
3783 patches = (patch1,) + patches
3784
3784
3785 date = opts.get('date')
3785 date = opts.get('date')
3786 if date:
3786 if date:
3787 opts['date'] = util.parsedate(date)
3787 opts['date'] = util.parsedate(date)
3788
3788
3789 editor = cmdutil.commiteditor
3789 editor = cmdutil.commiteditor
3790 if opts.get('edit'):
3790 if opts.get('edit'):
3791 editor = cmdutil.commitforceeditor
3791 editor = cmdutil.commitforceeditor
3792
3792
3793 update = not opts.get('bypass')
3793 update = not opts.get('bypass')
3794 if not update and opts.get('no_commit'):
3794 if not update and opts.get('no_commit'):
3795 raise util.Abort(_('cannot use --no-commit with --bypass'))
3795 raise util.Abort(_('cannot use --no-commit with --bypass'))
3796 try:
3796 try:
3797 sim = float(opts.get('similarity') or 0)
3797 sim = float(opts.get('similarity') or 0)
3798 except ValueError:
3798 except ValueError:
3799 raise util.Abort(_('similarity must be a number'))
3799 raise util.Abort(_('similarity must be a number'))
3800 if sim < 0 or sim > 100:
3800 if sim < 0 or sim > 100:
3801 raise util.Abort(_('similarity must be between 0 and 100'))
3801 raise util.Abort(_('similarity must be between 0 and 100'))
3802 if sim and not update:
3802 if sim and not update:
3803 raise util.Abort(_('cannot use --similarity with --bypass'))
3803 raise util.Abort(_('cannot use --similarity with --bypass'))
3804
3804
3805 if (opts.get('exact') or not opts.get('force')) and update:
3805 if (opts.get('exact') or not opts.get('force')) and update:
3806 cmdutil.bailifchanged(repo)
3806 cmdutil.bailifchanged(repo)
3807
3807
3808 base = opts["base"]
3808 base = opts["base"]
3809 strip = opts["strip"]
3809 strip = opts["strip"]
3810 wlock = lock = tr = None
3810 wlock = lock = tr = None
3811 msgs = []
3811 msgs = []
3812
3812
3813 def checkexact(repo, n, nodeid):
3813 def checkexact(repo, n, nodeid):
3814 if opts.get('exact') and hex(n) != nodeid:
3814 if opts.get('exact') and hex(n) != nodeid:
3815 repo.rollback()
3815 repo.rollback()
3816 raise util.Abort(_('patch is damaged or loses information'))
3816 raise util.Abort(_('patch is damaged or loses information'))
3817
3817
3818 def tryone(ui, hunk, parents):
3818 def tryone(ui, hunk, parents):
3819 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3819 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3820 patch.extract(ui, hunk)
3820 patch.extract(ui, hunk)
3821
3821
3822 if not tmpname:
3822 if not tmpname:
3823 return (None, None)
3823 return (None, None)
3824 msg = _('applied to working directory')
3824 msg = _('applied to working directory')
3825
3825
3826 try:
3826 try:
3827 cmdline_message = cmdutil.logmessage(ui, opts)
3827 cmdline_message = cmdutil.logmessage(ui, opts)
3828 if cmdline_message:
3828 if cmdline_message:
3829 # pickup the cmdline msg
3829 # pickup the cmdline msg
3830 message = cmdline_message
3830 message = cmdline_message
3831 elif message:
3831 elif message:
3832 # pickup the patch msg
3832 # pickup the patch msg
3833 message = message.strip()
3833 message = message.strip()
3834 else:
3834 else:
3835 # launch the editor
3835 # launch the editor
3836 message = None
3836 message = None
3837 ui.debug('message:\n%s\n' % message)
3837 ui.debug('message:\n%s\n' % message)
3838
3838
3839 if len(parents) == 1:
3839 if len(parents) == 1:
3840 parents.append(repo[nullid])
3840 parents.append(repo[nullid])
3841 if opts.get('exact'):
3841 if opts.get('exact'):
3842 if not nodeid or not p1:
3842 if not nodeid or not p1:
3843 raise util.Abort(_('not a Mercurial patch'))
3843 raise util.Abort(_('not a Mercurial patch'))
3844 p1 = repo[p1]
3844 p1 = repo[p1]
3845 p2 = repo[p2 or nullid]
3845 p2 = repo[p2 or nullid]
3846 elif p2:
3846 elif p2:
3847 try:
3847 try:
3848 p1 = repo[p1]
3848 p1 = repo[p1]
3849 p2 = repo[p2]
3849 p2 = repo[p2]
3850 # Without any options, consider p2 only if the
3850 # Without any options, consider p2 only if the
3851 # patch is being applied on top of the recorded
3851 # patch is being applied on top of the recorded
3852 # first parent.
3852 # first parent.
3853 if p1 != parents[0]:
3853 if p1 != parents[0]:
3854 p1 = parents[0]
3854 p1 = parents[0]
3855 p2 = repo[nullid]
3855 p2 = repo[nullid]
3856 except error.RepoError:
3856 except error.RepoError:
3857 p1, p2 = parents
3857 p1, p2 = parents
3858 else:
3858 else:
3859 p1, p2 = parents
3859 p1, p2 = parents
3860
3860
3861 n = None
3861 n = None
3862 if update:
3862 if update:
3863 if p1 != parents[0]:
3863 if p1 != parents[0]:
3864 hg.clean(repo, p1.node())
3864 hg.clean(repo, p1.node())
3865 if p2 != parents[1]:
3865 if p2 != parents[1]:
3866 repo.setparents(p1.node(), p2.node())
3866 repo.setparents(p1.node(), p2.node())
3867
3867
3868 if opts.get('exact') or opts.get('import_branch'):
3868 if opts.get('exact') or opts.get('import_branch'):
3869 repo.dirstate.setbranch(branch or 'default')
3869 repo.dirstate.setbranch(branch or 'default')
3870
3870
3871 files = set()
3871 files = set()
3872 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3872 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3873 eolmode=None, similarity=sim / 100.0)
3873 eolmode=None, similarity=sim / 100.0)
3874 files = list(files)
3874 files = list(files)
3875 if opts.get('no_commit'):
3875 if opts.get('no_commit'):
3876 if message:
3876 if message:
3877 msgs.append(message)
3877 msgs.append(message)
3878 else:
3878 else:
3879 if opts.get('exact') or p2:
3879 if opts.get('exact') or p2:
3880 # If you got here, you either use --force and know what
3880 # If you got here, you either use --force and know what
3881 # you are doing or used --exact or a merge patch while
3881 # you are doing or used --exact or a merge patch while
3882 # being updated to its first parent.
3882 # being updated to its first parent.
3883 m = None
3883 m = None
3884 else:
3884 else:
3885 m = scmutil.matchfiles(repo, files or [])
3885 m = scmutil.matchfiles(repo, files or [])
3886 n = repo.commit(message, opts.get('user') or user,
3886 n = repo.commit(message, opts.get('user') or user,
3887 opts.get('date') or date, match=m,
3887 opts.get('date') or date, match=m,
3888 editor=editor)
3888 editor=editor)
3889 checkexact(repo, n, nodeid)
3889 checkexact(repo, n, nodeid)
3890 else:
3890 else:
3891 if opts.get('exact') or opts.get('import_branch'):
3891 if opts.get('exact') or opts.get('import_branch'):
3892 branch = branch or 'default'
3892 branch = branch or 'default'
3893 else:
3893 else:
3894 branch = p1.branch()
3894 branch = p1.branch()
3895 store = patch.filestore()
3895 store = patch.filestore()
3896 try:
3896 try:
3897 files = set()
3897 files = set()
3898 try:
3898 try:
3899 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3899 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3900 files, eolmode=None)
3900 files, eolmode=None)
3901 except patch.PatchError, e:
3901 except patch.PatchError, e:
3902 raise util.Abort(str(e))
3902 raise util.Abort(str(e))
3903 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3903 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3904 message,
3904 message,
3905 opts.get('user') or user,
3905 opts.get('user') or user,
3906 opts.get('date') or date,
3906 opts.get('date') or date,
3907 branch, files, store,
3907 branch, files, store,
3908 editor=cmdutil.commiteditor)
3908 editor=cmdutil.commiteditor)
3909 repo.savecommitmessage(memctx.description())
3909 repo.savecommitmessage(memctx.description())
3910 n = memctx.commit()
3910 n = memctx.commit()
3911 checkexact(repo, n, nodeid)
3911 checkexact(repo, n, nodeid)
3912 finally:
3912 finally:
3913 store.close()
3913 store.close()
3914 if n:
3914 if n:
3915 # i18n: refers to a short changeset id
3915 # i18n: refers to a short changeset id
3916 msg = _('created %s') % short(n)
3916 msg = _('created %s') % short(n)
3917 return (msg, n)
3917 return (msg, n)
3918 finally:
3918 finally:
3919 os.unlink(tmpname)
3919 os.unlink(tmpname)
3920
3920
3921 try:
3921 try:
3922 try:
3922 try:
3923 wlock = repo.wlock()
3923 wlock = repo.wlock()
3924 if not opts.get('no_commit'):
3924 if not opts.get('no_commit'):
3925 lock = repo.lock()
3925 lock = repo.lock()
3926 tr = repo.transaction('import')
3926 tr = repo.transaction('import')
3927 parents = repo.parents()
3927 parents = repo.parents()
3928 for patchurl in patches:
3928 for patchurl in patches:
3929 if patchurl == '-':
3929 if patchurl == '-':
3930 ui.status(_('applying patch from stdin\n'))
3930 ui.status(_('applying patch from stdin\n'))
3931 patchfile = ui.fin
3931 patchfile = ui.fin
3932 patchurl = 'stdin' # for error message
3932 patchurl = 'stdin' # for error message
3933 else:
3933 else:
3934 patchurl = os.path.join(base, patchurl)
3934 patchurl = os.path.join(base, patchurl)
3935 ui.status(_('applying %s\n') % patchurl)
3935 ui.status(_('applying %s\n') % patchurl)
3936 patchfile = hg.openpath(ui, patchurl)
3936 patchfile = hg.openpath(ui, patchurl)
3937
3937
3938 haspatch = False
3938 haspatch = False
3939 for hunk in patch.split(patchfile):
3939 for hunk in patch.split(patchfile):
3940 (msg, node) = tryone(ui, hunk, parents)
3940 (msg, node) = tryone(ui, hunk, parents)
3941 if msg:
3941 if msg:
3942 haspatch = True
3942 haspatch = True
3943 ui.note(msg + '\n')
3943 ui.note(msg + '\n')
3944 if update or opts.get('exact'):
3944 if update or opts.get('exact'):
3945 parents = repo.parents()
3945 parents = repo.parents()
3946 else:
3946 else:
3947 parents = [repo[node]]
3947 parents = [repo[node]]
3948
3948
3949 if not haspatch:
3949 if not haspatch:
3950 raise util.Abort(_('%s: no diffs found') % patchurl)
3950 raise util.Abort(_('%s: no diffs found') % patchurl)
3951
3951
3952 if tr:
3952 if tr:
3953 tr.close()
3953 tr.close()
3954 if msgs:
3954 if msgs:
3955 repo.savecommitmessage('\n* * *\n'.join(msgs))
3955 repo.savecommitmessage('\n* * *\n'.join(msgs))
3956 except: # re-raises
3956 except: # re-raises
3957 # wlock.release() indirectly calls dirstate.write(): since
3957 # wlock.release() indirectly calls dirstate.write(): since
3958 # we're crashing, we do not want to change the working dir
3958 # we're crashing, we do not want to change the working dir
3959 # parent after all, so make sure it writes nothing
3959 # parent after all, so make sure it writes nothing
3960 repo.dirstate.invalidate()
3960 repo.dirstate.invalidate()
3961 raise
3961 raise
3962 finally:
3962 finally:
3963 if tr:
3963 if tr:
3964 tr.release()
3964 tr.release()
3965 release(lock, wlock)
3965 release(lock, wlock)
3966
3966
3967 @command('incoming|in',
3967 @command('incoming|in',
3968 [('f', 'force', None,
3968 [('f', 'force', None,
3969 _('run even if remote repository is unrelated')),
3969 _('run even if remote repository is unrelated')),
3970 ('n', 'newest-first', None, _('show newest record first')),
3970 ('n', 'newest-first', None, _('show newest record first')),
3971 ('', 'bundle', '',
3971 ('', 'bundle', '',
3972 _('file to store the bundles into'), _('FILE')),
3972 _('file to store the bundles into'), _('FILE')),
3973 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3973 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3974 ('B', 'bookmarks', False, _("compare bookmarks")),
3974 ('B', 'bookmarks', False, _("compare bookmarks")),
3975 ('b', 'branch', [],
3975 ('b', 'branch', [],
3976 _('a specific branch you would like to pull'), _('BRANCH')),
3976 _('a specific branch you would like to pull'), _('BRANCH')),
3977 ] + logopts + remoteopts + subrepoopts,
3977 ] + logopts + remoteopts + subrepoopts,
3978 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3978 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3979 def incoming(ui, repo, source="default", **opts):
3979 def incoming(ui, repo, source="default", **opts):
3980 """show new changesets found in source
3980 """show new changesets found in source
3981
3981
3982 Show new changesets found in the specified path/URL or the default
3982 Show new changesets found in the specified path/URL or the default
3983 pull location. These are the changesets that would have been pulled
3983 pull location. These are the changesets that would have been pulled
3984 if a pull at the time you issued this command.
3984 if a pull at the time you issued this command.
3985
3985
3986 For remote repository, using --bundle avoids downloading the
3986 For remote repository, using --bundle avoids downloading the
3987 changesets twice if the incoming is followed by a pull.
3987 changesets twice if the incoming is followed by a pull.
3988
3988
3989 See pull for valid source format details.
3989 See pull for valid source format details.
3990
3990
3991 Returns 0 if there are incoming changes, 1 otherwise.
3991 Returns 0 if there are incoming changes, 1 otherwise.
3992 """
3992 """
3993 if opts.get('graph'):
3993 if opts.get('graph'):
3994 cmdutil.checkunsupportedgraphflags([], opts)
3994 cmdutil.checkunsupportedgraphflags([], opts)
3995 def display(other, chlist, displayer):
3995 def display(other, chlist, displayer):
3996 revdag = cmdutil.graphrevs(other, chlist, opts)
3996 revdag = cmdutil.graphrevs(other, chlist, opts)
3997 showparents = [ctx.node() for ctx in repo[None].parents()]
3997 showparents = [ctx.node() for ctx in repo[None].parents()]
3998 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3998 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3999 graphmod.asciiedges)
3999 graphmod.asciiedges)
4000
4000
4001 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4001 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4002 return 0
4002 return 0
4003
4003
4004 if opts.get('bundle') and opts.get('subrepos'):
4004 if opts.get('bundle') and opts.get('subrepos'):
4005 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4005 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4006
4006
4007 if opts.get('bookmarks'):
4007 if opts.get('bookmarks'):
4008 source, branches = hg.parseurl(ui.expandpath(source),
4008 source, branches = hg.parseurl(ui.expandpath(source),
4009 opts.get('branch'))
4009 opts.get('branch'))
4010 other = hg.peer(repo, opts, source)
4010 other = hg.peer(repo, opts, source)
4011 if 'bookmarks' not in other.listkeys('namespaces'):
4011 if 'bookmarks' not in other.listkeys('namespaces'):
4012 ui.warn(_("remote doesn't support bookmarks\n"))
4012 ui.warn(_("remote doesn't support bookmarks\n"))
4013 return 0
4013 return 0
4014 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4014 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4015 return bookmarks.diff(ui, repo, other)
4015 return bookmarks.diff(ui, repo, other)
4016
4016
4017 repo._subtoppath = ui.expandpath(source)
4017 repo._subtoppath = ui.expandpath(source)
4018 try:
4018 try:
4019 return hg.incoming(ui, repo, source, opts)
4019 return hg.incoming(ui, repo, source, opts)
4020 finally:
4020 finally:
4021 del repo._subtoppath
4021 del repo._subtoppath
4022
4022
4023
4023
4024 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
4024 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
4025 def init(ui, dest=".", **opts):
4025 def init(ui, dest=".", **opts):
4026 """create a new repository in the given directory
4026 """create a new repository in the given directory
4027
4027
4028 Initialize a new repository in the given directory. If the given
4028 Initialize a new repository in the given directory. If the given
4029 directory does not exist, it will be created.
4029 directory does not exist, it will be created.
4030
4030
4031 If no directory is given, the current directory is used.
4031 If no directory is given, the current directory is used.
4032
4032
4033 It is possible to specify an ``ssh://`` URL as the destination.
4033 It is possible to specify an ``ssh://`` URL as the destination.
4034 See :hg:`help urls` for more information.
4034 See :hg:`help urls` for more information.
4035
4035
4036 Returns 0 on success.
4036 Returns 0 on success.
4037 """
4037 """
4038 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4038 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4039
4039
4040 @command('locate',
4040 @command('locate',
4041 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4041 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4042 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4042 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4043 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4043 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4044 ] + walkopts,
4044 ] + walkopts,
4045 _('[OPTION]... [PATTERN]...'))
4045 _('[OPTION]... [PATTERN]...'))
4046 def locate(ui, repo, *pats, **opts):
4046 def locate(ui, repo, *pats, **opts):
4047 """locate files matching specific patterns
4047 """locate files matching specific patterns
4048
4048
4049 Print files under Mercurial control in the working directory whose
4049 Print files under Mercurial control in the working directory whose
4050 names match the given patterns.
4050 names match the given patterns.
4051
4051
4052 By default, this command searches all directories in the working
4052 By default, this command searches all directories in the working
4053 directory. To search just the current directory and its
4053 directory. To search just the current directory and its
4054 subdirectories, use "--include .".
4054 subdirectories, use "--include .".
4055
4055
4056 If no patterns are given to match, this command prints the names
4056 If no patterns are given to match, this command prints the names
4057 of all files under Mercurial control in the working directory.
4057 of all files under Mercurial control in the working directory.
4058
4058
4059 If you want to feed the output of this command into the "xargs"
4059 If you want to feed the output of this command into the "xargs"
4060 command, use the -0 option to both this command and "xargs". This
4060 command, use the -0 option to both this command and "xargs". This
4061 will avoid the problem of "xargs" treating single filenames that
4061 will avoid the problem of "xargs" treating single filenames that
4062 contain whitespace as multiple filenames.
4062 contain whitespace as multiple filenames.
4063
4063
4064 Returns 0 if a match is found, 1 otherwise.
4064 Returns 0 if a match is found, 1 otherwise.
4065 """
4065 """
4066 end = opts.get('print0') and '\0' or '\n'
4066 end = opts.get('print0') and '\0' or '\n'
4067 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4067 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4068
4068
4069 ret = 1
4069 ret = 1
4070 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4070 m = scmutil.match(repo[rev], pats, opts, default='relglob')
4071 m.bad = lambda x, y: False
4071 m.bad = lambda x, y: False
4072 for abs in repo[rev].walk(m):
4072 for abs in repo[rev].walk(m):
4073 if not rev and abs not in repo.dirstate:
4073 if not rev and abs not in repo.dirstate:
4074 continue
4074 continue
4075 if opts.get('fullpath'):
4075 if opts.get('fullpath'):
4076 ui.write(repo.wjoin(abs), end)
4076 ui.write(repo.wjoin(abs), end)
4077 else:
4077 else:
4078 ui.write(((pats and m.rel(abs)) or abs), end)
4078 ui.write(((pats and m.rel(abs)) or abs), end)
4079 ret = 0
4079 ret = 0
4080
4080
4081 return ret
4081 return ret
4082
4082
4083 @command('^log|history',
4083 @command('^log|history',
4084 [('f', 'follow', None,
4084 [('f', 'follow', None,
4085 _('follow changeset history, or file history across copies and renames')),
4085 _('follow changeset history, or file history across copies and renames')),
4086 ('', 'follow-first', None,
4086 ('', 'follow-first', None,
4087 _('only follow the first parent of merge changesets (DEPRECATED)')),
4087 _('only follow the first parent of merge changesets (DEPRECATED)')),
4088 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4088 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4089 ('C', 'copies', None, _('show copied files')),
4089 ('C', 'copies', None, _('show copied files')),
4090 ('k', 'keyword', [],
4090 ('k', 'keyword', [],
4091 _('do case-insensitive search for a given text'), _('TEXT')),
4091 _('do case-insensitive search for a given text'), _('TEXT')),
4092 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4092 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4093 ('', 'removed', None, _('include revisions where files were removed')),
4093 ('', 'removed', None, _('include revisions where files were removed')),
4094 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4094 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4095 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4095 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4096 ('', 'only-branch', [],
4096 ('', 'only-branch', [],
4097 _('show only changesets within the given named branch (DEPRECATED)'),
4097 _('show only changesets within the given named branch (DEPRECATED)'),
4098 _('BRANCH')),
4098 _('BRANCH')),
4099 ('b', 'branch', [],
4099 ('b', 'branch', [],
4100 _('show changesets within the given named branch'), _('BRANCH')),
4100 _('show changesets within the given named branch'), _('BRANCH')),
4101 ('P', 'prune', [],
4101 ('P', 'prune', [],
4102 _('do not display revision or any of its ancestors'), _('REV')),
4102 _('do not display revision or any of its ancestors'), _('REV')),
4103 ] + logopts + walkopts,
4103 ] + logopts + walkopts,
4104 _('[OPTION]... [FILE]'))
4104 _('[OPTION]... [FILE]'))
4105 def log(ui, repo, *pats, **opts):
4105 def log(ui, repo, *pats, **opts):
4106 """show revision history of entire repository or files
4106 """show revision history of entire repository or files
4107
4107
4108 Print the revision history of the specified files or the entire
4108 Print the revision history of the specified files or the entire
4109 project.
4109 project.
4110
4110
4111 If no revision range is specified, the default is ``tip:0`` unless
4111 If no revision range is specified, the default is ``tip:0`` unless
4112 --follow is set, in which case the working directory parent is
4112 --follow is set, in which case the working directory parent is
4113 used as the starting revision.
4113 used as the starting revision.
4114
4114
4115 File history is shown without following rename or copy history of
4115 File history is shown without following rename or copy history of
4116 files. Use -f/--follow with a filename to follow history across
4116 files. Use -f/--follow with a filename to follow history across
4117 renames and copies. --follow without a filename will only show
4117 renames and copies. --follow without a filename will only show
4118 ancestors or descendants of the starting revision.
4118 ancestors or descendants of the starting revision.
4119
4119
4120 By default this command prints revision number and changeset id,
4120 By default this command prints revision number and changeset id,
4121 tags, non-trivial parents, user, date and time, and a summary for
4121 tags, non-trivial parents, user, date and time, and a summary for
4122 each commit. When the -v/--verbose switch is used, the list of
4122 each commit. When the -v/--verbose switch is used, the list of
4123 changed files and full commit message are shown.
4123 changed files and full commit message are shown.
4124
4124
4125 .. note::
4125 .. note::
4126 log -p/--patch may generate unexpected diff output for merge
4126 log -p/--patch may generate unexpected diff output for merge
4127 changesets, as it will only compare the merge changeset against
4127 changesets, as it will only compare the merge changeset against
4128 its first parent. Also, only files different from BOTH parents
4128 its first parent. Also, only files different from BOTH parents
4129 will appear in files:.
4129 will appear in files:.
4130
4130
4131 .. note::
4131 .. note::
4132 for performance reasons, log FILE may omit duplicate changes
4132 for performance reasons, log FILE may omit duplicate changes
4133 made on branches and will not show deletions. To see all
4133 made on branches and will not show deletions. To see all
4134 changes including duplicates and deletions, use the --removed
4134 changes including duplicates and deletions, use the --removed
4135 switch.
4135 switch.
4136
4136
4137 .. container:: verbose
4137 .. container:: verbose
4138
4138
4139 Some examples:
4139 Some examples:
4140
4140
4141 - changesets with full descriptions and file lists::
4141 - changesets with full descriptions and file lists::
4142
4142
4143 hg log -v
4143 hg log -v
4144
4144
4145 - changesets ancestral to the working directory::
4145 - changesets ancestral to the working directory::
4146
4146
4147 hg log -f
4147 hg log -f
4148
4148
4149 - last 10 commits on the current branch::
4149 - last 10 commits on the current branch::
4150
4150
4151 hg log -l 10 -b .
4151 hg log -l 10 -b .
4152
4152
4153 - changesets showing all modifications of a file, including removals::
4153 - changesets showing all modifications of a file, including removals::
4154
4154
4155 hg log --removed file.c
4155 hg log --removed file.c
4156
4156
4157 - all changesets that touch a directory, with diffs, excluding merges::
4157 - all changesets that touch a directory, with diffs, excluding merges::
4158
4158
4159 hg log -Mp lib/
4159 hg log -Mp lib/
4160
4160
4161 - all revision numbers that match a keyword::
4161 - all revision numbers that match a keyword::
4162
4162
4163 hg log -k bug --template "{rev}\\n"
4163 hg log -k bug --template "{rev}\\n"
4164
4164
4165 - check if a given changeset is included is a tagged release::
4165 - check if a given changeset is included is a tagged release::
4166
4166
4167 hg log -r "a21ccf and ancestor(1.9)"
4167 hg log -r "a21ccf and ancestor(1.9)"
4168
4168
4169 - find all changesets by some user in a date range::
4169 - find all changesets by some user in a date range::
4170
4170
4171 hg log -k alice -d "may 2008 to jul 2008"
4171 hg log -k alice -d "may 2008 to jul 2008"
4172
4172
4173 - summary of all changesets after the last tag::
4173 - summary of all changesets after the last tag::
4174
4174
4175 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4175 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4176
4176
4177 See :hg:`help dates` for a list of formats valid for -d/--date.
4177 See :hg:`help dates` for a list of formats valid for -d/--date.
4178
4178
4179 See :hg:`help revisions` and :hg:`help revsets` for more about
4179 See :hg:`help revisions` and :hg:`help revsets` for more about
4180 specifying revisions.
4180 specifying revisions.
4181
4181
4182 See :hg:`help templates` for more about pre-packaged styles and
4182 See :hg:`help templates` for more about pre-packaged styles and
4183 specifying custom templates.
4183 specifying custom templates.
4184
4184
4185 Returns 0 on success.
4185 Returns 0 on success.
4186 """
4186 """
4187 if opts.get('graph'):
4187 if opts.get('graph'):
4188 return cmdutil.graphlog(ui, repo, *pats, **opts)
4188 return cmdutil.graphlog(ui, repo, *pats, **opts)
4189
4189
4190 matchfn = scmutil.match(repo[None], pats, opts)
4190 matchfn = scmutil.match(repo[None], pats, opts)
4191 limit = cmdutil.loglimit(opts)
4191 limit = cmdutil.loglimit(opts)
4192 count = 0
4192 count = 0
4193
4193
4194 getrenamed, endrev = None, None
4194 getrenamed, endrev = None, None
4195 if opts.get('copies'):
4195 if opts.get('copies'):
4196 if opts.get('rev'):
4196 if opts.get('rev'):
4197 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4197 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4198 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4198 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4199
4199
4200 df = False
4200 df = False
4201 if opts.get("date"):
4201 if opts.get("date"):
4202 df = util.matchdate(opts["date"])
4202 df = util.matchdate(opts["date"])
4203
4203
4204 branches = opts.get('branch', []) + opts.get('only_branch', [])
4204 branches = opts.get('branch', []) + opts.get('only_branch', [])
4205 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4205 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4206
4206
4207 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4207 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4208 def prep(ctx, fns):
4208 def prep(ctx, fns):
4209 rev = ctx.rev()
4209 rev = ctx.rev()
4210 parents = [p for p in repo.changelog.parentrevs(rev)
4210 parents = [p for p in repo.changelog.parentrevs(rev)
4211 if p != nullrev]
4211 if p != nullrev]
4212 if opts.get('no_merges') and len(parents) == 2:
4212 if opts.get('no_merges') and len(parents) == 2:
4213 return
4213 return
4214 if opts.get('only_merges') and len(parents) != 2:
4214 if opts.get('only_merges') and len(parents) != 2:
4215 return
4215 return
4216 if opts.get('branch') and ctx.branch() not in opts['branch']:
4216 if opts.get('branch') and ctx.branch() not in opts['branch']:
4217 return
4217 return
4218 if df and not df(ctx.date()[0]):
4218 if df and not df(ctx.date()[0]):
4219 return
4219 return
4220
4220
4221 lower = encoding.lower
4221 lower = encoding.lower
4222 if opts.get('user'):
4222 if opts.get('user'):
4223 luser = lower(ctx.user())
4223 luser = lower(ctx.user())
4224 for k in [lower(x) for x in opts['user']]:
4224 for k in [lower(x) for x in opts['user']]:
4225 if (k in luser):
4225 if (k in luser):
4226 break
4226 break
4227 else:
4227 else:
4228 return
4228 return
4229 if opts.get('keyword'):
4229 if opts.get('keyword'):
4230 luser = lower(ctx.user())
4230 luser = lower(ctx.user())
4231 ldesc = lower(ctx.description())
4231 ldesc = lower(ctx.description())
4232 lfiles = lower(" ".join(ctx.files()))
4232 lfiles = lower(" ".join(ctx.files()))
4233 for k in [lower(x) for x in opts['keyword']]:
4233 for k in [lower(x) for x in opts['keyword']]:
4234 if (k in luser or k in ldesc or k in lfiles):
4234 if (k in luser or k in ldesc or k in lfiles):
4235 break
4235 break
4236 else:
4236 else:
4237 return
4237 return
4238
4238
4239 copies = None
4239 copies = None
4240 if getrenamed is not None and rev:
4240 if getrenamed is not None and rev:
4241 copies = []
4241 copies = []
4242 for fn in ctx.files():
4242 for fn in ctx.files():
4243 rename = getrenamed(fn, rev)
4243 rename = getrenamed(fn, rev)
4244 if rename:
4244 if rename:
4245 copies.append((fn, rename[0]))
4245 copies.append((fn, rename[0]))
4246
4246
4247 revmatchfn = None
4247 revmatchfn = None
4248 if opts.get('patch') or opts.get('stat'):
4248 if opts.get('patch') or opts.get('stat'):
4249 if opts.get('follow') or opts.get('follow_first'):
4249 if opts.get('follow') or opts.get('follow_first'):
4250 # note: this might be wrong when following through merges
4250 # note: this might be wrong when following through merges
4251 revmatchfn = scmutil.match(repo[None], fns, default='path')
4251 revmatchfn = scmutil.match(repo[None], fns, default='path')
4252 else:
4252 else:
4253 revmatchfn = matchfn
4253 revmatchfn = matchfn
4254
4254
4255 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4255 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4256
4256
4257 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4257 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4258 if count == limit:
4258 if count == limit:
4259 break
4259 break
4260 if displayer.flush(ctx.rev()):
4260 if displayer.flush(ctx.rev()):
4261 count += 1
4261 count += 1
4262 displayer.close()
4262 displayer.close()
4263
4263
4264 @command('manifest',
4264 @command('manifest',
4265 [('r', 'rev', '', _('revision to display'), _('REV')),
4265 [('r', 'rev', '', _('revision to display'), _('REV')),
4266 ('', 'all', False, _("list files from all revisions"))],
4266 ('', 'all', False, _("list files from all revisions"))],
4267 _('[-r REV]'))
4267 _('[-r REV]'))
4268 def manifest(ui, repo, node=None, rev=None, **opts):
4268 def manifest(ui, repo, node=None, rev=None, **opts):
4269 """output the current or given revision of the project manifest
4269 """output the current or given revision of the project manifest
4270
4270
4271 Print a list of version controlled files for the given revision.
4271 Print a list of version controlled files for the given revision.
4272 If no revision is given, the first parent of the working directory
4272 If no revision is given, the first parent of the working directory
4273 is used, or the null revision if no revision is checked out.
4273 is used, or the null revision if no revision is checked out.
4274
4274
4275 With -v, print file permissions, symlink and executable bits.
4275 With -v, print file permissions, symlink and executable bits.
4276 With --debug, print file revision hashes.
4276 With --debug, print file revision hashes.
4277
4277
4278 If option --all is specified, the list of all files from all revisions
4278 If option --all is specified, the list of all files from all revisions
4279 is printed. This includes deleted and renamed files.
4279 is printed. This includes deleted and renamed files.
4280
4280
4281 Returns 0 on success.
4281 Returns 0 on success.
4282 """
4282 """
4283
4283
4284 fm = ui.formatter('manifest', opts)
4284 fm = ui.formatter('manifest', opts)
4285
4285
4286 if opts.get('all'):
4286 if opts.get('all'):
4287 if rev or node:
4287 if rev or node:
4288 raise util.Abort(_("can't specify a revision with --all"))
4288 raise util.Abort(_("can't specify a revision with --all"))
4289
4289
4290 res = []
4290 res = []
4291 prefix = "data/"
4291 prefix = "data/"
4292 suffix = ".i"
4292 suffix = ".i"
4293 plen = len(prefix)
4293 plen = len(prefix)
4294 slen = len(suffix)
4294 slen = len(suffix)
4295 lock = repo.lock()
4295 lock = repo.lock()
4296 try:
4296 try:
4297 for fn, b, size in repo.store.datafiles():
4297 for fn, b, size in repo.store.datafiles():
4298 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4298 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4299 res.append(fn[plen:-slen])
4299 res.append(fn[plen:-slen])
4300 finally:
4300 finally:
4301 lock.release()
4301 lock.release()
4302 for f in res:
4302 for f in res:
4303 fm.startitem()
4303 fm.startitem()
4304 fm.write("path", '%s\n', f)
4304 fm.write("path", '%s\n', f)
4305 fm.end()
4305 fm.end()
4306 return
4306 return
4307
4307
4308 if rev and node:
4308 if rev and node:
4309 raise util.Abort(_("please specify just one revision"))
4309 raise util.Abort(_("please specify just one revision"))
4310
4310
4311 if not node:
4311 if not node:
4312 node = rev
4312 node = rev
4313
4313
4314 char = {'l': '@', 'x': '*', '': ''}
4314 char = {'l': '@', 'x': '*', '': ''}
4315 mode = {'l': '644', 'x': '755', '': '644'}
4315 mode = {'l': '644', 'x': '755', '': '644'}
4316 ctx = scmutil.revsingle(repo, node)
4316 ctx = scmutil.revsingle(repo, node)
4317 mf = ctx.manifest()
4317 mf = ctx.manifest()
4318 for f in ctx:
4318 for f in ctx:
4319 fm.startitem()
4319 fm.startitem()
4320 fl = ctx[f].flags()
4320 fl = ctx[f].flags()
4321 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4321 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4322 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4322 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4323 fm.write('path', '%s\n', f)
4323 fm.write('path', '%s\n', f)
4324 fm.end()
4324 fm.end()
4325
4325
4326 @command('^merge',
4326 @command('^merge',
4327 [('f', 'force', None, _('force a merge with outstanding changes')),
4327 [('f', 'force', None, _('force a merge with outstanding changes')),
4328 ('r', 'rev', '', _('revision to merge'), _('REV')),
4328 ('r', 'rev', '', _('revision to merge'), _('REV')),
4329 ('P', 'preview', None,
4329 ('P', 'preview', None,
4330 _('review revisions to merge (no merge is performed)'))
4330 _('review revisions to merge (no merge is performed)'))
4331 ] + mergetoolopts,
4331 ] + mergetoolopts,
4332 _('[-P] [-f] [[-r] REV]'))
4332 _('[-P] [-f] [[-r] REV]'))
4333 def merge(ui, repo, node=None, **opts):
4333 def merge(ui, repo, node=None, **opts):
4334 """merge working directory with another revision
4334 """merge working directory with another revision
4335
4335
4336 The current working directory is updated with all changes made in
4336 The current working directory is updated with all changes made in
4337 the requested revision since the last common predecessor revision.
4337 the requested revision since the last common predecessor revision.
4338
4338
4339 Files that changed between either parent are marked as changed for
4339 Files that changed between either parent are marked as changed for
4340 the next commit and a commit must be performed before any further
4340 the next commit and a commit must be performed before any further
4341 updates to the repository are allowed. The next commit will have
4341 updates to the repository are allowed. The next commit will have
4342 two parents.
4342 two parents.
4343
4343
4344 ``--tool`` can be used to specify the merge tool used for file
4344 ``--tool`` can be used to specify the merge tool used for file
4345 merges. It overrides the HGMERGE environment variable and your
4345 merges. It overrides the HGMERGE environment variable and your
4346 configuration files. See :hg:`help merge-tools` for options.
4346 configuration files. See :hg:`help merge-tools` for options.
4347
4347
4348 If no revision is specified, the working directory's parent is a
4348 If no revision is specified, the working directory's parent is a
4349 head revision, and the current branch contains exactly one other
4349 head revision, and the current branch contains exactly one other
4350 head, the other head is merged with by default. Otherwise, an
4350 head, the other head is merged with by default. Otherwise, an
4351 explicit revision with which to merge with must be provided.
4351 explicit revision with which to merge with must be provided.
4352
4352
4353 :hg:`resolve` must be used to resolve unresolved files.
4353 :hg:`resolve` must be used to resolve unresolved files.
4354
4354
4355 To undo an uncommitted merge, use :hg:`update --clean .` which
4355 To undo an uncommitted merge, use :hg:`update --clean .` which
4356 will check out a clean copy of the original merge parent, losing
4356 will check out a clean copy of the original merge parent, losing
4357 all changes.
4357 all changes.
4358
4358
4359 Returns 0 on success, 1 if there are unresolved files.
4359 Returns 0 on success, 1 if there are unresolved files.
4360 """
4360 """
4361
4361
4362 if opts.get('rev') and node:
4362 if opts.get('rev') and node:
4363 raise util.Abort(_("please specify just one revision"))
4363 raise util.Abort(_("please specify just one revision"))
4364 if not node:
4364 if not node:
4365 node = opts.get('rev')
4365 node = opts.get('rev')
4366
4366
4367 if node:
4367 if node:
4368 node = scmutil.revsingle(repo, node).node()
4368 node = scmutil.revsingle(repo, node).node()
4369
4369
4370 if not node and repo._bookmarkcurrent:
4370 if not node and repo._bookmarkcurrent:
4371 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4371 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4372 curhead = repo[repo._bookmarkcurrent].node()
4372 curhead = repo[repo._bookmarkcurrent].node()
4373 if len(bmheads) == 2:
4373 if len(bmheads) == 2:
4374 if curhead == bmheads[0]:
4374 if curhead == bmheads[0]:
4375 node = bmheads[1]
4375 node = bmheads[1]
4376 else:
4376 else:
4377 node = bmheads[0]
4377 node = bmheads[0]
4378 elif len(bmheads) > 2:
4378 elif len(bmheads) > 2:
4379 raise util.Abort(_("multiple matching bookmarks to merge - "
4379 raise util.Abort(_("multiple matching bookmarks to merge - "
4380 "please merge with an explicit rev or bookmark"),
4380 "please merge with an explicit rev or bookmark"),
4381 hint=_("run 'hg heads' to see all heads"))
4381 hint=_("run 'hg heads' to see all heads"))
4382 elif len(bmheads) <= 1:
4382 elif len(bmheads) <= 1:
4383 raise util.Abort(_("no matching bookmark to merge - "
4383 raise util.Abort(_("no matching bookmark to merge - "
4384 "please merge with an explicit rev or bookmark"),
4384 "please merge with an explicit rev or bookmark"),
4385 hint=_("run 'hg heads' to see all heads"))
4385 hint=_("run 'hg heads' to see all heads"))
4386
4386
4387 if not node and not repo._bookmarkcurrent:
4387 if not node and not repo._bookmarkcurrent:
4388 branch = repo[None].branch()
4388 branch = repo[None].branch()
4389 bheads = repo.branchheads(branch)
4389 bheads = repo.branchheads(branch)
4390 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4390 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4391
4391
4392 if len(nbhs) > 2:
4392 if len(nbhs) > 2:
4393 raise util.Abort(_("branch '%s' has %d heads - "
4393 raise util.Abort(_("branch '%s' has %d heads - "
4394 "please merge with an explicit rev")
4394 "please merge with an explicit rev")
4395 % (branch, len(bheads)),
4395 % (branch, len(bheads)),
4396 hint=_("run 'hg heads .' to see heads"))
4396 hint=_("run 'hg heads .' to see heads"))
4397
4397
4398 parent = repo.dirstate.p1()
4398 parent = repo.dirstate.p1()
4399 if len(nbhs) <= 1:
4399 if len(nbhs) <= 1:
4400 if len(bheads) > 1:
4400 if len(bheads) > 1:
4401 raise util.Abort(_("heads are bookmarked - "
4401 raise util.Abort(_("heads are bookmarked - "
4402 "please merge with an explicit rev"),
4402 "please merge with an explicit rev"),
4403 hint=_("run 'hg heads' to see all heads"))
4403 hint=_("run 'hg heads' to see all heads"))
4404 if len(repo.heads()) > 1:
4404 if len(repo.heads()) > 1:
4405 raise util.Abort(_("branch '%s' has one head - "
4405 raise util.Abort(_("branch '%s' has one head - "
4406 "please merge with an explicit rev")
4406 "please merge with an explicit rev")
4407 % branch,
4407 % branch,
4408 hint=_("run 'hg heads' to see all heads"))
4408 hint=_("run 'hg heads' to see all heads"))
4409 msg, hint = _('nothing to merge'), None
4409 msg, hint = _('nothing to merge'), None
4410 if parent != repo.lookup(branch):
4410 if parent != repo.lookup(branch):
4411 hint = _("use 'hg update' instead")
4411 hint = _("use 'hg update' instead")
4412 raise util.Abort(msg, hint=hint)
4412 raise util.Abort(msg, hint=hint)
4413
4413
4414 if parent not in bheads:
4414 if parent not in bheads:
4415 raise util.Abort(_('working directory not at a head revision'),
4415 raise util.Abort(_('working directory not at a head revision'),
4416 hint=_("use 'hg update' or merge with an "
4416 hint=_("use 'hg update' or merge with an "
4417 "explicit revision"))
4417 "explicit revision"))
4418 if parent == nbhs[0]:
4418 if parent == nbhs[0]:
4419 node = nbhs[-1]
4419 node = nbhs[-1]
4420 else:
4420 else:
4421 node = nbhs[0]
4421 node = nbhs[0]
4422
4422
4423 if opts.get('preview'):
4423 if opts.get('preview'):
4424 # find nodes that are ancestors of p2 but not of p1
4424 # find nodes that are ancestors of p2 but not of p1
4425 p1 = repo.lookup('.')
4425 p1 = repo.lookup('.')
4426 p2 = repo.lookup(node)
4426 p2 = repo.lookup(node)
4427 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4427 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4428
4428
4429 displayer = cmdutil.show_changeset(ui, repo, opts)
4429 displayer = cmdutil.show_changeset(ui, repo, opts)
4430 for node in nodes:
4430 for node in nodes:
4431 displayer.show(repo[node])
4431 displayer.show(repo[node])
4432 displayer.close()
4432 displayer.close()
4433 return 0
4433 return 0
4434
4434
4435 try:
4435 try:
4436 # ui.forcemerge is an internal variable, do not document
4436 # ui.forcemerge is an internal variable, do not document
4437 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4437 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4438 return hg.merge(repo, node, force=opts.get('force'))
4438 return hg.merge(repo, node, force=opts.get('force'))
4439 finally:
4439 finally:
4440 ui.setconfig('ui', 'forcemerge', '')
4440 ui.setconfig('ui', 'forcemerge', '')
4441
4441
4442 @command('outgoing|out',
4442 @command('outgoing|out',
4443 [('f', 'force', None, _('run even when the destination is unrelated')),
4443 [('f', 'force', None, _('run even when the destination is unrelated')),
4444 ('r', 'rev', [],
4444 ('r', 'rev', [],
4445 _('a changeset intended to be included in the destination'), _('REV')),
4445 _('a changeset intended to be included in the destination'), _('REV')),
4446 ('n', 'newest-first', None, _('show newest record first')),
4446 ('n', 'newest-first', None, _('show newest record first')),
4447 ('B', 'bookmarks', False, _('compare bookmarks')),
4447 ('B', 'bookmarks', False, _('compare bookmarks')),
4448 ('b', 'branch', [], _('a specific branch you would like to push'),
4448 ('b', 'branch', [], _('a specific branch you would like to push'),
4449 _('BRANCH')),
4449 _('BRANCH')),
4450 ] + logopts + remoteopts + subrepoopts,
4450 ] + logopts + remoteopts + subrepoopts,
4451 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4451 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4452 def outgoing(ui, repo, dest=None, **opts):
4452 def outgoing(ui, repo, dest=None, **opts):
4453 """show changesets not found in the destination
4453 """show changesets not found in the destination
4454
4454
4455 Show changesets not found in the specified destination repository
4455 Show changesets not found in the specified destination repository
4456 or the default push location. These are the changesets that would
4456 or the default push location. These are the changesets that would
4457 be pushed if a push was requested.
4457 be pushed if a push was requested.
4458
4458
4459 See pull for details of valid destination formats.
4459 See pull for details of valid destination formats.
4460
4460
4461 Returns 0 if there are outgoing changes, 1 otherwise.
4461 Returns 0 if there are outgoing changes, 1 otherwise.
4462 """
4462 """
4463 if opts.get('graph'):
4463 if opts.get('graph'):
4464 cmdutil.checkunsupportedgraphflags([], opts)
4464 cmdutil.checkunsupportedgraphflags([], opts)
4465 o = hg._outgoing(ui, repo, dest, opts)
4465 o = hg._outgoing(ui, repo, dest, opts)
4466 if o is None:
4466 if o is None:
4467 return
4467 return
4468
4468
4469 revdag = cmdutil.graphrevs(repo, o, opts)
4469 revdag = cmdutil.graphrevs(repo, o, opts)
4470 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4470 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4471 showparents = [ctx.node() for ctx in repo[None].parents()]
4471 showparents = [ctx.node() for ctx in repo[None].parents()]
4472 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4472 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4473 graphmod.asciiedges)
4473 graphmod.asciiedges)
4474 return 0
4474 return 0
4475
4475
4476 if opts.get('bookmarks'):
4476 if opts.get('bookmarks'):
4477 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4477 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4478 dest, branches = hg.parseurl(dest, opts.get('branch'))
4478 dest, branches = hg.parseurl(dest, opts.get('branch'))
4479 other = hg.peer(repo, opts, dest)
4479 other = hg.peer(repo, opts, dest)
4480 if 'bookmarks' not in other.listkeys('namespaces'):
4480 if 'bookmarks' not in other.listkeys('namespaces'):
4481 ui.warn(_("remote doesn't support bookmarks\n"))
4481 ui.warn(_("remote doesn't support bookmarks\n"))
4482 return 0
4482 return 0
4483 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4483 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4484 return bookmarks.diff(ui, other, repo)
4484 return bookmarks.diff(ui, other, repo)
4485
4485
4486 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4486 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4487 try:
4487 try:
4488 return hg.outgoing(ui, repo, dest, opts)
4488 return hg.outgoing(ui, repo, dest, opts)
4489 finally:
4489 finally:
4490 del repo._subtoppath
4490 del repo._subtoppath
4491
4491
4492 @command('parents',
4492 @command('parents',
4493 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4493 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4494 ] + templateopts,
4494 ] + templateopts,
4495 _('[-r REV] [FILE]'))
4495 _('[-r REV] [FILE]'))
4496 def parents(ui, repo, file_=None, **opts):
4496 def parents(ui, repo, file_=None, **opts):
4497 """show the parents of the working directory or revision
4497 """show the parents of the working directory or revision
4498
4498
4499 Print the working directory's parent revisions. If a revision is
4499 Print the working directory's parent revisions. If a revision is
4500 given via -r/--rev, the parent of that revision will be printed.
4500 given via -r/--rev, the parent of that revision will be printed.
4501 If a file argument is given, the revision in which the file was
4501 If a file argument is given, the revision in which the file was
4502 last changed (before the working directory revision or the
4502 last changed (before the working directory revision or the
4503 argument to --rev if given) is printed.
4503 argument to --rev if given) is printed.
4504
4504
4505 Returns 0 on success.
4505 Returns 0 on success.
4506 """
4506 """
4507
4507
4508 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4508 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4509
4509
4510 if file_:
4510 if file_:
4511 m = scmutil.match(ctx, (file_,), opts)
4511 m = scmutil.match(ctx, (file_,), opts)
4512 if m.anypats() or len(m.files()) != 1:
4512 if m.anypats() or len(m.files()) != 1:
4513 raise util.Abort(_('can only specify an explicit filename'))
4513 raise util.Abort(_('can only specify an explicit filename'))
4514 file_ = m.files()[0]
4514 file_ = m.files()[0]
4515 filenodes = []
4515 filenodes = []
4516 for cp in ctx.parents():
4516 for cp in ctx.parents():
4517 if not cp:
4517 if not cp:
4518 continue
4518 continue
4519 try:
4519 try:
4520 filenodes.append(cp.filenode(file_))
4520 filenodes.append(cp.filenode(file_))
4521 except error.LookupError:
4521 except error.LookupError:
4522 pass
4522 pass
4523 if not filenodes:
4523 if not filenodes:
4524 raise util.Abort(_("'%s' not found in manifest!") % file_)
4524 raise util.Abort(_("'%s' not found in manifest!") % file_)
4525 fl = repo.file(file_)
4525 fl = repo.file(file_)
4526 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4526 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4527 else:
4527 else:
4528 p = [cp.node() for cp in ctx.parents()]
4528 p = [cp.node() for cp in ctx.parents()]
4529
4529
4530 displayer = cmdutil.show_changeset(ui, repo, opts)
4530 displayer = cmdutil.show_changeset(ui, repo, opts)
4531 for n in p:
4531 for n in p:
4532 if n != nullid:
4532 if n != nullid:
4533 displayer.show(repo[n])
4533 displayer.show(repo[n])
4534 displayer.close()
4534 displayer.close()
4535
4535
4536 @command('paths', [], _('[NAME]'))
4536 @command('paths', [], _('[NAME]'))
4537 def paths(ui, repo, search=None):
4537 def paths(ui, repo, search=None):
4538 """show aliases for remote repositories
4538 """show aliases for remote repositories
4539
4539
4540 Show definition of symbolic path name NAME. If no name is given,
4540 Show definition of symbolic path name NAME. If no name is given,
4541 show definition of all available names.
4541 show definition of all available names.
4542
4542
4543 Option -q/--quiet suppresses all output when searching for NAME
4543 Option -q/--quiet suppresses all output when searching for NAME
4544 and shows only the path names when listing all definitions.
4544 and shows only the path names when listing all definitions.
4545
4545
4546 Path names are defined in the [paths] section of your
4546 Path names are defined in the [paths] section of your
4547 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4547 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4548 repository, ``.hg/hgrc`` is used, too.
4548 repository, ``.hg/hgrc`` is used, too.
4549
4549
4550 The path names ``default`` and ``default-push`` have a special
4550 The path names ``default`` and ``default-push`` have a special
4551 meaning. When performing a push or pull operation, they are used
4551 meaning. When performing a push or pull operation, they are used
4552 as fallbacks if no location is specified on the command-line.
4552 as fallbacks if no location is specified on the command-line.
4553 When ``default-push`` is set, it will be used for push and
4553 When ``default-push`` is set, it will be used for push and
4554 ``default`` will be used for pull; otherwise ``default`` is used
4554 ``default`` will be used for pull; otherwise ``default`` is used
4555 as the fallback for both. When cloning a repository, the clone
4555 as the fallback for both. When cloning a repository, the clone
4556 source is written as ``default`` in ``.hg/hgrc``. Note that
4556 source is written as ``default`` in ``.hg/hgrc``. Note that
4557 ``default`` and ``default-push`` apply to all inbound (e.g.
4557 ``default`` and ``default-push`` apply to all inbound (e.g.
4558 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4558 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4559 :hg:`bundle`) operations.
4559 :hg:`bundle`) operations.
4560
4560
4561 See :hg:`help urls` for more information.
4561 See :hg:`help urls` for more information.
4562
4562
4563 Returns 0 on success.
4563 Returns 0 on success.
4564 """
4564 """
4565 if search:
4565 if search:
4566 for name, path in ui.configitems("paths"):
4566 for name, path in ui.configitems("paths"):
4567 if name == search:
4567 if name == search:
4568 ui.status("%s\n" % util.hidepassword(path))
4568 ui.status("%s\n" % util.hidepassword(path))
4569 return
4569 return
4570 if not ui.quiet:
4570 if not ui.quiet:
4571 ui.warn(_("not found!\n"))
4571 ui.warn(_("not found!\n"))
4572 return 1
4572 return 1
4573 else:
4573 else:
4574 for name, path in ui.configitems("paths"):
4574 for name, path in ui.configitems("paths"):
4575 if ui.quiet:
4575 if ui.quiet:
4576 ui.write("%s\n" % name)
4576 ui.write("%s\n" % name)
4577 else:
4577 else:
4578 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4578 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4579
4579
4580 @command('phase',
4580 @command('phase',
4581 [('p', 'public', False, _('set changeset phase to public')),
4581 [('p', 'public', False, _('set changeset phase to public')),
4582 ('d', 'draft', False, _('set changeset phase to draft')),
4582 ('d', 'draft', False, _('set changeset phase to draft')),
4583 ('s', 'secret', False, _('set changeset phase to secret')),
4583 ('s', 'secret', False, _('set changeset phase to secret')),
4584 ('f', 'force', False, _('allow to move boundary backward')),
4584 ('f', 'force', False, _('allow to move boundary backward')),
4585 ('r', 'rev', [], _('target revision'), _('REV')),
4585 ('r', 'rev', [], _('target revision'), _('REV')),
4586 ],
4586 ],
4587 _('[-p|-d|-s] [-f] [-r] REV...'))
4587 _('[-p|-d|-s] [-f] [-r] REV...'))
4588 def phase(ui, repo, *revs, **opts):
4588 def phase(ui, repo, *revs, **opts):
4589 """set or show the current phase name
4589 """set or show the current phase name
4590
4590
4591 With no argument, show the phase name of specified revisions.
4591 With no argument, show the phase name of specified revisions.
4592
4592
4593 With one of -p/--public, -d/--draft or -s/--secret, change the
4593 With one of -p/--public, -d/--draft or -s/--secret, change the
4594 phase value of the specified revisions.
4594 phase value of the specified revisions.
4595
4595
4596 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4596 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4597 lower phase to an higher phase. Phases are ordered as follows::
4597 lower phase to an higher phase. Phases are ordered as follows::
4598
4598
4599 public < draft < secret
4599 public < draft < secret
4600
4600
4601 Return 0 on success, 1 if no phases were changed or some could not
4601 Return 0 on success, 1 if no phases were changed or some could not
4602 be changed.
4602 be changed.
4603 """
4603 """
4604 # search for a unique phase argument
4604 # search for a unique phase argument
4605 targetphase = None
4605 targetphase = None
4606 for idx, name in enumerate(phases.phasenames):
4606 for idx, name in enumerate(phases.phasenames):
4607 if opts[name]:
4607 if opts[name]:
4608 if targetphase is not None:
4608 if targetphase is not None:
4609 raise util.Abort(_('only one phase can be specified'))
4609 raise util.Abort(_('only one phase can be specified'))
4610 targetphase = idx
4610 targetphase = idx
4611
4611
4612 # look for specified revision
4612 # look for specified revision
4613 revs = list(revs)
4613 revs = list(revs)
4614 revs.extend(opts['rev'])
4614 revs.extend(opts['rev'])
4615 if not revs:
4615 if not revs:
4616 raise util.Abort(_('no revisions specified'))
4616 raise util.Abort(_('no revisions specified'))
4617
4617
4618 revs = scmutil.revrange(repo, revs)
4618 revs = scmutil.revrange(repo, revs)
4619
4619
4620 lock = None
4620 lock = None
4621 ret = 0
4621 ret = 0
4622 if targetphase is None:
4622 if targetphase is None:
4623 # display
4623 # display
4624 for r in revs:
4624 for r in revs:
4625 ctx = repo[r]
4625 ctx = repo[r]
4626 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4626 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4627 else:
4627 else:
4628 lock = repo.lock()
4628 lock = repo.lock()
4629 try:
4629 try:
4630 # set phase
4630 # set phase
4631 if not revs:
4631 if not revs:
4632 raise util.Abort(_('empty revision set'))
4632 raise util.Abort(_('empty revision set'))
4633 nodes = [repo[r].node() for r in revs]
4633 nodes = [repo[r].node() for r in revs]
4634 olddata = repo._phasecache.getphaserevs(repo)[:]
4634 olddata = repo._phasecache.getphaserevs(repo)[:]
4635 phases.advanceboundary(repo, targetphase, nodes)
4635 phases.advanceboundary(repo, targetphase, nodes)
4636 if opts['force']:
4636 if opts['force']:
4637 phases.retractboundary(repo, targetphase, nodes)
4637 phases.retractboundary(repo, targetphase, nodes)
4638 finally:
4638 finally:
4639 lock.release()
4639 lock.release()
4640 # moving revision from public to draft may hide them
4640 # moving revision from public to draft may hide them
4641 # We have to check result on an unfiltered repository
4641 # We have to check result on an unfiltered repository
4642 unfi = repo.unfiltered()
4642 unfi = repo.unfiltered()
4643 newdata = repo._phasecache.getphaserevs(unfi)
4643 newdata = repo._phasecache.getphaserevs(unfi)
4644 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4644 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4645 cl = unfi.changelog
4645 cl = unfi.changelog
4646 rejected = [n for n in nodes
4646 rejected = [n for n in nodes
4647 if newdata[cl.rev(n)] < targetphase]
4647 if newdata[cl.rev(n)] < targetphase]
4648 if rejected:
4648 if rejected:
4649 ui.warn(_('cannot move %i changesets to a more permissive '
4649 ui.warn(_('cannot move %i changesets to a more permissive '
4650 'phase, use --force\n') % len(rejected))
4650 'phase, use --force\n') % len(rejected))
4651 ret = 1
4651 ret = 1
4652 if changes:
4652 if changes:
4653 msg = _('phase changed for %i changesets\n') % changes
4653 msg = _('phase changed for %i changesets\n') % changes
4654 if ret:
4654 if ret:
4655 ui.status(msg)
4655 ui.status(msg)
4656 else:
4656 else:
4657 ui.note(msg)
4657 ui.note(msg)
4658 else:
4658 else:
4659 ui.warn(_('no phases changed\n'))
4659 ui.warn(_('no phases changed\n'))
4660 ret = 1
4660 ret = 1
4661 return ret
4661 return ret
4662
4662
4663 def postincoming(ui, repo, modheads, optupdate, checkout):
4663 def postincoming(ui, repo, modheads, optupdate, checkout):
4664 if modheads == 0:
4664 if modheads == 0:
4665 return
4665 return
4666 if optupdate:
4666 if optupdate:
4667 movemarkfrom = repo['.'].node()
4667 movemarkfrom = repo['.'].node()
4668 try:
4668 try:
4669 ret = hg.update(repo, checkout)
4669 ret = hg.update(repo, checkout)
4670 except util.Abort, inst:
4670 except util.Abort, inst:
4671 ui.warn(_("not updating: %s\n") % str(inst))
4671 ui.warn(_("not updating: %s\n") % str(inst))
4672 return 0
4672 return 0
4673 if not ret and not checkout:
4673 if not ret and not checkout:
4674 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4674 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4675 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4675 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4676 return ret
4676 return ret
4677 if modheads > 1:
4677 if modheads > 1:
4678 currentbranchheads = len(repo.branchheads())
4678 currentbranchheads = len(repo.branchheads())
4679 if currentbranchheads == modheads:
4679 if currentbranchheads == modheads:
4680 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4680 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4681 elif currentbranchheads > 1:
4681 elif currentbranchheads > 1:
4682 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4682 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4683 "merge)\n"))
4683 "merge)\n"))
4684 else:
4684 else:
4685 ui.status(_("(run 'hg heads' to see heads)\n"))
4685 ui.status(_("(run 'hg heads' to see heads)\n"))
4686 else:
4686 else:
4687 ui.status(_("(run 'hg update' to get a working copy)\n"))
4687 ui.status(_("(run 'hg update' to get a working copy)\n"))
4688
4688
4689 @command('^pull',
4689 @command('^pull',
4690 [('u', 'update', None,
4690 [('u', 'update', None,
4691 _('update to new branch head if changesets were pulled')),
4691 _('update to new branch head if changesets were pulled')),
4692 ('f', 'force', None, _('run even when remote repository is unrelated')),
4692 ('f', 'force', None, _('run even when remote repository is unrelated')),
4693 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4693 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4694 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4694 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4695 ('b', 'branch', [], _('a specific branch you would like to pull'),
4695 ('b', 'branch', [], _('a specific branch you would like to pull'),
4696 _('BRANCH')),
4696 _('BRANCH')),
4697 ] + remoteopts,
4697 ] + remoteopts,
4698 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4698 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4699 def pull(ui, repo, source="default", **opts):
4699 def pull(ui, repo, source="default", **opts):
4700 """pull changes from the specified source
4700 """pull changes from the specified source
4701
4701
4702 Pull changes from a remote repository to a local one.
4702 Pull changes from a remote repository to a local one.
4703
4703
4704 This finds all changes from the repository at the specified path
4704 This finds all changes from the repository at the specified path
4705 or URL and adds them to a local repository (the current one unless
4705 or URL and adds them to a local repository (the current one unless
4706 -R is specified). By default, this does not update the copy of the
4706 -R is specified). By default, this does not update the copy of the
4707 project in the working directory.
4707 project in the working directory.
4708
4708
4709 Use :hg:`incoming` if you want to see what would have been added
4709 Use :hg:`incoming` if you want to see what would have been added
4710 by a pull at the time you issued this command. If you then decide
4710 by a pull at the time you issued this command. If you then decide
4711 to add those changes to the repository, you should use :hg:`pull
4711 to add those changes to the repository, you should use :hg:`pull
4712 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4712 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4713
4713
4714 If SOURCE is omitted, the 'default' path will be used.
4714 If SOURCE is omitted, the 'default' path will be used.
4715 See :hg:`help urls` for more information.
4715 See :hg:`help urls` for more information.
4716
4716
4717 Returns 0 on success, 1 if an update had unresolved files.
4717 Returns 0 on success, 1 if an update had unresolved files.
4718 """
4718 """
4719 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4719 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4720 other = hg.peer(repo, opts, source)
4720 other = hg.peer(repo, opts, source)
4721 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4721 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4722 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4722 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4723
4723
4724 if opts.get('bookmark'):
4724 if opts.get('bookmark'):
4725 if not revs:
4725 if not revs:
4726 revs = []
4726 revs = []
4727 rb = other.listkeys('bookmarks')
4727 rb = other.listkeys('bookmarks')
4728 for b in opts['bookmark']:
4728 for b in opts['bookmark']:
4729 if b not in rb:
4729 if b not in rb:
4730 raise util.Abort(_('remote bookmark %s not found!') % b)
4730 raise util.Abort(_('remote bookmark %s not found!') % b)
4731 revs.append(rb[b])
4731 revs.append(rb[b])
4732
4732
4733 if revs:
4733 if revs:
4734 try:
4734 try:
4735 revs = [other.lookup(rev) for rev in revs]
4735 revs = [other.lookup(rev) for rev in revs]
4736 except error.CapabilityError:
4736 except error.CapabilityError:
4737 err = _("other repository doesn't support revision lookup, "
4737 err = _("other repository doesn't support revision lookup, "
4738 "so a rev cannot be specified.")
4738 "so a rev cannot be specified.")
4739 raise util.Abort(err)
4739 raise util.Abort(err)
4740
4740
4741 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4741 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4742 bookmarks.updatefromremote(ui, repo, other, source)
4742 bookmarks.updatefromremote(ui, repo, other, source)
4743 if checkout:
4743 if checkout:
4744 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4744 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4745 repo._subtoppath = source
4745 repo._subtoppath = source
4746 try:
4746 try:
4747 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4747 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4748
4748
4749 finally:
4749 finally:
4750 del repo._subtoppath
4750 del repo._subtoppath
4751
4751
4752 # update specified bookmarks
4752 # update specified bookmarks
4753 if opts.get('bookmark'):
4753 if opts.get('bookmark'):
4754 marks = repo._bookmarks
4754 marks = repo._bookmarks
4755 for b in opts['bookmark']:
4755 for b in opts['bookmark']:
4756 # explicit pull overrides local bookmark if any
4756 # explicit pull overrides local bookmark if any
4757 ui.status(_("importing bookmark %s\n") % b)
4757 ui.status(_("importing bookmark %s\n") % b)
4758 marks[b] = repo[rb[b]].node()
4758 marks[b] = repo[rb[b]].node()
4759 marks.write()
4759 marks.write()
4760
4760
4761 return ret
4761 return ret
4762
4762
4763 @command('^push',
4763 @command('^push',
4764 [('f', 'force', None, _('force push')),
4764 [('f', 'force', None, _('force push')),
4765 ('r', 'rev', [],
4765 ('r', 'rev', [],
4766 _('a changeset intended to be included in the destination'),
4766 _('a changeset intended to be included in the destination'),
4767 _('REV')),
4767 _('REV')),
4768 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4768 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4769 ('b', 'branch', [],
4769 ('b', 'branch', [],
4770 _('a specific branch you would like to push'), _('BRANCH')),
4770 _('a specific branch you would like to push'), _('BRANCH')),
4771 ('', 'new-branch', False, _('allow pushing a new branch')),
4771 ('', 'new-branch', False, _('allow pushing a new branch')),
4772 ] + remoteopts,
4772 ] + remoteopts,
4773 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4773 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4774 def push(ui, repo, dest=None, **opts):
4774 def push(ui, repo, dest=None, **opts):
4775 """push changes to the specified destination
4775 """push changes to the specified destination
4776
4776
4777 Push changesets from the local repository to the specified
4777 Push changesets from the local repository to the specified
4778 destination.
4778 destination.
4779
4779
4780 This operation is symmetrical to pull: it is identical to a pull
4780 This operation is symmetrical to pull: it is identical to a pull
4781 in the destination repository from the current one.
4781 in the destination repository from the current one.
4782
4782
4783 By default, push will not allow creation of new heads at the
4783 By default, push will not allow creation of new heads at the
4784 destination, since multiple heads would make it unclear which head
4784 destination, since multiple heads would make it unclear which head
4785 to use. In this situation, it is recommended to pull and merge
4785 to use. In this situation, it is recommended to pull and merge
4786 before pushing.
4786 before pushing.
4787
4787
4788 Use --new-branch if you want to allow push to create a new named
4788 Use --new-branch if you want to allow push to create a new named
4789 branch that is not present at the destination. This allows you to
4789 branch that is not present at the destination. This allows you to
4790 only create a new branch without forcing other changes.
4790 only create a new branch without forcing other changes.
4791
4791
4792 Use -f/--force to override the default behavior and push all
4792 Use -f/--force to override the default behavior and push all
4793 changesets on all branches.
4793 changesets on all branches.
4794
4794
4795 If -r/--rev is used, the specified revision and all its ancestors
4795 If -r/--rev is used, the specified revision and all its ancestors
4796 will be pushed to the remote repository.
4796 will be pushed to the remote repository.
4797
4797
4798 If -B/--bookmark is used, the specified bookmarked revision, its
4798 If -B/--bookmark is used, the specified bookmarked revision, its
4799 ancestors, and the bookmark will be pushed to the remote
4799 ancestors, and the bookmark will be pushed to the remote
4800 repository.
4800 repository.
4801
4801
4802 Please see :hg:`help urls` for important details about ``ssh://``
4802 Please see :hg:`help urls` for important details about ``ssh://``
4803 URLs. If DESTINATION is omitted, a default path will be used.
4803 URLs. If DESTINATION is omitted, a default path will be used.
4804
4804
4805 Returns 0 if push was successful, 1 if nothing to push.
4805 Returns 0 if push was successful, 1 if nothing to push.
4806 """
4806 """
4807
4807
4808 if opts.get('bookmark'):
4808 if opts.get('bookmark'):
4809 for b in opts['bookmark']:
4809 for b in opts['bookmark']:
4810 # translate -B options to -r so changesets get pushed
4810 # translate -B options to -r so changesets get pushed
4811 if b in repo._bookmarks:
4811 if b in repo._bookmarks:
4812 opts.setdefault('rev', []).append(b)
4812 opts.setdefault('rev', []).append(b)
4813 else:
4813 else:
4814 # if we try to push a deleted bookmark, translate it to null
4814 # if we try to push a deleted bookmark, translate it to null
4815 # this lets simultaneous -r, -b options continue working
4815 # this lets simultaneous -r, -b options continue working
4816 opts.setdefault('rev', []).append("null")
4816 opts.setdefault('rev', []).append("null")
4817
4817
4818 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4818 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4819 dest, branches = hg.parseurl(dest, opts.get('branch'))
4819 dest, branches = hg.parseurl(dest, opts.get('branch'))
4820 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4820 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4821 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4821 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4822 other = hg.peer(repo, opts, dest)
4822 other = hg.peer(repo, opts, dest)
4823 if revs:
4823 if revs:
4824 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4824 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4825
4825
4826 repo._subtoppath = dest
4826 repo._subtoppath = dest
4827 try:
4827 try:
4828 # push subrepos depth-first for coherent ordering
4828 # push subrepos depth-first for coherent ordering
4829 c = repo['']
4829 c = repo['']
4830 subs = c.substate # only repos that are committed
4830 subs = c.substate # only repos that are committed
4831 for s in sorted(subs):
4831 for s in sorted(subs):
4832 if c.sub(s).push(opts) == 0:
4832 if c.sub(s).push(opts) == 0:
4833 return False
4833 return False
4834 finally:
4834 finally:
4835 del repo._subtoppath
4835 del repo._subtoppath
4836 result = repo.push(other, opts.get('force'), revs=revs,
4836 result = repo.push(other, opts.get('force'), revs=revs,
4837 newbranch=opts.get('new_branch'))
4837 newbranch=opts.get('new_branch'))
4838
4838
4839 result = not result
4839 result = not result
4840
4840
4841 if opts.get('bookmark'):
4841 if opts.get('bookmark'):
4842 rb = other.listkeys('bookmarks')
4842 rb = other.listkeys('bookmarks')
4843 for b in opts['bookmark']:
4843 for b in opts['bookmark']:
4844 # explicit push overrides remote bookmark if any
4844 # explicit push overrides remote bookmark if any
4845 if b in repo._bookmarks:
4845 if b in repo._bookmarks:
4846 ui.status(_("exporting bookmark %s\n") % b)
4846 ui.status(_("exporting bookmark %s\n") % b)
4847 new = repo[b].hex()
4847 new = repo[b].hex()
4848 elif b in rb:
4848 elif b in rb:
4849 ui.status(_("deleting remote bookmark %s\n") % b)
4849 ui.status(_("deleting remote bookmark %s\n") % b)
4850 new = '' # delete
4850 new = '' # delete
4851 else:
4851 else:
4852 ui.warn(_('bookmark %s does not exist on the local '
4852 ui.warn(_('bookmark %s does not exist on the local '
4853 'or remote repository!\n') % b)
4853 'or remote repository!\n') % b)
4854 return 2
4854 return 2
4855 old = rb.get(b, '')
4855 old = rb.get(b, '')
4856 r = other.pushkey('bookmarks', b, old, new)
4856 r = other.pushkey('bookmarks', b, old, new)
4857 if not r:
4857 if not r:
4858 ui.warn(_('updating bookmark %s failed!\n') % b)
4858 ui.warn(_('updating bookmark %s failed!\n') % b)
4859 if not result:
4859 if not result:
4860 result = 2
4860 result = 2
4861
4861
4862 return result
4862 return result
4863
4863
4864 @command('recover', [])
4864 @command('recover', [])
4865 def recover(ui, repo):
4865 def recover(ui, repo):
4866 """roll back an interrupted transaction
4866 """roll back an interrupted transaction
4867
4867
4868 Recover from an interrupted commit or pull.
4868 Recover from an interrupted commit or pull.
4869
4869
4870 This command tries to fix the repository status after an
4870 This command tries to fix the repository status after an
4871 interrupted operation. It should only be necessary when Mercurial
4871 interrupted operation. It should only be necessary when Mercurial
4872 suggests it.
4872 suggests it.
4873
4873
4874 Returns 0 if successful, 1 if nothing to recover or verify fails.
4874 Returns 0 if successful, 1 if nothing to recover or verify fails.
4875 """
4875 """
4876 if repo.recover():
4876 if repo.recover():
4877 return hg.verify(repo)
4877 return hg.verify(repo)
4878 return 1
4878 return 1
4879
4879
4880 @command('^remove|rm',
4880 @command('^remove|rm',
4881 [('A', 'after', None, _('record delete for missing files')),
4881 [('A', 'after', None, _('record delete for missing files')),
4882 ('f', 'force', None,
4882 ('f', 'force', None,
4883 _('remove (and delete) file even if added or modified')),
4883 _('remove (and delete) file even if added or modified')),
4884 ] + walkopts,
4884 ] + walkopts,
4885 _('[OPTION]... FILE...'))
4885 _('[OPTION]... FILE...'))
4886 def remove(ui, repo, *pats, **opts):
4886 def remove(ui, repo, *pats, **opts):
4887 """remove the specified files on the next commit
4887 """remove the specified files on the next commit
4888
4888
4889 Schedule the indicated files for removal from the current branch.
4889 Schedule the indicated files for removal from the current branch.
4890
4890
4891 This command schedules the files to be removed at the next commit.
4891 This command schedules the files to be removed at the next commit.
4892 To undo a remove before that, see :hg:`revert`. To undo added
4892 To undo a remove before that, see :hg:`revert`. To undo added
4893 files, see :hg:`forget`.
4893 files, see :hg:`forget`.
4894
4894
4895 .. container:: verbose
4895 .. container:: verbose
4896
4896
4897 -A/--after can be used to remove only files that have already
4897 -A/--after can be used to remove only files that have already
4898 been deleted, -f/--force can be used to force deletion, and -Af
4898 been deleted, -f/--force can be used to force deletion, and -Af
4899 can be used to remove files from the next revision without
4899 can be used to remove files from the next revision without
4900 deleting them from the working directory.
4900 deleting them from the working directory.
4901
4901
4902 The following table details the behavior of remove for different
4902 The following table details the behavior of remove for different
4903 file states (columns) and option combinations (rows). The file
4903 file states (columns) and option combinations (rows). The file
4904 states are Added [A], Clean [C], Modified [M] and Missing [!]
4904 states are Added [A], Clean [C], Modified [M] and Missing [!]
4905 (as reported by :hg:`status`). The actions are Warn, Remove
4905 (as reported by :hg:`status`). The actions are Warn, Remove
4906 (from branch) and Delete (from disk):
4906 (from branch) and Delete (from disk):
4907
4907
4908 ======= == == == ==
4908 ======= == == == ==
4909 A C M !
4909 A C M !
4910 ======= == == == ==
4910 ======= == == == ==
4911 none W RD W R
4911 none W RD W R
4912 -f R RD RD R
4912 -f R RD RD R
4913 -A W W W R
4913 -A W W W R
4914 -Af R R R R
4914 -Af R R R R
4915 ======= == == == ==
4915 ======= == == == ==
4916
4916
4917 Note that remove never deletes files in Added [A] state from the
4917 Note that remove never deletes files in Added [A] state from the
4918 working directory, not even if option --force is specified.
4918 working directory, not even if option --force is specified.
4919
4919
4920 Returns 0 on success, 1 if any warnings encountered.
4920 Returns 0 on success, 1 if any warnings encountered.
4921 """
4921 """
4922
4922
4923 ret = 0
4923 ret = 0
4924 after, force = opts.get('after'), opts.get('force')
4924 after, force = opts.get('after'), opts.get('force')
4925 if not pats and not after:
4925 if not pats and not after:
4926 raise util.Abort(_('no files specified'))
4926 raise util.Abort(_('no files specified'))
4927
4927
4928 m = scmutil.match(repo[None], pats, opts)
4928 m = scmutil.match(repo[None], pats, opts)
4929 s = repo.status(match=m, clean=True)
4929 s = repo.status(match=m, clean=True)
4930 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4930 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4931
4931
4932 # warn about failure to delete explicit files/dirs
4932 # warn about failure to delete explicit files/dirs
4933 wctx = repo[None]
4933 wctx = repo[None]
4934 for f in m.files():
4934 for f in m.files():
4935 if f in repo.dirstate or f in wctx.dirs():
4935 if f in repo.dirstate or f in wctx.dirs():
4936 continue
4936 continue
4937 if os.path.exists(m.rel(f)):
4937 if os.path.exists(m.rel(f)):
4938 if os.path.isdir(m.rel(f)):
4938 if os.path.isdir(m.rel(f)):
4939 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4939 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4940 else:
4940 else:
4941 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4941 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4942 # missing files will generate a warning elsewhere
4942 # missing files will generate a warning elsewhere
4943 ret = 1
4943 ret = 1
4944
4944
4945 if force:
4945 if force:
4946 list = modified + deleted + clean + added
4946 list = modified + deleted + clean + added
4947 elif after:
4947 elif after:
4948 list = deleted
4948 list = deleted
4949 for f in modified + added + clean:
4949 for f in modified + added + clean:
4950 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4950 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4951 ret = 1
4951 ret = 1
4952 else:
4952 else:
4953 list = deleted + clean
4953 list = deleted + clean
4954 for f in modified:
4954 for f in modified:
4955 ui.warn(_('not removing %s: file is modified (use -f'
4955 ui.warn(_('not removing %s: file is modified (use -f'
4956 ' to force removal)\n') % m.rel(f))
4956 ' to force removal)\n') % m.rel(f))
4957 ret = 1
4957 ret = 1
4958 for f in added:
4958 for f in added:
4959 ui.warn(_('not removing %s: file has been marked for add'
4959 ui.warn(_('not removing %s: file has been marked for add'
4960 ' (use forget to undo)\n') % m.rel(f))
4960 ' (use forget to undo)\n') % m.rel(f))
4961 ret = 1
4961 ret = 1
4962
4962
4963 for f in sorted(list):
4963 for f in sorted(list):
4964 if ui.verbose or not m.exact(f):
4964 if ui.verbose or not m.exact(f):
4965 ui.status(_('removing %s\n') % m.rel(f))
4965 ui.status(_('removing %s\n') % m.rel(f))
4966
4966
4967 wlock = repo.wlock()
4967 wlock = repo.wlock()
4968 try:
4968 try:
4969 if not after:
4969 if not after:
4970 for f in list:
4970 for f in list:
4971 if f in added:
4971 if f in added:
4972 continue # we never unlink added files on remove
4972 continue # we never unlink added files on remove
4973 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4973 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4974 repo[None].forget(list)
4974 repo[None].forget(list)
4975 finally:
4975 finally:
4976 wlock.release()
4976 wlock.release()
4977
4977
4978 return ret
4978 return ret
4979
4979
4980 @command('rename|move|mv',
4980 @command('rename|move|mv',
4981 [('A', 'after', None, _('record a rename that has already occurred')),
4981 [('A', 'after', None, _('record a rename that has already occurred')),
4982 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4982 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4983 ] + walkopts + dryrunopts,
4983 ] + walkopts + dryrunopts,
4984 _('[OPTION]... SOURCE... DEST'))
4984 _('[OPTION]... SOURCE... DEST'))
4985 def rename(ui, repo, *pats, **opts):
4985 def rename(ui, repo, *pats, **opts):
4986 """rename files; equivalent of copy + remove
4986 """rename files; equivalent of copy + remove
4987
4987
4988 Mark dest as copies of sources; mark sources for deletion. If dest
4988 Mark dest as copies of sources; mark sources for deletion. If dest
4989 is a directory, copies are put in that directory. If dest is a
4989 is a directory, copies are put in that directory. If dest is a
4990 file, there can only be one source.
4990 file, there can only be one source.
4991
4991
4992 By default, this command copies the contents of files as they
4992 By default, this command copies the contents of files as they
4993 exist in the working directory. If invoked with -A/--after, the
4993 exist in the working directory. If invoked with -A/--after, the
4994 operation is recorded, but no copying is performed.
4994 operation is recorded, but no copying is performed.
4995
4995
4996 This command takes effect at the next commit. To undo a rename
4996 This command takes effect at the next commit. To undo a rename
4997 before that, see :hg:`revert`.
4997 before that, see :hg:`revert`.
4998
4998
4999 Returns 0 on success, 1 if errors are encountered.
4999 Returns 0 on success, 1 if errors are encountered.
5000 """
5000 """
5001 wlock = repo.wlock(False)
5001 wlock = repo.wlock(False)
5002 try:
5002 try:
5003 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5003 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5004 finally:
5004 finally:
5005 wlock.release()
5005 wlock.release()
5006
5006
5007 @command('resolve',
5007 @command('resolve',
5008 [('a', 'all', None, _('select all unresolved files')),
5008 [('a', 'all', None, _('select all unresolved files')),
5009 ('l', 'list', None, _('list state of files needing merge')),
5009 ('l', 'list', None, _('list state of files needing merge')),
5010 ('m', 'mark', None, _('mark files as resolved')),
5010 ('m', 'mark', None, _('mark files as resolved')),
5011 ('u', 'unmark', None, _('mark files as unresolved')),
5011 ('u', 'unmark', None, _('mark files as unresolved')),
5012 ('n', 'no-status', None, _('hide status prefix'))]
5012 ('n', 'no-status', None, _('hide status prefix'))]
5013 + mergetoolopts + walkopts,
5013 + mergetoolopts + walkopts,
5014 _('[OPTION]... [FILE]...'))
5014 _('[OPTION]... [FILE]...'))
5015 def resolve(ui, repo, *pats, **opts):
5015 def resolve(ui, repo, *pats, **opts):
5016 """redo merges or set/view the merge status of files
5016 """redo merges or set/view the merge status of files
5017
5017
5018 Merges with unresolved conflicts are often the result of
5018 Merges with unresolved conflicts are often the result of
5019 non-interactive merging using the ``internal:merge`` configuration
5019 non-interactive merging using the ``internal:merge`` configuration
5020 setting, or a command-line merge tool like ``diff3``. The resolve
5020 setting, or a command-line merge tool like ``diff3``. The resolve
5021 command is used to manage the files involved in a merge, after
5021 command is used to manage the files involved in a merge, after
5022 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5022 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5023 working directory must have two parents). See :hg:`help
5023 working directory must have two parents). See :hg:`help
5024 merge-tools` for information on configuring merge tools.
5024 merge-tools` for information on configuring merge tools.
5025
5025
5026 The resolve command can be used in the following ways:
5026 The resolve command can be used in the following ways:
5027
5027
5028 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5028 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5029 files, discarding any previous merge attempts. Re-merging is not
5029 files, discarding any previous merge attempts. Re-merging is not
5030 performed for files already marked as resolved. Use ``--all/-a``
5030 performed for files already marked as resolved. Use ``--all/-a``
5031 to select all unresolved files. ``--tool`` can be used to specify
5031 to select all unresolved files. ``--tool`` can be used to specify
5032 the merge tool used for the given files. It overrides the HGMERGE
5032 the merge tool used for the given files. It overrides the HGMERGE
5033 environment variable and your configuration files. Previous file
5033 environment variable and your configuration files. Previous file
5034 contents are saved with a ``.orig`` suffix.
5034 contents are saved with a ``.orig`` suffix.
5035
5035
5036 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5036 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5037 (e.g. after having manually fixed-up the files). The default is
5037 (e.g. after having manually fixed-up the files). The default is
5038 to mark all unresolved files.
5038 to mark all unresolved files.
5039
5039
5040 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5040 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5041 default is to mark all resolved files.
5041 default is to mark all resolved files.
5042
5042
5043 - :hg:`resolve -l`: list files which had or still have conflicts.
5043 - :hg:`resolve -l`: list files which had or still have conflicts.
5044 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5044 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5045
5045
5046 Note that Mercurial will not let you commit files with unresolved
5046 Note that Mercurial will not let you commit files with unresolved
5047 merge conflicts. You must use :hg:`resolve -m ...` before you can
5047 merge conflicts. You must use :hg:`resolve -m ...` before you can
5048 commit after a conflicting merge.
5048 commit after a conflicting merge.
5049
5049
5050 Returns 0 on success, 1 if any files fail a resolve attempt.
5050 Returns 0 on success, 1 if any files fail a resolve attempt.
5051 """
5051 """
5052
5052
5053 all, mark, unmark, show, nostatus = \
5053 all, mark, unmark, show, nostatus = \
5054 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5054 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5055
5055
5056 if (show and (mark or unmark)) or (mark and unmark):
5056 if (show and (mark or unmark)) or (mark and unmark):
5057 raise util.Abort(_("too many options specified"))
5057 raise util.Abort(_("too many options specified"))
5058 if pats and all:
5058 if pats and all:
5059 raise util.Abort(_("can't specify --all and patterns"))
5059 raise util.Abort(_("can't specify --all and patterns"))
5060 if not (all or pats or show or mark or unmark):
5060 if not (all or pats or show or mark or unmark):
5061 raise util.Abort(_('no files or directories specified; '
5061 raise util.Abort(_('no files or directories specified; '
5062 'use --all to remerge all files'))
5062 'use --all to remerge all files'))
5063
5063
5064 ms = mergemod.mergestate(repo)
5064 ms = mergemod.mergestate(repo)
5065 m = scmutil.match(repo[None], pats, opts)
5065 m = scmutil.match(repo[None], pats, opts)
5066 ret = 0
5066 ret = 0
5067
5067
5068 for f in ms:
5068 for f in ms:
5069 if m(f):
5069 if m(f):
5070 if show:
5070 if show:
5071 if nostatus:
5071 if nostatus:
5072 ui.write("%s\n" % f)
5072 ui.write("%s\n" % f)
5073 else:
5073 else:
5074 ui.write("%s %s\n" % (ms[f].upper(), f),
5074 ui.write("%s %s\n" % (ms[f].upper(), f),
5075 label='resolve.' +
5075 label='resolve.' +
5076 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5076 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5077 elif mark:
5077 elif mark:
5078 ms.mark(f, "r")
5078 ms.mark(f, "r")
5079 elif unmark:
5079 elif unmark:
5080 ms.mark(f, "u")
5080 ms.mark(f, "u")
5081 else:
5081 else:
5082 wctx = repo[None]
5082 wctx = repo[None]
5083 mctx = wctx.parents()[-1]
5083 mctx = wctx.parents()[-1]
5084
5084
5085 # backup pre-resolve (merge uses .orig for its own purposes)
5085 # backup pre-resolve (merge uses .orig for its own purposes)
5086 a = repo.wjoin(f)
5086 a = repo.wjoin(f)
5087 util.copyfile(a, a + ".resolve")
5087 util.copyfile(a, a + ".resolve")
5088
5088
5089 try:
5089 try:
5090 # resolve file
5090 # resolve file
5091 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5091 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
5092 if ms.resolve(f, wctx, mctx):
5092 if ms.resolve(f, wctx, mctx):
5093 ret = 1
5093 ret = 1
5094 finally:
5094 finally:
5095 ui.setconfig('ui', 'forcemerge', '')
5095 ui.setconfig('ui', 'forcemerge', '')
5096 ms.commit()
5096 ms.commit()
5097
5097
5098 # replace filemerge's .orig file with our resolve file
5098 # replace filemerge's .orig file with our resolve file
5099 util.rename(a + ".resolve", a + ".orig")
5099 util.rename(a + ".resolve", a + ".orig")
5100
5100
5101 ms.commit()
5101 ms.commit()
5102 return ret
5102 return ret
5103
5103
5104 @command('revert',
5104 @command('revert',
5105 [('a', 'all', None, _('revert all changes when no arguments given')),
5105 [('a', 'all', None, _('revert all changes when no arguments given')),
5106 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5106 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5107 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5107 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5108 ('C', 'no-backup', None, _('do not save backup copies of files')),
5108 ('C', 'no-backup', None, _('do not save backup copies of files')),
5109 ] + walkopts + dryrunopts,
5109 ] + walkopts + dryrunopts,
5110 _('[OPTION]... [-r REV] [NAME]...'))
5110 _('[OPTION]... [-r REV] [NAME]...'))
5111 def revert(ui, repo, *pats, **opts):
5111 def revert(ui, repo, *pats, **opts):
5112 """restore files to their checkout state
5112 """restore files to their checkout state
5113
5113
5114 .. note::
5114 .. note::
5115
5115
5116 To check out earlier revisions, you should use :hg:`update REV`.
5116 To check out earlier revisions, you should use :hg:`update REV`.
5117 To cancel an uncommitted merge (and lose your changes), use
5117 To cancel an uncommitted merge (and lose your changes), use
5118 :hg:`update --clean .`.
5118 :hg:`update --clean .`.
5119
5119
5120 With no revision specified, revert the specified files or directories
5120 With no revision specified, revert the specified files or directories
5121 to the contents they had in the parent of the working directory.
5121 to the contents they had in the parent of the working directory.
5122 This restores the contents of files to an unmodified
5122 This restores the contents of files to an unmodified
5123 state and unschedules adds, removes, copies, and renames. If the
5123 state and unschedules adds, removes, copies, and renames. If the
5124 working directory has two parents, you must explicitly specify a
5124 working directory has two parents, you must explicitly specify a
5125 revision.
5125 revision.
5126
5126
5127 Using the -r/--rev or -d/--date options, revert the given files or
5127 Using the -r/--rev or -d/--date options, revert the given files or
5128 directories to their states as of a specific revision. Because
5128 directories to their states as of a specific revision. Because
5129 revert does not change the working directory parents, this will
5129 revert does not change the working directory parents, this will
5130 cause these files to appear modified. This can be helpful to "back
5130 cause these files to appear modified. This can be helpful to "back
5131 out" some or all of an earlier change. See :hg:`backout` for a
5131 out" some or all of an earlier change. See :hg:`backout` for a
5132 related method.
5132 related method.
5133
5133
5134 Modified files are saved with a .orig suffix before reverting.
5134 Modified files are saved with a .orig suffix before reverting.
5135 To disable these backups, use --no-backup.
5135 To disable these backups, use --no-backup.
5136
5136
5137 See :hg:`help dates` for a list of formats valid for -d/--date.
5137 See :hg:`help dates` for a list of formats valid for -d/--date.
5138
5138
5139 Returns 0 on success.
5139 Returns 0 on success.
5140 """
5140 """
5141
5141
5142 if opts.get("date"):
5142 if opts.get("date"):
5143 if opts.get("rev"):
5143 if opts.get("rev"):
5144 raise util.Abort(_("you can't specify a revision and a date"))
5144 raise util.Abort(_("you can't specify a revision and a date"))
5145 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5145 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5146
5146
5147 parent, p2 = repo.dirstate.parents()
5147 parent, p2 = repo.dirstate.parents()
5148 if not opts.get('rev') and p2 != nullid:
5148 if not opts.get('rev') and p2 != nullid:
5149 # revert after merge is a trap for new users (issue2915)
5149 # revert after merge is a trap for new users (issue2915)
5150 raise util.Abort(_('uncommitted merge with no revision specified'),
5150 raise util.Abort(_('uncommitted merge with no revision specified'),
5151 hint=_('use "hg update" or see "hg help revert"'))
5151 hint=_('use "hg update" or see "hg help revert"'))
5152
5152
5153 ctx = scmutil.revsingle(repo, opts.get('rev'))
5153 ctx = scmutil.revsingle(repo, opts.get('rev'))
5154
5154
5155 if not pats and not opts.get('all'):
5155 if not pats and not opts.get('all'):
5156 msg = _("no files or directories specified")
5156 msg = _("no files or directories specified")
5157 if p2 != nullid:
5157 if p2 != nullid:
5158 hint = _("uncommitted merge, use --all to discard all changes,"
5158 hint = _("uncommitted merge, use --all to discard all changes,"
5159 " or 'hg update -C .' to abort the merge")
5159 " or 'hg update -C .' to abort the merge")
5160 raise util.Abort(msg, hint=hint)
5160 raise util.Abort(msg, hint=hint)
5161 dirty = util.any(repo.status())
5161 dirty = util.any(repo.status())
5162 node = ctx.node()
5162 node = ctx.node()
5163 if node != parent:
5163 if node != parent:
5164 if dirty:
5164 if dirty:
5165 hint = _("uncommitted changes, use --all to discard all"
5165 hint = _("uncommitted changes, use --all to discard all"
5166 " changes, or 'hg update %s' to update") % ctx.rev()
5166 " changes, or 'hg update %s' to update") % ctx.rev()
5167 else:
5167 else:
5168 hint = _("use --all to revert all files,"
5168 hint = _("use --all to revert all files,"
5169 " or 'hg update %s' to update") % ctx.rev()
5169 " or 'hg update %s' to update") % ctx.rev()
5170 elif dirty:
5170 elif dirty:
5171 hint = _("uncommitted changes, use --all to discard all changes")
5171 hint = _("uncommitted changes, use --all to discard all changes")
5172 else:
5172 else:
5173 hint = _("use --all to revert all files")
5173 hint = _("use --all to revert all files")
5174 raise util.Abort(msg, hint=hint)
5174 raise util.Abort(msg, hint=hint)
5175
5175
5176 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5176 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5177
5177
5178 @command('rollback', dryrunopts +
5178 @command('rollback', dryrunopts +
5179 [('f', 'force', False, _('ignore safety measures'))])
5179 [('f', 'force', False, _('ignore safety measures'))])
5180 def rollback(ui, repo, **opts):
5180 def rollback(ui, repo, **opts):
5181 """roll back the last transaction (dangerous)
5181 """roll back the last transaction (dangerous)
5182
5182
5183 This command should be used with care. There is only one level of
5183 This command should be used with care. There is only one level of
5184 rollback, and there is no way to undo a rollback. It will also
5184 rollback, and there is no way to undo a rollback. It will also
5185 restore the dirstate at the time of the last transaction, losing
5185 restore the dirstate at the time of the last transaction, losing
5186 any dirstate changes since that time. This command does not alter
5186 any dirstate changes since that time. This command does not alter
5187 the working directory.
5187 the working directory.
5188
5188
5189 Transactions are used to encapsulate the effects of all commands
5189 Transactions are used to encapsulate the effects of all commands
5190 that create new changesets or propagate existing changesets into a
5190 that create new changesets or propagate existing changesets into a
5191 repository.
5191 repository.
5192
5192
5193 .. container:: verbose
5193 .. container:: verbose
5194
5194
5195 For example, the following commands are transactional, and their
5195 For example, the following commands are transactional, and their
5196 effects can be rolled back:
5196 effects can be rolled back:
5197
5197
5198 - commit
5198 - commit
5199 - import
5199 - import
5200 - pull
5200 - pull
5201 - push (with this repository as the destination)
5201 - push (with this repository as the destination)
5202 - unbundle
5202 - unbundle
5203
5203
5204 To avoid permanent data loss, rollback will refuse to rollback a
5204 To avoid permanent data loss, rollback will refuse to rollback a
5205 commit transaction if it isn't checked out. Use --force to
5205 commit transaction if it isn't checked out. Use --force to
5206 override this protection.
5206 override this protection.
5207
5207
5208 This command is not intended for use on public repositories. Once
5208 This command is not intended for use on public repositories. Once
5209 changes are visible for pull by other users, rolling a transaction
5209 changes are visible for pull by other users, rolling a transaction
5210 back locally is ineffective (someone else may already have pulled
5210 back locally is ineffective (someone else may already have pulled
5211 the changes). Furthermore, a race is possible with readers of the
5211 the changes). Furthermore, a race is possible with readers of the
5212 repository; for example an in-progress pull from the repository
5212 repository; for example an in-progress pull from the repository
5213 may fail if a rollback is performed.
5213 may fail if a rollback is performed.
5214
5214
5215 Returns 0 on success, 1 if no rollback data is available.
5215 Returns 0 on success, 1 if no rollback data is available.
5216 """
5216 """
5217 return repo.rollback(dryrun=opts.get('dry_run'),
5217 return repo.rollback(dryrun=opts.get('dry_run'),
5218 force=opts.get('force'))
5218 force=opts.get('force'))
5219
5219
5220 @command('root', [])
5220 @command('root', [])
5221 def root(ui, repo):
5221 def root(ui, repo):
5222 """print the root (top) of the current working directory
5222 """print the root (top) of the current working directory
5223
5223
5224 Print the root directory of the current repository.
5224 Print the root directory of the current repository.
5225
5225
5226 Returns 0 on success.
5226 Returns 0 on success.
5227 """
5227 """
5228 ui.write(repo.root + "\n")
5228 ui.write(repo.root + "\n")
5229
5229
5230 @command('^serve',
5230 @command('^serve',
5231 [('A', 'accesslog', '', _('name of access log file to write to'),
5231 [('A', 'accesslog', '', _('name of access log file to write to'),
5232 _('FILE')),
5232 _('FILE')),
5233 ('d', 'daemon', None, _('run server in background')),
5233 ('d', 'daemon', None, _('run server in background')),
5234 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5234 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5235 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5235 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5236 # use string type, then we can check if something was passed
5236 # use string type, then we can check if something was passed
5237 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5237 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5238 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5238 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5239 _('ADDR')),
5239 _('ADDR')),
5240 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5240 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5241 _('PREFIX')),
5241 _('PREFIX')),
5242 ('n', 'name', '',
5242 ('n', 'name', '',
5243 _('name to show in web pages (default: working directory)'), _('NAME')),
5243 _('name to show in web pages (default: working directory)'), _('NAME')),
5244 ('', 'web-conf', '',
5244 ('', 'web-conf', '',
5245 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5245 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5246 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5246 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5247 _('FILE')),
5247 _('FILE')),
5248 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5248 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5249 ('', 'stdio', None, _('for remote clients')),
5249 ('', 'stdio', None, _('for remote clients')),
5250 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5250 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5251 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5251 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5252 ('', 'style', '', _('template style to use'), _('STYLE')),
5252 ('', 'style', '', _('template style to use'), _('STYLE')),
5253 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5253 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5254 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5254 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5255 _('[OPTION]...'))
5255 _('[OPTION]...'))
5256 def serve(ui, repo, **opts):
5256 def serve(ui, repo, **opts):
5257 """start stand-alone webserver
5257 """start stand-alone webserver
5258
5258
5259 Start a local HTTP repository browser and pull server. You can use
5259 Start a local HTTP repository browser and pull server. You can use
5260 this for ad-hoc sharing and browsing of repositories. It is
5260 this for ad-hoc sharing and browsing of repositories. It is
5261 recommended to use a real web server to serve a repository for
5261 recommended to use a real web server to serve a repository for
5262 longer periods of time.
5262 longer periods of time.
5263
5263
5264 Please note that the server does not implement access control.
5264 Please note that the server does not implement access control.
5265 This means that, by default, anybody can read from the server and
5265 This means that, by default, anybody can read from the server and
5266 nobody can write to it by default. Set the ``web.allow_push``
5266 nobody can write to it by default. Set the ``web.allow_push``
5267 option to ``*`` to allow everybody to push to the server. You
5267 option to ``*`` to allow everybody to push to the server. You
5268 should use a real web server if you need to authenticate users.
5268 should use a real web server if you need to authenticate users.
5269
5269
5270 By default, the server logs accesses to stdout and errors to
5270 By default, the server logs accesses to stdout and errors to
5271 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5271 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5272 files.
5272 files.
5273
5273
5274 To have the server choose a free port number to listen on, specify
5274 To have the server choose a free port number to listen on, specify
5275 a port number of 0; in this case, the server will print the port
5275 a port number of 0; in this case, the server will print the port
5276 number it uses.
5276 number it uses.
5277
5277
5278 Returns 0 on success.
5278 Returns 0 on success.
5279 """
5279 """
5280
5280
5281 if opts["stdio"] and opts["cmdserver"]:
5281 if opts["stdio"] and opts["cmdserver"]:
5282 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5282 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5283
5283
5284 def checkrepo():
5284 def checkrepo():
5285 if repo is None:
5285 if repo is None:
5286 raise error.RepoError(_("there is no Mercurial repository here"
5286 raise error.RepoError(_("there is no Mercurial repository here"
5287 " (.hg not found)"))
5287 " (.hg not found)"))
5288
5288
5289 if opts["stdio"]:
5289 if opts["stdio"]:
5290 checkrepo()
5290 checkrepo()
5291 s = sshserver.sshserver(ui, repo)
5291 s = sshserver.sshserver(ui, repo)
5292 s.serve_forever()
5292 s.serve_forever()
5293
5293
5294 if opts["cmdserver"]:
5294 if opts["cmdserver"]:
5295 checkrepo()
5295 checkrepo()
5296 s = commandserver.server(ui, repo, opts["cmdserver"])
5296 s = commandserver.server(ui, repo, opts["cmdserver"])
5297 return s.serve()
5297 return s.serve()
5298
5298
5299 # this way we can check if something was given in the command-line
5299 # this way we can check if something was given in the command-line
5300 if opts.get('port'):
5300 if opts.get('port'):
5301 opts['port'] = util.getport(opts.get('port'))
5301 opts['port'] = util.getport(opts.get('port'))
5302
5302
5303 baseui = repo and repo.baseui or ui
5303 baseui = repo and repo.baseui or ui
5304 optlist = ("name templates style address port prefix ipv6"
5304 optlist = ("name templates style address port prefix ipv6"
5305 " accesslog errorlog certificate encoding")
5305 " accesslog errorlog certificate encoding")
5306 for o in optlist.split():
5306 for o in optlist.split():
5307 val = opts.get(o, '')
5307 val = opts.get(o, '')
5308 if val in (None, ''): # should check against default options instead
5308 if val in (None, ''): # should check against default options instead
5309 continue
5309 continue
5310 baseui.setconfig("web", o, val)
5310 baseui.setconfig("web", o, val)
5311 if repo and repo.ui != baseui:
5311 if repo and repo.ui != baseui:
5312 repo.ui.setconfig("web", o, val)
5312 repo.ui.setconfig("web", o, val)
5313
5313
5314 o = opts.get('web_conf') or opts.get('webdir_conf')
5314 o = opts.get('web_conf') or opts.get('webdir_conf')
5315 if not o:
5315 if not o:
5316 if not repo:
5316 if not repo:
5317 raise error.RepoError(_("there is no Mercurial repository"
5317 raise error.RepoError(_("there is no Mercurial repository"
5318 " here (.hg not found)"))
5318 " here (.hg not found)"))
5319 o = repo.root
5319 o = repo.root
5320
5320
5321 app = hgweb.hgweb(o, baseui=ui)
5321 app = hgweb.hgweb(o, baseui=ui)
5322
5322
5323 class service(object):
5323 class service(object):
5324 def init(self):
5324 def init(self):
5325 util.setsignalhandler()
5325 util.setsignalhandler()
5326 self.httpd = hgweb.server.create_server(ui, app)
5326 self.httpd = hgweb.server.create_server(ui, app)
5327
5327
5328 if opts['port'] and not ui.verbose:
5328 if opts['port'] and not ui.verbose:
5329 return
5329 return
5330
5330
5331 if self.httpd.prefix:
5331 if self.httpd.prefix:
5332 prefix = self.httpd.prefix.strip('/') + '/'
5332 prefix = self.httpd.prefix.strip('/') + '/'
5333 else:
5333 else:
5334 prefix = ''
5334 prefix = ''
5335
5335
5336 port = ':%d' % self.httpd.port
5336 port = ':%d' % self.httpd.port
5337 if port == ':80':
5337 if port == ':80':
5338 port = ''
5338 port = ''
5339
5339
5340 bindaddr = self.httpd.addr
5340 bindaddr = self.httpd.addr
5341 if bindaddr == '0.0.0.0':
5341 if bindaddr == '0.0.0.0':
5342 bindaddr = '*'
5342 bindaddr = '*'
5343 elif ':' in bindaddr: # IPv6
5343 elif ':' in bindaddr: # IPv6
5344 bindaddr = '[%s]' % bindaddr
5344 bindaddr = '[%s]' % bindaddr
5345
5345
5346 fqaddr = self.httpd.fqaddr
5346 fqaddr = self.httpd.fqaddr
5347 if ':' in fqaddr:
5347 if ':' in fqaddr:
5348 fqaddr = '[%s]' % fqaddr
5348 fqaddr = '[%s]' % fqaddr
5349 if opts['port']:
5349 if opts['port']:
5350 write = ui.status
5350 write = ui.status
5351 else:
5351 else:
5352 write = ui.write
5352 write = ui.write
5353 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5353 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5354 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5354 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5355
5355
5356 def run(self):
5356 def run(self):
5357 self.httpd.serve_forever()
5357 self.httpd.serve_forever()
5358
5358
5359 service = service()
5359 service = service()
5360
5360
5361 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5361 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5362
5362
5363 @command('showconfig|debugconfig',
5363 @command('showconfig|debugconfig',
5364 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5364 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5365 _('[-u] [NAME]...'))
5365 _('[-u] [NAME]...'))
5366 def showconfig(ui, repo, *values, **opts):
5366 def showconfig(ui, repo, *values, **opts):
5367 """show combined config settings from all hgrc files
5367 """show combined config settings from all hgrc files
5368
5368
5369 With no arguments, print names and values of all config items.
5369 With no arguments, print names and values of all config items.
5370
5370
5371 With one argument of the form section.name, print just the value
5371 With one argument of the form section.name, print just the value
5372 of that config item.
5372 of that config item.
5373
5373
5374 With multiple arguments, print names and values of all config
5374 With multiple arguments, print names and values of all config
5375 items with matching section names.
5375 items with matching section names.
5376
5376
5377 With --debug, the source (filename and line number) is printed
5377 With --debug, the source (filename and line number) is printed
5378 for each config item.
5378 for each config item.
5379
5379
5380 Returns 0 on success.
5380 Returns 0 on success.
5381 """
5381 """
5382
5382
5383 for f in scmutil.rcpath():
5383 for f in scmutil.rcpath():
5384 ui.debug('read config from: %s\n' % f)
5384 ui.debug('read config from: %s\n' % f)
5385 untrusted = bool(opts.get('untrusted'))
5385 untrusted = bool(opts.get('untrusted'))
5386 if values:
5386 if values:
5387 sections = [v for v in values if '.' not in v]
5387 sections = [v for v in values if '.' not in v]
5388 items = [v for v in values if '.' in v]
5388 items = [v for v in values if '.' in v]
5389 if len(items) > 1 or items and sections:
5389 if len(items) > 1 or items and sections:
5390 raise util.Abort(_('only one config item permitted'))
5390 raise util.Abort(_('only one config item permitted'))
5391 for section, name, value in ui.walkconfig(untrusted=untrusted):
5391 for section, name, value in ui.walkconfig(untrusted=untrusted):
5392 value = str(value).replace('\n', '\\n')
5392 value = str(value).replace('\n', '\\n')
5393 sectname = section + '.' + name
5393 sectname = section + '.' + name
5394 if values:
5394 if values:
5395 for v in values:
5395 for v in values:
5396 if v == section:
5396 if v == section:
5397 ui.debug('%s: ' %
5397 ui.debug('%s: ' %
5398 ui.configsource(section, name, untrusted))
5398 ui.configsource(section, name, untrusted))
5399 ui.write('%s=%s\n' % (sectname, value))
5399 ui.write('%s=%s\n' % (sectname, value))
5400 elif v == sectname:
5400 elif v == sectname:
5401 ui.debug('%s: ' %
5401 ui.debug('%s: ' %
5402 ui.configsource(section, name, untrusted))
5402 ui.configsource(section, name, untrusted))
5403 ui.write(value, '\n')
5403 ui.write(value, '\n')
5404 else:
5404 else:
5405 ui.debug('%s: ' %
5405 ui.debug('%s: ' %
5406 ui.configsource(section, name, untrusted))
5406 ui.configsource(section, name, untrusted))
5407 ui.write('%s=%s\n' % (sectname, value))
5407 ui.write('%s=%s\n' % (sectname, value))
5408
5408
5409 @command('^status|st',
5409 @command('^status|st',
5410 [('A', 'all', None, _('show status of all files')),
5410 [('A', 'all', None, _('show status of all files')),
5411 ('m', 'modified', None, _('show only modified files')),
5411 ('m', 'modified', None, _('show only modified files')),
5412 ('a', 'added', None, _('show only added files')),
5412 ('a', 'added', None, _('show only added files')),
5413 ('r', 'removed', None, _('show only removed files')),
5413 ('r', 'removed', None, _('show only removed files')),
5414 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5414 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5415 ('c', 'clean', None, _('show only files without changes')),
5415 ('c', 'clean', None, _('show only files without changes')),
5416 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5416 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5417 ('i', 'ignored', None, _('show only ignored files')),
5417 ('i', 'ignored', None, _('show only ignored files')),
5418 ('n', 'no-status', None, _('hide status prefix')),
5418 ('n', 'no-status', None, _('hide status prefix')),
5419 ('C', 'copies', None, _('show source of copied files')),
5419 ('C', 'copies', None, _('show source of copied files')),
5420 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5420 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5421 ('', 'rev', [], _('show difference from revision'), _('REV')),
5421 ('', 'rev', [], _('show difference from revision'), _('REV')),
5422 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5422 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5423 ] + walkopts + subrepoopts,
5423 ] + walkopts + subrepoopts,
5424 _('[OPTION]... [FILE]...'))
5424 _('[OPTION]... [FILE]...'))
5425 def status(ui, repo, *pats, **opts):
5425 def status(ui, repo, *pats, **opts):
5426 """show changed files in the working directory
5426 """show changed files in the working directory
5427
5427
5428 Show status of files in the repository. If names are given, only
5428 Show status of files in the repository. If names are given, only
5429 files that match are shown. Files that are clean or ignored or
5429 files that match are shown. Files that are clean or ignored or
5430 the source of a copy/move operation, are not listed unless
5430 the source of a copy/move operation, are not listed unless
5431 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5431 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5432 Unless options described with "show only ..." are given, the
5432 Unless options described with "show only ..." are given, the
5433 options -mardu are used.
5433 options -mardu are used.
5434
5434
5435 Option -q/--quiet hides untracked (unknown and ignored) files
5435 Option -q/--quiet hides untracked (unknown and ignored) files
5436 unless explicitly requested with -u/--unknown or -i/--ignored.
5436 unless explicitly requested with -u/--unknown or -i/--ignored.
5437
5437
5438 .. note::
5438 .. note::
5439 status may appear to disagree with diff if permissions have
5439 status may appear to disagree with diff if permissions have
5440 changed or a merge has occurred. The standard diff format does
5440 changed or a merge has occurred. The standard diff format does
5441 not report permission changes and diff only reports changes
5441 not report permission changes and diff only reports changes
5442 relative to one merge parent.
5442 relative to one merge parent.
5443
5443
5444 If one revision is given, it is used as the base revision.
5444 If one revision is given, it is used as the base revision.
5445 If two revisions are given, the differences between them are
5445 If two revisions are given, the differences between them are
5446 shown. The --change option can also be used as a shortcut to list
5446 shown. The --change option can also be used as a shortcut to list
5447 the changed files of a revision from its first parent.
5447 the changed files of a revision from its first parent.
5448
5448
5449 The codes used to show the status of files are::
5449 The codes used to show the status of files are::
5450
5450
5451 M = modified
5451 M = modified
5452 A = added
5452 A = added
5453 R = removed
5453 R = removed
5454 C = clean
5454 C = clean
5455 ! = missing (deleted by non-hg command, but still tracked)
5455 ! = missing (deleted by non-hg command, but still tracked)
5456 ? = not tracked
5456 ? = not tracked
5457 I = ignored
5457 I = ignored
5458 = origin of the previous file listed as A (added)
5458 = origin of the previous file listed as A (added)
5459
5459
5460 .. container:: verbose
5460 .. container:: verbose
5461
5461
5462 Examples:
5462 Examples:
5463
5463
5464 - show changes in the working directory relative to a
5464 - show changes in the working directory relative to a
5465 changeset::
5465 changeset::
5466
5466
5467 hg status --rev 9353
5467 hg status --rev 9353
5468
5468
5469 - show all changes including copies in an existing changeset::
5469 - show all changes including copies in an existing changeset::
5470
5470
5471 hg status --copies --change 9353
5471 hg status --copies --change 9353
5472
5472
5473 - get a NUL separated list of added files, suitable for xargs::
5473 - get a NUL separated list of added files, suitable for xargs::
5474
5474
5475 hg status -an0
5475 hg status -an0
5476
5476
5477 Returns 0 on success.
5477 Returns 0 on success.
5478 """
5478 """
5479
5479
5480 revs = opts.get('rev')
5480 revs = opts.get('rev')
5481 change = opts.get('change')
5481 change = opts.get('change')
5482
5482
5483 if revs and change:
5483 if revs and change:
5484 msg = _('cannot specify --rev and --change at the same time')
5484 msg = _('cannot specify --rev and --change at the same time')
5485 raise util.Abort(msg)
5485 raise util.Abort(msg)
5486 elif change:
5486 elif change:
5487 node2 = scmutil.revsingle(repo, change, None).node()
5487 node2 = scmutil.revsingle(repo, change, None).node()
5488 node1 = repo[node2].p1().node()
5488 node1 = repo[node2].p1().node()
5489 else:
5489 else:
5490 node1, node2 = scmutil.revpair(repo, revs)
5490 node1, node2 = scmutil.revpair(repo, revs)
5491
5491
5492 cwd = (pats and repo.getcwd()) or ''
5492 cwd = (pats and repo.getcwd()) or ''
5493 end = opts.get('print0') and '\0' or '\n'
5493 end = opts.get('print0') and '\0' or '\n'
5494 copy = {}
5494 copy = {}
5495 states = 'modified added removed deleted unknown ignored clean'.split()
5495 states = 'modified added removed deleted unknown ignored clean'.split()
5496 show = [k for k in states if opts.get(k)]
5496 show = [k for k in states if opts.get(k)]
5497 if opts.get('all'):
5497 if opts.get('all'):
5498 show += ui.quiet and (states[:4] + ['clean']) or states
5498 show += ui.quiet and (states[:4] + ['clean']) or states
5499 if not show:
5499 if not show:
5500 show = ui.quiet and states[:4] or states[:5]
5500 show = ui.quiet and states[:4] or states[:5]
5501
5501
5502 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5502 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5503 'ignored' in show, 'clean' in show, 'unknown' in show,
5503 'ignored' in show, 'clean' in show, 'unknown' in show,
5504 opts.get('subrepos'))
5504 opts.get('subrepos'))
5505 changestates = zip(states, 'MAR!?IC', stat)
5505 changestates = zip(states, 'MAR!?IC', stat)
5506
5506
5507 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5507 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5508 copy = copies.pathcopies(repo[node1], repo[node2])
5508 copy = copies.pathcopies(repo[node1], repo[node2])
5509
5509
5510 fm = ui.formatter('status', opts)
5510 fm = ui.formatter('status', opts)
5511 fmt = '%s' + end
5511 fmt = '%s' + end
5512 showchar = not opts.get('no_status')
5512 showchar = not opts.get('no_status')
5513
5513
5514 for state, char, files in changestates:
5514 for state, char, files in changestates:
5515 if state in show:
5515 if state in show:
5516 label = 'status.' + state
5516 label = 'status.' + state
5517 for f in files:
5517 for f in files:
5518 fm.startitem()
5518 fm.startitem()
5519 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5519 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5520 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5520 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5521 if f in copy:
5521 if f in copy:
5522 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5522 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5523 label='status.copied')
5523 label='status.copied')
5524 fm.end()
5524 fm.end()
5525
5525
5526 @command('^summary|sum',
5526 @command('^summary|sum',
5527 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5527 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5528 def summary(ui, repo, **opts):
5528 def summary(ui, repo, **opts):
5529 """summarize working directory state
5529 """summarize working directory state
5530
5530
5531 This generates a brief summary of the working directory state,
5531 This generates a brief summary of the working directory state,
5532 including parents, branch, commit status, and available updates.
5532 including parents, branch, commit status, and available updates.
5533
5533
5534 With the --remote option, this will check the default paths for
5534 With the --remote option, this will check the default paths for
5535 incoming and outgoing changes. This can be time-consuming.
5535 incoming and outgoing changes. This can be time-consuming.
5536
5536
5537 Returns 0 on success.
5537 Returns 0 on success.
5538 """
5538 """
5539
5539
5540 ctx = repo[None]
5540 ctx = repo[None]
5541 parents = ctx.parents()
5541 parents = ctx.parents()
5542 pnode = parents[0].node()
5542 pnode = parents[0].node()
5543 marks = []
5543 marks = []
5544
5544
5545 for p in parents:
5545 for p in parents:
5546 # label with log.changeset (instead of log.parent) since this
5546 # label with log.changeset (instead of log.parent) since this
5547 # shows a working directory parent *changeset*:
5547 # shows a working directory parent *changeset*:
5548 # i18n: column positioning for "hg summary"
5548 # i18n: column positioning for "hg summary"
5549 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5549 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5550 label='log.changeset changeset.%s' % p.phasestr())
5550 label='log.changeset changeset.%s' % p.phasestr())
5551 ui.write(' '.join(p.tags()), label='log.tag')
5551 ui.write(' '.join(p.tags()), label='log.tag')
5552 if p.bookmarks():
5552 if p.bookmarks():
5553 marks.extend(p.bookmarks())
5553 marks.extend(p.bookmarks())
5554 if p.rev() == -1:
5554 if p.rev() == -1:
5555 if not len(repo):
5555 if not len(repo):
5556 ui.write(_(' (empty repository)'))
5556 ui.write(_(' (empty repository)'))
5557 else:
5557 else:
5558 ui.write(_(' (no revision checked out)'))
5558 ui.write(_(' (no revision checked out)'))
5559 ui.write('\n')
5559 ui.write('\n')
5560 if p.description():
5560 if p.description():
5561 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5561 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5562 label='log.summary')
5562 label='log.summary')
5563
5563
5564 branch = ctx.branch()
5564 branch = ctx.branch()
5565 bheads = repo.branchheads(branch)
5565 bheads = repo.branchheads(branch)
5566 # i18n: column positioning for "hg summary"
5566 # i18n: column positioning for "hg summary"
5567 m = _('branch: %s\n') % branch
5567 m = _('branch: %s\n') % branch
5568 if branch != 'default':
5568 if branch != 'default':
5569 ui.write(m, label='log.branch')
5569 ui.write(m, label='log.branch')
5570 else:
5570 else:
5571 ui.status(m, label='log.branch')
5571 ui.status(m, label='log.branch')
5572
5572
5573 if marks:
5573 if marks:
5574 current = repo._bookmarkcurrent
5574 current = repo._bookmarkcurrent
5575 # i18n: column positioning for "hg summary"
5575 # i18n: column positioning for "hg summary"
5576 ui.write(_('bookmarks:'), label='log.bookmark')
5576 ui.write(_('bookmarks:'), label='log.bookmark')
5577 if current is not None:
5577 if current is not None:
5578 try:
5578 try:
5579 marks.remove(current)
5579 marks.remove(current)
5580 ui.write(' *' + current, label='bookmarks.current')
5580 ui.write(' *' + current, label='bookmarks.current')
5581 except ValueError:
5581 except ValueError:
5582 # current bookmark not in parent ctx marks
5582 # current bookmark not in parent ctx marks
5583 pass
5583 pass
5584 for m in marks:
5584 for m in marks:
5585 ui.write(' ' + m, label='log.bookmark')
5585 ui.write(' ' + m, label='log.bookmark')
5586 ui.write('\n', label='log.bookmark')
5586 ui.write('\n', label='log.bookmark')
5587
5587
5588 st = list(repo.status(unknown=True))[:6]
5588 st = list(repo.status(unknown=True))[:6]
5589
5589
5590 c = repo.dirstate.copies()
5590 c = repo.dirstate.copies()
5591 copied, renamed = [], []
5591 copied, renamed = [], []
5592 for d, s in c.iteritems():
5592 for d, s in c.iteritems():
5593 if s in st[2]:
5593 if s in st[2]:
5594 st[2].remove(s)
5594 st[2].remove(s)
5595 renamed.append(d)
5595 renamed.append(d)
5596 else:
5596 else:
5597 copied.append(d)
5597 copied.append(d)
5598 if d in st[1]:
5598 if d in st[1]:
5599 st[1].remove(d)
5599 st[1].remove(d)
5600 st.insert(3, renamed)
5600 st.insert(3, renamed)
5601 st.insert(4, copied)
5601 st.insert(4, copied)
5602
5602
5603 ms = mergemod.mergestate(repo)
5603 ms = mergemod.mergestate(repo)
5604 st.append([f for f in ms if ms[f] == 'u'])
5604 st.append([f for f in ms if ms[f] == 'u'])
5605
5605
5606 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5606 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5607 st.append(subs)
5607 st.append(subs)
5608
5608
5609 labels = [ui.label(_('%d modified'), 'status.modified'),
5609 labels = [ui.label(_('%d modified'), 'status.modified'),
5610 ui.label(_('%d added'), 'status.added'),
5610 ui.label(_('%d added'), 'status.added'),
5611 ui.label(_('%d removed'), 'status.removed'),
5611 ui.label(_('%d removed'), 'status.removed'),
5612 ui.label(_('%d renamed'), 'status.copied'),
5612 ui.label(_('%d renamed'), 'status.copied'),
5613 ui.label(_('%d copied'), 'status.copied'),
5613 ui.label(_('%d copied'), 'status.copied'),
5614 ui.label(_('%d deleted'), 'status.deleted'),
5614 ui.label(_('%d deleted'), 'status.deleted'),
5615 ui.label(_('%d unknown'), 'status.unknown'),
5615 ui.label(_('%d unknown'), 'status.unknown'),
5616 ui.label(_('%d ignored'), 'status.ignored'),
5616 ui.label(_('%d ignored'), 'status.ignored'),
5617 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5617 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5618 ui.label(_('%d subrepos'), 'status.modified')]
5618 ui.label(_('%d subrepos'), 'status.modified')]
5619 t = []
5619 t = []
5620 for s, l in zip(st, labels):
5620 for s, l in zip(st, labels):
5621 if s:
5621 if s:
5622 t.append(l % len(s))
5622 t.append(l % len(s))
5623
5623
5624 t = ', '.join(t)
5624 t = ', '.join(t)
5625 cleanworkdir = False
5625 cleanworkdir = False
5626
5626
5627 if len(parents) > 1:
5627 if len(parents) > 1:
5628 t += _(' (merge)')
5628 t += _(' (merge)')
5629 elif branch != parents[0].branch():
5629 elif branch != parents[0].branch():
5630 t += _(' (new branch)')
5630 t += _(' (new branch)')
5631 elif (parents[0].closesbranch() and
5631 elif (parents[0].closesbranch() and
5632 pnode in repo.branchheads(branch, closed=True)):
5632 pnode in repo.branchheads(branch, closed=True)):
5633 t += _(' (head closed)')
5633 t += _(' (head closed)')
5634 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5634 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5635 t += _(' (clean)')
5635 t += _(' (clean)')
5636 cleanworkdir = True
5636 cleanworkdir = True
5637 elif pnode not in bheads:
5637 elif pnode not in bheads:
5638 t += _(' (new branch head)')
5638 t += _(' (new branch head)')
5639
5639
5640 if cleanworkdir:
5640 if cleanworkdir:
5641 # i18n: column positioning for "hg summary"
5641 # i18n: column positioning for "hg summary"
5642 ui.status(_('commit: %s\n') % t.strip())
5642 ui.status(_('commit: %s\n') % t.strip())
5643 else:
5643 else:
5644 # i18n: column positioning for "hg summary"
5644 # i18n: column positioning for "hg summary"
5645 ui.write(_('commit: %s\n') % t.strip())
5645 ui.write(_('commit: %s\n') % t.strip())
5646
5646
5647 # all ancestors of branch heads - all ancestors of parent = new csets
5647 # all ancestors of branch heads - all ancestors of parent = new csets
5648 new = [0] * len(repo)
5648 new = [0] * len(repo)
5649 cl = repo.changelog
5649 cl = repo.changelog
5650 for a in [cl.rev(n) for n in bheads]:
5650 for a in [cl.rev(n) for n in bheads]:
5651 new[a] = 1
5651 new[a] = 1
5652 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5652 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5653 new[a] = 1
5653 new[a] = 1
5654 for a in [p.rev() for p in parents]:
5654 for a in [p.rev() for p in parents]:
5655 if a >= 0:
5655 if a >= 0:
5656 new[a] = 0
5656 new[a] = 0
5657 for a in cl.ancestors([p.rev() for p in parents]):
5657 for a in cl.ancestors([p.rev() for p in parents]):
5658 new[a] = 0
5658 new[a] = 0
5659 new = sum(new)
5659 new = sum(new)
5660
5660
5661 if new == 0:
5661 if new == 0:
5662 # i18n: column positioning for "hg summary"
5662 # i18n: column positioning for "hg summary"
5663 ui.status(_('update: (current)\n'))
5663 ui.status(_('update: (current)\n'))
5664 elif pnode not in bheads:
5664 elif pnode not in bheads:
5665 # i18n: column positioning for "hg summary"
5665 # i18n: column positioning for "hg summary"
5666 ui.write(_('update: %d new changesets (update)\n') % new)
5666 ui.write(_('update: %d new changesets (update)\n') % new)
5667 else:
5667 else:
5668 # i18n: column positioning for "hg summary"
5668 # i18n: column positioning for "hg summary"
5669 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5669 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5670 (new, len(bheads)))
5670 (new, len(bheads)))
5671
5671
5672 if opts.get('remote'):
5672 if opts.get('remote'):
5673 t = []
5673 t = []
5674 source, branches = hg.parseurl(ui.expandpath('default'))
5674 source, branches = hg.parseurl(ui.expandpath('default'))
5675 other = hg.peer(repo, {}, source)
5675 other = hg.peer(repo, {}, source)
5676 revs, checkout = hg.addbranchrevs(repo, other, branches,
5676 revs, checkout = hg.addbranchrevs(repo, other, branches,
5677 opts.get('rev'))
5677 opts.get('rev'))
5678 ui.debug('comparing with %s\n' % util.hidepassword(source))
5678 ui.debug('comparing with %s\n' % util.hidepassword(source))
5679 repo.ui.pushbuffer()
5679 repo.ui.pushbuffer()
5680 commoninc = discovery.findcommonincoming(repo, other)
5680 commoninc = discovery.findcommonincoming(repo, other)
5681 _common, incoming, _rheads = commoninc
5681 _common, incoming, _rheads = commoninc
5682 repo.ui.popbuffer()
5682 repo.ui.popbuffer()
5683 if incoming:
5683 if incoming:
5684 t.append(_('1 or more incoming'))
5684 t.append(_('1 or more incoming'))
5685
5685
5686 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5686 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5687 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5687 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5688 if source != dest:
5688 if source != dest:
5689 other = hg.peer(repo, {}, dest)
5689 other = hg.peer(repo, {}, dest)
5690 commoninc = None
5690 commoninc = None
5691 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5691 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5692 repo.ui.pushbuffer()
5692 repo.ui.pushbuffer()
5693 outgoing = discovery.findcommonoutgoing(repo, other,
5693 outgoing = discovery.findcommonoutgoing(repo, other,
5694 commoninc=commoninc)
5694 commoninc=commoninc)
5695 repo.ui.popbuffer()
5695 repo.ui.popbuffer()
5696 o = outgoing.missing
5696 o = outgoing.missing
5697 if o:
5697 if o:
5698 t.append(_('%d outgoing') % len(o))
5698 t.append(_('%d outgoing') % len(o))
5699 if 'bookmarks' in other.listkeys('namespaces'):
5699 if 'bookmarks' in other.listkeys('namespaces'):
5700 lmarks = repo.listkeys('bookmarks')
5700 lmarks = repo.listkeys('bookmarks')
5701 rmarks = other.listkeys('bookmarks')
5701 rmarks = other.listkeys('bookmarks')
5702 diff = set(rmarks) - set(lmarks)
5702 diff = set(rmarks) - set(lmarks)
5703 if len(diff) > 0:
5703 if len(diff) > 0:
5704 t.append(_('%d incoming bookmarks') % len(diff))
5704 t.append(_('%d incoming bookmarks') % len(diff))
5705 diff = set(lmarks) - set(rmarks)
5705 diff = set(lmarks) - set(rmarks)
5706 if len(diff) > 0:
5706 if len(diff) > 0:
5707 t.append(_('%d outgoing bookmarks') % len(diff))
5707 t.append(_('%d outgoing bookmarks') % len(diff))
5708
5708
5709 if t:
5709 if t:
5710 # i18n: column positioning for "hg summary"
5710 # i18n: column positioning for "hg summary"
5711 ui.write(_('remote: %s\n') % (', '.join(t)))
5711 ui.write(_('remote: %s\n') % (', '.join(t)))
5712 else:
5712 else:
5713 # i18n: column positioning for "hg summary"
5713 # i18n: column positioning for "hg summary"
5714 ui.status(_('remote: (synced)\n'))
5714 ui.status(_('remote: (synced)\n'))
5715
5715
5716 @command('tag',
5716 @command('tag',
5717 [('f', 'force', None, _('force tag')),
5717 [('f', 'force', None, _('force tag')),
5718 ('l', 'local', None, _('make the tag local')),
5718 ('l', 'local', None, _('make the tag local')),
5719 ('r', 'rev', '', _('revision to tag'), _('REV')),
5719 ('r', 'rev', '', _('revision to tag'), _('REV')),
5720 ('', 'remove', None, _('remove a tag')),
5720 ('', 'remove', None, _('remove a tag')),
5721 # -l/--local is already there, commitopts cannot be used
5721 # -l/--local is already there, commitopts cannot be used
5722 ('e', 'edit', None, _('edit commit message')),
5722 ('e', 'edit', None, _('edit commit message')),
5723 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5723 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5724 ] + commitopts2,
5724 ] + commitopts2,
5725 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5725 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5726 def tag(ui, repo, name1, *names, **opts):
5726 def tag(ui, repo, name1, *names, **opts):
5727 """add one or more tags for the current or given revision
5727 """add one or more tags for the current or given revision
5728
5728
5729 Name a particular revision using <name>.
5729 Name a particular revision using <name>.
5730
5730
5731 Tags are used to name particular revisions of the repository and are
5731 Tags are used to name particular revisions of the repository and are
5732 very useful to compare different revisions, to go back to significant
5732 very useful to compare different revisions, to go back to significant
5733 earlier versions or to mark branch points as releases, etc. Changing
5733 earlier versions or to mark branch points as releases, etc. Changing
5734 an existing tag is normally disallowed; use -f/--force to override.
5734 an existing tag is normally disallowed; use -f/--force to override.
5735
5735
5736 If no revision is given, the parent of the working directory is
5736 If no revision is given, the parent of the working directory is
5737 used, or tip if no revision is checked out.
5737 used, or tip if no revision is checked out.
5738
5738
5739 To facilitate version control, distribution, and merging of tags,
5739 To facilitate version control, distribution, and merging of tags,
5740 they are stored as a file named ".hgtags" which is managed similarly
5740 they are stored as a file named ".hgtags" which is managed similarly
5741 to other project files and can be hand-edited if necessary. This
5741 to other project files and can be hand-edited if necessary. This
5742 also means that tagging creates a new commit. The file
5742 also means that tagging creates a new commit. The file
5743 ".hg/localtags" is used for local tags (not shared among
5743 ".hg/localtags" is used for local tags (not shared among
5744 repositories).
5744 repositories).
5745
5745
5746 Tag commits are usually made at the head of a branch. If the parent
5746 Tag commits are usually made at the head of a branch. If the parent
5747 of the working directory is not a branch head, :hg:`tag` aborts; use
5747 of the working directory is not a branch head, :hg:`tag` aborts; use
5748 -f/--force to force the tag commit to be based on a non-head
5748 -f/--force to force the tag commit to be based on a non-head
5749 changeset.
5749 changeset.
5750
5750
5751 See :hg:`help dates` for a list of formats valid for -d/--date.
5751 See :hg:`help dates` for a list of formats valid for -d/--date.
5752
5752
5753 Since tag names have priority over branch names during revision
5753 Since tag names have priority over branch names during revision
5754 lookup, using an existing branch name as a tag name is discouraged.
5754 lookup, using an existing branch name as a tag name is discouraged.
5755
5755
5756 Returns 0 on success.
5756 Returns 0 on success.
5757 """
5757 """
5758 wlock = lock = None
5758 wlock = lock = None
5759 try:
5759 try:
5760 wlock = repo.wlock()
5760 wlock = repo.wlock()
5761 lock = repo.lock()
5761 lock = repo.lock()
5762 rev_ = "."
5762 rev_ = "."
5763 names = [t.strip() for t in (name1,) + names]
5763 names = [t.strip() for t in (name1,) + names]
5764 if len(names) != len(set(names)):
5764 if len(names) != len(set(names)):
5765 raise util.Abort(_('tag names must be unique'))
5765 raise util.Abort(_('tag names must be unique'))
5766 for n in names:
5766 for n in names:
5767 scmutil.checknewlabel(repo, n, 'tag')
5767 scmutil.checknewlabel(repo, n, 'tag')
5768 if not n:
5768 if not n:
5769 raise util.Abort(_('tag names cannot consist entirely of '
5769 raise util.Abort(_('tag names cannot consist entirely of '
5770 'whitespace'))
5770 'whitespace'))
5771 if opts.get('rev') and opts.get('remove'):
5771 if opts.get('rev') and opts.get('remove'):
5772 raise util.Abort(_("--rev and --remove are incompatible"))
5772 raise util.Abort(_("--rev and --remove are incompatible"))
5773 if opts.get('rev'):
5773 if opts.get('rev'):
5774 rev_ = opts['rev']
5774 rev_ = opts['rev']
5775 message = opts.get('message')
5775 message = opts.get('message')
5776 if opts.get('remove'):
5776 if opts.get('remove'):
5777 expectedtype = opts.get('local') and 'local' or 'global'
5777 expectedtype = opts.get('local') and 'local' or 'global'
5778 for n in names:
5778 for n in names:
5779 if not repo.tagtype(n):
5779 if not repo.tagtype(n):
5780 raise util.Abort(_("tag '%s' does not exist") % n)
5780 raise util.Abort(_("tag '%s' does not exist") % n)
5781 if repo.tagtype(n) != expectedtype:
5781 if repo.tagtype(n) != expectedtype:
5782 if expectedtype == 'global':
5782 if expectedtype == 'global':
5783 raise util.Abort(_("tag '%s' is not a global tag") % n)
5783 raise util.Abort(_("tag '%s' is not a global tag") % n)
5784 else:
5784 else:
5785 raise util.Abort(_("tag '%s' is not a local tag") % n)
5785 raise util.Abort(_("tag '%s' is not a local tag") % n)
5786 rev_ = nullid
5786 rev_ = nullid
5787 if not message:
5787 if not message:
5788 # we don't translate commit messages
5788 # we don't translate commit messages
5789 message = 'Removed tag %s' % ', '.join(names)
5789 message = 'Removed tag %s' % ', '.join(names)
5790 elif not opts.get('force'):
5790 elif not opts.get('force'):
5791 for n in names:
5791 for n in names:
5792 if n in repo.tags():
5792 if n in repo.tags():
5793 raise util.Abort(_("tag '%s' already exists "
5793 raise util.Abort(_("tag '%s' already exists "
5794 "(use -f to force)") % n)
5794 "(use -f to force)") % n)
5795 if not opts.get('local'):
5795 if not opts.get('local'):
5796 p1, p2 = repo.dirstate.parents()
5796 p1, p2 = repo.dirstate.parents()
5797 if p2 != nullid:
5797 if p2 != nullid:
5798 raise util.Abort(_('uncommitted merge'))
5798 raise util.Abort(_('uncommitted merge'))
5799 bheads = repo.branchheads()
5799 bheads = repo.branchheads()
5800 if not opts.get('force') and bheads and p1 not in bheads:
5800 if not opts.get('force') and bheads and p1 not in bheads:
5801 raise util.Abort(_('not at a branch head (use -f to force)'))
5801 raise util.Abort(_('not at a branch head (use -f to force)'))
5802 r = scmutil.revsingle(repo, rev_).node()
5802 r = scmutil.revsingle(repo, rev_).node()
5803
5803
5804 if not message:
5804 if not message:
5805 # we don't translate commit messages
5805 # we don't translate commit messages
5806 message = ('Added tag %s for changeset %s' %
5806 message = ('Added tag %s for changeset %s' %
5807 (', '.join(names), short(r)))
5807 (', '.join(names), short(r)))
5808
5808
5809 date = opts.get('date')
5809 date = opts.get('date')
5810 if date:
5810 if date:
5811 date = util.parsedate(date)
5811 date = util.parsedate(date)
5812
5812
5813 if opts.get('edit'):
5813 if opts.get('edit'):
5814 message = ui.edit(message, ui.username())
5814 message = ui.edit(message, ui.username())
5815
5815
5816 # don't allow tagging the null rev
5816 # don't allow tagging the null rev
5817 if (not opts.get('remove') and
5817 if (not opts.get('remove') and
5818 scmutil.revsingle(repo, rev_).rev() == nullrev):
5818 scmutil.revsingle(repo, rev_).rev() == nullrev):
5819 raise util.Abort(_("null revision specified"))
5819 raise util.Abort(_("null revision specified"))
5820
5820
5821 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5821 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5822 finally:
5822 finally:
5823 release(lock, wlock)
5823 release(lock, wlock)
5824
5824
5825 @command('tags', [], '')
5825 @command('tags', [], '')
5826 def tags(ui, repo, **opts):
5826 def tags(ui, repo, **opts):
5827 """list repository tags
5827 """list repository tags
5828
5828
5829 This lists both regular and local tags. When the -v/--verbose
5829 This lists both regular and local tags. When the -v/--verbose
5830 switch is used, a third column "local" is printed for local tags.
5830 switch is used, a third column "local" is printed for local tags.
5831
5831
5832 Returns 0 on success.
5832 Returns 0 on success.
5833 """
5833 """
5834
5834
5835 fm = ui.formatter('tags', opts)
5835 fm = ui.formatter('tags', opts)
5836 hexfunc = ui.debugflag and hex or short
5836 hexfunc = ui.debugflag and hex or short
5837 tagtype = ""
5837 tagtype = ""
5838
5838
5839 for t, n in reversed(repo.tagslist()):
5839 for t, n in reversed(repo.tagslist()):
5840 hn = hexfunc(n)
5840 hn = hexfunc(n)
5841 label = 'tags.normal'
5841 label = 'tags.normal'
5842 tagtype = ''
5842 tagtype = ''
5843 if repo.tagtype(t) == 'local':
5843 if repo.tagtype(t) == 'local':
5844 label = 'tags.local'
5844 label = 'tags.local'
5845 tagtype = 'local'
5845 tagtype = 'local'
5846
5846
5847 fm.startitem()
5847 fm.startitem()
5848 fm.write('tag', '%s', t, label=label)
5848 fm.write('tag', '%s', t, label=label)
5849 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5849 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5850 fm.condwrite(not ui.quiet, 'rev id', fmt,
5850 fm.condwrite(not ui.quiet, 'rev id', fmt,
5851 repo.changelog.rev(n), hn, label=label)
5851 repo.changelog.rev(n), hn, label=label)
5852 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5852 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5853 tagtype, label=label)
5853 tagtype, label=label)
5854 fm.plain('\n')
5854 fm.plain('\n')
5855 fm.end()
5855 fm.end()
5856
5856
5857 @command('tip',
5857 @command('tip',
5858 [('p', 'patch', None, _('show patch')),
5858 [('p', 'patch', None, _('show patch')),
5859 ('g', 'git', None, _('use git extended diff format')),
5859 ('g', 'git', None, _('use git extended diff format')),
5860 ] + templateopts,
5860 ] + templateopts,
5861 _('[-p] [-g]'))
5861 _('[-p] [-g]'))
5862 def tip(ui, repo, **opts):
5862 def tip(ui, repo, **opts):
5863 """show the tip revision
5863 """show the tip revision
5864
5864
5865 The tip revision (usually just called the tip) is the changeset
5865 The tip revision (usually just called the tip) is the changeset
5866 most recently added to the repository (and therefore the most
5866 most recently added to the repository (and therefore the most
5867 recently changed head).
5867 recently changed head).
5868
5868
5869 If you have just made a commit, that commit will be the tip. If
5869 If you have just made a commit, that commit will be the tip. If
5870 you have just pulled changes from another repository, the tip of
5870 you have just pulled changes from another repository, the tip of
5871 that repository becomes the current tip. The "tip" tag is special
5871 that repository becomes the current tip. The "tip" tag is special
5872 and cannot be renamed or assigned to a different changeset.
5872 and cannot be renamed or assigned to a different changeset.
5873
5873
5874 Returns 0 on success.
5874 Returns 0 on success.
5875 """
5875 """
5876 displayer = cmdutil.show_changeset(ui, repo, opts)
5876 displayer = cmdutil.show_changeset(ui, repo, opts)
5877 displayer.show(repo['tip'])
5877 displayer.show(repo['tip'])
5878 displayer.close()
5878 displayer.close()
5879
5879
5880 @command('unbundle',
5880 @command('unbundle',
5881 [('u', 'update', None,
5881 [('u', 'update', None,
5882 _('update to new branch head if changesets were unbundled'))],
5882 _('update to new branch head if changesets were unbundled'))],
5883 _('[-u] FILE...'))
5883 _('[-u] FILE...'))
5884 def unbundle(ui, repo, fname1, *fnames, **opts):
5884 def unbundle(ui, repo, fname1, *fnames, **opts):
5885 """apply one or more changegroup files
5885 """apply one or more changegroup files
5886
5886
5887 Apply one or more compressed changegroup files generated by the
5887 Apply one or more compressed changegroup files generated by the
5888 bundle command.
5888 bundle command.
5889
5889
5890 Returns 0 on success, 1 if an update has unresolved files.
5890 Returns 0 on success, 1 if an update has unresolved files.
5891 """
5891 """
5892 fnames = (fname1,) + fnames
5892 fnames = (fname1,) + fnames
5893
5893
5894 lock = repo.lock()
5894 lock = repo.lock()
5895 wc = repo['.']
5895 wc = repo['.']
5896 try:
5896 try:
5897 for fname in fnames:
5897 for fname in fnames:
5898 f = hg.openpath(ui, fname)
5898 f = hg.openpath(ui, fname)
5899 gen = changegroup.readbundle(f, fname)
5899 gen = changegroup.readbundle(f, fname)
5900 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5900 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5901 finally:
5901 finally:
5902 lock.release()
5902 lock.release()
5903 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5903 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5904 return postincoming(ui, repo, modheads, opts.get('update'), None)
5904 return postincoming(ui, repo, modheads, opts.get('update'), None)
5905
5905
5906 @command('^update|up|checkout|co',
5906 @command('^update|up|checkout|co',
5907 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5907 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5908 ('c', 'check', None,
5908 ('c', 'check', None,
5909 _('update across branches if no uncommitted changes')),
5909 _('update across branches if no uncommitted changes')),
5910 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5910 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5911 ('r', 'rev', '', _('revision'), _('REV'))],
5911 ('r', 'rev', '', _('revision'), _('REV'))],
5912 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5912 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5913 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5913 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5914 """update working directory (or switch revisions)
5914 """update working directory (or switch revisions)
5915
5915
5916 Update the repository's working directory to the specified
5916 Update the repository's working directory to the specified
5917 changeset. If no changeset is specified, update to the tip of the
5917 changeset. If no changeset is specified, update to the tip of the
5918 current named branch and move the current bookmark (see :hg:`help
5918 current named branch and move the current bookmark (see :hg:`help
5919 bookmarks`).
5919 bookmarks`).
5920
5920
5921 Update sets the working directory's parent revision to the specified
5921 Update sets the working directory's parent revision to the specified
5922 changeset (see :hg:`help parents`).
5922 changeset (see :hg:`help parents`).
5923
5923
5924 If the changeset is not a descendant or ancestor of the working
5924 If the changeset is not a descendant or ancestor of the working
5925 directory's parent, the update is aborted. With the -c/--check
5925 directory's parent, the update is aborted. With the -c/--check
5926 option, the working directory is checked for uncommitted changes; if
5926 option, the working directory is checked for uncommitted changes; if
5927 none are found, the working directory is updated to the specified
5927 none are found, the working directory is updated to the specified
5928 changeset.
5928 changeset.
5929
5929
5930 .. container:: verbose
5930 .. container:: verbose
5931
5931
5932 The following rules apply when the working directory contains
5932 The following rules apply when the working directory contains
5933 uncommitted changes:
5933 uncommitted changes:
5934
5934
5935 1. If neither -c/--check nor -C/--clean is specified, and if
5935 1. If neither -c/--check nor -C/--clean is specified, and if
5936 the requested changeset is an ancestor or descendant of
5936 the requested changeset is an ancestor or descendant of
5937 the working directory's parent, the uncommitted changes
5937 the working directory's parent, the uncommitted changes
5938 are merged into the requested changeset and the merged
5938 are merged into the requested changeset and the merged
5939 result is left uncommitted. If the requested changeset is
5939 result is left uncommitted. If the requested changeset is
5940 not an ancestor or descendant (that is, it is on another
5940 not an ancestor or descendant (that is, it is on another
5941 branch), the update is aborted and the uncommitted changes
5941 branch), the update is aborted and the uncommitted changes
5942 are preserved.
5942 are preserved.
5943
5943
5944 2. With the -c/--check option, the update is aborted and the
5944 2. With the -c/--check option, the update is aborted and the
5945 uncommitted changes are preserved.
5945 uncommitted changes are preserved.
5946
5946
5947 3. With the -C/--clean option, uncommitted changes are discarded and
5947 3. With the -C/--clean option, uncommitted changes are discarded and
5948 the working directory is updated to the requested changeset.
5948 the working directory is updated to the requested changeset.
5949
5949
5950 To cancel an uncommitted merge (and lose your changes), use
5950 To cancel an uncommitted merge (and lose your changes), use
5951 :hg:`update --clean .`.
5951 :hg:`update --clean .`.
5952
5952
5953 Use null as the changeset to remove the working directory (like
5953 Use null as the changeset to remove the working directory (like
5954 :hg:`clone -U`).
5954 :hg:`clone -U`).
5955
5955
5956 If you want to revert just one file to an older revision, use
5956 If you want to revert just one file to an older revision, use
5957 :hg:`revert [-r REV] NAME`.
5957 :hg:`revert [-r REV] NAME`.
5958
5958
5959 See :hg:`help dates` for a list of formats valid for -d/--date.
5959 See :hg:`help dates` for a list of formats valid for -d/--date.
5960
5960
5961 Returns 0 on success, 1 if there are unresolved files.
5961 Returns 0 on success, 1 if there are unresolved files.
5962 """
5962 """
5963 if rev and node:
5963 if rev and node:
5964 raise util.Abort(_("please specify just one revision"))
5964 raise util.Abort(_("please specify just one revision"))
5965
5965
5966 if rev is None or rev == '':
5966 if rev is None or rev == '':
5967 rev = node
5967 rev = node
5968
5968
5969 # with no argument, we also move the current bookmark, if any
5969 # with no argument, we also move the current bookmark, if any
5970 movemarkfrom = None
5970 movemarkfrom = None
5971 if rev is None:
5971 if rev is None:
5972 curmark = repo._bookmarkcurrent
5972 curmark = repo._bookmarkcurrent
5973 if bookmarks.iscurrent(repo):
5973 if bookmarks.iscurrent(repo):
5974 movemarkfrom = repo['.'].node()
5974 movemarkfrom = repo['.'].node()
5975 elif curmark:
5975 elif curmark:
5976 ui.status(_("updating to active bookmark %s\n") % curmark)
5976 ui.status(_("updating to active bookmark %s\n") % curmark)
5977 rev = curmark
5977 rev = curmark
5978
5978
5979 # if we defined a bookmark, we have to remember the original bookmark name
5979 # if we defined a bookmark, we have to remember the original bookmark name
5980 brev = rev
5980 brev = rev
5981 rev = scmutil.revsingle(repo, rev, rev).rev()
5981 rev = scmutil.revsingle(repo, rev, rev).rev()
5982
5982
5983 if check and clean:
5983 if check and clean:
5984 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5984 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5985
5985
5986 if date:
5986 if date:
5987 if rev is not None:
5987 if rev is not None:
5988 raise util.Abort(_("you can't specify a revision and a date"))
5988 raise util.Abort(_("you can't specify a revision and a date"))
5989 rev = cmdutil.finddate(ui, repo, date)
5989 rev = cmdutil.finddate(ui, repo, date)
5990
5990
5991 if check:
5991 if check:
5992 c = repo[None]
5992 c = repo[None]
5993 if c.dirty(merge=False, branch=False, missing=True):
5993 if c.dirty(merge=False, branch=False, missing=True):
5994 raise util.Abort(_("uncommitted local changes"))
5994 raise util.Abort(_("uncommitted local changes"))
5995 if rev is None:
5995 if rev is None:
5996 rev = repo[repo[None].branch()].rev()
5996 rev = repo[repo[None].branch()].rev()
5997 mergemod._checkunknown(repo, repo[None], repo[rev])
5997 mergemod._checkunknown(repo, repo[None], repo[rev])
5998
5998
5999 if clean:
5999 if clean:
6000 ret = hg.clean(repo, rev)
6000 ret = hg.clean(repo, rev)
6001 else:
6001 else:
6002 ret = hg.update(repo, rev)
6002 ret = hg.update(repo, rev)
6003
6003
6004 if not ret and movemarkfrom:
6004 if not ret and movemarkfrom:
6005 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6005 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6006 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6006 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6007 elif brev in repo._bookmarks:
6007 elif brev in repo._bookmarks:
6008 bookmarks.setcurrent(repo, brev)
6008 bookmarks.setcurrent(repo, brev)
6009 elif brev:
6009 elif brev:
6010 bookmarks.unsetcurrent(repo)
6010 bookmarks.unsetcurrent(repo)
6011
6011
6012 return ret
6012 return ret
6013
6013
6014 @command('verify', [])
6014 @command('verify', [])
6015 def verify(ui, repo):
6015 def verify(ui, repo):
6016 """verify the integrity of the repository
6016 """verify the integrity of the repository
6017
6017
6018 Verify the integrity of the current repository.
6018 Verify the integrity of the current repository.
6019
6019
6020 This will perform an extensive check of the repository's
6020 This will perform an extensive check of the repository's
6021 integrity, validating the hashes and checksums of each entry in
6021 integrity, validating the hashes and checksums of each entry in
6022 the changelog, manifest, and tracked files, as well as the
6022 the changelog, manifest, and tracked files, as well as the
6023 integrity of their crosslinks and indices.
6023 integrity of their crosslinks and indices.
6024
6024
6025 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6025 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6026 for more information about recovery from corruption of the
6026 for more information about recovery from corruption of the
6027 repository.
6027 repository.
6028
6028
6029 Returns 0 on success, 1 if errors are encountered.
6029 Returns 0 on success, 1 if errors are encountered.
6030 """
6030 """
6031 return hg.verify(repo)
6031 return hg.verify(repo)
6032
6032
6033 @command('version', [])
6033 @command('version', [])
6034 def version_(ui):
6034 def version_(ui):
6035 """output version and copyright information"""
6035 """output version and copyright information"""
6036 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6036 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6037 % util.version())
6037 % util.version())
6038 ui.status(_(
6038 ui.status(_(
6039 "(see http://mercurial.selenic.com for more information)\n"
6039 "(see http://mercurial.selenic.com for more information)\n"
6040 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
6040 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
6041 "This is free software; see the source for copying conditions. "
6041 "This is free software; see the source for copying conditions. "
6042 "There is NO\nwarranty; "
6042 "There is NO\nwarranty; "
6043 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6043 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6044 ))
6044 ))
6045
6045
6046 norepo = ("clone init version help debugcommands debugcomplete"
6046 norepo = ("clone init version help debugcommands debugcomplete"
6047 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
6047 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
6048 " debugknown debuggetbundle debugbundle")
6048 " debugknown debuggetbundle debugbundle")
6049 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
6049 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
6050 " debugdata debugindex debugindexdot debugrevlog")
6050 " debugdata debugindex debugindexdot debugrevlog")
6051 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
6051 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
6052 " remove resolve status debugwalk")
6052 " remove resolve status debugwalk")
@@ -1,383 +1,383 b''
1 $ "$TESTDIR/hghave" serve || exit 80
1 $ "$TESTDIR/hghave" serve || exit 80
2
2
3 $ cat << EOF >> $HGRCPATH
3 $ cat << EOF >> $HGRCPATH
4 > [ui]
4 > [ui]
5 > logtemplate={rev}:{node|short} {desc|firstline}
5 > logtemplate={rev}:{node|short} {desc|firstline}
6 > [phases]
6 > [phases]
7 > publish=False
7 > publish=False
8 > [extensions]
8 > [extensions]
9 > EOF
9 > EOF
10 $ cat > obs.py << EOF
10 $ cat > obs.py << EOF
11 > import mercurial.obsolete
11 > import mercurial.obsolete
12 > mercurial.obsolete._enabled = True
12 > mercurial.obsolete._enabled = True
13 > EOF
13 > EOF
14 $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
14 $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
15
15
16 initialize
16 initialize
17
17
18 $ hg init a
18 $ hg init a
19 $ cd a
19 $ cd a
20 $ echo 'test' > test
20 $ echo 'test' > test
21 $ hg commit -Am'test'
21 $ hg commit -Am'test'
22 adding test
22 adding test
23
23
24 set bookmarks
24 set bookmarks
25
25
26 $ hg bookmark X
26 $ hg bookmark X
27 $ hg bookmark Y
27 $ hg bookmark Y
28 $ hg bookmark Z
28 $ hg bookmark Z
29
29
30 import bookmark by name
30 import bookmark by name
31
31
32 $ hg init ../b
32 $ hg init ../b
33 $ cd ../b
33 $ cd ../b
34 $ hg book Y
34 $ hg book Y
35 $ hg book
35 $ hg book
36 * Y -1:000000000000
36 * Y -1:000000000000
37 $ hg pull ../a
37 $ hg pull ../a
38 pulling from ../a
38 pulling from ../a
39 requesting all changes
39 requesting all changes
40 adding changesets
40 adding changesets
41 adding manifests
41 adding manifests
42 adding file changes
42 adding file changes
43 added 1 changesets with 1 changes to 1 files
43 added 1 changesets with 1 changes to 1 files
44 adding remote bookmark X
44 adding remote bookmark X
45 updating bookmark Y
45 updating bookmark Y
46 adding remote bookmark Z
46 adding remote bookmark Z
47 (run 'hg update' to get a working copy)
47 (run 'hg update' to get a working copy)
48 $ hg bookmarks
48 $ hg bookmarks
49 X 0:4e3505fd9583
49 X 0:4e3505fd9583
50 Y 0:4e3505fd9583
50 * Y 0:4e3505fd9583
51 Z 0:4e3505fd9583
51 Z 0:4e3505fd9583
52 $ hg debugpushkey ../a namespaces
52 $ hg debugpushkey ../a namespaces
53 bookmarks
53 bookmarks
54 namespaces
54 namespaces
55 obsolete
55 obsolete
56 phases
56 phases
57 $ hg debugpushkey ../a bookmarks
57 $ hg debugpushkey ../a bookmarks
58 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
58 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
59 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
59 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
60 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
60 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
61 $ hg pull -B X ../a
61 $ hg pull -B X ../a
62 pulling from ../a
62 pulling from ../a
63 no changes found
63 no changes found
64 importing bookmark X
64 importing bookmark X
65 $ hg bookmark
65 $ hg bookmark
66 X 0:4e3505fd9583
66 X 0:4e3505fd9583
67 Y 0:4e3505fd9583
67 * Y 0:4e3505fd9583
68 Z 0:4e3505fd9583
68 Z 0:4e3505fd9583
69
69
70 export bookmark by name
70 export bookmark by name
71
71
72 $ hg bookmark W
72 $ hg bookmark W
73 $ hg bookmark foo
73 $ hg bookmark foo
74 $ hg bookmark foobar
74 $ hg bookmark foobar
75 $ hg push -B W ../a
75 $ hg push -B W ../a
76 pushing to ../a
76 pushing to ../a
77 searching for changes
77 searching for changes
78 no changes found
78 no changes found
79 exporting bookmark W
79 exporting bookmark W
80 [1]
80 [1]
81 $ hg -R ../a bookmarks
81 $ hg -R ../a bookmarks
82 W -1:000000000000
82 W -1:000000000000
83 X 0:4e3505fd9583
83 X 0:4e3505fd9583
84 Y 0:4e3505fd9583
84 Y 0:4e3505fd9583
85 * Z 0:4e3505fd9583
85 * Z 0:4e3505fd9583
86
86
87 delete a remote bookmark
87 delete a remote bookmark
88
88
89 $ hg book -d W
89 $ hg book -d W
90 $ hg push -B W ../a
90 $ hg push -B W ../a
91 pushing to ../a
91 pushing to ../a
92 searching for changes
92 searching for changes
93 no changes found
93 no changes found
94 deleting remote bookmark W
94 deleting remote bookmark W
95 [1]
95 [1]
96
96
97 push/pull name that doesn't exist
97 push/pull name that doesn't exist
98
98
99 $ hg push -B badname ../a
99 $ hg push -B badname ../a
100 pushing to ../a
100 pushing to ../a
101 searching for changes
101 searching for changes
102 no changes found
102 no changes found
103 bookmark badname does not exist on the local or remote repository!
103 bookmark badname does not exist on the local or remote repository!
104 [2]
104 [2]
105 $ hg pull -B anotherbadname ../a
105 $ hg pull -B anotherbadname ../a
106 pulling from ../a
106 pulling from ../a
107 abort: remote bookmark anotherbadname not found!
107 abort: remote bookmark anotherbadname not found!
108 [255]
108 [255]
109
109
110 divergent bookmarks
110 divergent bookmarks
111
111
112 $ cd ../a
112 $ cd ../a
113 $ echo c1 > f1
113 $ echo c1 > f1
114 $ hg ci -Am1
114 $ hg ci -Am1
115 adding f1
115 adding f1
116 $ hg book -f @
116 $ hg book -f @
117 $ hg book -f X
117 $ hg book -f X
118 $ hg book
118 $ hg book
119 @ 1:0d2164f0ce0d
119 @ 1:0d2164f0ce0d
120 * X 1:0d2164f0ce0d
120 * X 1:0d2164f0ce0d
121 Y 0:4e3505fd9583
121 Y 0:4e3505fd9583
122 Z 1:0d2164f0ce0d
122 Z 1:0d2164f0ce0d
123
123
124 $ cd ../b
124 $ cd ../b
125 $ hg up
125 $ hg up
126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 updating bookmark foobar
127 updating bookmark foobar
128 $ echo c2 > f2
128 $ echo c2 > f2
129 $ hg ci -Am2
129 $ hg ci -Am2
130 adding f2
130 adding f2
131 $ hg book -if @
131 $ hg book -if @
132 $ hg book -if X
132 $ hg book -if X
133 $ hg book
133 $ hg book
134 @ 1:9b140be10808
134 @ 1:9b140be10808
135 X 1:9b140be10808
135 X 1:9b140be10808
136 Y 0:4e3505fd9583
136 Y 0:4e3505fd9583
137 Z 0:4e3505fd9583
137 Z 0:4e3505fd9583
138 foo -1:000000000000
138 foo -1:000000000000
139 * foobar 1:9b140be10808
139 * foobar 1:9b140be10808
140
140
141 $ hg pull --config paths.foo=../a foo
141 $ hg pull --config paths.foo=../a foo
142 pulling from $TESTTMP/a (glob)
142 pulling from $TESTTMP/a (glob)
143 searching for changes
143 searching for changes
144 adding changesets
144 adding changesets
145 adding manifests
145 adding manifests
146 adding file changes
146 adding file changes
147 added 1 changesets with 1 changes to 1 files (+1 heads)
147 added 1 changesets with 1 changes to 1 files (+1 heads)
148 divergent bookmark @ stored as @foo
148 divergent bookmark @ stored as @foo
149 divergent bookmark X stored as X@foo
149 divergent bookmark X stored as X@foo
150 updating bookmark Z
150 updating bookmark Z
151 (run 'hg heads' to see heads, 'hg merge' to merge)
151 (run 'hg heads' to see heads, 'hg merge' to merge)
152 $ hg book
152 $ hg book
153 @ 1:9b140be10808
153 @ 1:9b140be10808
154 @foo 2:0d2164f0ce0d
154 @foo 2:0d2164f0ce0d
155 X 1:9b140be10808
155 X 1:9b140be10808
156 X@foo 2:0d2164f0ce0d
156 X@foo 2:0d2164f0ce0d
157 Y 0:4e3505fd9583
157 Y 0:4e3505fd9583
158 Z 2:0d2164f0ce0d
158 Z 2:0d2164f0ce0d
159 foo -1:000000000000
159 foo -1:000000000000
160 * foobar 1:9b140be10808
160 * foobar 1:9b140be10808
161 $ hg push -f ../a
161 $ hg push -f ../a
162 pushing to ../a
162 pushing to ../a
163 searching for changes
163 searching for changes
164 adding changesets
164 adding changesets
165 adding manifests
165 adding manifests
166 adding file changes
166 adding file changes
167 added 1 changesets with 1 changes to 1 files (+1 heads)
167 added 1 changesets with 1 changes to 1 files (+1 heads)
168 $ hg -R ../a book
168 $ hg -R ../a book
169 @ 1:0d2164f0ce0d
169 @ 1:0d2164f0ce0d
170 * X 1:0d2164f0ce0d
170 * X 1:0d2164f0ce0d
171 Y 0:4e3505fd9583
171 Y 0:4e3505fd9583
172 Z 1:0d2164f0ce0d
172 Z 1:0d2164f0ce0d
173
173
174 update a remote bookmark from a non-head to a head
174 update a remote bookmark from a non-head to a head
175
175
176 $ hg up -q Y
176 $ hg up -q Y
177 $ echo c3 > f2
177 $ echo c3 > f2
178 $ hg ci -Am3
178 $ hg ci -Am3
179 adding f2
179 adding f2
180 created new head
180 created new head
181 $ hg push ../a
181 $ hg push ../a
182 pushing to ../a
182 pushing to ../a
183 searching for changes
183 searching for changes
184 adding changesets
184 adding changesets
185 adding manifests
185 adding manifests
186 adding file changes
186 adding file changes
187 added 1 changesets with 1 changes to 1 files (+1 heads)
187 added 1 changesets with 1 changes to 1 files (+1 heads)
188 updating bookmark Y
188 updating bookmark Y
189 $ hg -R ../a book
189 $ hg -R ../a book
190 @ 1:0d2164f0ce0d
190 @ 1:0d2164f0ce0d
191 * X 1:0d2164f0ce0d
191 * X 1:0d2164f0ce0d
192 Y 3:f6fc62dde3c0
192 Y 3:f6fc62dde3c0
193 Z 1:0d2164f0ce0d
193 Z 1:0d2164f0ce0d
194
194
195 diverging a remote bookmark fails
195 diverging a remote bookmark fails
196
196
197 $ hg up -q 4e3505fd9583
197 $ hg up -q 4e3505fd9583
198 $ echo c4 > f2
198 $ echo c4 > f2
199 $ hg ci -Am4
199 $ hg ci -Am4
200 adding f2
200 adding f2
201 created new head
201 created new head
202 $ echo c5 > f2
202 $ echo c5 > f2
203 $ hg ci -Am5
203 $ hg ci -Am5
204 $ hg log -G
204 $ hg log -G
205 @ 5:c922c0139ca0 5
205 @ 5:c922c0139ca0 5
206 |
206 |
207 o 4:4efff6d98829 4
207 o 4:4efff6d98829 4
208 |
208 |
209 | o 3:f6fc62dde3c0 3
209 | o 3:f6fc62dde3c0 3
210 |/
210 |/
211 | o 2:0d2164f0ce0d 1
211 | o 2:0d2164f0ce0d 1
212 |/
212 |/
213 | o 1:9b140be10808 2
213 | o 1:9b140be10808 2
214 |/
214 |/
215 o 0:4e3505fd9583 test
215 o 0:4e3505fd9583 test
216
216
217
217
218 $ hg book -f Y
218 $ hg book -f Y
219
219
220 $ cat <<EOF > ../a/.hg/hgrc
220 $ cat <<EOF > ../a/.hg/hgrc
221 > [web]
221 > [web]
222 > push_ssl = false
222 > push_ssl = false
223 > allow_push = *
223 > allow_push = *
224 > EOF
224 > EOF
225
225
226 $ hg -R ../a serve -p $HGPORT2 -d --pid-file=../hg2.pid
226 $ hg -R ../a serve -p $HGPORT2 -d --pid-file=../hg2.pid
227 $ cat ../hg2.pid >> $DAEMON_PIDS
227 $ cat ../hg2.pid >> $DAEMON_PIDS
228
228
229 $ hg push http://localhost:$HGPORT2/
229 $ hg push http://localhost:$HGPORT2/
230 pushing to http://localhost:$HGPORT2/
230 pushing to http://localhost:$HGPORT2/
231 searching for changes
231 searching for changes
232 abort: push creates new remote head c922c0139ca0!
232 abort: push creates new remote head c922c0139ca0!
233 (did you forget to merge? use push -f to force)
233 (did you forget to merge? use push -f to force)
234 [255]
234 [255]
235 $ hg -R ../a book
235 $ hg -R ../a book
236 @ 1:0d2164f0ce0d
236 @ 1:0d2164f0ce0d
237 * X 1:0d2164f0ce0d
237 * X 1:0d2164f0ce0d
238 Y 3:f6fc62dde3c0
238 Y 3:f6fc62dde3c0
239 Z 1:0d2164f0ce0d
239 Z 1:0d2164f0ce0d
240
240
241
241
242 Unrelated marker does not alter the decision
242 Unrelated marker does not alter the decision
243
243
244 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
244 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
245 $ hg push http://localhost:$HGPORT2/
245 $ hg push http://localhost:$HGPORT2/
246 pushing to http://localhost:$HGPORT2/
246 pushing to http://localhost:$HGPORT2/
247 searching for changes
247 searching for changes
248 abort: push creates new remote head c922c0139ca0!
248 abort: push creates new remote head c922c0139ca0!
249 (did you forget to merge? use push -f to force)
249 (did you forget to merge? use push -f to force)
250 [255]
250 [255]
251 $ hg -R ../a book
251 $ hg -R ../a book
252 @ 1:0d2164f0ce0d
252 @ 1:0d2164f0ce0d
253 * X 1:0d2164f0ce0d
253 * X 1:0d2164f0ce0d
254 Y 3:f6fc62dde3c0
254 Y 3:f6fc62dde3c0
255 Z 1:0d2164f0ce0d
255 Z 1:0d2164f0ce0d
256
256
257 Update to a successor works
257 Update to a successor works
258
258
259 $ hg id --debug -r 3
259 $ hg id --debug -r 3
260 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
260 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
261 $ hg id --debug -r 4
261 $ hg id --debug -r 4
262 4efff6d98829d9c824c621afd6e3f01865f5439f
262 4efff6d98829d9c824c621afd6e3f01865f5439f
263 $ hg id --debug -r 5
263 $ hg id --debug -r 5
264 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
264 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
265 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
265 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
266 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
266 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
267 $ hg push http://localhost:$HGPORT2/
267 $ hg push http://localhost:$HGPORT2/
268 pushing to http://localhost:$HGPORT2/
268 pushing to http://localhost:$HGPORT2/
269 searching for changes
269 searching for changes
270 remote: adding changesets
270 remote: adding changesets
271 remote: adding manifests
271 remote: adding manifests
272 remote: adding file changes
272 remote: adding file changes
273 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
273 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
274 updating bookmark Y
274 updating bookmark Y
275 $ hg -R ../a book
275 $ hg -R ../a book
276 @ 1:0d2164f0ce0d
276 @ 1:0d2164f0ce0d
277 * X 1:0d2164f0ce0d
277 * X 1:0d2164f0ce0d
278 Y 5:c922c0139ca0
278 Y 5:c922c0139ca0
279 Z 1:0d2164f0ce0d
279 Z 1:0d2164f0ce0d
280
280
281 hgweb
281 hgweb
282
282
283 $ cat <<EOF > .hg/hgrc
283 $ cat <<EOF > .hg/hgrc
284 > [web]
284 > [web]
285 > push_ssl = false
285 > push_ssl = false
286 > allow_push = *
286 > allow_push = *
287 > EOF
287 > EOF
288
288
289 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
289 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
290 $ cat ../hg.pid >> $DAEMON_PIDS
290 $ cat ../hg.pid >> $DAEMON_PIDS
291 $ cd ../a
291 $ cd ../a
292
292
293 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
293 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
294 bookmarks
294 bookmarks
295 namespaces
295 namespaces
296 obsolete
296 obsolete
297 phases
297 phases
298 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
298 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
299 @ 9b140be1080824d768c5a4691a564088eede71f9
299 @ 9b140be1080824d768c5a4691a564088eede71f9
300 X 9b140be1080824d768c5a4691a564088eede71f9
300 X 9b140be1080824d768c5a4691a564088eede71f9
301 Y c922c0139ca03858f655e4a2af4dd02796a63969
301 Y c922c0139ca03858f655e4a2af4dd02796a63969
302 Z 0d2164f0ce0d8f1d6f94351eba04b794909be66c
302 Z 0d2164f0ce0d8f1d6f94351eba04b794909be66c
303 foo 0000000000000000000000000000000000000000
303 foo 0000000000000000000000000000000000000000
304 foobar 9b140be1080824d768c5a4691a564088eede71f9
304 foobar 9b140be1080824d768c5a4691a564088eede71f9
305 $ hg out -B http://localhost:$HGPORT/
305 $ hg out -B http://localhost:$HGPORT/
306 comparing with http://localhost:$HGPORT/
306 comparing with http://localhost:$HGPORT/
307 searching for changed bookmarks
307 searching for changed bookmarks
308 no changed bookmarks found
308 no changed bookmarks found
309 [1]
309 [1]
310 $ hg push -B Z http://localhost:$HGPORT/
310 $ hg push -B Z http://localhost:$HGPORT/
311 pushing to http://localhost:$HGPORT/
311 pushing to http://localhost:$HGPORT/
312 searching for changes
312 searching for changes
313 no changes found
313 no changes found
314 exporting bookmark Z
314 exporting bookmark Z
315 [1]
315 [1]
316 $ hg book -d Z
316 $ hg book -d Z
317 $ hg in -B http://localhost:$HGPORT/
317 $ hg in -B http://localhost:$HGPORT/
318 comparing with http://localhost:$HGPORT/
318 comparing with http://localhost:$HGPORT/
319 searching for changed bookmarks
319 searching for changed bookmarks
320 Z 0d2164f0ce0d
320 Z 0d2164f0ce0d
321 foo 000000000000
321 foo 000000000000
322 foobar 9b140be10808
322 foobar 9b140be10808
323 $ hg pull -B Z http://localhost:$HGPORT/
323 $ hg pull -B Z http://localhost:$HGPORT/
324 pulling from http://localhost:$HGPORT/
324 pulling from http://localhost:$HGPORT/
325 no changes found
325 no changes found
326 divergent bookmark @ stored as @1
326 divergent bookmark @ stored as @1
327 divergent bookmark X stored as X@1
327 divergent bookmark X stored as X@1
328 adding remote bookmark Z
328 adding remote bookmark Z
329 adding remote bookmark foo
329 adding remote bookmark foo
330 adding remote bookmark foobar
330 adding remote bookmark foobar
331 importing bookmark Z
331 importing bookmark Z
332 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
332 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
333 requesting all changes
333 requesting all changes
334 adding changesets
334 adding changesets
335 adding manifests
335 adding manifests
336 adding file changes
336 adding file changes
337 added 5 changesets with 5 changes to 3 files (+2 heads)
337 added 5 changesets with 5 changes to 3 files (+2 heads)
338 updating to bookmark @
338 updating to bookmark @
339 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
339 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
340 $ hg -R cloned-bookmarks bookmarks
340 $ hg -R cloned-bookmarks bookmarks
341 * @ 1:9b140be10808
341 * @ 1:9b140be10808
342 X 1:9b140be10808
342 X 1:9b140be10808
343 Y 4:c922c0139ca0
343 Y 4:c922c0139ca0
344 Z 2:0d2164f0ce0d
344 Z 2:0d2164f0ce0d
345 foo -1:000000000000
345 foo -1:000000000000
346 foobar 1:9b140be10808
346 foobar 1:9b140be10808
347
347
348 $ cd ..
348 $ cd ..
349
349
350 Pushing a bookmark should only push the changes required by that
350 Pushing a bookmark should only push the changes required by that
351 bookmark, not all outgoing changes:
351 bookmark, not all outgoing changes:
352 $ hg clone http://localhost:$HGPORT/ addmarks
352 $ hg clone http://localhost:$HGPORT/ addmarks
353 requesting all changes
353 requesting all changes
354 adding changesets
354 adding changesets
355 adding manifests
355 adding manifests
356 adding file changes
356 adding file changes
357 added 5 changesets with 5 changes to 3 files (+2 heads)
357 added 5 changesets with 5 changes to 3 files (+2 heads)
358 updating to bookmark @
358 updating to bookmark @
359 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
360 $ cd addmarks
360 $ cd addmarks
361 $ echo foo > foo
361 $ echo foo > foo
362 $ hg add foo
362 $ hg add foo
363 $ hg commit -m 'add foo'
363 $ hg commit -m 'add foo'
364 $ echo bar > bar
364 $ echo bar > bar
365 $ hg add bar
365 $ hg add bar
366 $ hg commit -m 'add bar'
366 $ hg commit -m 'add bar'
367 $ hg co "tip^"
367 $ hg co "tip^"
368 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
368 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
369 $ hg book add-foo
369 $ hg book add-foo
370 $ hg book -r tip add-bar
370 $ hg book -r tip add-bar
371 Note: this push *must* push only a single changeset, as that's the point
371 Note: this push *must* push only a single changeset, as that's the point
372 of this test.
372 of this test.
373 $ hg push -B add-foo --traceback
373 $ hg push -B add-foo --traceback
374 pushing to http://localhost:$HGPORT/
374 pushing to http://localhost:$HGPORT/
375 searching for changes
375 searching for changes
376 remote: adding changesets
376 remote: adding changesets
377 remote: adding manifests
377 remote: adding manifests
378 remote: adding file changes
378 remote: adding file changes
379 remote: added 1 changesets with 1 changes to 1 files
379 remote: added 1 changesets with 1 changes to 1 files
380 updating bookmark @ failed!
380 updating bookmark @ failed!
381 exporting bookmark add-foo
381 exporting bookmark add-foo
382
382
383 $ cd ..
383 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now