##// END OF EJS Templates
commit: amending with --close-branch (issue3445)...
Iulian Stana -
r19305:b500a663 stable
parent child Browse files
Show More
@@ -1,5868 +1,5875 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 _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, 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 bheads = repo.branchheads(branch)
459 bheads = repo.branchheads(branch)
460 hg.clean(repo, node, show_stats=False)
460 hg.clean(repo, node, show_stats=False)
461 repo.dirstate.setbranch(branch)
461 repo.dirstate.setbranch(branch)
462 rctx = scmutil.revsingle(repo, hex(parent))
462 rctx = scmutil.revsingle(repo, hex(parent))
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
464 if not opts.get('merge') and op1 != node:
464 if not opts.get('merge') and op1 != node:
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.update(repo, op1)
467 return hg.update(repo, op1)
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470
470
471 e = cmdutil.commiteditor
471 e = cmdutil.commiteditor
472 if not opts['message'] and not opts['logfile']:
472 if not opts['message'] and not opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 opts['message'] = "Backed out changeset %s" % short(node)
474 opts['message'] = "Backed out changeset %s" % short(node)
475 e = cmdutil.commitforceeditor
475 e = cmdutil.commitforceeditor
476
476
477 def commitfunc(ui, repo, message, match, opts):
477 def commitfunc(ui, repo, message, match, opts):
478 return repo.commit(message, opts.get('user'), opts.get('date'),
478 return repo.commit(message, opts.get('user'), opts.get('date'),
479 match, editor=e)
479 match, editor=e)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
482
482
483 def nice(node):
483 def nice(node):
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
485 ui.status(_('changeset %s backs out changeset %s\n') %
485 ui.status(_('changeset %s backs out changeset %s\n') %
486 (nice(repo.changelog.tip()), nice(node)))
486 (nice(repo.changelog.tip()), nice(node)))
487 if opts.get('merge') and op1 != node:
487 if opts.get('merge') and op1 != node:
488 hg.clean(repo, op1, show_stats=False)
488 hg.clean(repo, op1, show_stats=False)
489 ui.status(_('merging with changeset %s\n')
489 ui.status(_('merging with changeset %s\n')
490 % nice(repo.changelog.tip()))
490 % nice(repo.changelog.tip()))
491 try:
491 try:
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
493 return hg.merge(repo, hex(repo.changelog.tip()))
493 return hg.merge(repo, hex(repo.changelog.tip()))
494 finally:
494 finally:
495 ui.setconfig('ui', 'forcemerge', '')
495 ui.setconfig('ui', 'forcemerge', '')
496 finally:
496 finally:
497 wlock.release()
497 wlock.release()
498 return 0
498 return 0
499
499
500 @command('bisect',
500 @command('bisect',
501 [('r', 'reset', False, _('reset bisect state')),
501 [('r', 'reset', False, _('reset bisect state')),
502 ('g', 'good', False, _('mark changeset good')),
502 ('g', 'good', False, _('mark changeset good')),
503 ('b', 'bad', False, _('mark changeset bad')),
503 ('b', 'bad', False, _('mark changeset bad')),
504 ('s', 'skip', False, _('skip testing changeset')),
504 ('s', 'skip', False, _('skip testing changeset')),
505 ('e', 'extend', False, _('extend the bisect range')),
505 ('e', 'extend', False, _('extend the bisect range')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
507 ('U', 'noupdate', False, _('do not update to target'))],
507 ('U', 'noupdate', False, _('do not update to target'))],
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
509 def bisect(ui, repo, rev=None, extra=None, command=None,
509 def bisect(ui, repo, rev=None, extra=None, command=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
511 noupdate=None):
511 noupdate=None):
512 """subdivision search of changesets
512 """subdivision search of changesets
513
513
514 This command helps to find changesets which introduce problems. To
514 This command helps to find changesets which introduce problems. To
515 use, mark the earliest changeset you know exhibits the problem as
515 use, mark the earliest changeset you know exhibits the problem as
516 bad, then mark the latest changeset which is free from the problem
516 bad, then mark the latest changeset which is free from the problem
517 as good. Bisect will update your working directory to a revision
517 as good. Bisect will update your working directory to a revision
518 for testing (unless the -U/--noupdate option is specified). Once
518 for testing (unless the -U/--noupdate option is specified). Once
519 you have performed tests, mark the working directory as good or
519 you have performed tests, mark the working directory as good or
520 bad, and bisect will either update to another candidate changeset
520 bad, and bisect will either update to another candidate changeset
521 or announce that it has found the bad revision.
521 or announce that it has found the bad revision.
522
522
523 As a shortcut, you can also use the revision argument to mark a
523 As a shortcut, you can also use the revision argument to mark a
524 revision as good or bad without checking it out first.
524 revision as good or bad without checking it out first.
525
525
526 If you supply a command, it will be used for automatic bisection.
526 If you supply a command, it will be used for automatic bisection.
527 The environment variable HG_NODE will contain the ID of the
527 The environment variable HG_NODE will contain the ID of the
528 changeset being tested. The exit status of the command will be
528 changeset being tested. The exit status of the command will be
529 used to mark revisions as good or bad: status 0 means good, 125
529 used to mark revisions as good or bad: status 0 means good, 125
530 means to skip the revision, 127 (command not found) will abort the
530 means to skip the revision, 127 (command not found) will abort the
531 bisection, and any other non-zero exit status means the revision
531 bisection, and any other non-zero exit status means the revision
532 is bad.
532 is bad.
533
533
534 .. container:: verbose
534 .. container:: verbose
535
535
536 Some examples:
536 Some examples:
537
537
538 - start a bisection with known bad revision 12, and good revision 34::
538 - start a bisection with known bad revision 12, and good revision 34::
539
539
540 hg bisect --bad 34
540 hg bisect --bad 34
541 hg bisect --good 12
541 hg bisect --good 12
542
542
543 - advance the current bisection by marking current revision as good or
543 - advance the current bisection by marking current revision as good or
544 bad::
544 bad::
545
545
546 hg bisect --good
546 hg bisect --good
547 hg bisect --bad
547 hg bisect --bad
548
548
549 - mark the current revision, or a known revision, to be skipped (e.g. if
549 - mark the current revision, or a known revision, to be skipped (e.g. if
550 that revision is not usable because of another issue)::
550 that revision is not usable because of another issue)::
551
551
552 hg bisect --skip
552 hg bisect --skip
553 hg bisect --skip 23
553 hg bisect --skip 23
554
554
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
556
556
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
558
558
559 - forget the current bisection::
559 - forget the current bisection::
560
560
561 hg bisect --reset
561 hg bisect --reset
562
562
563 - use 'make && make tests' to automatically find the first broken
563 - use 'make && make tests' to automatically find the first broken
564 revision::
564 revision::
565
565
566 hg bisect --reset
566 hg bisect --reset
567 hg bisect --bad 34
567 hg bisect --bad 34
568 hg bisect --good 12
568 hg bisect --good 12
569 hg bisect --command 'make && make tests'
569 hg bisect --command 'make && make tests'
570
570
571 - see all changesets whose states are already known in the current
571 - see all changesets whose states are already known in the current
572 bisection::
572 bisection::
573
573
574 hg log -r "bisect(pruned)"
574 hg log -r "bisect(pruned)"
575
575
576 - see the changeset currently being bisected (especially useful
576 - see the changeset currently being bisected (especially useful
577 if running with -U/--noupdate)::
577 if running with -U/--noupdate)::
578
578
579 hg log -r "bisect(current)"
579 hg log -r "bisect(current)"
580
580
581 - see all changesets that took part in the current bisection::
581 - see all changesets that took part in the current bisection::
582
582
583 hg log -r "bisect(range)"
583 hg log -r "bisect(range)"
584
584
585 - with the graphlog extension, you can even get a nice graph::
585 - with the graphlog extension, you can even get a nice graph::
586
586
587 hg log --graph -r "bisect(range)"
587 hg log --graph -r "bisect(range)"
588
588
589 See :hg:`help revsets` for more about the `bisect()` keyword.
589 See :hg:`help revsets` for more about the `bisect()` keyword.
590
590
591 Returns 0 on success.
591 Returns 0 on success.
592 """
592 """
593 def extendbisectrange(nodes, good):
593 def extendbisectrange(nodes, good):
594 # bisect is incomplete when it ends on a merge node and
594 # bisect is incomplete when it ends on a merge node and
595 # one of the parent was not checked.
595 # one of the parent was not checked.
596 parents = repo[nodes[0]].parents()
596 parents = repo[nodes[0]].parents()
597 if len(parents) > 1:
597 if len(parents) > 1:
598 side = good and state['bad'] or state['good']
598 side = good and state['bad'] or state['good']
599 num = len(set(i.node() for i in parents) & set(side))
599 num = len(set(i.node() for i in parents) & set(side))
600 if num == 1:
600 if num == 1:
601 return parents[0].ancestor(parents[1])
601 return parents[0].ancestor(parents[1])
602 return None
602 return None
603
603
604 def print_result(nodes, good):
604 def print_result(nodes, good):
605 displayer = cmdutil.show_changeset(ui, repo, {})
605 displayer = cmdutil.show_changeset(ui, repo, {})
606 if len(nodes) == 1:
606 if len(nodes) == 1:
607 # narrowed it down to a single revision
607 # narrowed it down to a single revision
608 if good:
608 if good:
609 ui.write(_("The first good revision is:\n"))
609 ui.write(_("The first good revision is:\n"))
610 else:
610 else:
611 ui.write(_("The first bad revision is:\n"))
611 ui.write(_("The first bad revision is:\n"))
612 displayer.show(repo[nodes[0]])
612 displayer.show(repo[nodes[0]])
613 extendnode = extendbisectrange(nodes, good)
613 extendnode = extendbisectrange(nodes, good)
614 if extendnode is not None:
614 if extendnode is not None:
615 ui.write(_('Not all ancestors of this changeset have been'
615 ui.write(_('Not all ancestors of this changeset have been'
616 ' checked.\nUse bisect --extend to continue the '
616 ' checked.\nUse bisect --extend to continue the '
617 'bisection from\nthe common ancestor, %s.\n')
617 'bisection from\nthe common ancestor, %s.\n')
618 % extendnode)
618 % extendnode)
619 else:
619 else:
620 # multiple possible revisions
620 # multiple possible revisions
621 if good:
621 if good:
622 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
623 "good revision could be any of:\n"))
623 "good revision could be any of:\n"))
624 else:
624 else:
625 ui.write(_("Due to skipped revisions, the first "
625 ui.write(_("Due to skipped revisions, the first "
626 "bad revision could be any of:\n"))
626 "bad revision could be any of:\n"))
627 for n in nodes:
627 for n in nodes:
628 displayer.show(repo[n])
628 displayer.show(repo[n])
629 displayer.close()
629 displayer.close()
630
630
631 def check_state(state, interactive=True):
631 def check_state(state, interactive=True):
632 if not state['good'] or not state['bad']:
632 if not state['good'] or not state['bad']:
633 if (good or bad or skip or reset) and interactive:
633 if (good or bad or skip or reset) and interactive:
634 return
634 return
635 if not state['good']:
635 if not state['good']:
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
637 else:
637 else:
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
639 return True
639 return True
640
640
641 # backward compatibility
641 # backward compatibility
642 if rev in "good bad reset init".split():
642 if rev in "good bad reset init".split():
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
644 cmd, rev, extra = rev, extra, None
644 cmd, rev, extra = rev, extra, None
645 if cmd == "good":
645 if cmd == "good":
646 good = True
646 good = True
647 elif cmd == "bad":
647 elif cmd == "bad":
648 bad = True
648 bad = True
649 else:
649 else:
650 reset = True
650 reset = True
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
652 raise util.Abort(_('incompatible arguments'))
652 raise util.Abort(_('incompatible arguments'))
653
653
654 if reset:
654 if reset:
655 p = repo.join("bisect.state")
655 p = repo.join("bisect.state")
656 if os.path.exists(p):
656 if os.path.exists(p):
657 os.unlink(p)
657 os.unlink(p)
658 return
658 return
659
659
660 state = hbisect.load_state(repo)
660 state = hbisect.load_state(repo)
661
661
662 if command:
662 if command:
663 changesets = 1
663 changesets = 1
664 try:
664 try:
665 node = state['current'][0]
665 node = state['current'][0]
666 except LookupError:
666 except LookupError:
667 if noupdate:
667 if noupdate:
668 raise util.Abort(_('current bisect revision is unknown - '
668 raise util.Abort(_('current bisect revision is unknown - '
669 'start a new bisect to fix'))
669 'start a new bisect to fix'))
670 node, p2 = repo.dirstate.parents()
670 node, p2 = repo.dirstate.parents()
671 if p2 != nullid:
671 if p2 != nullid:
672 raise util.Abort(_('current bisect revision is a merge'))
672 raise util.Abort(_('current bisect revision is a merge'))
673 try:
673 try:
674 while changesets:
674 while changesets:
675 # update state
675 # update state
676 state['current'] = [node]
676 state['current'] = [node]
677 hbisect.save_state(repo, state)
677 hbisect.save_state(repo, state)
678 status = util.system(command,
678 status = util.system(command,
679 environ={'HG_NODE': hex(node)},
679 environ={'HG_NODE': hex(node)},
680 out=ui.fout)
680 out=ui.fout)
681 if status == 125:
681 if status == 125:
682 transition = "skip"
682 transition = "skip"
683 elif status == 0:
683 elif status == 0:
684 transition = "good"
684 transition = "good"
685 # status < 0 means process was killed
685 # status < 0 means process was killed
686 elif status == 127:
686 elif status == 127:
687 raise util.Abort(_("failed to execute %s") % command)
687 raise util.Abort(_("failed to execute %s") % command)
688 elif status < 0:
688 elif status < 0:
689 raise util.Abort(_("%s killed") % command)
689 raise util.Abort(_("%s killed") % command)
690 else:
690 else:
691 transition = "bad"
691 transition = "bad"
692 ctx = scmutil.revsingle(repo, rev, node)
692 ctx = scmutil.revsingle(repo, rev, node)
693 rev = None # clear for future iterations
693 rev = None # clear for future iterations
694 state[transition].append(ctx.node())
694 state[transition].append(ctx.node())
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
696 check_state(state, interactive=False)
696 check_state(state, interactive=False)
697 # bisect
697 # bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 # update to next check
699 # update to next check
700 node = nodes[0]
700 node = nodes[0]
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 hg.clean(repo, node, show_stats=False)
703 hg.clean(repo, node, show_stats=False)
704 finally:
704 finally:
705 state['current'] = [node]
705 state['current'] = [node]
706 hbisect.save_state(repo, state)
706 hbisect.save_state(repo, state)
707 print_result(nodes, good)
707 print_result(nodes, good)
708 return
708 return
709
709
710 # update state
710 # update state
711
711
712 if rev:
712 if rev:
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
714 else:
714 else:
715 nodes = [repo.lookup('.')]
715 nodes = [repo.lookup('.')]
716
716
717 if good or bad or skip:
717 if good or bad or skip:
718 if good:
718 if good:
719 state['good'] += nodes
719 state['good'] += nodes
720 elif bad:
720 elif bad:
721 state['bad'] += nodes
721 state['bad'] += nodes
722 elif skip:
722 elif skip:
723 state['skip'] += nodes
723 state['skip'] += nodes
724 hbisect.save_state(repo, state)
724 hbisect.save_state(repo, state)
725
725
726 if not check_state(state):
726 if not check_state(state):
727 return
727 return
728
728
729 # actually bisect
729 # actually bisect
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
731 if extend:
731 if extend:
732 if not changesets:
732 if not changesets:
733 extendnode = extendbisectrange(nodes, good)
733 extendnode = extendbisectrange(nodes, good)
734 if extendnode is not None:
734 if extendnode is not None:
735 ui.write(_("Extending search to changeset %d:%s\n"
735 ui.write(_("Extending search to changeset %d:%s\n"
736 % (extendnode.rev(), extendnode)))
736 % (extendnode.rev(), extendnode)))
737 state['current'] = [extendnode.node()]
737 state['current'] = [extendnode.node()]
738 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
739 if noupdate:
739 if noupdate:
740 return
740 return
741 cmdutil.bailifchanged(repo)
741 cmdutil.bailifchanged(repo)
742 return hg.clean(repo, extendnode.node())
742 return hg.clean(repo, extendnode.node())
743 raise util.Abort(_("nothing to extend"))
743 raise util.Abort(_("nothing to extend"))
744
744
745 if changesets == 0:
745 if changesets == 0:
746 print_result(nodes, good)
746 print_result(nodes, good)
747 else:
747 else:
748 assert len(nodes) == 1 # only a single node can be tested next
748 assert len(nodes) == 1 # only a single node can be tested next
749 node = nodes[0]
749 node = nodes[0]
750 # compute the approximate number of remaining tests
750 # compute the approximate number of remaining tests
751 tests, size = 0, 2
751 tests, size = 0, 2
752 while size <= changesets:
752 while size <= changesets:
753 tests, size = tests + 1, size * 2
753 tests, size = tests + 1, size * 2
754 rev = repo.changelog.rev(node)
754 rev = repo.changelog.rev(node)
755 ui.write(_("Testing changeset %d:%s "
755 ui.write(_("Testing changeset %d:%s "
756 "(%d changesets remaining, ~%d tests)\n")
756 "(%d changesets remaining, ~%d tests)\n")
757 % (rev, short(node), changesets, tests))
757 % (rev, short(node), changesets, tests))
758 state['current'] = [node]
758 state['current'] = [node]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if not noupdate:
760 if not noupdate:
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, node)
762 return hg.clean(repo, node)
763
763
764 @command('bookmarks|bookmark',
764 @command('bookmarks|bookmark',
765 [('f', 'force', False, _('force')),
765 [('f', 'force', False, _('force')),
766 ('r', 'rev', '', _('revision'), _('REV')),
766 ('r', 'rev', '', _('revision'), _('REV')),
767 ('d', 'delete', False, _('delete a given bookmark')),
767 ('d', 'delete', False, _('delete a given bookmark')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
772 rename=None, inactive=False):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
773 '''track a line of development with movable markers
774
774
775 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
776 Bookmarks are local. They can be renamed, copied and deleted. It is
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
778 :hg:`update NAME` to update to a given bookmark.
779
779
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
781 directory's parent revision with the given name. If you specify
781 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
782 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
783 the bookmark is assigned to that revision.
784
784
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
786 push` and :hg:`help pull`). This requires both the local and remote
787 repositories to support bookmarks. For versions prior to 1.8, this means
787 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
788 the bookmarks extension must be enabled.
789
789
790 If you set a bookmark called '@', new clones of the repository will
790 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
791 have that revision checked out (and the bookmark made active) by
792 default.
792 default.
793
793
794 With -i/--inactive, the new bookmark will not be made the active
794 With -i/--inactive, the new bookmark will not be made the active
795 bookmark. If -r/--rev is given, the new bookmark will not be made
795 bookmark. If -r/--rev is given, the new bookmark will not be made
796 active even if -i/--inactive is not given. If no NAME is given, the
796 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
797 current active bookmark will be marked inactive.
798 '''
798 '''
799 hexfn = ui.debugflag and hex or short
799 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
800 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
801 cur = repo.changectx('.').node()
802
802
803 def checkformat(mark):
803 def checkformat(mark):
804 mark = mark.strip()
804 mark = mark.strip()
805 if not mark:
805 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
806 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
807 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
808 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
809 return mark
810
810
811 def checkconflict(repo, mark, force=False, target=None):
811 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
812 if mark in marks and not force:
813 if target:
813 if target:
814 if marks[mark] == target and target == cur:
814 if marks[mark] == target and target == cur:
815 # re-activating a bookmark
815 # re-activating a bookmark
816 return
816 return
817 anc = repo.changelog.ancestors([repo[target].rev()])
817 anc = repo.changelog.ancestors([repo[target].rev()])
818 bmctx = repo[marks[mark]]
818 bmctx = repo[marks[mark]]
819 divs = [repo[b].node() for b in marks
819 divs = [repo[b].node() for b in marks
820 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
820 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
821
821
822 # allow resolving a single divergent bookmark even if moving
822 # allow resolving a single divergent bookmark even if moving
823 # the bookmark across branches when a revision is specified
823 # the bookmark across branches when a revision is specified
824 # that contains a divergent bookmark
824 # that contains a divergent bookmark
825 if bmctx.rev() not in anc and target in divs:
825 if bmctx.rev() not in anc and target in divs:
826 bookmarks.deletedivergent(repo, [target], mark)
826 bookmarks.deletedivergent(repo, [target], mark)
827 return
827 return
828
828
829 deletefrom = [b for b in divs
829 deletefrom = [b for b in divs
830 if repo[b].rev() in anc or b == target]
830 if repo[b].rev() in anc or b == target]
831 bookmarks.deletedivergent(repo, deletefrom, mark)
831 bookmarks.deletedivergent(repo, deletefrom, mark)
832 if bmctx.rev() in anc:
832 if bmctx.rev() in anc:
833 ui.status(_("moving bookmark '%s' forward from %s\n") %
833 ui.status(_("moving bookmark '%s' forward from %s\n") %
834 (mark, short(bmctx.node())))
834 (mark, short(bmctx.node())))
835 return
835 return
836 raise util.Abort(_("bookmark '%s' already exists "
836 raise util.Abort(_("bookmark '%s' already exists "
837 "(use -f to force)") % mark)
837 "(use -f to force)") % mark)
838 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
838 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
839 and not force):
839 and not force):
840 raise util.Abort(
840 raise util.Abort(
841 _("a bookmark cannot have the name of an existing branch"))
841 _("a bookmark cannot have the name of an existing branch"))
842
842
843 if delete and rename:
843 if delete and rename:
844 raise util.Abort(_("--delete and --rename are incompatible"))
844 raise util.Abort(_("--delete and --rename are incompatible"))
845 if delete and rev:
845 if delete and rev:
846 raise util.Abort(_("--rev is incompatible with --delete"))
846 raise util.Abort(_("--rev is incompatible with --delete"))
847 if rename and rev:
847 if rename and rev:
848 raise util.Abort(_("--rev is incompatible with --rename"))
848 raise util.Abort(_("--rev is incompatible with --rename"))
849 if mark is None and (delete or rev):
849 if mark is None and (delete or rev):
850 raise util.Abort(_("bookmark name required"))
850 raise util.Abort(_("bookmark name required"))
851
851
852 if delete:
852 if delete:
853 if mark not in marks:
853 if mark not in marks:
854 raise util.Abort(_("bookmark '%s' does not exist") % mark)
854 raise util.Abort(_("bookmark '%s' does not exist") % mark)
855 if mark == repo._bookmarkcurrent:
855 if mark == repo._bookmarkcurrent:
856 bookmarks.setcurrent(repo, None)
856 bookmarks.setcurrent(repo, None)
857 del marks[mark]
857 del marks[mark]
858 marks.write()
858 marks.write()
859
859
860 elif rename:
860 elif rename:
861 if mark is None:
861 if mark is None:
862 raise util.Abort(_("new bookmark name required"))
862 raise util.Abort(_("new bookmark name required"))
863 mark = checkformat(mark)
863 mark = checkformat(mark)
864 if rename not in marks:
864 if rename not in marks:
865 raise util.Abort(_("bookmark '%s' does not exist") % rename)
865 raise util.Abort(_("bookmark '%s' does not exist") % rename)
866 checkconflict(repo, mark, force)
866 checkconflict(repo, mark, force)
867 marks[mark] = marks[rename]
867 marks[mark] = marks[rename]
868 if repo._bookmarkcurrent == rename and not inactive:
868 if repo._bookmarkcurrent == rename and not inactive:
869 bookmarks.setcurrent(repo, mark)
869 bookmarks.setcurrent(repo, mark)
870 del marks[rename]
870 del marks[rename]
871 marks.write()
871 marks.write()
872
872
873 elif mark is not None:
873 elif mark is not None:
874 mark = checkformat(mark)
874 mark = checkformat(mark)
875 if inactive and mark == repo._bookmarkcurrent:
875 if inactive and mark == repo._bookmarkcurrent:
876 bookmarks.setcurrent(repo, None)
876 bookmarks.setcurrent(repo, None)
877 return
877 return
878 tgt = cur
878 tgt = cur
879 if rev:
879 if rev:
880 tgt = scmutil.revsingle(repo, rev).node()
880 tgt = scmutil.revsingle(repo, rev).node()
881 checkconflict(repo, mark, force, tgt)
881 checkconflict(repo, mark, force, tgt)
882 marks[mark] = tgt
882 marks[mark] = tgt
883 if not inactive and cur == marks[mark] and not rev:
883 if not inactive and cur == marks[mark] and not rev:
884 bookmarks.setcurrent(repo, mark)
884 bookmarks.setcurrent(repo, mark)
885 elif cur != tgt and mark == repo._bookmarkcurrent:
885 elif cur != tgt and mark == repo._bookmarkcurrent:
886 bookmarks.setcurrent(repo, None)
886 bookmarks.setcurrent(repo, None)
887 marks.write()
887 marks.write()
888
888
889 # Same message whether trying to deactivate the current bookmark (-i
889 # Same message whether trying to deactivate the current bookmark (-i
890 # with no NAME) or listing bookmarks
890 # with no NAME) or listing bookmarks
891 elif len(marks) == 0:
891 elif len(marks) == 0:
892 ui.status(_("no bookmarks set\n"))
892 ui.status(_("no bookmarks set\n"))
893
893
894 elif inactive:
894 elif inactive:
895 if not repo._bookmarkcurrent:
895 if not repo._bookmarkcurrent:
896 ui.status(_("no active bookmark\n"))
896 ui.status(_("no active bookmark\n"))
897 else:
897 else:
898 bookmarks.setcurrent(repo, None)
898 bookmarks.setcurrent(repo, None)
899
899
900 else: # show bookmarks
900 else: # show bookmarks
901 for bmark, n in sorted(marks.iteritems()):
901 for bmark, n in sorted(marks.iteritems()):
902 current = repo._bookmarkcurrent
902 current = repo._bookmarkcurrent
903 if bmark == current:
903 if bmark == current:
904 prefix, label = '*', 'bookmarks.current'
904 prefix, label = '*', 'bookmarks.current'
905 else:
905 else:
906 prefix, label = ' ', ''
906 prefix, label = ' ', ''
907
907
908 if ui.quiet:
908 if ui.quiet:
909 ui.write("%s\n" % bmark, label=label)
909 ui.write("%s\n" % bmark, label=label)
910 else:
910 else:
911 ui.write(" %s %-25s %d:%s\n" % (
911 ui.write(" %s %-25s %d:%s\n" % (
912 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
912 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
913 label=label)
913 label=label)
914
914
915 @command('branch',
915 @command('branch',
916 [('f', 'force', None,
916 [('f', 'force', None,
917 _('set branch name even if it shadows an existing branch')),
917 _('set branch name even if it shadows an existing branch')),
918 ('C', 'clean', None, _('reset branch name to parent branch name'))],
918 ('C', 'clean', None, _('reset branch name to parent branch name'))],
919 _('[-fC] [NAME]'))
919 _('[-fC] [NAME]'))
920 def branch(ui, repo, label=None, **opts):
920 def branch(ui, repo, label=None, **opts):
921 """set or show the current branch name
921 """set or show the current branch name
922
922
923 .. note::
923 .. note::
924 Branch names are permanent and global. Use :hg:`bookmark` to create a
924 Branch names are permanent and global. Use :hg:`bookmark` to create a
925 light-weight bookmark instead. See :hg:`help glossary` for more
925 light-weight bookmark instead. See :hg:`help glossary` for more
926 information about named branches and bookmarks.
926 information about named branches and bookmarks.
927
927
928 With no argument, show the current branch name. With one argument,
928 With no argument, show the current branch name. With one argument,
929 set the working directory branch name (the branch will not exist
929 set the working directory branch name (the branch will not exist
930 in the repository until the next commit). Standard practice
930 in the repository until the next commit). Standard practice
931 recommends that primary development take place on the 'default'
931 recommends that primary development take place on the 'default'
932 branch.
932 branch.
933
933
934 Unless -f/--force is specified, branch will not let you set a
934 Unless -f/--force is specified, branch will not let you set a
935 branch name that already exists, even if it's inactive.
935 branch name that already exists, even if it's inactive.
936
936
937 Use -C/--clean to reset the working directory branch to that of
937 Use -C/--clean to reset the working directory branch to that of
938 the parent of the working directory, negating a previous branch
938 the parent of the working directory, negating a previous branch
939 change.
939 change.
940
940
941 Use the command :hg:`update` to switch to an existing branch. Use
941 Use the command :hg:`update` to switch to an existing branch. Use
942 :hg:`commit --close-branch` to mark this branch as closed.
942 :hg:`commit --close-branch` to mark this branch as closed.
943
943
944 Returns 0 on success.
944 Returns 0 on success.
945 """
945 """
946 if label:
946 if label:
947 label = label.strip()
947 label = label.strip()
948
948
949 if not opts.get('clean') and not label:
949 if not opts.get('clean') and not label:
950 ui.write("%s\n" % repo.dirstate.branch())
950 ui.write("%s\n" % repo.dirstate.branch())
951 return
951 return
952
952
953 wlock = repo.wlock()
953 wlock = repo.wlock()
954 try:
954 try:
955 if opts.get('clean'):
955 if opts.get('clean'):
956 label = repo[None].p1().branch()
956 label = repo[None].p1().branch()
957 repo.dirstate.setbranch(label)
957 repo.dirstate.setbranch(label)
958 ui.status(_('reset working directory to branch %s\n') % label)
958 ui.status(_('reset working directory to branch %s\n') % label)
959 elif label:
959 elif label:
960 if not opts.get('force') and label in repo.branchmap():
960 if not opts.get('force') and label in repo.branchmap():
961 if label not in [p.branch() for p in repo.parents()]:
961 if label not in [p.branch() for p in repo.parents()]:
962 raise util.Abort(_('a branch of the same name already'
962 raise util.Abort(_('a branch of the same name already'
963 ' exists'),
963 ' exists'),
964 # i18n: "it" refers to an existing branch
964 # i18n: "it" refers to an existing branch
965 hint=_("use 'hg update' to switch to it"))
965 hint=_("use 'hg update' to switch to it"))
966 scmutil.checknewlabel(repo, label, 'branch')
966 scmutil.checknewlabel(repo, label, 'branch')
967 repo.dirstate.setbranch(label)
967 repo.dirstate.setbranch(label)
968 ui.status(_('marked working directory as branch %s\n') % label)
968 ui.status(_('marked working directory as branch %s\n') % label)
969 ui.status(_('(branches are permanent and global, '
969 ui.status(_('(branches are permanent and global, '
970 'did you want a bookmark?)\n'))
970 'did you want a bookmark?)\n'))
971 finally:
971 finally:
972 wlock.release()
972 wlock.release()
973
973
974 @command('branches',
974 @command('branches',
975 [('a', 'active', False, _('show only branches that have unmerged heads')),
975 [('a', 'active', False, _('show only branches that have unmerged heads')),
976 ('c', 'closed', False, _('show normal and closed branches'))],
976 ('c', 'closed', False, _('show normal and closed branches'))],
977 _('[-ac]'))
977 _('[-ac]'))
978 def branches(ui, repo, active=False, closed=False):
978 def branches(ui, repo, active=False, closed=False):
979 """list repository named branches
979 """list repository named branches
980
980
981 List the repository's named branches, indicating which ones are
981 List the repository's named branches, indicating which ones are
982 inactive. If -c/--closed is specified, also list branches which have
982 inactive. If -c/--closed is specified, also list branches which have
983 been marked closed (see :hg:`commit --close-branch`).
983 been marked closed (see :hg:`commit --close-branch`).
984
984
985 If -a/--active is specified, only show active branches. A branch
985 If -a/--active is specified, only show active branches. A branch
986 is considered active if it contains repository heads.
986 is considered active if it contains repository heads.
987
987
988 Use the command :hg:`update` to switch to an existing branch.
988 Use the command :hg:`update` to switch to an existing branch.
989
989
990 Returns 0.
990 Returns 0.
991 """
991 """
992
992
993 hexfunc = ui.debugflag and hex or short
993 hexfunc = ui.debugflag and hex or short
994
994
995 activebranches = set([repo[n].branch() for n in repo.heads()])
995 activebranches = set([repo[n].branch() for n in repo.heads()])
996 branches = []
996 branches = []
997 for tag, heads in repo.branchmap().iteritems():
997 for tag, heads in repo.branchmap().iteritems():
998 for h in reversed(heads):
998 for h in reversed(heads):
999 ctx = repo[h]
999 ctx = repo[h]
1000 isopen = not ctx.closesbranch()
1000 isopen = not ctx.closesbranch()
1001 if isopen:
1001 if isopen:
1002 tip = ctx
1002 tip = ctx
1003 break
1003 break
1004 else:
1004 else:
1005 tip = repo[heads[-1]]
1005 tip = repo[heads[-1]]
1006 isactive = tag in activebranches and isopen
1006 isactive = tag in activebranches and isopen
1007 branches.append((tip, isactive, isopen))
1007 branches.append((tip, isactive, isopen))
1008 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1008 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
1009 reverse=True)
1009 reverse=True)
1010
1010
1011 for ctx, isactive, isopen in branches:
1011 for ctx, isactive, isopen in branches:
1012 if (not active) or isactive:
1012 if (not active) or isactive:
1013 if isactive:
1013 if isactive:
1014 label = 'branches.active'
1014 label = 'branches.active'
1015 notice = ''
1015 notice = ''
1016 elif not isopen:
1016 elif not isopen:
1017 if not closed:
1017 if not closed:
1018 continue
1018 continue
1019 label = 'branches.closed'
1019 label = 'branches.closed'
1020 notice = _(' (closed)')
1020 notice = _(' (closed)')
1021 else:
1021 else:
1022 label = 'branches.inactive'
1022 label = 'branches.inactive'
1023 notice = _(' (inactive)')
1023 notice = _(' (inactive)')
1024 if ctx.branch() == repo.dirstate.branch():
1024 if ctx.branch() == repo.dirstate.branch():
1025 label = 'branches.current'
1025 label = 'branches.current'
1026 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1026 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1027 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1027 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1028 'log.changeset changeset.%s' % ctx.phasestr())
1028 'log.changeset changeset.%s' % ctx.phasestr())
1029 tag = ui.label(ctx.branch(), label)
1029 tag = ui.label(ctx.branch(), label)
1030 if ui.quiet:
1030 if ui.quiet:
1031 ui.write("%s\n" % tag)
1031 ui.write("%s\n" % tag)
1032 else:
1032 else:
1033 ui.write("%s %s%s\n" % (tag, rev, notice))
1033 ui.write("%s %s%s\n" % (tag, rev, notice))
1034
1034
1035 @command('bundle',
1035 @command('bundle',
1036 [('f', 'force', None, _('run even when the destination is unrelated')),
1036 [('f', 'force', None, _('run even when the destination is unrelated')),
1037 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1037 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1038 _('REV')),
1038 _('REV')),
1039 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1039 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1040 _('BRANCH')),
1040 _('BRANCH')),
1041 ('', 'base', [],
1041 ('', 'base', [],
1042 _('a base changeset assumed to be available at the destination'),
1042 _('a base changeset assumed to be available at the destination'),
1043 _('REV')),
1043 _('REV')),
1044 ('a', 'all', None, _('bundle all changesets in the repository')),
1044 ('a', 'all', None, _('bundle all changesets in the repository')),
1045 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1045 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1046 ] + remoteopts,
1046 ] + remoteopts,
1047 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1047 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1048 def bundle(ui, repo, fname, dest=None, **opts):
1048 def bundle(ui, repo, fname, dest=None, **opts):
1049 """create a changegroup file
1049 """create a changegroup file
1050
1050
1051 Generate a compressed changegroup file collecting changesets not
1051 Generate a compressed changegroup file collecting changesets not
1052 known to be in another repository.
1052 known to be in another repository.
1053
1053
1054 If you omit the destination repository, then hg assumes the
1054 If you omit the destination repository, then hg assumes the
1055 destination will have all the nodes you specify with --base
1055 destination will have all the nodes you specify with --base
1056 parameters. To create a bundle containing all changesets, use
1056 parameters. To create a bundle containing all changesets, use
1057 -a/--all (or --base null).
1057 -a/--all (or --base null).
1058
1058
1059 You can change compression method with the -t/--type option.
1059 You can change compression method with the -t/--type option.
1060 The available compression methods are: none, bzip2, and
1060 The available compression methods are: none, bzip2, and
1061 gzip (by default, bundles are compressed using bzip2).
1061 gzip (by default, bundles are compressed using bzip2).
1062
1062
1063 The bundle file can then be transferred using conventional means
1063 The bundle file can then be transferred using conventional means
1064 and applied to another repository with the unbundle or pull
1064 and applied to another repository with the unbundle or pull
1065 command. This is useful when direct push and pull are not
1065 command. This is useful when direct push and pull are not
1066 available or when exporting an entire repository is undesirable.
1066 available or when exporting an entire repository is undesirable.
1067
1067
1068 Applying bundles preserves all changeset contents including
1068 Applying bundles preserves all changeset contents including
1069 permissions, copy/rename information, and revision history.
1069 permissions, copy/rename information, and revision history.
1070
1070
1071 Returns 0 on success, 1 if no changes found.
1071 Returns 0 on success, 1 if no changes found.
1072 """
1072 """
1073 revs = None
1073 revs = None
1074 if 'rev' in opts:
1074 if 'rev' in opts:
1075 revs = scmutil.revrange(repo, opts['rev'])
1075 revs = scmutil.revrange(repo, opts['rev'])
1076
1076
1077 bundletype = opts.get('type', 'bzip2').lower()
1077 bundletype = opts.get('type', 'bzip2').lower()
1078 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1078 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1079 bundletype = btypes.get(bundletype)
1079 bundletype = btypes.get(bundletype)
1080 if bundletype not in changegroup.bundletypes:
1080 if bundletype not in changegroup.bundletypes:
1081 raise util.Abort(_('unknown bundle type specified with --type'))
1081 raise util.Abort(_('unknown bundle type specified with --type'))
1082
1082
1083 if opts.get('all'):
1083 if opts.get('all'):
1084 base = ['null']
1084 base = ['null']
1085 else:
1085 else:
1086 base = scmutil.revrange(repo, opts.get('base'))
1086 base = scmutil.revrange(repo, opts.get('base'))
1087 if base:
1087 if base:
1088 if dest:
1088 if dest:
1089 raise util.Abort(_("--base is incompatible with specifying "
1089 raise util.Abort(_("--base is incompatible with specifying "
1090 "a destination"))
1090 "a destination"))
1091 common = [repo.lookup(rev) for rev in base]
1091 common = [repo.lookup(rev) for rev in base]
1092 heads = revs and map(repo.lookup, revs) or revs
1092 heads = revs and map(repo.lookup, revs) or revs
1093 cg = repo.getbundle('bundle', heads=heads, common=common)
1093 cg = repo.getbundle('bundle', heads=heads, common=common)
1094 outgoing = None
1094 outgoing = None
1095 else:
1095 else:
1096 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1096 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1097 dest, branches = hg.parseurl(dest, opts.get('branch'))
1097 dest, branches = hg.parseurl(dest, opts.get('branch'))
1098 other = hg.peer(repo, opts, dest)
1098 other = hg.peer(repo, opts, dest)
1099 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1099 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1100 heads = revs and map(repo.lookup, revs) or revs
1100 heads = revs and map(repo.lookup, revs) or revs
1101 outgoing = discovery.findcommonoutgoing(repo, other,
1101 outgoing = discovery.findcommonoutgoing(repo, other,
1102 onlyheads=heads,
1102 onlyheads=heads,
1103 force=opts.get('force'),
1103 force=opts.get('force'),
1104 portable=True)
1104 portable=True)
1105 cg = repo.getlocalbundle('bundle', outgoing)
1105 cg = repo.getlocalbundle('bundle', outgoing)
1106 if not cg:
1106 if not cg:
1107 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1107 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1108 return 1
1108 return 1
1109
1109
1110 changegroup.writebundle(cg, fname, bundletype)
1110 changegroup.writebundle(cg, fname, bundletype)
1111
1111
1112 @command('cat',
1112 @command('cat',
1113 [('o', 'output', '',
1113 [('o', 'output', '',
1114 _('print output to file with formatted name'), _('FORMAT')),
1114 _('print output to file with formatted name'), _('FORMAT')),
1115 ('r', 'rev', '', _('print the given revision'), _('REV')),
1115 ('r', 'rev', '', _('print the given revision'), _('REV')),
1116 ('', 'decode', None, _('apply any matching decode filter')),
1116 ('', 'decode', None, _('apply any matching decode filter')),
1117 ] + walkopts,
1117 ] + walkopts,
1118 _('[OPTION]... FILE...'))
1118 _('[OPTION]... FILE...'))
1119 def cat(ui, repo, file1, *pats, **opts):
1119 def cat(ui, repo, file1, *pats, **opts):
1120 """output the current or given revision of files
1120 """output the current or given revision of files
1121
1121
1122 Print the specified files as they were at the given revision. If
1122 Print the specified files as they were at the given revision. If
1123 no revision is given, the parent of the working directory is used,
1123 no revision is given, the parent of the working directory is used,
1124 or tip if no revision is checked out.
1124 or tip if no revision is checked out.
1125
1125
1126 Output may be to a file, in which case the name of the file is
1126 Output may be to a file, in which case the name of the file is
1127 given using a format string. The formatting rules are the same as
1127 given using a format string. The formatting rules are the same as
1128 for the export command, with the following additions:
1128 for the export command, with the following additions:
1129
1129
1130 :``%s``: basename of file being printed
1130 :``%s``: basename of file being printed
1131 :``%d``: dirname of file being printed, or '.' if in repository root
1131 :``%d``: dirname of file being printed, or '.' if in repository root
1132 :``%p``: root-relative path name of file being printed
1132 :``%p``: root-relative path name of file being printed
1133
1133
1134 Returns 0 on success.
1134 Returns 0 on success.
1135 """
1135 """
1136 ctx = scmutil.revsingle(repo, opts.get('rev'))
1136 ctx = scmutil.revsingle(repo, opts.get('rev'))
1137 err = 1
1137 err = 1
1138 m = scmutil.match(ctx, (file1,) + pats, opts)
1138 m = scmutil.match(ctx, (file1,) + pats, opts)
1139 for abs in ctx.walk(m):
1139 for abs in ctx.walk(m):
1140 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1140 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1141 pathname=abs)
1141 pathname=abs)
1142 data = ctx[abs].data()
1142 data = ctx[abs].data()
1143 if opts.get('decode'):
1143 if opts.get('decode'):
1144 data = repo.wwritedata(abs, data)
1144 data = repo.wwritedata(abs, data)
1145 fp.write(data)
1145 fp.write(data)
1146 fp.close()
1146 fp.close()
1147 err = 0
1147 err = 0
1148 return err
1148 return err
1149
1149
1150 @command('^clone',
1150 @command('^clone',
1151 [('U', 'noupdate', None,
1151 [('U', 'noupdate', None,
1152 _('the clone will include an empty working copy (only a repository)')),
1152 _('the clone will include an empty working copy (only a repository)')),
1153 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1153 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1154 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1154 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1155 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1155 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1156 ('', 'pull', None, _('use pull protocol to copy metadata')),
1156 ('', 'pull', None, _('use pull protocol to copy metadata')),
1157 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1157 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1158 ] + remoteopts,
1158 ] + remoteopts,
1159 _('[OPTION]... SOURCE [DEST]'))
1159 _('[OPTION]... SOURCE [DEST]'))
1160 def clone(ui, source, dest=None, **opts):
1160 def clone(ui, source, dest=None, **opts):
1161 """make a copy of an existing repository
1161 """make a copy of an existing repository
1162
1162
1163 Create a copy of an existing repository in a new directory.
1163 Create a copy of an existing repository in a new directory.
1164
1164
1165 If no destination directory name is specified, it defaults to the
1165 If no destination directory name is specified, it defaults to the
1166 basename of the source.
1166 basename of the source.
1167
1167
1168 The location of the source is added to the new repository's
1168 The location of the source is added to the new repository's
1169 ``.hg/hgrc`` file, as the default to be used for future pulls.
1169 ``.hg/hgrc`` file, as the default to be used for future pulls.
1170
1170
1171 Only local paths and ``ssh://`` URLs are supported as
1171 Only local paths and ``ssh://`` URLs are supported as
1172 destinations. For ``ssh://`` destinations, no working directory or
1172 destinations. For ``ssh://`` destinations, no working directory or
1173 ``.hg/hgrc`` will be created on the remote side.
1173 ``.hg/hgrc`` will be created on the remote side.
1174
1174
1175 To pull only a subset of changesets, specify one or more revisions
1175 To pull only a subset of changesets, specify one or more revisions
1176 identifiers with -r/--rev or branches with -b/--branch. The
1176 identifiers with -r/--rev or branches with -b/--branch. The
1177 resulting clone will contain only the specified changesets and
1177 resulting clone will contain only the specified changesets and
1178 their ancestors. These options (or 'clone src#rev dest') imply
1178 their ancestors. These options (or 'clone src#rev dest') imply
1179 --pull, even for local source repositories. Note that specifying a
1179 --pull, even for local source repositories. Note that specifying a
1180 tag will include the tagged changeset but not the changeset
1180 tag will include the tagged changeset but not the changeset
1181 containing the tag.
1181 containing the tag.
1182
1182
1183 If the source repository has a bookmark called '@' set, that
1183 If the source repository has a bookmark called '@' set, that
1184 revision will be checked out in the new repository by default.
1184 revision will be checked out in the new repository by default.
1185
1185
1186 To check out a particular version, use -u/--update, or
1186 To check out a particular version, use -u/--update, or
1187 -U/--noupdate to create a clone with no working directory.
1187 -U/--noupdate to create a clone with no working directory.
1188
1188
1189 .. container:: verbose
1189 .. container:: verbose
1190
1190
1191 For efficiency, hardlinks are used for cloning whenever the
1191 For efficiency, hardlinks are used for cloning whenever the
1192 source and destination are on the same filesystem (note this
1192 source and destination are on the same filesystem (note this
1193 applies only to the repository data, not to the working
1193 applies only to the repository data, not to the working
1194 directory). Some filesystems, such as AFS, implement hardlinking
1194 directory). Some filesystems, such as AFS, implement hardlinking
1195 incorrectly, but do not report errors. In these cases, use the
1195 incorrectly, but do not report errors. In these cases, use the
1196 --pull option to avoid hardlinking.
1196 --pull option to avoid hardlinking.
1197
1197
1198 In some cases, you can clone repositories and the working
1198 In some cases, you can clone repositories and the working
1199 directory using full hardlinks with ::
1199 directory using full hardlinks with ::
1200
1200
1201 $ cp -al REPO REPOCLONE
1201 $ cp -al REPO REPOCLONE
1202
1202
1203 This is the fastest way to clone, but it is not always safe. The
1203 This is the fastest way to clone, but it is not always safe. The
1204 operation is not atomic (making sure REPO is not modified during
1204 operation is not atomic (making sure REPO is not modified during
1205 the operation is up to you) and you have to make sure your
1205 the operation is up to you) and you have to make sure your
1206 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1206 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1207 so). Also, this is not compatible with certain extensions that
1207 so). Also, this is not compatible with certain extensions that
1208 place their metadata under the .hg directory, such as mq.
1208 place their metadata under the .hg directory, such as mq.
1209
1209
1210 Mercurial will update the working directory to the first applicable
1210 Mercurial will update the working directory to the first applicable
1211 revision from this list:
1211 revision from this list:
1212
1212
1213 a) null if -U or the source repository has no changesets
1213 a) null if -U or the source repository has no changesets
1214 b) if -u . and the source repository is local, the first parent of
1214 b) if -u . and the source repository is local, the first parent of
1215 the source repository's working directory
1215 the source repository's working directory
1216 c) the changeset specified with -u (if a branch name, this means the
1216 c) the changeset specified with -u (if a branch name, this means the
1217 latest head of that branch)
1217 latest head of that branch)
1218 d) the changeset specified with -r
1218 d) the changeset specified with -r
1219 e) the tipmost head specified with -b
1219 e) the tipmost head specified with -b
1220 f) the tipmost head specified with the url#branch source syntax
1220 f) the tipmost head specified with the url#branch source syntax
1221 g) the revision marked with the '@' bookmark, if present
1221 g) the revision marked with the '@' bookmark, if present
1222 h) the tipmost head of the default branch
1222 h) the tipmost head of the default branch
1223 i) tip
1223 i) tip
1224
1224
1225 Examples:
1225 Examples:
1226
1226
1227 - clone a remote repository to a new directory named hg/::
1227 - clone a remote repository to a new directory named hg/::
1228
1228
1229 hg clone http://selenic.com/hg
1229 hg clone http://selenic.com/hg
1230
1230
1231 - create a lightweight local clone::
1231 - create a lightweight local clone::
1232
1232
1233 hg clone project/ project-feature/
1233 hg clone project/ project-feature/
1234
1234
1235 - clone from an absolute path on an ssh server (note double-slash)::
1235 - clone from an absolute path on an ssh server (note double-slash)::
1236
1236
1237 hg clone ssh://user@server//home/projects/alpha/
1237 hg clone ssh://user@server//home/projects/alpha/
1238
1238
1239 - do a high-speed clone over a LAN while checking out a
1239 - do a high-speed clone over a LAN while checking out a
1240 specified version::
1240 specified version::
1241
1241
1242 hg clone --uncompressed http://server/repo -u 1.5
1242 hg clone --uncompressed http://server/repo -u 1.5
1243
1243
1244 - create a repository without changesets after a particular revision::
1244 - create a repository without changesets after a particular revision::
1245
1245
1246 hg clone -r 04e544 experimental/ good/
1246 hg clone -r 04e544 experimental/ good/
1247
1247
1248 - clone (and track) a particular named branch::
1248 - clone (and track) a particular named branch::
1249
1249
1250 hg clone http://selenic.com/hg#stable
1250 hg clone http://selenic.com/hg#stable
1251
1251
1252 See :hg:`help urls` for details on specifying URLs.
1252 See :hg:`help urls` for details on specifying URLs.
1253
1253
1254 Returns 0 on success.
1254 Returns 0 on success.
1255 """
1255 """
1256 if opts.get('noupdate') and opts.get('updaterev'):
1256 if opts.get('noupdate') and opts.get('updaterev'):
1257 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1257 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1258
1258
1259 r = hg.clone(ui, opts, source, dest,
1259 r = hg.clone(ui, opts, source, dest,
1260 pull=opts.get('pull'),
1260 pull=opts.get('pull'),
1261 stream=opts.get('uncompressed'),
1261 stream=opts.get('uncompressed'),
1262 rev=opts.get('rev'),
1262 rev=opts.get('rev'),
1263 update=opts.get('updaterev') or not opts.get('noupdate'),
1263 update=opts.get('updaterev') or not opts.get('noupdate'),
1264 branch=opts.get('branch'))
1264 branch=opts.get('branch'))
1265
1265
1266 return r is None
1266 return r is None
1267
1267
1268 @command('^commit|ci',
1268 @command('^commit|ci',
1269 [('A', 'addremove', None,
1269 [('A', 'addremove', None,
1270 _('mark new/missing files as added/removed before committing')),
1270 _('mark new/missing files as added/removed before committing')),
1271 ('', 'close-branch', None,
1271 ('', 'close-branch', None,
1272 _('mark a branch as closed, hiding it from the branch list')),
1272 _('mark a branch as closed, hiding it from the branch list')),
1273 ('', 'amend', None, _('amend the parent of the working dir')),
1273 ('', 'amend', None, _('amend the parent of the working dir')),
1274 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1274 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1275 _('[OPTION]... [FILE]...'))
1275 _('[OPTION]... [FILE]...'))
1276 def commit(ui, repo, *pats, **opts):
1276 def commit(ui, repo, *pats, **opts):
1277 """commit the specified files or all outstanding changes
1277 """commit the specified files or all outstanding changes
1278
1278
1279 Commit changes to the given files into the repository. Unlike a
1279 Commit changes to the given files into the repository. Unlike a
1280 centralized SCM, this operation is a local operation. See
1280 centralized SCM, this operation is a local operation. See
1281 :hg:`push` for a way to actively distribute your changes.
1281 :hg:`push` for a way to actively distribute your changes.
1282
1282
1283 If a list of files is omitted, all changes reported by :hg:`status`
1283 If a list of files is omitted, all changes reported by :hg:`status`
1284 will be committed.
1284 will be committed.
1285
1285
1286 If you are committing the result of a merge, do not provide any
1286 If you are committing the result of a merge, do not provide any
1287 filenames or -I/-X filters.
1287 filenames or -I/-X filters.
1288
1288
1289 If no commit message is specified, Mercurial starts your
1289 If no commit message is specified, Mercurial starts your
1290 configured editor where you can enter a message. In case your
1290 configured editor where you can enter a message. In case your
1291 commit fails, you will find a backup of your message in
1291 commit fails, you will find a backup of your message in
1292 ``.hg/last-message.txt``.
1292 ``.hg/last-message.txt``.
1293
1293
1294 The --amend flag can be used to amend the parent of the
1294 The --amend flag can be used to amend the parent of the
1295 working directory with a new commit that contains the changes
1295 working directory with a new commit that contains the changes
1296 in the parent in addition to those currently reported by :hg:`status`,
1296 in the parent in addition to those currently reported by :hg:`status`,
1297 if there are any. The old commit is stored in a backup bundle in
1297 if there are any. The old commit is stored in a backup bundle in
1298 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1298 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1299 on how to restore it).
1299 on how to restore it).
1300
1300
1301 Message, user and date are taken from the amended commit unless
1301 Message, user and date are taken from the amended commit unless
1302 specified. When a message isn't specified on the command line,
1302 specified. When a message isn't specified on the command line,
1303 the editor will open with the message of the amended commit.
1303 the editor will open with the message of the amended commit.
1304
1304
1305 It is not possible to amend public changesets (see :hg:`help phases`)
1305 It is not possible to amend public changesets (see :hg:`help phases`)
1306 or changesets that have children.
1306 or changesets that have children.
1307
1307
1308 See :hg:`help dates` for a list of formats valid for -d/--date.
1308 See :hg:`help dates` for a list of formats valid for -d/--date.
1309
1309
1310 Returns 0 on success, 1 if nothing changed.
1310 Returns 0 on success, 1 if nothing changed.
1311 """
1311 """
1312 if opts.get('subrepos'):
1312 if opts.get('subrepos'):
1313 if opts.get('amend'):
1313 if opts.get('amend'):
1314 raise util.Abort(_('cannot amend with --subrepos'))
1314 raise util.Abort(_('cannot amend with --subrepos'))
1315 # Let --subrepos on the command line override config setting.
1315 # Let --subrepos on the command line override config setting.
1316 ui.setconfig('ui', 'commitsubrepos', True)
1316 ui.setconfig('ui', 'commitsubrepos', True)
1317
1317
1318 if repo.vfs.exists('graftstate'):
1318 if repo.vfs.exists('graftstate'):
1319 raise util.Abort(_('cannot commit an interrupted graft operation'),
1319 raise util.Abort(_('cannot commit an interrupted graft operation'),
1320 hint=_('use "hg graft -c" to continue graft'))
1320 hint=_('use "hg graft -c" to continue graft'))
1321
1321
1322 branch = repo[None].branch()
1323 bheads = repo.branchheads(branch)
1324
1322 extra = {}
1325 extra = {}
1323 if opts.get('close_branch'):
1326 if opts.get('close_branch'):
1324 extra['close'] = 1
1327 extra['close'] = 1
1325
1328
1326 branch = repo[None].branch()
1329 if not bheads:
1327 bheads = repo.branchheads(branch)
1330 raise util.Abort(_('can only close branch heads'))
1331 elif opts.get('amend'):
1332 if repo.parents()[0].p1().branch() != branch and \
1333 repo.parents()[0].p2().branch() != branch:
1334 raise util.Abort(_('can only close branch heads'))
1328
1335
1329 if opts.get('amend'):
1336 if opts.get('amend'):
1330 if ui.configbool('ui', 'commitsubrepos'):
1337 if ui.configbool('ui', 'commitsubrepos'):
1331 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1338 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1332
1339
1333 old = repo['.']
1340 old = repo['.']
1334 if old.phase() == phases.public:
1341 if old.phase() == phases.public:
1335 raise util.Abort(_('cannot amend public changesets'))
1342 raise util.Abort(_('cannot amend public changesets'))
1336 if len(repo[None].parents()) > 1:
1343 if len(repo[None].parents()) > 1:
1337 raise util.Abort(_('cannot amend while merging'))
1344 raise util.Abort(_('cannot amend while merging'))
1338 if (not obsolete._enabled) and old.children():
1345 if (not obsolete._enabled) and old.children():
1339 raise util.Abort(_('cannot amend changeset with children'))
1346 raise util.Abort(_('cannot amend changeset with children'))
1340
1347
1341 e = cmdutil.commiteditor
1348 e = cmdutil.commiteditor
1342 if opts.get('force_editor'):
1349 if opts.get('force_editor'):
1343 e = cmdutil.commitforceeditor
1350 e = cmdutil.commitforceeditor
1344
1351
1345 def commitfunc(ui, repo, message, match, opts):
1352 def commitfunc(ui, repo, message, match, opts):
1346 editor = e
1353 editor = e
1347 # message contains text from -m or -l, if it's empty,
1354 # message contains text from -m or -l, if it's empty,
1348 # open the editor with the old message
1355 # open the editor with the old message
1349 if not message:
1356 if not message:
1350 message = old.description()
1357 message = old.description()
1351 editor = cmdutil.commitforceeditor
1358 editor = cmdutil.commitforceeditor
1352 return repo.commit(message,
1359 return repo.commit(message,
1353 opts.get('user') or old.user(),
1360 opts.get('user') or old.user(),
1354 opts.get('date') or old.date(),
1361 opts.get('date') or old.date(),
1355 match,
1362 match,
1356 editor=editor,
1363 editor=editor,
1357 extra=extra)
1364 extra=extra)
1358
1365
1359 current = repo._bookmarkcurrent
1366 current = repo._bookmarkcurrent
1360 marks = old.bookmarks()
1367 marks = old.bookmarks()
1361 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1368 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1362 if node == old.node():
1369 if node == old.node():
1363 ui.status(_("nothing changed\n"))
1370 ui.status(_("nothing changed\n"))
1364 return 1
1371 return 1
1365 elif marks:
1372 elif marks:
1366 ui.debug('moving bookmarks %r from %s to %s\n' %
1373 ui.debug('moving bookmarks %r from %s to %s\n' %
1367 (marks, old.hex(), hex(node)))
1374 (marks, old.hex(), hex(node)))
1368 newmarks = repo._bookmarks
1375 newmarks = repo._bookmarks
1369 for bm in marks:
1376 for bm in marks:
1370 newmarks[bm] = node
1377 newmarks[bm] = node
1371 if bm == current:
1378 if bm == current:
1372 bookmarks.setcurrent(repo, bm)
1379 bookmarks.setcurrent(repo, bm)
1373 newmarks.write()
1380 newmarks.write()
1374 else:
1381 else:
1375 e = cmdutil.commiteditor
1382 e = cmdutil.commiteditor
1376 if opts.get('force_editor'):
1383 if opts.get('force_editor'):
1377 e = cmdutil.commitforceeditor
1384 e = cmdutil.commitforceeditor
1378
1385
1379 def commitfunc(ui, repo, message, match, opts):
1386 def commitfunc(ui, repo, message, match, opts):
1380 return repo.commit(message, opts.get('user'), opts.get('date'),
1387 return repo.commit(message, opts.get('user'), opts.get('date'),
1381 match, editor=e, extra=extra)
1388 match, editor=e, extra=extra)
1382
1389
1383 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1390 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1384
1391
1385 if not node:
1392 if not node:
1386 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1393 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1387 if stat[3]:
1394 if stat[3]:
1388 ui.status(_("nothing changed (%d missing files, see "
1395 ui.status(_("nothing changed (%d missing files, see "
1389 "'hg status')\n") % len(stat[3]))
1396 "'hg status')\n") % len(stat[3]))
1390 else:
1397 else:
1391 ui.status(_("nothing changed\n"))
1398 ui.status(_("nothing changed\n"))
1392 return 1
1399 return 1
1393
1400
1394 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1401 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1395
1402
1396 @command('copy|cp',
1403 @command('copy|cp',
1397 [('A', 'after', None, _('record a copy that has already occurred')),
1404 [('A', 'after', None, _('record a copy that has already occurred')),
1398 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1405 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1399 ] + walkopts + dryrunopts,
1406 ] + walkopts + dryrunopts,
1400 _('[OPTION]... [SOURCE]... DEST'))
1407 _('[OPTION]... [SOURCE]... DEST'))
1401 def copy(ui, repo, *pats, **opts):
1408 def copy(ui, repo, *pats, **opts):
1402 """mark files as copied for the next commit
1409 """mark files as copied for the next commit
1403
1410
1404 Mark dest as having copies of source files. If dest is a
1411 Mark dest as having copies of source files. If dest is a
1405 directory, copies are put in that directory. If dest is a file,
1412 directory, copies are put in that directory. If dest is a file,
1406 the source must be a single file.
1413 the source must be a single file.
1407
1414
1408 By default, this command copies the contents of files as they
1415 By default, this command copies the contents of files as they
1409 exist in the working directory. If invoked with -A/--after, the
1416 exist in the working directory. If invoked with -A/--after, the
1410 operation is recorded, but no copying is performed.
1417 operation is recorded, but no copying is performed.
1411
1418
1412 This command takes effect with the next commit. To undo a copy
1419 This command takes effect with the next commit. To undo a copy
1413 before that, see :hg:`revert`.
1420 before that, see :hg:`revert`.
1414
1421
1415 Returns 0 on success, 1 if errors are encountered.
1422 Returns 0 on success, 1 if errors are encountered.
1416 """
1423 """
1417 wlock = repo.wlock(False)
1424 wlock = repo.wlock(False)
1418 try:
1425 try:
1419 return cmdutil.copy(ui, repo, pats, opts)
1426 return cmdutil.copy(ui, repo, pats, opts)
1420 finally:
1427 finally:
1421 wlock.release()
1428 wlock.release()
1422
1429
1423 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1430 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1424 def debugancestor(ui, repo, *args):
1431 def debugancestor(ui, repo, *args):
1425 """find the ancestor revision of two revisions in a given index"""
1432 """find the ancestor revision of two revisions in a given index"""
1426 if len(args) == 3:
1433 if len(args) == 3:
1427 index, rev1, rev2 = args
1434 index, rev1, rev2 = args
1428 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1435 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1429 lookup = r.lookup
1436 lookup = r.lookup
1430 elif len(args) == 2:
1437 elif len(args) == 2:
1431 if not repo:
1438 if not repo:
1432 raise util.Abort(_("there is no Mercurial repository here "
1439 raise util.Abort(_("there is no Mercurial repository here "
1433 "(.hg not found)"))
1440 "(.hg not found)"))
1434 rev1, rev2 = args
1441 rev1, rev2 = args
1435 r = repo.changelog
1442 r = repo.changelog
1436 lookup = repo.lookup
1443 lookup = repo.lookup
1437 else:
1444 else:
1438 raise util.Abort(_('either two or three arguments required'))
1445 raise util.Abort(_('either two or three arguments required'))
1439 a = r.ancestor(lookup(rev1), lookup(rev2))
1446 a = r.ancestor(lookup(rev1), lookup(rev2))
1440 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1447 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1441
1448
1442 @command('debugbuilddag',
1449 @command('debugbuilddag',
1443 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1450 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1444 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1451 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1445 ('n', 'new-file', None, _('add new file at each rev'))],
1452 ('n', 'new-file', None, _('add new file at each rev'))],
1446 _('[OPTION]... [TEXT]'))
1453 _('[OPTION]... [TEXT]'))
1447 def debugbuilddag(ui, repo, text=None,
1454 def debugbuilddag(ui, repo, text=None,
1448 mergeable_file=False,
1455 mergeable_file=False,
1449 overwritten_file=False,
1456 overwritten_file=False,
1450 new_file=False):
1457 new_file=False):
1451 """builds a repo with a given DAG from scratch in the current empty repo
1458 """builds a repo with a given DAG from scratch in the current empty repo
1452
1459
1453 The description of the DAG is read from stdin if not given on the
1460 The description of the DAG is read from stdin if not given on the
1454 command line.
1461 command line.
1455
1462
1456 Elements:
1463 Elements:
1457
1464
1458 - "+n" is a linear run of n nodes based on the current default parent
1465 - "+n" is a linear run of n nodes based on the current default parent
1459 - "." is a single node based on the current default parent
1466 - "." is a single node based on the current default parent
1460 - "$" resets the default parent to null (implied at the start);
1467 - "$" resets the default parent to null (implied at the start);
1461 otherwise the default parent is always the last node created
1468 otherwise the default parent is always the last node created
1462 - "<p" sets the default parent to the backref p
1469 - "<p" sets the default parent to the backref p
1463 - "*p" is a fork at parent p, which is a backref
1470 - "*p" is a fork at parent p, which is a backref
1464 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1471 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1465 - "/p2" is a merge of the preceding node and p2
1472 - "/p2" is a merge of the preceding node and p2
1466 - ":tag" defines a local tag for the preceding node
1473 - ":tag" defines a local tag for the preceding node
1467 - "@branch" sets the named branch for subsequent nodes
1474 - "@branch" sets the named branch for subsequent nodes
1468 - "#...\\n" is a comment up to the end of the line
1475 - "#...\\n" is a comment up to the end of the line
1469
1476
1470 Whitespace between the above elements is ignored.
1477 Whitespace between the above elements is ignored.
1471
1478
1472 A backref is either
1479 A backref is either
1473
1480
1474 - a number n, which references the node curr-n, where curr is the current
1481 - a number n, which references the node curr-n, where curr is the current
1475 node, or
1482 node, or
1476 - the name of a local tag you placed earlier using ":tag", or
1483 - the name of a local tag you placed earlier using ":tag", or
1477 - empty to denote the default parent.
1484 - empty to denote the default parent.
1478
1485
1479 All string valued-elements are either strictly alphanumeric, or must
1486 All string valued-elements are either strictly alphanumeric, or must
1480 be enclosed in double quotes ("..."), with "\\" as escape character.
1487 be enclosed in double quotes ("..."), with "\\" as escape character.
1481 """
1488 """
1482
1489
1483 if text is None:
1490 if text is None:
1484 ui.status(_("reading DAG from stdin\n"))
1491 ui.status(_("reading DAG from stdin\n"))
1485 text = ui.fin.read()
1492 text = ui.fin.read()
1486
1493
1487 cl = repo.changelog
1494 cl = repo.changelog
1488 if len(cl) > 0:
1495 if len(cl) > 0:
1489 raise util.Abort(_('repository is not empty'))
1496 raise util.Abort(_('repository is not empty'))
1490
1497
1491 # determine number of revs in DAG
1498 # determine number of revs in DAG
1492 total = 0
1499 total = 0
1493 for type, data in dagparser.parsedag(text):
1500 for type, data in dagparser.parsedag(text):
1494 if type == 'n':
1501 if type == 'n':
1495 total += 1
1502 total += 1
1496
1503
1497 if mergeable_file:
1504 if mergeable_file:
1498 linesperrev = 2
1505 linesperrev = 2
1499 # make a file with k lines per rev
1506 # make a file with k lines per rev
1500 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1507 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1501 initialmergedlines.append("")
1508 initialmergedlines.append("")
1502
1509
1503 tags = []
1510 tags = []
1504
1511
1505 lock = tr = None
1512 lock = tr = None
1506 try:
1513 try:
1507 lock = repo.lock()
1514 lock = repo.lock()
1508 tr = repo.transaction("builddag")
1515 tr = repo.transaction("builddag")
1509
1516
1510 at = -1
1517 at = -1
1511 atbranch = 'default'
1518 atbranch = 'default'
1512 nodeids = []
1519 nodeids = []
1513 id = 0
1520 id = 0
1514 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1521 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1515 for type, data in dagparser.parsedag(text):
1522 for type, data in dagparser.parsedag(text):
1516 if type == 'n':
1523 if type == 'n':
1517 ui.note(('node %s\n' % str(data)))
1524 ui.note(('node %s\n' % str(data)))
1518 id, ps = data
1525 id, ps = data
1519
1526
1520 files = []
1527 files = []
1521 fctxs = {}
1528 fctxs = {}
1522
1529
1523 p2 = None
1530 p2 = None
1524 if mergeable_file:
1531 if mergeable_file:
1525 fn = "mf"
1532 fn = "mf"
1526 p1 = repo[ps[0]]
1533 p1 = repo[ps[0]]
1527 if len(ps) > 1:
1534 if len(ps) > 1:
1528 p2 = repo[ps[1]]
1535 p2 = repo[ps[1]]
1529 pa = p1.ancestor(p2)
1536 pa = p1.ancestor(p2)
1530 base, local, other = [x[fn].data() for x in (pa, p1,
1537 base, local, other = [x[fn].data() for x in (pa, p1,
1531 p2)]
1538 p2)]
1532 m3 = simplemerge.Merge3Text(base, local, other)
1539 m3 = simplemerge.Merge3Text(base, local, other)
1533 ml = [l.strip() for l in m3.merge_lines()]
1540 ml = [l.strip() for l in m3.merge_lines()]
1534 ml.append("")
1541 ml.append("")
1535 elif at > 0:
1542 elif at > 0:
1536 ml = p1[fn].data().split("\n")
1543 ml = p1[fn].data().split("\n")
1537 else:
1544 else:
1538 ml = initialmergedlines
1545 ml = initialmergedlines
1539 ml[id * linesperrev] += " r%i" % id
1546 ml[id * linesperrev] += " r%i" % id
1540 mergedtext = "\n".join(ml)
1547 mergedtext = "\n".join(ml)
1541 files.append(fn)
1548 files.append(fn)
1542 fctxs[fn] = context.memfilectx(fn, mergedtext)
1549 fctxs[fn] = context.memfilectx(fn, mergedtext)
1543
1550
1544 if overwritten_file:
1551 if overwritten_file:
1545 fn = "of"
1552 fn = "of"
1546 files.append(fn)
1553 files.append(fn)
1547 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1554 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1548
1555
1549 if new_file:
1556 if new_file:
1550 fn = "nf%i" % id
1557 fn = "nf%i" % id
1551 files.append(fn)
1558 files.append(fn)
1552 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1559 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1553 if len(ps) > 1:
1560 if len(ps) > 1:
1554 if not p2:
1561 if not p2:
1555 p2 = repo[ps[1]]
1562 p2 = repo[ps[1]]
1556 for fn in p2:
1563 for fn in p2:
1557 if fn.startswith("nf"):
1564 if fn.startswith("nf"):
1558 files.append(fn)
1565 files.append(fn)
1559 fctxs[fn] = p2[fn]
1566 fctxs[fn] = p2[fn]
1560
1567
1561 def fctxfn(repo, cx, path):
1568 def fctxfn(repo, cx, path):
1562 return fctxs.get(path)
1569 return fctxs.get(path)
1563
1570
1564 if len(ps) == 0 or ps[0] < 0:
1571 if len(ps) == 0 or ps[0] < 0:
1565 pars = [None, None]
1572 pars = [None, None]
1566 elif len(ps) == 1:
1573 elif len(ps) == 1:
1567 pars = [nodeids[ps[0]], None]
1574 pars = [nodeids[ps[0]], None]
1568 else:
1575 else:
1569 pars = [nodeids[p] for p in ps]
1576 pars = [nodeids[p] for p in ps]
1570 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1577 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1571 date=(id, 0),
1578 date=(id, 0),
1572 user="debugbuilddag",
1579 user="debugbuilddag",
1573 extra={'branch': atbranch})
1580 extra={'branch': atbranch})
1574 nodeid = repo.commitctx(cx)
1581 nodeid = repo.commitctx(cx)
1575 nodeids.append(nodeid)
1582 nodeids.append(nodeid)
1576 at = id
1583 at = id
1577 elif type == 'l':
1584 elif type == 'l':
1578 id, name = data
1585 id, name = data
1579 ui.note(('tag %s\n' % name))
1586 ui.note(('tag %s\n' % name))
1580 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1587 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1581 elif type == 'a':
1588 elif type == 'a':
1582 ui.note(('branch %s\n' % data))
1589 ui.note(('branch %s\n' % data))
1583 atbranch = data
1590 atbranch = data
1584 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1591 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1585 tr.close()
1592 tr.close()
1586
1593
1587 if tags:
1594 if tags:
1588 repo.opener.write("localtags", "".join(tags))
1595 repo.opener.write("localtags", "".join(tags))
1589 finally:
1596 finally:
1590 ui.progress(_('building'), None)
1597 ui.progress(_('building'), None)
1591 release(tr, lock)
1598 release(tr, lock)
1592
1599
1593 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1600 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1594 def debugbundle(ui, bundlepath, all=None, **opts):
1601 def debugbundle(ui, bundlepath, all=None, **opts):
1595 """lists the contents of a bundle"""
1602 """lists the contents of a bundle"""
1596 f = hg.openpath(ui, bundlepath)
1603 f = hg.openpath(ui, bundlepath)
1597 try:
1604 try:
1598 gen = changegroup.readbundle(f, bundlepath)
1605 gen = changegroup.readbundle(f, bundlepath)
1599 if all:
1606 if all:
1600 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1607 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1601
1608
1602 def showchunks(named):
1609 def showchunks(named):
1603 ui.write("\n%s\n" % named)
1610 ui.write("\n%s\n" % named)
1604 chain = None
1611 chain = None
1605 while True:
1612 while True:
1606 chunkdata = gen.deltachunk(chain)
1613 chunkdata = gen.deltachunk(chain)
1607 if not chunkdata:
1614 if not chunkdata:
1608 break
1615 break
1609 node = chunkdata['node']
1616 node = chunkdata['node']
1610 p1 = chunkdata['p1']
1617 p1 = chunkdata['p1']
1611 p2 = chunkdata['p2']
1618 p2 = chunkdata['p2']
1612 cs = chunkdata['cs']
1619 cs = chunkdata['cs']
1613 deltabase = chunkdata['deltabase']
1620 deltabase = chunkdata['deltabase']
1614 delta = chunkdata['delta']
1621 delta = chunkdata['delta']
1615 ui.write("%s %s %s %s %s %s\n" %
1622 ui.write("%s %s %s %s %s %s\n" %
1616 (hex(node), hex(p1), hex(p2),
1623 (hex(node), hex(p1), hex(p2),
1617 hex(cs), hex(deltabase), len(delta)))
1624 hex(cs), hex(deltabase), len(delta)))
1618 chain = node
1625 chain = node
1619
1626
1620 chunkdata = gen.changelogheader()
1627 chunkdata = gen.changelogheader()
1621 showchunks("changelog")
1628 showchunks("changelog")
1622 chunkdata = gen.manifestheader()
1629 chunkdata = gen.manifestheader()
1623 showchunks("manifest")
1630 showchunks("manifest")
1624 while True:
1631 while True:
1625 chunkdata = gen.filelogheader()
1632 chunkdata = gen.filelogheader()
1626 if not chunkdata:
1633 if not chunkdata:
1627 break
1634 break
1628 fname = chunkdata['filename']
1635 fname = chunkdata['filename']
1629 showchunks(fname)
1636 showchunks(fname)
1630 else:
1637 else:
1631 chunkdata = gen.changelogheader()
1638 chunkdata = gen.changelogheader()
1632 chain = None
1639 chain = None
1633 while True:
1640 while True:
1634 chunkdata = gen.deltachunk(chain)
1641 chunkdata = gen.deltachunk(chain)
1635 if not chunkdata:
1642 if not chunkdata:
1636 break
1643 break
1637 node = chunkdata['node']
1644 node = chunkdata['node']
1638 ui.write("%s\n" % hex(node))
1645 ui.write("%s\n" % hex(node))
1639 chain = node
1646 chain = node
1640 finally:
1647 finally:
1641 f.close()
1648 f.close()
1642
1649
1643 @command('debugcheckstate', [], '')
1650 @command('debugcheckstate', [], '')
1644 def debugcheckstate(ui, repo):
1651 def debugcheckstate(ui, repo):
1645 """validate the correctness of the current dirstate"""
1652 """validate the correctness of the current dirstate"""
1646 parent1, parent2 = repo.dirstate.parents()
1653 parent1, parent2 = repo.dirstate.parents()
1647 m1 = repo[parent1].manifest()
1654 m1 = repo[parent1].manifest()
1648 m2 = repo[parent2].manifest()
1655 m2 = repo[parent2].manifest()
1649 errors = 0
1656 errors = 0
1650 for f in repo.dirstate:
1657 for f in repo.dirstate:
1651 state = repo.dirstate[f]
1658 state = repo.dirstate[f]
1652 if state in "nr" and f not in m1:
1659 if state in "nr" and f not in m1:
1653 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1660 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1654 errors += 1
1661 errors += 1
1655 if state in "a" and f in m1:
1662 if state in "a" and f in m1:
1656 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1663 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1657 errors += 1
1664 errors += 1
1658 if state in "m" and f not in m1 and f not in m2:
1665 if state in "m" and f not in m1 and f not in m2:
1659 ui.warn(_("%s in state %s, but not in either manifest\n") %
1666 ui.warn(_("%s in state %s, but not in either manifest\n") %
1660 (f, state))
1667 (f, state))
1661 errors += 1
1668 errors += 1
1662 for f in m1:
1669 for f in m1:
1663 state = repo.dirstate[f]
1670 state = repo.dirstate[f]
1664 if state not in "nrm":
1671 if state not in "nrm":
1665 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1672 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1666 errors += 1
1673 errors += 1
1667 if errors:
1674 if errors:
1668 error = _(".hg/dirstate inconsistent with current parent's manifest")
1675 error = _(".hg/dirstate inconsistent with current parent's manifest")
1669 raise util.Abort(error)
1676 raise util.Abort(error)
1670
1677
1671 @command('debugcommands', [], _('[COMMAND]'))
1678 @command('debugcommands', [], _('[COMMAND]'))
1672 def debugcommands(ui, cmd='', *args):
1679 def debugcommands(ui, cmd='', *args):
1673 """list all available commands and options"""
1680 """list all available commands and options"""
1674 for cmd, vals in sorted(table.iteritems()):
1681 for cmd, vals in sorted(table.iteritems()):
1675 cmd = cmd.split('|')[0].strip('^')
1682 cmd = cmd.split('|')[0].strip('^')
1676 opts = ', '.join([i[1] for i in vals[1]])
1683 opts = ', '.join([i[1] for i in vals[1]])
1677 ui.write('%s: %s\n' % (cmd, opts))
1684 ui.write('%s: %s\n' % (cmd, opts))
1678
1685
1679 @command('debugcomplete',
1686 @command('debugcomplete',
1680 [('o', 'options', None, _('show the command options'))],
1687 [('o', 'options', None, _('show the command options'))],
1681 _('[-o] CMD'))
1688 _('[-o] CMD'))
1682 def debugcomplete(ui, cmd='', **opts):
1689 def debugcomplete(ui, cmd='', **opts):
1683 """returns the completion list associated with the given command"""
1690 """returns the completion list associated with the given command"""
1684
1691
1685 if opts.get('options'):
1692 if opts.get('options'):
1686 options = []
1693 options = []
1687 otables = [globalopts]
1694 otables = [globalopts]
1688 if cmd:
1695 if cmd:
1689 aliases, entry = cmdutil.findcmd(cmd, table, False)
1696 aliases, entry = cmdutil.findcmd(cmd, table, False)
1690 otables.append(entry[1])
1697 otables.append(entry[1])
1691 for t in otables:
1698 for t in otables:
1692 for o in t:
1699 for o in t:
1693 if "(DEPRECATED)" in o[3]:
1700 if "(DEPRECATED)" in o[3]:
1694 continue
1701 continue
1695 if o[0]:
1702 if o[0]:
1696 options.append('-%s' % o[0])
1703 options.append('-%s' % o[0])
1697 options.append('--%s' % o[1])
1704 options.append('--%s' % o[1])
1698 ui.write("%s\n" % "\n".join(options))
1705 ui.write("%s\n" % "\n".join(options))
1699 return
1706 return
1700
1707
1701 cmdlist = cmdutil.findpossible(cmd, table)
1708 cmdlist = cmdutil.findpossible(cmd, table)
1702 if ui.verbose:
1709 if ui.verbose:
1703 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1710 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1704 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1711 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1705
1712
1706 @command('debugdag',
1713 @command('debugdag',
1707 [('t', 'tags', None, _('use tags as labels')),
1714 [('t', 'tags', None, _('use tags as labels')),
1708 ('b', 'branches', None, _('annotate with branch names')),
1715 ('b', 'branches', None, _('annotate with branch names')),
1709 ('', 'dots', None, _('use dots for runs')),
1716 ('', 'dots', None, _('use dots for runs')),
1710 ('s', 'spaces', None, _('separate elements by spaces'))],
1717 ('s', 'spaces', None, _('separate elements by spaces'))],
1711 _('[OPTION]... [FILE [REV]...]'))
1718 _('[OPTION]... [FILE [REV]...]'))
1712 def debugdag(ui, repo, file_=None, *revs, **opts):
1719 def debugdag(ui, repo, file_=None, *revs, **opts):
1713 """format the changelog or an index DAG as a concise textual description
1720 """format the changelog or an index DAG as a concise textual description
1714
1721
1715 If you pass a revlog index, the revlog's DAG is emitted. If you list
1722 If you pass a revlog index, the revlog's DAG is emitted. If you list
1716 revision numbers, they get labeled in the output as rN.
1723 revision numbers, they get labeled in the output as rN.
1717
1724
1718 Otherwise, the changelog DAG of the current repo is emitted.
1725 Otherwise, the changelog DAG of the current repo is emitted.
1719 """
1726 """
1720 spaces = opts.get('spaces')
1727 spaces = opts.get('spaces')
1721 dots = opts.get('dots')
1728 dots = opts.get('dots')
1722 if file_:
1729 if file_:
1723 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1730 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1724 revs = set((int(r) for r in revs))
1731 revs = set((int(r) for r in revs))
1725 def events():
1732 def events():
1726 for r in rlog:
1733 for r in rlog:
1727 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1734 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1728 if p != -1)))
1735 if p != -1)))
1729 if r in revs:
1736 if r in revs:
1730 yield 'l', (r, "r%i" % r)
1737 yield 'l', (r, "r%i" % r)
1731 elif repo:
1738 elif repo:
1732 cl = repo.changelog
1739 cl = repo.changelog
1733 tags = opts.get('tags')
1740 tags = opts.get('tags')
1734 branches = opts.get('branches')
1741 branches = opts.get('branches')
1735 if tags:
1742 if tags:
1736 labels = {}
1743 labels = {}
1737 for l, n in repo.tags().items():
1744 for l, n in repo.tags().items():
1738 labels.setdefault(cl.rev(n), []).append(l)
1745 labels.setdefault(cl.rev(n), []).append(l)
1739 def events():
1746 def events():
1740 b = "default"
1747 b = "default"
1741 for r in cl:
1748 for r in cl:
1742 if branches:
1749 if branches:
1743 newb = cl.read(cl.node(r))[5]['branch']
1750 newb = cl.read(cl.node(r))[5]['branch']
1744 if newb != b:
1751 if newb != b:
1745 yield 'a', newb
1752 yield 'a', newb
1746 b = newb
1753 b = newb
1747 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1754 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1748 if p != -1)))
1755 if p != -1)))
1749 if tags:
1756 if tags:
1750 ls = labels.get(r)
1757 ls = labels.get(r)
1751 if ls:
1758 if ls:
1752 for l in ls:
1759 for l in ls:
1753 yield 'l', (r, l)
1760 yield 'l', (r, l)
1754 else:
1761 else:
1755 raise util.Abort(_('need repo for changelog dag'))
1762 raise util.Abort(_('need repo for changelog dag'))
1756
1763
1757 for line in dagparser.dagtextlines(events(),
1764 for line in dagparser.dagtextlines(events(),
1758 addspaces=spaces,
1765 addspaces=spaces,
1759 wraplabels=True,
1766 wraplabels=True,
1760 wrapannotations=True,
1767 wrapannotations=True,
1761 wrapnonlinear=dots,
1768 wrapnonlinear=dots,
1762 usedots=dots,
1769 usedots=dots,
1763 maxlinewidth=70):
1770 maxlinewidth=70):
1764 ui.write(line)
1771 ui.write(line)
1765 ui.write("\n")
1772 ui.write("\n")
1766
1773
1767 @command('debugdata',
1774 @command('debugdata',
1768 [('c', 'changelog', False, _('open changelog')),
1775 [('c', 'changelog', False, _('open changelog')),
1769 ('m', 'manifest', False, _('open manifest'))],
1776 ('m', 'manifest', False, _('open manifest'))],
1770 _('-c|-m|FILE REV'))
1777 _('-c|-m|FILE REV'))
1771 def debugdata(ui, repo, file_, rev = None, **opts):
1778 def debugdata(ui, repo, file_, rev = None, **opts):
1772 """dump the contents of a data file revision"""
1779 """dump the contents of a data file revision"""
1773 if opts.get('changelog') or opts.get('manifest'):
1780 if opts.get('changelog') or opts.get('manifest'):
1774 file_, rev = None, file_
1781 file_, rev = None, file_
1775 elif rev is None:
1782 elif rev is None:
1776 raise error.CommandError('debugdata', _('invalid arguments'))
1783 raise error.CommandError('debugdata', _('invalid arguments'))
1777 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1784 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1778 try:
1785 try:
1779 ui.write(r.revision(r.lookup(rev)))
1786 ui.write(r.revision(r.lookup(rev)))
1780 except KeyError:
1787 except KeyError:
1781 raise util.Abort(_('invalid revision identifier %s') % rev)
1788 raise util.Abort(_('invalid revision identifier %s') % rev)
1782
1789
1783 @command('debugdate',
1790 @command('debugdate',
1784 [('e', 'extended', None, _('try extended date formats'))],
1791 [('e', 'extended', None, _('try extended date formats'))],
1785 _('[-e] DATE [RANGE]'))
1792 _('[-e] DATE [RANGE]'))
1786 def debugdate(ui, date, range=None, **opts):
1793 def debugdate(ui, date, range=None, **opts):
1787 """parse and display a date"""
1794 """parse and display a date"""
1788 if opts["extended"]:
1795 if opts["extended"]:
1789 d = util.parsedate(date, util.extendeddateformats)
1796 d = util.parsedate(date, util.extendeddateformats)
1790 else:
1797 else:
1791 d = util.parsedate(date)
1798 d = util.parsedate(date)
1792 ui.write(("internal: %s %s\n") % d)
1799 ui.write(("internal: %s %s\n") % d)
1793 ui.write(("standard: %s\n") % util.datestr(d))
1800 ui.write(("standard: %s\n") % util.datestr(d))
1794 if range:
1801 if range:
1795 m = util.matchdate(range)
1802 m = util.matchdate(range)
1796 ui.write(("match: %s\n") % m(d[0]))
1803 ui.write(("match: %s\n") % m(d[0]))
1797
1804
1798 @command('debugdiscovery',
1805 @command('debugdiscovery',
1799 [('', 'old', None, _('use old-style discovery')),
1806 [('', 'old', None, _('use old-style discovery')),
1800 ('', 'nonheads', None,
1807 ('', 'nonheads', None,
1801 _('use old-style discovery with non-heads included')),
1808 _('use old-style discovery with non-heads included')),
1802 ] + remoteopts,
1809 ] + remoteopts,
1803 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1810 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1804 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1811 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1805 """runs the changeset discovery protocol in isolation"""
1812 """runs the changeset discovery protocol in isolation"""
1806 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1813 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1807 opts.get('branch'))
1814 opts.get('branch'))
1808 remote = hg.peer(repo, opts, remoteurl)
1815 remote = hg.peer(repo, opts, remoteurl)
1809 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1816 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1810
1817
1811 # make sure tests are repeatable
1818 # make sure tests are repeatable
1812 random.seed(12323)
1819 random.seed(12323)
1813
1820
1814 def doit(localheads, remoteheads, remote=remote):
1821 def doit(localheads, remoteheads, remote=remote):
1815 if opts.get('old'):
1822 if opts.get('old'):
1816 if localheads:
1823 if localheads:
1817 raise util.Abort('cannot use localheads with old style '
1824 raise util.Abort('cannot use localheads with old style '
1818 'discovery')
1825 'discovery')
1819 if not util.safehasattr(remote, 'branches'):
1826 if not util.safehasattr(remote, 'branches'):
1820 # enable in-client legacy support
1827 # enable in-client legacy support
1821 remote = localrepo.locallegacypeer(remote.local())
1828 remote = localrepo.locallegacypeer(remote.local())
1822 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1829 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1823 force=True)
1830 force=True)
1824 common = set(common)
1831 common = set(common)
1825 if not opts.get('nonheads'):
1832 if not opts.get('nonheads'):
1826 ui.write(("unpruned common: %s\n") %
1833 ui.write(("unpruned common: %s\n") %
1827 " ".join(sorted(short(n) for n in common)))
1834 " ".join(sorted(short(n) for n in common)))
1828 dag = dagutil.revlogdag(repo.changelog)
1835 dag = dagutil.revlogdag(repo.changelog)
1829 all = dag.ancestorset(dag.internalizeall(common))
1836 all = dag.ancestorset(dag.internalizeall(common))
1830 common = dag.externalizeall(dag.headsetofconnecteds(all))
1837 common = dag.externalizeall(dag.headsetofconnecteds(all))
1831 else:
1838 else:
1832 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1839 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1833 common = set(common)
1840 common = set(common)
1834 rheads = set(hds)
1841 rheads = set(hds)
1835 lheads = set(repo.heads())
1842 lheads = set(repo.heads())
1836 ui.write(("common heads: %s\n") %
1843 ui.write(("common heads: %s\n") %
1837 " ".join(sorted(short(n) for n in common)))
1844 " ".join(sorted(short(n) for n in common)))
1838 if lheads <= common:
1845 if lheads <= common:
1839 ui.write(("local is subset\n"))
1846 ui.write(("local is subset\n"))
1840 elif rheads <= common:
1847 elif rheads <= common:
1841 ui.write(("remote is subset\n"))
1848 ui.write(("remote is subset\n"))
1842
1849
1843 serverlogs = opts.get('serverlog')
1850 serverlogs = opts.get('serverlog')
1844 if serverlogs:
1851 if serverlogs:
1845 for filename in serverlogs:
1852 for filename in serverlogs:
1846 logfile = open(filename, 'r')
1853 logfile = open(filename, 'r')
1847 try:
1854 try:
1848 line = logfile.readline()
1855 line = logfile.readline()
1849 while line:
1856 while line:
1850 parts = line.strip().split(';')
1857 parts = line.strip().split(';')
1851 op = parts[1]
1858 op = parts[1]
1852 if op == 'cg':
1859 if op == 'cg':
1853 pass
1860 pass
1854 elif op == 'cgss':
1861 elif op == 'cgss':
1855 doit(parts[2].split(' '), parts[3].split(' '))
1862 doit(parts[2].split(' '), parts[3].split(' '))
1856 elif op == 'unb':
1863 elif op == 'unb':
1857 doit(parts[3].split(' '), parts[2].split(' '))
1864 doit(parts[3].split(' '), parts[2].split(' '))
1858 line = logfile.readline()
1865 line = logfile.readline()
1859 finally:
1866 finally:
1860 logfile.close()
1867 logfile.close()
1861
1868
1862 else:
1869 else:
1863 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1870 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1864 opts.get('remote_head'))
1871 opts.get('remote_head'))
1865 localrevs = opts.get('local_head')
1872 localrevs = opts.get('local_head')
1866 doit(localrevs, remoterevs)
1873 doit(localrevs, remoterevs)
1867
1874
1868 @command('debugfileset',
1875 @command('debugfileset',
1869 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1876 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1870 _('[-r REV] FILESPEC'))
1877 _('[-r REV] FILESPEC'))
1871 def debugfileset(ui, repo, expr, **opts):
1878 def debugfileset(ui, repo, expr, **opts):
1872 '''parse and apply a fileset specification'''
1879 '''parse and apply a fileset specification'''
1873 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1880 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1874 if ui.verbose:
1881 if ui.verbose:
1875 tree = fileset.parse(expr)[0]
1882 tree = fileset.parse(expr)[0]
1876 ui.note(tree, "\n")
1883 ui.note(tree, "\n")
1877
1884
1878 for f in fileset.getfileset(ctx, expr):
1885 for f in fileset.getfileset(ctx, expr):
1879 ui.write("%s\n" % f)
1886 ui.write("%s\n" % f)
1880
1887
1881 @command('debugfsinfo', [], _('[PATH]'))
1888 @command('debugfsinfo', [], _('[PATH]'))
1882 def debugfsinfo(ui, path = "."):
1889 def debugfsinfo(ui, path = "."):
1883 """show information detected about current filesystem"""
1890 """show information detected about current filesystem"""
1884 util.writefile('.debugfsinfo', '')
1891 util.writefile('.debugfsinfo', '')
1885 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1892 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1886 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1893 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1887 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1894 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1888 and 'yes' or 'no'))
1895 and 'yes' or 'no'))
1889 os.unlink('.debugfsinfo')
1896 os.unlink('.debugfsinfo')
1890
1897
1891 @command('debuggetbundle',
1898 @command('debuggetbundle',
1892 [('H', 'head', [], _('id of head node'), _('ID')),
1899 [('H', 'head', [], _('id of head node'), _('ID')),
1893 ('C', 'common', [], _('id of common node'), _('ID')),
1900 ('C', 'common', [], _('id of common node'), _('ID')),
1894 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1901 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1895 _('REPO FILE [-H|-C ID]...'))
1902 _('REPO FILE [-H|-C ID]...'))
1896 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1903 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1897 """retrieves a bundle from a repo
1904 """retrieves a bundle from a repo
1898
1905
1899 Every ID must be a full-length hex node id string. Saves the bundle to the
1906 Every ID must be a full-length hex node id string. Saves the bundle to the
1900 given file.
1907 given file.
1901 """
1908 """
1902 repo = hg.peer(ui, opts, repopath)
1909 repo = hg.peer(ui, opts, repopath)
1903 if not repo.capable('getbundle'):
1910 if not repo.capable('getbundle'):
1904 raise util.Abort("getbundle() not supported by target repository")
1911 raise util.Abort("getbundle() not supported by target repository")
1905 args = {}
1912 args = {}
1906 if common:
1913 if common:
1907 args['common'] = [bin(s) for s in common]
1914 args['common'] = [bin(s) for s in common]
1908 if head:
1915 if head:
1909 args['heads'] = [bin(s) for s in head]
1916 args['heads'] = [bin(s) for s in head]
1910 bundle = repo.getbundle('debug', **args)
1917 bundle = repo.getbundle('debug', **args)
1911
1918
1912 bundletype = opts.get('type', 'bzip2').lower()
1919 bundletype = opts.get('type', 'bzip2').lower()
1913 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1920 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1914 bundletype = btypes.get(bundletype)
1921 bundletype = btypes.get(bundletype)
1915 if bundletype not in changegroup.bundletypes:
1922 if bundletype not in changegroup.bundletypes:
1916 raise util.Abort(_('unknown bundle type specified with --type'))
1923 raise util.Abort(_('unknown bundle type specified with --type'))
1917 changegroup.writebundle(bundle, bundlepath, bundletype)
1924 changegroup.writebundle(bundle, bundlepath, bundletype)
1918
1925
1919 @command('debugignore', [], '')
1926 @command('debugignore', [], '')
1920 def debugignore(ui, repo, *values, **opts):
1927 def debugignore(ui, repo, *values, **opts):
1921 """display the combined ignore pattern"""
1928 """display the combined ignore pattern"""
1922 ignore = repo.dirstate._ignore
1929 ignore = repo.dirstate._ignore
1923 includepat = getattr(ignore, 'includepat', None)
1930 includepat = getattr(ignore, 'includepat', None)
1924 if includepat is not None:
1931 if includepat is not None:
1925 ui.write("%s\n" % includepat)
1932 ui.write("%s\n" % includepat)
1926 else:
1933 else:
1927 raise util.Abort(_("no ignore patterns found"))
1934 raise util.Abort(_("no ignore patterns found"))
1928
1935
1929 @command('debugindex',
1936 @command('debugindex',
1930 [('c', 'changelog', False, _('open changelog')),
1937 [('c', 'changelog', False, _('open changelog')),
1931 ('m', 'manifest', False, _('open manifest')),
1938 ('m', 'manifest', False, _('open manifest')),
1932 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1939 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1933 _('[-f FORMAT] -c|-m|FILE'))
1940 _('[-f FORMAT] -c|-m|FILE'))
1934 def debugindex(ui, repo, file_ = None, **opts):
1941 def debugindex(ui, repo, file_ = None, **opts):
1935 """dump the contents of an index file"""
1942 """dump the contents of an index file"""
1936 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1943 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1937 format = opts.get('format', 0)
1944 format = opts.get('format', 0)
1938 if format not in (0, 1):
1945 if format not in (0, 1):
1939 raise util.Abort(_("unknown format %d") % format)
1946 raise util.Abort(_("unknown format %d") % format)
1940
1947
1941 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1948 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1942 if generaldelta:
1949 if generaldelta:
1943 basehdr = ' delta'
1950 basehdr = ' delta'
1944 else:
1951 else:
1945 basehdr = ' base'
1952 basehdr = ' base'
1946
1953
1947 if format == 0:
1954 if format == 0:
1948 ui.write(" rev offset length " + basehdr + " linkrev"
1955 ui.write(" rev offset length " + basehdr + " linkrev"
1949 " nodeid p1 p2\n")
1956 " nodeid p1 p2\n")
1950 elif format == 1:
1957 elif format == 1:
1951 ui.write(" rev flag offset length"
1958 ui.write(" rev flag offset length"
1952 " size " + basehdr + " link p1 p2"
1959 " size " + basehdr + " link p1 p2"
1953 " nodeid\n")
1960 " nodeid\n")
1954
1961
1955 for i in r:
1962 for i in r:
1956 node = r.node(i)
1963 node = r.node(i)
1957 if generaldelta:
1964 if generaldelta:
1958 base = r.deltaparent(i)
1965 base = r.deltaparent(i)
1959 else:
1966 else:
1960 base = r.chainbase(i)
1967 base = r.chainbase(i)
1961 if format == 0:
1968 if format == 0:
1962 try:
1969 try:
1963 pp = r.parents(node)
1970 pp = r.parents(node)
1964 except Exception:
1971 except Exception:
1965 pp = [nullid, nullid]
1972 pp = [nullid, nullid]
1966 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1973 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1967 i, r.start(i), r.length(i), base, r.linkrev(i),
1974 i, r.start(i), r.length(i), base, r.linkrev(i),
1968 short(node), short(pp[0]), short(pp[1])))
1975 short(node), short(pp[0]), short(pp[1])))
1969 elif format == 1:
1976 elif format == 1:
1970 pr = r.parentrevs(i)
1977 pr = r.parentrevs(i)
1971 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1978 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1972 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1979 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1973 base, r.linkrev(i), pr[0], pr[1], short(node)))
1980 base, r.linkrev(i), pr[0], pr[1], short(node)))
1974
1981
1975 @command('debugindexdot', [], _('FILE'))
1982 @command('debugindexdot', [], _('FILE'))
1976 def debugindexdot(ui, repo, file_):
1983 def debugindexdot(ui, repo, file_):
1977 """dump an index DAG as a graphviz dot file"""
1984 """dump an index DAG as a graphviz dot file"""
1978 r = None
1985 r = None
1979 if repo:
1986 if repo:
1980 filelog = repo.file(file_)
1987 filelog = repo.file(file_)
1981 if len(filelog):
1988 if len(filelog):
1982 r = filelog
1989 r = filelog
1983 if not r:
1990 if not r:
1984 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1991 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1985 ui.write(("digraph G {\n"))
1992 ui.write(("digraph G {\n"))
1986 for i in r:
1993 for i in r:
1987 node = r.node(i)
1994 node = r.node(i)
1988 pp = r.parents(node)
1995 pp = r.parents(node)
1989 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1996 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1990 if pp[1] != nullid:
1997 if pp[1] != nullid:
1991 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1998 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1992 ui.write("}\n")
1999 ui.write("}\n")
1993
2000
1994 @command('debuginstall', [], '')
2001 @command('debuginstall', [], '')
1995 def debuginstall(ui):
2002 def debuginstall(ui):
1996 '''test Mercurial installation
2003 '''test Mercurial installation
1997
2004
1998 Returns 0 on success.
2005 Returns 0 on success.
1999 '''
2006 '''
2000
2007
2001 def writetemp(contents):
2008 def writetemp(contents):
2002 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2009 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2003 f = os.fdopen(fd, "wb")
2010 f = os.fdopen(fd, "wb")
2004 f.write(contents)
2011 f.write(contents)
2005 f.close()
2012 f.close()
2006 return name
2013 return name
2007
2014
2008 problems = 0
2015 problems = 0
2009
2016
2010 # encoding
2017 # encoding
2011 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2018 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2012 try:
2019 try:
2013 encoding.fromlocal("test")
2020 encoding.fromlocal("test")
2014 except util.Abort, inst:
2021 except util.Abort, inst:
2015 ui.write(" %s\n" % inst)
2022 ui.write(" %s\n" % inst)
2016 ui.write(_(" (check that your locale is properly set)\n"))
2023 ui.write(_(" (check that your locale is properly set)\n"))
2017 problems += 1
2024 problems += 1
2018
2025
2019 # Python lib
2026 # Python lib
2020 ui.status(_("checking Python lib (%s)...\n")
2027 ui.status(_("checking Python lib (%s)...\n")
2021 % os.path.dirname(os.__file__))
2028 % os.path.dirname(os.__file__))
2022
2029
2023 # compiled modules
2030 # compiled modules
2024 ui.status(_("checking installed modules (%s)...\n")
2031 ui.status(_("checking installed modules (%s)...\n")
2025 % os.path.dirname(__file__))
2032 % os.path.dirname(__file__))
2026 try:
2033 try:
2027 import bdiff, mpatch, base85, osutil
2034 import bdiff, mpatch, base85, osutil
2028 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2035 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2029 except Exception, inst:
2036 except Exception, inst:
2030 ui.write(" %s\n" % inst)
2037 ui.write(" %s\n" % inst)
2031 ui.write(_(" One or more extensions could not be found"))
2038 ui.write(_(" One or more extensions could not be found"))
2032 ui.write(_(" (check that you compiled the extensions)\n"))
2039 ui.write(_(" (check that you compiled the extensions)\n"))
2033 problems += 1
2040 problems += 1
2034
2041
2035 # templates
2042 # templates
2036 import templater
2043 import templater
2037 p = templater.templatepath()
2044 p = templater.templatepath()
2038 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2045 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2039 try:
2046 try:
2040 templater.templater(templater.templatepath("map-cmdline.default"))
2047 templater.templater(templater.templatepath("map-cmdline.default"))
2041 except Exception, inst:
2048 except Exception, inst:
2042 ui.write(" %s\n" % inst)
2049 ui.write(" %s\n" % inst)
2043 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2050 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2044 problems += 1
2051 problems += 1
2045
2052
2046 # editor
2053 # editor
2047 ui.status(_("checking commit editor...\n"))
2054 ui.status(_("checking commit editor...\n"))
2048 editor = ui.geteditor()
2055 editor = ui.geteditor()
2049 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2056 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2050 if not cmdpath:
2057 if not cmdpath:
2051 if editor == 'vi':
2058 if editor == 'vi':
2052 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2059 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2053 ui.write(_(" (specify a commit editor in your configuration"
2060 ui.write(_(" (specify a commit editor in your configuration"
2054 " file)\n"))
2061 " file)\n"))
2055 else:
2062 else:
2056 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2063 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2057 ui.write(_(" (specify a commit editor in your configuration"
2064 ui.write(_(" (specify a commit editor in your configuration"
2058 " file)\n"))
2065 " file)\n"))
2059 problems += 1
2066 problems += 1
2060
2067
2061 # check username
2068 # check username
2062 ui.status(_("checking username...\n"))
2069 ui.status(_("checking username...\n"))
2063 try:
2070 try:
2064 ui.username()
2071 ui.username()
2065 except util.Abort, e:
2072 except util.Abort, e:
2066 ui.write(" %s\n" % e)
2073 ui.write(" %s\n" % e)
2067 ui.write(_(" (specify a username in your configuration file)\n"))
2074 ui.write(_(" (specify a username in your configuration file)\n"))
2068 problems += 1
2075 problems += 1
2069
2076
2070 if not problems:
2077 if not problems:
2071 ui.status(_("no problems detected\n"))
2078 ui.status(_("no problems detected\n"))
2072 else:
2079 else:
2073 ui.write(_("%s problems detected,"
2080 ui.write(_("%s problems detected,"
2074 " please check your install!\n") % problems)
2081 " please check your install!\n") % problems)
2075
2082
2076 return problems
2083 return problems
2077
2084
2078 @command('debugknown', [], _('REPO ID...'))
2085 @command('debugknown', [], _('REPO ID...'))
2079 def debugknown(ui, repopath, *ids, **opts):
2086 def debugknown(ui, repopath, *ids, **opts):
2080 """test whether node ids are known to a repo
2087 """test whether node ids are known to a repo
2081
2088
2082 Every ID must be a full-length hex node id string. Returns a list of 0s
2089 Every ID must be a full-length hex node id string. Returns a list of 0s
2083 and 1s indicating unknown/known.
2090 and 1s indicating unknown/known.
2084 """
2091 """
2085 repo = hg.peer(ui, opts, repopath)
2092 repo = hg.peer(ui, opts, repopath)
2086 if not repo.capable('known'):
2093 if not repo.capable('known'):
2087 raise util.Abort("known() not supported by target repository")
2094 raise util.Abort("known() not supported by target repository")
2088 flags = repo.known([bin(s) for s in ids])
2095 flags = repo.known([bin(s) for s in ids])
2089 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2096 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2090
2097
2091 @command('debuglabelcomplete', [], _('LABEL...'))
2098 @command('debuglabelcomplete', [], _('LABEL...'))
2092 def debuglabelcomplete(ui, repo, *args):
2099 def debuglabelcomplete(ui, repo, *args):
2093 '''complete "labels" - tags, open branch names, bookmark names'''
2100 '''complete "labels" - tags, open branch names, bookmark names'''
2094
2101
2095 labels = set()
2102 labels = set()
2096 labels.update(t[0] for t in repo.tagslist())
2103 labels.update(t[0] for t in repo.tagslist())
2097 labels.update(repo._bookmarks.keys())
2104 labels.update(repo._bookmarks.keys())
2098 for heads in repo.branchmap().itervalues():
2105 for heads in repo.branchmap().itervalues():
2099 for h in heads:
2106 for h in heads:
2100 ctx = repo[h]
2107 ctx = repo[h]
2101 if not ctx.closesbranch():
2108 if not ctx.closesbranch():
2102 labels.add(ctx.branch())
2109 labels.add(ctx.branch())
2103 completions = set()
2110 completions = set()
2104 if not args:
2111 if not args:
2105 args = ['']
2112 args = ['']
2106 for a in args:
2113 for a in args:
2107 completions.update(l for l in labels if l.startswith(a))
2114 completions.update(l for l in labels if l.startswith(a))
2108 ui.write('\n'.join(sorted(completions)))
2115 ui.write('\n'.join(sorted(completions)))
2109 ui.write('\n')
2116 ui.write('\n')
2110
2117
2111 @command('debugobsolete',
2118 @command('debugobsolete',
2112 [('', 'flags', 0, _('markers flag')),
2119 [('', 'flags', 0, _('markers flag')),
2113 ] + commitopts2,
2120 ] + commitopts2,
2114 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2121 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2115 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2122 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2116 """create arbitrary obsolete marker
2123 """create arbitrary obsolete marker
2117
2124
2118 With no arguments, displays the list of obsolescence markers."""
2125 With no arguments, displays the list of obsolescence markers."""
2119 def parsenodeid(s):
2126 def parsenodeid(s):
2120 try:
2127 try:
2121 # We do not use revsingle/revrange functions here to accept
2128 # We do not use revsingle/revrange functions here to accept
2122 # arbitrary node identifiers, possibly not present in the
2129 # arbitrary node identifiers, possibly not present in the
2123 # local repository.
2130 # local repository.
2124 n = bin(s)
2131 n = bin(s)
2125 if len(n) != len(nullid):
2132 if len(n) != len(nullid):
2126 raise TypeError()
2133 raise TypeError()
2127 return n
2134 return n
2128 except TypeError:
2135 except TypeError:
2129 raise util.Abort('changeset references must be full hexadecimal '
2136 raise util.Abort('changeset references must be full hexadecimal '
2130 'node identifiers')
2137 'node identifiers')
2131
2138
2132 if precursor is not None:
2139 if precursor is not None:
2133 metadata = {}
2140 metadata = {}
2134 if 'date' in opts:
2141 if 'date' in opts:
2135 metadata['date'] = opts['date']
2142 metadata['date'] = opts['date']
2136 metadata['user'] = opts['user'] or ui.username()
2143 metadata['user'] = opts['user'] or ui.username()
2137 succs = tuple(parsenodeid(succ) for succ in successors)
2144 succs = tuple(parsenodeid(succ) for succ in successors)
2138 l = repo.lock()
2145 l = repo.lock()
2139 try:
2146 try:
2140 tr = repo.transaction('debugobsolete')
2147 tr = repo.transaction('debugobsolete')
2141 try:
2148 try:
2142 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2149 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2143 opts['flags'], metadata)
2150 opts['flags'], metadata)
2144 tr.close()
2151 tr.close()
2145 finally:
2152 finally:
2146 tr.release()
2153 tr.release()
2147 finally:
2154 finally:
2148 l.release()
2155 l.release()
2149 else:
2156 else:
2150 for m in obsolete.allmarkers(repo):
2157 for m in obsolete.allmarkers(repo):
2151 ui.write(hex(m.precnode()))
2158 ui.write(hex(m.precnode()))
2152 for repl in m.succnodes():
2159 for repl in m.succnodes():
2153 ui.write(' ')
2160 ui.write(' ')
2154 ui.write(hex(repl))
2161 ui.write(hex(repl))
2155 ui.write(' %X ' % m._data[2])
2162 ui.write(' %X ' % m._data[2])
2156 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2163 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2157 sorted(m.metadata().items()))))
2164 sorted(m.metadata().items()))))
2158 ui.write('\n')
2165 ui.write('\n')
2159
2166
2160 @command('debugpathcomplete',
2167 @command('debugpathcomplete',
2161 [('f', 'full', None, _('complete an entire path')),
2168 [('f', 'full', None, _('complete an entire path')),
2162 ('n', 'normal', None, _('show only normal files')),
2169 ('n', 'normal', None, _('show only normal files')),
2163 ('a', 'added', None, _('show only added files')),
2170 ('a', 'added', None, _('show only added files')),
2164 ('r', 'removed', None, _('show only removed files'))],
2171 ('r', 'removed', None, _('show only removed files'))],
2165 _('FILESPEC...'))
2172 _('FILESPEC...'))
2166 def debugpathcomplete(ui, repo, *specs, **opts):
2173 def debugpathcomplete(ui, repo, *specs, **opts):
2167 '''complete part or all of a tracked path
2174 '''complete part or all of a tracked path
2168
2175
2169 This command supports shells that offer path name completion. It
2176 This command supports shells that offer path name completion. It
2170 currently completes only files already known to the dirstate.
2177 currently completes only files already known to the dirstate.
2171
2178
2172 Completion extends only to the next path segment unless
2179 Completion extends only to the next path segment unless
2173 --full is specified, in which case entire paths are used.'''
2180 --full is specified, in which case entire paths are used.'''
2174
2181
2175 def complete(path, acceptable):
2182 def complete(path, acceptable):
2176 dirstate = repo.dirstate
2183 dirstate = repo.dirstate
2177 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2184 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2178 rootdir = repo.root + os.sep
2185 rootdir = repo.root + os.sep
2179 if spec != repo.root and not spec.startswith(rootdir):
2186 if spec != repo.root and not spec.startswith(rootdir):
2180 return [], []
2187 return [], []
2181 if os.path.isdir(spec):
2188 if os.path.isdir(spec):
2182 spec += '/'
2189 spec += '/'
2183 spec = spec[len(rootdir):]
2190 spec = spec[len(rootdir):]
2184 fixpaths = os.sep != '/'
2191 fixpaths = os.sep != '/'
2185 if fixpaths:
2192 if fixpaths:
2186 spec = spec.replace(os.sep, '/')
2193 spec = spec.replace(os.sep, '/')
2187 speclen = len(spec)
2194 speclen = len(spec)
2188 fullpaths = opts['full']
2195 fullpaths = opts['full']
2189 files, dirs = set(), set()
2196 files, dirs = set(), set()
2190 adddir, addfile = dirs.add, files.add
2197 adddir, addfile = dirs.add, files.add
2191 for f, st in dirstate.iteritems():
2198 for f, st in dirstate.iteritems():
2192 if f.startswith(spec) and st[0] in acceptable:
2199 if f.startswith(spec) and st[0] in acceptable:
2193 if fixpaths:
2200 if fixpaths:
2194 f = f.replace('/', os.sep)
2201 f = f.replace('/', os.sep)
2195 if fullpaths:
2202 if fullpaths:
2196 addfile(f)
2203 addfile(f)
2197 continue
2204 continue
2198 s = f.find(os.sep, speclen)
2205 s = f.find(os.sep, speclen)
2199 if s >= 0:
2206 if s >= 0:
2200 adddir(f[:s + 1])
2207 adddir(f[:s + 1])
2201 else:
2208 else:
2202 addfile(f)
2209 addfile(f)
2203 return files, dirs
2210 return files, dirs
2204
2211
2205 acceptable = ''
2212 acceptable = ''
2206 if opts['normal']:
2213 if opts['normal']:
2207 acceptable += 'nm'
2214 acceptable += 'nm'
2208 if opts['added']:
2215 if opts['added']:
2209 acceptable += 'a'
2216 acceptable += 'a'
2210 if opts['removed']:
2217 if opts['removed']:
2211 acceptable += 'r'
2218 acceptable += 'r'
2212 cwd = repo.getcwd()
2219 cwd = repo.getcwd()
2213 if not specs:
2220 if not specs:
2214 specs = ['.']
2221 specs = ['.']
2215
2222
2216 files, dirs = set(), set()
2223 files, dirs = set(), set()
2217 for spec in specs:
2224 for spec in specs:
2218 f, d = complete(spec, acceptable or 'nmar')
2225 f, d = complete(spec, acceptable or 'nmar')
2219 files.update(f)
2226 files.update(f)
2220 dirs.update(d)
2227 dirs.update(d)
2221 if not files and len(dirs) == 1:
2228 if not files and len(dirs) == 1:
2222 # force the shell to consider a completion that matches one
2229 # force the shell to consider a completion that matches one
2223 # directory and zero files to be ambiguous
2230 # directory and zero files to be ambiguous
2224 dirs.add(iter(dirs).next() + '.')
2231 dirs.add(iter(dirs).next() + '.')
2225 files.update(dirs)
2232 files.update(dirs)
2226 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2233 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2227 ui.write('\n')
2234 ui.write('\n')
2228
2235
2229 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2236 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2230 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2237 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2231 '''access the pushkey key/value protocol
2238 '''access the pushkey key/value protocol
2232
2239
2233 With two args, list the keys in the given namespace.
2240 With two args, list the keys in the given namespace.
2234
2241
2235 With five args, set a key to new if it currently is set to old.
2242 With five args, set a key to new if it currently is set to old.
2236 Reports success or failure.
2243 Reports success or failure.
2237 '''
2244 '''
2238
2245
2239 target = hg.peer(ui, {}, repopath)
2246 target = hg.peer(ui, {}, repopath)
2240 if keyinfo:
2247 if keyinfo:
2241 key, old, new = keyinfo
2248 key, old, new = keyinfo
2242 r = target.pushkey(namespace, key, old, new)
2249 r = target.pushkey(namespace, key, old, new)
2243 ui.status(str(r) + '\n')
2250 ui.status(str(r) + '\n')
2244 return not r
2251 return not r
2245 else:
2252 else:
2246 for k, v in sorted(target.listkeys(namespace).iteritems()):
2253 for k, v in sorted(target.listkeys(namespace).iteritems()):
2247 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2254 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2248 v.encode('string-escape')))
2255 v.encode('string-escape')))
2249
2256
2250 @command('debugpvec', [], _('A B'))
2257 @command('debugpvec', [], _('A B'))
2251 def debugpvec(ui, repo, a, b=None):
2258 def debugpvec(ui, repo, a, b=None):
2252 ca = scmutil.revsingle(repo, a)
2259 ca = scmutil.revsingle(repo, a)
2253 cb = scmutil.revsingle(repo, b)
2260 cb = scmutil.revsingle(repo, b)
2254 pa = pvec.ctxpvec(ca)
2261 pa = pvec.ctxpvec(ca)
2255 pb = pvec.ctxpvec(cb)
2262 pb = pvec.ctxpvec(cb)
2256 if pa == pb:
2263 if pa == pb:
2257 rel = "="
2264 rel = "="
2258 elif pa > pb:
2265 elif pa > pb:
2259 rel = ">"
2266 rel = ">"
2260 elif pa < pb:
2267 elif pa < pb:
2261 rel = "<"
2268 rel = "<"
2262 elif pa | pb:
2269 elif pa | pb:
2263 rel = "|"
2270 rel = "|"
2264 ui.write(_("a: %s\n") % pa)
2271 ui.write(_("a: %s\n") % pa)
2265 ui.write(_("b: %s\n") % pb)
2272 ui.write(_("b: %s\n") % pb)
2266 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2273 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2267 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2274 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2268 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2275 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2269 pa.distance(pb), rel))
2276 pa.distance(pb), rel))
2270
2277
2271 @command('debugrebuilddirstate|debugrebuildstate',
2278 @command('debugrebuilddirstate|debugrebuildstate',
2272 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2279 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2273 _('[-r REV]'))
2280 _('[-r REV]'))
2274 def debugrebuilddirstate(ui, repo, rev):
2281 def debugrebuilddirstate(ui, repo, rev):
2275 """rebuild the dirstate as it would look like for the given revision
2282 """rebuild the dirstate as it would look like for the given revision
2276
2283
2277 If no revision is specified the first current parent will be used.
2284 If no revision is specified the first current parent will be used.
2278
2285
2279 The dirstate will be set to the files of the given revision.
2286 The dirstate will be set to the files of the given revision.
2280 The actual working directory content or existing dirstate
2287 The actual working directory content or existing dirstate
2281 information such as adds or removes is not considered.
2288 information such as adds or removes is not considered.
2282
2289
2283 One use of this command is to make the next :hg:`status` invocation
2290 One use of this command is to make the next :hg:`status` invocation
2284 check the actual file content.
2291 check the actual file content.
2285 """
2292 """
2286 ctx = scmutil.revsingle(repo, rev)
2293 ctx = scmutil.revsingle(repo, rev)
2287 wlock = repo.wlock()
2294 wlock = repo.wlock()
2288 try:
2295 try:
2289 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2296 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2290 finally:
2297 finally:
2291 wlock.release()
2298 wlock.release()
2292
2299
2293 @command('debugrename',
2300 @command('debugrename',
2294 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2301 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2295 _('[-r REV] FILE'))
2302 _('[-r REV] FILE'))
2296 def debugrename(ui, repo, file1, *pats, **opts):
2303 def debugrename(ui, repo, file1, *pats, **opts):
2297 """dump rename information"""
2304 """dump rename information"""
2298
2305
2299 ctx = scmutil.revsingle(repo, opts.get('rev'))
2306 ctx = scmutil.revsingle(repo, opts.get('rev'))
2300 m = scmutil.match(ctx, (file1,) + pats, opts)
2307 m = scmutil.match(ctx, (file1,) + pats, opts)
2301 for abs in ctx.walk(m):
2308 for abs in ctx.walk(m):
2302 fctx = ctx[abs]
2309 fctx = ctx[abs]
2303 o = fctx.filelog().renamed(fctx.filenode())
2310 o = fctx.filelog().renamed(fctx.filenode())
2304 rel = m.rel(abs)
2311 rel = m.rel(abs)
2305 if o:
2312 if o:
2306 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2313 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2307 else:
2314 else:
2308 ui.write(_("%s not renamed\n") % rel)
2315 ui.write(_("%s not renamed\n") % rel)
2309
2316
2310 @command('debugrevlog',
2317 @command('debugrevlog',
2311 [('c', 'changelog', False, _('open changelog')),
2318 [('c', 'changelog', False, _('open changelog')),
2312 ('m', 'manifest', False, _('open manifest')),
2319 ('m', 'manifest', False, _('open manifest')),
2313 ('d', 'dump', False, _('dump index data'))],
2320 ('d', 'dump', False, _('dump index data'))],
2314 _('-c|-m|FILE'))
2321 _('-c|-m|FILE'))
2315 def debugrevlog(ui, repo, file_ = None, **opts):
2322 def debugrevlog(ui, repo, file_ = None, **opts):
2316 """show data and statistics about a revlog"""
2323 """show data and statistics about a revlog"""
2317 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2324 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2318
2325
2319 if opts.get("dump"):
2326 if opts.get("dump"):
2320 numrevs = len(r)
2327 numrevs = len(r)
2321 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2328 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2322 " rawsize totalsize compression heads\n")
2329 " rawsize totalsize compression heads\n")
2323 ts = 0
2330 ts = 0
2324 heads = set()
2331 heads = set()
2325 for rev in xrange(numrevs):
2332 for rev in xrange(numrevs):
2326 dbase = r.deltaparent(rev)
2333 dbase = r.deltaparent(rev)
2327 if dbase == -1:
2334 if dbase == -1:
2328 dbase = rev
2335 dbase = rev
2329 cbase = r.chainbase(rev)
2336 cbase = r.chainbase(rev)
2330 p1, p2 = r.parentrevs(rev)
2337 p1, p2 = r.parentrevs(rev)
2331 rs = r.rawsize(rev)
2338 rs = r.rawsize(rev)
2332 ts = ts + rs
2339 ts = ts + rs
2333 heads -= set(r.parentrevs(rev))
2340 heads -= set(r.parentrevs(rev))
2334 heads.add(rev)
2341 heads.add(rev)
2335 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2342 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2336 (rev, p1, p2, r.start(rev), r.end(rev),
2343 (rev, p1, p2, r.start(rev), r.end(rev),
2337 r.start(dbase), r.start(cbase),
2344 r.start(dbase), r.start(cbase),
2338 r.start(p1), r.start(p2),
2345 r.start(p1), r.start(p2),
2339 rs, ts, ts / r.end(rev), len(heads)))
2346 rs, ts, ts / r.end(rev), len(heads)))
2340 return 0
2347 return 0
2341
2348
2342 v = r.version
2349 v = r.version
2343 format = v & 0xFFFF
2350 format = v & 0xFFFF
2344 flags = []
2351 flags = []
2345 gdelta = False
2352 gdelta = False
2346 if v & revlog.REVLOGNGINLINEDATA:
2353 if v & revlog.REVLOGNGINLINEDATA:
2347 flags.append('inline')
2354 flags.append('inline')
2348 if v & revlog.REVLOGGENERALDELTA:
2355 if v & revlog.REVLOGGENERALDELTA:
2349 gdelta = True
2356 gdelta = True
2350 flags.append('generaldelta')
2357 flags.append('generaldelta')
2351 if not flags:
2358 if not flags:
2352 flags = ['(none)']
2359 flags = ['(none)']
2353
2360
2354 nummerges = 0
2361 nummerges = 0
2355 numfull = 0
2362 numfull = 0
2356 numprev = 0
2363 numprev = 0
2357 nump1 = 0
2364 nump1 = 0
2358 nump2 = 0
2365 nump2 = 0
2359 numother = 0
2366 numother = 0
2360 nump1prev = 0
2367 nump1prev = 0
2361 nump2prev = 0
2368 nump2prev = 0
2362 chainlengths = []
2369 chainlengths = []
2363
2370
2364 datasize = [None, 0, 0L]
2371 datasize = [None, 0, 0L]
2365 fullsize = [None, 0, 0L]
2372 fullsize = [None, 0, 0L]
2366 deltasize = [None, 0, 0L]
2373 deltasize = [None, 0, 0L]
2367
2374
2368 def addsize(size, l):
2375 def addsize(size, l):
2369 if l[0] is None or size < l[0]:
2376 if l[0] is None or size < l[0]:
2370 l[0] = size
2377 l[0] = size
2371 if size > l[1]:
2378 if size > l[1]:
2372 l[1] = size
2379 l[1] = size
2373 l[2] += size
2380 l[2] += size
2374
2381
2375 numrevs = len(r)
2382 numrevs = len(r)
2376 for rev in xrange(numrevs):
2383 for rev in xrange(numrevs):
2377 p1, p2 = r.parentrevs(rev)
2384 p1, p2 = r.parentrevs(rev)
2378 delta = r.deltaparent(rev)
2385 delta = r.deltaparent(rev)
2379 if format > 0:
2386 if format > 0:
2380 addsize(r.rawsize(rev), datasize)
2387 addsize(r.rawsize(rev), datasize)
2381 if p2 != nullrev:
2388 if p2 != nullrev:
2382 nummerges += 1
2389 nummerges += 1
2383 size = r.length(rev)
2390 size = r.length(rev)
2384 if delta == nullrev:
2391 if delta == nullrev:
2385 chainlengths.append(0)
2392 chainlengths.append(0)
2386 numfull += 1
2393 numfull += 1
2387 addsize(size, fullsize)
2394 addsize(size, fullsize)
2388 else:
2395 else:
2389 chainlengths.append(chainlengths[delta] + 1)
2396 chainlengths.append(chainlengths[delta] + 1)
2390 addsize(size, deltasize)
2397 addsize(size, deltasize)
2391 if delta == rev - 1:
2398 if delta == rev - 1:
2392 numprev += 1
2399 numprev += 1
2393 if delta == p1:
2400 if delta == p1:
2394 nump1prev += 1
2401 nump1prev += 1
2395 elif delta == p2:
2402 elif delta == p2:
2396 nump2prev += 1
2403 nump2prev += 1
2397 elif delta == p1:
2404 elif delta == p1:
2398 nump1 += 1
2405 nump1 += 1
2399 elif delta == p2:
2406 elif delta == p2:
2400 nump2 += 1
2407 nump2 += 1
2401 elif delta != nullrev:
2408 elif delta != nullrev:
2402 numother += 1
2409 numother += 1
2403
2410
2404 # Adjust size min value for empty cases
2411 # Adjust size min value for empty cases
2405 for size in (datasize, fullsize, deltasize):
2412 for size in (datasize, fullsize, deltasize):
2406 if size[0] is None:
2413 if size[0] is None:
2407 size[0] = 0
2414 size[0] = 0
2408
2415
2409 numdeltas = numrevs - numfull
2416 numdeltas = numrevs - numfull
2410 numoprev = numprev - nump1prev - nump2prev
2417 numoprev = numprev - nump1prev - nump2prev
2411 totalrawsize = datasize[2]
2418 totalrawsize = datasize[2]
2412 datasize[2] /= numrevs
2419 datasize[2] /= numrevs
2413 fulltotal = fullsize[2]
2420 fulltotal = fullsize[2]
2414 fullsize[2] /= numfull
2421 fullsize[2] /= numfull
2415 deltatotal = deltasize[2]
2422 deltatotal = deltasize[2]
2416 if numrevs - numfull > 0:
2423 if numrevs - numfull > 0:
2417 deltasize[2] /= numrevs - numfull
2424 deltasize[2] /= numrevs - numfull
2418 totalsize = fulltotal + deltatotal
2425 totalsize = fulltotal + deltatotal
2419 avgchainlen = sum(chainlengths) / numrevs
2426 avgchainlen = sum(chainlengths) / numrevs
2420 compratio = totalrawsize / totalsize
2427 compratio = totalrawsize / totalsize
2421
2428
2422 basedfmtstr = '%%%dd\n'
2429 basedfmtstr = '%%%dd\n'
2423 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2430 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2424
2431
2425 def dfmtstr(max):
2432 def dfmtstr(max):
2426 return basedfmtstr % len(str(max))
2433 return basedfmtstr % len(str(max))
2427 def pcfmtstr(max, padding=0):
2434 def pcfmtstr(max, padding=0):
2428 return basepcfmtstr % (len(str(max)), ' ' * padding)
2435 return basepcfmtstr % (len(str(max)), ' ' * padding)
2429
2436
2430 def pcfmt(value, total):
2437 def pcfmt(value, total):
2431 return (value, 100 * float(value) / total)
2438 return (value, 100 * float(value) / total)
2432
2439
2433 ui.write(('format : %d\n') % format)
2440 ui.write(('format : %d\n') % format)
2434 ui.write(('flags : %s\n') % ', '.join(flags))
2441 ui.write(('flags : %s\n') % ', '.join(flags))
2435
2442
2436 ui.write('\n')
2443 ui.write('\n')
2437 fmt = pcfmtstr(totalsize)
2444 fmt = pcfmtstr(totalsize)
2438 fmt2 = dfmtstr(totalsize)
2445 fmt2 = dfmtstr(totalsize)
2439 ui.write(('revisions : ') + fmt2 % numrevs)
2446 ui.write(('revisions : ') + fmt2 % numrevs)
2440 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2447 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2441 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2448 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2442 ui.write(('revisions : ') + fmt2 % numrevs)
2449 ui.write(('revisions : ') + fmt2 % numrevs)
2443 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2450 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2444 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2451 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2445 ui.write(('revision size : ') + fmt2 % totalsize)
2452 ui.write(('revision size : ') + fmt2 % totalsize)
2446 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2453 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2447 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2454 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2448
2455
2449 ui.write('\n')
2456 ui.write('\n')
2450 fmt = dfmtstr(max(avgchainlen, compratio))
2457 fmt = dfmtstr(max(avgchainlen, compratio))
2451 ui.write(('avg chain length : ') + fmt % avgchainlen)
2458 ui.write(('avg chain length : ') + fmt % avgchainlen)
2452 ui.write(('compression ratio : ') + fmt % compratio)
2459 ui.write(('compression ratio : ') + fmt % compratio)
2453
2460
2454 if format > 0:
2461 if format > 0:
2455 ui.write('\n')
2462 ui.write('\n')
2456 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2463 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2457 % tuple(datasize))
2464 % tuple(datasize))
2458 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2465 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2459 % tuple(fullsize))
2466 % tuple(fullsize))
2460 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2467 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2461 % tuple(deltasize))
2468 % tuple(deltasize))
2462
2469
2463 if numdeltas > 0:
2470 if numdeltas > 0:
2464 ui.write('\n')
2471 ui.write('\n')
2465 fmt = pcfmtstr(numdeltas)
2472 fmt = pcfmtstr(numdeltas)
2466 fmt2 = pcfmtstr(numdeltas, 4)
2473 fmt2 = pcfmtstr(numdeltas, 4)
2467 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2474 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2468 if numprev > 0:
2475 if numprev > 0:
2469 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2476 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2470 numprev))
2477 numprev))
2471 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2478 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2472 numprev))
2479 numprev))
2473 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2480 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2474 numprev))
2481 numprev))
2475 if gdelta:
2482 if gdelta:
2476 ui.write(('deltas against p1 : ')
2483 ui.write(('deltas against p1 : ')
2477 + fmt % pcfmt(nump1, numdeltas))
2484 + fmt % pcfmt(nump1, numdeltas))
2478 ui.write(('deltas against p2 : ')
2485 ui.write(('deltas against p2 : ')
2479 + fmt % pcfmt(nump2, numdeltas))
2486 + fmt % pcfmt(nump2, numdeltas))
2480 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2487 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2481 numdeltas))
2488 numdeltas))
2482
2489
2483 @command('debugrevspec', [], ('REVSPEC'))
2490 @command('debugrevspec', [], ('REVSPEC'))
2484 def debugrevspec(ui, repo, expr):
2491 def debugrevspec(ui, repo, expr):
2485 """parse and apply a revision specification
2492 """parse and apply a revision specification
2486
2493
2487 Use --verbose to print the parsed tree before and after aliases
2494 Use --verbose to print the parsed tree before and after aliases
2488 expansion.
2495 expansion.
2489 """
2496 """
2490 if ui.verbose:
2497 if ui.verbose:
2491 tree = revset.parse(expr)[0]
2498 tree = revset.parse(expr)[0]
2492 ui.note(revset.prettyformat(tree), "\n")
2499 ui.note(revset.prettyformat(tree), "\n")
2493 newtree = revset.findaliases(ui, tree)
2500 newtree = revset.findaliases(ui, tree)
2494 if newtree != tree:
2501 if newtree != tree:
2495 ui.note(revset.prettyformat(newtree), "\n")
2502 ui.note(revset.prettyformat(newtree), "\n")
2496 func = revset.match(ui, expr)
2503 func = revset.match(ui, expr)
2497 for c in func(repo, range(len(repo))):
2504 for c in func(repo, range(len(repo))):
2498 ui.write("%s\n" % c)
2505 ui.write("%s\n" % c)
2499
2506
2500 @command('debugsetparents', [], _('REV1 [REV2]'))
2507 @command('debugsetparents', [], _('REV1 [REV2]'))
2501 def debugsetparents(ui, repo, rev1, rev2=None):
2508 def debugsetparents(ui, repo, rev1, rev2=None):
2502 """manually set the parents of the current working directory
2509 """manually set the parents of the current working directory
2503
2510
2504 This is useful for writing repository conversion tools, but should
2511 This is useful for writing repository conversion tools, but should
2505 be used with care.
2512 be used with care.
2506
2513
2507 Returns 0 on success.
2514 Returns 0 on success.
2508 """
2515 """
2509
2516
2510 r1 = scmutil.revsingle(repo, rev1).node()
2517 r1 = scmutil.revsingle(repo, rev1).node()
2511 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2518 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2512
2519
2513 wlock = repo.wlock()
2520 wlock = repo.wlock()
2514 try:
2521 try:
2515 repo.setparents(r1, r2)
2522 repo.setparents(r1, r2)
2516 finally:
2523 finally:
2517 wlock.release()
2524 wlock.release()
2518
2525
2519 @command('debugdirstate|debugstate',
2526 @command('debugdirstate|debugstate',
2520 [('', 'nodates', None, _('do not display the saved mtime')),
2527 [('', 'nodates', None, _('do not display the saved mtime')),
2521 ('', 'datesort', None, _('sort by saved mtime'))],
2528 ('', 'datesort', None, _('sort by saved mtime'))],
2522 _('[OPTION]...'))
2529 _('[OPTION]...'))
2523 def debugstate(ui, repo, nodates=None, datesort=None):
2530 def debugstate(ui, repo, nodates=None, datesort=None):
2524 """show the contents of the current dirstate"""
2531 """show the contents of the current dirstate"""
2525 timestr = ""
2532 timestr = ""
2526 showdate = not nodates
2533 showdate = not nodates
2527 if datesort:
2534 if datesort:
2528 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2535 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2529 else:
2536 else:
2530 keyfunc = None # sort by filename
2537 keyfunc = None # sort by filename
2531 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2538 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2532 if showdate:
2539 if showdate:
2533 if ent[3] == -1:
2540 if ent[3] == -1:
2534 # Pad or slice to locale representation
2541 # Pad or slice to locale representation
2535 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2542 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2536 time.localtime(0)))
2543 time.localtime(0)))
2537 timestr = 'unset'
2544 timestr = 'unset'
2538 timestr = (timestr[:locale_len] +
2545 timestr = (timestr[:locale_len] +
2539 ' ' * (locale_len - len(timestr)))
2546 ' ' * (locale_len - len(timestr)))
2540 else:
2547 else:
2541 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2548 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2542 time.localtime(ent[3]))
2549 time.localtime(ent[3]))
2543 if ent[1] & 020000:
2550 if ent[1] & 020000:
2544 mode = 'lnk'
2551 mode = 'lnk'
2545 else:
2552 else:
2546 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2553 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2547 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2554 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2548 for f in repo.dirstate.copies():
2555 for f in repo.dirstate.copies():
2549 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2556 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2550
2557
2551 @command('debugsub',
2558 @command('debugsub',
2552 [('r', 'rev', '',
2559 [('r', 'rev', '',
2553 _('revision to check'), _('REV'))],
2560 _('revision to check'), _('REV'))],
2554 _('[-r REV] [REV]'))
2561 _('[-r REV] [REV]'))
2555 def debugsub(ui, repo, rev=None):
2562 def debugsub(ui, repo, rev=None):
2556 ctx = scmutil.revsingle(repo, rev, None)
2563 ctx = scmutil.revsingle(repo, rev, None)
2557 for k, v in sorted(ctx.substate.items()):
2564 for k, v in sorted(ctx.substate.items()):
2558 ui.write(('path %s\n') % k)
2565 ui.write(('path %s\n') % k)
2559 ui.write((' source %s\n') % v[0])
2566 ui.write((' source %s\n') % v[0])
2560 ui.write((' revision %s\n') % v[1])
2567 ui.write((' revision %s\n') % v[1])
2561
2568
2562 @command('debugsuccessorssets',
2569 @command('debugsuccessorssets',
2563 [],
2570 [],
2564 _('[REV]'))
2571 _('[REV]'))
2565 def debugsuccessorssets(ui, repo, *revs):
2572 def debugsuccessorssets(ui, repo, *revs):
2566 """show set of successors for revision
2573 """show set of successors for revision
2567
2574
2568 A successors set of changeset A is a consistent group of revisions that
2575 A successors set of changeset A is a consistent group of revisions that
2569 succeed A. It contains non-obsolete changesets only.
2576 succeed A. It contains non-obsolete changesets only.
2570
2577
2571 In most cases a changeset A has a single successors set containing a single
2578 In most cases a changeset A has a single successors set containing a single
2572 successor (changeset A replaced by A').
2579 successor (changeset A replaced by A').
2573
2580
2574 A changeset that is made obsolete with no successors are called "pruned".
2581 A changeset that is made obsolete with no successors are called "pruned".
2575 Such changesets have no successors sets at all.
2582 Such changesets have no successors sets at all.
2576
2583
2577 A changeset that has been "split" will have a successors set containing
2584 A changeset that has been "split" will have a successors set containing
2578 more than one successor.
2585 more than one successor.
2579
2586
2580 A changeset that has been rewritten in multiple different ways is called
2587 A changeset that has been rewritten in multiple different ways is called
2581 "divergent". Such changesets have multiple successor sets (each of which
2588 "divergent". Such changesets have multiple successor sets (each of which
2582 may also be split, i.e. have multiple successors).
2589 may also be split, i.e. have multiple successors).
2583
2590
2584 Results are displayed as follows::
2591 Results are displayed as follows::
2585
2592
2586 <rev1>
2593 <rev1>
2587 <successors-1A>
2594 <successors-1A>
2588 <rev2>
2595 <rev2>
2589 <successors-2A>
2596 <successors-2A>
2590 <successors-2B1> <successors-2B2> <successors-2B3>
2597 <successors-2B1> <successors-2B2> <successors-2B3>
2591
2598
2592 Here rev2 has two possible (i.e. divergent) successors sets. The first
2599 Here rev2 has two possible (i.e. divergent) successors sets. The first
2593 holds one element, whereas the second holds three (i.e. the changeset has
2600 holds one element, whereas the second holds three (i.e. the changeset has
2594 been split).
2601 been split).
2595 """
2602 """
2596 # passed to successorssets caching computation from one call to another
2603 # passed to successorssets caching computation from one call to another
2597 cache = {}
2604 cache = {}
2598 ctx2str = str
2605 ctx2str = str
2599 node2str = short
2606 node2str = short
2600 if ui.debug():
2607 if ui.debug():
2601 def ctx2str(ctx):
2608 def ctx2str(ctx):
2602 return ctx.hex()
2609 return ctx.hex()
2603 node2str = hex
2610 node2str = hex
2604 for rev in scmutil.revrange(repo, revs):
2611 for rev in scmutil.revrange(repo, revs):
2605 ctx = repo[rev]
2612 ctx = repo[rev]
2606 ui.write('%s\n'% ctx2str(ctx))
2613 ui.write('%s\n'% ctx2str(ctx))
2607 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2614 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2608 if succsset:
2615 if succsset:
2609 ui.write(' ')
2616 ui.write(' ')
2610 ui.write(node2str(succsset[0]))
2617 ui.write(node2str(succsset[0]))
2611 for node in succsset[1:]:
2618 for node in succsset[1:]:
2612 ui.write(' ')
2619 ui.write(' ')
2613 ui.write(node2str(node))
2620 ui.write(node2str(node))
2614 ui.write('\n')
2621 ui.write('\n')
2615
2622
2616 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2623 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2617 def debugwalk(ui, repo, *pats, **opts):
2624 def debugwalk(ui, repo, *pats, **opts):
2618 """show how files match on given patterns"""
2625 """show how files match on given patterns"""
2619 m = scmutil.match(repo[None], pats, opts)
2626 m = scmutil.match(repo[None], pats, opts)
2620 items = list(repo.walk(m))
2627 items = list(repo.walk(m))
2621 if not items:
2628 if not items:
2622 return
2629 return
2623 f = lambda fn: fn
2630 f = lambda fn: fn
2624 if ui.configbool('ui', 'slash') and os.sep != '/':
2631 if ui.configbool('ui', 'slash') and os.sep != '/':
2625 f = lambda fn: util.normpath(fn)
2632 f = lambda fn: util.normpath(fn)
2626 fmt = 'f %%-%ds %%-%ds %%s' % (
2633 fmt = 'f %%-%ds %%-%ds %%s' % (
2627 max([len(abs) for abs in items]),
2634 max([len(abs) for abs in items]),
2628 max([len(m.rel(abs)) for abs in items]))
2635 max([len(m.rel(abs)) for abs in items]))
2629 for abs in items:
2636 for abs in items:
2630 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2637 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2631 ui.write("%s\n" % line.rstrip())
2638 ui.write("%s\n" % line.rstrip())
2632
2639
2633 @command('debugwireargs',
2640 @command('debugwireargs',
2634 [('', 'three', '', 'three'),
2641 [('', 'three', '', 'three'),
2635 ('', 'four', '', 'four'),
2642 ('', 'four', '', 'four'),
2636 ('', 'five', '', 'five'),
2643 ('', 'five', '', 'five'),
2637 ] + remoteopts,
2644 ] + remoteopts,
2638 _('REPO [OPTIONS]... [ONE [TWO]]'))
2645 _('REPO [OPTIONS]... [ONE [TWO]]'))
2639 def debugwireargs(ui, repopath, *vals, **opts):
2646 def debugwireargs(ui, repopath, *vals, **opts):
2640 repo = hg.peer(ui, opts, repopath)
2647 repo = hg.peer(ui, opts, repopath)
2641 for opt in remoteopts:
2648 for opt in remoteopts:
2642 del opts[opt[1]]
2649 del opts[opt[1]]
2643 args = {}
2650 args = {}
2644 for k, v in opts.iteritems():
2651 for k, v in opts.iteritems():
2645 if v:
2652 if v:
2646 args[k] = v
2653 args[k] = v
2647 # run twice to check that we don't mess up the stream for the next command
2654 # run twice to check that we don't mess up the stream for the next command
2648 res1 = repo.debugwireargs(*vals, **args)
2655 res1 = repo.debugwireargs(*vals, **args)
2649 res2 = repo.debugwireargs(*vals, **args)
2656 res2 = repo.debugwireargs(*vals, **args)
2650 ui.write("%s\n" % res1)
2657 ui.write("%s\n" % res1)
2651 if res1 != res2:
2658 if res1 != res2:
2652 ui.warn("%s\n" % res2)
2659 ui.warn("%s\n" % res2)
2653
2660
2654 @command('^diff',
2661 @command('^diff',
2655 [('r', 'rev', [], _('revision'), _('REV')),
2662 [('r', 'rev', [], _('revision'), _('REV')),
2656 ('c', 'change', '', _('change made by revision'), _('REV'))
2663 ('c', 'change', '', _('change made by revision'), _('REV'))
2657 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2664 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2658 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2665 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2659 def diff(ui, repo, *pats, **opts):
2666 def diff(ui, repo, *pats, **opts):
2660 """diff repository (or selected files)
2667 """diff repository (or selected files)
2661
2668
2662 Show differences between revisions for the specified files.
2669 Show differences between revisions for the specified files.
2663
2670
2664 Differences between files are shown using the unified diff format.
2671 Differences between files are shown using the unified diff format.
2665
2672
2666 .. note::
2673 .. note::
2667 diff may generate unexpected results for merges, as it will
2674 diff may generate unexpected results for merges, as it will
2668 default to comparing against the working directory's first
2675 default to comparing against the working directory's first
2669 parent changeset if no revisions are specified.
2676 parent changeset if no revisions are specified.
2670
2677
2671 When two revision arguments are given, then changes are shown
2678 When two revision arguments are given, then changes are shown
2672 between those revisions. If only one revision is specified then
2679 between those revisions. If only one revision is specified then
2673 that revision is compared to the working directory, and, when no
2680 that revision is compared to the working directory, and, when no
2674 revisions are specified, the working directory files are compared
2681 revisions are specified, the working directory files are compared
2675 to its parent.
2682 to its parent.
2676
2683
2677 Alternatively you can specify -c/--change with a revision to see
2684 Alternatively you can specify -c/--change with a revision to see
2678 the changes in that changeset relative to its first parent.
2685 the changes in that changeset relative to its first parent.
2679
2686
2680 Without the -a/--text option, diff will avoid generating diffs of
2687 Without the -a/--text option, diff will avoid generating diffs of
2681 files it detects as binary. With -a, diff will generate a diff
2688 files it detects as binary. With -a, diff will generate a diff
2682 anyway, probably with undesirable results.
2689 anyway, probably with undesirable results.
2683
2690
2684 Use the -g/--git option to generate diffs in the git extended diff
2691 Use the -g/--git option to generate diffs in the git extended diff
2685 format. For more information, read :hg:`help diffs`.
2692 format. For more information, read :hg:`help diffs`.
2686
2693
2687 .. container:: verbose
2694 .. container:: verbose
2688
2695
2689 Examples:
2696 Examples:
2690
2697
2691 - compare a file in the current working directory to its parent::
2698 - compare a file in the current working directory to its parent::
2692
2699
2693 hg diff foo.c
2700 hg diff foo.c
2694
2701
2695 - compare two historical versions of a directory, with rename info::
2702 - compare two historical versions of a directory, with rename info::
2696
2703
2697 hg diff --git -r 1.0:1.2 lib/
2704 hg diff --git -r 1.0:1.2 lib/
2698
2705
2699 - get change stats relative to the last change on some date::
2706 - get change stats relative to the last change on some date::
2700
2707
2701 hg diff --stat -r "date('may 2')"
2708 hg diff --stat -r "date('may 2')"
2702
2709
2703 - diff all newly-added files that contain a keyword::
2710 - diff all newly-added files that contain a keyword::
2704
2711
2705 hg diff "set:added() and grep(GNU)"
2712 hg diff "set:added() and grep(GNU)"
2706
2713
2707 - compare a revision and its parents::
2714 - compare a revision and its parents::
2708
2715
2709 hg diff -c 9353 # compare against first parent
2716 hg diff -c 9353 # compare against first parent
2710 hg diff -r 9353^:9353 # same using revset syntax
2717 hg diff -r 9353^:9353 # same using revset syntax
2711 hg diff -r 9353^2:9353 # compare against the second parent
2718 hg diff -r 9353^2:9353 # compare against the second parent
2712
2719
2713 Returns 0 on success.
2720 Returns 0 on success.
2714 """
2721 """
2715
2722
2716 revs = opts.get('rev')
2723 revs = opts.get('rev')
2717 change = opts.get('change')
2724 change = opts.get('change')
2718 stat = opts.get('stat')
2725 stat = opts.get('stat')
2719 reverse = opts.get('reverse')
2726 reverse = opts.get('reverse')
2720
2727
2721 if revs and change:
2728 if revs and change:
2722 msg = _('cannot specify --rev and --change at the same time')
2729 msg = _('cannot specify --rev and --change at the same time')
2723 raise util.Abort(msg)
2730 raise util.Abort(msg)
2724 elif change:
2731 elif change:
2725 node2 = scmutil.revsingle(repo, change, None).node()
2732 node2 = scmutil.revsingle(repo, change, None).node()
2726 node1 = repo[node2].p1().node()
2733 node1 = repo[node2].p1().node()
2727 else:
2734 else:
2728 node1, node2 = scmutil.revpair(repo, revs)
2735 node1, node2 = scmutil.revpair(repo, revs)
2729
2736
2730 if reverse:
2737 if reverse:
2731 node1, node2 = node2, node1
2738 node1, node2 = node2, node1
2732
2739
2733 diffopts = patch.diffopts(ui, opts)
2740 diffopts = patch.diffopts(ui, opts)
2734 m = scmutil.match(repo[node2], pats, opts)
2741 m = scmutil.match(repo[node2], pats, opts)
2735 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2742 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2736 listsubrepos=opts.get('subrepos'))
2743 listsubrepos=opts.get('subrepos'))
2737
2744
2738 @command('^export',
2745 @command('^export',
2739 [('o', 'output', '',
2746 [('o', 'output', '',
2740 _('print output to file with formatted name'), _('FORMAT')),
2747 _('print output to file with formatted name'), _('FORMAT')),
2741 ('', 'switch-parent', None, _('diff against the second parent')),
2748 ('', 'switch-parent', None, _('diff against the second parent')),
2742 ('r', 'rev', [], _('revisions to export'), _('REV')),
2749 ('r', 'rev', [], _('revisions to export'), _('REV')),
2743 ] + diffopts,
2750 ] + diffopts,
2744 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2751 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2745 def export(ui, repo, *changesets, **opts):
2752 def export(ui, repo, *changesets, **opts):
2746 """dump the header and diffs for one or more changesets
2753 """dump the header and diffs for one or more changesets
2747
2754
2748 Print the changeset header and diffs for one or more revisions.
2755 Print the changeset header and diffs for one or more revisions.
2749 If no revision is given, the parent of the working directory is used.
2756 If no revision is given, the parent of the working directory is used.
2750
2757
2751 The information shown in the changeset header is: author, date,
2758 The information shown in the changeset header is: author, date,
2752 branch name (if non-default), changeset hash, parent(s) and commit
2759 branch name (if non-default), changeset hash, parent(s) and commit
2753 comment.
2760 comment.
2754
2761
2755 .. note::
2762 .. note::
2756 export may generate unexpected diff output for merge
2763 export may generate unexpected diff output for merge
2757 changesets, as it will compare the merge changeset against its
2764 changesets, as it will compare the merge changeset against its
2758 first parent only.
2765 first parent only.
2759
2766
2760 Output may be to a file, in which case the name of the file is
2767 Output may be to a file, in which case the name of the file is
2761 given using a format string. The formatting rules are as follows:
2768 given using a format string. The formatting rules are as follows:
2762
2769
2763 :``%%``: literal "%" character
2770 :``%%``: literal "%" character
2764 :``%H``: changeset hash (40 hexadecimal digits)
2771 :``%H``: changeset hash (40 hexadecimal digits)
2765 :``%N``: number of patches being generated
2772 :``%N``: number of patches being generated
2766 :``%R``: changeset revision number
2773 :``%R``: changeset revision number
2767 :``%b``: basename of the exporting repository
2774 :``%b``: basename of the exporting repository
2768 :``%h``: short-form changeset hash (12 hexadecimal digits)
2775 :``%h``: short-form changeset hash (12 hexadecimal digits)
2769 :``%m``: first line of the commit message (only alphanumeric characters)
2776 :``%m``: first line of the commit message (only alphanumeric characters)
2770 :``%n``: zero-padded sequence number, starting at 1
2777 :``%n``: zero-padded sequence number, starting at 1
2771 :``%r``: zero-padded changeset revision number
2778 :``%r``: zero-padded changeset revision number
2772
2779
2773 Without the -a/--text option, export will avoid generating diffs
2780 Without the -a/--text option, export will avoid generating diffs
2774 of files it detects as binary. With -a, export will generate a
2781 of files it detects as binary. With -a, export will generate a
2775 diff anyway, probably with undesirable results.
2782 diff anyway, probably with undesirable results.
2776
2783
2777 Use the -g/--git option to generate diffs in the git extended diff
2784 Use the -g/--git option to generate diffs in the git extended diff
2778 format. See :hg:`help diffs` for more information.
2785 format. See :hg:`help diffs` for more information.
2779
2786
2780 With the --switch-parent option, the diff will be against the
2787 With the --switch-parent option, the diff will be against the
2781 second parent. It can be useful to review a merge.
2788 second parent. It can be useful to review a merge.
2782
2789
2783 .. container:: verbose
2790 .. container:: verbose
2784
2791
2785 Examples:
2792 Examples:
2786
2793
2787 - use export and import to transplant a bugfix to the current
2794 - use export and import to transplant a bugfix to the current
2788 branch::
2795 branch::
2789
2796
2790 hg export -r 9353 | hg import -
2797 hg export -r 9353 | hg import -
2791
2798
2792 - export all the changesets between two revisions to a file with
2799 - export all the changesets between two revisions to a file with
2793 rename information::
2800 rename information::
2794
2801
2795 hg export --git -r 123:150 > changes.txt
2802 hg export --git -r 123:150 > changes.txt
2796
2803
2797 - split outgoing changes into a series of patches with
2804 - split outgoing changes into a series of patches with
2798 descriptive names::
2805 descriptive names::
2799
2806
2800 hg export -r "outgoing()" -o "%n-%m.patch"
2807 hg export -r "outgoing()" -o "%n-%m.patch"
2801
2808
2802 Returns 0 on success.
2809 Returns 0 on success.
2803 """
2810 """
2804 changesets += tuple(opts.get('rev', []))
2811 changesets += tuple(opts.get('rev', []))
2805 if not changesets:
2812 if not changesets:
2806 changesets = ['.']
2813 changesets = ['.']
2807 revs = scmutil.revrange(repo, changesets)
2814 revs = scmutil.revrange(repo, changesets)
2808 if not revs:
2815 if not revs:
2809 raise util.Abort(_("export requires at least one changeset"))
2816 raise util.Abort(_("export requires at least one changeset"))
2810 if len(revs) > 1:
2817 if len(revs) > 1:
2811 ui.note(_('exporting patches:\n'))
2818 ui.note(_('exporting patches:\n'))
2812 else:
2819 else:
2813 ui.note(_('exporting patch:\n'))
2820 ui.note(_('exporting patch:\n'))
2814 cmdutil.export(repo, revs, template=opts.get('output'),
2821 cmdutil.export(repo, revs, template=opts.get('output'),
2815 switch_parent=opts.get('switch_parent'),
2822 switch_parent=opts.get('switch_parent'),
2816 opts=patch.diffopts(ui, opts))
2823 opts=patch.diffopts(ui, opts))
2817
2824
2818 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2825 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2819 def forget(ui, repo, *pats, **opts):
2826 def forget(ui, repo, *pats, **opts):
2820 """forget the specified files on the next commit
2827 """forget the specified files on the next commit
2821
2828
2822 Mark the specified files so they will no longer be tracked
2829 Mark the specified files so they will no longer be tracked
2823 after the next commit.
2830 after the next commit.
2824
2831
2825 This only removes files from the current branch, not from the
2832 This only removes files from the current branch, not from the
2826 entire project history, and it does not delete them from the
2833 entire project history, and it does not delete them from the
2827 working directory.
2834 working directory.
2828
2835
2829 To undo a forget before the next commit, see :hg:`add`.
2836 To undo a forget before the next commit, see :hg:`add`.
2830
2837
2831 .. container:: verbose
2838 .. container:: verbose
2832
2839
2833 Examples:
2840 Examples:
2834
2841
2835 - forget newly-added binary files::
2842 - forget newly-added binary files::
2836
2843
2837 hg forget "set:added() and binary()"
2844 hg forget "set:added() and binary()"
2838
2845
2839 - forget files that would be excluded by .hgignore::
2846 - forget files that would be excluded by .hgignore::
2840
2847
2841 hg forget "set:hgignore()"
2848 hg forget "set:hgignore()"
2842
2849
2843 Returns 0 on success.
2850 Returns 0 on success.
2844 """
2851 """
2845
2852
2846 if not pats:
2853 if not pats:
2847 raise util.Abort(_('no files specified'))
2854 raise util.Abort(_('no files specified'))
2848
2855
2849 m = scmutil.match(repo[None], pats, opts)
2856 m = scmutil.match(repo[None], pats, opts)
2850 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2857 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2851 return rejected and 1 or 0
2858 return rejected and 1 or 0
2852
2859
2853 @command(
2860 @command(
2854 'graft',
2861 'graft',
2855 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2862 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2856 ('c', 'continue', False, _('resume interrupted graft')),
2863 ('c', 'continue', False, _('resume interrupted graft')),
2857 ('e', 'edit', False, _('invoke editor on commit messages')),
2864 ('e', 'edit', False, _('invoke editor on commit messages')),
2858 ('', 'log', None, _('append graft info to log message')),
2865 ('', 'log', None, _('append graft info to log message')),
2859 ('D', 'currentdate', False,
2866 ('D', 'currentdate', False,
2860 _('record the current date as commit date')),
2867 _('record the current date as commit date')),
2861 ('U', 'currentuser', False,
2868 ('U', 'currentuser', False,
2862 _('record the current user as committer'), _('DATE'))]
2869 _('record the current user as committer'), _('DATE'))]
2863 + commitopts2 + mergetoolopts + dryrunopts,
2870 + commitopts2 + mergetoolopts + dryrunopts,
2864 _('[OPTION]... [-r] REV...'))
2871 _('[OPTION]... [-r] REV...'))
2865 def graft(ui, repo, *revs, **opts):
2872 def graft(ui, repo, *revs, **opts):
2866 '''copy changes from other branches onto the current branch
2873 '''copy changes from other branches onto the current branch
2867
2874
2868 This command uses Mercurial's merge logic to copy individual
2875 This command uses Mercurial's merge logic to copy individual
2869 changes from other branches without merging branches in the
2876 changes from other branches without merging branches in the
2870 history graph. This is sometimes known as 'backporting' or
2877 history graph. This is sometimes known as 'backporting' or
2871 'cherry-picking'. By default, graft will copy user, date, and
2878 'cherry-picking'. By default, graft will copy user, date, and
2872 description from the source changesets.
2879 description from the source changesets.
2873
2880
2874 Changesets that are ancestors of the current revision, that have
2881 Changesets that are ancestors of the current revision, that have
2875 already been grafted, or that are merges will be skipped.
2882 already been grafted, or that are merges will be skipped.
2876
2883
2877 If --log is specified, log messages will have a comment appended
2884 If --log is specified, log messages will have a comment appended
2878 of the form::
2885 of the form::
2879
2886
2880 (grafted from CHANGESETHASH)
2887 (grafted from CHANGESETHASH)
2881
2888
2882 If a graft merge results in conflicts, the graft process is
2889 If a graft merge results in conflicts, the graft process is
2883 interrupted so that the current merge can be manually resolved.
2890 interrupted so that the current merge can be manually resolved.
2884 Once all conflicts are addressed, the graft process can be
2891 Once all conflicts are addressed, the graft process can be
2885 continued with the -c/--continue option.
2892 continued with the -c/--continue option.
2886
2893
2887 .. note::
2894 .. note::
2888 The -c/--continue option does not reapply earlier options.
2895 The -c/--continue option does not reapply earlier options.
2889
2896
2890 .. container:: verbose
2897 .. container:: verbose
2891
2898
2892 Examples:
2899 Examples:
2893
2900
2894 - copy a single change to the stable branch and edit its description::
2901 - copy a single change to the stable branch and edit its description::
2895
2902
2896 hg update stable
2903 hg update stable
2897 hg graft --edit 9393
2904 hg graft --edit 9393
2898
2905
2899 - graft a range of changesets with one exception, updating dates::
2906 - graft a range of changesets with one exception, updating dates::
2900
2907
2901 hg graft -D "2085::2093 and not 2091"
2908 hg graft -D "2085::2093 and not 2091"
2902
2909
2903 - continue a graft after resolving conflicts::
2910 - continue a graft after resolving conflicts::
2904
2911
2905 hg graft -c
2912 hg graft -c
2906
2913
2907 - show the source of a grafted changeset::
2914 - show the source of a grafted changeset::
2908
2915
2909 hg log --debug -r tip
2916 hg log --debug -r tip
2910
2917
2911 Returns 0 on successful completion.
2918 Returns 0 on successful completion.
2912 '''
2919 '''
2913
2920
2914 revs = list(revs)
2921 revs = list(revs)
2915 revs.extend(opts['rev'])
2922 revs.extend(opts['rev'])
2916
2923
2917 if not opts.get('user') and opts.get('currentuser'):
2924 if not opts.get('user') and opts.get('currentuser'):
2918 opts['user'] = ui.username()
2925 opts['user'] = ui.username()
2919 if not opts.get('date') and opts.get('currentdate'):
2926 if not opts.get('date') and opts.get('currentdate'):
2920 opts['date'] = "%d %d" % util.makedate()
2927 opts['date'] = "%d %d" % util.makedate()
2921
2928
2922 editor = None
2929 editor = None
2923 if opts.get('edit'):
2930 if opts.get('edit'):
2924 editor = cmdutil.commitforceeditor
2931 editor = cmdutil.commitforceeditor
2925
2932
2926 cont = False
2933 cont = False
2927 if opts['continue']:
2934 if opts['continue']:
2928 cont = True
2935 cont = True
2929 if revs:
2936 if revs:
2930 raise util.Abort(_("can't specify --continue and revisions"))
2937 raise util.Abort(_("can't specify --continue and revisions"))
2931 # read in unfinished revisions
2938 # read in unfinished revisions
2932 try:
2939 try:
2933 nodes = repo.opener.read('graftstate').splitlines()
2940 nodes = repo.opener.read('graftstate').splitlines()
2934 revs = [repo[node].rev() for node in nodes]
2941 revs = [repo[node].rev() for node in nodes]
2935 except IOError, inst:
2942 except IOError, inst:
2936 if inst.errno != errno.ENOENT:
2943 if inst.errno != errno.ENOENT:
2937 raise
2944 raise
2938 raise util.Abort(_("no graft state found, can't continue"))
2945 raise util.Abort(_("no graft state found, can't continue"))
2939 else:
2946 else:
2940 cmdutil.bailifchanged(repo)
2947 cmdutil.bailifchanged(repo)
2941 if not revs:
2948 if not revs:
2942 raise util.Abort(_('no revisions specified'))
2949 raise util.Abort(_('no revisions specified'))
2943 revs = scmutil.revrange(repo, revs)
2950 revs = scmutil.revrange(repo, revs)
2944
2951
2945 # check for merges
2952 # check for merges
2946 for rev in repo.revs('%ld and merge()', revs):
2953 for rev in repo.revs('%ld and merge()', revs):
2947 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2954 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2948 revs.remove(rev)
2955 revs.remove(rev)
2949 if not revs:
2956 if not revs:
2950 return -1
2957 return -1
2951
2958
2952 # check for ancestors of dest branch
2959 # check for ancestors of dest branch
2953 crev = repo['.'].rev()
2960 crev = repo['.'].rev()
2954 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2961 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2955 # don't mutate while iterating, create a copy
2962 # don't mutate while iterating, create a copy
2956 for rev in list(revs):
2963 for rev in list(revs):
2957 if rev in ancestors:
2964 if rev in ancestors:
2958 ui.warn(_('skipping ancestor revision %s\n') % rev)
2965 ui.warn(_('skipping ancestor revision %s\n') % rev)
2959 revs.remove(rev)
2966 revs.remove(rev)
2960 if not revs:
2967 if not revs:
2961 return -1
2968 return -1
2962
2969
2963 # analyze revs for earlier grafts
2970 # analyze revs for earlier grafts
2964 ids = {}
2971 ids = {}
2965 for ctx in repo.set("%ld", revs):
2972 for ctx in repo.set("%ld", revs):
2966 ids[ctx.hex()] = ctx.rev()
2973 ids[ctx.hex()] = ctx.rev()
2967 n = ctx.extra().get('source')
2974 n = ctx.extra().get('source')
2968 if n:
2975 if n:
2969 ids[n] = ctx.rev()
2976 ids[n] = ctx.rev()
2970
2977
2971 # check ancestors for earlier grafts
2978 # check ancestors for earlier grafts
2972 ui.debug('scanning for duplicate grafts\n')
2979 ui.debug('scanning for duplicate grafts\n')
2973
2980
2974 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2981 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2975 ctx = repo[rev]
2982 ctx = repo[rev]
2976 n = ctx.extra().get('source')
2983 n = ctx.extra().get('source')
2977 if n in ids:
2984 if n in ids:
2978 r = repo[n].rev()
2985 r = repo[n].rev()
2979 if r in revs:
2986 if r in revs:
2980 ui.warn(_('skipping already grafted revision %s\n') % r)
2987 ui.warn(_('skipping already grafted revision %s\n') % r)
2981 revs.remove(r)
2988 revs.remove(r)
2982 elif ids[n] in revs:
2989 elif ids[n] in revs:
2983 ui.warn(_('skipping already grafted revision %s '
2990 ui.warn(_('skipping already grafted revision %s '
2984 '(same origin %d)\n') % (ids[n], r))
2991 '(same origin %d)\n') % (ids[n], r))
2985 revs.remove(ids[n])
2992 revs.remove(ids[n])
2986 elif ctx.hex() in ids:
2993 elif ctx.hex() in ids:
2987 r = ids[ctx.hex()]
2994 r = ids[ctx.hex()]
2988 ui.warn(_('skipping already grafted revision %s '
2995 ui.warn(_('skipping already grafted revision %s '
2989 '(was grafted from %d)\n') % (r, rev))
2996 '(was grafted from %d)\n') % (r, rev))
2990 revs.remove(r)
2997 revs.remove(r)
2991 if not revs:
2998 if not revs:
2992 return -1
2999 return -1
2993
3000
2994 wlock = repo.wlock()
3001 wlock = repo.wlock()
2995 try:
3002 try:
2996 current = repo['.']
3003 current = repo['.']
2997 for pos, ctx in enumerate(repo.set("%ld", revs)):
3004 for pos, ctx in enumerate(repo.set("%ld", revs)):
2998
3005
2999 ui.status(_('grafting revision %s\n') % ctx.rev())
3006 ui.status(_('grafting revision %s\n') % ctx.rev())
3000 if opts.get('dry_run'):
3007 if opts.get('dry_run'):
3001 continue
3008 continue
3002
3009
3003 source = ctx.extra().get('source')
3010 source = ctx.extra().get('source')
3004 if not source:
3011 if not source:
3005 source = ctx.hex()
3012 source = ctx.hex()
3006 extra = {'source': source}
3013 extra = {'source': source}
3007 user = ctx.user()
3014 user = ctx.user()
3008 if opts.get('user'):
3015 if opts.get('user'):
3009 user = opts['user']
3016 user = opts['user']
3010 date = ctx.date()
3017 date = ctx.date()
3011 if opts.get('date'):
3018 if opts.get('date'):
3012 date = opts['date']
3019 date = opts['date']
3013 message = ctx.description()
3020 message = ctx.description()
3014 if opts.get('log'):
3021 if opts.get('log'):
3015 message += '\n(grafted from %s)' % ctx.hex()
3022 message += '\n(grafted from %s)' % ctx.hex()
3016
3023
3017 # we don't merge the first commit when continuing
3024 # we don't merge the first commit when continuing
3018 if not cont:
3025 if not cont:
3019 # perform the graft merge with p1(rev) as 'ancestor'
3026 # perform the graft merge with p1(rev) as 'ancestor'
3020 try:
3027 try:
3021 # ui.forcemerge is an internal variable, do not document
3028 # ui.forcemerge is an internal variable, do not document
3022 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3029 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3023 stats = mergemod.update(repo, ctx.node(), True, True, False,
3030 stats = mergemod.update(repo, ctx.node(), True, True, False,
3024 ctx.p1().node())
3031 ctx.p1().node())
3025 finally:
3032 finally:
3026 repo.ui.setconfig('ui', 'forcemerge', '')
3033 repo.ui.setconfig('ui', 'forcemerge', '')
3027 # report any conflicts
3034 # report any conflicts
3028 if stats and stats[3] > 0:
3035 if stats and stats[3] > 0:
3029 # write out state for --continue
3036 # write out state for --continue
3030 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3037 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3031 repo.opener.write('graftstate', ''.join(nodelines))
3038 repo.opener.write('graftstate', ''.join(nodelines))
3032 raise util.Abort(
3039 raise util.Abort(
3033 _("unresolved conflicts, can't continue"),
3040 _("unresolved conflicts, can't continue"),
3034 hint=_('use hg resolve and hg graft --continue'))
3041 hint=_('use hg resolve and hg graft --continue'))
3035 else:
3042 else:
3036 cont = False
3043 cont = False
3037
3044
3038 # drop the second merge parent
3045 # drop the second merge parent
3039 repo.setparents(current.node(), nullid)
3046 repo.setparents(current.node(), nullid)
3040 repo.dirstate.write()
3047 repo.dirstate.write()
3041 # fix up dirstate for copies and renames
3048 # fix up dirstate for copies and renames
3042 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3049 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3043
3050
3044 # commit
3051 # commit
3045 node = repo.commit(text=message, user=user,
3052 node = repo.commit(text=message, user=user,
3046 date=date, extra=extra, editor=editor)
3053 date=date, extra=extra, editor=editor)
3047 if node is None:
3054 if node is None:
3048 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3055 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3049 else:
3056 else:
3050 current = repo[node]
3057 current = repo[node]
3051 finally:
3058 finally:
3052 wlock.release()
3059 wlock.release()
3053
3060
3054 # remove state when we complete successfully
3061 # remove state when we complete successfully
3055 if not opts.get('dry_run'):
3062 if not opts.get('dry_run'):
3056 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3063 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3057
3064
3058 return 0
3065 return 0
3059
3066
3060 @command('grep',
3067 @command('grep',
3061 [('0', 'print0', None, _('end fields with NUL')),
3068 [('0', 'print0', None, _('end fields with NUL')),
3062 ('', 'all', None, _('print all revisions that match')),
3069 ('', 'all', None, _('print all revisions that match')),
3063 ('a', 'text', None, _('treat all files as text')),
3070 ('a', 'text', None, _('treat all files as text')),
3064 ('f', 'follow', None,
3071 ('f', 'follow', None,
3065 _('follow changeset history,'
3072 _('follow changeset history,'
3066 ' or file history across copies and renames')),
3073 ' or file history across copies and renames')),
3067 ('i', 'ignore-case', None, _('ignore case when matching')),
3074 ('i', 'ignore-case', None, _('ignore case when matching')),
3068 ('l', 'files-with-matches', None,
3075 ('l', 'files-with-matches', None,
3069 _('print only filenames and revisions that match')),
3076 _('print only filenames and revisions that match')),
3070 ('n', 'line-number', None, _('print matching line numbers')),
3077 ('n', 'line-number', None, _('print matching line numbers')),
3071 ('r', 'rev', [],
3078 ('r', 'rev', [],
3072 _('only search files changed within revision range'), _('REV')),
3079 _('only search files changed within revision range'), _('REV')),
3073 ('u', 'user', None, _('list the author (long with -v)')),
3080 ('u', 'user', None, _('list the author (long with -v)')),
3074 ('d', 'date', None, _('list the date (short with -q)')),
3081 ('d', 'date', None, _('list the date (short with -q)')),
3075 ] + walkopts,
3082 ] + walkopts,
3076 _('[OPTION]... PATTERN [FILE]...'))
3083 _('[OPTION]... PATTERN [FILE]...'))
3077 def grep(ui, repo, pattern, *pats, **opts):
3084 def grep(ui, repo, pattern, *pats, **opts):
3078 """search for a pattern in specified files and revisions
3085 """search for a pattern in specified files and revisions
3079
3086
3080 Search revisions of files for a regular expression.
3087 Search revisions of files for a regular expression.
3081
3088
3082 This command behaves differently than Unix grep. It only accepts
3089 This command behaves differently than Unix grep. It only accepts
3083 Python/Perl regexps. It searches repository history, not the
3090 Python/Perl regexps. It searches repository history, not the
3084 working directory. It always prints the revision number in which a
3091 working directory. It always prints the revision number in which a
3085 match appears.
3092 match appears.
3086
3093
3087 By default, grep only prints output for the first revision of a
3094 By default, grep only prints output for the first revision of a
3088 file in which it finds a match. To get it to print every revision
3095 file in which it finds a match. To get it to print every revision
3089 that contains a change in match status ("-" for a match that
3096 that contains a change in match status ("-" for a match that
3090 becomes a non-match, or "+" for a non-match that becomes a match),
3097 becomes a non-match, or "+" for a non-match that becomes a match),
3091 use the --all flag.
3098 use the --all flag.
3092
3099
3093 Returns 0 if a match is found, 1 otherwise.
3100 Returns 0 if a match is found, 1 otherwise.
3094 """
3101 """
3095 reflags = re.M
3102 reflags = re.M
3096 if opts.get('ignore_case'):
3103 if opts.get('ignore_case'):
3097 reflags |= re.I
3104 reflags |= re.I
3098 try:
3105 try:
3099 regexp = util.compilere(pattern, reflags)
3106 regexp = util.compilere(pattern, reflags)
3100 except re.error, inst:
3107 except re.error, inst:
3101 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3108 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3102 return 1
3109 return 1
3103 sep, eol = ':', '\n'
3110 sep, eol = ':', '\n'
3104 if opts.get('print0'):
3111 if opts.get('print0'):
3105 sep = eol = '\0'
3112 sep = eol = '\0'
3106
3113
3107 getfile = util.lrucachefunc(repo.file)
3114 getfile = util.lrucachefunc(repo.file)
3108
3115
3109 def matchlines(body):
3116 def matchlines(body):
3110 begin = 0
3117 begin = 0
3111 linenum = 0
3118 linenum = 0
3112 while begin < len(body):
3119 while begin < len(body):
3113 match = regexp.search(body, begin)
3120 match = regexp.search(body, begin)
3114 if not match:
3121 if not match:
3115 break
3122 break
3116 mstart, mend = match.span()
3123 mstart, mend = match.span()
3117 linenum += body.count('\n', begin, mstart) + 1
3124 linenum += body.count('\n', begin, mstart) + 1
3118 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3125 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3119 begin = body.find('\n', mend) + 1 or len(body) + 1
3126 begin = body.find('\n', mend) + 1 or len(body) + 1
3120 lend = begin - 1
3127 lend = begin - 1
3121 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3128 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3122
3129
3123 class linestate(object):
3130 class linestate(object):
3124 def __init__(self, line, linenum, colstart, colend):
3131 def __init__(self, line, linenum, colstart, colend):
3125 self.line = line
3132 self.line = line
3126 self.linenum = linenum
3133 self.linenum = linenum
3127 self.colstart = colstart
3134 self.colstart = colstart
3128 self.colend = colend
3135 self.colend = colend
3129
3136
3130 def __hash__(self):
3137 def __hash__(self):
3131 return hash((self.linenum, self.line))
3138 return hash((self.linenum, self.line))
3132
3139
3133 def __eq__(self, other):
3140 def __eq__(self, other):
3134 return self.line == other.line
3141 return self.line == other.line
3135
3142
3136 matches = {}
3143 matches = {}
3137 copies = {}
3144 copies = {}
3138 def grepbody(fn, rev, body):
3145 def grepbody(fn, rev, body):
3139 matches[rev].setdefault(fn, [])
3146 matches[rev].setdefault(fn, [])
3140 m = matches[rev][fn]
3147 m = matches[rev][fn]
3141 for lnum, cstart, cend, line in matchlines(body):
3148 for lnum, cstart, cend, line in matchlines(body):
3142 s = linestate(line, lnum, cstart, cend)
3149 s = linestate(line, lnum, cstart, cend)
3143 m.append(s)
3150 m.append(s)
3144
3151
3145 def difflinestates(a, b):
3152 def difflinestates(a, b):
3146 sm = difflib.SequenceMatcher(None, a, b)
3153 sm = difflib.SequenceMatcher(None, a, b)
3147 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3154 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3148 if tag == 'insert':
3155 if tag == 'insert':
3149 for i in xrange(blo, bhi):
3156 for i in xrange(blo, bhi):
3150 yield ('+', b[i])
3157 yield ('+', b[i])
3151 elif tag == 'delete':
3158 elif tag == 'delete':
3152 for i in xrange(alo, ahi):
3159 for i in xrange(alo, ahi):
3153 yield ('-', a[i])
3160 yield ('-', a[i])
3154 elif tag == 'replace':
3161 elif tag == 'replace':
3155 for i in xrange(alo, ahi):
3162 for i in xrange(alo, ahi):
3156 yield ('-', a[i])
3163 yield ('-', a[i])
3157 for i in xrange(blo, bhi):
3164 for i in xrange(blo, bhi):
3158 yield ('+', b[i])
3165 yield ('+', b[i])
3159
3166
3160 def display(fn, ctx, pstates, states):
3167 def display(fn, ctx, pstates, states):
3161 rev = ctx.rev()
3168 rev = ctx.rev()
3162 datefunc = ui.quiet and util.shortdate or util.datestr
3169 datefunc = ui.quiet and util.shortdate or util.datestr
3163 found = False
3170 found = False
3164 filerevmatches = {}
3171 filerevmatches = {}
3165 def binary():
3172 def binary():
3166 flog = getfile(fn)
3173 flog = getfile(fn)
3167 return util.binary(flog.read(ctx.filenode(fn)))
3174 return util.binary(flog.read(ctx.filenode(fn)))
3168
3175
3169 if opts.get('all'):
3176 if opts.get('all'):
3170 iter = difflinestates(pstates, states)
3177 iter = difflinestates(pstates, states)
3171 else:
3178 else:
3172 iter = [('', l) for l in states]
3179 iter = [('', l) for l in states]
3173 for change, l in iter:
3180 for change, l in iter:
3174 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3181 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3175 before, match, after = None, None, None
3182 before, match, after = None, None, None
3176
3183
3177 if opts.get('line_number'):
3184 if opts.get('line_number'):
3178 cols.append((str(l.linenum), 'grep.linenumber'))
3185 cols.append((str(l.linenum), 'grep.linenumber'))
3179 if opts.get('all'):
3186 if opts.get('all'):
3180 cols.append((change, 'grep.change'))
3187 cols.append((change, 'grep.change'))
3181 if opts.get('user'):
3188 if opts.get('user'):
3182 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3189 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3183 if opts.get('date'):
3190 if opts.get('date'):
3184 cols.append((datefunc(ctx.date()), 'grep.date'))
3191 cols.append((datefunc(ctx.date()), 'grep.date'))
3185 if opts.get('files_with_matches'):
3192 if opts.get('files_with_matches'):
3186 c = (fn, rev)
3193 c = (fn, rev)
3187 if c in filerevmatches:
3194 if c in filerevmatches:
3188 continue
3195 continue
3189 filerevmatches[c] = 1
3196 filerevmatches[c] = 1
3190 else:
3197 else:
3191 before = l.line[:l.colstart]
3198 before = l.line[:l.colstart]
3192 match = l.line[l.colstart:l.colend]
3199 match = l.line[l.colstart:l.colend]
3193 after = l.line[l.colend:]
3200 after = l.line[l.colend:]
3194 for col, label in cols[:-1]:
3201 for col, label in cols[:-1]:
3195 ui.write(col, label=label)
3202 ui.write(col, label=label)
3196 ui.write(sep, label='grep.sep')
3203 ui.write(sep, label='grep.sep')
3197 ui.write(cols[-1][0], label=cols[-1][1])
3204 ui.write(cols[-1][0], label=cols[-1][1])
3198 if before is not None:
3205 if before is not None:
3199 ui.write(sep, label='grep.sep')
3206 ui.write(sep, label='grep.sep')
3200 if not opts.get('text') and binary():
3207 if not opts.get('text') and binary():
3201 ui.write(" Binary file matches")
3208 ui.write(" Binary file matches")
3202 else:
3209 else:
3203 ui.write(before)
3210 ui.write(before)
3204 ui.write(match, label='grep.match')
3211 ui.write(match, label='grep.match')
3205 ui.write(after)
3212 ui.write(after)
3206 ui.write(eol)
3213 ui.write(eol)
3207 found = True
3214 found = True
3208 return found
3215 return found
3209
3216
3210 skip = {}
3217 skip = {}
3211 revfiles = {}
3218 revfiles = {}
3212 matchfn = scmutil.match(repo[None], pats, opts)
3219 matchfn = scmutil.match(repo[None], pats, opts)
3213 found = False
3220 found = False
3214 follow = opts.get('follow')
3221 follow = opts.get('follow')
3215
3222
3216 def prep(ctx, fns):
3223 def prep(ctx, fns):
3217 rev = ctx.rev()
3224 rev = ctx.rev()
3218 pctx = ctx.p1()
3225 pctx = ctx.p1()
3219 parent = pctx.rev()
3226 parent = pctx.rev()
3220 matches.setdefault(rev, {})
3227 matches.setdefault(rev, {})
3221 matches.setdefault(parent, {})
3228 matches.setdefault(parent, {})
3222 files = revfiles.setdefault(rev, [])
3229 files = revfiles.setdefault(rev, [])
3223 for fn in fns:
3230 for fn in fns:
3224 flog = getfile(fn)
3231 flog = getfile(fn)
3225 try:
3232 try:
3226 fnode = ctx.filenode(fn)
3233 fnode = ctx.filenode(fn)
3227 except error.LookupError:
3234 except error.LookupError:
3228 continue
3235 continue
3229
3236
3230 copied = flog.renamed(fnode)
3237 copied = flog.renamed(fnode)
3231 copy = follow and copied and copied[0]
3238 copy = follow and copied and copied[0]
3232 if copy:
3239 if copy:
3233 copies.setdefault(rev, {})[fn] = copy
3240 copies.setdefault(rev, {})[fn] = copy
3234 if fn in skip:
3241 if fn in skip:
3235 if copy:
3242 if copy:
3236 skip[copy] = True
3243 skip[copy] = True
3237 continue
3244 continue
3238 files.append(fn)
3245 files.append(fn)
3239
3246
3240 if fn not in matches[rev]:
3247 if fn not in matches[rev]:
3241 grepbody(fn, rev, flog.read(fnode))
3248 grepbody(fn, rev, flog.read(fnode))
3242
3249
3243 pfn = copy or fn
3250 pfn = copy or fn
3244 if pfn not in matches[parent]:
3251 if pfn not in matches[parent]:
3245 try:
3252 try:
3246 fnode = pctx.filenode(pfn)
3253 fnode = pctx.filenode(pfn)
3247 grepbody(pfn, parent, flog.read(fnode))
3254 grepbody(pfn, parent, flog.read(fnode))
3248 except error.LookupError:
3255 except error.LookupError:
3249 pass
3256 pass
3250
3257
3251 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3258 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3252 rev = ctx.rev()
3259 rev = ctx.rev()
3253 parent = ctx.p1().rev()
3260 parent = ctx.p1().rev()
3254 for fn in sorted(revfiles.get(rev, [])):
3261 for fn in sorted(revfiles.get(rev, [])):
3255 states = matches[rev][fn]
3262 states = matches[rev][fn]
3256 copy = copies.get(rev, {}).get(fn)
3263 copy = copies.get(rev, {}).get(fn)
3257 if fn in skip:
3264 if fn in skip:
3258 if copy:
3265 if copy:
3259 skip[copy] = True
3266 skip[copy] = True
3260 continue
3267 continue
3261 pstates = matches.get(parent, {}).get(copy or fn, [])
3268 pstates = matches.get(parent, {}).get(copy or fn, [])
3262 if pstates or states:
3269 if pstates or states:
3263 r = display(fn, ctx, pstates, states)
3270 r = display(fn, ctx, pstates, states)
3264 found = found or r
3271 found = found or r
3265 if r and not opts.get('all'):
3272 if r and not opts.get('all'):
3266 skip[fn] = True
3273 skip[fn] = True
3267 if copy:
3274 if copy:
3268 skip[copy] = True
3275 skip[copy] = True
3269 del matches[rev]
3276 del matches[rev]
3270 del revfiles[rev]
3277 del revfiles[rev]
3271
3278
3272 return not found
3279 return not found
3273
3280
3274 @command('heads',
3281 @command('heads',
3275 [('r', 'rev', '',
3282 [('r', 'rev', '',
3276 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3283 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3277 ('t', 'topo', False, _('show topological heads only')),
3284 ('t', 'topo', False, _('show topological heads only')),
3278 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3285 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3279 ('c', 'closed', False, _('show normal and closed branch heads')),
3286 ('c', 'closed', False, _('show normal and closed branch heads')),
3280 ] + templateopts,
3287 ] + templateopts,
3281 _('[-ct] [-r STARTREV] [REV]...'))
3288 _('[-ct] [-r STARTREV] [REV]...'))
3282 def heads(ui, repo, *branchrevs, **opts):
3289 def heads(ui, repo, *branchrevs, **opts):
3283 """show current repository heads or show branch heads
3290 """show current repository heads or show branch heads
3284
3291
3285 With no arguments, show all repository branch heads.
3292 With no arguments, show all repository branch heads.
3286
3293
3287 Repository "heads" are changesets with no child changesets. They are
3294 Repository "heads" are changesets with no child changesets. They are
3288 where development generally takes place and are the usual targets
3295 where development generally takes place and are the usual targets
3289 for update and merge operations. Branch heads are changesets that have
3296 for update and merge operations. Branch heads are changesets that have
3290 no child changeset on the same branch.
3297 no child changeset on the same branch.
3291
3298
3292 If one or more REVs are given, only branch heads on the branches
3299 If one or more REVs are given, only branch heads on the branches
3293 associated with the specified changesets are shown. This means
3300 associated with the specified changesets are shown. This means
3294 that you can use :hg:`heads foo` to see the heads on a branch
3301 that you can use :hg:`heads foo` to see the heads on a branch
3295 named ``foo``.
3302 named ``foo``.
3296
3303
3297 If -c/--closed is specified, also show branch heads marked closed
3304 If -c/--closed is specified, also show branch heads marked closed
3298 (see :hg:`commit --close-branch`).
3305 (see :hg:`commit --close-branch`).
3299
3306
3300 If STARTREV is specified, only those heads that are descendants of
3307 If STARTREV is specified, only those heads that are descendants of
3301 STARTREV will be displayed.
3308 STARTREV will be displayed.
3302
3309
3303 If -t/--topo is specified, named branch mechanics will be ignored and only
3310 If -t/--topo is specified, named branch mechanics will be ignored and only
3304 changesets without children will be shown.
3311 changesets without children will be shown.
3305
3312
3306 Returns 0 if matching heads are found, 1 if not.
3313 Returns 0 if matching heads are found, 1 if not.
3307 """
3314 """
3308
3315
3309 start = None
3316 start = None
3310 if 'rev' in opts:
3317 if 'rev' in opts:
3311 start = scmutil.revsingle(repo, opts['rev'], None).node()
3318 start = scmutil.revsingle(repo, opts['rev'], None).node()
3312
3319
3313 if opts.get('topo'):
3320 if opts.get('topo'):
3314 heads = [repo[h] for h in repo.heads(start)]
3321 heads = [repo[h] for h in repo.heads(start)]
3315 else:
3322 else:
3316 heads = []
3323 heads = []
3317 for branch in repo.branchmap():
3324 for branch in repo.branchmap():
3318 heads += repo.branchheads(branch, start, opts.get('closed'))
3325 heads += repo.branchheads(branch, start, opts.get('closed'))
3319 heads = [repo[h] for h in heads]
3326 heads = [repo[h] for h in heads]
3320
3327
3321 if branchrevs:
3328 if branchrevs:
3322 branches = set(repo[br].branch() for br in branchrevs)
3329 branches = set(repo[br].branch() for br in branchrevs)
3323 heads = [h for h in heads if h.branch() in branches]
3330 heads = [h for h in heads if h.branch() in branches]
3324
3331
3325 if opts.get('active') and branchrevs:
3332 if opts.get('active') and branchrevs:
3326 dagheads = repo.heads(start)
3333 dagheads = repo.heads(start)
3327 heads = [h for h in heads if h.node() in dagheads]
3334 heads = [h for h in heads if h.node() in dagheads]
3328
3335
3329 if branchrevs:
3336 if branchrevs:
3330 haveheads = set(h.branch() for h in heads)
3337 haveheads = set(h.branch() for h in heads)
3331 if branches - haveheads:
3338 if branches - haveheads:
3332 headless = ', '.join(b for b in branches - haveheads)
3339 headless = ', '.join(b for b in branches - haveheads)
3333 msg = _('no open branch heads found on branches %s')
3340 msg = _('no open branch heads found on branches %s')
3334 if opts.get('rev'):
3341 if opts.get('rev'):
3335 msg += _(' (started at %s)') % opts['rev']
3342 msg += _(' (started at %s)') % opts['rev']
3336 ui.warn((msg + '\n') % headless)
3343 ui.warn((msg + '\n') % headless)
3337
3344
3338 if not heads:
3345 if not heads:
3339 return 1
3346 return 1
3340
3347
3341 heads = sorted(heads, key=lambda x: -x.rev())
3348 heads = sorted(heads, key=lambda x: -x.rev())
3342 displayer = cmdutil.show_changeset(ui, repo, opts)
3349 displayer = cmdutil.show_changeset(ui, repo, opts)
3343 for ctx in heads:
3350 for ctx in heads:
3344 displayer.show(ctx)
3351 displayer.show(ctx)
3345 displayer.close()
3352 displayer.close()
3346
3353
3347 @command('help',
3354 @command('help',
3348 [('e', 'extension', None, _('show only help for extensions')),
3355 [('e', 'extension', None, _('show only help for extensions')),
3349 ('c', 'command', None, _('show only help for commands')),
3356 ('c', 'command', None, _('show only help for commands')),
3350 ('k', 'keyword', '', _('show topics matching keyword')),
3357 ('k', 'keyword', '', _('show topics matching keyword')),
3351 ],
3358 ],
3352 _('[-ec] [TOPIC]'))
3359 _('[-ec] [TOPIC]'))
3353 def help_(ui, name=None, **opts):
3360 def help_(ui, name=None, **opts):
3354 """show help for a given topic or a help overview
3361 """show help for a given topic or a help overview
3355
3362
3356 With no arguments, print a list of commands with short help messages.
3363 With no arguments, print a list of commands with short help messages.
3357
3364
3358 Given a topic, extension, or command name, print help for that
3365 Given a topic, extension, or command name, print help for that
3359 topic.
3366 topic.
3360
3367
3361 Returns 0 if successful.
3368 Returns 0 if successful.
3362 """
3369 """
3363
3370
3364 textwidth = min(ui.termwidth(), 80) - 2
3371 textwidth = min(ui.termwidth(), 80) - 2
3365
3372
3366 keep = ui.verbose and ['verbose'] or []
3373 keep = ui.verbose and ['verbose'] or []
3367 text = help.help_(ui, name, **opts)
3374 text = help.help_(ui, name, **opts)
3368
3375
3369 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3376 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3370 if 'verbose' in pruned:
3377 if 'verbose' in pruned:
3371 keep.append('omitted')
3378 keep.append('omitted')
3372 else:
3379 else:
3373 keep.append('notomitted')
3380 keep.append('notomitted')
3374 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3381 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3375 ui.write(formatted)
3382 ui.write(formatted)
3376
3383
3377
3384
3378 @command('identify|id',
3385 @command('identify|id',
3379 [('r', 'rev', '',
3386 [('r', 'rev', '',
3380 _('identify the specified revision'), _('REV')),
3387 _('identify the specified revision'), _('REV')),
3381 ('n', 'num', None, _('show local revision number')),
3388 ('n', 'num', None, _('show local revision number')),
3382 ('i', 'id', None, _('show global revision id')),
3389 ('i', 'id', None, _('show global revision id')),
3383 ('b', 'branch', None, _('show branch')),
3390 ('b', 'branch', None, _('show branch')),
3384 ('t', 'tags', None, _('show tags')),
3391 ('t', 'tags', None, _('show tags')),
3385 ('B', 'bookmarks', None, _('show bookmarks')),
3392 ('B', 'bookmarks', None, _('show bookmarks')),
3386 ] + remoteopts,
3393 ] + remoteopts,
3387 _('[-nibtB] [-r REV] [SOURCE]'))
3394 _('[-nibtB] [-r REV] [SOURCE]'))
3388 def identify(ui, repo, source=None, rev=None,
3395 def identify(ui, repo, source=None, rev=None,
3389 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3396 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3390 """identify the working copy or specified revision
3397 """identify the working copy or specified revision
3391
3398
3392 Print a summary identifying the repository state at REV using one or
3399 Print a summary identifying the repository state at REV using one or
3393 two parent hash identifiers, followed by a "+" if the working
3400 two parent hash identifiers, followed by a "+" if the working
3394 directory has uncommitted changes, the branch name (if not default),
3401 directory has uncommitted changes, the branch name (if not default),
3395 a list of tags, and a list of bookmarks.
3402 a list of tags, and a list of bookmarks.
3396
3403
3397 When REV is not given, print a summary of the current state of the
3404 When REV is not given, print a summary of the current state of the
3398 repository.
3405 repository.
3399
3406
3400 Specifying a path to a repository root or Mercurial bundle will
3407 Specifying a path to a repository root or Mercurial bundle will
3401 cause lookup to operate on that repository/bundle.
3408 cause lookup to operate on that repository/bundle.
3402
3409
3403 .. container:: verbose
3410 .. container:: verbose
3404
3411
3405 Examples:
3412 Examples:
3406
3413
3407 - generate a build identifier for the working directory::
3414 - generate a build identifier for the working directory::
3408
3415
3409 hg id --id > build-id.dat
3416 hg id --id > build-id.dat
3410
3417
3411 - find the revision corresponding to a tag::
3418 - find the revision corresponding to a tag::
3412
3419
3413 hg id -n -r 1.3
3420 hg id -n -r 1.3
3414
3421
3415 - check the most recent revision of a remote repository::
3422 - check the most recent revision of a remote repository::
3416
3423
3417 hg id -r tip http://selenic.com/hg/
3424 hg id -r tip http://selenic.com/hg/
3418
3425
3419 Returns 0 if successful.
3426 Returns 0 if successful.
3420 """
3427 """
3421
3428
3422 if not repo and not source:
3429 if not repo and not source:
3423 raise util.Abort(_("there is no Mercurial repository here "
3430 raise util.Abort(_("there is no Mercurial repository here "
3424 "(.hg not found)"))
3431 "(.hg not found)"))
3425
3432
3426 hexfunc = ui.debugflag and hex or short
3433 hexfunc = ui.debugflag and hex or short
3427 default = not (num or id or branch or tags or bookmarks)
3434 default = not (num or id or branch or tags or bookmarks)
3428 output = []
3435 output = []
3429 revs = []
3436 revs = []
3430
3437
3431 if source:
3438 if source:
3432 source, branches = hg.parseurl(ui.expandpath(source))
3439 source, branches = hg.parseurl(ui.expandpath(source))
3433 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3440 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3434 repo = peer.local()
3441 repo = peer.local()
3435 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3442 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3436
3443
3437 if not repo:
3444 if not repo:
3438 if num or branch or tags:
3445 if num or branch or tags:
3439 raise util.Abort(
3446 raise util.Abort(
3440 _("can't query remote revision number, branch, or tags"))
3447 _("can't query remote revision number, branch, or tags"))
3441 if not rev and revs:
3448 if not rev and revs:
3442 rev = revs[0]
3449 rev = revs[0]
3443 if not rev:
3450 if not rev:
3444 rev = "tip"
3451 rev = "tip"
3445
3452
3446 remoterev = peer.lookup(rev)
3453 remoterev = peer.lookup(rev)
3447 if default or id:
3454 if default or id:
3448 output = [hexfunc(remoterev)]
3455 output = [hexfunc(remoterev)]
3449
3456
3450 def getbms():
3457 def getbms():
3451 bms = []
3458 bms = []
3452
3459
3453 if 'bookmarks' in peer.listkeys('namespaces'):
3460 if 'bookmarks' in peer.listkeys('namespaces'):
3454 hexremoterev = hex(remoterev)
3461 hexremoterev = hex(remoterev)
3455 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3462 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3456 if bmr == hexremoterev]
3463 if bmr == hexremoterev]
3457
3464
3458 return sorted(bms)
3465 return sorted(bms)
3459
3466
3460 if bookmarks:
3467 if bookmarks:
3461 output.extend(getbms())
3468 output.extend(getbms())
3462 elif default and not ui.quiet:
3469 elif default and not ui.quiet:
3463 # multiple bookmarks for a single parent separated by '/'
3470 # multiple bookmarks for a single parent separated by '/'
3464 bm = '/'.join(getbms())
3471 bm = '/'.join(getbms())
3465 if bm:
3472 if bm:
3466 output.append(bm)
3473 output.append(bm)
3467 else:
3474 else:
3468 if not rev:
3475 if not rev:
3469 ctx = repo[None]
3476 ctx = repo[None]
3470 parents = ctx.parents()
3477 parents = ctx.parents()
3471 changed = ""
3478 changed = ""
3472 if default or id or num:
3479 if default or id or num:
3473 if (util.any(repo.status())
3480 if (util.any(repo.status())
3474 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3481 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3475 changed = '+'
3482 changed = '+'
3476 if default or id:
3483 if default or id:
3477 output = ["%s%s" %
3484 output = ["%s%s" %
3478 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3485 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3479 if num:
3486 if num:
3480 output.append("%s%s" %
3487 output.append("%s%s" %
3481 ('+'.join([str(p.rev()) for p in parents]), changed))
3488 ('+'.join([str(p.rev()) for p in parents]), changed))
3482 else:
3489 else:
3483 ctx = scmutil.revsingle(repo, rev)
3490 ctx = scmutil.revsingle(repo, rev)
3484 if default or id:
3491 if default or id:
3485 output = [hexfunc(ctx.node())]
3492 output = [hexfunc(ctx.node())]
3486 if num:
3493 if num:
3487 output.append(str(ctx.rev()))
3494 output.append(str(ctx.rev()))
3488
3495
3489 if default and not ui.quiet:
3496 if default and not ui.quiet:
3490 b = ctx.branch()
3497 b = ctx.branch()
3491 if b != 'default':
3498 if b != 'default':
3492 output.append("(%s)" % b)
3499 output.append("(%s)" % b)
3493
3500
3494 # multiple tags for a single parent separated by '/'
3501 # multiple tags for a single parent separated by '/'
3495 t = '/'.join(ctx.tags())
3502 t = '/'.join(ctx.tags())
3496 if t:
3503 if t:
3497 output.append(t)
3504 output.append(t)
3498
3505
3499 # multiple bookmarks for a single parent separated by '/'
3506 # multiple bookmarks for a single parent separated by '/'
3500 bm = '/'.join(ctx.bookmarks())
3507 bm = '/'.join(ctx.bookmarks())
3501 if bm:
3508 if bm:
3502 output.append(bm)
3509 output.append(bm)
3503 else:
3510 else:
3504 if branch:
3511 if branch:
3505 output.append(ctx.branch())
3512 output.append(ctx.branch())
3506
3513
3507 if tags:
3514 if tags:
3508 output.extend(ctx.tags())
3515 output.extend(ctx.tags())
3509
3516
3510 if bookmarks:
3517 if bookmarks:
3511 output.extend(ctx.bookmarks())
3518 output.extend(ctx.bookmarks())
3512
3519
3513 ui.write("%s\n" % ' '.join(output))
3520 ui.write("%s\n" % ' '.join(output))
3514
3521
3515 @command('import|patch',
3522 @command('import|patch',
3516 [('p', 'strip', 1,
3523 [('p', 'strip', 1,
3517 _('directory strip option for patch. This has the same '
3524 _('directory strip option for patch. This has the same '
3518 'meaning as the corresponding patch option'), _('NUM')),
3525 'meaning as the corresponding patch option'), _('NUM')),
3519 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3526 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3520 ('e', 'edit', False, _('invoke editor on commit messages')),
3527 ('e', 'edit', False, _('invoke editor on commit messages')),
3521 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3528 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3522 ('', 'no-commit', None,
3529 ('', 'no-commit', None,
3523 _("don't commit, just update the working directory")),
3530 _("don't commit, just update the working directory")),
3524 ('', 'bypass', None,
3531 ('', 'bypass', None,
3525 _("apply patch without touching the working directory")),
3532 _("apply patch without touching the working directory")),
3526 ('', 'exact', None,
3533 ('', 'exact', None,
3527 _('apply patch to the nodes from which it was generated')),
3534 _('apply patch to the nodes from which it was generated')),
3528 ('', 'import-branch', None,
3535 ('', 'import-branch', None,
3529 _('use any branch information in patch (implied by --exact)'))] +
3536 _('use any branch information in patch (implied by --exact)'))] +
3530 commitopts + commitopts2 + similarityopts,
3537 commitopts + commitopts2 + similarityopts,
3531 _('[OPTION]... PATCH...'))
3538 _('[OPTION]... PATCH...'))
3532 def import_(ui, repo, patch1=None, *patches, **opts):
3539 def import_(ui, repo, patch1=None, *patches, **opts):
3533 """import an ordered set of patches
3540 """import an ordered set of patches
3534
3541
3535 Import a list of patches and commit them individually (unless
3542 Import a list of patches and commit them individually (unless
3536 --no-commit is specified).
3543 --no-commit is specified).
3537
3544
3538 If there are outstanding changes in the working directory, import
3545 If there are outstanding changes in the working directory, import
3539 will abort unless given the -f/--force flag.
3546 will abort unless given the -f/--force flag.
3540
3547
3541 You can import a patch straight from a mail message. Even patches
3548 You can import a patch straight from a mail message. Even patches
3542 as attachments work (to use the body part, it must have type
3549 as attachments work (to use the body part, it must have type
3543 text/plain or text/x-patch). From and Subject headers of email
3550 text/plain or text/x-patch). From and Subject headers of email
3544 message are used as default committer and commit message. All
3551 message are used as default committer and commit message. All
3545 text/plain body parts before first diff are added to commit
3552 text/plain body parts before first diff are added to commit
3546 message.
3553 message.
3547
3554
3548 If the imported patch was generated by :hg:`export`, user and
3555 If the imported patch was generated by :hg:`export`, user and
3549 description from patch override values from message headers and
3556 description from patch override values from message headers and
3550 body. Values given on command line with -m/--message and -u/--user
3557 body. Values given on command line with -m/--message and -u/--user
3551 override these.
3558 override these.
3552
3559
3553 If --exact is specified, import will set the working directory to
3560 If --exact is specified, import will set the working directory to
3554 the parent of each patch before applying it, and will abort if the
3561 the parent of each patch before applying it, and will abort if the
3555 resulting changeset has a different ID than the one recorded in
3562 resulting changeset has a different ID than the one recorded in
3556 the patch. This may happen due to character set problems or other
3563 the patch. This may happen due to character set problems or other
3557 deficiencies in the text patch format.
3564 deficiencies in the text patch format.
3558
3565
3559 Use --bypass to apply and commit patches directly to the
3566 Use --bypass to apply and commit patches directly to the
3560 repository, not touching the working directory. Without --exact,
3567 repository, not touching the working directory. Without --exact,
3561 patches will be applied on top of the working directory parent
3568 patches will be applied on top of the working directory parent
3562 revision.
3569 revision.
3563
3570
3564 With -s/--similarity, hg will attempt to discover renames and
3571 With -s/--similarity, hg will attempt to discover renames and
3565 copies in the patch in the same way as :hg:`addremove`.
3572 copies in the patch in the same way as :hg:`addremove`.
3566
3573
3567 To read a patch from standard input, use "-" as the patch name. If
3574 To read a patch from standard input, use "-" as the patch name. If
3568 a URL is specified, the patch will be downloaded from it.
3575 a URL is specified, the patch will be downloaded from it.
3569 See :hg:`help dates` for a list of formats valid for -d/--date.
3576 See :hg:`help dates` for a list of formats valid for -d/--date.
3570
3577
3571 .. container:: verbose
3578 .. container:: verbose
3572
3579
3573 Examples:
3580 Examples:
3574
3581
3575 - import a traditional patch from a website and detect renames::
3582 - import a traditional patch from a website and detect renames::
3576
3583
3577 hg import -s 80 http://example.com/bugfix.patch
3584 hg import -s 80 http://example.com/bugfix.patch
3578
3585
3579 - import a changeset from an hgweb server::
3586 - import a changeset from an hgweb server::
3580
3587
3581 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3588 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3582
3589
3583 - import all the patches in an Unix-style mbox::
3590 - import all the patches in an Unix-style mbox::
3584
3591
3585 hg import incoming-patches.mbox
3592 hg import incoming-patches.mbox
3586
3593
3587 - attempt to exactly restore an exported changeset (not always
3594 - attempt to exactly restore an exported changeset (not always
3588 possible)::
3595 possible)::
3589
3596
3590 hg import --exact proposed-fix.patch
3597 hg import --exact proposed-fix.patch
3591
3598
3592 Returns 0 on success.
3599 Returns 0 on success.
3593 """
3600 """
3594
3601
3595 if not patch1:
3602 if not patch1:
3596 raise util.Abort(_('need at least one patch to import'))
3603 raise util.Abort(_('need at least one patch to import'))
3597
3604
3598 patches = (patch1,) + patches
3605 patches = (patch1,) + patches
3599
3606
3600 date = opts.get('date')
3607 date = opts.get('date')
3601 if date:
3608 if date:
3602 opts['date'] = util.parsedate(date)
3609 opts['date'] = util.parsedate(date)
3603
3610
3604 editor = cmdutil.commiteditor
3611 editor = cmdutil.commiteditor
3605 if opts.get('edit'):
3612 if opts.get('edit'):
3606 editor = cmdutil.commitforceeditor
3613 editor = cmdutil.commitforceeditor
3607
3614
3608 update = not opts.get('bypass')
3615 update = not opts.get('bypass')
3609 if not update and opts.get('no_commit'):
3616 if not update and opts.get('no_commit'):
3610 raise util.Abort(_('cannot use --no-commit with --bypass'))
3617 raise util.Abort(_('cannot use --no-commit with --bypass'))
3611 try:
3618 try:
3612 sim = float(opts.get('similarity') or 0)
3619 sim = float(opts.get('similarity') or 0)
3613 except ValueError:
3620 except ValueError:
3614 raise util.Abort(_('similarity must be a number'))
3621 raise util.Abort(_('similarity must be a number'))
3615 if sim < 0 or sim > 100:
3622 if sim < 0 or sim > 100:
3616 raise util.Abort(_('similarity must be between 0 and 100'))
3623 raise util.Abort(_('similarity must be between 0 and 100'))
3617 if sim and not update:
3624 if sim and not update:
3618 raise util.Abort(_('cannot use --similarity with --bypass'))
3625 raise util.Abort(_('cannot use --similarity with --bypass'))
3619
3626
3620 if (opts.get('exact') or not opts.get('force')) and update:
3627 if (opts.get('exact') or not opts.get('force')) and update:
3621 cmdutil.bailifchanged(repo)
3628 cmdutil.bailifchanged(repo)
3622
3629
3623 base = opts["base"]
3630 base = opts["base"]
3624 strip = opts["strip"]
3631 strip = opts["strip"]
3625 wlock = lock = tr = None
3632 wlock = lock = tr = None
3626 msgs = []
3633 msgs = []
3627
3634
3628 def tryone(ui, hunk, parents):
3635 def tryone(ui, hunk, parents):
3629 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3636 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3630 patch.extract(ui, hunk)
3637 patch.extract(ui, hunk)
3631
3638
3632 if not tmpname:
3639 if not tmpname:
3633 return (None, None)
3640 return (None, None)
3634 msg = _('applied to working directory')
3641 msg = _('applied to working directory')
3635
3642
3636 try:
3643 try:
3637 cmdline_message = cmdutil.logmessage(ui, opts)
3644 cmdline_message = cmdutil.logmessage(ui, opts)
3638 if cmdline_message:
3645 if cmdline_message:
3639 # pickup the cmdline msg
3646 # pickup the cmdline msg
3640 message = cmdline_message
3647 message = cmdline_message
3641 elif message:
3648 elif message:
3642 # pickup the patch msg
3649 # pickup the patch msg
3643 message = message.strip()
3650 message = message.strip()
3644 else:
3651 else:
3645 # launch the editor
3652 # launch the editor
3646 message = None
3653 message = None
3647 ui.debug('message:\n%s\n' % message)
3654 ui.debug('message:\n%s\n' % message)
3648
3655
3649 if len(parents) == 1:
3656 if len(parents) == 1:
3650 parents.append(repo[nullid])
3657 parents.append(repo[nullid])
3651 if opts.get('exact'):
3658 if opts.get('exact'):
3652 if not nodeid or not p1:
3659 if not nodeid or not p1:
3653 raise util.Abort(_('not a Mercurial patch'))
3660 raise util.Abort(_('not a Mercurial patch'))
3654 p1 = repo[p1]
3661 p1 = repo[p1]
3655 p2 = repo[p2 or nullid]
3662 p2 = repo[p2 or nullid]
3656 elif p2:
3663 elif p2:
3657 try:
3664 try:
3658 p1 = repo[p1]
3665 p1 = repo[p1]
3659 p2 = repo[p2]
3666 p2 = repo[p2]
3660 # Without any options, consider p2 only if the
3667 # Without any options, consider p2 only if the
3661 # patch is being applied on top of the recorded
3668 # patch is being applied on top of the recorded
3662 # first parent.
3669 # first parent.
3663 if p1 != parents[0]:
3670 if p1 != parents[0]:
3664 p1 = parents[0]
3671 p1 = parents[0]
3665 p2 = repo[nullid]
3672 p2 = repo[nullid]
3666 except error.RepoError:
3673 except error.RepoError:
3667 p1, p2 = parents
3674 p1, p2 = parents
3668 else:
3675 else:
3669 p1, p2 = parents
3676 p1, p2 = parents
3670
3677
3671 n = None
3678 n = None
3672 if update:
3679 if update:
3673 if p1 != parents[0]:
3680 if p1 != parents[0]:
3674 hg.clean(repo, p1.node())
3681 hg.clean(repo, p1.node())
3675 if p2 != parents[1]:
3682 if p2 != parents[1]:
3676 repo.setparents(p1.node(), p2.node())
3683 repo.setparents(p1.node(), p2.node())
3677
3684
3678 if opts.get('exact') or opts.get('import_branch'):
3685 if opts.get('exact') or opts.get('import_branch'):
3679 repo.dirstate.setbranch(branch or 'default')
3686 repo.dirstate.setbranch(branch or 'default')
3680
3687
3681 files = set()
3688 files = set()
3682 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3689 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3683 eolmode=None, similarity=sim / 100.0)
3690 eolmode=None, similarity=sim / 100.0)
3684 files = list(files)
3691 files = list(files)
3685 if opts.get('no_commit'):
3692 if opts.get('no_commit'):
3686 if message:
3693 if message:
3687 msgs.append(message)
3694 msgs.append(message)
3688 else:
3695 else:
3689 if opts.get('exact') or p2:
3696 if opts.get('exact') or p2:
3690 # If you got here, you either use --force and know what
3697 # If you got here, you either use --force and know what
3691 # you are doing or used --exact or a merge patch while
3698 # you are doing or used --exact or a merge patch while
3692 # being updated to its first parent.
3699 # being updated to its first parent.
3693 m = None
3700 m = None
3694 else:
3701 else:
3695 m = scmutil.matchfiles(repo, files or [])
3702 m = scmutil.matchfiles(repo, files or [])
3696 n = repo.commit(message, opts.get('user') or user,
3703 n = repo.commit(message, opts.get('user') or user,
3697 opts.get('date') or date, match=m,
3704 opts.get('date') or date, match=m,
3698 editor=editor)
3705 editor=editor)
3699 else:
3706 else:
3700 if opts.get('exact') or opts.get('import_branch'):
3707 if opts.get('exact') or opts.get('import_branch'):
3701 branch = branch or 'default'
3708 branch = branch or 'default'
3702 else:
3709 else:
3703 branch = p1.branch()
3710 branch = p1.branch()
3704 store = patch.filestore()
3711 store = patch.filestore()
3705 try:
3712 try:
3706 files = set()
3713 files = set()
3707 try:
3714 try:
3708 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3715 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3709 files, eolmode=None)
3716 files, eolmode=None)
3710 except patch.PatchError, e:
3717 except patch.PatchError, e:
3711 raise util.Abort(str(e))
3718 raise util.Abort(str(e))
3712 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3719 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3713 message,
3720 message,
3714 opts.get('user') or user,
3721 opts.get('user') or user,
3715 opts.get('date') or date,
3722 opts.get('date') or date,
3716 branch, files, store,
3723 branch, files, store,
3717 editor=cmdutil.commiteditor)
3724 editor=cmdutil.commiteditor)
3718 repo.savecommitmessage(memctx.description())
3725 repo.savecommitmessage(memctx.description())
3719 n = memctx.commit()
3726 n = memctx.commit()
3720 finally:
3727 finally:
3721 store.close()
3728 store.close()
3722 if opts.get('exact') and hex(n) != nodeid:
3729 if opts.get('exact') and hex(n) != nodeid:
3723 raise util.Abort(_('patch is damaged or loses information'))
3730 raise util.Abort(_('patch is damaged or loses information'))
3724 if n:
3731 if n:
3725 # i18n: refers to a short changeset id
3732 # i18n: refers to a short changeset id
3726 msg = _('created %s') % short(n)
3733 msg = _('created %s') % short(n)
3727 return (msg, n)
3734 return (msg, n)
3728 finally:
3735 finally:
3729 os.unlink(tmpname)
3736 os.unlink(tmpname)
3730
3737
3731 try:
3738 try:
3732 try:
3739 try:
3733 wlock = repo.wlock()
3740 wlock = repo.wlock()
3734 if not opts.get('no_commit'):
3741 if not opts.get('no_commit'):
3735 lock = repo.lock()
3742 lock = repo.lock()
3736 tr = repo.transaction('import')
3743 tr = repo.transaction('import')
3737 parents = repo.parents()
3744 parents = repo.parents()
3738 for patchurl in patches:
3745 for patchurl in patches:
3739 if patchurl == '-':
3746 if patchurl == '-':
3740 ui.status(_('applying patch from stdin\n'))
3747 ui.status(_('applying patch from stdin\n'))
3741 patchfile = ui.fin
3748 patchfile = ui.fin
3742 patchurl = 'stdin' # for error message
3749 patchurl = 'stdin' # for error message
3743 else:
3750 else:
3744 patchurl = os.path.join(base, patchurl)
3751 patchurl = os.path.join(base, patchurl)
3745 ui.status(_('applying %s\n') % patchurl)
3752 ui.status(_('applying %s\n') % patchurl)
3746 patchfile = hg.openpath(ui, patchurl)
3753 patchfile = hg.openpath(ui, patchurl)
3747
3754
3748 haspatch = False
3755 haspatch = False
3749 for hunk in patch.split(patchfile):
3756 for hunk in patch.split(patchfile):
3750 (msg, node) = tryone(ui, hunk, parents)
3757 (msg, node) = tryone(ui, hunk, parents)
3751 if msg:
3758 if msg:
3752 haspatch = True
3759 haspatch = True
3753 ui.note(msg + '\n')
3760 ui.note(msg + '\n')
3754 if update or opts.get('exact'):
3761 if update or opts.get('exact'):
3755 parents = repo.parents()
3762 parents = repo.parents()
3756 else:
3763 else:
3757 parents = [repo[node]]
3764 parents = [repo[node]]
3758
3765
3759 if not haspatch:
3766 if not haspatch:
3760 raise util.Abort(_('%s: no diffs found') % patchurl)
3767 raise util.Abort(_('%s: no diffs found') % patchurl)
3761
3768
3762 if tr:
3769 if tr:
3763 tr.close()
3770 tr.close()
3764 if msgs:
3771 if msgs:
3765 repo.savecommitmessage('\n* * *\n'.join(msgs))
3772 repo.savecommitmessage('\n* * *\n'.join(msgs))
3766 except: # re-raises
3773 except: # re-raises
3767 # wlock.release() indirectly calls dirstate.write(): since
3774 # wlock.release() indirectly calls dirstate.write(): since
3768 # we're crashing, we do not want to change the working dir
3775 # we're crashing, we do not want to change the working dir
3769 # parent after all, so make sure it writes nothing
3776 # parent after all, so make sure it writes nothing
3770 repo.dirstate.invalidate()
3777 repo.dirstate.invalidate()
3771 raise
3778 raise
3772 finally:
3779 finally:
3773 if tr:
3780 if tr:
3774 tr.release()
3781 tr.release()
3775 release(lock, wlock)
3782 release(lock, wlock)
3776
3783
3777 @command('incoming|in',
3784 @command('incoming|in',
3778 [('f', 'force', None,
3785 [('f', 'force', None,
3779 _('run even if remote repository is unrelated')),
3786 _('run even if remote repository is unrelated')),
3780 ('n', 'newest-first', None, _('show newest record first')),
3787 ('n', 'newest-first', None, _('show newest record first')),
3781 ('', 'bundle', '',
3788 ('', 'bundle', '',
3782 _('file to store the bundles into'), _('FILE')),
3789 _('file to store the bundles into'), _('FILE')),
3783 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3790 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3784 ('B', 'bookmarks', False, _("compare bookmarks")),
3791 ('B', 'bookmarks', False, _("compare bookmarks")),
3785 ('b', 'branch', [],
3792 ('b', 'branch', [],
3786 _('a specific branch you would like to pull'), _('BRANCH')),
3793 _('a specific branch you would like to pull'), _('BRANCH')),
3787 ] + logopts + remoteopts + subrepoopts,
3794 ] + logopts + remoteopts + subrepoopts,
3788 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3795 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3789 def incoming(ui, repo, source="default", **opts):
3796 def incoming(ui, repo, source="default", **opts):
3790 """show new changesets found in source
3797 """show new changesets found in source
3791
3798
3792 Show new changesets found in the specified path/URL or the default
3799 Show new changesets found in the specified path/URL or the default
3793 pull location. These are the changesets that would have been pulled
3800 pull location. These are the changesets that would have been pulled
3794 if a pull at the time you issued this command.
3801 if a pull at the time you issued this command.
3795
3802
3796 For remote repository, using --bundle avoids downloading the
3803 For remote repository, using --bundle avoids downloading the
3797 changesets twice if the incoming is followed by a pull.
3804 changesets twice if the incoming is followed by a pull.
3798
3805
3799 See pull for valid source format details.
3806 See pull for valid source format details.
3800
3807
3801 Returns 0 if there are incoming changes, 1 otherwise.
3808 Returns 0 if there are incoming changes, 1 otherwise.
3802 """
3809 """
3803 if opts.get('graph'):
3810 if opts.get('graph'):
3804 cmdutil.checkunsupportedgraphflags([], opts)
3811 cmdutil.checkunsupportedgraphflags([], opts)
3805 def display(other, chlist, displayer):
3812 def display(other, chlist, displayer):
3806 revdag = cmdutil.graphrevs(other, chlist, opts)
3813 revdag = cmdutil.graphrevs(other, chlist, opts)
3807 showparents = [ctx.node() for ctx in repo[None].parents()]
3814 showparents = [ctx.node() for ctx in repo[None].parents()]
3808 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3815 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3809 graphmod.asciiedges)
3816 graphmod.asciiedges)
3810
3817
3811 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3818 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3812 return 0
3819 return 0
3813
3820
3814 if opts.get('bundle') and opts.get('subrepos'):
3821 if opts.get('bundle') and opts.get('subrepos'):
3815 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3822 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3816
3823
3817 if opts.get('bookmarks'):
3824 if opts.get('bookmarks'):
3818 source, branches = hg.parseurl(ui.expandpath(source),
3825 source, branches = hg.parseurl(ui.expandpath(source),
3819 opts.get('branch'))
3826 opts.get('branch'))
3820 other = hg.peer(repo, opts, source)
3827 other = hg.peer(repo, opts, source)
3821 if 'bookmarks' not in other.listkeys('namespaces'):
3828 if 'bookmarks' not in other.listkeys('namespaces'):
3822 ui.warn(_("remote doesn't support bookmarks\n"))
3829 ui.warn(_("remote doesn't support bookmarks\n"))
3823 return 0
3830 return 0
3824 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3831 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3825 return bookmarks.diff(ui, repo, other)
3832 return bookmarks.diff(ui, repo, other)
3826
3833
3827 repo._subtoppath = ui.expandpath(source)
3834 repo._subtoppath = ui.expandpath(source)
3828 try:
3835 try:
3829 return hg.incoming(ui, repo, source, opts)
3836 return hg.incoming(ui, repo, source, opts)
3830 finally:
3837 finally:
3831 del repo._subtoppath
3838 del repo._subtoppath
3832
3839
3833
3840
3834 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3841 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3835 def init(ui, dest=".", **opts):
3842 def init(ui, dest=".", **opts):
3836 """create a new repository in the given directory
3843 """create a new repository in the given directory
3837
3844
3838 Initialize a new repository in the given directory. If the given
3845 Initialize a new repository in the given directory. If the given
3839 directory does not exist, it will be created.
3846 directory does not exist, it will be created.
3840
3847
3841 If no directory is given, the current directory is used.
3848 If no directory is given, the current directory is used.
3842
3849
3843 It is possible to specify an ``ssh://`` URL as the destination.
3850 It is possible to specify an ``ssh://`` URL as the destination.
3844 See :hg:`help urls` for more information.
3851 See :hg:`help urls` for more information.
3845
3852
3846 Returns 0 on success.
3853 Returns 0 on success.
3847 """
3854 """
3848 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3855 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3849
3856
3850 @command('locate',
3857 @command('locate',
3851 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3858 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3852 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3859 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3853 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3860 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3854 ] + walkopts,
3861 ] + walkopts,
3855 _('[OPTION]... [PATTERN]...'))
3862 _('[OPTION]... [PATTERN]...'))
3856 def locate(ui, repo, *pats, **opts):
3863 def locate(ui, repo, *pats, **opts):
3857 """locate files matching specific patterns
3864 """locate files matching specific patterns
3858
3865
3859 Print files under Mercurial control in the working directory whose
3866 Print files under Mercurial control in the working directory whose
3860 names match the given patterns.
3867 names match the given patterns.
3861
3868
3862 By default, this command searches all directories in the working
3869 By default, this command searches all directories in the working
3863 directory. To search just the current directory and its
3870 directory. To search just the current directory and its
3864 subdirectories, use "--include .".
3871 subdirectories, use "--include .".
3865
3872
3866 If no patterns are given to match, this command prints the names
3873 If no patterns are given to match, this command prints the names
3867 of all files under Mercurial control in the working directory.
3874 of all files under Mercurial control in the working directory.
3868
3875
3869 If you want to feed the output of this command into the "xargs"
3876 If you want to feed the output of this command into the "xargs"
3870 command, use the -0 option to both this command and "xargs". This
3877 command, use the -0 option to both this command and "xargs". This
3871 will avoid the problem of "xargs" treating single filenames that
3878 will avoid the problem of "xargs" treating single filenames that
3872 contain whitespace as multiple filenames.
3879 contain whitespace as multiple filenames.
3873
3880
3874 Returns 0 if a match is found, 1 otherwise.
3881 Returns 0 if a match is found, 1 otherwise.
3875 """
3882 """
3876 end = opts.get('print0') and '\0' or '\n'
3883 end = opts.get('print0') and '\0' or '\n'
3877 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3884 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3878
3885
3879 ret = 1
3886 ret = 1
3880 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3887 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3881 m.bad = lambda x, y: False
3888 m.bad = lambda x, y: False
3882 for abs in repo[rev].walk(m):
3889 for abs in repo[rev].walk(m):
3883 if not rev and abs not in repo.dirstate:
3890 if not rev and abs not in repo.dirstate:
3884 continue
3891 continue
3885 if opts.get('fullpath'):
3892 if opts.get('fullpath'):
3886 ui.write(repo.wjoin(abs), end)
3893 ui.write(repo.wjoin(abs), end)
3887 else:
3894 else:
3888 ui.write(((pats and m.rel(abs)) or abs), end)
3895 ui.write(((pats and m.rel(abs)) or abs), end)
3889 ret = 0
3896 ret = 0
3890
3897
3891 return ret
3898 return ret
3892
3899
3893 @command('^log|history',
3900 @command('^log|history',
3894 [('f', 'follow', None,
3901 [('f', 'follow', None,
3895 _('follow changeset history, or file history across copies and renames')),
3902 _('follow changeset history, or file history across copies and renames')),
3896 ('', 'follow-first', None,
3903 ('', 'follow-first', None,
3897 _('only follow the first parent of merge changesets (DEPRECATED)')),
3904 _('only follow the first parent of merge changesets (DEPRECATED)')),
3898 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3905 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3899 ('C', 'copies', None, _('show copied files')),
3906 ('C', 'copies', None, _('show copied files')),
3900 ('k', 'keyword', [],
3907 ('k', 'keyword', [],
3901 _('do case-insensitive search for a given text'), _('TEXT')),
3908 _('do case-insensitive search for a given text'), _('TEXT')),
3902 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3909 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3903 ('', 'removed', None, _('include revisions where files were removed')),
3910 ('', 'removed', None, _('include revisions where files were removed')),
3904 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3911 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3905 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3912 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3906 ('', 'only-branch', [],
3913 ('', 'only-branch', [],
3907 _('show only changesets within the given named branch (DEPRECATED)'),
3914 _('show only changesets within the given named branch (DEPRECATED)'),
3908 _('BRANCH')),
3915 _('BRANCH')),
3909 ('b', 'branch', [],
3916 ('b', 'branch', [],
3910 _('show changesets within the given named branch'), _('BRANCH')),
3917 _('show changesets within the given named branch'), _('BRANCH')),
3911 ('P', 'prune', [],
3918 ('P', 'prune', [],
3912 _('do not display revision or any of its ancestors'), _('REV')),
3919 _('do not display revision or any of its ancestors'), _('REV')),
3913 ] + logopts + walkopts,
3920 ] + logopts + walkopts,
3914 _('[OPTION]... [FILE]'))
3921 _('[OPTION]... [FILE]'))
3915 def log(ui, repo, *pats, **opts):
3922 def log(ui, repo, *pats, **opts):
3916 """show revision history of entire repository or files
3923 """show revision history of entire repository or files
3917
3924
3918 Print the revision history of the specified files or the entire
3925 Print the revision history of the specified files or the entire
3919 project.
3926 project.
3920
3927
3921 If no revision range is specified, the default is ``tip:0`` unless
3928 If no revision range is specified, the default is ``tip:0`` unless
3922 --follow is set, in which case the working directory parent is
3929 --follow is set, in which case the working directory parent is
3923 used as the starting revision.
3930 used as the starting revision.
3924
3931
3925 File history is shown without following rename or copy history of
3932 File history is shown without following rename or copy history of
3926 files. Use -f/--follow with a filename to follow history across
3933 files. Use -f/--follow with a filename to follow history across
3927 renames and copies. --follow without a filename will only show
3934 renames and copies. --follow without a filename will only show
3928 ancestors or descendants of the starting revision.
3935 ancestors or descendants of the starting revision.
3929
3936
3930 By default this command prints revision number and changeset id,
3937 By default this command prints revision number and changeset id,
3931 tags, non-trivial parents, user, date and time, and a summary for
3938 tags, non-trivial parents, user, date and time, and a summary for
3932 each commit. When the -v/--verbose switch is used, the list of
3939 each commit. When the -v/--verbose switch is used, the list of
3933 changed files and full commit message are shown.
3940 changed files and full commit message are shown.
3934
3941
3935 .. note::
3942 .. note::
3936 log -p/--patch may generate unexpected diff output for merge
3943 log -p/--patch may generate unexpected diff output for merge
3937 changesets, as it will only compare the merge changeset against
3944 changesets, as it will only compare the merge changeset against
3938 its first parent. Also, only files different from BOTH parents
3945 its first parent. Also, only files different from BOTH parents
3939 will appear in files:.
3946 will appear in files:.
3940
3947
3941 .. note::
3948 .. note::
3942 for performance reasons, log FILE may omit duplicate changes
3949 for performance reasons, log FILE may omit duplicate changes
3943 made on branches and will not show deletions. To see all
3950 made on branches and will not show deletions. To see all
3944 changes including duplicates and deletions, use the --removed
3951 changes including duplicates and deletions, use the --removed
3945 switch.
3952 switch.
3946
3953
3947 .. container:: verbose
3954 .. container:: verbose
3948
3955
3949 Some examples:
3956 Some examples:
3950
3957
3951 - changesets with full descriptions and file lists::
3958 - changesets with full descriptions and file lists::
3952
3959
3953 hg log -v
3960 hg log -v
3954
3961
3955 - changesets ancestral to the working directory::
3962 - changesets ancestral to the working directory::
3956
3963
3957 hg log -f
3964 hg log -f
3958
3965
3959 - last 10 commits on the current branch::
3966 - last 10 commits on the current branch::
3960
3967
3961 hg log -l 10 -b .
3968 hg log -l 10 -b .
3962
3969
3963 - changesets showing all modifications of a file, including removals::
3970 - changesets showing all modifications of a file, including removals::
3964
3971
3965 hg log --removed file.c
3972 hg log --removed file.c
3966
3973
3967 - all changesets that touch a directory, with diffs, excluding merges::
3974 - all changesets that touch a directory, with diffs, excluding merges::
3968
3975
3969 hg log -Mp lib/
3976 hg log -Mp lib/
3970
3977
3971 - all revision numbers that match a keyword::
3978 - all revision numbers that match a keyword::
3972
3979
3973 hg log -k bug --template "{rev}\\n"
3980 hg log -k bug --template "{rev}\\n"
3974
3981
3975 - check if a given changeset is included is a tagged release::
3982 - check if a given changeset is included is a tagged release::
3976
3983
3977 hg log -r "a21ccf and ancestor(1.9)"
3984 hg log -r "a21ccf and ancestor(1.9)"
3978
3985
3979 - find all changesets by some user in a date range::
3986 - find all changesets by some user in a date range::
3980
3987
3981 hg log -k alice -d "may 2008 to jul 2008"
3988 hg log -k alice -d "may 2008 to jul 2008"
3982
3989
3983 - summary of all changesets after the last tag::
3990 - summary of all changesets after the last tag::
3984
3991
3985 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3992 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3986
3993
3987 See :hg:`help dates` for a list of formats valid for -d/--date.
3994 See :hg:`help dates` for a list of formats valid for -d/--date.
3988
3995
3989 See :hg:`help revisions` and :hg:`help revsets` for more about
3996 See :hg:`help revisions` and :hg:`help revsets` for more about
3990 specifying revisions.
3997 specifying revisions.
3991
3998
3992 See :hg:`help templates` for more about pre-packaged styles and
3999 See :hg:`help templates` for more about pre-packaged styles and
3993 specifying custom templates.
4000 specifying custom templates.
3994
4001
3995 Returns 0 on success.
4002 Returns 0 on success.
3996 """
4003 """
3997 if opts.get('graph'):
4004 if opts.get('graph'):
3998 return cmdutil.graphlog(ui, repo, *pats, **opts)
4005 return cmdutil.graphlog(ui, repo, *pats, **opts)
3999
4006
4000 matchfn = scmutil.match(repo[None], pats, opts)
4007 matchfn = scmutil.match(repo[None], pats, opts)
4001 limit = cmdutil.loglimit(opts)
4008 limit = cmdutil.loglimit(opts)
4002 count = 0
4009 count = 0
4003
4010
4004 getrenamed, endrev = None, None
4011 getrenamed, endrev = None, None
4005 if opts.get('copies'):
4012 if opts.get('copies'):
4006 if opts.get('rev'):
4013 if opts.get('rev'):
4007 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4014 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4008 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4015 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4009
4016
4010 df = False
4017 df = False
4011 if opts.get("date"):
4018 if opts.get("date"):
4012 df = util.matchdate(opts["date"])
4019 df = util.matchdate(opts["date"])
4013
4020
4014 branches = opts.get('branch', []) + opts.get('only_branch', [])
4021 branches = opts.get('branch', []) + opts.get('only_branch', [])
4015 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4022 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4016
4023
4017 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4024 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4018 def prep(ctx, fns):
4025 def prep(ctx, fns):
4019 rev = ctx.rev()
4026 rev = ctx.rev()
4020 parents = [p for p in repo.changelog.parentrevs(rev)
4027 parents = [p for p in repo.changelog.parentrevs(rev)
4021 if p != nullrev]
4028 if p != nullrev]
4022 if opts.get('no_merges') and len(parents) == 2:
4029 if opts.get('no_merges') and len(parents) == 2:
4023 return
4030 return
4024 if opts.get('only_merges') and len(parents) != 2:
4031 if opts.get('only_merges') and len(parents) != 2:
4025 return
4032 return
4026 if opts.get('branch') and ctx.branch() not in opts['branch']:
4033 if opts.get('branch') and ctx.branch() not in opts['branch']:
4027 return
4034 return
4028 if df and not df(ctx.date()[0]):
4035 if df and not df(ctx.date()[0]):
4029 return
4036 return
4030
4037
4031 lower = encoding.lower
4038 lower = encoding.lower
4032 if opts.get('user'):
4039 if opts.get('user'):
4033 luser = lower(ctx.user())
4040 luser = lower(ctx.user())
4034 for k in [lower(x) for x in opts['user']]:
4041 for k in [lower(x) for x in opts['user']]:
4035 if (k in luser):
4042 if (k in luser):
4036 break
4043 break
4037 else:
4044 else:
4038 return
4045 return
4039 if opts.get('keyword'):
4046 if opts.get('keyword'):
4040 luser = lower(ctx.user())
4047 luser = lower(ctx.user())
4041 ldesc = lower(ctx.description())
4048 ldesc = lower(ctx.description())
4042 lfiles = lower(" ".join(ctx.files()))
4049 lfiles = lower(" ".join(ctx.files()))
4043 for k in [lower(x) for x in opts['keyword']]:
4050 for k in [lower(x) for x in opts['keyword']]:
4044 if (k in luser or k in ldesc or k in lfiles):
4051 if (k in luser or k in ldesc or k in lfiles):
4045 break
4052 break
4046 else:
4053 else:
4047 return
4054 return
4048
4055
4049 copies = None
4056 copies = None
4050 if getrenamed is not None and rev:
4057 if getrenamed is not None and rev:
4051 copies = []
4058 copies = []
4052 for fn in ctx.files():
4059 for fn in ctx.files():
4053 rename = getrenamed(fn, rev)
4060 rename = getrenamed(fn, rev)
4054 if rename:
4061 if rename:
4055 copies.append((fn, rename[0]))
4062 copies.append((fn, rename[0]))
4056
4063
4057 revmatchfn = None
4064 revmatchfn = None
4058 if opts.get('patch') or opts.get('stat'):
4065 if opts.get('patch') or opts.get('stat'):
4059 if opts.get('follow') or opts.get('follow_first'):
4066 if opts.get('follow') or opts.get('follow_first'):
4060 # note: this might be wrong when following through merges
4067 # note: this might be wrong when following through merges
4061 revmatchfn = scmutil.match(repo[None], fns, default='path')
4068 revmatchfn = scmutil.match(repo[None], fns, default='path')
4062 else:
4069 else:
4063 revmatchfn = matchfn
4070 revmatchfn = matchfn
4064
4071
4065 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4072 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4066
4073
4067 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4074 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4068 if displayer.flush(ctx.rev()):
4075 if displayer.flush(ctx.rev()):
4069 count += 1
4076 count += 1
4070 if count == limit:
4077 if count == limit:
4071 break
4078 break
4072 displayer.close()
4079 displayer.close()
4073
4080
4074 @command('manifest',
4081 @command('manifest',
4075 [('r', 'rev', '', _('revision to display'), _('REV')),
4082 [('r', 'rev', '', _('revision to display'), _('REV')),
4076 ('', 'all', False, _("list files from all revisions"))],
4083 ('', 'all', False, _("list files from all revisions"))],
4077 _('[-r REV]'))
4084 _('[-r REV]'))
4078 def manifest(ui, repo, node=None, rev=None, **opts):
4085 def manifest(ui, repo, node=None, rev=None, **opts):
4079 """output the current or given revision of the project manifest
4086 """output the current or given revision of the project manifest
4080
4087
4081 Print a list of version controlled files for the given revision.
4088 Print a list of version controlled files for the given revision.
4082 If no revision is given, the first parent of the working directory
4089 If no revision is given, the first parent of the working directory
4083 is used, or the null revision if no revision is checked out.
4090 is used, or the null revision if no revision is checked out.
4084
4091
4085 With -v, print file permissions, symlink and executable bits.
4092 With -v, print file permissions, symlink and executable bits.
4086 With --debug, print file revision hashes.
4093 With --debug, print file revision hashes.
4087
4094
4088 If option --all is specified, the list of all files from all revisions
4095 If option --all is specified, the list of all files from all revisions
4089 is printed. This includes deleted and renamed files.
4096 is printed. This includes deleted and renamed files.
4090
4097
4091 Returns 0 on success.
4098 Returns 0 on success.
4092 """
4099 """
4093
4100
4094 fm = ui.formatter('manifest', opts)
4101 fm = ui.formatter('manifest', opts)
4095
4102
4096 if opts.get('all'):
4103 if opts.get('all'):
4097 if rev or node:
4104 if rev or node:
4098 raise util.Abort(_("can't specify a revision with --all"))
4105 raise util.Abort(_("can't specify a revision with --all"))
4099
4106
4100 res = []
4107 res = []
4101 prefix = "data/"
4108 prefix = "data/"
4102 suffix = ".i"
4109 suffix = ".i"
4103 plen = len(prefix)
4110 plen = len(prefix)
4104 slen = len(suffix)
4111 slen = len(suffix)
4105 lock = repo.lock()
4112 lock = repo.lock()
4106 try:
4113 try:
4107 for fn, b, size in repo.store.datafiles():
4114 for fn, b, size in repo.store.datafiles():
4108 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4115 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4109 res.append(fn[plen:-slen])
4116 res.append(fn[plen:-slen])
4110 finally:
4117 finally:
4111 lock.release()
4118 lock.release()
4112 for f in res:
4119 for f in res:
4113 fm.startitem()
4120 fm.startitem()
4114 fm.write("path", '%s\n', f)
4121 fm.write("path", '%s\n', f)
4115 fm.end()
4122 fm.end()
4116 return
4123 return
4117
4124
4118 if rev and node:
4125 if rev and node:
4119 raise util.Abort(_("please specify just one revision"))
4126 raise util.Abort(_("please specify just one revision"))
4120
4127
4121 if not node:
4128 if not node:
4122 node = rev
4129 node = rev
4123
4130
4124 char = {'l': '@', 'x': '*', '': ''}
4131 char = {'l': '@', 'x': '*', '': ''}
4125 mode = {'l': '644', 'x': '755', '': '644'}
4132 mode = {'l': '644', 'x': '755', '': '644'}
4126 ctx = scmutil.revsingle(repo, node)
4133 ctx = scmutil.revsingle(repo, node)
4127 mf = ctx.manifest()
4134 mf = ctx.manifest()
4128 for f in ctx:
4135 for f in ctx:
4129 fm.startitem()
4136 fm.startitem()
4130 fl = ctx[f].flags()
4137 fl = ctx[f].flags()
4131 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4138 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4132 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4139 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4133 fm.write('path', '%s\n', f)
4140 fm.write('path', '%s\n', f)
4134 fm.end()
4141 fm.end()
4135
4142
4136 @command('^merge',
4143 @command('^merge',
4137 [('f', 'force', None, _('force a merge with outstanding changes')),
4144 [('f', 'force', None, _('force a merge with outstanding changes')),
4138 ('r', 'rev', '', _('revision to merge'), _('REV')),
4145 ('r', 'rev', '', _('revision to merge'), _('REV')),
4139 ('P', 'preview', None,
4146 ('P', 'preview', None,
4140 _('review revisions to merge (no merge is performed)'))
4147 _('review revisions to merge (no merge is performed)'))
4141 ] + mergetoolopts,
4148 ] + mergetoolopts,
4142 _('[-P] [-f] [[-r] REV]'))
4149 _('[-P] [-f] [[-r] REV]'))
4143 def merge(ui, repo, node=None, **opts):
4150 def merge(ui, repo, node=None, **opts):
4144 """merge working directory with another revision
4151 """merge working directory with another revision
4145
4152
4146 The current working directory is updated with all changes made in
4153 The current working directory is updated with all changes made in
4147 the requested revision since the last common predecessor revision.
4154 the requested revision since the last common predecessor revision.
4148
4155
4149 Files that changed between either parent are marked as changed for
4156 Files that changed between either parent are marked as changed for
4150 the next commit and a commit must be performed before any further
4157 the next commit and a commit must be performed before any further
4151 updates to the repository are allowed. The next commit will have
4158 updates to the repository are allowed. The next commit will have
4152 two parents.
4159 two parents.
4153
4160
4154 ``--tool`` can be used to specify the merge tool used for file
4161 ``--tool`` can be used to specify the merge tool used for file
4155 merges. It overrides the HGMERGE environment variable and your
4162 merges. It overrides the HGMERGE environment variable and your
4156 configuration files. See :hg:`help merge-tools` for options.
4163 configuration files. See :hg:`help merge-tools` for options.
4157
4164
4158 If no revision is specified, the working directory's parent is a
4165 If no revision is specified, the working directory's parent is a
4159 head revision, and the current branch contains exactly one other
4166 head revision, and the current branch contains exactly one other
4160 head, the other head is merged with by default. Otherwise, an
4167 head, the other head is merged with by default. Otherwise, an
4161 explicit revision with which to merge with must be provided.
4168 explicit revision with which to merge with must be provided.
4162
4169
4163 :hg:`resolve` must be used to resolve unresolved files.
4170 :hg:`resolve` must be used to resolve unresolved files.
4164
4171
4165 To undo an uncommitted merge, use :hg:`update --clean .` which
4172 To undo an uncommitted merge, use :hg:`update --clean .` which
4166 will check out a clean copy of the original merge parent, losing
4173 will check out a clean copy of the original merge parent, losing
4167 all changes.
4174 all changes.
4168
4175
4169 Returns 0 on success, 1 if there are unresolved files.
4176 Returns 0 on success, 1 if there are unresolved files.
4170 """
4177 """
4171
4178
4172 if opts.get('rev') and node:
4179 if opts.get('rev') and node:
4173 raise util.Abort(_("please specify just one revision"))
4180 raise util.Abort(_("please specify just one revision"))
4174 if not node:
4181 if not node:
4175 node = opts.get('rev')
4182 node = opts.get('rev')
4176
4183
4177 if node:
4184 if node:
4178 node = scmutil.revsingle(repo, node).node()
4185 node = scmutil.revsingle(repo, node).node()
4179
4186
4180 if not node and repo._bookmarkcurrent:
4187 if not node and repo._bookmarkcurrent:
4181 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4188 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4182 curhead = repo[repo._bookmarkcurrent].node()
4189 curhead = repo[repo._bookmarkcurrent].node()
4183 if len(bmheads) == 2:
4190 if len(bmheads) == 2:
4184 if curhead == bmheads[0]:
4191 if curhead == bmheads[0]:
4185 node = bmheads[1]
4192 node = bmheads[1]
4186 else:
4193 else:
4187 node = bmheads[0]
4194 node = bmheads[0]
4188 elif len(bmheads) > 2:
4195 elif len(bmheads) > 2:
4189 raise util.Abort(_("multiple matching bookmarks to merge - "
4196 raise util.Abort(_("multiple matching bookmarks to merge - "
4190 "please merge with an explicit rev or bookmark"),
4197 "please merge with an explicit rev or bookmark"),
4191 hint=_("run 'hg heads' to see all heads"))
4198 hint=_("run 'hg heads' to see all heads"))
4192 elif len(bmheads) <= 1:
4199 elif len(bmheads) <= 1:
4193 raise util.Abort(_("no matching bookmark to merge - "
4200 raise util.Abort(_("no matching bookmark to merge - "
4194 "please merge with an explicit rev or bookmark"),
4201 "please merge with an explicit rev or bookmark"),
4195 hint=_("run 'hg heads' to see all heads"))
4202 hint=_("run 'hg heads' to see all heads"))
4196
4203
4197 if not node and not repo._bookmarkcurrent:
4204 if not node and not repo._bookmarkcurrent:
4198 branch = repo[None].branch()
4205 branch = repo[None].branch()
4199 bheads = repo.branchheads(branch)
4206 bheads = repo.branchheads(branch)
4200 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4207 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4201
4208
4202 if len(nbhs) > 2:
4209 if len(nbhs) > 2:
4203 raise util.Abort(_("branch '%s' has %d heads - "
4210 raise util.Abort(_("branch '%s' has %d heads - "
4204 "please merge with an explicit rev")
4211 "please merge with an explicit rev")
4205 % (branch, len(bheads)),
4212 % (branch, len(bheads)),
4206 hint=_("run 'hg heads .' to see heads"))
4213 hint=_("run 'hg heads .' to see heads"))
4207
4214
4208 parent = repo.dirstate.p1()
4215 parent = repo.dirstate.p1()
4209 if len(nbhs) <= 1:
4216 if len(nbhs) <= 1:
4210 if len(bheads) > 1:
4217 if len(bheads) > 1:
4211 raise util.Abort(_("heads are bookmarked - "
4218 raise util.Abort(_("heads are bookmarked - "
4212 "please merge with an explicit rev"),
4219 "please merge with an explicit rev"),
4213 hint=_("run 'hg heads' to see all heads"))
4220 hint=_("run 'hg heads' to see all heads"))
4214 if len(repo.heads()) > 1:
4221 if len(repo.heads()) > 1:
4215 raise util.Abort(_("branch '%s' has one head - "
4222 raise util.Abort(_("branch '%s' has one head - "
4216 "please merge with an explicit rev")
4223 "please merge with an explicit rev")
4217 % branch,
4224 % branch,
4218 hint=_("run 'hg heads' to see all heads"))
4225 hint=_("run 'hg heads' to see all heads"))
4219 msg, hint = _('nothing to merge'), None
4226 msg, hint = _('nothing to merge'), None
4220 if parent != repo.lookup(branch):
4227 if parent != repo.lookup(branch):
4221 hint = _("use 'hg update' instead")
4228 hint = _("use 'hg update' instead")
4222 raise util.Abort(msg, hint=hint)
4229 raise util.Abort(msg, hint=hint)
4223
4230
4224 if parent not in bheads:
4231 if parent not in bheads:
4225 raise util.Abort(_('working directory not at a head revision'),
4232 raise util.Abort(_('working directory not at a head revision'),
4226 hint=_("use 'hg update' or merge with an "
4233 hint=_("use 'hg update' or merge with an "
4227 "explicit revision"))
4234 "explicit revision"))
4228 if parent == nbhs[0]:
4235 if parent == nbhs[0]:
4229 node = nbhs[-1]
4236 node = nbhs[-1]
4230 else:
4237 else:
4231 node = nbhs[0]
4238 node = nbhs[0]
4232
4239
4233 if opts.get('preview'):
4240 if opts.get('preview'):
4234 # find nodes that are ancestors of p2 but not of p1
4241 # find nodes that are ancestors of p2 but not of p1
4235 p1 = repo.lookup('.')
4242 p1 = repo.lookup('.')
4236 p2 = repo.lookup(node)
4243 p2 = repo.lookup(node)
4237 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4244 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4238
4245
4239 displayer = cmdutil.show_changeset(ui, repo, opts)
4246 displayer = cmdutil.show_changeset(ui, repo, opts)
4240 for node in nodes:
4247 for node in nodes:
4241 displayer.show(repo[node])
4248 displayer.show(repo[node])
4242 displayer.close()
4249 displayer.close()
4243 return 0
4250 return 0
4244
4251
4245 try:
4252 try:
4246 # ui.forcemerge is an internal variable, do not document
4253 # ui.forcemerge is an internal variable, do not document
4247 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4254 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4248 return hg.merge(repo, node, force=opts.get('force'))
4255 return hg.merge(repo, node, force=opts.get('force'))
4249 finally:
4256 finally:
4250 ui.setconfig('ui', 'forcemerge', '')
4257 ui.setconfig('ui', 'forcemerge', '')
4251
4258
4252 @command('outgoing|out',
4259 @command('outgoing|out',
4253 [('f', 'force', None, _('run even when the destination is unrelated')),
4260 [('f', 'force', None, _('run even when the destination is unrelated')),
4254 ('r', 'rev', [],
4261 ('r', 'rev', [],
4255 _('a changeset intended to be included in the destination'), _('REV')),
4262 _('a changeset intended to be included in the destination'), _('REV')),
4256 ('n', 'newest-first', None, _('show newest record first')),
4263 ('n', 'newest-first', None, _('show newest record first')),
4257 ('B', 'bookmarks', False, _('compare bookmarks')),
4264 ('B', 'bookmarks', False, _('compare bookmarks')),
4258 ('b', 'branch', [], _('a specific branch you would like to push'),
4265 ('b', 'branch', [], _('a specific branch you would like to push'),
4259 _('BRANCH')),
4266 _('BRANCH')),
4260 ] + logopts + remoteopts + subrepoopts,
4267 ] + logopts + remoteopts + subrepoopts,
4261 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4268 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4262 def outgoing(ui, repo, dest=None, **opts):
4269 def outgoing(ui, repo, dest=None, **opts):
4263 """show changesets not found in the destination
4270 """show changesets not found in the destination
4264
4271
4265 Show changesets not found in the specified destination repository
4272 Show changesets not found in the specified destination repository
4266 or the default push location. These are the changesets that would
4273 or the default push location. These are the changesets that would
4267 be pushed if a push was requested.
4274 be pushed if a push was requested.
4268
4275
4269 See pull for details of valid destination formats.
4276 See pull for details of valid destination formats.
4270
4277
4271 Returns 0 if there are outgoing changes, 1 otherwise.
4278 Returns 0 if there are outgoing changes, 1 otherwise.
4272 """
4279 """
4273 if opts.get('graph'):
4280 if opts.get('graph'):
4274 cmdutil.checkunsupportedgraphflags([], opts)
4281 cmdutil.checkunsupportedgraphflags([], opts)
4275 o = hg._outgoing(ui, repo, dest, opts)
4282 o = hg._outgoing(ui, repo, dest, opts)
4276 if o is None:
4283 if o is None:
4277 return
4284 return
4278
4285
4279 revdag = cmdutil.graphrevs(repo, o, opts)
4286 revdag = cmdutil.graphrevs(repo, o, opts)
4280 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4287 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4281 showparents = [ctx.node() for ctx in repo[None].parents()]
4288 showparents = [ctx.node() for ctx in repo[None].parents()]
4282 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4289 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4283 graphmod.asciiedges)
4290 graphmod.asciiedges)
4284 return 0
4291 return 0
4285
4292
4286 if opts.get('bookmarks'):
4293 if opts.get('bookmarks'):
4287 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4294 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4288 dest, branches = hg.parseurl(dest, opts.get('branch'))
4295 dest, branches = hg.parseurl(dest, opts.get('branch'))
4289 other = hg.peer(repo, opts, dest)
4296 other = hg.peer(repo, opts, dest)
4290 if 'bookmarks' not in other.listkeys('namespaces'):
4297 if 'bookmarks' not in other.listkeys('namespaces'):
4291 ui.warn(_("remote doesn't support bookmarks\n"))
4298 ui.warn(_("remote doesn't support bookmarks\n"))
4292 return 0
4299 return 0
4293 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4300 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4294 return bookmarks.diff(ui, other, repo)
4301 return bookmarks.diff(ui, other, repo)
4295
4302
4296 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4303 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4297 try:
4304 try:
4298 return hg.outgoing(ui, repo, dest, opts)
4305 return hg.outgoing(ui, repo, dest, opts)
4299 finally:
4306 finally:
4300 del repo._subtoppath
4307 del repo._subtoppath
4301
4308
4302 @command('parents',
4309 @command('parents',
4303 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4310 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4304 ] + templateopts,
4311 ] + templateopts,
4305 _('[-r REV] [FILE]'))
4312 _('[-r REV] [FILE]'))
4306 def parents(ui, repo, file_=None, **opts):
4313 def parents(ui, repo, file_=None, **opts):
4307 """show the parents of the working directory or revision
4314 """show the parents of the working directory or revision
4308
4315
4309 Print the working directory's parent revisions. If a revision is
4316 Print the working directory's parent revisions. If a revision is
4310 given via -r/--rev, the parent of that revision will be printed.
4317 given via -r/--rev, the parent of that revision will be printed.
4311 If a file argument is given, the revision in which the file was
4318 If a file argument is given, the revision in which the file was
4312 last changed (before the working directory revision or the
4319 last changed (before the working directory revision or the
4313 argument to --rev if given) is printed.
4320 argument to --rev if given) is printed.
4314
4321
4315 Returns 0 on success.
4322 Returns 0 on success.
4316 """
4323 """
4317
4324
4318 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4325 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4319
4326
4320 if file_:
4327 if file_:
4321 m = scmutil.match(ctx, (file_,), opts)
4328 m = scmutil.match(ctx, (file_,), opts)
4322 if m.anypats() or len(m.files()) != 1:
4329 if m.anypats() or len(m.files()) != 1:
4323 raise util.Abort(_('can only specify an explicit filename'))
4330 raise util.Abort(_('can only specify an explicit filename'))
4324 file_ = m.files()[0]
4331 file_ = m.files()[0]
4325 filenodes = []
4332 filenodes = []
4326 for cp in ctx.parents():
4333 for cp in ctx.parents():
4327 if not cp:
4334 if not cp:
4328 continue
4335 continue
4329 try:
4336 try:
4330 filenodes.append(cp.filenode(file_))
4337 filenodes.append(cp.filenode(file_))
4331 except error.LookupError:
4338 except error.LookupError:
4332 pass
4339 pass
4333 if not filenodes:
4340 if not filenodes:
4334 raise util.Abort(_("'%s' not found in manifest!") % file_)
4341 raise util.Abort(_("'%s' not found in manifest!") % file_)
4335 fl = repo.file(file_)
4342 fl = repo.file(file_)
4336 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4343 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4337 else:
4344 else:
4338 p = [cp.node() for cp in ctx.parents()]
4345 p = [cp.node() for cp in ctx.parents()]
4339
4346
4340 displayer = cmdutil.show_changeset(ui, repo, opts)
4347 displayer = cmdutil.show_changeset(ui, repo, opts)
4341 for n in p:
4348 for n in p:
4342 if n != nullid:
4349 if n != nullid:
4343 displayer.show(repo[n])
4350 displayer.show(repo[n])
4344 displayer.close()
4351 displayer.close()
4345
4352
4346 @command('paths', [], _('[NAME]'))
4353 @command('paths', [], _('[NAME]'))
4347 def paths(ui, repo, search=None):
4354 def paths(ui, repo, search=None):
4348 """show aliases for remote repositories
4355 """show aliases for remote repositories
4349
4356
4350 Show definition of symbolic path name NAME. If no name is given,
4357 Show definition of symbolic path name NAME. If no name is given,
4351 show definition of all available names.
4358 show definition of all available names.
4352
4359
4353 Option -q/--quiet suppresses all output when searching for NAME
4360 Option -q/--quiet suppresses all output when searching for NAME
4354 and shows only the path names when listing all definitions.
4361 and shows only the path names when listing all definitions.
4355
4362
4356 Path names are defined in the [paths] section of your
4363 Path names are defined in the [paths] section of your
4357 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4364 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4358 repository, ``.hg/hgrc`` is used, too.
4365 repository, ``.hg/hgrc`` is used, too.
4359
4366
4360 The path names ``default`` and ``default-push`` have a special
4367 The path names ``default`` and ``default-push`` have a special
4361 meaning. When performing a push or pull operation, they are used
4368 meaning. When performing a push or pull operation, they are used
4362 as fallbacks if no location is specified on the command-line.
4369 as fallbacks if no location is specified on the command-line.
4363 When ``default-push`` is set, it will be used for push and
4370 When ``default-push`` is set, it will be used for push and
4364 ``default`` will be used for pull; otherwise ``default`` is used
4371 ``default`` will be used for pull; otherwise ``default`` is used
4365 as the fallback for both. When cloning a repository, the clone
4372 as the fallback for both. When cloning a repository, the clone
4366 source is written as ``default`` in ``.hg/hgrc``. Note that
4373 source is written as ``default`` in ``.hg/hgrc``. Note that
4367 ``default`` and ``default-push`` apply to all inbound (e.g.
4374 ``default`` and ``default-push`` apply to all inbound (e.g.
4368 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4375 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4369 :hg:`bundle`) operations.
4376 :hg:`bundle`) operations.
4370
4377
4371 See :hg:`help urls` for more information.
4378 See :hg:`help urls` for more information.
4372
4379
4373 Returns 0 on success.
4380 Returns 0 on success.
4374 """
4381 """
4375 if search:
4382 if search:
4376 for name, path in ui.configitems("paths"):
4383 for name, path in ui.configitems("paths"):
4377 if name == search:
4384 if name == search:
4378 ui.status("%s\n" % util.hidepassword(path))
4385 ui.status("%s\n" % util.hidepassword(path))
4379 return
4386 return
4380 if not ui.quiet:
4387 if not ui.quiet:
4381 ui.warn(_("not found!\n"))
4388 ui.warn(_("not found!\n"))
4382 return 1
4389 return 1
4383 else:
4390 else:
4384 for name, path in ui.configitems("paths"):
4391 for name, path in ui.configitems("paths"):
4385 if ui.quiet:
4392 if ui.quiet:
4386 ui.write("%s\n" % name)
4393 ui.write("%s\n" % name)
4387 else:
4394 else:
4388 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4395 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4389
4396
4390 @command('phase',
4397 @command('phase',
4391 [('p', 'public', False, _('set changeset phase to public')),
4398 [('p', 'public', False, _('set changeset phase to public')),
4392 ('d', 'draft', False, _('set changeset phase to draft')),
4399 ('d', 'draft', False, _('set changeset phase to draft')),
4393 ('s', 'secret', False, _('set changeset phase to secret')),
4400 ('s', 'secret', False, _('set changeset phase to secret')),
4394 ('f', 'force', False, _('allow to move boundary backward')),
4401 ('f', 'force', False, _('allow to move boundary backward')),
4395 ('r', 'rev', [], _('target revision'), _('REV')),
4402 ('r', 'rev', [], _('target revision'), _('REV')),
4396 ],
4403 ],
4397 _('[-p|-d|-s] [-f] [-r] REV...'))
4404 _('[-p|-d|-s] [-f] [-r] REV...'))
4398 def phase(ui, repo, *revs, **opts):
4405 def phase(ui, repo, *revs, **opts):
4399 """set or show the current phase name
4406 """set or show the current phase name
4400
4407
4401 With no argument, show the phase name of specified revisions.
4408 With no argument, show the phase name of specified revisions.
4402
4409
4403 With one of -p/--public, -d/--draft or -s/--secret, change the
4410 With one of -p/--public, -d/--draft or -s/--secret, change the
4404 phase value of the specified revisions.
4411 phase value of the specified revisions.
4405
4412
4406 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4413 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4407 lower phase to an higher phase. Phases are ordered as follows::
4414 lower phase to an higher phase. Phases are ordered as follows::
4408
4415
4409 public < draft < secret
4416 public < draft < secret
4410
4417
4411 Return 0 on success, 1 if no phases were changed or some could not
4418 Return 0 on success, 1 if no phases were changed or some could not
4412 be changed.
4419 be changed.
4413 """
4420 """
4414 # search for a unique phase argument
4421 # search for a unique phase argument
4415 targetphase = None
4422 targetphase = None
4416 for idx, name in enumerate(phases.phasenames):
4423 for idx, name in enumerate(phases.phasenames):
4417 if opts[name]:
4424 if opts[name]:
4418 if targetphase is not None:
4425 if targetphase is not None:
4419 raise util.Abort(_('only one phase can be specified'))
4426 raise util.Abort(_('only one phase can be specified'))
4420 targetphase = idx
4427 targetphase = idx
4421
4428
4422 # look for specified revision
4429 # look for specified revision
4423 revs = list(revs)
4430 revs = list(revs)
4424 revs.extend(opts['rev'])
4431 revs.extend(opts['rev'])
4425 if not revs:
4432 if not revs:
4426 raise util.Abort(_('no revisions specified'))
4433 raise util.Abort(_('no revisions specified'))
4427
4434
4428 revs = scmutil.revrange(repo, revs)
4435 revs = scmutil.revrange(repo, revs)
4429
4436
4430 lock = None
4437 lock = None
4431 ret = 0
4438 ret = 0
4432 if targetphase is None:
4439 if targetphase is None:
4433 # display
4440 # display
4434 for r in revs:
4441 for r in revs:
4435 ctx = repo[r]
4442 ctx = repo[r]
4436 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4443 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4437 else:
4444 else:
4438 lock = repo.lock()
4445 lock = repo.lock()
4439 try:
4446 try:
4440 # set phase
4447 # set phase
4441 if not revs:
4448 if not revs:
4442 raise util.Abort(_('empty revision set'))
4449 raise util.Abort(_('empty revision set'))
4443 nodes = [repo[r].node() for r in revs]
4450 nodes = [repo[r].node() for r in revs]
4444 olddata = repo._phasecache.getphaserevs(repo)[:]
4451 olddata = repo._phasecache.getphaserevs(repo)[:]
4445 phases.advanceboundary(repo, targetphase, nodes)
4452 phases.advanceboundary(repo, targetphase, nodes)
4446 if opts['force']:
4453 if opts['force']:
4447 phases.retractboundary(repo, targetphase, nodes)
4454 phases.retractboundary(repo, targetphase, nodes)
4448 finally:
4455 finally:
4449 lock.release()
4456 lock.release()
4450 # moving revision from public to draft may hide them
4457 # moving revision from public to draft may hide them
4451 # We have to check result on an unfiltered repository
4458 # We have to check result on an unfiltered repository
4452 unfi = repo.unfiltered()
4459 unfi = repo.unfiltered()
4453 newdata = repo._phasecache.getphaserevs(unfi)
4460 newdata = repo._phasecache.getphaserevs(unfi)
4454 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4461 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4455 cl = unfi.changelog
4462 cl = unfi.changelog
4456 rejected = [n for n in nodes
4463 rejected = [n for n in nodes
4457 if newdata[cl.rev(n)] < targetphase]
4464 if newdata[cl.rev(n)] < targetphase]
4458 if rejected:
4465 if rejected:
4459 ui.warn(_('cannot move %i changesets to a more permissive '
4466 ui.warn(_('cannot move %i changesets to a more permissive '
4460 'phase, use --force\n') % len(rejected))
4467 'phase, use --force\n') % len(rejected))
4461 ret = 1
4468 ret = 1
4462 if changes:
4469 if changes:
4463 msg = _('phase changed for %i changesets\n') % changes
4470 msg = _('phase changed for %i changesets\n') % changes
4464 if ret:
4471 if ret:
4465 ui.status(msg)
4472 ui.status(msg)
4466 else:
4473 else:
4467 ui.note(msg)
4474 ui.note(msg)
4468 else:
4475 else:
4469 ui.warn(_('no phases changed\n'))
4476 ui.warn(_('no phases changed\n'))
4470 ret = 1
4477 ret = 1
4471 return ret
4478 return ret
4472
4479
4473 def postincoming(ui, repo, modheads, optupdate, checkout):
4480 def postincoming(ui, repo, modheads, optupdate, checkout):
4474 if modheads == 0:
4481 if modheads == 0:
4475 return
4482 return
4476 if optupdate:
4483 if optupdate:
4477 movemarkfrom = repo['.'].node()
4484 movemarkfrom = repo['.'].node()
4478 try:
4485 try:
4479 ret = hg.update(repo, checkout)
4486 ret = hg.update(repo, checkout)
4480 except util.Abort, inst:
4487 except util.Abort, inst:
4481 ui.warn(_("not updating: %s\n") % str(inst))
4488 ui.warn(_("not updating: %s\n") % str(inst))
4482 return 0
4489 return 0
4483 if not ret and not checkout:
4490 if not ret and not checkout:
4484 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4491 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4485 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4492 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4486 return ret
4493 return ret
4487 if modheads > 1:
4494 if modheads > 1:
4488 currentbranchheads = len(repo.branchheads())
4495 currentbranchheads = len(repo.branchheads())
4489 if currentbranchheads == modheads:
4496 if currentbranchheads == modheads:
4490 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4497 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4491 elif currentbranchheads > 1:
4498 elif currentbranchheads > 1:
4492 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4499 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4493 "merge)\n"))
4500 "merge)\n"))
4494 else:
4501 else:
4495 ui.status(_("(run 'hg heads' to see heads)\n"))
4502 ui.status(_("(run 'hg heads' to see heads)\n"))
4496 else:
4503 else:
4497 ui.status(_("(run 'hg update' to get a working copy)\n"))
4504 ui.status(_("(run 'hg update' to get a working copy)\n"))
4498
4505
4499 @command('^pull',
4506 @command('^pull',
4500 [('u', 'update', None,
4507 [('u', 'update', None,
4501 _('update to new branch head if changesets were pulled')),
4508 _('update to new branch head if changesets were pulled')),
4502 ('f', 'force', None, _('run even when remote repository is unrelated')),
4509 ('f', 'force', None, _('run even when remote repository is unrelated')),
4503 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4510 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4504 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4511 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4505 ('b', 'branch', [], _('a specific branch you would like to pull'),
4512 ('b', 'branch', [], _('a specific branch you would like to pull'),
4506 _('BRANCH')),
4513 _('BRANCH')),
4507 ] + remoteopts,
4514 ] + remoteopts,
4508 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4515 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4509 def pull(ui, repo, source="default", **opts):
4516 def pull(ui, repo, source="default", **opts):
4510 """pull changes from the specified source
4517 """pull changes from the specified source
4511
4518
4512 Pull changes from a remote repository to a local one.
4519 Pull changes from a remote repository to a local one.
4513
4520
4514 This finds all changes from the repository at the specified path
4521 This finds all changes from the repository at the specified path
4515 or URL and adds them to a local repository (the current one unless
4522 or URL and adds them to a local repository (the current one unless
4516 -R is specified). By default, this does not update the copy of the
4523 -R is specified). By default, this does not update the copy of the
4517 project in the working directory.
4524 project in the working directory.
4518
4525
4519 Use :hg:`incoming` if you want to see what would have been added
4526 Use :hg:`incoming` if you want to see what would have been added
4520 by a pull at the time you issued this command. If you then decide
4527 by a pull at the time you issued this command. If you then decide
4521 to add those changes to the repository, you should use :hg:`pull
4528 to add those changes to the repository, you should use :hg:`pull
4522 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4529 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4523
4530
4524 If SOURCE is omitted, the 'default' path will be used.
4531 If SOURCE is omitted, the 'default' path will be used.
4525 See :hg:`help urls` for more information.
4532 See :hg:`help urls` for more information.
4526
4533
4527 Returns 0 on success, 1 if an update had unresolved files.
4534 Returns 0 on success, 1 if an update had unresolved files.
4528 """
4535 """
4529 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4536 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4530 other = hg.peer(repo, opts, source)
4537 other = hg.peer(repo, opts, source)
4531 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4538 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4532 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4539 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4533
4540
4534 remotebookmarks = other.listkeys('bookmarks')
4541 remotebookmarks = other.listkeys('bookmarks')
4535
4542
4536 if opts.get('bookmark'):
4543 if opts.get('bookmark'):
4537 if not revs:
4544 if not revs:
4538 revs = []
4545 revs = []
4539 for b in opts['bookmark']:
4546 for b in opts['bookmark']:
4540 if b not in remotebookmarks:
4547 if b not in remotebookmarks:
4541 raise util.Abort(_('remote bookmark %s not found!') % b)
4548 raise util.Abort(_('remote bookmark %s not found!') % b)
4542 revs.append(remotebookmarks[b])
4549 revs.append(remotebookmarks[b])
4543
4550
4544 if revs:
4551 if revs:
4545 try:
4552 try:
4546 revs = [other.lookup(rev) for rev in revs]
4553 revs = [other.lookup(rev) for rev in revs]
4547 except error.CapabilityError:
4554 except error.CapabilityError:
4548 err = _("other repository doesn't support revision lookup, "
4555 err = _("other repository doesn't support revision lookup, "
4549 "so a rev cannot be specified.")
4556 "so a rev cannot be specified.")
4550 raise util.Abort(err)
4557 raise util.Abort(err)
4551
4558
4552 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4559 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4553 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4560 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4554 if checkout:
4561 if checkout:
4555 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4562 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4556 repo._subtoppath = source
4563 repo._subtoppath = source
4557 try:
4564 try:
4558 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4565 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4559
4566
4560 finally:
4567 finally:
4561 del repo._subtoppath
4568 del repo._subtoppath
4562
4569
4563 # update specified bookmarks
4570 # update specified bookmarks
4564 if opts.get('bookmark'):
4571 if opts.get('bookmark'):
4565 marks = repo._bookmarks
4572 marks = repo._bookmarks
4566 for b in opts['bookmark']:
4573 for b in opts['bookmark']:
4567 # explicit pull overrides local bookmark if any
4574 # explicit pull overrides local bookmark if any
4568 ui.status(_("importing bookmark %s\n") % b)
4575 ui.status(_("importing bookmark %s\n") % b)
4569 marks[b] = repo[remotebookmarks[b]].node()
4576 marks[b] = repo[remotebookmarks[b]].node()
4570 marks.write()
4577 marks.write()
4571
4578
4572 return ret
4579 return ret
4573
4580
4574 @command('^push',
4581 @command('^push',
4575 [('f', 'force', None, _('force push')),
4582 [('f', 'force', None, _('force push')),
4576 ('r', 'rev', [],
4583 ('r', 'rev', [],
4577 _('a changeset intended to be included in the destination'),
4584 _('a changeset intended to be included in the destination'),
4578 _('REV')),
4585 _('REV')),
4579 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4586 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4580 ('b', 'branch', [],
4587 ('b', 'branch', [],
4581 _('a specific branch you would like to push'), _('BRANCH')),
4588 _('a specific branch you would like to push'), _('BRANCH')),
4582 ('', 'new-branch', False, _('allow pushing a new branch')),
4589 ('', 'new-branch', False, _('allow pushing a new branch')),
4583 ] + remoteopts,
4590 ] + remoteopts,
4584 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4591 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4585 def push(ui, repo, dest=None, **opts):
4592 def push(ui, repo, dest=None, **opts):
4586 """push changes to the specified destination
4593 """push changes to the specified destination
4587
4594
4588 Push changesets from the local repository to the specified
4595 Push changesets from the local repository to the specified
4589 destination.
4596 destination.
4590
4597
4591 This operation is symmetrical to pull: it is identical to a pull
4598 This operation is symmetrical to pull: it is identical to a pull
4592 in the destination repository from the current one.
4599 in the destination repository from the current one.
4593
4600
4594 By default, push will not allow creation of new heads at the
4601 By default, push will not allow creation of new heads at the
4595 destination, since multiple heads would make it unclear which head
4602 destination, since multiple heads would make it unclear which head
4596 to use. In this situation, it is recommended to pull and merge
4603 to use. In this situation, it is recommended to pull and merge
4597 before pushing.
4604 before pushing.
4598
4605
4599 Use --new-branch if you want to allow push to create a new named
4606 Use --new-branch if you want to allow push to create a new named
4600 branch that is not present at the destination. This allows you to
4607 branch that is not present at the destination. This allows you to
4601 only create a new branch without forcing other changes.
4608 only create a new branch without forcing other changes.
4602
4609
4603 Use -f/--force to override the default behavior and push all
4610 Use -f/--force to override the default behavior and push all
4604 changesets on all branches.
4611 changesets on all branches.
4605
4612
4606 If -r/--rev is used, the specified revision and all its ancestors
4613 If -r/--rev is used, the specified revision and all its ancestors
4607 will be pushed to the remote repository.
4614 will be pushed to the remote repository.
4608
4615
4609 If -B/--bookmark is used, the specified bookmarked revision, its
4616 If -B/--bookmark is used, the specified bookmarked revision, its
4610 ancestors, and the bookmark will be pushed to the remote
4617 ancestors, and the bookmark will be pushed to the remote
4611 repository.
4618 repository.
4612
4619
4613 Please see :hg:`help urls` for important details about ``ssh://``
4620 Please see :hg:`help urls` for important details about ``ssh://``
4614 URLs. If DESTINATION is omitted, a default path will be used.
4621 URLs. If DESTINATION is omitted, a default path will be used.
4615
4622
4616 Returns 0 if push was successful, 1 if nothing to push.
4623 Returns 0 if push was successful, 1 if nothing to push.
4617 """
4624 """
4618
4625
4619 if opts.get('bookmark'):
4626 if opts.get('bookmark'):
4620 for b in opts['bookmark']:
4627 for b in opts['bookmark']:
4621 # translate -B options to -r so changesets get pushed
4628 # translate -B options to -r so changesets get pushed
4622 if b in repo._bookmarks:
4629 if b in repo._bookmarks:
4623 opts.setdefault('rev', []).append(b)
4630 opts.setdefault('rev', []).append(b)
4624 else:
4631 else:
4625 # if we try to push a deleted bookmark, translate it to null
4632 # if we try to push a deleted bookmark, translate it to null
4626 # this lets simultaneous -r, -b options continue working
4633 # this lets simultaneous -r, -b options continue working
4627 opts.setdefault('rev', []).append("null")
4634 opts.setdefault('rev', []).append("null")
4628
4635
4629 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4636 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4630 dest, branches = hg.parseurl(dest, opts.get('branch'))
4637 dest, branches = hg.parseurl(dest, opts.get('branch'))
4631 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4638 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4632 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4639 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4633 other = hg.peer(repo, opts, dest)
4640 other = hg.peer(repo, opts, dest)
4634 if revs:
4641 if revs:
4635 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4642 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4636
4643
4637 repo._subtoppath = dest
4644 repo._subtoppath = dest
4638 try:
4645 try:
4639 # push subrepos depth-first for coherent ordering
4646 # push subrepos depth-first for coherent ordering
4640 c = repo['']
4647 c = repo['']
4641 subs = c.substate # only repos that are committed
4648 subs = c.substate # only repos that are committed
4642 for s in sorted(subs):
4649 for s in sorted(subs):
4643 if c.sub(s).push(opts) == 0:
4650 if c.sub(s).push(opts) == 0:
4644 return False
4651 return False
4645 finally:
4652 finally:
4646 del repo._subtoppath
4653 del repo._subtoppath
4647 result = repo.push(other, opts.get('force'), revs=revs,
4654 result = repo.push(other, opts.get('force'), revs=revs,
4648 newbranch=opts.get('new_branch'))
4655 newbranch=opts.get('new_branch'))
4649
4656
4650 result = not result
4657 result = not result
4651
4658
4652 if opts.get('bookmark'):
4659 if opts.get('bookmark'):
4653 rb = other.listkeys('bookmarks')
4660 rb = other.listkeys('bookmarks')
4654 for b in opts['bookmark']:
4661 for b in opts['bookmark']:
4655 # explicit push overrides remote bookmark if any
4662 # explicit push overrides remote bookmark if any
4656 if b in repo._bookmarks:
4663 if b in repo._bookmarks:
4657 ui.status(_("exporting bookmark %s\n") % b)
4664 ui.status(_("exporting bookmark %s\n") % b)
4658 new = repo[b].hex()
4665 new = repo[b].hex()
4659 elif b in rb:
4666 elif b in rb:
4660 ui.status(_("deleting remote bookmark %s\n") % b)
4667 ui.status(_("deleting remote bookmark %s\n") % b)
4661 new = '' # delete
4668 new = '' # delete
4662 else:
4669 else:
4663 ui.warn(_('bookmark %s does not exist on the local '
4670 ui.warn(_('bookmark %s does not exist on the local '
4664 'or remote repository!\n') % b)
4671 'or remote repository!\n') % b)
4665 return 2
4672 return 2
4666 old = rb.get(b, '')
4673 old = rb.get(b, '')
4667 r = other.pushkey('bookmarks', b, old, new)
4674 r = other.pushkey('bookmarks', b, old, new)
4668 if not r:
4675 if not r:
4669 ui.warn(_('updating bookmark %s failed!\n') % b)
4676 ui.warn(_('updating bookmark %s failed!\n') % b)
4670 if not result:
4677 if not result:
4671 result = 2
4678 result = 2
4672
4679
4673 return result
4680 return result
4674
4681
4675 @command('recover', [])
4682 @command('recover', [])
4676 def recover(ui, repo):
4683 def recover(ui, repo):
4677 """roll back an interrupted transaction
4684 """roll back an interrupted transaction
4678
4685
4679 Recover from an interrupted commit or pull.
4686 Recover from an interrupted commit or pull.
4680
4687
4681 This command tries to fix the repository status after an
4688 This command tries to fix the repository status after an
4682 interrupted operation. It should only be necessary when Mercurial
4689 interrupted operation. It should only be necessary when Mercurial
4683 suggests it.
4690 suggests it.
4684
4691
4685 Returns 0 if successful, 1 if nothing to recover or verify fails.
4692 Returns 0 if successful, 1 if nothing to recover or verify fails.
4686 """
4693 """
4687 if repo.recover():
4694 if repo.recover():
4688 return hg.verify(repo)
4695 return hg.verify(repo)
4689 return 1
4696 return 1
4690
4697
4691 @command('^remove|rm',
4698 @command('^remove|rm',
4692 [('A', 'after', None, _('record delete for missing files')),
4699 [('A', 'after', None, _('record delete for missing files')),
4693 ('f', 'force', None,
4700 ('f', 'force', None,
4694 _('remove (and delete) file even if added or modified')),
4701 _('remove (and delete) file even if added or modified')),
4695 ] + walkopts,
4702 ] + walkopts,
4696 _('[OPTION]... FILE...'))
4703 _('[OPTION]... FILE...'))
4697 def remove(ui, repo, *pats, **opts):
4704 def remove(ui, repo, *pats, **opts):
4698 """remove the specified files on the next commit
4705 """remove the specified files on the next commit
4699
4706
4700 Schedule the indicated files for removal from the current branch.
4707 Schedule the indicated files for removal from the current branch.
4701
4708
4702 This command schedules the files to be removed at the next commit.
4709 This command schedules the files to be removed at the next commit.
4703 To undo a remove before that, see :hg:`revert`. To undo added
4710 To undo a remove before that, see :hg:`revert`. To undo added
4704 files, see :hg:`forget`.
4711 files, see :hg:`forget`.
4705
4712
4706 .. container:: verbose
4713 .. container:: verbose
4707
4714
4708 -A/--after can be used to remove only files that have already
4715 -A/--after can be used to remove only files that have already
4709 been deleted, -f/--force can be used to force deletion, and -Af
4716 been deleted, -f/--force can be used to force deletion, and -Af
4710 can be used to remove files from the next revision without
4717 can be used to remove files from the next revision without
4711 deleting them from the working directory.
4718 deleting them from the working directory.
4712
4719
4713 The following table details the behavior of remove for different
4720 The following table details the behavior of remove for different
4714 file states (columns) and option combinations (rows). The file
4721 file states (columns) and option combinations (rows). The file
4715 states are Added [A], Clean [C], Modified [M] and Missing [!]
4722 states are Added [A], Clean [C], Modified [M] and Missing [!]
4716 (as reported by :hg:`status`). The actions are Warn, Remove
4723 (as reported by :hg:`status`). The actions are Warn, Remove
4717 (from branch) and Delete (from disk):
4724 (from branch) and Delete (from disk):
4718
4725
4719 ======= == == == ==
4726 ======= == == == ==
4720 A C M !
4727 A C M !
4721 ======= == == == ==
4728 ======= == == == ==
4722 none W RD W R
4729 none W RD W R
4723 -f R RD RD R
4730 -f R RD RD R
4724 -A W W W R
4731 -A W W W R
4725 -Af R R R R
4732 -Af R R R R
4726 ======= == == == ==
4733 ======= == == == ==
4727
4734
4728 Note that remove never deletes files in Added [A] state from the
4735 Note that remove never deletes files in Added [A] state from the
4729 working directory, not even if option --force is specified.
4736 working directory, not even if option --force is specified.
4730
4737
4731 Returns 0 on success, 1 if any warnings encountered.
4738 Returns 0 on success, 1 if any warnings encountered.
4732 """
4739 """
4733
4740
4734 ret = 0
4741 ret = 0
4735 after, force = opts.get('after'), opts.get('force')
4742 after, force = opts.get('after'), opts.get('force')
4736 if not pats and not after:
4743 if not pats and not after:
4737 raise util.Abort(_('no files specified'))
4744 raise util.Abort(_('no files specified'))
4738
4745
4739 m = scmutil.match(repo[None], pats, opts)
4746 m = scmutil.match(repo[None], pats, opts)
4740 s = repo.status(match=m, clean=True)
4747 s = repo.status(match=m, clean=True)
4741 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4748 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4742
4749
4743 # warn about failure to delete explicit files/dirs
4750 # warn about failure to delete explicit files/dirs
4744 wctx = repo[None]
4751 wctx = repo[None]
4745 for f in m.files():
4752 for f in m.files():
4746 if f in repo.dirstate or f in wctx.dirs():
4753 if f in repo.dirstate or f in wctx.dirs():
4747 continue
4754 continue
4748 if os.path.exists(m.rel(f)):
4755 if os.path.exists(m.rel(f)):
4749 if os.path.isdir(m.rel(f)):
4756 if os.path.isdir(m.rel(f)):
4750 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4757 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4751 else:
4758 else:
4752 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4759 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4753 # missing files will generate a warning elsewhere
4760 # missing files will generate a warning elsewhere
4754 ret = 1
4761 ret = 1
4755
4762
4756 if force:
4763 if force:
4757 list = modified + deleted + clean + added
4764 list = modified + deleted + clean + added
4758 elif after:
4765 elif after:
4759 list = deleted
4766 list = deleted
4760 for f in modified + added + clean:
4767 for f in modified + added + clean:
4761 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4768 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4762 ret = 1
4769 ret = 1
4763 else:
4770 else:
4764 list = deleted + clean
4771 list = deleted + clean
4765 for f in modified:
4772 for f in modified:
4766 ui.warn(_('not removing %s: file is modified (use -f'
4773 ui.warn(_('not removing %s: file is modified (use -f'
4767 ' to force removal)\n') % m.rel(f))
4774 ' to force removal)\n') % m.rel(f))
4768 ret = 1
4775 ret = 1
4769 for f in added:
4776 for f in added:
4770 ui.warn(_('not removing %s: file has been marked for add'
4777 ui.warn(_('not removing %s: file has been marked for add'
4771 ' (use forget to undo)\n') % m.rel(f))
4778 ' (use forget to undo)\n') % m.rel(f))
4772 ret = 1
4779 ret = 1
4773
4780
4774 for f in sorted(list):
4781 for f in sorted(list):
4775 if ui.verbose or not m.exact(f):
4782 if ui.verbose or not m.exact(f):
4776 ui.status(_('removing %s\n') % m.rel(f))
4783 ui.status(_('removing %s\n') % m.rel(f))
4777
4784
4778 wlock = repo.wlock()
4785 wlock = repo.wlock()
4779 try:
4786 try:
4780 if not after:
4787 if not after:
4781 for f in list:
4788 for f in list:
4782 if f in added:
4789 if f in added:
4783 continue # we never unlink added files on remove
4790 continue # we never unlink added files on remove
4784 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4791 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4785 repo[None].forget(list)
4792 repo[None].forget(list)
4786 finally:
4793 finally:
4787 wlock.release()
4794 wlock.release()
4788
4795
4789 return ret
4796 return ret
4790
4797
4791 @command('rename|move|mv',
4798 @command('rename|move|mv',
4792 [('A', 'after', None, _('record a rename that has already occurred')),
4799 [('A', 'after', None, _('record a rename that has already occurred')),
4793 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4800 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4794 ] + walkopts + dryrunopts,
4801 ] + walkopts + dryrunopts,
4795 _('[OPTION]... SOURCE... DEST'))
4802 _('[OPTION]... SOURCE... DEST'))
4796 def rename(ui, repo, *pats, **opts):
4803 def rename(ui, repo, *pats, **opts):
4797 """rename files; equivalent of copy + remove
4804 """rename files; equivalent of copy + remove
4798
4805
4799 Mark dest as copies of sources; mark sources for deletion. If dest
4806 Mark dest as copies of sources; mark sources for deletion. If dest
4800 is a directory, copies are put in that directory. If dest is a
4807 is a directory, copies are put in that directory. If dest is a
4801 file, there can only be one source.
4808 file, there can only be one source.
4802
4809
4803 By default, this command copies the contents of files as they
4810 By default, this command copies the contents of files as they
4804 exist in the working directory. If invoked with -A/--after, the
4811 exist in the working directory. If invoked with -A/--after, the
4805 operation is recorded, but no copying is performed.
4812 operation is recorded, but no copying is performed.
4806
4813
4807 This command takes effect at the next commit. To undo a rename
4814 This command takes effect at the next commit. To undo a rename
4808 before that, see :hg:`revert`.
4815 before that, see :hg:`revert`.
4809
4816
4810 Returns 0 on success, 1 if errors are encountered.
4817 Returns 0 on success, 1 if errors are encountered.
4811 """
4818 """
4812 wlock = repo.wlock(False)
4819 wlock = repo.wlock(False)
4813 try:
4820 try:
4814 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4821 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4815 finally:
4822 finally:
4816 wlock.release()
4823 wlock.release()
4817
4824
4818 @command('resolve',
4825 @command('resolve',
4819 [('a', 'all', None, _('select all unresolved files')),
4826 [('a', 'all', None, _('select all unresolved files')),
4820 ('l', 'list', None, _('list state of files needing merge')),
4827 ('l', 'list', None, _('list state of files needing merge')),
4821 ('m', 'mark', None, _('mark files as resolved')),
4828 ('m', 'mark', None, _('mark files as resolved')),
4822 ('u', 'unmark', None, _('mark files as unresolved')),
4829 ('u', 'unmark', None, _('mark files as unresolved')),
4823 ('n', 'no-status', None, _('hide status prefix'))]
4830 ('n', 'no-status', None, _('hide status prefix'))]
4824 + mergetoolopts + walkopts,
4831 + mergetoolopts + walkopts,
4825 _('[OPTION]... [FILE]...'))
4832 _('[OPTION]... [FILE]...'))
4826 def resolve(ui, repo, *pats, **opts):
4833 def resolve(ui, repo, *pats, **opts):
4827 """redo merges or set/view the merge status of files
4834 """redo merges or set/view the merge status of files
4828
4835
4829 Merges with unresolved conflicts are often the result of
4836 Merges with unresolved conflicts are often the result of
4830 non-interactive merging using the ``internal:merge`` configuration
4837 non-interactive merging using the ``internal:merge`` configuration
4831 setting, or a command-line merge tool like ``diff3``. The resolve
4838 setting, or a command-line merge tool like ``diff3``. The resolve
4832 command is used to manage the files involved in a merge, after
4839 command is used to manage the files involved in a merge, after
4833 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4840 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4834 working directory must have two parents). See :hg:`help
4841 working directory must have two parents). See :hg:`help
4835 merge-tools` for information on configuring merge tools.
4842 merge-tools` for information on configuring merge tools.
4836
4843
4837 The resolve command can be used in the following ways:
4844 The resolve command can be used in the following ways:
4838
4845
4839 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4846 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4840 files, discarding any previous merge attempts. Re-merging is not
4847 files, discarding any previous merge attempts. Re-merging is not
4841 performed for files already marked as resolved. Use ``--all/-a``
4848 performed for files already marked as resolved. Use ``--all/-a``
4842 to select all unresolved files. ``--tool`` can be used to specify
4849 to select all unresolved files. ``--tool`` can be used to specify
4843 the merge tool used for the given files. It overrides the HGMERGE
4850 the merge tool used for the given files. It overrides the HGMERGE
4844 environment variable and your configuration files. Previous file
4851 environment variable and your configuration files. Previous file
4845 contents are saved with a ``.orig`` suffix.
4852 contents are saved with a ``.orig`` suffix.
4846
4853
4847 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4854 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4848 (e.g. after having manually fixed-up the files). The default is
4855 (e.g. after having manually fixed-up the files). The default is
4849 to mark all unresolved files.
4856 to mark all unresolved files.
4850
4857
4851 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4858 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4852 default is to mark all resolved files.
4859 default is to mark all resolved files.
4853
4860
4854 - :hg:`resolve -l`: list files which had or still have conflicts.
4861 - :hg:`resolve -l`: list files which had or still have conflicts.
4855 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4862 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4856
4863
4857 Note that Mercurial will not let you commit files with unresolved
4864 Note that Mercurial will not let you commit files with unresolved
4858 merge conflicts. You must use :hg:`resolve -m ...` before you can
4865 merge conflicts. You must use :hg:`resolve -m ...` before you can
4859 commit after a conflicting merge.
4866 commit after a conflicting merge.
4860
4867
4861 Returns 0 on success, 1 if any files fail a resolve attempt.
4868 Returns 0 on success, 1 if any files fail a resolve attempt.
4862 """
4869 """
4863
4870
4864 all, mark, unmark, show, nostatus = \
4871 all, mark, unmark, show, nostatus = \
4865 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4872 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4866
4873
4867 if (show and (mark or unmark)) or (mark and unmark):
4874 if (show and (mark or unmark)) or (mark and unmark):
4868 raise util.Abort(_("too many options specified"))
4875 raise util.Abort(_("too many options specified"))
4869 if pats and all:
4876 if pats and all:
4870 raise util.Abort(_("can't specify --all and patterns"))
4877 raise util.Abort(_("can't specify --all and patterns"))
4871 if not (all or pats or show or mark or unmark):
4878 if not (all or pats or show or mark or unmark):
4872 raise util.Abort(_('no files or directories specified; '
4879 raise util.Abort(_('no files or directories specified; '
4873 'use --all to remerge all files'))
4880 'use --all to remerge all files'))
4874
4881
4875 ms = mergemod.mergestate(repo)
4882 ms = mergemod.mergestate(repo)
4876 m = scmutil.match(repo[None], pats, opts)
4883 m = scmutil.match(repo[None], pats, opts)
4877 ret = 0
4884 ret = 0
4878
4885
4879 for f in ms:
4886 for f in ms:
4880 if m(f):
4887 if m(f):
4881 if show:
4888 if show:
4882 if nostatus:
4889 if nostatus:
4883 ui.write("%s\n" % f)
4890 ui.write("%s\n" % f)
4884 else:
4891 else:
4885 ui.write("%s %s\n" % (ms[f].upper(), f),
4892 ui.write("%s %s\n" % (ms[f].upper(), f),
4886 label='resolve.' +
4893 label='resolve.' +
4887 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4894 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4888 elif mark:
4895 elif mark:
4889 ms.mark(f, "r")
4896 ms.mark(f, "r")
4890 elif unmark:
4897 elif unmark:
4891 ms.mark(f, "u")
4898 ms.mark(f, "u")
4892 else:
4899 else:
4893 wctx = repo[None]
4900 wctx = repo[None]
4894 mctx = wctx.parents()[-1]
4901 mctx = wctx.parents()[-1]
4895
4902
4896 # backup pre-resolve (merge uses .orig for its own purposes)
4903 # backup pre-resolve (merge uses .orig for its own purposes)
4897 a = repo.wjoin(f)
4904 a = repo.wjoin(f)
4898 util.copyfile(a, a + ".resolve")
4905 util.copyfile(a, a + ".resolve")
4899
4906
4900 try:
4907 try:
4901 # resolve file
4908 # resolve file
4902 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4909 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4903 if ms.resolve(f, wctx, mctx):
4910 if ms.resolve(f, wctx, mctx):
4904 ret = 1
4911 ret = 1
4905 finally:
4912 finally:
4906 ui.setconfig('ui', 'forcemerge', '')
4913 ui.setconfig('ui', 'forcemerge', '')
4907 ms.commit()
4914 ms.commit()
4908
4915
4909 # replace filemerge's .orig file with our resolve file
4916 # replace filemerge's .orig file with our resolve file
4910 util.rename(a + ".resolve", a + ".orig")
4917 util.rename(a + ".resolve", a + ".orig")
4911
4918
4912 ms.commit()
4919 ms.commit()
4913 return ret
4920 return ret
4914
4921
4915 @command('revert',
4922 @command('revert',
4916 [('a', 'all', None, _('revert all changes when no arguments given')),
4923 [('a', 'all', None, _('revert all changes when no arguments given')),
4917 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4924 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4918 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4925 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4919 ('C', 'no-backup', None, _('do not save backup copies of files')),
4926 ('C', 'no-backup', None, _('do not save backup copies of files')),
4920 ] + walkopts + dryrunopts,
4927 ] + walkopts + dryrunopts,
4921 _('[OPTION]... [-r REV] [NAME]...'))
4928 _('[OPTION]... [-r REV] [NAME]...'))
4922 def revert(ui, repo, *pats, **opts):
4929 def revert(ui, repo, *pats, **opts):
4923 """restore files to their checkout state
4930 """restore files to their checkout state
4924
4931
4925 .. note::
4932 .. note::
4926 To check out earlier revisions, you should use :hg:`update REV`.
4933 To check out earlier revisions, you should use :hg:`update REV`.
4927 To cancel an uncommitted merge (and lose your changes),
4934 To cancel an uncommitted merge (and lose your changes),
4928 use :hg:`update --clean .`.
4935 use :hg:`update --clean .`.
4929
4936
4930 With no revision specified, revert the specified files or directories
4937 With no revision specified, revert the specified files or directories
4931 to the contents they had in the parent of the working directory.
4938 to the contents they had in the parent of the working directory.
4932 This restores the contents of files to an unmodified
4939 This restores the contents of files to an unmodified
4933 state and unschedules adds, removes, copies, and renames. If the
4940 state and unschedules adds, removes, copies, and renames. If the
4934 working directory has two parents, you must explicitly specify a
4941 working directory has two parents, you must explicitly specify a
4935 revision.
4942 revision.
4936
4943
4937 Using the -r/--rev or -d/--date options, revert the given files or
4944 Using the -r/--rev or -d/--date options, revert the given files or
4938 directories to their states as of a specific revision. Because
4945 directories to their states as of a specific revision. Because
4939 revert does not change the working directory parents, this will
4946 revert does not change the working directory parents, this will
4940 cause these files to appear modified. This can be helpful to "back
4947 cause these files to appear modified. This can be helpful to "back
4941 out" some or all of an earlier change. See :hg:`backout` for a
4948 out" some or all of an earlier change. See :hg:`backout` for a
4942 related method.
4949 related method.
4943
4950
4944 Modified files are saved with a .orig suffix before reverting.
4951 Modified files are saved with a .orig suffix before reverting.
4945 To disable these backups, use --no-backup.
4952 To disable these backups, use --no-backup.
4946
4953
4947 See :hg:`help dates` for a list of formats valid for -d/--date.
4954 See :hg:`help dates` for a list of formats valid for -d/--date.
4948
4955
4949 Returns 0 on success.
4956 Returns 0 on success.
4950 """
4957 """
4951
4958
4952 if opts.get("date"):
4959 if opts.get("date"):
4953 if opts.get("rev"):
4960 if opts.get("rev"):
4954 raise util.Abort(_("you can't specify a revision and a date"))
4961 raise util.Abort(_("you can't specify a revision and a date"))
4955 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4962 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4956
4963
4957 parent, p2 = repo.dirstate.parents()
4964 parent, p2 = repo.dirstate.parents()
4958 if not opts.get('rev') and p2 != nullid:
4965 if not opts.get('rev') and p2 != nullid:
4959 # revert after merge is a trap for new users (issue2915)
4966 # revert after merge is a trap for new users (issue2915)
4960 raise util.Abort(_('uncommitted merge with no revision specified'),
4967 raise util.Abort(_('uncommitted merge with no revision specified'),
4961 hint=_('use "hg update" or see "hg help revert"'))
4968 hint=_('use "hg update" or see "hg help revert"'))
4962
4969
4963 ctx = scmutil.revsingle(repo, opts.get('rev'))
4970 ctx = scmutil.revsingle(repo, opts.get('rev'))
4964
4971
4965 if not pats and not opts.get('all'):
4972 if not pats and not opts.get('all'):
4966 msg = _("no files or directories specified")
4973 msg = _("no files or directories specified")
4967 if p2 != nullid:
4974 if p2 != nullid:
4968 hint = _("uncommitted merge, use --all to discard all changes,"
4975 hint = _("uncommitted merge, use --all to discard all changes,"
4969 " or 'hg update -C .' to abort the merge")
4976 " or 'hg update -C .' to abort the merge")
4970 raise util.Abort(msg, hint=hint)
4977 raise util.Abort(msg, hint=hint)
4971 dirty = util.any(repo.status())
4978 dirty = util.any(repo.status())
4972 node = ctx.node()
4979 node = ctx.node()
4973 if node != parent:
4980 if node != parent:
4974 if dirty:
4981 if dirty:
4975 hint = _("uncommitted changes, use --all to discard all"
4982 hint = _("uncommitted changes, use --all to discard all"
4976 " changes, or 'hg update %s' to update") % ctx.rev()
4983 " changes, or 'hg update %s' to update") % ctx.rev()
4977 else:
4984 else:
4978 hint = _("use --all to revert all files,"
4985 hint = _("use --all to revert all files,"
4979 " or 'hg update %s' to update") % ctx.rev()
4986 " or 'hg update %s' to update") % ctx.rev()
4980 elif dirty:
4987 elif dirty:
4981 hint = _("uncommitted changes, use --all to discard all changes")
4988 hint = _("uncommitted changes, use --all to discard all changes")
4982 else:
4989 else:
4983 hint = _("use --all to revert all files")
4990 hint = _("use --all to revert all files")
4984 raise util.Abort(msg, hint=hint)
4991 raise util.Abort(msg, hint=hint)
4985
4992
4986 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4993 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4987
4994
4988 @command('rollback', dryrunopts +
4995 @command('rollback', dryrunopts +
4989 [('f', 'force', False, _('ignore safety measures'))])
4996 [('f', 'force', False, _('ignore safety measures'))])
4990 def rollback(ui, repo, **opts):
4997 def rollback(ui, repo, **opts):
4991 """roll back the last transaction (dangerous)
4998 """roll back the last transaction (dangerous)
4992
4999
4993 This command should be used with care. There is only one level of
5000 This command should be used with care. There is only one level of
4994 rollback, and there is no way to undo a rollback. It will also
5001 rollback, and there is no way to undo a rollback. It will also
4995 restore the dirstate at the time of the last transaction, losing
5002 restore the dirstate at the time of the last transaction, losing
4996 any dirstate changes since that time. This command does not alter
5003 any dirstate changes since that time. This command does not alter
4997 the working directory.
5004 the working directory.
4998
5005
4999 Transactions are used to encapsulate the effects of all commands
5006 Transactions are used to encapsulate the effects of all commands
5000 that create new changesets or propagate existing changesets into a
5007 that create new changesets or propagate existing changesets into a
5001 repository.
5008 repository.
5002
5009
5003 .. container:: verbose
5010 .. container:: verbose
5004
5011
5005 For example, the following commands are transactional, and their
5012 For example, the following commands are transactional, and their
5006 effects can be rolled back:
5013 effects can be rolled back:
5007
5014
5008 - commit
5015 - commit
5009 - import
5016 - import
5010 - pull
5017 - pull
5011 - push (with this repository as the destination)
5018 - push (with this repository as the destination)
5012 - unbundle
5019 - unbundle
5013
5020
5014 To avoid permanent data loss, rollback will refuse to rollback a
5021 To avoid permanent data loss, rollback will refuse to rollback a
5015 commit transaction if it isn't checked out. Use --force to
5022 commit transaction if it isn't checked out. Use --force to
5016 override this protection.
5023 override this protection.
5017
5024
5018 This command is not intended for use on public repositories. Once
5025 This command is not intended for use on public repositories. Once
5019 changes are visible for pull by other users, rolling a transaction
5026 changes are visible for pull by other users, rolling a transaction
5020 back locally is ineffective (someone else may already have pulled
5027 back locally is ineffective (someone else may already have pulled
5021 the changes). Furthermore, a race is possible with readers of the
5028 the changes). Furthermore, a race is possible with readers of the
5022 repository; for example an in-progress pull from the repository
5029 repository; for example an in-progress pull from the repository
5023 may fail if a rollback is performed.
5030 may fail if a rollback is performed.
5024
5031
5025 Returns 0 on success, 1 if no rollback data is available.
5032 Returns 0 on success, 1 if no rollback data is available.
5026 """
5033 """
5027 return repo.rollback(dryrun=opts.get('dry_run'),
5034 return repo.rollback(dryrun=opts.get('dry_run'),
5028 force=opts.get('force'))
5035 force=opts.get('force'))
5029
5036
5030 @command('root', [])
5037 @command('root', [])
5031 def root(ui, repo):
5038 def root(ui, repo):
5032 """print the root (top) of the current working directory
5039 """print the root (top) of the current working directory
5033
5040
5034 Print the root directory of the current repository.
5041 Print the root directory of the current repository.
5035
5042
5036 Returns 0 on success.
5043 Returns 0 on success.
5037 """
5044 """
5038 ui.write(repo.root + "\n")
5045 ui.write(repo.root + "\n")
5039
5046
5040 @command('^serve',
5047 @command('^serve',
5041 [('A', 'accesslog', '', _('name of access log file to write to'),
5048 [('A', 'accesslog', '', _('name of access log file to write to'),
5042 _('FILE')),
5049 _('FILE')),
5043 ('d', 'daemon', None, _('run server in background')),
5050 ('d', 'daemon', None, _('run server in background')),
5044 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5051 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5045 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5052 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5046 # use string type, then we can check if something was passed
5053 # use string type, then we can check if something was passed
5047 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5054 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5048 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5055 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5049 _('ADDR')),
5056 _('ADDR')),
5050 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5057 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5051 _('PREFIX')),
5058 _('PREFIX')),
5052 ('n', 'name', '',
5059 ('n', 'name', '',
5053 _('name to show in web pages (default: working directory)'), _('NAME')),
5060 _('name to show in web pages (default: working directory)'), _('NAME')),
5054 ('', 'web-conf', '',
5061 ('', 'web-conf', '',
5055 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5062 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5056 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5063 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5057 _('FILE')),
5064 _('FILE')),
5058 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5065 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5059 ('', 'stdio', None, _('for remote clients')),
5066 ('', 'stdio', None, _('for remote clients')),
5060 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5067 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5061 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5068 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5062 ('', 'style', '', _('template style to use'), _('STYLE')),
5069 ('', 'style', '', _('template style to use'), _('STYLE')),
5063 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5070 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5064 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5071 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5065 _('[OPTION]...'))
5072 _('[OPTION]...'))
5066 def serve(ui, repo, **opts):
5073 def serve(ui, repo, **opts):
5067 """start stand-alone webserver
5074 """start stand-alone webserver
5068
5075
5069 Start a local HTTP repository browser and pull server. You can use
5076 Start a local HTTP repository browser and pull server. You can use
5070 this for ad-hoc sharing and browsing of repositories. It is
5077 this for ad-hoc sharing and browsing of repositories. It is
5071 recommended to use a real web server to serve a repository for
5078 recommended to use a real web server to serve a repository for
5072 longer periods of time.
5079 longer periods of time.
5073
5080
5074 Please note that the server does not implement access control.
5081 Please note that the server does not implement access control.
5075 This means that, by default, anybody can read from the server and
5082 This means that, by default, anybody can read from the server and
5076 nobody can write to it by default. Set the ``web.allow_push``
5083 nobody can write to it by default. Set the ``web.allow_push``
5077 option to ``*`` to allow everybody to push to the server. You
5084 option to ``*`` to allow everybody to push to the server. You
5078 should use a real web server if you need to authenticate users.
5085 should use a real web server if you need to authenticate users.
5079
5086
5080 By default, the server logs accesses to stdout and errors to
5087 By default, the server logs accesses to stdout and errors to
5081 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5088 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5082 files.
5089 files.
5083
5090
5084 To have the server choose a free port number to listen on, specify
5091 To have the server choose a free port number to listen on, specify
5085 a port number of 0; in this case, the server will print the port
5092 a port number of 0; in this case, the server will print the port
5086 number it uses.
5093 number it uses.
5087
5094
5088 Returns 0 on success.
5095 Returns 0 on success.
5089 """
5096 """
5090
5097
5091 if opts["stdio"] and opts["cmdserver"]:
5098 if opts["stdio"] and opts["cmdserver"]:
5092 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5099 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5093
5100
5094 def checkrepo():
5101 def checkrepo():
5095 if repo is None:
5102 if repo is None:
5096 raise error.RepoError(_("there is no Mercurial repository here"
5103 raise error.RepoError(_("there is no Mercurial repository here"
5097 " (.hg not found)"))
5104 " (.hg not found)"))
5098
5105
5099 if opts["stdio"]:
5106 if opts["stdio"]:
5100 checkrepo()
5107 checkrepo()
5101 s = sshserver.sshserver(ui, repo)
5108 s = sshserver.sshserver(ui, repo)
5102 s.serve_forever()
5109 s.serve_forever()
5103
5110
5104 if opts["cmdserver"]:
5111 if opts["cmdserver"]:
5105 checkrepo()
5112 checkrepo()
5106 s = commandserver.server(ui, repo, opts["cmdserver"])
5113 s = commandserver.server(ui, repo, opts["cmdserver"])
5107 return s.serve()
5114 return s.serve()
5108
5115
5109 # this way we can check if something was given in the command-line
5116 # this way we can check if something was given in the command-line
5110 if opts.get('port'):
5117 if opts.get('port'):
5111 opts['port'] = util.getport(opts.get('port'))
5118 opts['port'] = util.getport(opts.get('port'))
5112
5119
5113 baseui = repo and repo.baseui or ui
5120 baseui = repo and repo.baseui or ui
5114 optlist = ("name templates style address port prefix ipv6"
5121 optlist = ("name templates style address port prefix ipv6"
5115 " accesslog errorlog certificate encoding")
5122 " accesslog errorlog certificate encoding")
5116 for o in optlist.split():
5123 for o in optlist.split():
5117 val = opts.get(o, '')
5124 val = opts.get(o, '')
5118 if val in (None, ''): # should check against default options instead
5125 if val in (None, ''): # should check against default options instead
5119 continue
5126 continue
5120 baseui.setconfig("web", o, val)
5127 baseui.setconfig("web", o, val)
5121 if repo and repo.ui != baseui:
5128 if repo and repo.ui != baseui:
5122 repo.ui.setconfig("web", o, val)
5129 repo.ui.setconfig("web", o, val)
5123
5130
5124 o = opts.get('web_conf') or opts.get('webdir_conf')
5131 o = opts.get('web_conf') or opts.get('webdir_conf')
5125 if not o:
5132 if not o:
5126 if not repo:
5133 if not repo:
5127 raise error.RepoError(_("there is no Mercurial repository"
5134 raise error.RepoError(_("there is no Mercurial repository"
5128 " here (.hg not found)"))
5135 " here (.hg not found)"))
5129 o = repo
5136 o = repo
5130
5137
5131 app = hgweb.hgweb(o, baseui=baseui)
5138 app = hgweb.hgweb(o, baseui=baseui)
5132
5139
5133 class service(object):
5140 class service(object):
5134 def init(self):
5141 def init(self):
5135 util.setsignalhandler()
5142 util.setsignalhandler()
5136 self.httpd = hgweb.server.create_server(ui, app)
5143 self.httpd = hgweb.server.create_server(ui, app)
5137
5144
5138 if opts['port'] and not ui.verbose:
5145 if opts['port'] and not ui.verbose:
5139 return
5146 return
5140
5147
5141 if self.httpd.prefix:
5148 if self.httpd.prefix:
5142 prefix = self.httpd.prefix.strip('/') + '/'
5149 prefix = self.httpd.prefix.strip('/') + '/'
5143 else:
5150 else:
5144 prefix = ''
5151 prefix = ''
5145
5152
5146 port = ':%d' % self.httpd.port
5153 port = ':%d' % self.httpd.port
5147 if port == ':80':
5154 if port == ':80':
5148 port = ''
5155 port = ''
5149
5156
5150 bindaddr = self.httpd.addr
5157 bindaddr = self.httpd.addr
5151 if bindaddr == '0.0.0.0':
5158 if bindaddr == '0.0.0.0':
5152 bindaddr = '*'
5159 bindaddr = '*'
5153 elif ':' in bindaddr: # IPv6
5160 elif ':' in bindaddr: # IPv6
5154 bindaddr = '[%s]' % bindaddr
5161 bindaddr = '[%s]' % bindaddr
5155
5162
5156 fqaddr = self.httpd.fqaddr
5163 fqaddr = self.httpd.fqaddr
5157 if ':' in fqaddr:
5164 if ':' in fqaddr:
5158 fqaddr = '[%s]' % fqaddr
5165 fqaddr = '[%s]' % fqaddr
5159 if opts['port']:
5166 if opts['port']:
5160 write = ui.status
5167 write = ui.status
5161 else:
5168 else:
5162 write = ui.write
5169 write = ui.write
5163 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5170 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5164 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5171 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5165
5172
5166 def run(self):
5173 def run(self):
5167 self.httpd.serve_forever()
5174 self.httpd.serve_forever()
5168
5175
5169 service = service()
5176 service = service()
5170
5177
5171 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5178 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5172
5179
5173 @command('showconfig|debugconfig',
5180 @command('showconfig|debugconfig',
5174 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5181 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5175 _('[-u] [NAME]...'))
5182 _('[-u] [NAME]...'))
5176 def showconfig(ui, repo, *values, **opts):
5183 def showconfig(ui, repo, *values, **opts):
5177 """show combined config settings from all hgrc files
5184 """show combined config settings from all hgrc files
5178
5185
5179 With no arguments, print names and values of all config items.
5186 With no arguments, print names and values of all config items.
5180
5187
5181 With one argument of the form section.name, print just the value
5188 With one argument of the form section.name, print just the value
5182 of that config item.
5189 of that config item.
5183
5190
5184 With multiple arguments, print names and values of all config
5191 With multiple arguments, print names and values of all config
5185 items with matching section names.
5192 items with matching section names.
5186
5193
5187 With --debug, the source (filename and line number) is printed
5194 With --debug, the source (filename and line number) is printed
5188 for each config item.
5195 for each config item.
5189
5196
5190 Returns 0 on success.
5197 Returns 0 on success.
5191 """
5198 """
5192
5199
5193 for f in scmutil.rcpath():
5200 for f in scmutil.rcpath():
5194 ui.debug('read config from: %s\n' % f)
5201 ui.debug('read config from: %s\n' % f)
5195 untrusted = bool(opts.get('untrusted'))
5202 untrusted = bool(opts.get('untrusted'))
5196 if values:
5203 if values:
5197 sections = [v for v in values if '.' not in v]
5204 sections = [v for v in values if '.' not in v]
5198 items = [v for v in values if '.' in v]
5205 items = [v for v in values if '.' in v]
5199 if len(items) > 1 or items and sections:
5206 if len(items) > 1 or items and sections:
5200 raise util.Abort(_('only one config item permitted'))
5207 raise util.Abort(_('only one config item permitted'))
5201 for section, name, value in ui.walkconfig(untrusted=untrusted):
5208 for section, name, value in ui.walkconfig(untrusted=untrusted):
5202 value = str(value).replace('\n', '\\n')
5209 value = str(value).replace('\n', '\\n')
5203 sectname = section + '.' + name
5210 sectname = section + '.' + name
5204 if values:
5211 if values:
5205 for v in values:
5212 for v in values:
5206 if v == section:
5213 if v == section:
5207 ui.debug('%s: ' %
5214 ui.debug('%s: ' %
5208 ui.configsource(section, name, untrusted))
5215 ui.configsource(section, name, untrusted))
5209 ui.write('%s=%s\n' % (sectname, value))
5216 ui.write('%s=%s\n' % (sectname, value))
5210 elif v == sectname:
5217 elif v == sectname:
5211 ui.debug('%s: ' %
5218 ui.debug('%s: ' %
5212 ui.configsource(section, name, untrusted))
5219 ui.configsource(section, name, untrusted))
5213 ui.write(value, '\n')
5220 ui.write(value, '\n')
5214 else:
5221 else:
5215 ui.debug('%s: ' %
5222 ui.debug('%s: ' %
5216 ui.configsource(section, name, untrusted))
5223 ui.configsource(section, name, untrusted))
5217 ui.write('%s=%s\n' % (sectname, value))
5224 ui.write('%s=%s\n' % (sectname, value))
5218
5225
5219 @command('^status|st',
5226 @command('^status|st',
5220 [('A', 'all', None, _('show status of all files')),
5227 [('A', 'all', None, _('show status of all files')),
5221 ('m', 'modified', None, _('show only modified files')),
5228 ('m', 'modified', None, _('show only modified files')),
5222 ('a', 'added', None, _('show only added files')),
5229 ('a', 'added', None, _('show only added files')),
5223 ('r', 'removed', None, _('show only removed files')),
5230 ('r', 'removed', None, _('show only removed files')),
5224 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5231 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5225 ('c', 'clean', None, _('show only files without changes')),
5232 ('c', 'clean', None, _('show only files without changes')),
5226 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5233 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5227 ('i', 'ignored', None, _('show only ignored files')),
5234 ('i', 'ignored', None, _('show only ignored files')),
5228 ('n', 'no-status', None, _('hide status prefix')),
5235 ('n', 'no-status', None, _('hide status prefix')),
5229 ('C', 'copies', None, _('show source of copied files')),
5236 ('C', 'copies', None, _('show source of copied files')),
5230 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5237 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5231 ('', 'rev', [], _('show difference from revision'), _('REV')),
5238 ('', 'rev', [], _('show difference from revision'), _('REV')),
5232 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5239 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5233 ] + walkopts + subrepoopts,
5240 ] + walkopts + subrepoopts,
5234 _('[OPTION]... [FILE]...'))
5241 _('[OPTION]... [FILE]...'))
5235 def status(ui, repo, *pats, **opts):
5242 def status(ui, repo, *pats, **opts):
5236 """show changed files in the working directory
5243 """show changed files in the working directory
5237
5244
5238 Show status of files in the repository. If names are given, only
5245 Show status of files in the repository. If names are given, only
5239 files that match are shown. Files that are clean or ignored or
5246 files that match are shown. Files that are clean or ignored or
5240 the source of a copy/move operation, are not listed unless
5247 the source of a copy/move operation, are not listed unless
5241 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5248 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5242 Unless options described with "show only ..." are given, the
5249 Unless options described with "show only ..." are given, the
5243 options -mardu are used.
5250 options -mardu are used.
5244
5251
5245 Option -q/--quiet hides untracked (unknown and ignored) files
5252 Option -q/--quiet hides untracked (unknown and ignored) files
5246 unless explicitly requested with -u/--unknown or -i/--ignored.
5253 unless explicitly requested with -u/--unknown or -i/--ignored.
5247
5254
5248 .. note::
5255 .. note::
5249 status may appear to disagree with diff if permissions have
5256 status may appear to disagree with diff if permissions have
5250 changed or a merge has occurred. The standard diff format does
5257 changed or a merge has occurred. The standard diff format does
5251 not report permission changes and diff only reports changes
5258 not report permission changes and diff only reports changes
5252 relative to one merge parent.
5259 relative to one merge parent.
5253
5260
5254 If one revision is given, it is used as the base revision.
5261 If one revision is given, it is used as the base revision.
5255 If two revisions are given, the differences between them are
5262 If two revisions are given, the differences between them are
5256 shown. The --change option can also be used as a shortcut to list
5263 shown. The --change option can also be used as a shortcut to list
5257 the changed files of a revision from its first parent.
5264 the changed files of a revision from its first parent.
5258
5265
5259 The codes used to show the status of files are::
5266 The codes used to show the status of files are::
5260
5267
5261 M = modified
5268 M = modified
5262 A = added
5269 A = added
5263 R = removed
5270 R = removed
5264 C = clean
5271 C = clean
5265 ! = missing (deleted by non-hg command, but still tracked)
5272 ! = missing (deleted by non-hg command, but still tracked)
5266 ? = not tracked
5273 ? = not tracked
5267 I = ignored
5274 I = ignored
5268 = origin of the previous file listed as A (added)
5275 = origin of the previous file listed as A (added)
5269
5276
5270 .. container:: verbose
5277 .. container:: verbose
5271
5278
5272 Examples:
5279 Examples:
5273
5280
5274 - show changes in the working directory relative to a
5281 - show changes in the working directory relative to a
5275 changeset::
5282 changeset::
5276
5283
5277 hg status --rev 9353
5284 hg status --rev 9353
5278
5285
5279 - show all changes including copies in an existing changeset::
5286 - show all changes including copies in an existing changeset::
5280
5287
5281 hg status --copies --change 9353
5288 hg status --copies --change 9353
5282
5289
5283 - get a NUL separated list of added files, suitable for xargs::
5290 - get a NUL separated list of added files, suitable for xargs::
5284
5291
5285 hg status -an0
5292 hg status -an0
5286
5293
5287 Returns 0 on success.
5294 Returns 0 on success.
5288 """
5295 """
5289
5296
5290 revs = opts.get('rev')
5297 revs = opts.get('rev')
5291 change = opts.get('change')
5298 change = opts.get('change')
5292
5299
5293 if revs and change:
5300 if revs and change:
5294 msg = _('cannot specify --rev and --change at the same time')
5301 msg = _('cannot specify --rev and --change at the same time')
5295 raise util.Abort(msg)
5302 raise util.Abort(msg)
5296 elif change:
5303 elif change:
5297 node2 = scmutil.revsingle(repo, change, None).node()
5304 node2 = scmutil.revsingle(repo, change, None).node()
5298 node1 = repo[node2].p1().node()
5305 node1 = repo[node2].p1().node()
5299 else:
5306 else:
5300 node1, node2 = scmutil.revpair(repo, revs)
5307 node1, node2 = scmutil.revpair(repo, revs)
5301
5308
5302 cwd = (pats and repo.getcwd()) or ''
5309 cwd = (pats and repo.getcwd()) or ''
5303 end = opts.get('print0') and '\0' or '\n'
5310 end = opts.get('print0') and '\0' or '\n'
5304 copy = {}
5311 copy = {}
5305 states = 'modified added removed deleted unknown ignored clean'.split()
5312 states = 'modified added removed deleted unknown ignored clean'.split()
5306 show = [k for k in states if opts.get(k)]
5313 show = [k for k in states if opts.get(k)]
5307 if opts.get('all'):
5314 if opts.get('all'):
5308 show += ui.quiet and (states[:4] + ['clean']) or states
5315 show += ui.quiet and (states[:4] + ['clean']) or states
5309 if not show:
5316 if not show:
5310 show = ui.quiet and states[:4] or states[:5]
5317 show = ui.quiet and states[:4] or states[:5]
5311
5318
5312 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5319 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5313 'ignored' in show, 'clean' in show, 'unknown' in show,
5320 'ignored' in show, 'clean' in show, 'unknown' in show,
5314 opts.get('subrepos'))
5321 opts.get('subrepos'))
5315 changestates = zip(states, 'MAR!?IC', stat)
5322 changestates = zip(states, 'MAR!?IC', stat)
5316
5323
5317 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5324 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5318 copy = copies.pathcopies(repo[node1], repo[node2])
5325 copy = copies.pathcopies(repo[node1], repo[node2])
5319
5326
5320 fm = ui.formatter('status', opts)
5327 fm = ui.formatter('status', opts)
5321 fmt = '%s' + end
5328 fmt = '%s' + end
5322 showchar = not opts.get('no_status')
5329 showchar = not opts.get('no_status')
5323
5330
5324 for state, char, files in changestates:
5331 for state, char, files in changestates:
5325 if state in show:
5332 if state in show:
5326 label = 'status.' + state
5333 label = 'status.' + state
5327 for f in files:
5334 for f in files:
5328 fm.startitem()
5335 fm.startitem()
5329 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5336 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5330 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5337 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5331 if f in copy:
5338 if f in copy:
5332 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5339 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5333 label='status.copied')
5340 label='status.copied')
5334 fm.end()
5341 fm.end()
5335
5342
5336 @command('^summary|sum',
5343 @command('^summary|sum',
5337 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5344 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5338 def summary(ui, repo, **opts):
5345 def summary(ui, repo, **opts):
5339 """summarize working directory state
5346 """summarize working directory state
5340
5347
5341 This generates a brief summary of the working directory state,
5348 This generates a brief summary of the working directory state,
5342 including parents, branch, commit status, and available updates.
5349 including parents, branch, commit status, and available updates.
5343
5350
5344 With the --remote option, this will check the default paths for
5351 With the --remote option, this will check the default paths for
5345 incoming and outgoing changes. This can be time-consuming.
5352 incoming and outgoing changes. This can be time-consuming.
5346
5353
5347 Returns 0 on success.
5354 Returns 0 on success.
5348 """
5355 """
5349
5356
5350 ctx = repo[None]
5357 ctx = repo[None]
5351 parents = ctx.parents()
5358 parents = ctx.parents()
5352 pnode = parents[0].node()
5359 pnode = parents[0].node()
5353 marks = []
5360 marks = []
5354
5361
5355 for p in parents:
5362 for p in parents:
5356 # label with log.changeset (instead of log.parent) since this
5363 # label with log.changeset (instead of log.parent) since this
5357 # shows a working directory parent *changeset*:
5364 # shows a working directory parent *changeset*:
5358 # i18n: column positioning for "hg summary"
5365 # i18n: column positioning for "hg summary"
5359 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5366 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5360 label='log.changeset changeset.%s' % p.phasestr())
5367 label='log.changeset changeset.%s' % p.phasestr())
5361 ui.write(' '.join(p.tags()), label='log.tag')
5368 ui.write(' '.join(p.tags()), label='log.tag')
5362 if p.bookmarks():
5369 if p.bookmarks():
5363 marks.extend(p.bookmarks())
5370 marks.extend(p.bookmarks())
5364 if p.rev() == -1:
5371 if p.rev() == -1:
5365 if not len(repo):
5372 if not len(repo):
5366 ui.write(_(' (empty repository)'))
5373 ui.write(_(' (empty repository)'))
5367 else:
5374 else:
5368 ui.write(_(' (no revision checked out)'))
5375 ui.write(_(' (no revision checked out)'))
5369 ui.write('\n')
5376 ui.write('\n')
5370 if p.description():
5377 if p.description():
5371 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5378 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5372 label='log.summary')
5379 label='log.summary')
5373
5380
5374 branch = ctx.branch()
5381 branch = ctx.branch()
5375 bheads = repo.branchheads(branch)
5382 bheads = repo.branchheads(branch)
5376 # i18n: column positioning for "hg summary"
5383 # i18n: column positioning for "hg summary"
5377 m = _('branch: %s\n') % branch
5384 m = _('branch: %s\n') % branch
5378 if branch != 'default':
5385 if branch != 'default':
5379 ui.write(m, label='log.branch')
5386 ui.write(m, label='log.branch')
5380 else:
5387 else:
5381 ui.status(m, label='log.branch')
5388 ui.status(m, label='log.branch')
5382
5389
5383 if marks:
5390 if marks:
5384 current = repo._bookmarkcurrent
5391 current = repo._bookmarkcurrent
5385 # i18n: column positioning for "hg summary"
5392 # i18n: column positioning for "hg summary"
5386 ui.write(_('bookmarks:'), label='log.bookmark')
5393 ui.write(_('bookmarks:'), label='log.bookmark')
5387 if current is not None:
5394 if current is not None:
5388 if current in marks:
5395 if current in marks:
5389 ui.write(' *' + current, label='bookmarks.current')
5396 ui.write(' *' + current, label='bookmarks.current')
5390 marks.remove(current)
5397 marks.remove(current)
5391 else:
5398 else:
5392 ui.write(' [%s]' % current, label='bookmarks.current')
5399 ui.write(' [%s]' % current, label='bookmarks.current')
5393 for m in marks:
5400 for m in marks:
5394 ui.write(' ' + m, label='log.bookmark')
5401 ui.write(' ' + m, label='log.bookmark')
5395 ui.write('\n', label='log.bookmark')
5402 ui.write('\n', label='log.bookmark')
5396
5403
5397 st = list(repo.status(unknown=True))[:6]
5404 st = list(repo.status(unknown=True))[:6]
5398
5405
5399 c = repo.dirstate.copies()
5406 c = repo.dirstate.copies()
5400 copied, renamed = [], []
5407 copied, renamed = [], []
5401 for d, s in c.iteritems():
5408 for d, s in c.iteritems():
5402 if s in st[2]:
5409 if s in st[2]:
5403 st[2].remove(s)
5410 st[2].remove(s)
5404 renamed.append(d)
5411 renamed.append(d)
5405 else:
5412 else:
5406 copied.append(d)
5413 copied.append(d)
5407 if d in st[1]:
5414 if d in st[1]:
5408 st[1].remove(d)
5415 st[1].remove(d)
5409 st.insert(3, renamed)
5416 st.insert(3, renamed)
5410 st.insert(4, copied)
5417 st.insert(4, copied)
5411
5418
5412 ms = mergemod.mergestate(repo)
5419 ms = mergemod.mergestate(repo)
5413 st.append([f for f in ms if ms[f] == 'u'])
5420 st.append([f for f in ms if ms[f] == 'u'])
5414
5421
5415 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5422 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5416 st.append(subs)
5423 st.append(subs)
5417
5424
5418 labels = [ui.label(_('%d modified'), 'status.modified'),
5425 labels = [ui.label(_('%d modified'), 'status.modified'),
5419 ui.label(_('%d added'), 'status.added'),
5426 ui.label(_('%d added'), 'status.added'),
5420 ui.label(_('%d removed'), 'status.removed'),
5427 ui.label(_('%d removed'), 'status.removed'),
5421 ui.label(_('%d renamed'), 'status.copied'),
5428 ui.label(_('%d renamed'), 'status.copied'),
5422 ui.label(_('%d copied'), 'status.copied'),
5429 ui.label(_('%d copied'), 'status.copied'),
5423 ui.label(_('%d deleted'), 'status.deleted'),
5430 ui.label(_('%d deleted'), 'status.deleted'),
5424 ui.label(_('%d unknown'), 'status.unknown'),
5431 ui.label(_('%d unknown'), 'status.unknown'),
5425 ui.label(_('%d ignored'), 'status.ignored'),
5432 ui.label(_('%d ignored'), 'status.ignored'),
5426 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5433 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5427 ui.label(_('%d subrepos'), 'status.modified')]
5434 ui.label(_('%d subrepos'), 'status.modified')]
5428 t = []
5435 t = []
5429 for s, l in zip(st, labels):
5436 for s, l in zip(st, labels):
5430 if s:
5437 if s:
5431 t.append(l % len(s))
5438 t.append(l % len(s))
5432
5439
5433 t = ', '.join(t)
5440 t = ', '.join(t)
5434 cleanworkdir = False
5441 cleanworkdir = False
5435
5442
5436 if len(parents) > 1:
5443 if len(parents) > 1:
5437 t += _(' (merge)')
5444 t += _(' (merge)')
5438 elif branch != parents[0].branch():
5445 elif branch != parents[0].branch():
5439 t += _(' (new branch)')
5446 t += _(' (new branch)')
5440 elif (parents[0].closesbranch() and
5447 elif (parents[0].closesbranch() and
5441 pnode in repo.branchheads(branch, closed=True)):
5448 pnode in repo.branchheads(branch, closed=True)):
5442 t += _(' (head closed)')
5449 t += _(' (head closed)')
5443 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5450 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5444 t += _(' (clean)')
5451 t += _(' (clean)')
5445 cleanworkdir = True
5452 cleanworkdir = True
5446 elif pnode not in bheads:
5453 elif pnode not in bheads:
5447 t += _(' (new branch head)')
5454 t += _(' (new branch head)')
5448
5455
5449 if cleanworkdir:
5456 if cleanworkdir:
5450 # i18n: column positioning for "hg summary"
5457 # i18n: column positioning for "hg summary"
5451 ui.status(_('commit: %s\n') % t.strip())
5458 ui.status(_('commit: %s\n') % t.strip())
5452 else:
5459 else:
5453 # i18n: column positioning for "hg summary"
5460 # i18n: column positioning for "hg summary"
5454 ui.write(_('commit: %s\n') % t.strip())
5461 ui.write(_('commit: %s\n') % t.strip())
5455
5462
5456 # all ancestors of branch heads - all ancestors of parent = new csets
5463 # all ancestors of branch heads - all ancestors of parent = new csets
5457 new = [0] * len(repo)
5464 new = [0] * len(repo)
5458 cl = repo.changelog
5465 cl = repo.changelog
5459 for a in [cl.rev(n) for n in bheads]:
5466 for a in [cl.rev(n) for n in bheads]:
5460 new[a] = 1
5467 new[a] = 1
5461 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5468 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5462 new[a] = 1
5469 new[a] = 1
5463 for a in [p.rev() for p in parents]:
5470 for a in [p.rev() for p in parents]:
5464 if a >= 0:
5471 if a >= 0:
5465 new[a] = 0
5472 new[a] = 0
5466 for a in cl.ancestors([p.rev() for p in parents]):
5473 for a in cl.ancestors([p.rev() for p in parents]):
5467 new[a] = 0
5474 new[a] = 0
5468 new = sum(new)
5475 new = sum(new)
5469
5476
5470 if new == 0:
5477 if new == 0:
5471 # i18n: column positioning for "hg summary"
5478 # i18n: column positioning for "hg summary"
5472 ui.status(_('update: (current)\n'))
5479 ui.status(_('update: (current)\n'))
5473 elif pnode not in bheads:
5480 elif pnode not in bheads:
5474 # i18n: column positioning for "hg summary"
5481 # i18n: column positioning for "hg summary"
5475 ui.write(_('update: %d new changesets (update)\n') % new)
5482 ui.write(_('update: %d new changesets (update)\n') % new)
5476 else:
5483 else:
5477 # i18n: column positioning for "hg summary"
5484 # i18n: column positioning for "hg summary"
5478 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5485 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5479 (new, len(bheads)))
5486 (new, len(bheads)))
5480
5487
5481 if opts.get('remote'):
5488 if opts.get('remote'):
5482 t = []
5489 t = []
5483 source, branches = hg.parseurl(ui.expandpath('default'))
5490 source, branches = hg.parseurl(ui.expandpath('default'))
5484 sbranch = branches[0]
5491 sbranch = branches[0]
5485 other = hg.peer(repo, {}, source)
5492 other = hg.peer(repo, {}, source)
5486 revs, checkout = hg.addbranchrevs(repo, other, branches,
5493 revs, checkout = hg.addbranchrevs(repo, other, branches,
5487 opts.get('rev'))
5494 opts.get('rev'))
5488 if revs:
5495 if revs:
5489 revs = [other.lookup(rev) for rev in revs]
5496 revs = [other.lookup(rev) for rev in revs]
5490 ui.debug('comparing with %s\n' % util.hidepassword(source))
5497 ui.debug('comparing with %s\n' % util.hidepassword(source))
5491 repo.ui.pushbuffer()
5498 repo.ui.pushbuffer()
5492 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5499 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5493 _common, incoming, _rheads = commoninc
5500 _common, incoming, _rheads = commoninc
5494 repo.ui.popbuffer()
5501 repo.ui.popbuffer()
5495 if incoming:
5502 if incoming:
5496 t.append(_('1 or more incoming'))
5503 t.append(_('1 or more incoming'))
5497
5504
5498 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5505 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5499 dbranch = branches[0]
5506 dbranch = branches[0]
5500 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5507 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5501 if source != dest:
5508 if source != dest:
5502 other = hg.peer(repo, {}, dest)
5509 other = hg.peer(repo, {}, dest)
5503 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5510 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5504 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5511 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5505 commoninc = None
5512 commoninc = None
5506 if revs:
5513 if revs:
5507 revs = [repo.lookup(rev) for rev in revs]
5514 revs = [repo.lookup(rev) for rev in revs]
5508 repo.ui.pushbuffer()
5515 repo.ui.pushbuffer()
5509 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5516 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5510 commoninc=commoninc)
5517 commoninc=commoninc)
5511 repo.ui.popbuffer()
5518 repo.ui.popbuffer()
5512 o = outgoing.missing
5519 o = outgoing.missing
5513 if o:
5520 if o:
5514 t.append(_('%d outgoing') % len(o))
5521 t.append(_('%d outgoing') % len(o))
5515 if 'bookmarks' in other.listkeys('namespaces'):
5522 if 'bookmarks' in other.listkeys('namespaces'):
5516 lmarks = repo.listkeys('bookmarks')
5523 lmarks = repo.listkeys('bookmarks')
5517 rmarks = other.listkeys('bookmarks')
5524 rmarks = other.listkeys('bookmarks')
5518 diff = set(rmarks) - set(lmarks)
5525 diff = set(rmarks) - set(lmarks)
5519 if len(diff) > 0:
5526 if len(diff) > 0:
5520 t.append(_('%d incoming bookmarks') % len(diff))
5527 t.append(_('%d incoming bookmarks') % len(diff))
5521 diff = set(lmarks) - set(rmarks)
5528 diff = set(lmarks) - set(rmarks)
5522 if len(diff) > 0:
5529 if len(diff) > 0:
5523 t.append(_('%d outgoing bookmarks') % len(diff))
5530 t.append(_('%d outgoing bookmarks') % len(diff))
5524
5531
5525 if t:
5532 if t:
5526 # i18n: column positioning for "hg summary"
5533 # i18n: column positioning for "hg summary"
5527 ui.write(_('remote: %s\n') % (', '.join(t)))
5534 ui.write(_('remote: %s\n') % (', '.join(t)))
5528 else:
5535 else:
5529 # i18n: column positioning for "hg summary"
5536 # i18n: column positioning for "hg summary"
5530 ui.status(_('remote: (synced)\n'))
5537 ui.status(_('remote: (synced)\n'))
5531
5538
5532 @command('tag',
5539 @command('tag',
5533 [('f', 'force', None, _('force tag')),
5540 [('f', 'force', None, _('force tag')),
5534 ('l', 'local', None, _('make the tag local')),
5541 ('l', 'local', None, _('make the tag local')),
5535 ('r', 'rev', '', _('revision to tag'), _('REV')),
5542 ('r', 'rev', '', _('revision to tag'), _('REV')),
5536 ('', 'remove', None, _('remove a tag')),
5543 ('', 'remove', None, _('remove a tag')),
5537 # -l/--local is already there, commitopts cannot be used
5544 # -l/--local is already there, commitopts cannot be used
5538 ('e', 'edit', None, _('edit commit message')),
5545 ('e', 'edit', None, _('edit commit message')),
5539 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5546 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5540 ] + commitopts2,
5547 ] + commitopts2,
5541 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5548 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5542 def tag(ui, repo, name1, *names, **opts):
5549 def tag(ui, repo, name1, *names, **opts):
5543 """add one or more tags for the current or given revision
5550 """add one or more tags for the current or given revision
5544
5551
5545 Name a particular revision using <name>.
5552 Name a particular revision using <name>.
5546
5553
5547 Tags are used to name particular revisions of the repository and are
5554 Tags are used to name particular revisions of the repository and are
5548 very useful to compare different revisions, to go back to significant
5555 very useful to compare different revisions, to go back to significant
5549 earlier versions or to mark branch points as releases, etc. Changing
5556 earlier versions or to mark branch points as releases, etc. Changing
5550 an existing tag is normally disallowed; use -f/--force to override.
5557 an existing tag is normally disallowed; use -f/--force to override.
5551
5558
5552 If no revision is given, the parent of the working directory is
5559 If no revision is given, the parent of the working directory is
5553 used, or tip if no revision is checked out.
5560 used, or tip if no revision is checked out.
5554
5561
5555 To facilitate version control, distribution, and merging of tags,
5562 To facilitate version control, distribution, and merging of tags,
5556 they are stored as a file named ".hgtags" which is managed similarly
5563 they are stored as a file named ".hgtags" which is managed similarly
5557 to other project files and can be hand-edited if necessary. This
5564 to other project files and can be hand-edited if necessary. This
5558 also means that tagging creates a new commit. The file
5565 also means that tagging creates a new commit. The file
5559 ".hg/localtags" is used for local tags (not shared among
5566 ".hg/localtags" is used for local tags (not shared among
5560 repositories).
5567 repositories).
5561
5568
5562 Tag commits are usually made at the head of a branch. If the parent
5569 Tag commits are usually made at the head of a branch. If the parent
5563 of the working directory is not a branch head, :hg:`tag` aborts; use
5570 of the working directory is not a branch head, :hg:`tag` aborts; use
5564 -f/--force to force the tag commit to be based on a non-head
5571 -f/--force to force the tag commit to be based on a non-head
5565 changeset.
5572 changeset.
5566
5573
5567 See :hg:`help dates` for a list of formats valid for -d/--date.
5574 See :hg:`help dates` for a list of formats valid for -d/--date.
5568
5575
5569 Since tag names have priority over branch names during revision
5576 Since tag names have priority over branch names during revision
5570 lookup, using an existing branch name as a tag name is discouraged.
5577 lookup, using an existing branch name as a tag name is discouraged.
5571
5578
5572 Returns 0 on success.
5579 Returns 0 on success.
5573 """
5580 """
5574 wlock = lock = None
5581 wlock = lock = None
5575 try:
5582 try:
5576 wlock = repo.wlock()
5583 wlock = repo.wlock()
5577 lock = repo.lock()
5584 lock = repo.lock()
5578 rev_ = "."
5585 rev_ = "."
5579 names = [t.strip() for t in (name1,) + names]
5586 names = [t.strip() for t in (name1,) + names]
5580 if len(names) != len(set(names)):
5587 if len(names) != len(set(names)):
5581 raise util.Abort(_('tag names must be unique'))
5588 raise util.Abort(_('tag names must be unique'))
5582 for n in names:
5589 for n in names:
5583 scmutil.checknewlabel(repo, n, 'tag')
5590 scmutil.checknewlabel(repo, n, 'tag')
5584 if not n:
5591 if not n:
5585 raise util.Abort(_('tag names cannot consist entirely of '
5592 raise util.Abort(_('tag names cannot consist entirely of '
5586 'whitespace'))
5593 'whitespace'))
5587 if opts.get('rev') and opts.get('remove'):
5594 if opts.get('rev') and opts.get('remove'):
5588 raise util.Abort(_("--rev and --remove are incompatible"))
5595 raise util.Abort(_("--rev and --remove are incompatible"))
5589 if opts.get('rev'):
5596 if opts.get('rev'):
5590 rev_ = opts['rev']
5597 rev_ = opts['rev']
5591 message = opts.get('message')
5598 message = opts.get('message')
5592 if opts.get('remove'):
5599 if opts.get('remove'):
5593 expectedtype = opts.get('local') and 'local' or 'global'
5600 expectedtype = opts.get('local') and 'local' or 'global'
5594 for n in names:
5601 for n in names:
5595 if not repo.tagtype(n):
5602 if not repo.tagtype(n):
5596 raise util.Abort(_("tag '%s' does not exist") % n)
5603 raise util.Abort(_("tag '%s' does not exist") % n)
5597 if repo.tagtype(n) != expectedtype:
5604 if repo.tagtype(n) != expectedtype:
5598 if expectedtype == 'global':
5605 if expectedtype == 'global':
5599 raise util.Abort(_("tag '%s' is not a global tag") % n)
5606 raise util.Abort(_("tag '%s' is not a global tag") % n)
5600 else:
5607 else:
5601 raise util.Abort(_("tag '%s' is not a local tag") % n)
5608 raise util.Abort(_("tag '%s' is not a local tag") % n)
5602 rev_ = nullid
5609 rev_ = nullid
5603 if not message:
5610 if not message:
5604 # we don't translate commit messages
5611 # we don't translate commit messages
5605 message = 'Removed tag %s' % ', '.join(names)
5612 message = 'Removed tag %s' % ', '.join(names)
5606 elif not opts.get('force'):
5613 elif not opts.get('force'):
5607 for n in names:
5614 for n in names:
5608 if n in repo.tags():
5615 if n in repo.tags():
5609 raise util.Abort(_("tag '%s' already exists "
5616 raise util.Abort(_("tag '%s' already exists "
5610 "(use -f to force)") % n)
5617 "(use -f to force)") % n)
5611 if not opts.get('local'):
5618 if not opts.get('local'):
5612 p1, p2 = repo.dirstate.parents()
5619 p1, p2 = repo.dirstate.parents()
5613 if p2 != nullid:
5620 if p2 != nullid:
5614 raise util.Abort(_('uncommitted merge'))
5621 raise util.Abort(_('uncommitted merge'))
5615 bheads = repo.branchheads()
5622 bheads = repo.branchheads()
5616 if not opts.get('force') and bheads and p1 not in bheads:
5623 if not opts.get('force') and bheads and p1 not in bheads:
5617 raise util.Abort(_('not at a branch head (use -f to force)'))
5624 raise util.Abort(_('not at a branch head (use -f to force)'))
5618 r = scmutil.revsingle(repo, rev_).node()
5625 r = scmutil.revsingle(repo, rev_).node()
5619
5626
5620 if not message:
5627 if not message:
5621 # we don't translate commit messages
5628 # we don't translate commit messages
5622 message = ('Added tag %s for changeset %s' %
5629 message = ('Added tag %s for changeset %s' %
5623 (', '.join(names), short(r)))
5630 (', '.join(names), short(r)))
5624
5631
5625 date = opts.get('date')
5632 date = opts.get('date')
5626 if date:
5633 if date:
5627 date = util.parsedate(date)
5634 date = util.parsedate(date)
5628
5635
5629 if opts.get('edit'):
5636 if opts.get('edit'):
5630 message = ui.edit(message, ui.username())
5637 message = ui.edit(message, ui.username())
5631
5638
5632 # don't allow tagging the null rev
5639 # don't allow tagging the null rev
5633 if (not opts.get('remove') and
5640 if (not opts.get('remove') and
5634 scmutil.revsingle(repo, rev_).rev() == nullrev):
5641 scmutil.revsingle(repo, rev_).rev() == nullrev):
5635 raise util.Abort(_("cannot tag null revision"))
5642 raise util.Abort(_("cannot tag null revision"))
5636
5643
5637 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5644 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5638 finally:
5645 finally:
5639 release(lock, wlock)
5646 release(lock, wlock)
5640
5647
5641 @command('tags', [], '')
5648 @command('tags', [], '')
5642 def tags(ui, repo, **opts):
5649 def tags(ui, repo, **opts):
5643 """list repository tags
5650 """list repository tags
5644
5651
5645 This lists both regular and local tags. When the -v/--verbose
5652 This lists both regular and local tags. When the -v/--verbose
5646 switch is used, a third column "local" is printed for local tags.
5653 switch is used, a third column "local" is printed for local tags.
5647
5654
5648 Returns 0 on success.
5655 Returns 0 on success.
5649 """
5656 """
5650
5657
5651 fm = ui.formatter('tags', opts)
5658 fm = ui.formatter('tags', opts)
5652 hexfunc = ui.debugflag and hex or short
5659 hexfunc = ui.debugflag and hex or short
5653 tagtype = ""
5660 tagtype = ""
5654
5661
5655 for t, n in reversed(repo.tagslist()):
5662 for t, n in reversed(repo.tagslist()):
5656 hn = hexfunc(n)
5663 hn = hexfunc(n)
5657 label = 'tags.normal'
5664 label = 'tags.normal'
5658 tagtype = ''
5665 tagtype = ''
5659 if repo.tagtype(t) == 'local':
5666 if repo.tagtype(t) == 'local':
5660 label = 'tags.local'
5667 label = 'tags.local'
5661 tagtype = 'local'
5668 tagtype = 'local'
5662
5669
5663 fm.startitem()
5670 fm.startitem()
5664 fm.write('tag', '%s', t, label=label)
5671 fm.write('tag', '%s', t, label=label)
5665 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5672 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5666 fm.condwrite(not ui.quiet, 'rev id', fmt,
5673 fm.condwrite(not ui.quiet, 'rev id', fmt,
5667 repo.changelog.rev(n), hn, label=label)
5674 repo.changelog.rev(n), hn, label=label)
5668 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5675 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5669 tagtype, label=label)
5676 tagtype, label=label)
5670 fm.plain('\n')
5677 fm.plain('\n')
5671 fm.end()
5678 fm.end()
5672
5679
5673 @command('tip',
5680 @command('tip',
5674 [('p', 'patch', None, _('show patch')),
5681 [('p', 'patch', None, _('show patch')),
5675 ('g', 'git', None, _('use git extended diff format')),
5682 ('g', 'git', None, _('use git extended diff format')),
5676 ] + templateopts,
5683 ] + templateopts,
5677 _('[-p] [-g]'))
5684 _('[-p] [-g]'))
5678 def tip(ui, repo, **opts):
5685 def tip(ui, repo, **opts):
5679 """show the tip revision
5686 """show the tip revision
5680
5687
5681 The tip revision (usually just called the tip) is the changeset
5688 The tip revision (usually just called the tip) is the changeset
5682 most recently added to the repository (and therefore the most
5689 most recently added to the repository (and therefore the most
5683 recently changed head).
5690 recently changed head).
5684
5691
5685 If you have just made a commit, that commit will be the tip. If
5692 If you have just made a commit, that commit will be the tip. If
5686 you have just pulled changes from another repository, the tip of
5693 you have just pulled changes from another repository, the tip of
5687 that repository becomes the current tip. The "tip" tag is special
5694 that repository becomes the current tip. The "tip" tag is special
5688 and cannot be renamed or assigned to a different changeset.
5695 and cannot be renamed or assigned to a different changeset.
5689
5696
5690 Returns 0 on success.
5697 Returns 0 on success.
5691 """
5698 """
5692 displayer = cmdutil.show_changeset(ui, repo, opts)
5699 displayer = cmdutil.show_changeset(ui, repo, opts)
5693 displayer.show(repo['tip'])
5700 displayer.show(repo['tip'])
5694 displayer.close()
5701 displayer.close()
5695
5702
5696 @command('unbundle',
5703 @command('unbundle',
5697 [('u', 'update', None,
5704 [('u', 'update', None,
5698 _('update to new branch head if changesets were unbundled'))],
5705 _('update to new branch head if changesets were unbundled'))],
5699 _('[-u] FILE...'))
5706 _('[-u] FILE...'))
5700 def unbundle(ui, repo, fname1, *fnames, **opts):
5707 def unbundle(ui, repo, fname1, *fnames, **opts):
5701 """apply one or more changegroup files
5708 """apply one or more changegroup files
5702
5709
5703 Apply one or more compressed changegroup files generated by the
5710 Apply one or more compressed changegroup files generated by the
5704 bundle command.
5711 bundle command.
5705
5712
5706 Returns 0 on success, 1 if an update has unresolved files.
5713 Returns 0 on success, 1 if an update has unresolved files.
5707 """
5714 """
5708 fnames = (fname1,) + fnames
5715 fnames = (fname1,) + fnames
5709
5716
5710 lock = repo.lock()
5717 lock = repo.lock()
5711 wc = repo['.']
5718 wc = repo['.']
5712 try:
5719 try:
5713 for fname in fnames:
5720 for fname in fnames:
5714 f = hg.openpath(ui, fname)
5721 f = hg.openpath(ui, fname)
5715 gen = changegroup.readbundle(f, fname)
5722 gen = changegroup.readbundle(f, fname)
5716 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5723 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5717 finally:
5724 finally:
5718 lock.release()
5725 lock.release()
5719 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5726 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5720 return postincoming(ui, repo, modheads, opts.get('update'), None)
5727 return postincoming(ui, repo, modheads, opts.get('update'), None)
5721
5728
5722 @command('^update|up|checkout|co',
5729 @command('^update|up|checkout|co',
5723 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5730 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5724 ('c', 'check', None,
5731 ('c', 'check', None,
5725 _('update across branches if no uncommitted changes')),
5732 _('update across branches if no uncommitted changes')),
5726 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5733 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5727 ('r', 'rev', '', _('revision'), _('REV'))],
5734 ('r', 'rev', '', _('revision'), _('REV'))],
5728 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5735 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5729 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5736 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5730 """update working directory (or switch revisions)
5737 """update working directory (or switch revisions)
5731
5738
5732 Update the repository's working directory to the specified
5739 Update the repository's working directory to the specified
5733 changeset. If no changeset is specified, update to the tip of the
5740 changeset. If no changeset is specified, update to the tip of the
5734 current named branch and move the current bookmark (see :hg:`help
5741 current named branch and move the current bookmark (see :hg:`help
5735 bookmarks`).
5742 bookmarks`).
5736
5743
5737 Update sets the working directory's parent revision to the specified
5744 Update sets the working directory's parent revision to the specified
5738 changeset (see :hg:`help parents`).
5745 changeset (see :hg:`help parents`).
5739
5746
5740 If the changeset is not a descendant or ancestor of the working
5747 If the changeset is not a descendant or ancestor of the working
5741 directory's parent, the update is aborted. With the -c/--check
5748 directory's parent, the update is aborted. With the -c/--check
5742 option, the working directory is checked for uncommitted changes; if
5749 option, the working directory is checked for uncommitted changes; if
5743 none are found, the working directory is updated to the specified
5750 none are found, the working directory is updated to the specified
5744 changeset.
5751 changeset.
5745
5752
5746 .. container:: verbose
5753 .. container:: verbose
5747
5754
5748 The following rules apply when the working directory contains
5755 The following rules apply when the working directory contains
5749 uncommitted changes:
5756 uncommitted changes:
5750
5757
5751 1. If neither -c/--check nor -C/--clean is specified, and if
5758 1. If neither -c/--check nor -C/--clean is specified, and if
5752 the requested changeset is an ancestor or descendant of
5759 the requested changeset is an ancestor or descendant of
5753 the working directory's parent, the uncommitted changes
5760 the working directory's parent, the uncommitted changes
5754 are merged into the requested changeset and the merged
5761 are merged into the requested changeset and the merged
5755 result is left uncommitted. If the requested changeset is
5762 result is left uncommitted. If the requested changeset is
5756 not an ancestor or descendant (that is, it is on another
5763 not an ancestor or descendant (that is, it is on another
5757 branch), the update is aborted and the uncommitted changes
5764 branch), the update is aborted and the uncommitted changes
5758 are preserved.
5765 are preserved.
5759
5766
5760 2. With the -c/--check option, the update is aborted and the
5767 2. With the -c/--check option, the update is aborted and the
5761 uncommitted changes are preserved.
5768 uncommitted changes are preserved.
5762
5769
5763 3. With the -C/--clean option, uncommitted changes are discarded and
5770 3. With the -C/--clean option, uncommitted changes are discarded and
5764 the working directory is updated to the requested changeset.
5771 the working directory is updated to the requested changeset.
5765
5772
5766 To cancel an uncommitted merge (and lose your changes), use
5773 To cancel an uncommitted merge (and lose your changes), use
5767 :hg:`update --clean .`.
5774 :hg:`update --clean .`.
5768
5775
5769 Use null as the changeset to remove the working directory (like
5776 Use null as the changeset to remove the working directory (like
5770 :hg:`clone -U`).
5777 :hg:`clone -U`).
5771
5778
5772 If you want to revert just one file to an older revision, use
5779 If you want to revert just one file to an older revision, use
5773 :hg:`revert [-r REV] NAME`.
5780 :hg:`revert [-r REV] NAME`.
5774
5781
5775 See :hg:`help dates` for a list of formats valid for -d/--date.
5782 See :hg:`help dates` for a list of formats valid for -d/--date.
5776
5783
5777 Returns 0 on success, 1 if there are unresolved files.
5784 Returns 0 on success, 1 if there are unresolved files.
5778 """
5785 """
5779 if rev and node:
5786 if rev and node:
5780 raise util.Abort(_("please specify just one revision"))
5787 raise util.Abort(_("please specify just one revision"))
5781
5788
5782 if rev is None or rev == '':
5789 if rev is None or rev == '':
5783 rev = node
5790 rev = node
5784
5791
5785 # with no argument, we also move the current bookmark, if any
5792 # with no argument, we also move the current bookmark, if any
5786 movemarkfrom = None
5793 movemarkfrom = None
5787 if rev is None:
5794 if rev is None:
5788 curmark = repo._bookmarkcurrent
5795 curmark = repo._bookmarkcurrent
5789 if bookmarks.iscurrent(repo):
5796 if bookmarks.iscurrent(repo):
5790 movemarkfrom = repo['.'].node()
5797 movemarkfrom = repo['.'].node()
5791 elif curmark:
5798 elif curmark:
5792 ui.status(_("updating to active bookmark %s\n") % curmark)
5799 ui.status(_("updating to active bookmark %s\n") % curmark)
5793 rev = curmark
5800 rev = curmark
5794
5801
5795 # if we defined a bookmark, we have to remember the original bookmark name
5802 # if we defined a bookmark, we have to remember the original bookmark name
5796 brev = rev
5803 brev = rev
5797 rev = scmutil.revsingle(repo, rev, rev).rev()
5804 rev = scmutil.revsingle(repo, rev, rev).rev()
5798
5805
5799 if check and clean:
5806 if check and clean:
5800 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5807 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5801
5808
5802 if date:
5809 if date:
5803 if rev is not None:
5810 if rev is not None:
5804 raise util.Abort(_("you can't specify a revision and a date"))
5811 raise util.Abort(_("you can't specify a revision and a date"))
5805 rev = cmdutil.finddate(ui, repo, date)
5812 rev = cmdutil.finddate(ui, repo, date)
5806
5813
5807 if check:
5814 if check:
5808 c = repo[None]
5815 c = repo[None]
5809 if c.dirty(merge=False, branch=False, missing=True):
5816 if c.dirty(merge=False, branch=False, missing=True):
5810 raise util.Abort(_("uncommitted local changes"))
5817 raise util.Abort(_("uncommitted local changes"))
5811 if rev is None:
5818 if rev is None:
5812 rev = repo[repo[None].branch()].rev()
5819 rev = repo[repo[None].branch()].rev()
5813 mergemod._checkunknown(repo, repo[None], repo[rev])
5820 mergemod._checkunknown(repo, repo[None], repo[rev])
5814
5821
5815 if clean:
5822 if clean:
5816 ret = hg.clean(repo, rev)
5823 ret = hg.clean(repo, rev)
5817 else:
5824 else:
5818 ret = hg.update(repo, rev)
5825 ret = hg.update(repo, rev)
5819
5826
5820 if not ret and movemarkfrom:
5827 if not ret and movemarkfrom:
5821 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5828 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5822 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5829 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5823 elif brev in repo._bookmarks:
5830 elif brev in repo._bookmarks:
5824 bookmarks.setcurrent(repo, brev)
5831 bookmarks.setcurrent(repo, brev)
5825 elif brev:
5832 elif brev:
5826 bookmarks.unsetcurrent(repo)
5833 bookmarks.unsetcurrent(repo)
5827
5834
5828 return ret
5835 return ret
5829
5836
5830 @command('verify', [])
5837 @command('verify', [])
5831 def verify(ui, repo):
5838 def verify(ui, repo):
5832 """verify the integrity of the repository
5839 """verify the integrity of the repository
5833
5840
5834 Verify the integrity of the current repository.
5841 Verify the integrity of the current repository.
5835
5842
5836 This will perform an extensive check of the repository's
5843 This will perform an extensive check of the repository's
5837 integrity, validating the hashes and checksums of each entry in
5844 integrity, validating the hashes and checksums of each entry in
5838 the changelog, manifest, and tracked files, as well as the
5845 the changelog, manifest, and tracked files, as well as the
5839 integrity of their crosslinks and indices.
5846 integrity of their crosslinks and indices.
5840
5847
5841 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5848 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5842 for more information about recovery from corruption of the
5849 for more information about recovery from corruption of the
5843 repository.
5850 repository.
5844
5851
5845 Returns 0 on success, 1 if errors are encountered.
5852 Returns 0 on success, 1 if errors are encountered.
5846 """
5853 """
5847 return hg.verify(repo)
5854 return hg.verify(repo)
5848
5855
5849 @command('version', [])
5856 @command('version', [])
5850 def version_(ui):
5857 def version_(ui):
5851 """output version and copyright information"""
5858 """output version and copyright information"""
5852 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5859 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5853 % util.version())
5860 % util.version())
5854 ui.status(_(
5861 ui.status(_(
5855 "(see http://mercurial.selenic.com for more information)\n"
5862 "(see http://mercurial.selenic.com for more information)\n"
5856 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5863 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5857 "This is free software; see the source for copying conditions. "
5864 "This is free software; see the source for copying conditions. "
5858 "There is NO\nwarranty; "
5865 "There is NO\nwarranty; "
5859 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5866 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5860 ))
5867 ))
5861
5868
5862 norepo = ("clone init version help debugcommands debugcomplete"
5869 norepo = ("clone init version help debugcommands debugcomplete"
5863 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5870 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5864 " debugknown debuggetbundle debugbundle")
5871 " debugknown debuggetbundle debugbundle")
5865 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5872 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5866 " debugdata debugindex debugindexdot debugrevlog")
5873 " debugdata debugindex debugindexdot debugrevlog")
5867 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5874 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5868 " remove resolve status debugwalk")
5875 " remove resolve status debugwalk")
@@ -1,475 +1,473 b''
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo 'root' >root
3 $ echo 'root' >root
4 $ hg add root
4 $ hg add root
5 $ hg commit -d '0 0' -m "Adding root node"
5 $ hg commit -d '0 0' -m "Adding root node"
6
6
7 $ echo 'a' >a
7 $ echo 'a' >a
8 $ hg add a
8 $ hg add a
9 $ hg branch a
9 $ hg branch a
10 marked working directory as branch a
10 marked working directory as branch a
11 (branches are permanent and global, did you want a bookmark?)
11 (branches are permanent and global, did you want a bookmark?)
12 $ hg commit -d '1 0' -m "Adding a branch"
12 $ hg commit -d '1 0' -m "Adding a branch"
13
13
14 $ hg branch q
14 $ hg branch q
15 marked working directory as branch q
15 marked working directory as branch q
16 (branches are permanent and global, did you want a bookmark?)
16 (branches are permanent and global, did you want a bookmark?)
17 $ echo 'aa' >a
17 $ echo 'aa' >a
18 $ hg branch -C
18 $ hg branch -C
19 reset working directory to branch a
19 reset working directory to branch a
20 $ hg commit -d '2 0' -m "Adding to a branch"
20 $ hg commit -d '2 0' -m "Adding to a branch"
21
21
22 $ hg update -C 0
22 $ hg update -C 0
23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
24 $ echo 'b' >b
24 $ echo 'b' >b
25 $ hg add b
25 $ hg add b
26 $ hg branch b
26 $ hg branch b
27 marked working directory as branch b
27 marked working directory as branch b
28 (branches are permanent and global, did you want a bookmark?)
28 (branches are permanent and global, did you want a bookmark?)
29 $ hg commit -d '2 0' -m "Adding b branch"
29 $ hg commit -d '2 0' -m "Adding b branch"
30
30
31 $ echo 'bh1' >bh1
31 $ echo 'bh1' >bh1
32 $ hg add bh1
32 $ hg add bh1
33 $ hg commit -d '3 0' -m "Adding b branch head 1"
33 $ hg commit -d '3 0' -m "Adding b branch head 1"
34
34
35 $ hg update -C 2
35 $ hg update -C 2
36 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
36 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
37 $ echo 'bh2' >bh2
37 $ echo 'bh2' >bh2
38 $ hg add bh2
38 $ hg add bh2
39 $ hg commit -d '4 0' -m "Adding b branch head 2"
39 $ hg commit -d '4 0' -m "Adding b branch head 2"
40
40
41 $ echo 'c' >c
41 $ echo 'c' >c
42 $ hg add c
42 $ hg add c
43 $ hg branch c
43 $ hg branch c
44 marked working directory as branch c
44 marked working directory as branch c
45 (branches are permanent and global, did you want a bookmark?)
45 (branches are permanent and global, did you want a bookmark?)
46 $ hg commit -d '5 0' -m "Adding c branch"
46 $ hg commit -d '5 0' -m "Adding c branch"
47
47
48 reserved names
48 reserved names
49
49
50 $ hg branch tip
50 $ hg branch tip
51 abort: the name 'tip' is reserved
51 abort: the name 'tip' is reserved
52 [255]
52 [255]
53 $ hg branch null
53 $ hg branch null
54 abort: the name 'null' is reserved
54 abort: the name 'null' is reserved
55 [255]
55 [255]
56 $ hg branch .
56 $ hg branch .
57 abort: the name '.' is reserved
57 abort: the name '.' is reserved
58 [255]
58 [255]
59
59
60 invalid characters
60 invalid characters
61
61
62 $ hg branch 'foo:bar'
62 $ hg branch 'foo:bar'
63 abort: ':' cannot be used in a name
63 abort: ':' cannot be used in a name
64 [255]
64 [255]
65
65
66 $ hg branch 'foo
66 $ hg branch 'foo
67 > bar'
67 > bar'
68 abort: '\n' cannot be used in a name
68 abort: '\n' cannot be used in a name
69 [255]
69 [255]
70
70
71 trailing or leading spaces should be stripped before testing duplicates
71 trailing or leading spaces should be stripped before testing duplicates
72
72
73 $ hg branch 'b '
73 $ hg branch 'b '
74 abort: a branch of the same name already exists
74 abort: a branch of the same name already exists
75 (use 'hg update' to switch to it)
75 (use 'hg update' to switch to it)
76 [255]
76 [255]
77
77
78 $ hg branch ' b'
78 $ hg branch ' b'
79 abort: a branch of the same name already exists
79 abort: a branch of the same name already exists
80 (use 'hg update' to switch to it)
80 (use 'hg update' to switch to it)
81 [255]
81 [255]
82
82
83 verify update will accept invalid legacy branch names
83 verify update will accept invalid legacy branch names
84
84
85 $ hg init test-invalid-branch-name
85 $ hg init test-invalid-branch-name
86 $ cd test-invalid-branch-name
86 $ cd test-invalid-branch-name
87 $ hg pull -u "$TESTDIR"/bundles/test-invalid-branch-name.hg
87 $ hg pull -u "$TESTDIR"/bundles/test-invalid-branch-name.hg
88 pulling from *test-invalid-branch-name.hg (glob)
88 pulling from *test-invalid-branch-name.hg (glob)
89 requesting all changes
89 requesting all changes
90 adding changesets
90 adding changesets
91 adding manifests
91 adding manifests
92 adding file changes
92 adding file changes
93 added 3 changesets with 3 changes to 2 files
93 added 3 changesets with 3 changes to 2 files
94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
95
95
96 $ hg update '"colon:test"'
96 $ hg update '"colon:test"'
97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 $ cd ..
98 $ cd ..
99
99
100 $ echo 'd' >d
100 $ echo 'd' >d
101 $ hg add d
101 $ hg add d
102 $ hg branch 'a branch name much longer than the default justification used by branches'
102 $ hg branch 'a branch name much longer than the default justification used by branches'
103 marked working directory as branch a branch name much longer than the default justification used by branches
103 marked working directory as branch a branch name much longer than the default justification used by branches
104 (branches are permanent and global, did you want a bookmark?)
104 (branches are permanent and global, did you want a bookmark?)
105 $ hg commit -d '6 0' -m "Adding d branch"
105 $ hg commit -d '6 0' -m "Adding d branch"
106
106
107 $ hg branches
107 $ hg branches
108 a branch name much longer than the default justification used by branches 7:10ff5895aa57
108 a branch name much longer than the default justification used by branches 7:10ff5895aa57
109 b 4:aee39cd168d0
109 b 4:aee39cd168d0
110 c 6:589736a22561 (inactive)
110 c 6:589736a22561 (inactive)
111 a 5:d8cbc61dbaa6 (inactive)
111 a 5:d8cbc61dbaa6 (inactive)
112 default 0:19709c5a4e75 (inactive)
112 default 0:19709c5a4e75 (inactive)
113
113
114 -------
114 -------
115
115
116 $ hg branches -a
116 $ hg branches -a
117 a branch name much longer than the default justification used by branches 7:10ff5895aa57
117 a branch name much longer than the default justification used by branches 7:10ff5895aa57
118 b 4:aee39cd168d0
118 b 4:aee39cd168d0
119
119
120 --- Branch a
120 --- Branch a
121
121
122 $ hg log -b a
122 $ hg log -b a
123 changeset: 5:d8cbc61dbaa6
123 changeset: 5:d8cbc61dbaa6
124 branch: a
124 branch: a
125 parent: 2:881fe2b92ad0
125 parent: 2:881fe2b92ad0
126 user: test
126 user: test
127 date: Thu Jan 01 00:00:04 1970 +0000
127 date: Thu Jan 01 00:00:04 1970 +0000
128 summary: Adding b branch head 2
128 summary: Adding b branch head 2
129
129
130 changeset: 2:881fe2b92ad0
130 changeset: 2:881fe2b92ad0
131 branch: a
131 branch: a
132 user: test
132 user: test
133 date: Thu Jan 01 00:00:02 1970 +0000
133 date: Thu Jan 01 00:00:02 1970 +0000
134 summary: Adding to a branch
134 summary: Adding to a branch
135
135
136 changeset: 1:dd6b440dd85a
136 changeset: 1:dd6b440dd85a
137 branch: a
137 branch: a
138 user: test
138 user: test
139 date: Thu Jan 01 00:00:01 1970 +0000
139 date: Thu Jan 01 00:00:01 1970 +0000
140 summary: Adding a branch
140 summary: Adding a branch
141
141
142
142
143 ---- Branch b
143 ---- Branch b
144
144
145 $ hg log -b b
145 $ hg log -b b
146 changeset: 4:aee39cd168d0
146 changeset: 4:aee39cd168d0
147 branch: b
147 branch: b
148 user: test
148 user: test
149 date: Thu Jan 01 00:00:03 1970 +0000
149 date: Thu Jan 01 00:00:03 1970 +0000
150 summary: Adding b branch head 1
150 summary: Adding b branch head 1
151
151
152 changeset: 3:ac22033332d1
152 changeset: 3:ac22033332d1
153 branch: b
153 branch: b
154 parent: 0:19709c5a4e75
154 parent: 0:19709c5a4e75
155 user: test
155 user: test
156 date: Thu Jan 01 00:00:02 1970 +0000
156 date: Thu Jan 01 00:00:02 1970 +0000
157 summary: Adding b branch
157 summary: Adding b branch
158
158
159
159
160 ---- going to test branch closing
160 ---- going to test branch closing
161
161
162 $ hg branches
162 $ hg branches
163 a branch name much longer than the default justification used by branches 7:10ff5895aa57
163 a branch name much longer than the default justification used by branches 7:10ff5895aa57
164 b 4:aee39cd168d0
164 b 4:aee39cd168d0
165 c 6:589736a22561 (inactive)
165 c 6:589736a22561 (inactive)
166 a 5:d8cbc61dbaa6 (inactive)
166 a 5:d8cbc61dbaa6 (inactive)
167 default 0:19709c5a4e75 (inactive)
167 default 0:19709c5a4e75 (inactive)
168 $ hg up -C b
168 $ hg up -C b
169 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
169 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
170 $ echo 'xxx1' >> b
170 $ echo 'xxx1' >> b
171 $ hg commit -d '7 0' -m 'adding cset to branch b'
171 $ hg commit -d '7 0' -m 'adding cset to branch b'
172 $ hg up -C aee39cd168d0
172 $ hg up -C aee39cd168d0
173 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
173 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 $ echo 'xxx2' >> b
174 $ echo 'xxx2' >> b
175 $ hg commit -d '8 0' -m 'adding head to branch b'
175 $ hg commit -d '8 0' -m 'adding head to branch b'
176 created new head
176 created new head
177 $ echo 'xxx3' >> b
177 $ echo 'xxx3' >> b
178 $ hg commit -d '9 0' -m 'adding another cset to branch b'
178 $ hg commit -d '9 0' -m 'adding another cset to branch b'
179 $ hg branches
179 $ hg branches
180 b 10:bfbe841b666e
180 b 10:bfbe841b666e
181 a branch name much longer than the default justification used by branches 7:10ff5895aa57
181 a branch name much longer than the default justification used by branches 7:10ff5895aa57
182 c 6:589736a22561 (inactive)
182 c 6:589736a22561 (inactive)
183 a 5:d8cbc61dbaa6 (inactive)
183 a 5:d8cbc61dbaa6 (inactive)
184 default 0:19709c5a4e75 (inactive)
184 default 0:19709c5a4e75 (inactive)
185 $ hg heads --closed
185 $ hg heads --closed
186 changeset: 10:bfbe841b666e
186 changeset: 10:bfbe841b666e
187 branch: b
187 branch: b
188 tag: tip
188 tag: tip
189 user: test
189 user: test
190 date: Thu Jan 01 00:00:09 1970 +0000
190 date: Thu Jan 01 00:00:09 1970 +0000
191 summary: adding another cset to branch b
191 summary: adding another cset to branch b
192
192
193 changeset: 8:eebb944467c9
193 changeset: 8:eebb944467c9
194 branch: b
194 branch: b
195 parent: 4:aee39cd168d0
195 parent: 4:aee39cd168d0
196 user: test
196 user: test
197 date: Thu Jan 01 00:00:07 1970 +0000
197 date: Thu Jan 01 00:00:07 1970 +0000
198 summary: adding cset to branch b
198 summary: adding cset to branch b
199
199
200 changeset: 7:10ff5895aa57
200 changeset: 7:10ff5895aa57
201 branch: a branch name much longer than the default justification used by branches
201 branch: a branch name much longer than the default justification used by branches
202 user: test
202 user: test
203 date: Thu Jan 01 00:00:06 1970 +0000
203 date: Thu Jan 01 00:00:06 1970 +0000
204 summary: Adding d branch
204 summary: Adding d branch
205
205
206 changeset: 6:589736a22561
206 changeset: 6:589736a22561
207 branch: c
207 branch: c
208 user: test
208 user: test
209 date: Thu Jan 01 00:00:05 1970 +0000
209 date: Thu Jan 01 00:00:05 1970 +0000
210 summary: Adding c branch
210 summary: Adding c branch
211
211
212 changeset: 5:d8cbc61dbaa6
212 changeset: 5:d8cbc61dbaa6
213 branch: a
213 branch: a
214 parent: 2:881fe2b92ad0
214 parent: 2:881fe2b92ad0
215 user: test
215 user: test
216 date: Thu Jan 01 00:00:04 1970 +0000
216 date: Thu Jan 01 00:00:04 1970 +0000
217 summary: Adding b branch head 2
217 summary: Adding b branch head 2
218
218
219 changeset: 0:19709c5a4e75
219 changeset: 0:19709c5a4e75
220 user: test
220 user: test
221 date: Thu Jan 01 00:00:00 1970 +0000
221 date: Thu Jan 01 00:00:00 1970 +0000
222 summary: Adding root node
222 summary: Adding root node
223
223
224 $ hg heads
224 $ hg heads
225 changeset: 10:bfbe841b666e
225 changeset: 10:bfbe841b666e
226 branch: b
226 branch: b
227 tag: tip
227 tag: tip
228 user: test
228 user: test
229 date: Thu Jan 01 00:00:09 1970 +0000
229 date: Thu Jan 01 00:00:09 1970 +0000
230 summary: adding another cset to branch b
230 summary: adding another cset to branch b
231
231
232 changeset: 8:eebb944467c9
232 changeset: 8:eebb944467c9
233 branch: b
233 branch: b
234 parent: 4:aee39cd168d0
234 parent: 4:aee39cd168d0
235 user: test
235 user: test
236 date: Thu Jan 01 00:00:07 1970 +0000
236 date: Thu Jan 01 00:00:07 1970 +0000
237 summary: adding cset to branch b
237 summary: adding cset to branch b
238
238
239 changeset: 7:10ff5895aa57
239 changeset: 7:10ff5895aa57
240 branch: a branch name much longer than the default justification used by branches
240 branch: a branch name much longer than the default justification used by branches
241 user: test
241 user: test
242 date: Thu Jan 01 00:00:06 1970 +0000
242 date: Thu Jan 01 00:00:06 1970 +0000
243 summary: Adding d branch
243 summary: Adding d branch
244
244
245 changeset: 6:589736a22561
245 changeset: 6:589736a22561
246 branch: c
246 branch: c
247 user: test
247 user: test
248 date: Thu Jan 01 00:00:05 1970 +0000
248 date: Thu Jan 01 00:00:05 1970 +0000
249 summary: Adding c branch
249 summary: Adding c branch
250
250
251 changeset: 5:d8cbc61dbaa6
251 changeset: 5:d8cbc61dbaa6
252 branch: a
252 branch: a
253 parent: 2:881fe2b92ad0
253 parent: 2:881fe2b92ad0
254 user: test
254 user: test
255 date: Thu Jan 01 00:00:04 1970 +0000
255 date: Thu Jan 01 00:00:04 1970 +0000
256 summary: Adding b branch head 2
256 summary: Adding b branch head 2
257
257
258 changeset: 0:19709c5a4e75
258 changeset: 0:19709c5a4e75
259 user: test
259 user: test
260 date: Thu Jan 01 00:00:00 1970 +0000
260 date: Thu Jan 01 00:00:00 1970 +0000
261 summary: Adding root node
261 summary: Adding root node
262
262
263 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
263 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
264 $ hg branches -a
264 $ hg branches -a
265 b 8:eebb944467c9
265 b 8:eebb944467c9
266 a branch name much longer than the default justification used by branches 7:10ff5895aa57
266 a branch name much longer than the default justification used by branches 7:10ff5895aa57
267 $ hg up -C b
267 $ hg up -C b
268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
269 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
270 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
271 abort: can only close branch heads
272 [255]
270
273
271 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
272 $ hg log -r tip --debug
274 $ hg log -r tip --debug
273 changeset: 13:c2601d54b1427e99506bee25a566ef3a5963af0b
275 changeset: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
274 branch: b
276 branch: b
275 tag: tip
277 tag: tip
276 phase: draft
278 phase: draft
277 parent: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
279 parent: 8:eebb944467c9fb9651ed232aeaf31b3c0a7fc6c1
278 parent: -1:0000000000000000000000000000000000000000
280 parent: -1:0000000000000000000000000000000000000000
279 manifest: 8:6f9ed32d2b310e391a4f107d5f0f071df785bfee
281 manifest: 8:6f9ed32d2b310e391a4f107d5f0f071df785bfee
280 user: test
282 user: test
281 date: Thu Jan 01 00:00:09 1970 +0000
283 date: Thu Jan 01 00:00:09 1970 +0000
282 extra: branch=b
284 extra: branch=b
283 extra: close=1
285 extra: close=1
284 description:
286 description:
285 re-closing this branch
287 close this part branch too
286
287
288
288 $ hg rollback
289 repository tip rolled back to revision 12 (undo commit)
290 working directory now based on revision 12
291
289
292 --- b branch should be inactive
290 --- b branch should be inactive
293
291
294 $ hg branches
292 $ hg branches
295 a branch name much longer than the default justification used by branches 7:10ff5895aa57
293 a branch name much longer than the default justification used by branches 7:10ff5895aa57
296 c 6:589736a22561 (inactive)
294 c 6:589736a22561 (inactive)
297 a 5:d8cbc61dbaa6 (inactive)
295 a 5:d8cbc61dbaa6 (inactive)
298 default 0:19709c5a4e75 (inactive)
296 default 0:19709c5a4e75 (inactive)
299 $ hg branches -c
297 $ hg branches -c
300 a branch name much longer than the default justification used by branches 7:10ff5895aa57
298 a branch name much longer than the default justification used by branches 7:10ff5895aa57
301 b 12:e3d49c0575d8 (closed)
299 b 12:e3d49c0575d8 (closed)
302 c 6:589736a22561 (inactive)
300 c 6:589736a22561 (inactive)
303 a 5:d8cbc61dbaa6 (inactive)
301 a 5:d8cbc61dbaa6 (inactive)
304 default 0:19709c5a4e75 (inactive)
302 default 0:19709c5a4e75 (inactive)
305 $ hg branches -a
303 $ hg branches -a
306 a branch name much longer than the default justification used by branches 7:10ff5895aa57
304 a branch name much longer than the default justification used by branches 7:10ff5895aa57
307 $ hg branches -q
305 $ hg branches -q
308 a branch name much longer than the default justification used by branches
306 a branch name much longer than the default justification used by branches
309 c
307 c
310 a
308 a
311 default
309 default
312 $ hg heads b
310 $ hg heads b
313 no open branch heads found on branches b
311 no open branch heads found on branches b
314 [1]
312 [1]
315 $ hg heads --closed b
313 $ hg heads --closed b
316 changeset: 12:e3d49c0575d8
314 changeset: 12:e3d49c0575d8
317 branch: b
315 branch: b
318 tag: tip
316 tag: tip
319 parent: 8:eebb944467c9
317 parent: 8:eebb944467c9
320 user: test
318 user: test
321 date: Thu Jan 01 00:00:09 1970 +0000
319 date: Thu Jan 01 00:00:09 1970 +0000
322 summary: close this part branch too
320 summary: close this part branch too
323
321
324 changeset: 11:d3f163457ebf
322 changeset: 11:d3f163457ebf
325 branch: b
323 branch: b
326 user: test
324 user: test
327 date: Thu Jan 01 00:00:09 1970 +0000
325 date: Thu Jan 01 00:00:09 1970 +0000
328 summary: prune bad branch
326 summary: prune bad branch
329
327
330 $ echo 'xxx4' >> b
328 $ echo 'xxx4' >> b
331 $ hg commit -d '9 0' -m 'reopen branch with a change'
329 $ hg commit -d '9 0' -m 'reopen branch with a change'
332 reopening closed branch head 12
330 reopening closed branch head 12
333
331
334 --- branch b is back in action
332 --- branch b is back in action
335
333
336 $ hg branches -a
334 $ hg branches -a
337 b 13:e23b5505d1ad
335 b 13:e23b5505d1ad
338 a branch name much longer than the default justification used by branches 7:10ff5895aa57
336 a branch name much longer than the default justification used by branches 7:10ff5895aa57
339
337
340 ---- test heads listings
338 ---- test heads listings
341
339
342 $ hg heads
340 $ hg heads
343 changeset: 13:e23b5505d1ad
341 changeset: 13:e23b5505d1ad
344 branch: b
342 branch: b
345 tag: tip
343 tag: tip
346 user: test
344 user: test
347 date: Thu Jan 01 00:00:09 1970 +0000
345 date: Thu Jan 01 00:00:09 1970 +0000
348 summary: reopen branch with a change
346 summary: reopen branch with a change
349
347
350 changeset: 7:10ff5895aa57
348 changeset: 7:10ff5895aa57
351 branch: a branch name much longer than the default justification used by branches
349 branch: a branch name much longer than the default justification used by branches
352 user: test
350 user: test
353 date: Thu Jan 01 00:00:06 1970 +0000
351 date: Thu Jan 01 00:00:06 1970 +0000
354 summary: Adding d branch
352 summary: Adding d branch
355
353
356 changeset: 6:589736a22561
354 changeset: 6:589736a22561
357 branch: c
355 branch: c
358 user: test
356 user: test
359 date: Thu Jan 01 00:00:05 1970 +0000
357 date: Thu Jan 01 00:00:05 1970 +0000
360 summary: Adding c branch
358 summary: Adding c branch
361
359
362 changeset: 5:d8cbc61dbaa6
360 changeset: 5:d8cbc61dbaa6
363 branch: a
361 branch: a
364 parent: 2:881fe2b92ad0
362 parent: 2:881fe2b92ad0
365 user: test
363 user: test
366 date: Thu Jan 01 00:00:04 1970 +0000
364 date: Thu Jan 01 00:00:04 1970 +0000
367 summary: Adding b branch head 2
365 summary: Adding b branch head 2
368
366
369 changeset: 0:19709c5a4e75
367 changeset: 0:19709c5a4e75
370 user: test
368 user: test
371 date: Thu Jan 01 00:00:00 1970 +0000
369 date: Thu Jan 01 00:00:00 1970 +0000
372 summary: Adding root node
370 summary: Adding root node
373
371
374
372
375 branch default
373 branch default
376
374
377 $ hg heads default
375 $ hg heads default
378 changeset: 0:19709c5a4e75
376 changeset: 0:19709c5a4e75
379 user: test
377 user: test
380 date: Thu Jan 01 00:00:00 1970 +0000
378 date: Thu Jan 01 00:00:00 1970 +0000
381 summary: Adding root node
379 summary: Adding root node
382
380
383
381
384 branch a
382 branch a
385
383
386 $ hg heads a
384 $ hg heads a
387 changeset: 5:d8cbc61dbaa6
385 changeset: 5:d8cbc61dbaa6
388 branch: a
386 branch: a
389 parent: 2:881fe2b92ad0
387 parent: 2:881fe2b92ad0
390 user: test
388 user: test
391 date: Thu Jan 01 00:00:04 1970 +0000
389 date: Thu Jan 01 00:00:04 1970 +0000
392 summary: Adding b branch head 2
390 summary: Adding b branch head 2
393
391
394 $ hg heads --active a
392 $ hg heads --active a
395 no open branch heads found on branches a
393 no open branch heads found on branches a
396 [1]
394 [1]
397
395
398 branch b
396 branch b
399
397
400 $ hg heads b
398 $ hg heads b
401 changeset: 13:e23b5505d1ad
399 changeset: 13:e23b5505d1ad
402 branch: b
400 branch: b
403 tag: tip
401 tag: tip
404 user: test
402 user: test
405 date: Thu Jan 01 00:00:09 1970 +0000
403 date: Thu Jan 01 00:00:09 1970 +0000
406 summary: reopen branch with a change
404 summary: reopen branch with a change
407
405
408 $ hg heads --closed b
406 $ hg heads --closed b
409 changeset: 13:e23b5505d1ad
407 changeset: 13:e23b5505d1ad
410 branch: b
408 branch: b
411 tag: tip
409 tag: tip
412 user: test
410 user: test
413 date: Thu Jan 01 00:00:09 1970 +0000
411 date: Thu Jan 01 00:00:09 1970 +0000
414 summary: reopen branch with a change
412 summary: reopen branch with a change
415
413
416 changeset: 11:d3f163457ebf
414 changeset: 11:d3f163457ebf
417 branch: b
415 branch: b
418 user: test
416 user: test
419 date: Thu Jan 01 00:00:09 1970 +0000
417 date: Thu Jan 01 00:00:09 1970 +0000
420 summary: prune bad branch
418 summary: prune bad branch
421
419
422 default branch colors:
420 default branch colors:
423
421
424 $ echo "[extensions]" >> $HGRCPATH
422 $ echo "[extensions]" >> $HGRCPATH
425 $ echo "color =" >> $HGRCPATH
423 $ echo "color =" >> $HGRCPATH
426 $ echo "[color]" >> $HGRCPATH
424 $ echo "[color]" >> $HGRCPATH
427 $ echo "mode = ansi" >> $HGRCPATH
425 $ echo "mode = ansi" >> $HGRCPATH
428
426
429 $ hg up -C c
427 $ hg up -C c
430 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
428 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
431 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
429 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
432 $ hg up -C b
430 $ hg up -C b
433 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
431 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
434 $ hg branches --color=always
432 $ hg branches --color=always
435 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
433 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
436 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
434 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
437 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
435 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
438 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
436 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
439
437
440 default closed branch color:
438 default closed branch color:
441
439
442 $ hg branches --color=always --closed
440 $ hg branches --color=always --closed
443 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
441 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
444 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
442 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
445 \x1b[0;30;1mc\x1b[0m \x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
443 \x1b[0;30;1mc\x1b[0m \x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
446 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
444 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
447 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
445 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
448
446
449 $ echo "[extensions]" >> $HGRCPATH
447 $ echo "[extensions]" >> $HGRCPATH
450 $ echo "color =" >> $HGRCPATH
448 $ echo "color =" >> $HGRCPATH
451 $ echo "[color]" >> $HGRCPATH
449 $ echo "[color]" >> $HGRCPATH
452 $ echo "branches.active = green" >> $HGRCPATH
450 $ echo "branches.active = green" >> $HGRCPATH
453 $ echo "branches.closed = blue" >> $HGRCPATH
451 $ echo "branches.closed = blue" >> $HGRCPATH
454 $ echo "branches.current = red" >> $HGRCPATH
452 $ echo "branches.current = red" >> $HGRCPATH
455 $ echo "branches.inactive = magenta" >> $HGRCPATH
453 $ echo "branches.inactive = magenta" >> $HGRCPATH
456 $ echo "log.changeset = cyan" >> $HGRCPATH
454 $ echo "log.changeset = cyan" >> $HGRCPATH
457
455
458 custom branch colors:
456 custom branch colors:
459
457
460 $ hg branches --color=always
458 $ hg branches --color=always
461 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
459 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
462 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
460 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
463 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
461 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
464 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
462 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
465
463
466 custom closed branch color:
464 custom closed branch color:
467
465
468 $ hg branches --color=always --closed
466 $ hg branches --color=always --closed
469 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
467 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
470 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
468 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
471 \x1b[0;34mc\x1b[0m \x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
469 \x1b[0;34mc\x1b[0m \x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
472 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
470 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
473 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
471 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
474
472
475 $ cd ..
473 $ cd ..
@@ -1,745 +1,769 b''
1 $ hg init
1 $ hg init
2
2
3 Setup:
3 Setup:
4
4
5 $ echo a >> a
5 $ echo a >> a
6 $ hg ci -Am 'base'
6 $ hg ci -Am 'base'
7 adding a
7 adding a
8
8
9 Refuse to amend public csets:
9 Refuse to amend public csets:
10
10
11 $ hg phase -r . -p
11 $ hg phase -r . -p
12 $ hg ci --amend
12 $ hg ci --amend
13 abort: cannot amend public changesets
13 abort: cannot amend public changesets
14 [255]
14 [255]
15 $ hg phase -r . -f -d
15 $ hg phase -r . -f -d
16
16
17 $ echo a >> a
17 $ echo a >> a
18 $ hg ci -Am 'base1'
18 $ hg ci -Am 'base1'
19
19
20 Nothing to amend:
20 Nothing to amend:
21
21
22 $ hg ci --amend
22 $ hg ci --amend
23 nothing changed
23 nothing changed
24 [1]
24 [1]
25
25
26 $ cat >> $HGRCPATH <<EOF
26 $ cat >> $HGRCPATH <<EOF
27 > [hooks]
27 > [hooks]
28 > pretxncommit.foo = sh -c "echo \\"pretxncommit \$HG_NODE\\"; hg id -r \$HG_NODE"
28 > pretxncommit.foo = sh -c "echo \\"pretxncommit \$HG_NODE\\"; hg id -r \$HG_NODE"
29 > EOF
29 > EOF
30
30
31 Amending changeset with changes in working dir:
31 Amending changeset with changes in working dir:
32 (and check that --message does not trigger an editor)
32 (and check that --message does not trigger an editor)
33
33
34 $ echo a >> a
34 $ echo a >> a
35 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -m 'amend base1'
35 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -m 'amend base1'
36 pretxncommit 43f1ba15f28a50abf0aae529cf8a16bfced7b149
36 pretxncommit 43f1ba15f28a50abf0aae529cf8a16bfced7b149
37 43f1ba15f28a tip
37 43f1ba15f28a tip
38 saved backup bundle to $TESTTMP/.hg/strip-backup/489edb5b847d-amend-backup.hg (glob)
38 saved backup bundle to $TESTTMP/.hg/strip-backup/489edb5b847d-amend-backup.hg (glob)
39 $ echo 'pretxncommit.foo = ' >> $HGRCPATH
39 $ echo 'pretxncommit.foo = ' >> $HGRCPATH
40 $ hg diff -c .
40 $ hg diff -c .
41 diff -r ad120869acf0 -r 43f1ba15f28a a
41 diff -r ad120869acf0 -r 43f1ba15f28a a
42 --- a/a Thu Jan 01 00:00:00 1970 +0000
42 --- a/a Thu Jan 01 00:00:00 1970 +0000
43 +++ b/a Thu Jan 01 00:00:00 1970 +0000
43 +++ b/a Thu Jan 01 00:00:00 1970 +0000
44 @@ -1,1 +1,3 @@
44 @@ -1,1 +1,3 @@
45 a
45 a
46 +a
46 +a
47 +a
47 +a
48 $ hg log
48 $ hg log
49 changeset: 1:43f1ba15f28a
49 changeset: 1:43f1ba15f28a
50 tag: tip
50 tag: tip
51 user: test
51 user: test
52 date: Thu Jan 01 00:00:00 1970 +0000
52 date: Thu Jan 01 00:00:00 1970 +0000
53 summary: amend base1
53 summary: amend base1
54
54
55 changeset: 0:ad120869acf0
55 changeset: 0:ad120869acf0
56 user: test
56 user: test
57 date: Thu Jan 01 00:00:00 1970 +0000
57 date: Thu Jan 01 00:00:00 1970 +0000
58 summary: base
58 summary: base
59
59
60
60
61 Check proper abort for empty message
61 Check proper abort for empty message
62
62
63 $ cat > editor.sh << '__EOF__'
63 $ cat > editor.sh << '__EOF__'
64 > #!/bin/sh
64 > #!/bin/sh
65 > echo "" > "$1"
65 > echo "" > "$1"
66 > __EOF__
66 > __EOF__
67 $ echo b > b
67 $ echo b > b
68 $ hg add b
68 $ hg add b
69 $ hg summary
69 $ hg summary
70 parent: 1:43f1ba15f28a tip
70 parent: 1:43f1ba15f28a tip
71 amend base1
71 amend base1
72 branch: default
72 branch: default
73 commit: 1 added, 1 unknown
73 commit: 1 added, 1 unknown
74 update: (current)
74 update: (current)
75 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
75 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
76 transaction abort!
76 transaction abort!
77 rollback completed
77 rollback completed
78 abort: empty commit message
78 abort: empty commit message
79 [255]
79 [255]
80 $ hg summary
80 $ hg summary
81 parent: 1:43f1ba15f28a tip
81 parent: 1:43f1ba15f28a tip
82 amend base1
82 amend base1
83 branch: default
83 branch: default
84 commit: 1 added, 1 unknown
84 commit: 1 added, 1 unknown
85 update: (current)
85 update: (current)
86
86
87 Add new file:
87 Add new file:
88 $ hg ci --amend -m 'amend base1 new file'
88 $ hg ci --amend -m 'amend base1 new file'
89 saved backup bundle to $TESTTMP/.hg/strip-backup/43f1ba15f28a-amend-backup.hg (glob)
89 saved backup bundle to $TESTTMP/.hg/strip-backup/43f1ba15f28a-amend-backup.hg (glob)
90
90
91 Remove file that was added in amended commit:
91 Remove file that was added in amended commit:
92 (and test logfile option)
92 (and test logfile option)
93 (and test that logfile option do not trigger an editor)
93 (and test that logfile option do not trigger an editor)
94
94
95 $ hg rm b
95 $ hg rm b
96 $ echo 'amend base1 remove new file' > ../logfile
96 $ echo 'amend base1 remove new file' > ../logfile
97 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg ci --amend --logfile ../logfile
97 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg ci --amend --logfile ../logfile
98 saved backup bundle to $TESTTMP/.hg/strip-backup/b8e3cb2b3882-amend-backup.hg (glob)
98 saved backup bundle to $TESTTMP/.hg/strip-backup/b8e3cb2b3882-amend-backup.hg (glob)
99
99
100 $ hg cat b
100 $ hg cat b
101 b: no such file in rev 74609c7f506e
101 b: no such file in rev 74609c7f506e
102 [1]
102 [1]
103
103
104 No changes, just a different message:
104 No changes, just a different message:
105
105
106 $ hg ci -v --amend -m 'no changes, new message'
106 $ hg ci -v --amend -m 'no changes, new message'
107 amending changeset 74609c7f506e
107 amending changeset 74609c7f506e
108 copying changeset 74609c7f506e to ad120869acf0
108 copying changeset 74609c7f506e to ad120869acf0
109 a
109 a
110 stripping amended changeset 74609c7f506e
110 stripping amended changeset 74609c7f506e
111 1 changesets found
111 1 changesets found
112 saved backup bundle to $TESTTMP/.hg/strip-backup/74609c7f506e-amend-backup.hg (glob)
112 saved backup bundle to $TESTTMP/.hg/strip-backup/74609c7f506e-amend-backup.hg (glob)
113 1 changesets found
113 1 changesets found
114 adding branch
114 adding branch
115 adding changesets
115 adding changesets
116 adding manifests
116 adding manifests
117 adding file changes
117 adding file changes
118 added 1 changesets with 1 changes to 1 files
118 added 1 changesets with 1 changes to 1 files
119 committed changeset 1:1cd866679df8
119 committed changeset 1:1cd866679df8
120 $ hg diff -c .
120 $ hg diff -c .
121 diff -r ad120869acf0 -r 1cd866679df8 a
121 diff -r ad120869acf0 -r 1cd866679df8 a
122 --- a/a Thu Jan 01 00:00:00 1970 +0000
122 --- a/a Thu Jan 01 00:00:00 1970 +0000
123 +++ b/a Thu Jan 01 00:00:00 1970 +0000
123 +++ b/a Thu Jan 01 00:00:00 1970 +0000
124 @@ -1,1 +1,3 @@
124 @@ -1,1 +1,3 @@
125 a
125 a
126 +a
126 +a
127 +a
127 +a
128 $ hg log
128 $ hg log
129 changeset: 1:1cd866679df8
129 changeset: 1:1cd866679df8
130 tag: tip
130 tag: tip
131 user: test
131 user: test
132 date: Thu Jan 01 00:00:00 1970 +0000
132 date: Thu Jan 01 00:00:00 1970 +0000
133 summary: no changes, new message
133 summary: no changes, new message
134
134
135 changeset: 0:ad120869acf0
135 changeset: 0:ad120869acf0
136 user: test
136 user: test
137 date: Thu Jan 01 00:00:00 1970 +0000
137 date: Thu Jan 01 00:00:00 1970 +0000
138 summary: base
138 summary: base
139
139
140
140
141 Disable default date on commit so when -d isn't given, the old date is preserved:
141 Disable default date on commit so when -d isn't given, the old date is preserved:
142
142
143 $ echo '[defaults]' >> $HGRCPATH
143 $ echo '[defaults]' >> $HGRCPATH
144 $ echo 'commit=' >> $HGRCPATH
144 $ echo 'commit=' >> $HGRCPATH
145
145
146 Test -u/-d:
146 Test -u/-d:
147
147
148 $ hg ci --amend -u foo -d '1 0'
148 $ hg ci --amend -u foo -d '1 0'
149 saved backup bundle to $TESTTMP/.hg/strip-backup/1cd866679df8-amend-backup.hg (glob)
149 saved backup bundle to $TESTTMP/.hg/strip-backup/1cd866679df8-amend-backup.hg (glob)
150 $ echo a >> a
150 $ echo a >> a
151 $ hg ci --amend -u foo -d '1 0'
151 $ hg ci --amend -u foo -d '1 0'
152 saved backup bundle to $TESTTMP/.hg/strip-backup/780e6f23e03d-amend-backup.hg (glob)
152 saved backup bundle to $TESTTMP/.hg/strip-backup/780e6f23e03d-amend-backup.hg (glob)
153 $ hg log -r .
153 $ hg log -r .
154 changeset: 1:5f357c7560ab
154 changeset: 1:5f357c7560ab
155 tag: tip
155 tag: tip
156 user: foo
156 user: foo
157 date: Thu Jan 01 00:00:01 1970 +0000
157 date: Thu Jan 01 00:00:01 1970 +0000
158 summary: no changes, new message
158 summary: no changes, new message
159
159
160
160
161 Open editor with old commit message if a message isn't given otherwise:
161 Open editor with old commit message if a message isn't given otherwise:
162
162
163 $ cat > editor.sh << '__EOF__'
163 $ cat > editor.sh << '__EOF__'
164 > #!/bin/sh
164 > #!/bin/sh
165 > cat $1
165 > cat $1
166 > echo "another precious commit message" > "$1"
166 > echo "another precious commit message" > "$1"
167 > __EOF__
167 > __EOF__
168 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
168 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
169 amending changeset 5f357c7560ab
169 amending changeset 5f357c7560ab
170 copying changeset 5f357c7560ab to ad120869acf0
170 copying changeset 5f357c7560ab to ad120869acf0
171 no changes, new message
171 no changes, new message
172
172
173
173
174 HG: Enter commit message. Lines beginning with 'HG:' are removed.
174 HG: Enter commit message. Lines beginning with 'HG:' are removed.
175 HG: Leave message empty to abort commit.
175 HG: Leave message empty to abort commit.
176 HG: --
176 HG: --
177 HG: user: foo
177 HG: user: foo
178 HG: branch 'default'
178 HG: branch 'default'
179 HG: changed a
179 HG: changed a
180 a
180 a
181 stripping amended changeset 5f357c7560ab
181 stripping amended changeset 5f357c7560ab
182 1 changesets found
182 1 changesets found
183 saved backup bundle to $TESTTMP/.hg/strip-backup/5f357c7560ab-amend-backup.hg (glob)
183 saved backup bundle to $TESTTMP/.hg/strip-backup/5f357c7560ab-amend-backup.hg (glob)
184 1 changesets found
184 1 changesets found
185 adding branch
185 adding branch
186 adding changesets
186 adding changesets
187 adding manifests
187 adding manifests
188 adding file changes
188 adding file changes
189 added 1 changesets with 1 changes to 1 files
189 added 1 changesets with 1 changes to 1 files
190 committed changeset 1:7ab3bf440b54
190 committed changeset 1:7ab3bf440b54
191
191
192 Same, but with changes in working dir (different code path):
192 Same, but with changes in working dir (different code path):
193
193
194 $ echo a >> a
194 $ echo a >> a
195 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
195 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend -v
196 amending changeset 7ab3bf440b54
196 amending changeset 7ab3bf440b54
197 a
197 a
198 copying changeset a0ea9b1a4c8c to ad120869acf0
198 copying changeset a0ea9b1a4c8c to ad120869acf0
199 another precious commit message
199 another precious commit message
200
200
201
201
202 HG: Enter commit message. Lines beginning with 'HG:' are removed.
202 HG: Enter commit message. Lines beginning with 'HG:' are removed.
203 HG: Leave message empty to abort commit.
203 HG: Leave message empty to abort commit.
204 HG: --
204 HG: --
205 HG: user: foo
205 HG: user: foo
206 HG: branch 'default'
206 HG: branch 'default'
207 HG: changed a
207 HG: changed a
208 a
208 a
209 stripping intermediate changeset a0ea9b1a4c8c
209 stripping intermediate changeset a0ea9b1a4c8c
210 stripping amended changeset 7ab3bf440b54
210 stripping amended changeset 7ab3bf440b54
211 2 changesets found
211 2 changesets found
212 saved backup bundle to $TESTTMP/.hg/strip-backup/7ab3bf440b54-amend-backup.hg (glob)
212 saved backup bundle to $TESTTMP/.hg/strip-backup/7ab3bf440b54-amend-backup.hg (glob)
213 1 changesets found
213 1 changesets found
214 adding branch
214 adding branch
215 adding changesets
215 adding changesets
216 adding manifests
216 adding manifests
217 adding file changes
217 adding file changes
218 added 1 changesets with 1 changes to 1 files
218 added 1 changesets with 1 changes to 1 files
219 committed changeset 1:ea22a388757c
219 committed changeset 1:ea22a388757c
220
220
221 $ rm editor.sh
221 $ rm editor.sh
222 $ hg log -r .
222 $ hg log -r .
223 changeset: 1:ea22a388757c
223 changeset: 1:ea22a388757c
224 tag: tip
224 tag: tip
225 user: foo
225 user: foo
226 date: Thu Jan 01 00:00:01 1970 +0000
226 date: Thu Jan 01 00:00:01 1970 +0000
227 summary: another precious commit message
227 summary: another precious commit message
228
228
229
229
230 Moving bookmarks, preserve active bookmark:
230 Moving bookmarks, preserve active bookmark:
231
231
232 $ hg book book1
232 $ hg book book1
233 $ hg book book2
233 $ hg book book2
234 $ hg ci --amend -m 'move bookmarks'
234 $ hg ci --amend -m 'move bookmarks'
235 saved backup bundle to $TESTTMP/.hg/strip-backup/ea22a388757c-amend-backup.hg (glob)
235 saved backup bundle to $TESTTMP/.hg/strip-backup/ea22a388757c-amend-backup.hg (glob)
236 $ hg book
236 $ hg book
237 book1 1:6cec5aa930e2
237 book1 1:6cec5aa930e2
238 * book2 1:6cec5aa930e2
238 * book2 1:6cec5aa930e2
239 $ echo a >> a
239 $ echo a >> a
240 $ hg ci --amend -m 'move bookmarks'
240 $ hg ci --amend -m 'move bookmarks'
241 saved backup bundle to $TESTTMP/.hg/strip-backup/6cec5aa930e2-amend-backup.hg (glob)
241 saved backup bundle to $TESTTMP/.hg/strip-backup/6cec5aa930e2-amend-backup.hg (glob)
242 $ hg book
242 $ hg book
243 book1 1:48bb6e53a15f
243 book1 1:48bb6e53a15f
244 * book2 1:48bb6e53a15f
244 * book2 1:48bb6e53a15f
245
245
246 abort does not loose bookmarks
246 abort does not loose bookmarks
247
247
248 $ cat > editor.sh << '__EOF__'
248 $ cat > editor.sh << '__EOF__'
249 > #!/bin/sh
249 > #!/bin/sh
250 > echo "" > "$1"
250 > echo "" > "$1"
251 > __EOF__
251 > __EOF__
252 $ echo a >> a
252 $ echo a >> a
253 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
253 $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg commit --amend
254 transaction abort!
254 transaction abort!
255 rollback completed
255 rollback completed
256 abort: empty commit message
256 abort: empty commit message
257 [255]
257 [255]
258 $ hg book
258 $ hg book
259 book1 1:48bb6e53a15f
259 book1 1:48bb6e53a15f
260 * book2 1:48bb6e53a15f
260 * book2 1:48bb6e53a15f
261 $ hg revert -Caq
261 $ hg revert -Caq
262 $ rm editor.sh
262 $ rm editor.sh
263
263
264 $ echo '[defaults]' >> $HGRCPATH
264 $ echo '[defaults]' >> $HGRCPATH
265 $ echo "commit=-d '0 0'" >> $HGRCPATH
265 $ echo "commit=-d '0 0'" >> $HGRCPATH
266
266
267 Moving branches:
267 Moving branches:
268
268
269 $ hg branch foo
269 $ hg branch foo
270 marked working directory as branch foo
270 marked working directory as branch foo
271 (branches are permanent and global, did you want a bookmark?)
271 (branches are permanent and global, did you want a bookmark?)
272 $ echo a >> a
272 $ echo a >> a
273 $ hg ci -m 'branch foo'
273 $ hg ci -m 'branch foo'
274 $ hg branch default -f
274 $ hg branch default -f
275 marked working directory as branch default
275 marked working directory as branch default
276 (branches are permanent and global, did you want a bookmark?)
276 (branches are permanent and global, did you want a bookmark?)
277 $ hg ci --amend -m 'back to default'
277 $ hg ci --amend -m 'back to default'
278 saved backup bundle to $TESTTMP/.hg/strip-backup/8ac881fbf49d-amend-backup.hg (glob)
278 saved backup bundle to $TESTTMP/.hg/strip-backup/8ac881fbf49d-amend-backup.hg (glob)
279 $ hg branches
279 $ hg branches
280 default 2:ce12b0b57d46
280 default 2:ce12b0b57d46
281
281
282 Close branch:
282 Close branch:
283
283
284 $ hg up -q 0
284 $ hg up -q 0
285 $ echo b >> b
285 $ echo b >> b
286 $ hg branch foo
286 $ hg branch foo
287 marked working directory as branch foo
287 marked working directory as branch foo
288 (branches are permanent and global, did you want a bookmark?)
288 (branches are permanent and global, did you want a bookmark?)
289 $ hg ci -Am 'fork'
289 $ hg ci -Am 'fork'
290 adding b
290 adding b
291 $ echo b >> b
291 $ echo b >> b
292 $ hg ci -mb
292 $ hg ci -mb
293 $ hg ci --amend --close-branch -m 'closing branch foo'
293 $ hg ci --amend --close-branch -m 'closing branch foo'
294 saved backup bundle to $TESTTMP/.hg/strip-backup/c962248fa264-amend-backup.hg (glob)
294 saved backup bundle to $TESTTMP/.hg/strip-backup/c962248fa264-amend-backup.hg (glob)
295
295
296 Same thing, different code path:
296 Same thing, different code path:
297
297
298 $ echo b >> b
298 $ echo b >> b
299 $ hg ci -m 'reopen branch'
299 $ hg ci -m 'reopen branch'
300 reopening closed branch head 4
300 reopening closed branch head 4
301 $ echo b >> b
301 $ echo b >> b
302 $ hg ci --amend --close-branch
302 $ hg ci --amend --close-branch
303 saved backup bundle to $TESTTMP/.hg/strip-backup/027371728205-amend-backup.hg (glob)
303 saved backup bundle to $TESTTMP/.hg/strip-backup/027371728205-amend-backup.hg (glob)
304 $ hg branches
304 $ hg branches
305 default 2:ce12b0b57d46
305 default 2:ce12b0b57d46
306
306
307 Refuse to amend during a merge:
307 Refuse to amend during a merge:
308
308
309 $ hg up -q default
309 $ hg up -q default
310 $ hg merge foo
310 $ hg merge foo
311 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
312 (branch merge, don't forget to commit)
312 (branch merge, don't forget to commit)
313 $ hg ci --amend
313 $ hg ci --amend
314 abort: cannot amend while merging
314 abort: cannot amend while merging
315 [255]
315 [255]
316 $ hg ci -m 'merge'
316 $ hg ci -m 'merge'
317
317
318 Follow copies/renames:
318 Follow copies/renames:
319
319
320 $ hg mv b c
320 $ hg mv b c
321 $ hg ci -m 'b -> c'
321 $ hg ci -m 'b -> c'
322 $ hg mv c d
322 $ hg mv c d
323 $ hg ci --amend -m 'b -> d'
323 $ hg ci --amend -m 'b -> d'
324 saved backup bundle to $TESTTMP/.hg/strip-backup/b8c6eac7f12e-amend-backup.hg (glob)
324 saved backup bundle to $TESTTMP/.hg/strip-backup/b8c6eac7f12e-amend-backup.hg (glob)
325 $ hg st --rev '.^' --copies d
325 $ hg st --rev '.^' --copies d
326 A d
326 A d
327 b
327 b
328 $ hg cp d e
328 $ hg cp d e
329 $ hg ci -m 'e = d'
329 $ hg ci -m 'e = d'
330 $ hg cp e f
330 $ hg cp e f
331 $ hg ci --amend -m 'f = d'
331 $ hg ci --amend -m 'f = d'
332 saved backup bundle to $TESTTMP/.hg/strip-backup/7f9761d65613-amend-backup.hg (glob)
332 saved backup bundle to $TESTTMP/.hg/strip-backup/7f9761d65613-amend-backup.hg (glob)
333 $ hg st --rev '.^' --copies f
333 $ hg st --rev '.^' --copies f
334 A f
334 A f
335 d
335 d
336
336
337 $ mv f f.orig
337 $ mv f f.orig
338 $ hg rm -A f
338 $ hg rm -A f
339 $ hg ci -m removef
339 $ hg ci -m removef
340 $ hg cp a f
340 $ hg cp a f
341 $ mv f.orig f
341 $ mv f.orig f
342 $ hg ci --amend -m replacef
342 $ hg ci --amend -m replacef
343 saved backup bundle to $TESTTMP/.hg/strip-backup/9e8c5f7e3d95-amend-backup.hg (glob)
343 saved backup bundle to $TESTTMP/.hg/strip-backup/9e8c5f7e3d95-amend-backup.hg (glob)
344 $ hg st --change . --copies
344 $ hg st --change . --copies
345 $ hg log -r . --template "{file_copies}\n"
345 $ hg log -r . --template "{file_copies}\n"
346
346
347
347
348 Move added file (issue3410):
348 Move added file (issue3410):
349
349
350 $ echo g >> g
350 $ echo g >> g
351 $ hg ci -Am g
351 $ hg ci -Am g
352 adding g
352 adding g
353 $ hg mv g h
353 $ hg mv g h
354 $ hg ci --amend
354 $ hg ci --amend
355 saved backup bundle to $TESTTMP/.hg/strip-backup/24aa8eacce2b-amend-backup.hg (glob)
355 saved backup bundle to $TESTTMP/.hg/strip-backup/24aa8eacce2b-amend-backup.hg (glob)
356 $ hg st --change . --copies h
356 $ hg st --change . --copies h
357 A h
357 A h
358 $ hg log -r . --template "{file_copies}\n"
358 $ hg log -r . --template "{file_copies}\n"
359
359
360
360
361 Can't rollback an amend:
361 Can't rollback an amend:
362
362
363 $ hg rollback
363 $ hg rollback
364 no rollback information available
364 no rollback information available
365 [1]
365 [1]
366
366
367 Preserve extra dict (issue3430):
367 Preserve extra dict (issue3430):
368
368
369 $ hg branch a
369 $ hg branch a
370 marked working directory as branch a
370 marked working directory as branch a
371 (branches are permanent and global, did you want a bookmark?)
371 (branches are permanent and global, did you want a bookmark?)
372 $ echo a >> a
372 $ echo a >> a
373 $ hg ci -ma
373 $ hg ci -ma
374 $ hg ci --amend -m "a'"
374 $ hg ci --amend -m "a'"
375 saved backup bundle to $TESTTMP/.hg/strip-backup/3837aa2a2fdb-amend-backup.hg (glob)
375 saved backup bundle to $TESTTMP/.hg/strip-backup/3837aa2a2fdb-amend-backup.hg (glob)
376 $ hg log -r . --template "{branch}\n"
376 $ hg log -r . --template "{branch}\n"
377 a
377 a
378 $ hg ci --amend -m "a''"
378 $ hg ci --amend -m "a''"
379 saved backup bundle to $TESTTMP/.hg/strip-backup/c05c06be7514-amend-backup.hg (glob)
379 saved backup bundle to $TESTTMP/.hg/strip-backup/c05c06be7514-amend-backup.hg (glob)
380 $ hg log -r . --template "{branch}\n"
380 $ hg log -r . --template "{branch}\n"
381 a
381 a
382
382
383 Also preserve other entries in the dict that are in the old commit,
383 Also preserve other entries in the dict that are in the old commit,
384 first graft something so there's an additional entry:
384 first graft something so there's an additional entry:
385
385
386 $ hg up 0 -q
386 $ hg up 0 -q
387 $ echo z > z
387 $ echo z > z
388 $ hg ci -Am 'fork'
388 $ hg ci -Am 'fork'
389 adding z
389 adding z
390 created new head
390 created new head
391 $ hg up 11
391 $ hg up 11
392 5 files updated, 0 files merged, 1 files removed, 0 files unresolved
392 5 files updated, 0 files merged, 1 files removed, 0 files unresolved
393 $ hg graft 12
393 $ hg graft 12
394 grafting revision 12
394 grafting revision 12
395 $ hg ci --amend -m 'graft amend'
395 $ hg ci --amend -m 'graft amend'
396 saved backup bundle to $TESTTMP/.hg/strip-backup/bd010aea3f39-amend-backup.hg (glob)
396 saved backup bundle to $TESTTMP/.hg/strip-backup/bd010aea3f39-amend-backup.hg (glob)
397 $ hg log -r . --debug | grep extra
397 $ hg log -r . --debug | grep extra
398 extra: amend_source=bd010aea3f39f3fb2a2f884b9ccb0471cd77398e
398 extra: amend_source=bd010aea3f39f3fb2a2f884b9ccb0471cd77398e
399 extra: branch=a
399 extra: branch=a
400 extra: source=2647734878ef0236dda712fae9c1651cf694ea8a
400 extra: source=2647734878ef0236dda712fae9c1651cf694ea8a
401
401
402 Preserve phase
402 Preserve phase
403
403
404 $ hg phase '.^::.'
404 $ hg phase '.^::.'
405 11: draft
405 11: draft
406 13: draft
406 13: draft
407 $ hg phase --secret --force .
407 $ hg phase --secret --force .
408 $ hg phase '.^::.'
408 $ hg phase '.^::.'
409 11: draft
409 11: draft
410 13: secret
410 13: secret
411 $ hg commit --amend -m 'amend for phase' -q
411 $ hg commit --amend -m 'amend for phase' -q
412 $ hg phase '.^::.'
412 $ hg phase '.^::.'
413 11: draft
413 11: draft
414 13: secret
414 13: secret
415
415
416 Test amend with obsolete
416 Test amend with obsolete
417 ---------------------------
417 ---------------------------
418
418
419 Enable obsolete
419 Enable obsolete
420
420
421 $ cat > ${TESTTMP}/obs.py << EOF
421 $ cat > ${TESTTMP}/obs.py << EOF
422 > import mercurial.obsolete
422 > import mercurial.obsolete
423 > mercurial.obsolete._enabled = True
423 > mercurial.obsolete._enabled = True
424 > EOF
424 > EOF
425 $ echo '[extensions]' >> $HGRCPATH
425 $ echo '[extensions]' >> $HGRCPATH
426 $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
426 $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
427
427
428
428
429 Amend with no files changes
429 Amend with no files changes
430
430
431 $ hg id -n
431 $ hg id -n
432 13
432 13
433 $ hg ci --amend -m 'babar'
433 $ hg ci --amend -m 'babar'
434 $ hg id -n
434 $ hg id -n
435 14
435 14
436 $ hg log -Gl 3 --style=compact
436 $ hg log -Gl 3 --style=compact
437 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
437 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
438 | babar
438 | babar
439 |
439 |
440 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
440 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
441 | | fork
441 | | fork
442 | |
442 | |
443 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
443 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
444 | | a''
444 | | a''
445 | |
445 | |
446 $ hg log -Gl 4 --hidden --style=compact
446 $ hg log -Gl 4 --hidden --style=compact
447 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
447 @ 14[tip]:11 b650e6ee8614 1970-01-01 00:00 +0000 test
448 | babar
448 | babar
449 |
449 |
450 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
450 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
451 |/ amend for phase
451 |/ amend for phase
452 |
452 |
453 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
453 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
454 | | fork
454 | | fork
455 | |
455 | |
456 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
456 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
457 | | a''
457 | | a''
458 | |
458 | |
459
459
460 Amend with files changes
460 Amend with files changes
461
461
462 (note: the extra commit over 15 is a temporary junk I would be happy to get
462 (note: the extra commit over 15 is a temporary junk I would be happy to get
463 ride of)
463 ride of)
464
464
465 $ echo 'babar' >> a
465 $ echo 'babar' >> a
466 $ hg commit --amend
466 $ hg commit --amend
467 $ hg log -Gl 6 --hidden --style=compact
467 $ hg log -Gl 6 --hidden --style=compact
468 @ 16[tip]:11 9f9e9bccf56c 1970-01-01 00:00 +0000 test
468 @ 16[tip]:11 9f9e9bccf56c 1970-01-01 00:00 +0000 test
469 | babar
469 | babar
470 |
470 |
471 | x 15 90fef497c56f 1970-01-01 00:00 +0000 test
471 | x 15 90fef497c56f 1970-01-01 00:00 +0000 test
472 | | temporary amend commit for b650e6ee8614
472 | | temporary amend commit for b650e6ee8614
473 | |
473 | |
474 | x 14:11 b650e6ee8614 1970-01-01 00:00 +0000 test
474 | x 14:11 b650e6ee8614 1970-01-01 00:00 +0000 test
475 |/ babar
475 |/ babar
476 |
476 |
477 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
477 | x 13:11 68ff8ff97044 1970-01-01 00:00 +0000 test
478 |/ amend for phase
478 |/ amend for phase
479 |
479 |
480 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
480 | o 12:0 2647734878ef 1970-01-01 00:00 +0000 test
481 | | fork
481 | | fork
482 | |
482 | |
483 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
483 o | 11 3334b7925910 1970-01-01 00:00 +0000 test
484 | | a''
484 | | a''
485 | |
485 | |
486
486
487
487
488 Test that amend does not make it easy to create obsolescence cycle
488 Test that amend does not make it easy to create obsolescence cycle
489 ---------------------------------------------------------------------
489 ---------------------------------------------------------------------
490
490
491 $ hg id -r 14 --hidden
491 $ hg id -r 14 --hidden
492 b650e6ee8614 (a)
492 b650e6ee8614 (a)
493 $ hg revert -ar 14 --hidden
493 $ hg revert -ar 14 --hidden
494 reverting a
494 reverting a
495 $ hg commit --amend
495 $ hg commit --amend
496 $ hg id
496 $ hg id
497 b99e5df575f7 (a) tip
497 b99e5df575f7 (a) tip
498
498
499 Test that rewriting leaving instability behind is allowed
499 Test that rewriting leaving instability behind is allowed
500 ---------------------------------------------------------------------
500 ---------------------------------------------------------------------
501
501
502 $ hg up '.^'
502 $ hg up '.^'
503 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
503 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
504 $ echo 'b' >> a
504 $ echo 'b' >> a
505 $ hg log --style compact -r 'children(.)'
505 $ hg log --style compact -r 'children(.)'
506 18[tip]:11 b99e5df575f7 1970-01-01 00:00 +0000 test
506 18[tip]:11 b99e5df575f7 1970-01-01 00:00 +0000 test
507 babar
507 babar
508
508
509 $ hg commit --amend
509 $ hg commit --amend
510 $ hg log -r 'unstable()'
510 $ hg log -r 'unstable()'
511 changeset: 18:b99e5df575f7
511 changeset: 18:b99e5df575f7
512 branch: a
512 branch: a
513 parent: 11:3334b7925910
513 parent: 11:3334b7925910
514 user: test
514 user: test
515 date: Thu Jan 01 00:00:00 1970 +0000
515 date: Thu Jan 01 00:00:00 1970 +0000
516 summary: babar
516 summary: babar
517
517
518
518
519 Amend a merge changeset (with renames and conflicts from the second parent):
519 Amend a merge changeset (with renames and conflicts from the second parent):
520
520
521 $ hg up -q default
521 $ hg up -q default
522 $ hg branch -q bar
522 $ hg branch -q bar
523 $ hg cp a aa
523 $ hg cp a aa
524 $ hg mv z zz
524 $ hg mv z zz
525 $ echo cc > cc
525 $ echo cc > cc
526 $ hg add cc
526 $ hg add cc
527 $ hg ci -m aazzcc
527 $ hg ci -m aazzcc
528 $ hg up -q default
528 $ hg up -q default
529 $ echo a >> a
529 $ echo a >> a
530 $ echo dd > cc
530 $ echo dd > cc
531 $ hg add cc
531 $ hg add cc
532 $ hg ci -m aa
532 $ hg ci -m aa
533 $ hg merge -q bar
533 $ hg merge -q bar
534 warning: conflicts during merge.
534 warning: conflicts during merge.
535 merging cc incomplete! (edit conflicts, then use 'hg resolve --mark')
535 merging cc incomplete! (edit conflicts, then use 'hg resolve --mark')
536 [1]
536 [1]
537 $ hg resolve -m cc
537 $ hg resolve -m cc
538 $ hg ci -m 'merge bar'
538 $ hg ci -m 'merge bar'
539 $ hg log --config diff.git=1 -pr .
539 $ hg log --config diff.git=1 -pr .
540 changeset: 23:d51446492733
540 changeset: 23:d51446492733
541 tag: tip
541 tag: tip
542 parent: 22:30d96aeaf27b
542 parent: 22:30d96aeaf27b
543 parent: 21:1aa437659d19
543 parent: 21:1aa437659d19
544 user: test
544 user: test
545 date: Thu Jan 01 00:00:00 1970 +0000
545 date: Thu Jan 01 00:00:00 1970 +0000
546 summary: merge bar
546 summary: merge bar
547
547
548 diff --git a/a b/aa
548 diff --git a/a b/aa
549 copy from a
549 copy from a
550 copy to aa
550 copy to aa
551 diff --git a/cc b/cc
551 diff --git a/cc b/cc
552 --- a/cc
552 --- a/cc
553 +++ b/cc
553 +++ b/cc
554 @@ -1,1 +1,5 @@
554 @@ -1,1 +1,5 @@
555 +<<<<<<< local
555 +<<<<<<< local
556 dd
556 dd
557 +=======
557 +=======
558 +cc
558 +cc
559 +>>>>>>> other
559 +>>>>>>> other
560 diff --git a/z b/zz
560 diff --git a/z b/zz
561 rename from z
561 rename from z
562 rename to zz
562 rename to zz
563
563
564 $ hg debugrename aa
564 $ hg debugrename aa
565 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
565 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
566 $ hg debugrename zz
566 $ hg debugrename zz
567 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
567 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
568 $ hg debugrename cc
568 $ hg debugrename cc
569 cc not renamed
569 cc not renamed
570 $ hg ci --amend -m 'merge bar (amend message)'
570 $ hg ci --amend -m 'merge bar (amend message)'
571 $ hg log --config diff.git=1 -pr .
571 $ hg log --config diff.git=1 -pr .
572 changeset: 24:59de3dce7a79
572 changeset: 24:59de3dce7a79
573 tag: tip
573 tag: tip
574 parent: 22:30d96aeaf27b
574 parent: 22:30d96aeaf27b
575 parent: 21:1aa437659d19
575 parent: 21:1aa437659d19
576 user: test
576 user: test
577 date: Thu Jan 01 00:00:00 1970 +0000
577 date: Thu Jan 01 00:00:00 1970 +0000
578 summary: merge bar (amend message)
578 summary: merge bar (amend message)
579
579
580 diff --git a/a b/aa
580 diff --git a/a b/aa
581 copy from a
581 copy from a
582 copy to aa
582 copy to aa
583 diff --git a/cc b/cc
583 diff --git a/cc b/cc
584 --- a/cc
584 --- a/cc
585 +++ b/cc
585 +++ b/cc
586 @@ -1,1 +1,5 @@
586 @@ -1,1 +1,5 @@
587 +<<<<<<< local
587 +<<<<<<< local
588 dd
588 dd
589 +=======
589 +=======
590 +cc
590 +cc
591 +>>>>>>> other
591 +>>>>>>> other
592 diff --git a/z b/zz
592 diff --git a/z b/zz
593 rename from z
593 rename from z
594 rename to zz
594 rename to zz
595
595
596 $ hg debugrename aa
596 $ hg debugrename aa
597 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
597 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
598 $ hg debugrename zz
598 $ hg debugrename zz
599 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
599 zz renamed from z:69a1b67522704ec122181c0890bd16e9d3e7516a
600 $ hg debugrename cc
600 $ hg debugrename cc
601 cc not renamed
601 cc not renamed
602 $ hg mv zz z
602 $ hg mv zz z
603 $ hg ci --amend -m 'merge bar (undo rename)'
603 $ hg ci --amend -m 'merge bar (undo rename)'
604 $ hg log --config diff.git=1 -pr .
604 $ hg log --config diff.git=1 -pr .
605 changeset: 26:7fb89c461f81
605 changeset: 26:7fb89c461f81
606 tag: tip
606 tag: tip
607 parent: 22:30d96aeaf27b
607 parent: 22:30d96aeaf27b
608 parent: 21:1aa437659d19
608 parent: 21:1aa437659d19
609 user: test
609 user: test
610 date: Thu Jan 01 00:00:00 1970 +0000
610 date: Thu Jan 01 00:00:00 1970 +0000
611 summary: merge bar (undo rename)
611 summary: merge bar (undo rename)
612
612
613 diff --git a/a b/aa
613 diff --git a/a b/aa
614 copy from a
614 copy from a
615 copy to aa
615 copy to aa
616 diff --git a/cc b/cc
616 diff --git a/cc b/cc
617 --- a/cc
617 --- a/cc
618 +++ b/cc
618 +++ b/cc
619 @@ -1,1 +1,5 @@
619 @@ -1,1 +1,5 @@
620 +<<<<<<< local
620 +<<<<<<< local
621 dd
621 dd
622 +=======
622 +=======
623 +cc
623 +cc
624 +>>>>>>> other
624 +>>>>>>> other
625
625
626 $ hg debugrename z
626 $ hg debugrename z
627 z not renamed
627 z not renamed
628
628
629 Amend a merge changeset (with renames during the merge):
629 Amend a merge changeset (with renames during the merge):
630
630
631 $ hg up -q bar
631 $ hg up -q bar
632 $ echo x > x
632 $ echo x > x
633 $ hg add x
633 $ hg add x
634 $ hg ci -m x
634 $ hg ci -m x
635 $ hg up -q default
635 $ hg up -q default
636 $ hg merge -q bar
636 $ hg merge -q bar
637 $ hg mv aa aaa
637 $ hg mv aa aaa
638 $ echo aa >> aaa
638 $ echo aa >> aaa
639 $ hg ci -m 'merge bar again'
639 $ hg ci -m 'merge bar again'
640 $ hg log --config diff.git=1 -pr .
640 $ hg log --config diff.git=1 -pr .
641 changeset: 28:982d7a34ffee
641 changeset: 28:982d7a34ffee
642 tag: tip
642 tag: tip
643 parent: 26:7fb89c461f81
643 parent: 26:7fb89c461f81
644 parent: 27:4c94d5bc65f5
644 parent: 27:4c94d5bc65f5
645 user: test
645 user: test
646 date: Thu Jan 01 00:00:00 1970 +0000
646 date: Thu Jan 01 00:00:00 1970 +0000
647 summary: merge bar again
647 summary: merge bar again
648
648
649 diff --git a/aa b/aa
649 diff --git a/aa b/aa
650 deleted file mode 100644
650 deleted file mode 100644
651 --- a/aa
651 --- a/aa
652 +++ /dev/null
652 +++ /dev/null
653 @@ -1,2 +0,0 @@
653 @@ -1,2 +0,0 @@
654 -a
654 -a
655 -a
655 -a
656 diff --git a/aaa b/aaa
656 diff --git a/aaa b/aaa
657 new file mode 100644
657 new file mode 100644
658 --- /dev/null
658 --- /dev/null
659 +++ b/aaa
659 +++ b/aaa
660 @@ -0,0 +1,3 @@
660 @@ -0,0 +1,3 @@
661 +a
661 +a
662 +a
662 +a
663 +aa
663 +aa
664 diff --git a/x b/x
664 diff --git a/x b/x
665 new file mode 100644
665 new file mode 100644
666 --- /dev/null
666 --- /dev/null
667 +++ b/x
667 +++ b/x
668 @@ -0,0 +1,1 @@
668 @@ -0,0 +1,1 @@
669 +x
669 +x
670
670
671 $ hg debugrename aaa
671 $ hg debugrename aaa
672 aaa renamed from aa:37d9b5d994eab34eda9c16b195ace52c7b129980
672 aaa renamed from aa:37d9b5d994eab34eda9c16b195ace52c7b129980
673 $ hg mv aaa aa
673 $ hg mv aaa aa
674 $ hg ci --amend -m 'merge bar again (undo rename)'
674 $ hg ci --amend -m 'merge bar again (undo rename)'
675 $ hg log --config diff.git=1 -pr .
675 $ hg log --config diff.git=1 -pr .
676 changeset: 30:522688c0e71b
676 changeset: 30:522688c0e71b
677 tag: tip
677 tag: tip
678 parent: 26:7fb89c461f81
678 parent: 26:7fb89c461f81
679 parent: 27:4c94d5bc65f5
679 parent: 27:4c94d5bc65f5
680 user: test
680 user: test
681 date: Thu Jan 01 00:00:00 1970 +0000
681 date: Thu Jan 01 00:00:00 1970 +0000
682 summary: merge bar again (undo rename)
682 summary: merge bar again (undo rename)
683
683
684 diff --git a/aa b/aa
684 diff --git a/aa b/aa
685 --- a/aa
685 --- a/aa
686 +++ b/aa
686 +++ b/aa
687 @@ -1,2 +1,3 @@
687 @@ -1,2 +1,3 @@
688 a
688 a
689 a
689 a
690 +aa
690 +aa
691 diff --git a/x b/x
691 diff --git a/x b/x
692 new file mode 100644
692 new file mode 100644
693 --- /dev/null
693 --- /dev/null
694 +++ b/x
694 +++ b/x
695 @@ -0,0 +1,1 @@
695 @@ -0,0 +1,1 @@
696 +x
696 +x
697
697
698 $ hg debugrename aa
698 $ hg debugrename aa
699 aa not renamed
699 aa not renamed
700 $ hg debugrename -r '.^' aa
700 $ hg debugrename -r '.^' aa
701 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
701 aa renamed from a:a80d06849b333b8a3d5c445f8ba3142010dcdc9e
702
702
703 Amend a merge changeset (with manifest-level conflicts):
703 Amend a merge changeset (with manifest-level conflicts):
704
704
705 $ hg up -q bar
705 $ hg up -q bar
706 $ hg rm aa
706 $ hg rm aa
707 $ hg ci -m 'rm aa'
707 $ hg ci -m 'rm aa'
708 $ hg up -q default
708 $ hg up -q default
709 $ echo aa >> aa
709 $ echo aa >> aa
710 $ hg ci -m aa
710 $ hg ci -m aa
711 $ hg merge -q bar
711 $ hg merge -q bar
712 local changed aa which remote deleted
712 local changed aa which remote deleted
713 use (c)hanged version or (d)elete? c
713 use (c)hanged version or (d)elete? c
714 $ hg ci -m 'merge bar (with conflicts)'
714 $ hg ci -m 'merge bar (with conflicts)'
715 $ hg log --config diff.git=1 -pr .
715 $ hg log --config diff.git=1 -pr .
716 changeset: 33:5f9904c491b8
716 changeset: 33:5f9904c491b8
717 tag: tip
717 tag: tip
718 parent: 32:01780b896f58
718 parent: 32:01780b896f58
719 parent: 31:67db8847a540
719 parent: 31:67db8847a540
720 user: test
720 user: test
721 date: Thu Jan 01 00:00:00 1970 +0000
721 date: Thu Jan 01 00:00:00 1970 +0000
722 summary: merge bar (with conflicts)
722 summary: merge bar (with conflicts)
723
723
724
724
725 $ hg rm aa
725 $ hg rm aa
726 $ hg ci --amend -m 'merge bar (with conflicts, amended)'
726 $ hg ci --amend -m 'merge bar (with conflicts, amended)'
727 $ hg log --config diff.git=1 -pr .
727 $ hg log --config diff.git=1 -pr .
728 changeset: 35:6ce0c89781a3
728 changeset: 35:6ce0c89781a3
729 tag: tip
729 tag: tip
730 parent: 32:01780b896f58
730 parent: 32:01780b896f58
731 parent: 31:67db8847a540
731 parent: 31:67db8847a540
732 user: test
732 user: test
733 date: Thu Jan 01 00:00:00 1970 +0000
733 date: Thu Jan 01 00:00:00 1970 +0000
734 summary: merge bar (with conflicts, amended)
734 summary: merge bar (with conflicts, amended)
735
735
736 diff --git a/aa b/aa
736 diff --git a/aa b/aa
737 deleted file mode 100644
737 deleted file mode 100644
738 --- a/aa
738 --- a/aa
739 +++ /dev/null
739 +++ /dev/null
740 @@ -1,4 +0,0 @@
740 @@ -1,4 +0,0 @@
741 -a
741 -a
742 -a
742 -a
743 -aa
743 -aa
744 -aa
744 -aa
745
745
746 Issue 3445: amending with --close-branch a commit that created a new head should fail
747 This shouldn't be possible:
748
749 $ hg up -q default
750 $ hg branch closewithamend
751 marked working directory as branch closewithamend
752 (branches are permanent and global, did you want a bookmark?)
753 $ hg ci -Am..
754 adding cc.orig
755 adding obs.py
756 adding obs.pyc
757 $ hg ci --amend --close-branch -m 'closing'
758 abort: can only close branch heads
759 [255]
760
761 This silliness fails:
762
763 $ hg branch silliness
764 marked working directory as branch silliness
765 (branches are permanent and global, did you want a bookmark?)
766 $ echo b >> b
767 $ hg ci --close-branch -m'open and close'
768 abort: can only close branch heads
769 [255]
General Comments 0
You need to be logged in to leave comments. Login now