##// END OF EJS Templates
bisect: use standard one-line commit summary...
Martin von Zweigbergk -
r47556:f51ff655 default
parent child Browse files
Show More
@@ -1,7924 +1,7924 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 __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import os
11 import os
12 import re
12 import re
13 import sys
13 import sys
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 hex,
17 hex,
18 nullid,
18 nullid,
19 nullrev,
19 nullrev,
20 short,
20 short,
21 wdirhex,
21 wdirhex,
22 wdirrev,
22 wdirrev,
23 )
23 )
24 from .pycompat import open
24 from .pycompat import open
25 from . import (
25 from . import (
26 archival,
26 archival,
27 bookmarks,
27 bookmarks,
28 bundle2,
28 bundle2,
29 bundlecaches,
29 bundlecaches,
30 changegroup,
30 changegroup,
31 cmdutil,
31 cmdutil,
32 copies,
32 copies,
33 debugcommands as debugcommandsmod,
33 debugcommands as debugcommandsmod,
34 destutil,
34 destutil,
35 dirstateguard,
35 dirstateguard,
36 discovery,
36 discovery,
37 encoding,
37 encoding,
38 error,
38 error,
39 exchange,
39 exchange,
40 extensions,
40 extensions,
41 filemerge,
41 filemerge,
42 formatter,
42 formatter,
43 graphmod,
43 graphmod,
44 grep as grepmod,
44 grep as grepmod,
45 hbisect,
45 hbisect,
46 help,
46 help,
47 hg,
47 hg,
48 logcmdutil,
48 logcmdutil,
49 merge as mergemod,
49 merge as mergemod,
50 mergestate as mergestatemod,
50 mergestate as mergestatemod,
51 narrowspec,
51 narrowspec,
52 obsolete,
52 obsolete,
53 obsutil,
53 obsutil,
54 patch,
54 patch,
55 phases,
55 phases,
56 pycompat,
56 pycompat,
57 rcutil,
57 rcutil,
58 registrar,
58 registrar,
59 requirements,
59 requirements,
60 revsetlang,
60 revsetlang,
61 rewriteutil,
61 rewriteutil,
62 scmutil,
62 scmutil,
63 server,
63 server,
64 shelve as shelvemod,
64 shelve as shelvemod,
65 state as statemod,
65 state as statemod,
66 streamclone,
66 streamclone,
67 tags as tagsmod,
67 tags as tagsmod,
68 ui as uimod,
68 ui as uimod,
69 util,
69 util,
70 verify as verifymod,
70 verify as verifymod,
71 vfs as vfsmod,
71 vfs as vfsmod,
72 wireprotoserver,
72 wireprotoserver,
73 )
73 )
74 from .utils import (
74 from .utils import (
75 dateutil,
75 dateutil,
76 stringutil,
76 stringutil,
77 )
77 )
78
78
79 table = {}
79 table = {}
80 table.update(debugcommandsmod.command._table)
80 table.update(debugcommandsmod.command._table)
81
81
82 command = registrar.command(table)
82 command = registrar.command(table)
83 INTENT_READONLY = registrar.INTENT_READONLY
83 INTENT_READONLY = registrar.INTENT_READONLY
84
84
85 # common command options
85 # common command options
86
86
87 globalopts = [
87 globalopts = [
88 (
88 (
89 b'R',
89 b'R',
90 b'repository',
90 b'repository',
91 b'',
91 b'',
92 _(b'repository root directory or name of overlay bundle file'),
92 _(b'repository root directory or name of overlay bundle file'),
93 _(b'REPO'),
93 _(b'REPO'),
94 ),
94 ),
95 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
95 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
96 (
96 (
97 b'y',
97 b'y',
98 b'noninteractive',
98 b'noninteractive',
99 None,
99 None,
100 _(
100 _(
101 b'do not prompt, automatically pick the first choice for all prompts'
101 b'do not prompt, automatically pick the first choice for all prompts'
102 ),
102 ),
103 ),
103 ),
104 (b'q', b'quiet', None, _(b'suppress output')),
104 (b'q', b'quiet', None, _(b'suppress output')),
105 (b'v', b'verbose', None, _(b'enable additional output')),
105 (b'v', b'verbose', None, _(b'enable additional output')),
106 (
106 (
107 b'',
107 b'',
108 b'color',
108 b'color',
109 b'',
109 b'',
110 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
110 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
111 # and should not be translated
111 # and should not be translated
112 _(b"when to colorize (boolean, always, auto, never, or debug)"),
112 _(b"when to colorize (boolean, always, auto, never, or debug)"),
113 _(b'TYPE'),
113 _(b'TYPE'),
114 ),
114 ),
115 (
115 (
116 b'',
116 b'',
117 b'config',
117 b'config',
118 [],
118 [],
119 _(b'set/override config option (use \'section.name=value\')'),
119 _(b'set/override config option (use \'section.name=value\')'),
120 _(b'CONFIG'),
120 _(b'CONFIG'),
121 ),
121 ),
122 (b'', b'debug', None, _(b'enable debugging output')),
122 (b'', b'debug', None, _(b'enable debugging output')),
123 (b'', b'debugger', None, _(b'start debugger')),
123 (b'', b'debugger', None, _(b'start debugger')),
124 (
124 (
125 b'',
125 b'',
126 b'encoding',
126 b'encoding',
127 encoding.encoding,
127 encoding.encoding,
128 _(b'set the charset encoding'),
128 _(b'set the charset encoding'),
129 _(b'ENCODE'),
129 _(b'ENCODE'),
130 ),
130 ),
131 (
131 (
132 b'',
132 b'',
133 b'encodingmode',
133 b'encodingmode',
134 encoding.encodingmode,
134 encoding.encodingmode,
135 _(b'set the charset encoding mode'),
135 _(b'set the charset encoding mode'),
136 _(b'MODE'),
136 _(b'MODE'),
137 ),
137 ),
138 (b'', b'traceback', None, _(b'always print a traceback on exception')),
138 (b'', b'traceback', None, _(b'always print a traceback on exception')),
139 (b'', b'time', None, _(b'time how long the command takes')),
139 (b'', b'time', None, _(b'time how long the command takes')),
140 (b'', b'profile', None, _(b'print command execution profile')),
140 (b'', b'profile', None, _(b'print command execution profile')),
141 (b'', b'version', None, _(b'output version information and exit')),
141 (b'', b'version', None, _(b'output version information and exit')),
142 (b'h', b'help', None, _(b'display help and exit')),
142 (b'h', b'help', None, _(b'display help and exit')),
143 (b'', b'hidden', False, _(b'consider hidden changesets')),
143 (b'', b'hidden', False, _(b'consider hidden changesets')),
144 (
144 (
145 b'',
145 b'',
146 b'pager',
146 b'pager',
147 b'auto',
147 b'auto',
148 _(b"when to paginate (boolean, always, auto, or never)"),
148 _(b"when to paginate (boolean, always, auto, or never)"),
149 _(b'TYPE'),
149 _(b'TYPE'),
150 ),
150 ),
151 ]
151 ]
152
152
153 dryrunopts = cmdutil.dryrunopts
153 dryrunopts = cmdutil.dryrunopts
154 remoteopts = cmdutil.remoteopts
154 remoteopts = cmdutil.remoteopts
155 walkopts = cmdutil.walkopts
155 walkopts = cmdutil.walkopts
156 commitopts = cmdutil.commitopts
156 commitopts = cmdutil.commitopts
157 commitopts2 = cmdutil.commitopts2
157 commitopts2 = cmdutil.commitopts2
158 commitopts3 = cmdutil.commitopts3
158 commitopts3 = cmdutil.commitopts3
159 formatteropts = cmdutil.formatteropts
159 formatteropts = cmdutil.formatteropts
160 templateopts = cmdutil.templateopts
160 templateopts = cmdutil.templateopts
161 logopts = cmdutil.logopts
161 logopts = cmdutil.logopts
162 diffopts = cmdutil.diffopts
162 diffopts = cmdutil.diffopts
163 diffwsopts = cmdutil.diffwsopts
163 diffwsopts = cmdutil.diffwsopts
164 diffopts2 = cmdutil.diffopts2
164 diffopts2 = cmdutil.diffopts2
165 mergetoolopts = cmdutil.mergetoolopts
165 mergetoolopts = cmdutil.mergetoolopts
166 similarityopts = cmdutil.similarityopts
166 similarityopts = cmdutil.similarityopts
167 subrepoopts = cmdutil.subrepoopts
167 subrepoopts = cmdutil.subrepoopts
168 debugrevlogopts = cmdutil.debugrevlogopts
168 debugrevlogopts = cmdutil.debugrevlogopts
169
169
170 # Commands start here, listed alphabetically
170 # Commands start here, listed alphabetically
171
171
172
172
173 @command(
173 @command(
174 b'abort',
174 b'abort',
175 dryrunopts,
175 dryrunopts,
176 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
176 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
177 helpbasic=True,
177 helpbasic=True,
178 )
178 )
179 def abort(ui, repo, **opts):
179 def abort(ui, repo, **opts):
180 """abort an unfinished operation (EXPERIMENTAL)
180 """abort an unfinished operation (EXPERIMENTAL)
181
181
182 Aborts a multistep operation like graft, histedit, rebase, merge,
182 Aborts a multistep operation like graft, histedit, rebase, merge,
183 and unshelve if they are in an unfinished state.
183 and unshelve if they are in an unfinished state.
184
184
185 use --dry-run/-n to dry run the command.
185 use --dry-run/-n to dry run the command.
186 """
186 """
187 dryrun = opts.get('dry_run')
187 dryrun = opts.get('dry_run')
188 abortstate = cmdutil.getunfinishedstate(repo)
188 abortstate = cmdutil.getunfinishedstate(repo)
189 if not abortstate:
189 if not abortstate:
190 raise error.StateError(_(b'no operation in progress'))
190 raise error.StateError(_(b'no operation in progress'))
191 if not abortstate.abortfunc:
191 if not abortstate.abortfunc:
192 raise error.InputError(
192 raise error.InputError(
193 (
193 (
194 _(b"%s in progress but does not support 'hg abort'")
194 _(b"%s in progress but does not support 'hg abort'")
195 % (abortstate._opname)
195 % (abortstate._opname)
196 ),
196 ),
197 hint=abortstate.hint(),
197 hint=abortstate.hint(),
198 )
198 )
199 if dryrun:
199 if dryrun:
200 ui.status(
200 ui.status(
201 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
201 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
202 )
202 )
203 return
203 return
204 return abortstate.abortfunc(ui, repo)
204 return abortstate.abortfunc(ui, repo)
205
205
206
206
207 @command(
207 @command(
208 b'add',
208 b'add',
209 walkopts + subrepoopts + dryrunopts,
209 walkopts + subrepoopts + dryrunopts,
210 _(b'[OPTION]... [FILE]...'),
210 _(b'[OPTION]... [FILE]...'),
211 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
211 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
212 helpbasic=True,
212 helpbasic=True,
213 inferrepo=True,
213 inferrepo=True,
214 )
214 )
215 def add(ui, repo, *pats, **opts):
215 def add(ui, repo, *pats, **opts):
216 """add the specified files on the next commit
216 """add the specified files on the next commit
217
217
218 Schedule files to be version controlled and added to the
218 Schedule files to be version controlled and added to the
219 repository.
219 repository.
220
220
221 The files will be added to the repository at the next commit. To
221 The files will be added to the repository at the next commit. To
222 undo an add before that, see :hg:`forget`.
222 undo an add before that, see :hg:`forget`.
223
223
224 If no names are given, add all files to the repository (except
224 If no names are given, add all files to the repository (except
225 files matching ``.hgignore``).
225 files matching ``.hgignore``).
226
226
227 .. container:: verbose
227 .. container:: verbose
228
228
229 Examples:
229 Examples:
230
230
231 - New (unknown) files are added
231 - New (unknown) files are added
232 automatically by :hg:`add`::
232 automatically by :hg:`add`::
233
233
234 $ ls
234 $ ls
235 foo.c
235 foo.c
236 $ hg status
236 $ hg status
237 ? foo.c
237 ? foo.c
238 $ hg add
238 $ hg add
239 adding foo.c
239 adding foo.c
240 $ hg status
240 $ hg status
241 A foo.c
241 A foo.c
242
242
243 - Specific files to be added can be specified::
243 - Specific files to be added can be specified::
244
244
245 $ ls
245 $ ls
246 bar.c foo.c
246 bar.c foo.c
247 $ hg status
247 $ hg status
248 ? bar.c
248 ? bar.c
249 ? foo.c
249 ? foo.c
250 $ hg add bar.c
250 $ hg add bar.c
251 $ hg status
251 $ hg status
252 A bar.c
252 A bar.c
253 ? foo.c
253 ? foo.c
254
254
255 Returns 0 if all files are successfully added.
255 Returns 0 if all files are successfully added.
256 """
256 """
257
257
258 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
258 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
259 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
259 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
260 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
260 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
261 return rejected and 1 or 0
261 return rejected and 1 or 0
262
262
263
263
264 @command(
264 @command(
265 b'addremove',
265 b'addremove',
266 similarityopts + subrepoopts + walkopts + dryrunopts,
266 similarityopts + subrepoopts + walkopts + dryrunopts,
267 _(b'[OPTION]... [FILE]...'),
267 _(b'[OPTION]... [FILE]...'),
268 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
268 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
269 inferrepo=True,
269 inferrepo=True,
270 )
270 )
271 def addremove(ui, repo, *pats, **opts):
271 def addremove(ui, repo, *pats, **opts):
272 """add all new files, delete all missing files
272 """add all new files, delete all missing files
273
273
274 Add all new files and remove all missing files from the
274 Add all new files and remove all missing files from the
275 repository.
275 repository.
276
276
277 Unless names are given, new files are ignored if they match any of
277 Unless names are given, new files are ignored if they match any of
278 the patterns in ``.hgignore``. As with add, these changes take
278 the patterns in ``.hgignore``. As with add, these changes take
279 effect at the next commit.
279 effect at the next commit.
280
280
281 Use the -s/--similarity option to detect renamed files. This
281 Use the -s/--similarity option to detect renamed files. This
282 option takes a percentage between 0 (disabled) and 100 (files must
282 option takes a percentage between 0 (disabled) and 100 (files must
283 be identical) as its parameter. With a parameter greater than 0,
283 be identical) as its parameter. With a parameter greater than 0,
284 this compares every removed file with every added file and records
284 this compares every removed file with every added file and records
285 those similar enough as renames. Detecting renamed files this way
285 those similar enough as renames. Detecting renamed files this way
286 can be expensive. After using this option, :hg:`status -C` can be
286 can be expensive. After using this option, :hg:`status -C` can be
287 used to check which files were identified as moved or renamed. If
287 used to check which files were identified as moved or renamed. If
288 not specified, -s/--similarity defaults to 100 and only renames of
288 not specified, -s/--similarity defaults to 100 and only renames of
289 identical files are detected.
289 identical files are detected.
290
290
291 .. container:: verbose
291 .. container:: verbose
292
292
293 Examples:
293 Examples:
294
294
295 - A number of files (bar.c and foo.c) are new,
295 - A number of files (bar.c and foo.c) are new,
296 while foobar.c has been removed (without using :hg:`remove`)
296 while foobar.c has been removed (without using :hg:`remove`)
297 from the repository::
297 from the repository::
298
298
299 $ ls
299 $ ls
300 bar.c foo.c
300 bar.c foo.c
301 $ hg status
301 $ hg status
302 ! foobar.c
302 ! foobar.c
303 ? bar.c
303 ? bar.c
304 ? foo.c
304 ? foo.c
305 $ hg addremove
305 $ hg addremove
306 adding bar.c
306 adding bar.c
307 adding foo.c
307 adding foo.c
308 removing foobar.c
308 removing foobar.c
309 $ hg status
309 $ hg status
310 A bar.c
310 A bar.c
311 A foo.c
311 A foo.c
312 R foobar.c
312 R foobar.c
313
313
314 - A file foobar.c was moved to foo.c without using :hg:`rename`.
314 - A file foobar.c was moved to foo.c without using :hg:`rename`.
315 Afterwards, it was edited slightly::
315 Afterwards, it was edited slightly::
316
316
317 $ ls
317 $ ls
318 foo.c
318 foo.c
319 $ hg status
319 $ hg status
320 ! foobar.c
320 ! foobar.c
321 ? foo.c
321 ? foo.c
322 $ hg addremove --similarity 90
322 $ hg addremove --similarity 90
323 removing foobar.c
323 removing foobar.c
324 adding foo.c
324 adding foo.c
325 recording removal of foobar.c as rename to foo.c (94% similar)
325 recording removal of foobar.c as rename to foo.c (94% similar)
326 $ hg status -C
326 $ hg status -C
327 A foo.c
327 A foo.c
328 foobar.c
328 foobar.c
329 R foobar.c
329 R foobar.c
330
330
331 Returns 0 if all files are successfully added.
331 Returns 0 if all files are successfully added.
332 """
332 """
333 opts = pycompat.byteskwargs(opts)
333 opts = pycompat.byteskwargs(opts)
334 if not opts.get(b'similarity'):
334 if not opts.get(b'similarity'):
335 opts[b'similarity'] = b'100'
335 opts[b'similarity'] = b'100'
336 matcher = scmutil.match(repo[None], pats, opts)
336 matcher = scmutil.match(repo[None], pats, opts)
337 relative = scmutil.anypats(pats, opts)
337 relative = scmutil.anypats(pats, opts)
338 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
338 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
339 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
339 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
340
340
341
341
342 @command(
342 @command(
343 b'annotate|blame',
343 b'annotate|blame',
344 [
344 [
345 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
345 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
346 (
346 (
347 b'',
347 b'',
348 b'follow',
348 b'follow',
349 None,
349 None,
350 _(b'follow copies/renames and list the filename (DEPRECATED)'),
350 _(b'follow copies/renames and list the filename (DEPRECATED)'),
351 ),
351 ),
352 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
352 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
353 (b'a', b'text', None, _(b'treat all files as text')),
353 (b'a', b'text', None, _(b'treat all files as text')),
354 (b'u', b'user', None, _(b'list the author (long with -v)')),
354 (b'u', b'user', None, _(b'list the author (long with -v)')),
355 (b'f', b'file', None, _(b'list the filename')),
355 (b'f', b'file', None, _(b'list the filename')),
356 (b'd', b'date', None, _(b'list the date (short with -q)')),
356 (b'd', b'date', None, _(b'list the date (short with -q)')),
357 (b'n', b'number', None, _(b'list the revision number (default)')),
357 (b'n', b'number', None, _(b'list the revision number (default)')),
358 (b'c', b'changeset', None, _(b'list the changeset')),
358 (b'c', b'changeset', None, _(b'list the changeset')),
359 (
359 (
360 b'l',
360 b'l',
361 b'line-number',
361 b'line-number',
362 None,
362 None,
363 _(b'show line number at the first appearance'),
363 _(b'show line number at the first appearance'),
364 ),
364 ),
365 (
365 (
366 b'',
366 b'',
367 b'skip',
367 b'skip',
368 [],
368 [],
369 _(b'revset to not display (EXPERIMENTAL)'),
369 _(b'revset to not display (EXPERIMENTAL)'),
370 _(b'REV'),
370 _(b'REV'),
371 ),
371 ),
372 ]
372 ]
373 + diffwsopts
373 + diffwsopts
374 + walkopts
374 + walkopts
375 + formatteropts,
375 + formatteropts,
376 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
376 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
377 helpcategory=command.CATEGORY_FILE_CONTENTS,
377 helpcategory=command.CATEGORY_FILE_CONTENTS,
378 helpbasic=True,
378 helpbasic=True,
379 inferrepo=True,
379 inferrepo=True,
380 )
380 )
381 def annotate(ui, repo, *pats, **opts):
381 def annotate(ui, repo, *pats, **opts):
382 """show changeset information by line for each file
382 """show changeset information by line for each file
383
383
384 List changes in files, showing the revision id responsible for
384 List changes in files, showing the revision id responsible for
385 each line.
385 each line.
386
386
387 This command is useful for discovering when a change was made and
387 This command is useful for discovering when a change was made and
388 by whom.
388 by whom.
389
389
390 If you include --file, --user, or --date, the revision number is
390 If you include --file, --user, or --date, the revision number is
391 suppressed unless you also include --number.
391 suppressed unless you also include --number.
392
392
393 Without the -a/--text option, annotate will avoid processing files
393 Without the -a/--text option, annotate will avoid processing files
394 it detects as binary. With -a, annotate will annotate the file
394 it detects as binary. With -a, annotate will annotate the file
395 anyway, although the results will probably be neither useful
395 anyway, although the results will probably be neither useful
396 nor desirable.
396 nor desirable.
397
397
398 .. container:: verbose
398 .. container:: verbose
399
399
400 Template:
400 Template:
401
401
402 The following keywords are supported in addition to the common template
402 The following keywords are supported in addition to the common template
403 keywords and functions. See also :hg:`help templates`.
403 keywords and functions. See also :hg:`help templates`.
404
404
405 :lines: List of lines with annotation data.
405 :lines: List of lines with annotation data.
406 :path: String. Repository-absolute path of the specified file.
406 :path: String. Repository-absolute path of the specified file.
407
407
408 And each entry of ``{lines}`` provides the following sub-keywords in
408 And each entry of ``{lines}`` provides the following sub-keywords in
409 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
409 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
410
410
411 :line: String. Line content.
411 :line: String. Line content.
412 :lineno: Integer. Line number at that revision.
412 :lineno: Integer. Line number at that revision.
413 :path: String. Repository-absolute path of the file at that revision.
413 :path: String. Repository-absolute path of the file at that revision.
414
414
415 See :hg:`help templates.operators` for the list expansion syntax.
415 See :hg:`help templates.operators` for the list expansion syntax.
416
416
417 Returns 0 on success.
417 Returns 0 on success.
418 """
418 """
419 opts = pycompat.byteskwargs(opts)
419 opts = pycompat.byteskwargs(opts)
420 if not pats:
420 if not pats:
421 raise error.InputError(
421 raise error.InputError(
422 _(b'at least one filename or pattern is required')
422 _(b'at least one filename or pattern is required')
423 )
423 )
424
424
425 if opts.get(b'follow'):
425 if opts.get(b'follow'):
426 # --follow is deprecated and now just an alias for -f/--file
426 # --follow is deprecated and now just an alias for -f/--file
427 # to mimic the behavior of Mercurial before version 1.5
427 # to mimic the behavior of Mercurial before version 1.5
428 opts[b'file'] = True
428 opts[b'file'] = True
429
429
430 if (
430 if (
431 not opts.get(b'user')
431 not opts.get(b'user')
432 and not opts.get(b'changeset')
432 and not opts.get(b'changeset')
433 and not opts.get(b'date')
433 and not opts.get(b'date')
434 and not opts.get(b'file')
434 and not opts.get(b'file')
435 ):
435 ):
436 opts[b'number'] = True
436 opts[b'number'] = True
437
437
438 linenumber = opts.get(b'line_number') is not None
438 linenumber = opts.get(b'line_number') is not None
439 if (
439 if (
440 linenumber
440 linenumber
441 and (not opts.get(b'changeset'))
441 and (not opts.get(b'changeset'))
442 and (not opts.get(b'number'))
442 and (not opts.get(b'number'))
443 ):
443 ):
444 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
444 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
445
445
446 rev = opts.get(b'rev')
446 rev = opts.get(b'rev')
447 if rev:
447 if rev:
448 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
448 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
449 ctx = scmutil.revsingle(repo, rev)
449 ctx = scmutil.revsingle(repo, rev)
450
450
451 ui.pager(b'annotate')
451 ui.pager(b'annotate')
452 rootfm = ui.formatter(b'annotate', opts)
452 rootfm = ui.formatter(b'annotate', opts)
453 if ui.debugflag:
453 if ui.debugflag:
454 shorthex = pycompat.identity
454 shorthex = pycompat.identity
455 else:
455 else:
456
456
457 def shorthex(h):
457 def shorthex(h):
458 return h[:12]
458 return h[:12]
459
459
460 if ui.quiet:
460 if ui.quiet:
461 datefunc = dateutil.shortdate
461 datefunc = dateutil.shortdate
462 else:
462 else:
463 datefunc = dateutil.datestr
463 datefunc = dateutil.datestr
464 if ctx.rev() is None:
464 if ctx.rev() is None:
465 if opts.get(b'changeset'):
465 if opts.get(b'changeset'):
466 # omit "+" suffix which is appended to node hex
466 # omit "+" suffix which is appended to node hex
467 def formatrev(rev):
467 def formatrev(rev):
468 if rev == wdirrev:
468 if rev == wdirrev:
469 return b'%d' % ctx.p1().rev()
469 return b'%d' % ctx.p1().rev()
470 else:
470 else:
471 return b'%d' % rev
471 return b'%d' % rev
472
472
473 else:
473 else:
474
474
475 def formatrev(rev):
475 def formatrev(rev):
476 if rev == wdirrev:
476 if rev == wdirrev:
477 return b'%d+' % ctx.p1().rev()
477 return b'%d+' % ctx.p1().rev()
478 else:
478 else:
479 return b'%d ' % rev
479 return b'%d ' % rev
480
480
481 def formathex(h):
481 def formathex(h):
482 if h == wdirhex:
482 if h == wdirhex:
483 return b'%s+' % shorthex(hex(ctx.p1().node()))
483 return b'%s+' % shorthex(hex(ctx.p1().node()))
484 else:
484 else:
485 return b'%s ' % shorthex(h)
485 return b'%s ' % shorthex(h)
486
486
487 else:
487 else:
488 formatrev = b'%d'.__mod__
488 formatrev = b'%d'.__mod__
489 formathex = shorthex
489 formathex = shorthex
490
490
491 opmap = [
491 opmap = [
492 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
492 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
493 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
493 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
494 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
494 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
495 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
495 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
496 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
496 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
497 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
497 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
498 ]
498 ]
499 opnamemap = {
499 opnamemap = {
500 b'rev': b'number',
500 b'rev': b'number',
501 b'node': b'changeset',
501 b'node': b'changeset',
502 b'path': b'file',
502 b'path': b'file',
503 b'lineno': b'line_number',
503 b'lineno': b'line_number',
504 }
504 }
505
505
506 if rootfm.isplain():
506 if rootfm.isplain():
507
507
508 def makefunc(get, fmt):
508 def makefunc(get, fmt):
509 return lambda x: fmt(get(x))
509 return lambda x: fmt(get(x))
510
510
511 else:
511 else:
512
512
513 def makefunc(get, fmt):
513 def makefunc(get, fmt):
514 return get
514 return get
515
515
516 datahint = rootfm.datahint()
516 datahint = rootfm.datahint()
517 funcmap = [
517 funcmap = [
518 (makefunc(get, fmt), sep)
518 (makefunc(get, fmt), sep)
519 for fn, sep, get, fmt in opmap
519 for fn, sep, get, fmt in opmap
520 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
520 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
521 ]
521 ]
522 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
522 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
523 fields = b' '.join(
523 fields = b' '.join(
524 fn
524 fn
525 for fn, sep, get, fmt in opmap
525 for fn, sep, get, fmt in opmap
526 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
526 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
527 )
527 )
528
528
529 def bad(x, y):
529 def bad(x, y):
530 raise error.Abort(b"%s: %s" % (x, y))
530 raise error.Abort(b"%s: %s" % (x, y))
531
531
532 m = scmutil.match(ctx, pats, opts, badfn=bad)
532 m = scmutil.match(ctx, pats, opts, badfn=bad)
533
533
534 follow = not opts.get(b'no_follow')
534 follow = not opts.get(b'no_follow')
535 diffopts = patch.difffeatureopts(
535 diffopts = patch.difffeatureopts(
536 ui, opts, section=b'annotate', whitespace=True
536 ui, opts, section=b'annotate', whitespace=True
537 )
537 )
538 skiprevs = opts.get(b'skip')
538 skiprevs = opts.get(b'skip')
539 if skiprevs:
539 if skiprevs:
540 skiprevs = scmutil.revrange(repo, skiprevs)
540 skiprevs = scmutil.revrange(repo, skiprevs)
541
541
542 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
542 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
543 for abs in ctx.walk(m):
543 for abs in ctx.walk(m):
544 fctx = ctx[abs]
544 fctx = ctx[abs]
545 rootfm.startitem()
545 rootfm.startitem()
546 rootfm.data(path=abs)
546 rootfm.data(path=abs)
547 if not opts.get(b'text') and fctx.isbinary():
547 if not opts.get(b'text') and fctx.isbinary():
548 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
548 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
549 continue
549 continue
550
550
551 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
551 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
552 lines = fctx.annotate(
552 lines = fctx.annotate(
553 follow=follow, skiprevs=skiprevs, diffopts=diffopts
553 follow=follow, skiprevs=skiprevs, diffopts=diffopts
554 )
554 )
555 if not lines:
555 if not lines:
556 fm.end()
556 fm.end()
557 continue
557 continue
558 formats = []
558 formats = []
559 pieces = []
559 pieces = []
560
560
561 for f, sep in funcmap:
561 for f, sep in funcmap:
562 l = [f(n) for n in lines]
562 l = [f(n) for n in lines]
563 if fm.isplain():
563 if fm.isplain():
564 sizes = [encoding.colwidth(x) for x in l]
564 sizes = [encoding.colwidth(x) for x in l]
565 ml = max(sizes)
565 ml = max(sizes)
566 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
566 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
567 else:
567 else:
568 formats.append([b'%s'] * len(l))
568 formats.append([b'%s'] * len(l))
569 pieces.append(l)
569 pieces.append(l)
570
570
571 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
571 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
572 fm.startitem()
572 fm.startitem()
573 fm.context(fctx=n.fctx)
573 fm.context(fctx=n.fctx)
574 fm.write(fields, b"".join(f), *p)
574 fm.write(fields, b"".join(f), *p)
575 if n.skip:
575 if n.skip:
576 fmt = b"* %s"
576 fmt = b"* %s"
577 else:
577 else:
578 fmt = b": %s"
578 fmt = b": %s"
579 fm.write(b'line', fmt, n.text)
579 fm.write(b'line', fmt, n.text)
580
580
581 if not lines[-1].text.endswith(b'\n'):
581 if not lines[-1].text.endswith(b'\n'):
582 fm.plain(b'\n')
582 fm.plain(b'\n')
583 fm.end()
583 fm.end()
584
584
585 rootfm.end()
585 rootfm.end()
586
586
587
587
588 @command(
588 @command(
589 b'archive',
589 b'archive',
590 [
590 [
591 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
591 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
592 (
592 (
593 b'p',
593 b'p',
594 b'prefix',
594 b'prefix',
595 b'',
595 b'',
596 _(b'directory prefix for files in archive'),
596 _(b'directory prefix for files in archive'),
597 _(b'PREFIX'),
597 _(b'PREFIX'),
598 ),
598 ),
599 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
599 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
600 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
600 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
601 ]
601 ]
602 + subrepoopts
602 + subrepoopts
603 + walkopts,
603 + walkopts,
604 _(b'[OPTION]... DEST'),
604 _(b'[OPTION]... DEST'),
605 helpcategory=command.CATEGORY_IMPORT_EXPORT,
605 helpcategory=command.CATEGORY_IMPORT_EXPORT,
606 )
606 )
607 def archive(ui, repo, dest, **opts):
607 def archive(ui, repo, dest, **opts):
608 """create an unversioned archive of a repository revision
608 """create an unversioned archive of a repository revision
609
609
610 By default, the revision used is the parent of the working
610 By default, the revision used is the parent of the working
611 directory; use -r/--rev to specify a different revision.
611 directory; use -r/--rev to specify a different revision.
612
612
613 The archive type is automatically detected based on file
613 The archive type is automatically detected based on file
614 extension (to override, use -t/--type).
614 extension (to override, use -t/--type).
615
615
616 .. container:: verbose
616 .. container:: verbose
617
617
618 Examples:
618 Examples:
619
619
620 - create a zip file containing the 1.0 release::
620 - create a zip file containing the 1.0 release::
621
621
622 hg archive -r 1.0 project-1.0.zip
622 hg archive -r 1.0 project-1.0.zip
623
623
624 - create a tarball excluding .hg files::
624 - create a tarball excluding .hg files::
625
625
626 hg archive project.tar.gz -X ".hg*"
626 hg archive project.tar.gz -X ".hg*"
627
627
628 Valid types are:
628 Valid types are:
629
629
630 :``files``: a directory full of files (default)
630 :``files``: a directory full of files (default)
631 :``tar``: tar archive, uncompressed
631 :``tar``: tar archive, uncompressed
632 :``tbz2``: tar archive, compressed using bzip2
632 :``tbz2``: tar archive, compressed using bzip2
633 :``tgz``: tar archive, compressed using gzip
633 :``tgz``: tar archive, compressed using gzip
634 :``txz``: tar archive, compressed using lzma (only in Python 3)
634 :``txz``: tar archive, compressed using lzma (only in Python 3)
635 :``uzip``: zip archive, uncompressed
635 :``uzip``: zip archive, uncompressed
636 :``zip``: zip archive, compressed using deflate
636 :``zip``: zip archive, compressed using deflate
637
637
638 The exact name of the destination archive or directory is given
638 The exact name of the destination archive or directory is given
639 using a format string; see :hg:`help export` for details.
639 using a format string; see :hg:`help export` for details.
640
640
641 Each member added to an archive file has a directory prefix
641 Each member added to an archive file has a directory prefix
642 prepended. Use -p/--prefix to specify a format string for the
642 prepended. Use -p/--prefix to specify a format string for the
643 prefix. The default is the basename of the archive, with suffixes
643 prefix. The default is the basename of the archive, with suffixes
644 removed.
644 removed.
645
645
646 Returns 0 on success.
646 Returns 0 on success.
647 """
647 """
648
648
649 opts = pycompat.byteskwargs(opts)
649 opts = pycompat.byteskwargs(opts)
650 rev = opts.get(b'rev')
650 rev = opts.get(b'rev')
651 if rev:
651 if rev:
652 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
652 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
653 ctx = scmutil.revsingle(repo, rev)
653 ctx = scmutil.revsingle(repo, rev)
654 if not ctx:
654 if not ctx:
655 raise error.InputError(
655 raise error.InputError(
656 _(b'no working directory: please specify a revision')
656 _(b'no working directory: please specify a revision')
657 )
657 )
658 node = ctx.node()
658 node = ctx.node()
659 dest = cmdutil.makefilename(ctx, dest)
659 dest = cmdutil.makefilename(ctx, dest)
660 if os.path.realpath(dest) == repo.root:
660 if os.path.realpath(dest) == repo.root:
661 raise error.InputError(_(b'repository root cannot be destination'))
661 raise error.InputError(_(b'repository root cannot be destination'))
662
662
663 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
663 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
664 prefix = opts.get(b'prefix')
664 prefix = opts.get(b'prefix')
665
665
666 if dest == b'-':
666 if dest == b'-':
667 if kind == b'files':
667 if kind == b'files':
668 raise error.InputError(_(b'cannot archive plain files to stdout'))
668 raise error.InputError(_(b'cannot archive plain files to stdout'))
669 dest = cmdutil.makefileobj(ctx, dest)
669 dest = cmdutil.makefileobj(ctx, dest)
670 if not prefix:
670 if not prefix:
671 prefix = os.path.basename(repo.root) + b'-%h'
671 prefix = os.path.basename(repo.root) + b'-%h'
672
672
673 prefix = cmdutil.makefilename(ctx, prefix)
673 prefix = cmdutil.makefilename(ctx, prefix)
674 match = scmutil.match(ctx, [], opts)
674 match = scmutil.match(ctx, [], opts)
675 archival.archive(
675 archival.archive(
676 repo,
676 repo,
677 dest,
677 dest,
678 node,
678 node,
679 kind,
679 kind,
680 not opts.get(b'no_decode'),
680 not opts.get(b'no_decode'),
681 match,
681 match,
682 prefix,
682 prefix,
683 subrepos=opts.get(b'subrepos'),
683 subrepos=opts.get(b'subrepos'),
684 )
684 )
685
685
686
686
687 @command(
687 @command(
688 b'backout',
688 b'backout',
689 [
689 [
690 (
690 (
691 b'',
691 b'',
692 b'merge',
692 b'merge',
693 None,
693 None,
694 _(b'merge with old dirstate parent after backout'),
694 _(b'merge with old dirstate parent after backout'),
695 ),
695 ),
696 (
696 (
697 b'',
697 b'',
698 b'commit',
698 b'commit',
699 None,
699 None,
700 _(b'commit if no conflicts were encountered (DEPRECATED)'),
700 _(b'commit if no conflicts were encountered (DEPRECATED)'),
701 ),
701 ),
702 (b'', b'no-commit', None, _(b'do not commit')),
702 (b'', b'no-commit', None, _(b'do not commit')),
703 (
703 (
704 b'',
704 b'',
705 b'parent',
705 b'parent',
706 b'',
706 b'',
707 _(b'parent to choose when backing out merge (DEPRECATED)'),
707 _(b'parent to choose when backing out merge (DEPRECATED)'),
708 _(b'REV'),
708 _(b'REV'),
709 ),
709 ),
710 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
710 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
711 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
711 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
712 ]
712 ]
713 + mergetoolopts
713 + mergetoolopts
714 + walkopts
714 + walkopts
715 + commitopts
715 + commitopts
716 + commitopts2,
716 + commitopts2,
717 _(b'[OPTION]... [-r] REV'),
717 _(b'[OPTION]... [-r] REV'),
718 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
718 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
719 )
719 )
720 def backout(ui, repo, node=None, rev=None, **opts):
720 def backout(ui, repo, node=None, rev=None, **opts):
721 """reverse effect of earlier changeset
721 """reverse effect of earlier changeset
722
722
723 Prepare a new changeset with the effect of REV undone in the
723 Prepare a new changeset with the effect of REV undone in the
724 current working directory. If no conflicts were encountered,
724 current working directory. If no conflicts were encountered,
725 it will be committed immediately.
725 it will be committed immediately.
726
726
727 If REV is the parent of the working directory, then this new changeset
727 If REV is the parent of the working directory, then this new changeset
728 is committed automatically (unless --no-commit is specified).
728 is committed automatically (unless --no-commit is specified).
729
729
730 .. note::
730 .. note::
731
731
732 :hg:`backout` cannot be used to fix either an unwanted or
732 :hg:`backout` cannot be used to fix either an unwanted or
733 incorrect merge.
733 incorrect merge.
734
734
735 .. container:: verbose
735 .. container:: verbose
736
736
737 Examples:
737 Examples:
738
738
739 - Reverse the effect of the parent of the working directory.
739 - Reverse the effect of the parent of the working directory.
740 This backout will be committed immediately::
740 This backout will be committed immediately::
741
741
742 hg backout -r .
742 hg backout -r .
743
743
744 - Reverse the effect of previous bad revision 23::
744 - Reverse the effect of previous bad revision 23::
745
745
746 hg backout -r 23
746 hg backout -r 23
747
747
748 - Reverse the effect of previous bad revision 23 and
748 - Reverse the effect of previous bad revision 23 and
749 leave changes uncommitted::
749 leave changes uncommitted::
750
750
751 hg backout -r 23 --no-commit
751 hg backout -r 23 --no-commit
752 hg commit -m "Backout revision 23"
752 hg commit -m "Backout revision 23"
753
753
754 By default, the pending changeset will have one parent,
754 By default, the pending changeset will have one parent,
755 maintaining a linear history. With --merge, the pending
755 maintaining a linear history. With --merge, the pending
756 changeset will instead have two parents: the old parent of the
756 changeset will instead have two parents: the old parent of the
757 working directory and a new child of REV that simply undoes REV.
757 working directory and a new child of REV that simply undoes REV.
758
758
759 Before version 1.7, the behavior without --merge was equivalent
759 Before version 1.7, the behavior without --merge was equivalent
760 to specifying --merge followed by :hg:`update --clean .` to
760 to specifying --merge followed by :hg:`update --clean .` to
761 cancel the merge and leave the child of REV as a head to be
761 cancel the merge and leave the child of REV as a head to be
762 merged separately.
762 merged separately.
763
763
764 See :hg:`help dates` for a list of formats valid for -d/--date.
764 See :hg:`help dates` for a list of formats valid for -d/--date.
765
765
766 See :hg:`help revert` for a way to restore files to the state
766 See :hg:`help revert` for a way to restore files to the state
767 of another revision.
767 of another revision.
768
768
769 Returns 0 on success, 1 if nothing to backout or there are unresolved
769 Returns 0 on success, 1 if nothing to backout or there are unresolved
770 files.
770 files.
771 """
771 """
772 with repo.wlock(), repo.lock():
772 with repo.wlock(), repo.lock():
773 return _dobackout(ui, repo, node, rev, **opts)
773 return _dobackout(ui, repo, node, rev, **opts)
774
774
775
775
776 def _dobackout(ui, repo, node=None, rev=None, **opts):
776 def _dobackout(ui, repo, node=None, rev=None, **opts):
777 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
777 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
778 opts = pycompat.byteskwargs(opts)
778 opts = pycompat.byteskwargs(opts)
779
779
780 if rev and node:
780 if rev and node:
781 raise error.InputError(_(b"please specify just one revision"))
781 raise error.InputError(_(b"please specify just one revision"))
782
782
783 if not rev:
783 if not rev:
784 rev = node
784 rev = node
785
785
786 if not rev:
786 if not rev:
787 raise error.InputError(_(b"please specify a revision to backout"))
787 raise error.InputError(_(b"please specify a revision to backout"))
788
788
789 date = opts.get(b'date')
789 date = opts.get(b'date')
790 if date:
790 if date:
791 opts[b'date'] = dateutil.parsedate(date)
791 opts[b'date'] = dateutil.parsedate(date)
792
792
793 cmdutil.checkunfinished(repo)
793 cmdutil.checkunfinished(repo)
794 cmdutil.bailifchanged(repo)
794 cmdutil.bailifchanged(repo)
795 ctx = scmutil.revsingle(repo, rev)
795 ctx = scmutil.revsingle(repo, rev)
796 node = ctx.node()
796 node = ctx.node()
797
797
798 op1, op2 = repo.dirstate.parents()
798 op1, op2 = repo.dirstate.parents()
799 if not repo.changelog.isancestor(node, op1):
799 if not repo.changelog.isancestor(node, op1):
800 raise error.InputError(
800 raise error.InputError(
801 _(b'cannot backout change that is not an ancestor')
801 _(b'cannot backout change that is not an ancestor')
802 )
802 )
803
803
804 p1, p2 = repo.changelog.parents(node)
804 p1, p2 = repo.changelog.parents(node)
805 if p1 == nullid:
805 if p1 == nullid:
806 raise error.InputError(_(b'cannot backout a change with no parents'))
806 raise error.InputError(_(b'cannot backout a change with no parents'))
807 if p2 != nullid:
807 if p2 != nullid:
808 if not opts.get(b'parent'):
808 if not opts.get(b'parent'):
809 raise error.InputError(_(b'cannot backout a merge changeset'))
809 raise error.InputError(_(b'cannot backout a merge changeset'))
810 p = repo.lookup(opts[b'parent'])
810 p = repo.lookup(opts[b'parent'])
811 if p not in (p1, p2):
811 if p not in (p1, p2):
812 raise error.InputError(
812 raise error.InputError(
813 _(b'%s is not a parent of %s') % (short(p), short(node))
813 _(b'%s is not a parent of %s') % (short(p), short(node))
814 )
814 )
815 parent = p
815 parent = p
816 else:
816 else:
817 if opts.get(b'parent'):
817 if opts.get(b'parent'):
818 raise error.InputError(
818 raise error.InputError(
819 _(b'cannot use --parent on non-merge changeset')
819 _(b'cannot use --parent on non-merge changeset')
820 )
820 )
821 parent = p1
821 parent = p1
822
822
823 # the backout should appear on the same branch
823 # the backout should appear on the same branch
824 branch = repo.dirstate.branch()
824 branch = repo.dirstate.branch()
825 bheads = repo.branchheads(branch)
825 bheads = repo.branchheads(branch)
826 rctx = scmutil.revsingle(repo, hex(parent))
826 rctx = scmutil.revsingle(repo, hex(parent))
827 if not opts.get(b'merge') and op1 != node:
827 if not opts.get(b'merge') and op1 != node:
828 with dirstateguard.dirstateguard(repo, b'backout'):
828 with dirstateguard.dirstateguard(repo, b'backout'):
829 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
829 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
830 with ui.configoverride(overrides, b'backout'):
830 with ui.configoverride(overrides, b'backout'):
831 stats = mergemod.back_out(ctx, parent=repo[parent])
831 stats = mergemod.back_out(ctx, parent=repo[parent])
832 repo.setparents(op1, op2)
832 repo.setparents(op1, op2)
833 hg._showstats(repo, stats)
833 hg._showstats(repo, stats)
834 if stats.unresolvedcount:
834 if stats.unresolvedcount:
835 repo.ui.status(
835 repo.ui.status(
836 _(b"use 'hg resolve' to retry unresolved file merges\n")
836 _(b"use 'hg resolve' to retry unresolved file merges\n")
837 )
837 )
838 return 1
838 return 1
839 else:
839 else:
840 hg.clean(repo, node, show_stats=False)
840 hg.clean(repo, node, show_stats=False)
841 repo.dirstate.setbranch(branch)
841 repo.dirstate.setbranch(branch)
842 cmdutil.revert(ui, repo, rctx)
842 cmdutil.revert(ui, repo, rctx)
843
843
844 if opts.get(b'no_commit'):
844 if opts.get(b'no_commit'):
845 msg = _(b"changeset %s backed out, don't forget to commit.\n")
845 msg = _(b"changeset %s backed out, don't forget to commit.\n")
846 ui.status(msg % short(node))
846 ui.status(msg % short(node))
847 return 0
847 return 0
848
848
849 def commitfunc(ui, repo, message, match, opts):
849 def commitfunc(ui, repo, message, match, opts):
850 editform = b'backout'
850 editform = b'backout'
851 e = cmdutil.getcommiteditor(
851 e = cmdutil.getcommiteditor(
852 editform=editform, **pycompat.strkwargs(opts)
852 editform=editform, **pycompat.strkwargs(opts)
853 )
853 )
854 if not message:
854 if not message:
855 # we don't translate commit messages
855 # we don't translate commit messages
856 message = b"Backed out changeset %s" % short(node)
856 message = b"Backed out changeset %s" % short(node)
857 e = cmdutil.getcommiteditor(edit=True, editform=editform)
857 e = cmdutil.getcommiteditor(edit=True, editform=editform)
858 return repo.commit(
858 return repo.commit(
859 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
859 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
860 )
860 )
861
861
862 # save to detect changes
862 # save to detect changes
863 tip = repo.changelog.tip()
863 tip = repo.changelog.tip()
864
864
865 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
865 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
866 if not newnode:
866 if not newnode:
867 ui.status(_(b"nothing changed\n"))
867 ui.status(_(b"nothing changed\n"))
868 return 1
868 return 1
869 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
869 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
870
870
871 def nice(node):
871 def nice(node):
872 return b'%d:%s' % (repo.changelog.rev(node), short(node))
872 return b'%d:%s' % (repo.changelog.rev(node), short(node))
873
873
874 ui.status(
874 ui.status(
875 _(b'changeset %s backs out changeset %s\n')
875 _(b'changeset %s backs out changeset %s\n')
876 % (nice(newnode), nice(node))
876 % (nice(newnode), nice(node))
877 )
877 )
878 if opts.get(b'merge') and op1 != node:
878 if opts.get(b'merge') and op1 != node:
879 hg.clean(repo, op1, show_stats=False)
879 hg.clean(repo, op1, show_stats=False)
880 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
880 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
881 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
881 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
882 with ui.configoverride(overrides, b'backout'):
882 with ui.configoverride(overrides, b'backout'):
883 return hg.merge(repo[b'tip'])
883 return hg.merge(repo[b'tip'])
884 return 0
884 return 0
885
885
886
886
887 @command(
887 @command(
888 b'bisect',
888 b'bisect',
889 [
889 [
890 (b'r', b'reset', False, _(b'reset bisect state')),
890 (b'r', b'reset', False, _(b'reset bisect state')),
891 (b'g', b'good', False, _(b'mark changeset good')),
891 (b'g', b'good', False, _(b'mark changeset good')),
892 (b'b', b'bad', False, _(b'mark changeset bad')),
892 (b'b', b'bad', False, _(b'mark changeset bad')),
893 (b's', b'skip', False, _(b'skip testing changeset')),
893 (b's', b'skip', False, _(b'skip testing changeset')),
894 (b'e', b'extend', False, _(b'extend the bisect range')),
894 (b'e', b'extend', False, _(b'extend the bisect range')),
895 (
895 (
896 b'c',
896 b'c',
897 b'command',
897 b'command',
898 b'',
898 b'',
899 _(b'use command to check changeset state'),
899 _(b'use command to check changeset state'),
900 _(b'CMD'),
900 _(b'CMD'),
901 ),
901 ),
902 (b'U', b'noupdate', False, _(b'do not update to target')),
902 (b'U', b'noupdate', False, _(b'do not update to target')),
903 ],
903 ],
904 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
904 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
905 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
905 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
906 )
906 )
907 def bisect(
907 def bisect(
908 ui,
908 ui,
909 repo,
909 repo,
910 positional_1=None,
910 positional_1=None,
911 positional_2=None,
911 positional_2=None,
912 command=None,
912 command=None,
913 reset=None,
913 reset=None,
914 good=None,
914 good=None,
915 bad=None,
915 bad=None,
916 skip=None,
916 skip=None,
917 extend=None,
917 extend=None,
918 noupdate=None,
918 noupdate=None,
919 ):
919 ):
920 """subdivision search of changesets
920 """subdivision search of changesets
921
921
922 This command helps to find changesets which introduce problems. To
922 This command helps to find changesets which introduce problems. To
923 use, mark the earliest changeset you know exhibits the problem as
923 use, mark the earliest changeset you know exhibits the problem as
924 bad, then mark the latest changeset which is free from the problem
924 bad, then mark the latest changeset which is free from the problem
925 as good. Bisect will update your working directory to a revision
925 as good. Bisect will update your working directory to a revision
926 for testing (unless the -U/--noupdate option is specified). Once
926 for testing (unless the -U/--noupdate option is specified). Once
927 you have performed tests, mark the working directory as good or
927 you have performed tests, mark the working directory as good or
928 bad, and bisect will either update to another candidate changeset
928 bad, and bisect will either update to another candidate changeset
929 or announce that it has found the bad revision.
929 or announce that it has found the bad revision.
930
930
931 As a shortcut, you can also use the revision argument to mark a
931 As a shortcut, you can also use the revision argument to mark a
932 revision as good or bad without checking it out first.
932 revision as good or bad without checking it out first.
933
933
934 If you supply a command, it will be used for automatic bisection.
934 If you supply a command, it will be used for automatic bisection.
935 The environment variable HG_NODE will contain the ID of the
935 The environment variable HG_NODE will contain the ID of the
936 changeset being tested. The exit status of the command will be
936 changeset being tested. The exit status of the command will be
937 used to mark revisions as good or bad: status 0 means good, 125
937 used to mark revisions as good or bad: status 0 means good, 125
938 means to skip the revision, 127 (command not found) will abort the
938 means to skip the revision, 127 (command not found) will abort the
939 bisection, and any other non-zero exit status means the revision
939 bisection, and any other non-zero exit status means the revision
940 is bad.
940 is bad.
941
941
942 .. container:: verbose
942 .. container:: verbose
943
943
944 Some examples:
944 Some examples:
945
945
946 - start a bisection with known bad revision 34, and good revision 12::
946 - start a bisection with known bad revision 34, and good revision 12::
947
947
948 hg bisect --bad 34
948 hg bisect --bad 34
949 hg bisect --good 12
949 hg bisect --good 12
950
950
951 - advance the current bisection by marking current revision as good or
951 - advance the current bisection by marking current revision as good or
952 bad::
952 bad::
953
953
954 hg bisect --good
954 hg bisect --good
955 hg bisect --bad
955 hg bisect --bad
956
956
957 - mark the current revision, or a known revision, to be skipped (e.g. if
957 - mark the current revision, or a known revision, to be skipped (e.g. if
958 that revision is not usable because of another issue)::
958 that revision is not usable because of another issue)::
959
959
960 hg bisect --skip
960 hg bisect --skip
961 hg bisect --skip 23
961 hg bisect --skip 23
962
962
963 - skip all revisions that do not touch directories ``foo`` or ``bar``::
963 - skip all revisions that do not touch directories ``foo`` or ``bar``::
964
964
965 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
965 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
966
966
967 - forget the current bisection::
967 - forget the current bisection::
968
968
969 hg bisect --reset
969 hg bisect --reset
970
970
971 - use 'make && make tests' to automatically find the first broken
971 - use 'make && make tests' to automatically find the first broken
972 revision::
972 revision::
973
973
974 hg bisect --reset
974 hg bisect --reset
975 hg bisect --bad 34
975 hg bisect --bad 34
976 hg bisect --good 12
976 hg bisect --good 12
977 hg bisect --command "make && make tests"
977 hg bisect --command "make && make tests"
978
978
979 - see all changesets whose states are already known in the current
979 - see all changesets whose states are already known in the current
980 bisection::
980 bisection::
981
981
982 hg log -r "bisect(pruned)"
982 hg log -r "bisect(pruned)"
983
983
984 - see the changeset currently being bisected (especially useful
984 - see the changeset currently being bisected (especially useful
985 if running with -U/--noupdate)::
985 if running with -U/--noupdate)::
986
986
987 hg log -r "bisect(current)"
987 hg log -r "bisect(current)"
988
988
989 - see all changesets that took part in the current bisection::
989 - see all changesets that took part in the current bisection::
990
990
991 hg log -r "bisect(range)"
991 hg log -r "bisect(range)"
992
992
993 - you can even get a nice graph::
993 - you can even get a nice graph::
994
994
995 hg log --graph -r "bisect(range)"
995 hg log --graph -r "bisect(range)"
996
996
997 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
997 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
998
998
999 Returns 0 on success.
999 Returns 0 on success.
1000 """
1000 """
1001 rev = []
1001 rev = []
1002 # backward compatibility
1002 # backward compatibility
1003 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1003 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1004 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1004 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1005 cmd = positional_1
1005 cmd = positional_1
1006 rev.append(positional_2)
1006 rev.append(positional_2)
1007 if cmd == b"good":
1007 if cmd == b"good":
1008 good = True
1008 good = True
1009 elif cmd == b"bad":
1009 elif cmd == b"bad":
1010 bad = True
1010 bad = True
1011 else:
1011 else:
1012 reset = True
1012 reset = True
1013 elif positional_2:
1013 elif positional_2:
1014 raise error.InputError(_(b'incompatible arguments'))
1014 raise error.InputError(_(b'incompatible arguments'))
1015 elif positional_1 is not None:
1015 elif positional_1 is not None:
1016 rev.append(positional_1)
1016 rev.append(positional_1)
1017
1017
1018 incompatibles = {
1018 incompatibles = {
1019 b'--bad': bad,
1019 b'--bad': bad,
1020 b'--command': bool(command),
1020 b'--command': bool(command),
1021 b'--extend': extend,
1021 b'--extend': extend,
1022 b'--good': good,
1022 b'--good': good,
1023 b'--reset': reset,
1023 b'--reset': reset,
1024 b'--skip': skip,
1024 b'--skip': skip,
1025 }
1025 }
1026
1026
1027 enabled = [x for x in incompatibles if incompatibles[x]]
1027 enabled = [x for x in incompatibles if incompatibles[x]]
1028
1028
1029 if len(enabled) > 1:
1029 if len(enabled) > 1:
1030 raise error.InputError(
1030 raise error.InputError(
1031 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1031 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1032 )
1032 )
1033
1033
1034 if reset:
1034 if reset:
1035 hbisect.resetstate(repo)
1035 hbisect.resetstate(repo)
1036 return
1036 return
1037
1037
1038 state = hbisect.load_state(repo)
1038 state = hbisect.load_state(repo)
1039
1039
1040 if rev:
1040 if rev:
1041 nodes = [repo[i].node() for i in scmutil.revrange(repo, rev)]
1041 nodes = [repo[i].node() for i in scmutil.revrange(repo, rev)]
1042 else:
1042 else:
1043 nodes = [repo.lookup(b'.')]
1043 nodes = [repo.lookup(b'.')]
1044
1044
1045 # update state
1045 # update state
1046 if good or bad or skip:
1046 if good or bad or skip:
1047 if good:
1047 if good:
1048 state[b'good'] += nodes
1048 state[b'good'] += nodes
1049 elif bad:
1049 elif bad:
1050 state[b'bad'] += nodes
1050 state[b'bad'] += nodes
1051 elif skip:
1051 elif skip:
1052 state[b'skip'] += nodes
1052 state[b'skip'] += nodes
1053 hbisect.save_state(repo, state)
1053 hbisect.save_state(repo, state)
1054 if not (state[b'good'] and state[b'bad']):
1054 if not (state[b'good'] and state[b'bad']):
1055 return
1055 return
1056
1056
1057 def mayupdate(repo, node, show_stats=True):
1057 def mayupdate(repo, node, show_stats=True):
1058 """common used update sequence"""
1058 """common used update sequence"""
1059 if noupdate:
1059 if noupdate:
1060 return
1060 return
1061 cmdutil.checkunfinished(repo)
1061 cmdutil.checkunfinished(repo)
1062 cmdutil.bailifchanged(repo)
1062 cmdutil.bailifchanged(repo)
1063 return hg.clean(repo, node, show_stats=show_stats)
1063 return hg.clean(repo, node, show_stats=show_stats)
1064
1064
1065 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1065 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1066
1066
1067 if command:
1067 if command:
1068 changesets = 1
1068 changesets = 1
1069 if noupdate:
1069 if noupdate:
1070 try:
1070 try:
1071 node = state[b'current'][0]
1071 node = state[b'current'][0]
1072 except LookupError:
1072 except LookupError:
1073 raise error.StateError(
1073 raise error.StateError(
1074 _(
1074 _(
1075 b'current bisect revision is unknown - '
1075 b'current bisect revision is unknown - '
1076 b'start a new bisect to fix'
1076 b'start a new bisect to fix'
1077 )
1077 )
1078 )
1078 )
1079 else:
1079 else:
1080 node, p2 = repo.dirstate.parents()
1080 node, p2 = repo.dirstate.parents()
1081 if p2 != nullid:
1081 if p2 != nullid:
1082 raise error.StateError(_(b'current bisect revision is a merge'))
1082 raise error.StateError(_(b'current bisect revision is a merge'))
1083 if rev:
1083 if rev:
1084 if not nodes:
1084 if not nodes:
1085 raise error.Abort(_(b'empty revision set'))
1085 raise error.Abort(_(b'empty revision set'))
1086 node = repo[nodes[-1]].node()
1086 node = repo[nodes[-1]].node()
1087 with hbisect.restore_state(repo, state, node):
1087 with hbisect.restore_state(repo, state, node):
1088 while changesets:
1088 while changesets:
1089 # update state
1089 # update state
1090 state[b'current'] = [node]
1090 state[b'current'] = [node]
1091 hbisect.save_state(repo, state)
1091 hbisect.save_state(repo, state)
1092 status = ui.system(
1092 status = ui.system(
1093 command,
1093 command,
1094 environ={b'HG_NODE': hex(node)},
1094 environ={b'HG_NODE': hex(node)},
1095 blockedtag=b'bisect_check',
1095 blockedtag=b'bisect_check',
1096 )
1096 )
1097 if status == 125:
1097 if status == 125:
1098 transition = b"skip"
1098 transition = b"skip"
1099 elif status == 0:
1099 elif status == 0:
1100 transition = b"good"
1100 transition = b"good"
1101 # status < 0 means process was killed
1101 # status < 0 means process was killed
1102 elif status == 127:
1102 elif status == 127:
1103 raise error.Abort(_(b"failed to execute %s") % command)
1103 raise error.Abort(_(b"failed to execute %s") % command)
1104 elif status < 0:
1104 elif status < 0:
1105 raise error.Abort(_(b"%s killed") % command)
1105 raise error.Abort(_(b"%s killed") % command)
1106 else:
1106 else:
1107 transition = b"bad"
1107 transition = b"bad"
1108 state[transition].append(node)
1108 state[transition].append(node)
1109 ctx = repo[node]
1109 ctx = repo[node]
1110 ui.status(
1110 summary = cmdutil.format_changeset_summary(ui, ctx, b'bisect')
1111 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1111 ui.status(_(b'changeset %s: %s\n') % (summary, transition))
1112 )
1113 hbisect.checkstate(state)
1112 hbisect.checkstate(state)
1114 # bisect
1113 # bisect
1115 nodes, changesets, bgood = hbisect.bisect(repo, state)
1114 nodes, changesets, bgood = hbisect.bisect(repo, state)
1116 # update to next check
1115 # update to next check
1117 node = nodes[0]
1116 node = nodes[0]
1118 mayupdate(repo, node, show_stats=False)
1117 mayupdate(repo, node, show_stats=False)
1119 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1118 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1120 return
1119 return
1121
1120
1122 hbisect.checkstate(state)
1121 hbisect.checkstate(state)
1123
1122
1124 # actually bisect
1123 # actually bisect
1125 nodes, changesets, good = hbisect.bisect(repo, state)
1124 nodes, changesets, good = hbisect.bisect(repo, state)
1126 if extend:
1125 if extend:
1127 if not changesets:
1126 if not changesets:
1128 extendnode = hbisect.extendrange(repo, state, nodes, good)
1127 extendctx = hbisect.extendrange(repo, state, nodes, good)
1129 if extendnode is not None:
1128 if extendctx is not None:
1130 ui.write(
1129 ui.write(
1131 _(b"Extending search to changeset %d:%s\n")
1130 _(b"Extending search to changeset %s\n")
1132 % (extendnode.rev(), extendnode)
1131 % cmdutil.format_changeset_summary(ui, extendctx, b'bisect')
1133 )
1132 )
1134 state[b'current'] = [extendnode.node()]
1133 state[b'current'] = [extendctx.node()]
1135 hbisect.save_state(repo, state)
1134 hbisect.save_state(repo, state)
1136 return mayupdate(repo, extendnode.node())
1135 return mayupdate(repo, extendctx.node())
1137 raise error.StateError(_(b"nothing to extend"))
1136 raise error.StateError(_(b"nothing to extend"))
1138
1137
1139 if changesets == 0:
1138 if changesets == 0:
1140 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1139 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1141 else:
1140 else:
1142 assert len(nodes) == 1 # only a single node can be tested next
1141 assert len(nodes) == 1 # only a single node can be tested next
1143 node = nodes[0]
1142 node = nodes[0]
1144 # compute the approximate number of remaining tests
1143 # compute the approximate number of remaining tests
1145 tests, size = 0, 2
1144 tests, size = 0, 2
1146 while size <= changesets:
1145 while size <= changesets:
1147 tests, size = tests + 1, size * 2
1146 tests, size = tests + 1, size * 2
1148 rev = repo.changelog.rev(node)
1147 rev = repo.changelog.rev(node)
1148 summary = cmdutil.format_changeset_summary(ui, repo[rev], b'bisect')
1149 ui.write(
1149 ui.write(
1150 _(
1150 _(
1151 b"Testing changeset %d:%s "
1151 b"Testing changeset %s "
1152 b"(%d changesets remaining, ~%d tests)\n"
1152 b"(%d changesets remaining, ~%d tests)\n"
1153 )
1153 )
1154 % (rev, short(node), changesets, tests)
1154 % (summary, changesets, tests)
1155 )
1155 )
1156 state[b'current'] = [node]
1156 state[b'current'] = [node]
1157 hbisect.save_state(repo, state)
1157 hbisect.save_state(repo, state)
1158 return mayupdate(repo, node)
1158 return mayupdate(repo, node)
1159
1159
1160
1160
1161 @command(
1161 @command(
1162 b'bookmarks|bookmark',
1162 b'bookmarks|bookmark',
1163 [
1163 [
1164 (b'f', b'force', False, _(b'force')),
1164 (b'f', b'force', False, _(b'force')),
1165 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1165 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1166 (b'd', b'delete', False, _(b'delete a given bookmark')),
1166 (b'd', b'delete', False, _(b'delete a given bookmark')),
1167 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1167 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1168 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1168 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1169 (b'l', b'list', False, _(b'list existing bookmarks')),
1169 (b'l', b'list', False, _(b'list existing bookmarks')),
1170 ]
1170 ]
1171 + formatteropts,
1171 + formatteropts,
1172 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1172 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1173 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1173 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1174 )
1174 )
1175 def bookmark(ui, repo, *names, **opts):
1175 def bookmark(ui, repo, *names, **opts):
1176 """create a new bookmark or list existing bookmarks
1176 """create a new bookmark or list existing bookmarks
1177
1177
1178 Bookmarks are labels on changesets to help track lines of development.
1178 Bookmarks are labels on changesets to help track lines of development.
1179 Bookmarks are unversioned and can be moved, renamed and deleted.
1179 Bookmarks are unversioned and can be moved, renamed and deleted.
1180 Deleting or moving a bookmark has no effect on the associated changesets.
1180 Deleting or moving a bookmark has no effect on the associated changesets.
1181
1181
1182 Creating or updating to a bookmark causes it to be marked as 'active'.
1182 Creating or updating to a bookmark causes it to be marked as 'active'.
1183 The active bookmark is indicated with a '*'.
1183 The active bookmark is indicated with a '*'.
1184 When a commit is made, the active bookmark will advance to the new commit.
1184 When a commit is made, the active bookmark will advance to the new commit.
1185 A plain :hg:`update` will also advance an active bookmark, if possible.
1185 A plain :hg:`update` will also advance an active bookmark, if possible.
1186 Updating away from a bookmark will cause it to be deactivated.
1186 Updating away from a bookmark will cause it to be deactivated.
1187
1187
1188 Bookmarks can be pushed and pulled between repositories (see
1188 Bookmarks can be pushed and pulled between repositories (see
1189 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1189 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1190 diverged, a new 'divergent bookmark' of the form 'name@path' will
1190 diverged, a new 'divergent bookmark' of the form 'name@path' will
1191 be created. Using :hg:`merge` will resolve the divergence.
1191 be created. Using :hg:`merge` will resolve the divergence.
1192
1192
1193 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1193 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1194 the active bookmark's name.
1194 the active bookmark's name.
1195
1195
1196 A bookmark named '@' has the special property that :hg:`clone` will
1196 A bookmark named '@' has the special property that :hg:`clone` will
1197 check it out by default if it exists.
1197 check it out by default if it exists.
1198
1198
1199 .. container:: verbose
1199 .. container:: verbose
1200
1200
1201 Template:
1201 Template:
1202
1202
1203 The following keywords are supported in addition to the common template
1203 The following keywords are supported in addition to the common template
1204 keywords and functions such as ``{bookmark}``. See also
1204 keywords and functions such as ``{bookmark}``. See also
1205 :hg:`help templates`.
1205 :hg:`help templates`.
1206
1206
1207 :active: Boolean. True if the bookmark is active.
1207 :active: Boolean. True if the bookmark is active.
1208
1208
1209 Examples:
1209 Examples:
1210
1210
1211 - create an active bookmark for a new line of development::
1211 - create an active bookmark for a new line of development::
1212
1212
1213 hg book new-feature
1213 hg book new-feature
1214
1214
1215 - create an inactive bookmark as a place marker::
1215 - create an inactive bookmark as a place marker::
1216
1216
1217 hg book -i reviewed
1217 hg book -i reviewed
1218
1218
1219 - create an inactive bookmark on another changeset::
1219 - create an inactive bookmark on another changeset::
1220
1220
1221 hg book -r .^ tested
1221 hg book -r .^ tested
1222
1222
1223 - rename bookmark turkey to dinner::
1223 - rename bookmark turkey to dinner::
1224
1224
1225 hg book -m turkey dinner
1225 hg book -m turkey dinner
1226
1226
1227 - move the '@' bookmark from another branch::
1227 - move the '@' bookmark from another branch::
1228
1228
1229 hg book -f @
1229 hg book -f @
1230
1230
1231 - print only the active bookmark name::
1231 - print only the active bookmark name::
1232
1232
1233 hg book -ql .
1233 hg book -ql .
1234 """
1234 """
1235 opts = pycompat.byteskwargs(opts)
1235 opts = pycompat.byteskwargs(opts)
1236 force = opts.get(b'force')
1236 force = opts.get(b'force')
1237 rev = opts.get(b'rev')
1237 rev = opts.get(b'rev')
1238 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1238 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1239
1239
1240 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1240 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1241 if action:
1241 if action:
1242 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1242 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1243 elif names or rev:
1243 elif names or rev:
1244 action = b'add'
1244 action = b'add'
1245 elif inactive:
1245 elif inactive:
1246 action = b'inactive' # meaning deactivate
1246 action = b'inactive' # meaning deactivate
1247 else:
1247 else:
1248 action = b'list'
1248 action = b'list'
1249
1249
1250 cmdutil.check_incompatible_arguments(
1250 cmdutil.check_incompatible_arguments(
1251 opts, b'inactive', [b'delete', b'list']
1251 opts, b'inactive', [b'delete', b'list']
1252 )
1252 )
1253 if not names and action in {b'add', b'delete'}:
1253 if not names and action in {b'add', b'delete'}:
1254 raise error.InputError(_(b"bookmark name required"))
1254 raise error.InputError(_(b"bookmark name required"))
1255
1255
1256 if action in {b'add', b'delete', b'rename', b'inactive'}:
1256 if action in {b'add', b'delete', b'rename', b'inactive'}:
1257 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1257 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1258 if action == b'delete':
1258 if action == b'delete':
1259 names = pycompat.maplist(repo._bookmarks.expandname, names)
1259 names = pycompat.maplist(repo._bookmarks.expandname, names)
1260 bookmarks.delete(repo, tr, names)
1260 bookmarks.delete(repo, tr, names)
1261 elif action == b'rename':
1261 elif action == b'rename':
1262 if not names:
1262 if not names:
1263 raise error.InputError(_(b"new bookmark name required"))
1263 raise error.InputError(_(b"new bookmark name required"))
1264 elif len(names) > 1:
1264 elif len(names) > 1:
1265 raise error.InputError(
1265 raise error.InputError(
1266 _(b"only one new bookmark name allowed")
1266 _(b"only one new bookmark name allowed")
1267 )
1267 )
1268 oldname = repo._bookmarks.expandname(opts[b'rename'])
1268 oldname = repo._bookmarks.expandname(opts[b'rename'])
1269 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1269 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1270 elif action == b'add':
1270 elif action == b'add':
1271 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1271 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1272 elif action == b'inactive':
1272 elif action == b'inactive':
1273 if len(repo._bookmarks) == 0:
1273 if len(repo._bookmarks) == 0:
1274 ui.status(_(b"no bookmarks set\n"))
1274 ui.status(_(b"no bookmarks set\n"))
1275 elif not repo._activebookmark:
1275 elif not repo._activebookmark:
1276 ui.status(_(b"no active bookmark\n"))
1276 ui.status(_(b"no active bookmark\n"))
1277 else:
1277 else:
1278 bookmarks.deactivate(repo)
1278 bookmarks.deactivate(repo)
1279 elif action == b'list':
1279 elif action == b'list':
1280 names = pycompat.maplist(repo._bookmarks.expandname, names)
1280 names = pycompat.maplist(repo._bookmarks.expandname, names)
1281 with ui.formatter(b'bookmarks', opts) as fm:
1281 with ui.formatter(b'bookmarks', opts) as fm:
1282 bookmarks.printbookmarks(ui, repo, fm, names)
1282 bookmarks.printbookmarks(ui, repo, fm, names)
1283 else:
1283 else:
1284 raise error.ProgrammingError(b'invalid action: %s' % action)
1284 raise error.ProgrammingError(b'invalid action: %s' % action)
1285
1285
1286
1286
1287 @command(
1287 @command(
1288 b'branch',
1288 b'branch',
1289 [
1289 [
1290 (
1290 (
1291 b'f',
1291 b'f',
1292 b'force',
1292 b'force',
1293 None,
1293 None,
1294 _(b'set branch name even if it shadows an existing branch'),
1294 _(b'set branch name even if it shadows an existing branch'),
1295 ),
1295 ),
1296 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1296 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1297 (
1297 (
1298 b'r',
1298 b'r',
1299 b'rev',
1299 b'rev',
1300 [],
1300 [],
1301 _(b'change branches of the given revs (EXPERIMENTAL)'),
1301 _(b'change branches of the given revs (EXPERIMENTAL)'),
1302 ),
1302 ),
1303 ],
1303 ],
1304 _(b'[-fC] [NAME]'),
1304 _(b'[-fC] [NAME]'),
1305 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1305 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1306 )
1306 )
1307 def branch(ui, repo, label=None, **opts):
1307 def branch(ui, repo, label=None, **opts):
1308 """set or show the current branch name
1308 """set or show the current branch name
1309
1309
1310 .. note::
1310 .. note::
1311
1311
1312 Branch names are permanent and global. Use :hg:`bookmark` to create a
1312 Branch names are permanent and global. Use :hg:`bookmark` to create a
1313 light-weight bookmark instead. See :hg:`help glossary` for more
1313 light-weight bookmark instead. See :hg:`help glossary` for more
1314 information about named branches and bookmarks.
1314 information about named branches and bookmarks.
1315
1315
1316 With no argument, show the current branch name. With one argument,
1316 With no argument, show the current branch name. With one argument,
1317 set the working directory branch name (the branch will not exist
1317 set the working directory branch name (the branch will not exist
1318 in the repository until the next commit). Standard practice
1318 in the repository until the next commit). Standard practice
1319 recommends that primary development take place on the 'default'
1319 recommends that primary development take place on the 'default'
1320 branch.
1320 branch.
1321
1321
1322 Unless -f/--force is specified, branch will not let you set a
1322 Unless -f/--force is specified, branch will not let you set a
1323 branch name that already exists.
1323 branch name that already exists.
1324
1324
1325 Use -C/--clean to reset the working directory branch to that of
1325 Use -C/--clean to reset the working directory branch to that of
1326 the parent of the working directory, negating a previous branch
1326 the parent of the working directory, negating a previous branch
1327 change.
1327 change.
1328
1328
1329 Use the command :hg:`update` to switch to an existing branch. Use
1329 Use the command :hg:`update` to switch to an existing branch. Use
1330 :hg:`commit --close-branch` to mark this branch head as closed.
1330 :hg:`commit --close-branch` to mark this branch head as closed.
1331 When all heads of a branch are closed, the branch will be
1331 When all heads of a branch are closed, the branch will be
1332 considered closed.
1332 considered closed.
1333
1333
1334 Returns 0 on success.
1334 Returns 0 on success.
1335 """
1335 """
1336 opts = pycompat.byteskwargs(opts)
1336 opts = pycompat.byteskwargs(opts)
1337 revs = opts.get(b'rev')
1337 revs = opts.get(b'rev')
1338 if label:
1338 if label:
1339 label = label.strip()
1339 label = label.strip()
1340
1340
1341 if not opts.get(b'clean') and not label:
1341 if not opts.get(b'clean') and not label:
1342 if revs:
1342 if revs:
1343 raise error.InputError(
1343 raise error.InputError(
1344 _(b"no branch name specified for the revisions")
1344 _(b"no branch name specified for the revisions")
1345 )
1345 )
1346 ui.write(b"%s\n" % repo.dirstate.branch())
1346 ui.write(b"%s\n" % repo.dirstate.branch())
1347 return
1347 return
1348
1348
1349 with repo.wlock():
1349 with repo.wlock():
1350 if opts.get(b'clean'):
1350 if opts.get(b'clean'):
1351 label = repo[b'.'].branch()
1351 label = repo[b'.'].branch()
1352 repo.dirstate.setbranch(label)
1352 repo.dirstate.setbranch(label)
1353 ui.status(_(b'reset working directory to branch %s\n') % label)
1353 ui.status(_(b'reset working directory to branch %s\n') % label)
1354 elif label:
1354 elif label:
1355
1355
1356 scmutil.checknewlabel(repo, label, b'branch')
1356 scmutil.checknewlabel(repo, label, b'branch')
1357 if revs:
1357 if revs:
1358 return cmdutil.changebranch(ui, repo, revs, label, opts)
1358 return cmdutil.changebranch(ui, repo, revs, label, opts)
1359
1359
1360 if not opts.get(b'force') and label in repo.branchmap():
1360 if not opts.get(b'force') and label in repo.branchmap():
1361 if label not in [p.branch() for p in repo[None].parents()]:
1361 if label not in [p.branch() for p in repo[None].parents()]:
1362 raise error.InputError(
1362 raise error.InputError(
1363 _(b'a branch of the same name already exists'),
1363 _(b'a branch of the same name already exists'),
1364 # i18n: "it" refers to an existing branch
1364 # i18n: "it" refers to an existing branch
1365 hint=_(b"use 'hg update' to switch to it"),
1365 hint=_(b"use 'hg update' to switch to it"),
1366 )
1366 )
1367
1367
1368 repo.dirstate.setbranch(label)
1368 repo.dirstate.setbranch(label)
1369 ui.status(_(b'marked working directory as branch %s\n') % label)
1369 ui.status(_(b'marked working directory as branch %s\n') % label)
1370
1370
1371 # find any open named branches aside from default
1371 # find any open named branches aside from default
1372 for n, h, t, c in repo.branchmap().iterbranches():
1372 for n, h, t, c in repo.branchmap().iterbranches():
1373 if n != b"default" and not c:
1373 if n != b"default" and not c:
1374 return 0
1374 return 0
1375 ui.status(
1375 ui.status(
1376 _(
1376 _(
1377 b'(branches are permanent and global, '
1377 b'(branches are permanent and global, '
1378 b'did you want a bookmark?)\n'
1378 b'did you want a bookmark?)\n'
1379 )
1379 )
1380 )
1380 )
1381
1381
1382
1382
1383 @command(
1383 @command(
1384 b'branches',
1384 b'branches',
1385 [
1385 [
1386 (
1386 (
1387 b'a',
1387 b'a',
1388 b'active',
1388 b'active',
1389 False,
1389 False,
1390 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1390 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1391 ),
1391 ),
1392 (b'c', b'closed', False, _(b'show normal and closed branches')),
1392 (b'c', b'closed', False, _(b'show normal and closed branches')),
1393 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1393 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1394 ]
1394 ]
1395 + formatteropts,
1395 + formatteropts,
1396 _(b'[-c]'),
1396 _(b'[-c]'),
1397 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1397 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1398 intents={INTENT_READONLY},
1398 intents={INTENT_READONLY},
1399 )
1399 )
1400 def branches(ui, repo, active=False, closed=False, **opts):
1400 def branches(ui, repo, active=False, closed=False, **opts):
1401 """list repository named branches
1401 """list repository named branches
1402
1402
1403 List the repository's named branches, indicating which ones are
1403 List the repository's named branches, indicating which ones are
1404 inactive. If -c/--closed is specified, also list branches which have
1404 inactive. If -c/--closed is specified, also list branches which have
1405 been marked closed (see :hg:`commit --close-branch`).
1405 been marked closed (see :hg:`commit --close-branch`).
1406
1406
1407 Use the command :hg:`update` to switch to an existing branch.
1407 Use the command :hg:`update` to switch to an existing branch.
1408
1408
1409 .. container:: verbose
1409 .. container:: verbose
1410
1410
1411 Template:
1411 Template:
1412
1412
1413 The following keywords are supported in addition to the common template
1413 The following keywords are supported in addition to the common template
1414 keywords and functions such as ``{branch}``. See also
1414 keywords and functions such as ``{branch}``. See also
1415 :hg:`help templates`.
1415 :hg:`help templates`.
1416
1416
1417 :active: Boolean. True if the branch is active.
1417 :active: Boolean. True if the branch is active.
1418 :closed: Boolean. True if the branch is closed.
1418 :closed: Boolean. True if the branch is closed.
1419 :current: Boolean. True if it is the current branch.
1419 :current: Boolean. True if it is the current branch.
1420
1420
1421 Returns 0.
1421 Returns 0.
1422 """
1422 """
1423
1423
1424 opts = pycompat.byteskwargs(opts)
1424 opts = pycompat.byteskwargs(opts)
1425 revs = opts.get(b'rev')
1425 revs = opts.get(b'rev')
1426 selectedbranches = None
1426 selectedbranches = None
1427 if revs:
1427 if revs:
1428 revs = scmutil.revrange(repo, revs)
1428 revs = scmutil.revrange(repo, revs)
1429 getbi = repo.revbranchcache().branchinfo
1429 getbi = repo.revbranchcache().branchinfo
1430 selectedbranches = {getbi(r)[0] for r in revs}
1430 selectedbranches = {getbi(r)[0] for r in revs}
1431
1431
1432 ui.pager(b'branches')
1432 ui.pager(b'branches')
1433 fm = ui.formatter(b'branches', opts)
1433 fm = ui.formatter(b'branches', opts)
1434 hexfunc = fm.hexfunc
1434 hexfunc = fm.hexfunc
1435
1435
1436 allheads = set(repo.heads())
1436 allheads = set(repo.heads())
1437 branches = []
1437 branches = []
1438 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1438 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1439 if selectedbranches is not None and tag not in selectedbranches:
1439 if selectedbranches is not None and tag not in selectedbranches:
1440 continue
1440 continue
1441 isactive = False
1441 isactive = False
1442 if not isclosed:
1442 if not isclosed:
1443 openheads = set(repo.branchmap().iteropen(heads))
1443 openheads = set(repo.branchmap().iteropen(heads))
1444 isactive = bool(openheads & allheads)
1444 isactive = bool(openheads & allheads)
1445 branches.append((tag, repo[tip], isactive, not isclosed))
1445 branches.append((tag, repo[tip], isactive, not isclosed))
1446 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1446 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1447
1447
1448 for tag, ctx, isactive, isopen in branches:
1448 for tag, ctx, isactive, isopen in branches:
1449 if active and not isactive:
1449 if active and not isactive:
1450 continue
1450 continue
1451 if isactive:
1451 if isactive:
1452 label = b'branches.active'
1452 label = b'branches.active'
1453 notice = b''
1453 notice = b''
1454 elif not isopen:
1454 elif not isopen:
1455 if not closed:
1455 if not closed:
1456 continue
1456 continue
1457 label = b'branches.closed'
1457 label = b'branches.closed'
1458 notice = _(b' (closed)')
1458 notice = _(b' (closed)')
1459 else:
1459 else:
1460 label = b'branches.inactive'
1460 label = b'branches.inactive'
1461 notice = _(b' (inactive)')
1461 notice = _(b' (inactive)')
1462 current = tag == repo.dirstate.branch()
1462 current = tag == repo.dirstate.branch()
1463 if current:
1463 if current:
1464 label = b'branches.current'
1464 label = b'branches.current'
1465
1465
1466 fm.startitem()
1466 fm.startitem()
1467 fm.write(b'branch', b'%s', tag, label=label)
1467 fm.write(b'branch', b'%s', tag, label=label)
1468 rev = ctx.rev()
1468 rev = ctx.rev()
1469 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1469 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1470 fmt = b' ' * padsize + b' %d:%s'
1470 fmt = b' ' * padsize + b' %d:%s'
1471 fm.condwrite(
1471 fm.condwrite(
1472 not ui.quiet,
1472 not ui.quiet,
1473 b'rev node',
1473 b'rev node',
1474 fmt,
1474 fmt,
1475 rev,
1475 rev,
1476 hexfunc(ctx.node()),
1476 hexfunc(ctx.node()),
1477 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1477 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1478 )
1478 )
1479 fm.context(ctx=ctx)
1479 fm.context(ctx=ctx)
1480 fm.data(active=isactive, closed=not isopen, current=current)
1480 fm.data(active=isactive, closed=not isopen, current=current)
1481 if not ui.quiet:
1481 if not ui.quiet:
1482 fm.plain(notice)
1482 fm.plain(notice)
1483 fm.plain(b'\n')
1483 fm.plain(b'\n')
1484 fm.end()
1484 fm.end()
1485
1485
1486
1486
1487 @command(
1487 @command(
1488 b'bundle',
1488 b'bundle',
1489 [
1489 [
1490 (
1490 (
1491 b'f',
1491 b'f',
1492 b'force',
1492 b'force',
1493 None,
1493 None,
1494 _(b'run even when the destination is unrelated'),
1494 _(b'run even when the destination is unrelated'),
1495 ),
1495 ),
1496 (
1496 (
1497 b'r',
1497 b'r',
1498 b'rev',
1498 b'rev',
1499 [],
1499 [],
1500 _(b'a changeset intended to be added to the destination'),
1500 _(b'a changeset intended to be added to the destination'),
1501 _(b'REV'),
1501 _(b'REV'),
1502 ),
1502 ),
1503 (
1503 (
1504 b'b',
1504 b'b',
1505 b'branch',
1505 b'branch',
1506 [],
1506 [],
1507 _(b'a specific branch you would like to bundle'),
1507 _(b'a specific branch you would like to bundle'),
1508 _(b'BRANCH'),
1508 _(b'BRANCH'),
1509 ),
1509 ),
1510 (
1510 (
1511 b'',
1511 b'',
1512 b'base',
1512 b'base',
1513 [],
1513 [],
1514 _(b'a base changeset assumed to be available at the destination'),
1514 _(b'a base changeset assumed to be available at the destination'),
1515 _(b'REV'),
1515 _(b'REV'),
1516 ),
1516 ),
1517 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1517 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1518 (
1518 (
1519 b't',
1519 b't',
1520 b'type',
1520 b'type',
1521 b'bzip2',
1521 b'bzip2',
1522 _(b'bundle compression type to use'),
1522 _(b'bundle compression type to use'),
1523 _(b'TYPE'),
1523 _(b'TYPE'),
1524 ),
1524 ),
1525 ]
1525 ]
1526 + remoteopts,
1526 + remoteopts,
1527 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1527 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1528 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1528 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1529 )
1529 )
1530 def bundle(ui, repo, fname, dest=None, **opts):
1530 def bundle(ui, repo, fname, dest=None, **opts):
1531 """create a bundle file
1531 """create a bundle file
1532
1532
1533 Generate a bundle file containing data to be transferred to another
1533 Generate a bundle file containing data to be transferred to another
1534 repository.
1534 repository.
1535
1535
1536 To create a bundle containing all changesets, use -a/--all
1536 To create a bundle containing all changesets, use -a/--all
1537 (or --base null). Otherwise, hg assumes the destination will have
1537 (or --base null). Otherwise, hg assumes the destination will have
1538 all the nodes you specify with --base parameters. Otherwise, hg
1538 all the nodes you specify with --base parameters. Otherwise, hg
1539 will assume the repository has all the nodes in destination, or
1539 will assume the repository has all the nodes in destination, or
1540 default-push/default if no destination is specified, where destination
1540 default-push/default if no destination is specified, where destination
1541 is the repository you provide through DEST option.
1541 is the repository you provide through DEST option.
1542
1542
1543 You can change bundle format with the -t/--type option. See
1543 You can change bundle format with the -t/--type option. See
1544 :hg:`help bundlespec` for documentation on this format. By default,
1544 :hg:`help bundlespec` for documentation on this format. By default,
1545 the most appropriate format is used and compression defaults to
1545 the most appropriate format is used and compression defaults to
1546 bzip2.
1546 bzip2.
1547
1547
1548 The bundle file can then be transferred using conventional means
1548 The bundle file can then be transferred using conventional means
1549 and applied to another repository with the unbundle or pull
1549 and applied to another repository with the unbundle or pull
1550 command. This is useful when direct push and pull are not
1550 command. This is useful when direct push and pull are not
1551 available or when exporting an entire repository is undesirable.
1551 available or when exporting an entire repository is undesirable.
1552
1552
1553 Applying bundles preserves all changeset contents including
1553 Applying bundles preserves all changeset contents including
1554 permissions, copy/rename information, and revision history.
1554 permissions, copy/rename information, and revision history.
1555
1555
1556 Returns 0 on success, 1 if no changes found.
1556 Returns 0 on success, 1 if no changes found.
1557 """
1557 """
1558 opts = pycompat.byteskwargs(opts)
1558 opts = pycompat.byteskwargs(opts)
1559 revs = None
1559 revs = None
1560 if b'rev' in opts:
1560 if b'rev' in opts:
1561 revstrings = opts[b'rev']
1561 revstrings = opts[b'rev']
1562 revs = scmutil.revrange(repo, revstrings)
1562 revs = scmutil.revrange(repo, revstrings)
1563 if revstrings and not revs:
1563 if revstrings and not revs:
1564 raise error.InputError(_(b'no commits to bundle'))
1564 raise error.InputError(_(b'no commits to bundle'))
1565
1565
1566 bundletype = opts.get(b'type', b'bzip2').lower()
1566 bundletype = opts.get(b'type', b'bzip2').lower()
1567 try:
1567 try:
1568 bundlespec = bundlecaches.parsebundlespec(
1568 bundlespec = bundlecaches.parsebundlespec(
1569 repo, bundletype, strict=False
1569 repo, bundletype, strict=False
1570 )
1570 )
1571 except error.UnsupportedBundleSpecification as e:
1571 except error.UnsupportedBundleSpecification as e:
1572 raise error.InputError(
1572 raise error.InputError(
1573 pycompat.bytestr(e),
1573 pycompat.bytestr(e),
1574 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1574 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1575 )
1575 )
1576 cgversion = bundlespec.contentopts[b"cg.version"]
1576 cgversion = bundlespec.contentopts[b"cg.version"]
1577
1577
1578 # Packed bundles are a pseudo bundle format for now.
1578 # Packed bundles are a pseudo bundle format for now.
1579 if cgversion == b's1':
1579 if cgversion == b's1':
1580 raise error.InputError(
1580 raise error.InputError(
1581 _(b'packed bundles cannot be produced by "hg bundle"'),
1581 _(b'packed bundles cannot be produced by "hg bundle"'),
1582 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1582 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1583 )
1583 )
1584
1584
1585 if opts.get(b'all'):
1585 if opts.get(b'all'):
1586 if dest:
1586 if dest:
1587 raise error.InputError(
1587 raise error.InputError(
1588 _(b"--all is incompatible with specifying a destination")
1588 _(b"--all is incompatible with specifying a destination")
1589 )
1589 )
1590 if opts.get(b'base'):
1590 if opts.get(b'base'):
1591 ui.warn(_(b"ignoring --base because --all was specified\n"))
1591 ui.warn(_(b"ignoring --base because --all was specified\n"))
1592 base = [nullrev]
1592 base = [nullrev]
1593 else:
1593 else:
1594 base = scmutil.revrange(repo, opts.get(b'base'))
1594 base = scmutil.revrange(repo, opts.get(b'base'))
1595 if cgversion not in changegroup.supportedoutgoingversions(repo):
1595 if cgversion not in changegroup.supportedoutgoingversions(repo):
1596 raise error.Abort(
1596 raise error.Abort(
1597 _(b"repository does not support bundle version %s") % cgversion
1597 _(b"repository does not support bundle version %s") % cgversion
1598 )
1598 )
1599
1599
1600 if base:
1600 if base:
1601 if dest:
1601 if dest:
1602 raise error.InputError(
1602 raise error.InputError(
1603 _(b"--base is incompatible with specifying a destination")
1603 _(b"--base is incompatible with specifying a destination")
1604 )
1604 )
1605 common = [repo[rev].node() for rev in base]
1605 common = [repo[rev].node() for rev in base]
1606 heads = [repo[r].node() for r in revs] if revs else None
1606 heads = [repo[r].node() for r in revs] if revs else None
1607 outgoing = discovery.outgoing(repo, common, heads)
1607 outgoing = discovery.outgoing(repo, common, heads)
1608 else:
1608 else:
1609 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1609 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1610 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1610 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1611 other = hg.peer(repo, opts, dest)
1611 other = hg.peer(repo, opts, dest)
1612 revs = [repo[r].hex() for r in revs]
1612 revs = [repo[r].hex() for r in revs]
1613 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1613 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1614 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1614 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1615 outgoing = discovery.findcommonoutgoing(
1615 outgoing = discovery.findcommonoutgoing(
1616 repo,
1616 repo,
1617 other,
1617 other,
1618 onlyheads=heads,
1618 onlyheads=heads,
1619 force=opts.get(b'force'),
1619 force=opts.get(b'force'),
1620 portable=True,
1620 portable=True,
1621 )
1621 )
1622
1622
1623 if not outgoing.missing:
1623 if not outgoing.missing:
1624 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1624 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1625 return 1
1625 return 1
1626
1626
1627 if cgversion == b'01': # bundle1
1627 if cgversion == b'01': # bundle1
1628 bversion = b'HG10' + bundlespec.wirecompression
1628 bversion = b'HG10' + bundlespec.wirecompression
1629 bcompression = None
1629 bcompression = None
1630 elif cgversion in (b'02', b'03'):
1630 elif cgversion in (b'02', b'03'):
1631 bversion = b'HG20'
1631 bversion = b'HG20'
1632 bcompression = bundlespec.wirecompression
1632 bcompression = bundlespec.wirecompression
1633 else:
1633 else:
1634 raise error.ProgrammingError(
1634 raise error.ProgrammingError(
1635 b'bundle: unexpected changegroup version %s' % cgversion
1635 b'bundle: unexpected changegroup version %s' % cgversion
1636 )
1636 )
1637
1637
1638 # TODO compression options should be derived from bundlespec parsing.
1638 # TODO compression options should be derived from bundlespec parsing.
1639 # This is a temporary hack to allow adjusting bundle compression
1639 # This is a temporary hack to allow adjusting bundle compression
1640 # level without a) formalizing the bundlespec changes to declare it
1640 # level without a) formalizing the bundlespec changes to declare it
1641 # b) introducing a command flag.
1641 # b) introducing a command flag.
1642 compopts = {}
1642 compopts = {}
1643 complevel = ui.configint(
1643 complevel = ui.configint(
1644 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1644 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1645 )
1645 )
1646 if complevel is None:
1646 if complevel is None:
1647 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1647 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1648 if complevel is not None:
1648 if complevel is not None:
1649 compopts[b'level'] = complevel
1649 compopts[b'level'] = complevel
1650
1650
1651 compthreads = ui.configint(
1651 compthreads = ui.configint(
1652 b'experimental', b'bundlecompthreads.' + bundlespec.compression
1652 b'experimental', b'bundlecompthreads.' + bundlespec.compression
1653 )
1653 )
1654 if compthreads is None:
1654 if compthreads is None:
1655 compthreads = ui.configint(b'experimental', b'bundlecompthreads')
1655 compthreads = ui.configint(b'experimental', b'bundlecompthreads')
1656 if compthreads is not None:
1656 if compthreads is not None:
1657 compopts[b'threads'] = compthreads
1657 compopts[b'threads'] = compthreads
1658
1658
1659 # Bundling of obsmarker and phases is optional as not all clients
1659 # Bundling of obsmarker and phases is optional as not all clients
1660 # support the necessary features.
1660 # support the necessary features.
1661 cfg = ui.configbool
1661 cfg = ui.configbool
1662 contentopts = {
1662 contentopts = {
1663 b'obsolescence': cfg(b'experimental', b'evolution.bundle-obsmarker'),
1663 b'obsolescence': cfg(b'experimental', b'evolution.bundle-obsmarker'),
1664 b'obsolescence-mandatory': cfg(
1664 b'obsolescence-mandatory': cfg(
1665 b'experimental', b'evolution.bundle-obsmarker:mandatory'
1665 b'experimental', b'evolution.bundle-obsmarker:mandatory'
1666 ),
1666 ),
1667 b'phases': cfg(b'experimental', b'bundle-phases'),
1667 b'phases': cfg(b'experimental', b'bundle-phases'),
1668 }
1668 }
1669 bundlespec.contentopts.update(contentopts)
1669 bundlespec.contentopts.update(contentopts)
1670
1670
1671 bundle2.writenewbundle(
1671 bundle2.writenewbundle(
1672 ui,
1672 ui,
1673 repo,
1673 repo,
1674 b'bundle',
1674 b'bundle',
1675 fname,
1675 fname,
1676 bversion,
1676 bversion,
1677 outgoing,
1677 outgoing,
1678 bundlespec.contentopts,
1678 bundlespec.contentopts,
1679 compression=bcompression,
1679 compression=bcompression,
1680 compopts=compopts,
1680 compopts=compopts,
1681 )
1681 )
1682
1682
1683
1683
1684 @command(
1684 @command(
1685 b'cat',
1685 b'cat',
1686 [
1686 [
1687 (
1687 (
1688 b'o',
1688 b'o',
1689 b'output',
1689 b'output',
1690 b'',
1690 b'',
1691 _(b'print output to file with formatted name'),
1691 _(b'print output to file with formatted name'),
1692 _(b'FORMAT'),
1692 _(b'FORMAT'),
1693 ),
1693 ),
1694 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1694 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1695 (b'', b'decode', None, _(b'apply any matching decode filter')),
1695 (b'', b'decode', None, _(b'apply any matching decode filter')),
1696 ]
1696 ]
1697 + walkopts
1697 + walkopts
1698 + formatteropts,
1698 + formatteropts,
1699 _(b'[OPTION]... FILE...'),
1699 _(b'[OPTION]... FILE...'),
1700 helpcategory=command.CATEGORY_FILE_CONTENTS,
1700 helpcategory=command.CATEGORY_FILE_CONTENTS,
1701 inferrepo=True,
1701 inferrepo=True,
1702 intents={INTENT_READONLY},
1702 intents={INTENT_READONLY},
1703 )
1703 )
1704 def cat(ui, repo, file1, *pats, **opts):
1704 def cat(ui, repo, file1, *pats, **opts):
1705 """output the current or given revision of files
1705 """output the current or given revision of files
1706
1706
1707 Print the specified files as they were at the given revision. If
1707 Print the specified files as they were at the given revision. If
1708 no revision is given, the parent of the working directory is used.
1708 no revision is given, the parent of the working directory is used.
1709
1709
1710 Output may be to a file, in which case the name of the file is
1710 Output may be to a file, in which case the name of the file is
1711 given using a template string. See :hg:`help templates`. In addition
1711 given using a template string. See :hg:`help templates`. In addition
1712 to the common template keywords, the following formatting rules are
1712 to the common template keywords, the following formatting rules are
1713 supported:
1713 supported:
1714
1714
1715 :``%%``: literal "%" character
1715 :``%%``: literal "%" character
1716 :``%s``: basename of file being printed
1716 :``%s``: basename of file being printed
1717 :``%d``: dirname of file being printed, or '.' if in repository root
1717 :``%d``: dirname of file being printed, or '.' if in repository root
1718 :``%p``: root-relative path name of file being printed
1718 :``%p``: root-relative path name of file being printed
1719 :``%H``: changeset hash (40 hexadecimal digits)
1719 :``%H``: changeset hash (40 hexadecimal digits)
1720 :``%R``: changeset revision number
1720 :``%R``: changeset revision number
1721 :``%h``: short-form changeset hash (12 hexadecimal digits)
1721 :``%h``: short-form changeset hash (12 hexadecimal digits)
1722 :``%r``: zero-padded changeset revision number
1722 :``%r``: zero-padded changeset revision number
1723 :``%b``: basename of the exporting repository
1723 :``%b``: basename of the exporting repository
1724 :``\\``: literal "\\" character
1724 :``\\``: literal "\\" character
1725
1725
1726 .. container:: verbose
1726 .. container:: verbose
1727
1727
1728 Template:
1728 Template:
1729
1729
1730 The following keywords are supported in addition to the common template
1730 The following keywords are supported in addition to the common template
1731 keywords and functions. See also :hg:`help templates`.
1731 keywords and functions. See also :hg:`help templates`.
1732
1732
1733 :data: String. File content.
1733 :data: String. File content.
1734 :path: String. Repository-absolute path of the file.
1734 :path: String. Repository-absolute path of the file.
1735
1735
1736 Returns 0 on success.
1736 Returns 0 on success.
1737 """
1737 """
1738 opts = pycompat.byteskwargs(opts)
1738 opts = pycompat.byteskwargs(opts)
1739 rev = opts.get(b'rev')
1739 rev = opts.get(b'rev')
1740 if rev:
1740 if rev:
1741 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1741 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1742 ctx = scmutil.revsingle(repo, rev)
1742 ctx = scmutil.revsingle(repo, rev)
1743 m = scmutil.match(ctx, (file1,) + pats, opts)
1743 m = scmutil.match(ctx, (file1,) + pats, opts)
1744 fntemplate = opts.pop(b'output', b'')
1744 fntemplate = opts.pop(b'output', b'')
1745 if cmdutil.isstdiofilename(fntemplate):
1745 if cmdutil.isstdiofilename(fntemplate):
1746 fntemplate = b''
1746 fntemplate = b''
1747
1747
1748 if fntemplate:
1748 if fntemplate:
1749 fm = formatter.nullformatter(ui, b'cat', opts)
1749 fm = formatter.nullformatter(ui, b'cat', opts)
1750 else:
1750 else:
1751 ui.pager(b'cat')
1751 ui.pager(b'cat')
1752 fm = ui.formatter(b'cat', opts)
1752 fm = ui.formatter(b'cat', opts)
1753 with fm:
1753 with fm:
1754 return cmdutil.cat(
1754 return cmdutil.cat(
1755 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1755 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1756 )
1756 )
1757
1757
1758
1758
1759 @command(
1759 @command(
1760 b'clone',
1760 b'clone',
1761 [
1761 [
1762 (
1762 (
1763 b'U',
1763 b'U',
1764 b'noupdate',
1764 b'noupdate',
1765 None,
1765 None,
1766 _(
1766 _(
1767 b'the clone will include an empty working '
1767 b'the clone will include an empty working '
1768 b'directory (only a repository)'
1768 b'directory (only a repository)'
1769 ),
1769 ),
1770 ),
1770 ),
1771 (
1771 (
1772 b'u',
1772 b'u',
1773 b'updaterev',
1773 b'updaterev',
1774 b'',
1774 b'',
1775 _(b'revision, tag, or branch to check out'),
1775 _(b'revision, tag, or branch to check out'),
1776 _(b'REV'),
1776 _(b'REV'),
1777 ),
1777 ),
1778 (
1778 (
1779 b'r',
1779 b'r',
1780 b'rev',
1780 b'rev',
1781 [],
1781 [],
1782 _(
1782 _(
1783 b'do not clone everything, but include this changeset'
1783 b'do not clone everything, but include this changeset'
1784 b' and its ancestors'
1784 b' and its ancestors'
1785 ),
1785 ),
1786 _(b'REV'),
1786 _(b'REV'),
1787 ),
1787 ),
1788 (
1788 (
1789 b'b',
1789 b'b',
1790 b'branch',
1790 b'branch',
1791 [],
1791 [],
1792 _(
1792 _(
1793 b'do not clone everything, but include this branch\'s'
1793 b'do not clone everything, but include this branch\'s'
1794 b' changesets and their ancestors'
1794 b' changesets and their ancestors'
1795 ),
1795 ),
1796 _(b'BRANCH'),
1796 _(b'BRANCH'),
1797 ),
1797 ),
1798 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1798 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1799 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1799 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1800 (b'', b'stream', None, _(b'clone with minimal data processing')),
1800 (b'', b'stream', None, _(b'clone with minimal data processing')),
1801 ]
1801 ]
1802 + remoteopts,
1802 + remoteopts,
1803 _(b'[OPTION]... SOURCE [DEST]'),
1803 _(b'[OPTION]... SOURCE [DEST]'),
1804 helpcategory=command.CATEGORY_REPO_CREATION,
1804 helpcategory=command.CATEGORY_REPO_CREATION,
1805 helpbasic=True,
1805 helpbasic=True,
1806 norepo=True,
1806 norepo=True,
1807 )
1807 )
1808 def clone(ui, source, dest=None, **opts):
1808 def clone(ui, source, dest=None, **opts):
1809 """make a copy of an existing repository
1809 """make a copy of an existing repository
1810
1810
1811 Create a copy of an existing repository in a new directory.
1811 Create a copy of an existing repository in a new directory.
1812
1812
1813 If no destination directory name is specified, it defaults to the
1813 If no destination directory name is specified, it defaults to the
1814 basename of the source.
1814 basename of the source.
1815
1815
1816 The location of the source is added to the new repository's
1816 The location of the source is added to the new repository's
1817 ``.hg/hgrc`` file, as the default to be used for future pulls.
1817 ``.hg/hgrc`` file, as the default to be used for future pulls.
1818
1818
1819 Only local paths and ``ssh://`` URLs are supported as
1819 Only local paths and ``ssh://`` URLs are supported as
1820 destinations. For ``ssh://`` destinations, no working directory or
1820 destinations. For ``ssh://`` destinations, no working directory or
1821 ``.hg/hgrc`` will be created on the remote side.
1821 ``.hg/hgrc`` will be created on the remote side.
1822
1822
1823 If the source repository has a bookmark called '@' set, that
1823 If the source repository has a bookmark called '@' set, that
1824 revision will be checked out in the new repository by default.
1824 revision will be checked out in the new repository by default.
1825
1825
1826 To check out a particular version, use -u/--update, or
1826 To check out a particular version, use -u/--update, or
1827 -U/--noupdate to create a clone with no working directory.
1827 -U/--noupdate to create a clone with no working directory.
1828
1828
1829 To pull only a subset of changesets, specify one or more revisions
1829 To pull only a subset of changesets, specify one or more revisions
1830 identifiers with -r/--rev or branches with -b/--branch. The
1830 identifiers with -r/--rev or branches with -b/--branch. The
1831 resulting clone will contain only the specified changesets and
1831 resulting clone will contain only the specified changesets and
1832 their ancestors. These options (or 'clone src#rev dest') imply
1832 their ancestors. These options (or 'clone src#rev dest') imply
1833 --pull, even for local source repositories.
1833 --pull, even for local source repositories.
1834
1834
1835 In normal clone mode, the remote normalizes repository data into a common
1835 In normal clone mode, the remote normalizes repository data into a common
1836 exchange format and the receiving end translates this data into its local
1836 exchange format and the receiving end translates this data into its local
1837 storage format. --stream activates a different clone mode that essentially
1837 storage format. --stream activates a different clone mode that essentially
1838 copies repository files from the remote with minimal data processing. This
1838 copies repository files from the remote with minimal data processing. This
1839 significantly reduces the CPU cost of a clone both remotely and locally.
1839 significantly reduces the CPU cost of a clone both remotely and locally.
1840 However, it often increases the transferred data size by 30-40%. This can
1840 However, it often increases the transferred data size by 30-40%. This can
1841 result in substantially faster clones where I/O throughput is plentiful,
1841 result in substantially faster clones where I/O throughput is plentiful,
1842 especially for larger repositories. A side-effect of --stream clones is
1842 especially for larger repositories. A side-effect of --stream clones is
1843 that storage settings and requirements on the remote are applied locally:
1843 that storage settings and requirements on the remote are applied locally:
1844 a modern client may inherit legacy or inefficient storage used by the
1844 a modern client may inherit legacy or inefficient storage used by the
1845 remote or a legacy Mercurial client may not be able to clone from a
1845 remote or a legacy Mercurial client may not be able to clone from a
1846 modern Mercurial remote.
1846 modern Mercurial remote.
1847
1847
1848 .. note::
1848 .. note::
1849
1849
1850 Specifying a tag will include the tagged changeset but not the
1850 Specifying a tag will include the tagged changeset but not the
1851 changeset containing the tag.
1851 changeset containing the tag.
1852
1852
1853 .. container:: verbose
1853 .. container:: verbose
1854
1854
1855 For efficiency, hardlinks are used for cloning whenever the
1855 For efficiency, hardlinks are used for cloning whenever the
1856 source and destination are on the same filesystem (note this
1856 source and destination are on the same filesystem (note this
1857 applies only to the repository data, not to the working
1857 applies only to the repository data, not to the working
1858 directory). Some filesystems, such as AFS, implement hardlinking
1858 directory). Some filesystems, such as AFS, implement hardlinking
1859 incorrectly, but do not report errors. In these cases, use the
1859 incorrectly, but do not report errors. In these cases, use the
1860 --pull option to avoid hardlinking.
1860 --pull option to avoid hardlinking.
1861
1861
1862 Mercurial will update the working directory to the first applicable
1862 Mercurial will update the working directory to the first applicable
1863 revision from this list:
1863 revision from this list:
1864
1864
1865 a) null if -U or the source repository has no changesets
1865 a) null if -U or the source repository has no changesets
1866 b) if -u . and the source repository is local, the first parent of
1866 b) if -u . and the source repository is local, the first parent of
1867 the source repository's working directory
1867 the source repository's working directory
1868 c) the changeset specified with -u (if a branch name, this means the
1868 c) the changeset specified with -u (if a branch name, this means the
1869 latest head of that branch)
1869 latest head of that branch)
1870 d) the changeset specified with -r
1870 d) the changeset specified with -r
1871 e) the tipmost head specified with -b
1871 e) the tipmost head specified with -b
1872 f) the tipmost head specified with the url#branch source syntax
1872 f) the tipmost head specified with the url#branch source syntax
1873 g) the revision marked with the '@' bookmark, if present
1873 g) the revision marked with the '@' bookmark, if present
1874 h) the tipmost head of the default branch
1874 h) the tipmost head of the default branch
1875 i) tip
1875 i) tip
1876
1876
1877 When cloning from servers that support it, Mercurial may fetch
1877 When cloning from servers that support it, Mercurial may fetch
1878 pre-generated data from a server-advertised URL or inline from the
1878 pre-generated data from a server-advertised URL or inline from the
1879 same stream. When this is done, hooks operating on incoming changesets
1879 same stream. When this is done, hooks operating on incoming changesets
1880 and changegroups may fire more than once, once for each pre-generated
1880 and changegroups may fire more than once, once for each pre-generated
1881 bundle and as well as for any additional remaining data. In addition,
1881 bundle and as well as for any additional remaining data. In addition,
1882 if an error occurs, the repository may be rolled back to a partial
1882 if an error occurs, the repository may be rolled back to a partial
1883 clone. This behavior may change in future releases.
1883 clone. This behavior may change in future releases.
1884 See :hg:`help -e clonebundles` for more.
1884 See :hg:`help -e clonebundles` for more.
1885
1885
1886 Examples:
1886 Examples:
1887
1887
1888 - clone a remote repository to a new directory named hg/::
1888 - clone a remote repository to a new directory named hg/::
1889
1889
1890 hg clone https://www.mercurial-scm.org/repo/hg/
1890 hg clone https://www.mercurial-scm.org/repo/hg/
1891
1891
1892 - create a lightweight local clone::
1892 - create a lightweight local clone::
1893
1893
1894 hg clone project/ project-feature/
1894 hg clone project/ project-feature/
1895
1895
1896 - clone from an absolute path on an ssh server (note double-slash)::
1896 - clone from an absolute path on an ssh server (note double-slash)::
1897
1897
1898 hg clone ssh://user@server//home/projects/alpha/
1898 hg clone ssh://user@server//home/projects/alpha/
1899
1899
1900 - do a streaming clone while checking out a specified version::
1900 - do a streaming clone while checking out a specified version::
1901
1901
1902 hg clone --stream http://server/repo -u 1.5
1902 hg clone --stream http://server/repo -u 1.5
1903
1903
1904 - create a repository without changesets after a particular revision::
1904 - create a repository without changesets after a particular revision::
1905
1905
1906 hg clone -r 04e544 experimental/ good/
1906 hg clone -r 04e544 experimental/ good/
1907
1907
1908 - clone (and track) a particular named branch::
1908 - clone (and track) a particular named branch::
1909
1909
1910 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1910 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1911
1911
1912 See :hg:`help urls` for details on specifying URLs.
1912 See :hg:`help urls` for details on specifying URLs.
1913
1913
1914 Returns 0 on success.
1914 Returns 0 on success.
1915 """
1915 """
1916 opts = pycompat.byteskwargs(opts)
1916 opts = pycompat.byteskwargs(opts)
1917 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1917 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1918
1918
1919 # --include/--exclude can come from narrow or sparse.
1919 # --include/--exclude can come from narrow or sparse.
1920 includepats, excludepats = None, None
1920 includepats, excludepats = None, None
1921
1921
1922 # hg.clone() differentiates between None and an empty set. So make sure
1922 # hg.clone() differentiates between None and an empty set. So make sure
1923 # patterns are sets if narrow is requested without patterns.
1923 # patterns are sets if narrow is requested without patterns.
1924 if opts.get(b'narrow'):
1924 if opts.get(b'narrow'):
1925 includepats = set()
1925 includepats = set()
1926 excludepats = set()
1926 excludepats = set()
1927
1927
1928 if opts.get(b'include'):
1928 if opts.get(b'include'):
1929 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1929 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1930 if opts.get(b'exclude'):
1930 if opts.get(b'exclude'):
1931 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1931 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1932
1932
1933 r = hg.clone(
1933 r = hg.clone(
1934 ui,
1934 ui,
1935 opts,
1935 opts,
1936 source,
1936 source,
1937 dest,
1937 dest,
1938 pull=opts.get(b'pull'),
1938 pull=opts.get(b'pull'),
1939 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1939 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1940 revs=opts.get(b'rev'),
1940 revs=opts.get(b'rev'),
1941 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1941 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1942 branch=opts.get(b'branch'),
1942 branch=opts.get(b'branch'),
1943 shareopts=opts.get(b'shareopts'),
1943 shareopts=opts.get(b'shareopts'),
1944 storeincludepats=includepats,
1944 storeincludepats=includepats,
1945 storeexcludepats=excludepats,
1945 storeexcludepats=excludepats,
1946 depth=opts.get(b'depth') or None,
1946 depth=opts.get(b'depth') or None,
1947 )
1947 )
1948
1948
1949 return r is None
1949 return r is None
1950
1950
1951
1951
1952 @command(
1952 @command(
1953 b'commit|ci',
1953 b'commit|ci',
1954 [
1954 [
1955 (
1955 (
1956 b'A',
1956 b'A',
1957 b'addremove',
1957 b'addremove',
1958 None,
1958 None,
1959 _(b'mark new/missing files as added/removed before committing'),
1959 _(b'mark new/missing files as added/removed before committing'),
1960 ),
1960 ),
1961 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1961 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1962 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1962 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1963 (b's', b'secret', None, _(b'use the secret phase for committing')),
1963 (b's', b'secret', None, _(b'use the secret phase for committing')),
1964 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1964 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1965 (
1965 (
1966 b'',
1966 b'',
1967 b'force-close-branch',
1967 b'force-close-branch',
1968 None,
1968 None,
1969 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1969 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1970 ),
1970 ),
1971 (b'i', b'interactive', None, _(b'use interactive mode')),
1971 (b'i', b'interactive', None, _(b'use interactive mode')),
1972 ]
1972 ]
1973 + walkopts
1973 + walkopts
1974 + commitopts
1974 + commitopts
1975 + commitopts2
1975 + commitopts2
1976 + subrepoopts,
1976 + subrepoopts,
1977 _(b'[OPTION]... [FILE]...'),
1977 _(b'[OPTION]... [FILE]...'),
1978 helpcategory=command.CATEGORY_COMMITTING,
1978 helpcategory=command.CATEGORY_COMMITTING,
1979 helpbasic=True,
1979 helpbasic=True,
1980 inferrepo=True,
1980 inferrepo=True,
1981 )
1981 )
1982 def commit(ui, repo, *pats, **opts):
1982 def commit(ui, repo, *pats, **opts):
1983 """commit the specified files or all outstanding changes
1983 """commit the specified files or all outstanding changes
1984
1984
1985 Commit changes to the given files into the repository. Unlike a
1985 Commit changes to the given files into the repository. Unlike a
1986 centralized SCM, this operation is a local operation. See
1986 centralized SCM, this operation is a local operation. See
1987 :hg:`push` for a way to actively distribute your changes.
1987 :hg:`push` for a way to actively distribute your changes.
1988
1988
1989 If a list of files is omitted, all changes reported by :hg:`status`
1989 If a list of files is omitted, all changes reported by :hg:`status`
1990 will be committed.
1990 will be committed.
1991
1991
1992 If you are committing the result of a merge, do not provide any
1992 If you are committing the result of a merge, do not provide any
1993 filenames or -I/-X filters.
1993 filenames or -I/-X filters.
1994
1994
1995 If no commit message is specified, Mercurial starts your
1995 If no commit message is specified, Mercurial starts your
1996 configured editor where you can enter a message. In case your
1996 configured editor where you can enter a message. In case your
1997 commit fails, you will find a backup of your message in
1997 commit fails, you will find a backup of your message in
1998 ``.hg/last-message.txt``.
1998 ``.hg/last-message.txt``.
1999
1999
2000 The --close-branch flag can be used to mark the current branch
2000 The --close-branch flag can be used to mark the current branch
2001 head closed. When all heads of a branch are closed, the branch
2001 head closed. When all heads of a branch are closed, the branch
2002 will be considered closed and no longer listed.
2002 will be considered closed and no longer listed.
2003
2003
2004 The --amend flag can be used to amend the parent of the
2004 The --amend flag can be used to amend the parent of the
2005 working directory with a new commit that contains the changes
2005 working directory with a new commit that contains the changes
2006 in the parent in addition to those currently reported by :hg:`status`,
2006 in the parent in addition to those currently reported by :hg:`status`,
2007 if there are any. The old commit is stored in a backup bundle in
2007 if there are any. The old commit is stored in a backup bundle in
2008 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2008 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2009 on how to restore it).
2009 on how to restore it).
2010
2010
2011 Message, user and date are taken from the amended commit unless
2011 Message, user and date are taken from the amended commit unless
2012 specified. When a message isn't specified on the command line,
2012 specified. When a message isn't specified on the command line,
2013 the editor will open with the message of the amended commit.
2013 the editor will open with the message of the amended commit.
2014
2014
2015 It is not possible to amend public changesets (see :hg:`help phases`)
2015 It is not possible to amend public changesets (see :hg:`help phases`)
2016 or changesets that have children.
2016 or changesets that have children.
2017
2017
2018 See :hg:`help dates` for a list of formats valid for -d/--date.
2018 See :hg:`help dates` for a list of formats valid for -d/--date.
2019
2019
2020 Returns 0 on success, 1 if nothing changed.
2020 Returns 0 on success, 1 if nothing changed.
2021
2021
2022 .. container:: verbose
2022 .. container:: verbose
2023
2023
2024 Examples:
2024 Examples:
2025
2025
2026 - commit all files ending in .py::
2026 - commit all files ending in .py::
2027
2027
2028 hg commit --include "set:**.py"
2028 hg commit --include "set:**.py"
2029
2029
2030 - commit all non-binary files::
2030 - commit all non-binary files::
2031
2031
2032 hg commit --exclude "set:binary()"
2032 hg commit --exclude "set:binary()"
2033
2033
2034 - amend the current commit and set the date to now::
2034 - amend the current commit and set the date to now::
2035
2035
2036 hg commit --amend --date now
2036 hg commit --amend --date now
2037 """
2037 """
2038 with repo.wlock(), repo.lock():
2038 with repo.wlock(), repo.lock():
2039 return _docommit(ui, repo, *pats, **opts)
2039 return _docommit(ui, repo, *pats, **opts)
2040
2040
2041
2041
2042 def _docommit(ui, repo, *pats, **opts):
2042 def _docommit(ui, repo, *pats, **opts):
2043 if opts.get('interactive'):
2043 if opts.get('interactive'):
2044 opts.pop('interactive')
2044 opts.pop('interactive')
2045 ret = cmdutil.dorecord(
2045 ret = cmdutil.dorecord(
2046 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2046 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2047 )
2047 )
2048 # ret can be 0 (no changes to record) or the value returned by
2048 # ret can be 0 (no changes to record) or the value returned by
2049 # commit(), 1 if nothing changed or None on success.
2049 # commit(), 1 if nothing changed or None on success.
2050 return 1 if ret == 0 else ret
2050 return 1 if ret == 0 else ret
2051
2051
2052 opts = pycompat.byteskwargs(opts)
2052 opts = pycompat.byteskwargs(opts)
2053 if opts.get(b'subrepos'):
2053 if opts.get(b'subrepos'):
2054 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'amend'])
2054 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'amend'])
2055 # Let --subrepos on the command line override config setting.
2055 # Let --subrepos on the command line override config setting.
2056 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2056 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2057
2057
2058 cmdutil.checkunfinished(repo, commit=True)
2058 cmdutil.checkunfinished(repo, commit=True)
2059
2059
2060 branch = repo[None].branch()
2060 branch = repo[None].branch()
2061 bheads = repo.branchheads(branch)
2061 bheads = repo.branchheads(branch)
2062 tip = repo.changelog.tip()
2062 tip = repo.changelog.tip()
2063
2063
2064 extra = {}
2064 extra = {}
2065 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2065 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2066 extra[b'close'] = b'1'
2066 extra[b'close'] = b'1'
2067
2067
2068 if repo[b'.'].closesbranch():
2068 if repo[b'.'].closesbranch():
2069 raise error.InputError(
2069 raise error.InputError(
2070 _(b'current revision is already a branch closing head')
2070 _(b'current revision is already a branch closing head')
2071 )
2071 )
2072 elif not bheads:
2072 elif not bheads:
2073 raise error.InputError(
2073 raise error.InputError(
2074 _(b'branch "%s" has no heads to close') % branch
2074 _(b'branch "%s" has no heads to close') % branch
2075 )
2075 )
2076 elif (
2076 elif (
2077 branch == repo[b'.'].branch()
2077 branch == repo[b'.'].branch()
2078 and repo[b'.'].node() not in bheads
2078 and repo[b'.'].node() not in bheads
2079 and not opts.get(b'force_close_branch')
2079 and not opts.get(b'force_close_branch')
2080 ):
2080 ):
2081 hint = _(
2081 hint = _(
2082 b'use --force-close-branch to close branch from a non-head'
2082 b'use --force-close-branch to close branch from a non-head'
2083 b' changeset'
2083 b' changeset'
2084 )
2084 )
2085 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2085 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2086 elif opts.get(b'amend'):
2086 elif opts.get(b'amend'):
2087 if (
2087 if (
2088 repo[b'.'].p1().branch() != branch
2088 repo[b'.'].p1().branch() != branch
2089 and repo[b'.'].p2().branch() != branch
2089 and repo[b'.'].p2().branch() != branch
2090 ):
2090 ):
2091 raise error.InputError(_(b'can only close branch heads'))
2091 raise error.InputError(_(b'can only close branch heads'))
2092
2092
2093 if opts.get(b'amend'):
2093 if opts.get(b'amend'):
2094 if ui.configbool(b'ui', b'commitsubrepos'):
2094 if ui.configbool(b'ui', b'commitsubrepos'):
2095 raise error.InputError(
2095 raise error.InputError(
2096 _(b'cannot amend with ui.commitsubrepos enabled')
2096 _(b'cannot amend with ui.commitsubrepos enabled')
2097 )
2097 )
2098
2098
2099 old = repo[b'.']
2099 old = repo[b'.']
2100 rewriteutil.precheck(repo, [old.rev()], b'amend')
2100 rewriteutil.precheck(repo, [old.rev()], b'amend')
2101
2101
2102 # Currently histedit gets confused if an amend happens while histedit
2102 # Currently histedit gets confused if an amend happens while histedit
2103 # is in progress. Since we have a checkunfinished command, we are
2103 # is in progress. Since we have a checkunfinished command, we are
2104 # temporarily honoring it.
2104 # temporarily honoring it.
2105 #
2105 #
2106 # Note: eventually this guard will be removed. Please do not expect
2106 # Note: eventually this guard will be removed. Please do not expect
2107 # this behavior to remain.
2107 # this behavior to remain.
2108 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2108 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2109 cmdutil.checkunfinished(repo)
2109 cmdutil.checkunfinished(repo)
2110
2110
2111 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2111 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2112 if node == old.node():
2112 if node == old.node():
2113 ui.status(_(b"nothing changed\n"))
2113 ui.status(_(b"nothing changed\n"))
2114 return 1
2114 return 1
2115 else:
2115 else:
2116
2116
2117 def commitfunc(ui, repo, message, match, opts):
2117 def commitfunc(ui, repo, message, match, opts):
2118 overrides = {}
2118 overrides = {}
2119 if opts.get(b'secret'):
2119 if opts.get(b'secret'):
2120 overrides[(b'phases', b'new-commit')] = b'secret'
2120 overrides[(b'phases', b'new-commit')] = b'secret'
2121
2121
2122 baseui = repo.baseui
2122 baseui = repo.baseui
2123 with baseui.configoverride(overrides, b'commit'):
2123 with baseui.configoverride(overrides, b'commit'):
2124 with ui.configoverride(overrides, b'commit'):
2124 with ui.configoverride(overrides, b'commit'):
2125 editform = cmdutil.mergeeditform(
2125 editform = cmdutil.mergeeditform(
2126 repo[None], b'commit.normal'
2126 repo[None], b'commit.normal'
2127 )
2127 )
2128 editor = cmdutil.getcommiteditor(
2128 editor = cmdutil.getcommiteditor(
2129 editform=editform, **pycompat.strkwargs(opts)
2129 editform=editform, **pycompat.strkwargs(opts)
2130 )
2130 )
2131 return repo.commit(
2131 return repo.commit(
2132 message,
2132 message,
2133 opts.get(b'user'),
2133 opts.get(b'user'),
2134 opts.get(b'date'),
2134 opts.get(b'date'),
2135 match,
2135 match,
2136 editor=editor,
2136 editor=editor,
2137 extra=extra,
2137 extra=extra,
2138 )
2138 )
2139
2139
2140 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2140 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2141
2141
2142 if not node:
2142 if not node:
2143 stat = cmdutil.postcommitstatus(repo, pats, opts)
2143 stat = cmdutil.postcommitstatus(repo, pats, opts)
2144 if stat.deleted:
2144 if stat.deleted:
2145 ui.status(
2145 ui.status(
2146 _(
2146 _(
2147 b"nothing changed (%d missing files, see "
2147 b"nothing changed (%d missing files, see "
2148 b"'hg status')\n"
2148 b"'hg status')\n"
2149 )
2149 )
2150 % len(stat.deleted)
2150 % len(stat.deleted)
2151 )
2151 )
2152 else:
2152 else:
2153 ui.status(_(b"nothing changed\n"))
2153 ui.status(_(b"nothing changed\n"))
2154 return 1
2154 return 1
2155
2155
2156 cmdutil.commitstatus(repo, node, branch, bheads, tip, opts)
2156 cmdutil.commitstatus(repo, node, branch, bheads, tip, opts)
2157
2157
2158 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2158 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2159 status(
2159 status(
2160 ui,
2160 ui,
2161 repo,
2161 repo,
2162 modified=True,
2162 modified=True,
2163 added=True,
2163 added=True,
2164 removed=True,
2164 removed=True,
2165 deleted=True,
2165 deleted=True,
2166 unknown=True,
2166 unknown=True,
2167 subrepos=opts.get(b'subrepos'),
2167 subrepos=opts.get(b'subrepos'),
2168 )
2168 )
2169
2169
2170
2170
2171 @command(
2171 @command(
2172 b'config|showconfig|debugconfig',
2172 b'config|showconfig|debugconfig',
2173 [
2173 [
2174 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2174 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2175 (b'e', b'edit', None, _(b'edit user config')),
2175 (b'e', b'edit', None, _(b'edit user config')),
2176 (b'l', b'local', None, _(b'edit repository config')),
2176 (b'l', b'local', None, _(b'edit repository config')),
2177 (
2177 (
2178 b'',
2178 b'',
2179 b'shared',
2179 b'shared',
2180 None,
2180 None,
2181 _(b'edit shared source repository config (EXPERIMENTAL)'),
2181 _(b'edit shared source repository config (EXPERIMENTAL)'),
2182 ),
2182 ),
2183 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2183 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2184 (b'g', b'global', None, _(b'edit global config')),
2184 (b'g', b'global', None, _(b'edit global config')),
2185 ]
2185 ]
2186 + formatteropts,
2186 + formatteropts,
2187 _(b'[-u] [NAME]...'),
2187 _(b'[-u] [NAME]...'),
2188 helpcategory=command.CATEGORY_HELP,
2188 helpcategory=command.CATEGORY_HELP,
2189 optionalrepo=True,
2189 optionalrepo=True,
2190 intents={INTENT_READONLY},
2190 intents={INTENT_READONLY},
2191 )
2191 )
2192 def config(ui, repo, *values, **opts):
2192 def config(ui, repo, *values, **opts):
2193 """show combined config settings from all hgrc files
2193 """show combined config settings from all hgrc files
2194
2194
2195 With no arguments, print names and values of all config items.
2195 With no arguments, print names and values of all config items.
2196
2196
2197 With one argument of the form section.name, print just the value
2197 With one argument of the form section.name, print just the value
2198 of that config item.
2198 of that config item.
2199
2199
2200 With multiple arguments, print names and values of all config
2200 With multiple arguments, print names and values of all config
2201 items with matching section names or section.names.
2201 items with matching section names or section.names.
2202
2202
2203 With --edit, start an editor on the user-level config file. With
2203 With --edit, start an editor on the user-level config file. With
2204 --global, edit the system-wide config file. With --local, edit the
2204 --global, edit the system-wide config file. With --local, edit the
2205 repository-level config file.
2205 repository-level config file.
2206
2206
2207 With --debug, the source (filename and line number) is printed
2207 With --debug, the source (filename and line number) is printed
2208 for each config item.
2208 for each config item.
2209
2209
2210 See :hg:`help config` for more information about config files.
2210 See :hg:`help config` for more information about config files.
2211
2211
2212 .. container:: verbose
2212 .. container:: verbose
2213
2213
2214 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2214 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2215 This file is not shared across shares when in share-safe mode.
2215 This file is not shared across shares when in share-safe mode.
2216
2216
2217 Template:
2217 Template:
2218
2218
2219 The following keywords are supported. See also :hg:`help templates`.
2219 The following keywords are supported. See also :hg:`help templates`.
2220
2220
2221 :name: String. Config name.
2221 :name: String. Config name.
2222 :source: String. Filename and line number where the item is defined.
2222 :source: String. Filename and line number where the item is defined.
2223 :value: String. Config value.
2223 :value: String. Config value.
2224
2224
2225 The --shared flag can be used to edit the config file of shared source
2225 The --shared flag can be used to edit the config file of shared source
2226 repository. It only works when you have shared using the experimental
2226 repository. It only works when you have shared using the experimental
2227 share safe feature.
2227 share safe feature.
2228
2228
2229 Returns 0 on success, 1 if NAME does not exist.
2229 Returns 0 on success, 1 if NAME does not exist.
2230
2230
2231 """
2231 """
2232
2232
2233 opts = pycompat.byteskwargs(opts)
2233 opts = pycompat.byteskwargs(opts)
2234 editopts = (b'edit', b'local', b'global', b'shared', b'non_shared')
2234 editopts = (b'edit', b'local', b'global', b'shared', b'non_shared')
2235 if any(opts.get(o) for o in editopts):
2235 if any(opts.get(o) for o in editopts):
2236 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2236 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2237 if opts.get(b'local'):
2237 if opts.get(b'local'):
2238 if not repo:
2238 if not repo:
2239 raise error.InputError(
2239 raise error.InputError(
2240 _(b"can't use --local outside a repository")
2240 _(b"can't use --local outside a repository")
2241 )
2241 )
2242 paths = [repo.vfs.join(b'hgrc')]
2242 paths = [repo.vfs.join(b'hgrc')]
2243 elif opts.get(b'global'):
2243 elif opts.get(b'global'):
2244 paths = rcutil.systemrcpath()
2244 paths = rcutil.systemrcpath()
2245 elif opts.get(b'shared'):
2245 elif opts.get(b'shared'):
2246 if not repo.shared():
2246 if not repo.shared():
2247 raise error.InputError(
2247 raise error.InputError(
2248 _(b"repository is not shared; can't use --shared")
2248 _(b"repository is not shared; can't use --shared")
2249 )
2249 )
2250 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2250 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2251 raise error.InputError(
2251 raise error.InputError(
2252 _(
2252 _(
2253 b"share safe feature not enabled; "
2253 b"share safe feature not enabled; "
2254 b"unable to edit shared source repository config"
2254 b"unable to edit shared source repository config"
2255 )
2255 )
2256 )
2256 )
2257 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2257 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2258 elif opts.get(b'non_shared'):
2258 elif opts.get(b'non_shared'):
2259 paths = [repo.vfs.join(b'hgrc-not-shared')]
2259 paths = [repo.vfs.join(b'hgrc-not-shared')]
2260 else:
2260 else:
2261 paths = rcutil.userrcpath()
2261 paths = rcutil.userrcpath()
2262
2262
2263 for f in paths:
2263 for f in paths:
2264 if os.path.exists(f):
2264 if os.path.exists(f):
2265 break
2265 break
2266 else:
2266 else:
2267 if opts.get(b'global'):
2267 if opts.get(b'global'):
2268 samplehgrc = uimod.samplehgrcs[b'global']
2268 samplehgrc = uimod.samplehgrcs[b'global']
2269 elif opts.get(b'local'):
2269 elif opts.get(b'local'):
2270 samplehgrc = uimod.samplehgrcs[b'local']
2270 samplehgrc = uimod.samplehgrcs[b'local']
2271 else:
2271 else:
2272 samplehgrc = uimod.samplehgrcs[b'user']
2272 samplehgrc = uimod.samplehgrcs[b'user']
2273
2273
2274 f = paths[0]
2274 f = paths[0]
2275 fp = open(f, b"wb")
2275 fp = open(f, b"wb")
2276 fp.write(util.tonativeeol(samplehgrc))
2276 fp.write(util.tonativeeol(samplehgrc))
2277 fp.close()
2277 fp.close()
2278
2278
2279 editor = ui.geteditor()
2279 editor = ui.geteditor()
2280 ui.system(
2280 ui.system(
2281 b"%s \"%s\"" % (editor, f),
2281 b"%s \"%s\"" % (editor, f),
2282 onerr=error.InputError,
2282 onerr=error.InputError,
2283 errprefix=_(b"edit failed"),
2283 errprefix=_(b"edit failed"),
2284 blockedtag=b'config_edit',
2284 blockedtag=b'config_edit',
2285 )
2285 )
2286 return
2286 return
2287 ui.pager(b'config')
2287 ui.pager(b'config')
2288 fm = ui.formatter(b'config', opts)
2288 fm = ui.formatter(b'config', opts)
2289 for t, f in rcutil.rccomponents():
2289 for t, f in rcutil.rccomponents():
2290 if t == b'path':
2290 if t == b'path':
2291 ui.debug(b'read config from: %s\n' % f)
2291 ui.debug(b'read config from: %s\n' % f)
2292 elif t == b'resource':
2292 elif t == b'resource':
2293 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2293 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2294 elif t == b'items':
2294 elif t == b'items':
2295 # Don't print anything for 'items'.
2295 # Don't print anything for 'items'.
2296 pass
2296 pass
2297 else:
2297 else:
2298 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2298 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2299 untrusted = bool(opts.get(b'untrusted'))
2299 untrusted = bool(opts.get(b'untrusted'))
2300
2300
2301 selsections = selentries = []
2301 selsections = selentries = []
2302 if values:
2302 if values:
2303 selsections = [v for v in values if b'.' not in v]
2303 selsections = [v for v in values if b'.' not in v]
2304 selentries = [v for v in values if b'.' in v]
2304 selentries = [v for v in values if b'.' in v]
2305 uniquesel = len(selentries) == 1 and not selsections
2305 uniquesel = len(selentries) == 1 and not selsections
2306 selsections = set(selsections)
2306 selsections = set(selsections)
2307 selentries = set(selentries)
2307 selentries = set(selentries)
2308
2308
2309 matched = False
2309 matched = False
2310 for section, name, value in ui.walkconfig(untrusted=untrusted):
2310 for section, name, value in ui.walkconfig(untrusted=untrusted):
2311 source = ui.configsource(section, name, untrusted)
2311 source = ui.configsource(section, name, untrusted)
2312 value = pycompat.bytestr(value)
2312 value = pycompat.bytestr(value)
2313 defaultvalue = ui.configdefault(section, name)
2313 defaultvalue = ui.configdefault(section, name)
2314 if fm.isplain():
2314 if fm.isplain():
2315 source = source or b'none'
2315 source = source or b'none'
2316 value = value.replace(b'\n', b'\\n')
2316 value = value.replace(b'\n', b'\\n')
2317 entryname = section + b'.' + name
2317 entryname = section + b'.' + name
2318 if values and not (section in selsections or entryname in selentries):
2318 if values and not (section in selsections or entryname in selentries):
2319 continue
2319 continue
2320 fm.startitem()
2320 fm.startitem()
2321 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2321 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2322 if uniquesel:
2322 if uniquesel:
2323 fm.data(name=entryname)
2323 fm.data(name=entryname)
2324 fm.write(b'value', b'%s\n', value)
2324 fm.write(b'value', b'%s\n', value)
2325 else:
2325 else:
2326 fm.write(b'name value', b'%s=%s\n', entryname, value)
2326 fm.write(b'name value', b'%s=%s\n', entryname, value)
2327 if formatter.isprintable(defaultvalue):
2327 if formatter.isprintable(defaultvalue):
2328 fm.data(defaultvalue=defaultvalue)
2328 fm.data(defaultvalue=defaultvalue)
2329 elif isinstance(defaultvalue, list) and all(
2329 elif isinstance(defaultvalue, list) and all(
2330 formatter.isprintable(e) for e in defaultvalue
2330 formatter.isprintable(e) for e in defaultvalue
2331 ):
2331 ):
2332 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2332 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2333 # TODO: no idea how to process unsupported defaultvalue types
2333 # TODO: no idea how to process unsupported defaultvalue types
2334 matched = True
2334 matched = True
2335 fm.end()
2335 fm.end()
2336 if matched:
2336 if matched:
2337 return 0
2337 return 0
2338 return 1
2338 return 1
2339
2339
2340
2340
2341 @command(
2341 @command(
2342 b'continue',
2342 b'continue',
2343 dryrunopts,
2343 dryrunopts,
2344 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2344 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2345 helpbasic=True,
2345 helpbasic=True,
2346 )
2346 )
2347 def continuecmd(ui, repo, **opts):
2347 def continuecmd(ui, repo, **opts):
2348 """resumes an interrupted operation (EXPERIMENTAL)
2348 """resumes an interrupted operation (EXPERIMENTAL)
2349
2349
2350 Finishes a multistep operation like graft, histedit, rebase, merge,
2350 Finishes a multistep operation like graft, histedit, rebase, merge,
2351 and unshelve if they are in an interrupted state.
2351 and unshelve if they are in an interrupted state.
2352
2352
2353 use --dry-run/-n to dry run the command.
2353 use --dry-run/-n to dry run the command.
2354 """
2354 """
2355 dryrun = opts.get('dry_run')
2355 dryrun = opts.get('dry_run')
2356 contstate = cmdutil.getunfinishedstate(repo)
2356 contstate = cmdutil.getunfinishedstate(repo)
2357 if not contstate:
2357 if not contstate:
2358 raise error.StateError(_(b'no operation in progress'))
2358 raise error.StateError(_(b'no operation in progress'))
2359 if not contstate.continuefunc:
2359 if not contstate.continuefunc:
2360 raise error.StateError(
2360 raise error.StateError(
2361 (
2361 (
2362 _(b"%s in progress but does not support 'hg continue'")
2362 _(b"%s in progress but does not support 'hg continue'")
2363 % (contstate._opname)
2363 % (contstate._opname)
2364 ),
2364 ),
2365 hint=contstate.continuemsg(),
2365 hint=contstate.continuemsg(),
2366 )
2366 )
2367 if dryrun:
2367 if dryrun:
2368 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2368 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2369 return
2369 return
2370 return contstate.continuefunc(ui, repo)
2370 return contstate.continuefunc(ui, repo)
2371
2371
2372
2372
2373 @command(
2373 @command(
2374 b'copy|cp',
2374 b'copy|cp',
2375 [
2375 [
2376 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2376 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2377 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2377 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2378 (
2378 (
2379 b'',
2379 b'',
2380 b'at-rev',
2380 b'at-rev',
2381 b'',
2381 b'',
2382 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2382 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2383 _(b'REV'),
2383 _(b'REV'),
2384 ),
2384 ),
2385 (
2385 (
2386 b'f',
2386 b'f',
2387 b'force',
2387 b'force',
2388 None,
2388 None,
2389 _(b'forcibly copy over an existing managed file'),
2389 _(b'forcibly copy over an existing managed file'),
2390 ),
2390 ),
2391 ]
2391 ]
2392 + walkopts
2392 + walkopts
2393 + dryrunopts,
2393 + dryrunopts,
2394 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2394 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2395 helpcategory=command.CATEGORY_FILE_CONTENTS,
2395 helpcategory=command.CATEGORY_FILE_CONTENTS,
2396 )
2396 )
2397 def copy(ui, repo, *pats, **opts):
2397 def copy(ui, repo, *pats, **opts):
2398 """mark files as copied for the next commit
2398 """mark files as copied for the next commit
2399
2399
2400 Mark dest as having copies of source files. If dest is a
2400 Mark dest as having copies of source files. If dest is a
2401 directory, copies are put in that directory. If dest is a file,
2401 directory, copies are put in that directory. If dest is a file,
2402 the source must be a single file.
2402 the source must be a single file.
2403
2403
2404 By default, this command copies the contents of files as they
2404 By default, this command copies the contents of files as they
2405 exist in the working directory. If invoked with -A/--after, the
2405 exist in the working directory. If invoked with -A/--after, the
2406 operation is recorded, but no copying is performed.
2406 operation is recorded, but no copying is performed.
2407
2407
2408 To undo marking a destination file as copied, use --forget. With that
2408 To undo marking a destination file as copied, use --forget. With that
2409 option, all given (positional) arguments are unmarked as copies. The
2409 option, all given (positional) arguments are unmarked as copies. The
2410 destination file(s) will be left in place (still tracked).
2410 destination file(s) will be left in place (still tracked).
2411
2411
2412 This command takes effect with the next commit by default.
2412 This command takes effect with the next commit by default.
2413
2413
2414 Returns 0 on success, 1 if errors are encountered.
2414 Returns 0 on success, 1 if errors are encountered.
2415 """
2415 """
2416 opts = pycompat.byteskwargs(opts)
2416 opts = pycompat.byteskwargs(opts)
2417 with repo.wlock():
2417 with repo.wlock():
2418 return cmdutil.copy(ui, repo, pats, opts)
2418 return cmdutil.copy(ui, repo, pats, opts)
2419
2419
2420
2420
2421 @command(
2421 @command(
2422 b'debugcommands',
2422 b'debugcommands',
2423 [],
2423 [],
2424 _(b'[COMMAND]'),
2424 _(b'[COMMAND]'),
2425 helpcategory=command.CATEGORY_HELP,
2425 helpcategory=command.CATEGORY_HELP,
2426 norepo=True,
2426 norepo=True,
2427 )
2427 )
2428 def debugcommands(ui, cmd=b'', *args):
2428 def debugcommands(ui, cmd=b'', *args):
2429 """list all available commands and options"""
2429 """list all available commands and options"""
2430 for cmd, vals in sorted(pycompat.iteritems(table)):
2430 for cmd, vals in sorted(pycompat.iteritems(table)):
2431 cmd = cmd.split(b'|')[0]
2431 cmd = cmd.split(b'|')[0]
2432 opts = b', '.join([i[1] for i in vals[1]])
2432 opts = b', '.join([i[1] for i in vals[1]])
2433 ui.write(b'%s: %s\n' % (cmd, opts))
2433 ui.write(b'%s: %s\n' % (cmd, opts))
2434
2434
2435
2435
2436 @command(
2436 @command(
2437 b'debugcomplete',
2437 b'debugcomplete',
2438 [(b'o', b'options', None, _(b'show the command options'))],
2438 [(b'o', b'options', None, _(b'show the command options'))],
2439 _(b'[-o] CMD'),
2439 _(b'[-o] CMD'),
2440 helpcategory=command.CATEGORY_HELP,
2440 helpcategory=command.CATEGORY_HELP,
2441 norepo=True,
2441 norepo=True,
2442 )
2442 )
2443 def debugcomplete(ui, cmd=b'', **opts):
2443 def debugcomplete(ui, cmd=b'', **opts):
2444 """returns the completion list associated with the given command"""
2444 """returns the completion list associated with the given command"""
2445
2445
2446 if opts.get('options'):
2446 if opts.get('options'):
2447 options = []
2447 options = []
2448 otables = [globalopts]
2448 otables = [globalopts]
2449 if cmd:
2449 if cmd:
2450 aliases, entry = cmdutil.findcmd(cmd, table, False)
2450 aliases, entry = cmdutil.findcmd(cmd, table, False)
2451 otables.append(entry[1])
2451 otables.append(entry[1])
2452 for t in otables:
2452 for t in otables:
2453 for o in t:
2453 for o in t:
2454 if b"(DEPRECATED)" in o[3]:
2454 if b"(DEPRECATED)" in o[3]:
2455 continue
2455 continue
2456 if o[0]:
2456 if o[0]:
2457 options.append(b'-%s' % o[0])
2457 options.append(b'-%s' % o[0])
2458 options.append(b'--%s' % o[1])
2458 options.append(b'--%s' % o[1])
2459 ui.write(b"%s\n" % b"\n".join(options))
2459 ui.write(b"%s\n" % b"\n".join(options))
2460 return
2460 return
2461
2461
2462 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2462 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2463 if ui.verbose:
2463 if ui.verbose:
2464 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2464 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2465 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2465 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2466
2466
2467
2467
2468 @command(
2468 @command(
2469 b'diff',
2469 b'diff',
2470 [
2470 [
2471 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2471 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2472 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2472 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2473 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2473 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2474 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2474 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2475 ]
2475 ]
2476 + diffopts
2476 + diffopts
2477 + diffopts2
2477 + diffopts2
2478 + walkopts
2478 + walkopts
2479 + subrepoopts,
2479 + subrepoopts,
2480 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2480 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2481 helpcategory=command.CATEGORY_FILE_CONTENTS,
2481 helpcategory=command.CATEGORY_FILE_CONTENTS,
2482 helpbasic=True,
2482 helpbasic=True,
2483 inferrepo=True,
2483 inferrepo=True,
2484 intents={INTENT_READONLY},
2484 intents={INTENT_READONLY},
2485 )
2485 )
2486 def diff(ui, repo, *pats, **opts):
2486 def diff(ui, repo, *pats, **opts):
2487 """diff repository (or selected files)
2487 """diff repository (or selected files)
2488
2488
2489 Show differences between revisions for the specified files.
2489 Show differences between revisions for the specified files.
2490
2490
2491 Differences between files are shown using the unified diff format.
2491 Differences between files are shown using the unified diff format.
2492
2492
2493 .. note::
2493 .. note::
2494
2494
2495 :hg:`diff` may generate unexpected results for merges, as it will
2495 :hg:`diff` may generate unexpected results for merges, as it will
2496 default to comparing against the working directory's first
2496 default to comparing against the working directory's first
2497 parent changeset if no revisions are specified.
2497 parent changeset if no revisions are specified.
2498
2498
2499 By default, the working directory files are compared to its first parent. To
2499 By default, the working directory files are compared to its first parent. To
2500 see the differences from another revision, use --from. To see the difference
2500 see the differences from another revision, use --from. To see the difference
2501 to another revision, use --to. For example, :hg:`diff --from .^` will show
2501 to another revision, use --to. For example, :hg:`diff --from .^` will show
2502 the differences from the working copy's grandparent to the working copy,
2502 the differences from the working copy's grandparent to the working copy,
2503 :hg:`diff --to .` will show the diff from the working copy to its parent
2503 :hg:`diff --to .` will show the diff from the working copy to its parent
2504 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2504 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2505 show the diff between those two revisions.
2505 show the diff between those two revisions.
2506
2506
2507 Alternatively you can specify -c/--change with a revision to see the changes
2507 Alternatively you can specify -c/--change with a revision to see the changes
2508 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2508 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2509 equivalent to :hg:`diff --from 42^ --to 42`)
2509 equivalent to :hg:`diff --from 42^ --to 42`)
2510
2510
2511 Without the -a/--text option, diff will avoid generating diffs of
2511 Without the -a/--text option, diff will avoid generating diffs of
2512 files it detects as binary. With -a, diff will generate a diff
2512 files it detects as binary. With -a, diff will generate a diff
2513 anyway, probably with undesirable results.
2513 anyway, probably with undesirable results.
2514
2514
2515 Use the -g/--git option to generate diffs in the git extended diff
2515 Use the -g/--git option to generate diffs in the git extended diff
2516 format. For more information, read :hg:`help diffs`.
2516 format. For more information, read :hg:`help diffs`.
2517
2517
2518 .. container:: verbose
2518 .. container:: verbose
2519
2519
2520 Examples:
2520 Examples:
2521
2521
2522 - compare a file in the current working directory to its parent::
2522 - compare a file in the current working directory to its parent::
2523
2523
2524 hg diff foo.c
2524 hg diff foo.c
2525
2525
2526 - compare two historical versions of a directory, with rename info::
2526 - compare two historical versions of a directory, with rename info::
2527
2527
2528 hg diff --git --from 1.0 --to 1.2 lib/
2528 hg diff --git --from 1.0 --to 1.2 lib/
2529
2529
2530 - get change stats relative to the last change on some date::
2530 - get change stats relative to the last change on some date::
2531
2531
2532 hg diff --stat --from "date('may 2')"
2532 hg diff --stat --from "date('may 2')"
2533
2533
2534 - diff all newly-added files that contain a keyword::
2534 - diff all newly-added files that contain a keyword::
2535
2535
2536 hg diff "set:added() and grep(GNU)"
2536 hg diff "set:added() and grep(GNU)"
2537
2537
2538 - compare a revision and its parents::
2538 - compare a revision and its parents::
2539
2539
2540 hg diff -c 9353 # compare against first parent
2540 hg diff -c 9353 # compare against first parent
2541 hg diff --from 9353^ --to 9353 # same using revset syntax
2541 hg diff --from 9353^ --to 9353 # same using revset syntax
2542 hg diff --from 9353^2 --to 9353 # compare against the second parent
2542 hg diff --from 9353^2 --to 9353 # compare against the second parent
2543
2543
2544 Returns 0 on success.
2544 Returns 0 on success.
2545 """
2545 """
2546
2546
2547 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2547 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2548 opts = pycompat.byteskwargs(opts)
2548 opts = pycompat.byteskwargs(opts)
2549 revs = opts.get(b'rev')
2549 revs = opts.get(b'rev')
2550 change = opts.get(b'change')
2550 change = opts.get(b'change')
2551 from_rev = opts.get(b'from')
2551 from_rev = opts.get(b'from')
2552 to_rev = opts.get(b'to')
2552 to_rev = opts.get(b'to')
2553 stat = opts.get(b'stat')
2553 stat = opts.get(b'stat')
2554 reverse = opts.get(b'reverse')
2554 reverse = opts.get(b'reverse')
2555
2555
2556 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2556 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2557 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2557 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2558 if change:
2558 if change:
2559 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2559 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2560 ctx2 = scmutil.revsingle(repo, change, None)
2560 ctx2 = scmutil.revsingle(repo, change, None)
2561 ctx1 = logcmdutil.diff_parent(ctx2)
2561 ctx1 = logcmdutil.diff_parent(ctx2)
2562 elif from_rev or to_rev:
2562 elif from_rev or to_rev:
2563 repo = scmutil.unhidehashlikerevs(
2563 repo = scmutil.unhidehashlikerevs(
2564 repo, [from_rev] + [to_rev], b'nowarn'
2564 repo, [from_rev] + [to_rev], b'nowarn'
2565 )
2565 )
2566 ctx1 = scmutil.revsingle(repo, from_rev, None)
2566 ctx1 = scmutil.revsingle(repo, from_rev, None)
2567 ctx2 = scmutil.revsingle(repo, to_rev, None)
2567 ctx2 = scmutil.revsingle(repo, to_rev, None)
2568 else:
2568 else:
2569 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2569 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2570 ctx1, ctx2 = scmutil.revpair(repo, revs)
2570 ctx1, ctx2 = scmutil.revpair(repo, revs)
2571
2571
2572 if reverse:
2572 if reverse:
2573 ctxleft = ctx2
2573 ctxleft = ctx2
2574 ctxright = ctx1
2574 ctxright = ctx1
2575 else:
2575 else:
2576 ctxleft = ctx1
2576 ctxleft = ctx1
2577 ctxright = ctx2
2577 ctxright = ctx2
2578
2578
2579 diffopts = patch.diffallopts(ui, opts)
2579 diffopts = patch.diffallopts(ui, opts)
2580 m = scmutil.match(ctx2, pats, opts)
2580 m = scmutil.match(ctx2, pats, opts)
2581 m = repo.narrowmatch(m)
2581 m = repo.narrowmatch(m)
2582 ui.pager(b'diff')
2582 ui.pager(b'diff')
2583 logcmdutil.diffordiffstat(
2583 logcmdutil.diffordiffstat(
2584 ui,
2584 ui,
2585 repo,
2585 repo,
2586 diffopts,
2586 diffopts,
2587 ctxleft,
2587 ctxleft,
2588 ctxright,
2588 ctxright,
2589 m,
2589 m,
2590 stat=stat,
2590 stat=stat,
2591 listsubrepos=opts.get(b'subrepos'),
2591 listsubrepos=opts.get(b'subrepos'),
2592 root=opts.get(b'root'),
2592 root=opts.get(b'root'),
2593 )
2593 )
2594
2594
2595
2595
2596 @command(
2596 @command(
2597 b'export',
2597 b'export',
2598 [
2598 [
2599 (
2599 (
2600 b'B',
2600 b'B',
2601 b'bookmark',
2601 b'bookmark',
2602 b'',
2602 b'',
2603 _(b'export changes only reachable by given bookmark'),
2603 _(b'export changes only reachable by given bookmark'),
2604 _(b'BOOKMARK'),
2604 _(b'BOOKMARK'),
2605 ),
2605 ),
2606 (
2606 (
2607 b'o',
2607 b'o',
2608 b'output',
2608 b'output',
2609 b'',
2609 b'',
2610 _(b'print output to file with formatted name'),
2610 _(b'print output to file with formatted name'),
2611 _(b'FORMAT'),
2611 _(b'FORMAT'),
2612 ),
2612 ),
2613 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2613 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2614 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2614 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2615 ]
2615 ]
2616 + diffopts
2616 + diffopts
2617 + formatteropts,
2617 + formatteropts,
2618 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2618 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2619 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2619 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2620 helpbasic=True,
2620 helpbasic=True,
2621 intents={INTENT_READONLY},
2621 intents={INTENT_READONLY},
2622 )
2622 )
2623 def export(ui, repo, *changesets, **opts):
2623 def export(ui, repo, *changesets, **opts):
2624 """dump the header and diffs for one or more changesets
2624 """dump the header and diffs for one or more changesets
2625
2625
2626 Print the changeset header and diffs for one or more revisions.
2626 Print the changeset header and diffs for one or more revisions.
2627 If no revision is given, the parent of the working directory is used.
2627 If no revision is given, the parent of the working directory is used.
2628
2628
2629 The information shown in the changeset header is: author, date,
2629 The information shown in the changeset header is: author, date,
2630 branch name (if non-default), changeset hash, parent(s) and commit
2630 branch name (if non-default), changeset hash, parent(s) and commit
2631 comment.
2631 comment.
2632
2632
2633 .. note::
2633 .. note::
2634
2634
2635 :hg:`export` may generate unexpected diff output for merge
2635 :hg:`export` may generate unexpected diff output for merge
2636 changesets, as it will compare the merge changeset against its
2636 changesets, as it will compare the merge changeset against its
2637 first parent only.
2637 first parent only.
2638
2638
2639 Output may be to a file, in which case the name of the file is
2639 Output may be to a file, in which case the name of the file is
2640 given using a template string. See :hg:`help templates`. In addition
2640 given using a template string. See :hg:`help templates`. In addition
2641 to the common template keywords, the following formatting rules are
2641 to the common template keywords, the following formatting rules are
2642 supported:
2642 supported:
2643
2643
2644 :``%%``: literal "%" character
2644 :``%%``: literal "%" character
2645 :``%H``: changeset hash (40 hexadecimal digits)
2645 :``%H``: changeset hash (40 hexadecimal digits)
2646 :``%N``: number of patches being generated
2646 :``%N``: number of patches being generated
2647 :``%R``: changeset revision number
2647 :``%R``: changeset revision number
2648 :``%b``: basename of the exporting repository
2648 :``%b``: basename of the exporting repository
2649 :``%h``: short-form changeset hash (12 hexadecimal digits)
2649 :``%h``: short-form changeset hash (12 hexadecimal digits)
2650 :``%m``: first line of the commit message (only alphanumeric characters)
2650 :``%m``: first line of the commit message (only alphanumeric characters)
2651 :``%n``: zero-padded sequence number, starting at 1
2651 :``%n``: zero-padded sequence number, starting at 1
2652 :``%r``: zero-padded changeset revision number
2652 :``%r``: zero-padded changeset revision number
2653 :``\\``: literal "\\" character
2653 :``\\``: literal "\\" character
2654
2654
2655 Without the -a/--text option, export will avoid generating diffs
2655 Without the -a/--text option, export will avoid generating diffs
2656 of files it detects as binary. With -a, export will generate a
2656 of files it detects as binary. With -a, export will generate a
2657 diff anyway, probably with undesirable results.
2657 diff anyway, probably with undesirable results.
2658
2658
2659 With -B/--bookmark changesets reachable by the given bookmark are
2659 With -B/--bookmark changesets reachable by the given bookmark are
2660 selected.
2660 selected.
2661
2661
2662 Use the -g/--git option to generate diffs in the git extended diff
2662 Use the -g/--git option to generate diffs in the git extended diff
2663 format. See :hg:`help diffs` for more information.
2663 format. See :hg:`help diffs` for more information.
2664
2664
2665 With the --switch-parent option, the diff will be against the
2665 With the --switch-parent option, the diff will be against the
2666 second parent. It can be useful to review a merge.
2666 second parent. It can be useful to review a merge.
2667
2667
2668 .. container:: verbose
2668 .. container:: verbose
2669
2669
2670 Template:
2670 Template:
2671
2671
2672 The following keywords are supported in addition to the common template
2672 The following keywords are supported in addition to the common template
2673 keywords and functions. See also :hg:`help templates`.
2673 keywords and functions. See also :hg:`help templates`.
2674
2674
2675 :diff: String. Diff content.
2675 :diff: String. Diff content.
2676 :parents: List of strings. Parent nodes of the changeset.
2676 :parents: List of strings. Parent nodes of the changeset.
2677
2677
2678 Examples:
2678 Examples:
2679
2679
2680 - use export and import to transplant a bugfix to the current
2680 - use export and import to transplant a bugfix to the current
2681 branch::
2681 branch::
2682
2682
2683 hg export -r 9353 | hg import -
2683 hg export -r 9353 | hg import -
2684
2684
2685 - export all the changesets between two revisions to a file with
2685 - export all the changesets between two revisions to a file with
2686 rename information::
2686 rename information::
2687
2687
2688 hg export --git -r 123:150 > changes.txt
2688 hg export --git -r 123:150 > changes.txt
2689
2689
2690 - split outgoing changes into a series of patches with
2690 - split outgoing changes into a series of patches with
2691 descriptive names::
2691 descriptive names::
2692
2692
2693 hg export -r "outgoing()" -o "%n-%m.patch"
2693 hg export -r "outgoing()" -o "%n-%m.patch"
2694
2694
2695 Returns 0 on success.
2695 Returns 0 on success.
2696 """
2696 """
2697 opts = pycompat.byteskwargs(opts)
2697 opts = pycompat.byteskwargs(opts)
2698 bookmark = opts.get(b'bookmark')
2698 bookmark = opts.get(b'bookmark')
2699 changesets += tuple(opts.get(b'rev', []))
2699 changesets += tuple(opts.get(b'rev', []))
2700
2700
2701 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2701 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2702
2702
2703 if bookmark:
2703 if bookmark:
2704 if bookmark not in repo._bookmarks:
2704 if bookmark not in repo._bookmarks:
2705 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2705 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2706
2706
2707 revs = scmutil.bookmarkrevs(repo, bookmark)
2707 revs = scmutil.bookmarkrevs(repo, bookmark)
2708 else:
2708 else:
2709 if not changesets:
2709 if not changesets:
2710 changesets = [b'.']
2710 changesets = [b'.']
2711
2711
2712 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2712 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2713 revs = scmutil.revrange(repo, changesets)
2713 revs = scmutil.revrange(repo, changesets)
2714
2714
2715 if not revs:
2715 if not revs:
2716 raise error.InputError(_(b"export requires at least one changeset"))
2716 raise error.InputError(_(b"export requires at least one changeset"))
2717 if len(revs) > 1:
2717 if len(revs) > 1:
2718 ui.note(_(b'exporting patches:\n'))
2718 ui.note(_(b'exporting patches:\n'))
2719 else:
2719 else:
2720 ui.note(_(b'exporting patch:\n'))
2720 ui.note(_(b'exporting patch:\n'))
2721
2721
2722 fntemplate = opts.get(b'output')
2722 fntemplate = opts.get(b'output')
2723 if cmdutil.isstdiofilename(fntemplate):
2723 if cmdutil.isstdiofilename(fntemplate):
2724 fntemplate = b''
2724 fntemplate = b''
2725
2725
2726 if fntemplate:
2726 if fntemplate:
2727 fm = formatter.nullformatter(ui, b'export', opts)
2727 fm = formatter.nullformatter(ui, b'export', opts)
2728 else:
2728 else:
2729 ui.pager(b'export')
2729 ui.pager(b'export')
2730 fm = ui.formatter(b'export', opts)
2730 fm = ui.formatter(b'export', opts)
2731 with fm:
2731 with fm:
2732 cmdutil.export(
2732 cmdutil.export(
2733 repo,
2733 repo,
2734 revs,
2734 revs,
2735 fm,
2735 fm,
2736 fntemplate=fntemplate,
2736 fntemplate=fntemplate,
2737 switch_parent=opts.get(b'switch_parent'),
2737 switch_parent=opts.get(b'switch_parent'),
2738 opts=patch.diffallopts(ui, opts),
2738 opts=patch.diffallopts(ui, opts),
2739 )
2739 )
2740
2740
2741
2741
2742 @command(
2742 @command(
2743 b'files',
2743 b'files',
2744 [
2744 [
2745 (
2745 (
2746 b'r',
2746 b'r',
2747 b'rev',
2747 b'rev',
2748 b'',
2748 b'',
2749 _(b'search the repository as it is in REV'),
2749 _(b'search the repository as it is in REV'),
2750 _(b'REV'),
2750 _(b'REV'),
2751 ),
2751 ),
2752 (
2752 (
2753 b'0',
2753 b'0',
2754 b'print0',
2754 b'print0',
2755 None,
2755 None,
2756 _(b'end filenames with NUL, for use with xargs'),
2756 _(b'end filenames with NUL, for use with xargs'),
2757 ),
2757 ),
2758 ]
2758 ]
2759 + walkopts
2759 + walkopts
2760 + formatteropts
2760 + formatteropts
2761 + subrepoopts,
2761 + subrepoopts,
2762 _(b'[OPTION]... [FILE]...'),
2762 _(b'[OPTION]... [FILE]...'),
2763 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2763 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2764 intents={INTENT_READONLY},
2764 intents={INTENT_READONLY},
2765 )
2765 )
2766 def files(ui, repo, *pats, **opts):
2766 def files(ui, repo, *pats, **opts):
2767 """list tracked files
2767 """list tracked files
2768
2768
2769 Print files under Mercurial control in the working directory or
2769 Print files under Mercurial control in the working directory or
2770 specified revision for given files (excluding removed files).
2770 specified revision for given files (excluding removed files).
2771 Files can be specified as filenames or filesets.
2771 Files can be specified as filenames or filesets.
2772
2772
2773 If no files are given to match, this command prints the names
2773 If no files are given to match, this command prints the names
2774 of all files under Mercurial control.
2774 of all files under Mercurial control.
2775
2775
2776 .. container:: verbose
2776 .. container:: verbose
2777
2777
2778 Template:
2778 Template:
2779
2779
2780 The following keywords are supported in addition to the common template
2780 The following keywords are supported in addition to the common template
2781 keywords and functions. See also :hg:`help templates`.
2781 keywords and functions. See also :hg:`help templates`.
2782
2782
2783 :flags: String. Character denoting file's symlink and executable bits.
2783 :flags: String. Character denoting file's symlink and executable bits.
2784 :path: String. Repository-absolute path of the file.
2784 :path: String. Repository-absolute path of the file.
2785 :size: Integer. Size of the file in bytes.
2785 :size: Integer. Size of the file in bytes.
2786
2786
2787 Examples:
2787 Examples:
2788
2788
2789 - list all files under the current directory::
2789 - list all files under the current directory::
2790
2790
2791 hg files .
2791 hg files .
2792
2792
2793 - shows sizes and flags for current revision::
2793 - shows sizes and flags for current revision::
2794
2794
2795 hg files -vr .
2795 hg files -vr .
2796
2796
2797 - list all files named README::
2797 - list all files named README::
2798
2798
2799 hg files -I "**/README"
2799 hg files -I "**/README"
2800
2800
2801 - list all binary files::
2801 - list all binary files::
2802
2802
2803 hg files "set:binary()"
2803 hg files "set:binary()"
2804
2804
2805 - find files containing a regular expression::
2805 - find files containing a regular expression::
2806
2806
2807 hg files "set:grep('bob')"
2807 hg files "set:grep('bob')"
2808
2808
2809 - search tracked file contents with xargs and grep::
2809 - search tracked file contents with xargs and grep::
2810
2810
2811 hg files -0 | xargs -0 grep foo
2811 hg files -0 | xargs -0 grep foo
2812
2812
2813 See :hg:`help patterns` and :hg:`help filesets` for more information
2813 See :hg:`help patterns` and :hg:`help filesets` for more information
2814 on specifying file patterns.
2814 on specifying file patterns.
2815
2815
2816 Returns 0 if a match is found, 1 otherwise.
2816 Returns 0 if a match is found, 1 otherwise.
2817
2817
2818 """
2818 """
2819
2819
2820 opts = pycompat.byteskwargs(opts)
2820 opts = pycompat.byteskwargs(opts)
2821 rev = opts.get(b'rev')
2821 rev = opts.get(b'rev')
2822 if rev:
2822 if rev:
2823 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2823 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2824 ctx = scmutil.revsingle(repo, rev, None)
2824 ctx = scmutil.revsingle(repo, rev, None)
2825
2825
2826 end = b'\n'
2826 end = b'\n'
2827 if opts.get(b'print0'):
2827 if opts.get(b'print0'):
2828 end = b'\0'
2828 end = b'\0'
2829 fmt = b'%s' + end
2829 fmt = b'%s' + end
2830
2830
2831 m = scmutil.match(ctx, pats, opts)
2831 m = scmutil.match(ctx, pats, opts)
2832 ui.pager(b'files')
2832 ui.pager(b'files')
2833 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2833 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2834 with ui.formatter(b'files', opts) as fm:
2834 with ui.formatter(b'files', opts) as fm:
2835 return cmdutil.files(
2835 return cmdutil.files(
2836 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2836 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2837 )
2837 )
2838
2838
2839
2839
2840 @command(
2840 @command(
2841 b'forget',
2841 b'forget',
2842 [
2842 [
2843 (b'i', b'interactive', None, _(b'use interactive mode')),
2843 (b'i', b'interactive', None, _(b'use interactive mode')),
2844 ]
2844 ]
2845 + walkopts
2845 + walkopts
2846 + dryrunopts,
2846 + dryrunopts,
2847 _(b'[OPTION]... FILE...'),
2847 _(b'[OPTION]... FILE...'),
2848 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2848 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2849 helpbasic=True,
2849 helpbasic=True,
2850 inferrepo=True,
2850 inferrepo=True,
2851 )
2851 )
2852 def forget(ui, repo, *pats, **opts):
2852 def forget(ui, repo, *pats, **opts):
2853 """forget the specified files on the next commit
2853 """forget the specified files on the next commit
2854
2854
2855 Mark the specified files so they will no longer be tracked
2855 Mark the specified files so they will no longer be tracked
2856 after the next commit.
2856 after the next commit.
2857
2857
2858 This only removes files from the current branch, not from the
2858 This only removes files from the current branch, not from the
2859 entire project history, and it does not delete them from the
2859 entire project history, and it does not delete them from the
2860 working directory.
2860 working directory.
2861
2861
2862 To delete the file from the working directory, see :hg:`remove`.
2862 To delete the file from the working directory, see :hg:`remove`.
2863
2863
2864 To undo a forget before the next commit, see :hg:`add`.
2864 To undo a forget before the next commit, see :hg:`add`.
2865
2865
2866 .. container:: verbose
2866 .. container:: verbose
2867
2867
2868 Examples:
2868 Examples:
2869
2869
2870 - forget newly-added binary files::
2870 - forget newly-added binary files::
2871
2871
2872 hg forget "set:added() and binary()"
2872 hg forget "set:added() and binary()"
2873
2873
2874 - forget files that would be excluded by .hgignore::
2874 - forget files that would be excluded by .hgignore::
2875
2875
2876 hg forget "set:hgignore()"
2876 hg forget "set:hgignore()"
2877
2877
2878 Returns 0 on success.
2878 Returns 0 on success.
2879 """
2879 """
2880
2880
2881 opts = pycompat.byteskwargs(opts)
2881 opts = pycompat.byteskwargs(opts)
2882 if not pats:
2882 if not pats:
2883 raise error.InputError(_(b'no files specified'))
2883 raise error.InputError(_(b'no files specified'))
2884
2884
2885 m = scmutil.match(repo[None], pats, opts)
2885 m = scmutil.match(repo[None], pats, opts)
2886 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2886 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2887 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2887 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2888 rejected = cmdutil.forget(
2888 rejected = cmdutil.forget(
2889 ui,
2889 ui,
2890 repo,
2890 repo,
2891 m,
2891 m,
2892 prefix=b"",
2892 prefix=b"",
2893 uipathfn=uipathfn,
2893 uipathfn=uipathfn,
2894 explicitonly=False,
2894 explicitonly=False,
2895 dryrun=dryrun,
2895 dryrun=dryrun,
2896 interactive=interactive,
2896 interactive=interactive,
2897 )[0]
2897 )[0]
2898 return rejected and 1 or 0
2898 return rejected and 1 or 0
2899
2899
2900
2900
2901 @command(
2901 @command(
2902 b'graft',
2902 b'graft',
2903 [
2903 [
2904 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2904 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2905 (
2905 (
2906 b'',
2906 b'',
2907 b'base',
2907 b'base',
2908 b'',
2908 b'',
2909 _(b'base revision when doing the graft merge (ADVANCED)'),
2909 _(b'base revision when doing the graft merge (ADVANCED)'),
2910 _(b'REV'),
2910 _(b'REV'),
2911 ),
2911 ),
2912 (b'c', b'continue', False, _(b'resume interrupted graft')),
2912 (b'c', b'continue', False, _(b'resume interrupted graft')),
2913 (b'', b'stop', False, _(b'stop interrupted graft')),
2913 (b'', b'stop', False, _(b'stop interrupted graft')),
2914 (b'', b'abort', False, _(b'abort interrupted graft')),
2914 (b'', b'abort', False, _(b'abort interrupted graft')),
2915 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2915 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2916 (b'', b'log', None, _(b'append graft info to log message')),
2916 (b'', b'log', None, _(b'append graft info to log message')),
2917 (
2917 (
2918 b'',
2918 b'',
2919 b'no-commit',
2919 b'no-commit',
2920 None,
2920 None,
2921 _(b"don't commit, just apply the changes in working directory"),
2921 _(b"don't commit, just apply the changes in working directory"),
2922 ),
2922 ),
2923 (b'f', b'force', False, _(b'force graft')),
2923 (b'f', b'force', False, _(b'force graft')),
2924 (
2924 (
2925 b'D',
2925 b'D',
2926 b'currentdate',
2926 b'currentdate',
2927 False,
2927 False,
2928 _(b'record the current date as commit date'),
2928 _(b'record the current date as commit date'),
2929 ),
2929 ),
2930 (
2930 (
2931 b'U',
2931 b'U',
2932 b'currentuser',
2932 b'currentuser',
2933 False,
2933 False,
2934 _(b'record the current user as committer'),
2934 _(b'record the current user as committer'),
2935 ),
2935 ),
2936 ]
2936 ]
2937 + commitopts2
2937 + commitopts2
2938 + mergetoolopts
2938 + mergetoolopts
2939 + dryrunopts,
2939 + dryrunopts,
2940 _(b'[OPTION]... [-r REV]... REV...'),
2940 _(b'[OPTION]... [-r REV]... REV...'),
2941 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2941 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2942 )
2942 )
2943 def graft(ui, repo, *revs, **opts):
2943 def graft(ui, repo, *revs, **opts):
2944 """copy changes from other branches onto the current branch
2944 """copy changes from other branches onto the current branch
2945
2945
2946 This command uses Mercurial's merge logic to copy individual
2946 This command uses Mercurial's merge logic to copy individual
2947 changes from other branches without merging branches in the
2947 changes from other branches without merging branches in the
2948 history graph. This is sometimes known as 'backporting' or
2948 history graph. This is sometimes known as 'backporting' or
2949 'cherry-picking'. By default, graft will copy user, date, and
2949 'cherry-picking'. By default, graft will copy user, date, and
2950 description from the source changesets.
2950 description from the source changesets.
2951
2951
2952 Changesets that are ancestors of the current revision, that have
2952 Changesets that are ancestors of the current revision, that have
2953 already been grafted, or that are merges will be skipped.
2953 already been grafted, or that are merges will be skipped.
2954
2954
2955 If --log is specified, log messages will have a comment appended
2955 If --log is specified, log messages will have a comment appended
2956 of the form::
2956 of the form::
2957
2957
2958 (grafted from CHANGESETHASH)
2958 (grafted from CHANGESETHASH)
2959
2959
2960 If --force is specified, revisions will be grafted even if they
2960 If --force is specified, revisions will be grafted even if they
2961 are already ancestors of, or have been grafted to, the destination.
2961 are already ancestors of, or have been grafted to, the destination.
2962 This is useful when the revisions have since been backed out.
2962 This is useful when the revisions have since been backed out.
2963
2963
2964 If a graft merge results in conflicts, the graft process is
2964 If a graft merge results in conflicts, the graft process is
2965 interrupted so that the current merge can be manually resolved.
2965 interrupted so that the current merge can be manually resolved.
2966 Once all conflicts are addressed, the graft process can be
2966 Once all conflicts are addressed, the graft process can be
2967 continued with the -c/--continue option.
2967 continued with the -c/--continue option.
2968
2968
2969 The -c/--continue option reapplies all the earlier options.
2969 The -c/--continue option reapplies all the earlier options.
2970
2970
2971 .. container:: verbose
2971 .. container:: verbose
2972
2972
2973 The --base option exposes more of how graft internally uses merge with a
2973 The --base option exposes more of how graft internally uses merge with a
2974 custom base revision. --base can be used to specify another ancestor than
2974 custom base revision. --base can be used to specify another ancestor than
2975 the first and only parent.
2975 the first and only parent.
2976
2976
2977 The command::
2977 The command::
2978
2978
2979 hg graft -r 345 --base 234
2979 hg graft -r 345 --base 234
2980
2980
2981 is thus pretty much the same as::
2981 is thus pretty much the same as::
2982
2982
2983 hg diff --from 234 --to 345 | hg import
2983 hg diff --from 234 --to 345 | hg import
2984
2984
2985 but using merge to resolve conflicts and track moved files.
2985 but using merge to resolve conflicts and track moved files.
2986
2986
2987 The result of a merge can thus be backported as a single commit by
2987 The result of a merge can thus be backported as a single commit by
2988 specifying one of the merge parents as base, and thus effectively
2988 specifying one of the merge parents as base, and thus effectively
2989 grafting the changes from the other side.
2989 grafting the changes from the other side.
2990
2990
2991 It is also possible to collapse multiple changesets and clean up history
2991 It is also possible to collapse multiple changesets and clean up history
2992 by specifying another ancestor as base, much like rebase --collapse
2992 by specifying another ancestor as base, much like rebase --collapse
2993 --keep.
2993 --keep.
2994
2994
2995 The commit message can be tweaked after the fact using commit --amend .
2995 The commit message can be tweaked after the fact using commit --amend .
2996
2996
2997 For using non-ancestors as the base to backout changes, see the backout
2997 For using non-ancestors as the base to backout changes, see the backout
2998 command and the hidden --parent option.
2998 command and the hidden --parent option.
2999
2999
3000 .. container:: verbose
3000 .. container:: verbose
3001
3001
3002 Examples:
3002 Examples:
3003
3003
3004 - copy a single change to the stable branch and edit its description::
3004 - copy a single change to the stable branch and edit its description::
3005
3005
3006 hg update stable
3006 hg update stable
3007 hg graft --edit 9393
3007 hg graft --edit 9393
3008
3008
3009 - graft a range of changesets with one exception, updating dates::
3009 - graft a range of changesets with one exception, updating dates::
3010
3010
3011 hg graft -D "2085::2093 and not 2091"
3011 hg graft -D "2085::2093 and not 2091"
3012
3012
3013 - continue a graft after resolving conflicts::
3013 - continue a graft after resolving conflicts::
3014
3014
3015 hg graft -c
3015 hg graft -c
3016
3016
3017 - show the source of a grafted changeset::
3017 - show the source of a grafted changeset::
3018
3018
3019 hg log --debug -r .
3019 hg log --debug -r .
3020
3020
3021 - show revisions sorted by date::
3021 - show revisions sorted by date::
3022
3022
3023 hg log -r "sort(all(), date)"
3023 hg log -r "sort(all(), date)"
3024
3024
3025 - backport the result of a merge as a single commit::
3025 - backport the result of a merge as a single commit::
3026
3026
3027 hg graft -r 123 --base 123^
3027 hg graft -r 123 --base 123^
3028
3028
3029 - land a feature branch as one changeset::
3029 - land a feature branch as one changeset::
3030
3030
3031 hg up -cr default
3031 hg up -cr default
3032 hg graft -r featureX --base "ancestor('featureX', 'default')"
3032 hg graft -r featureX --base "ancestor('featureX', 'default')"
3033
3033
3034 See :hg:`help revisions` for more about specifying revisions.
3034 See :hg:`help revisions` for more about specifying revisions.
3035
3035
3036 Returns 0 on successful completion, 1 if there are unresolved files.
3036 Returns 0 on successful completion, 1 if there are unresolved files.
3037 """
3037 """
3038 with repo.wlock():
3038 with repo.wlock():
3039 return _dograft(ui, repo, *revs, **opts)
3039 return _dograft(ui, repo, *revs, **opts)
3040
3040
3041
3041
3042 def _dograft(ui, repo, *revs, **opts):
3042 def _dograft(ui, repo, *revs, **opts):
3043 opts = pycompat.byteskwargs(opts)
3043 opts = pycompat.byteskwargs(opts)
3044 if revs and opts.get(b'rev'):
3044 if revs and opts.get(b'rev'):
3045 ui.warn(
3045 ui.warn(
3046 _(
3046 _(
3047 b'warning: inconsistent use of --rev might give unexpected '
3047 b'warning: inconsistent use of --rev might give unexpected '
3048 b'revision ordering!\n'
3048 b'revision ordering!\n'
3049 )
3049 )
3050 )
3050 )
3051
3051
3052 revs = list(revs)
3052 revs = list(revs)
3053 revs.extend(opts.get(b'rev'))
3053 revs.extend(opts.get(b'rev'))
3054 # a dict of data to be stored in state file
3054 # a dict of data to be stored in state file
3055 statedata = {}
3055 statedata = {}
3056 # list of new nodes created by ongoing graft
3056 # list of new nodes created by ongoing graft
3057 statedata[b'newnodes'] = []
3057 statedata[b'newnodes'] = []
3058
3058
3059 cmdutil.resolvecommitoptions(ui, opts)
3059 cmdutil.resolvecommitoptions(ui, opts)
3060
3060
3061 editor = cmdutil.getcommiteditor(
3061 editor = cmdutil.getcommiteditor(
3062 editform=b'graft', **pycompat.strkwargs(opts)
3062 editform=b'graft', **pycompat.strkwargs(opts)
3063 )
3063 )
3064
3064
3065 cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
3065 cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
3066
3066
3067 cont = False
3067 cont = False
3068 if opts.get(b'no_commit'):
3068 if opts.get(b'no_commit'):
3069 cmdutil.check_incompatible_arguments(
3069 cmdutil.check_incompatible_arguments(
3070 opts,
3070 opts,
3071 b'no_commit',
3071 b'no_commit',
3072 [b'edit', b'currentuser', b'currentdate', b'log'],
3072 [b'edit', b'currentuser', b'currentdate', b'log'],
3073 )
3073 )
3074
3074
3075 graftstate = statemod.cmdstate(repo, b'graftstate')
3075 graftstate = statemod.cmdstate(repo, b'graftstate')
3076
3076
3077 if opts.get(b'stop'):
3077 if opts.get(b'stop'):
3078 cmdutil.check_incompatible_arguments(
3078 cmdutil.check_incompatible_arguments(
3079 opts,
3079 opts,
3080 b'stop',
3080 b'stop',
3081 [
3081 [
3082 b'edit',
3082 b'edit',
3083 b'log',
3083 b'log',
3084 b'user',
3084 b'user',
3085 b'date',
3085 b'date',
3086 b'currentdate',
3086 b'currentdate',
3087 b'currentuser',
3087 b'currentuser',
3088 b'rev',
3088 b'rev',
3089 ],
3089 ],
3090 )
3090 )
3091 return _stopgraft(ui, repo, graftstate)
3091 return _stopgraft(ui, repo, graftstate)
3092 elif opts.get(b'abort'):
3092 elif opts.get(b'abort'):
3093 cmdutil.check_incompatible_arguments(
3093 cmdutil.check_incompatible_arguments(
3094 opts,
3094 opts,
3095 b'abort',
3095 b'abort',
3096 [
3096 [
3097 b'edit',
3097 b'edit',
3098 b'log',
3098 b'log',
3099 b'user',
3099 b'user',
3100 b'date',
3100 b'date',
3101 b'currentdate',
3101 b'currentdate',
3102 b'currentuser',
3102 b'currentuser',
3103 b'rev',
3103 b'rev',
3104 ],
3104 ],
3105 )
3105 )
3106 return cmdutil.abortgraft(ui, repo, graftstate)
3106 return cmdutil.abortgraft(ui, repo, graftstate)
3107 elif opts.get(b'continue'):
3107 elif opts.get(b'continue'):
3108 cont = True
3108 cont = True
3109 if revs:
3109 if revs:
3110 raise error.InputError(_(b"can't specify --continue and revisions"))
3110 raise error.InputError(_(b"can't specify --continue and revisions"))
3111 # read in unfinished revisions
3111 # read in unfinished revisions
3112 if graftstate.exists():
3112 if graftstate.exists():
3113 statedata = cmdutil.readgraftstate(repo, graftstate)
3113 statedata = cmdutil.readgraftstate(repo, graftstate)
3114 if statedata.get(b'date'):
3114 if statedata.get(b'date'):
3115 opts[b'date'] = statedata[b'date']
3115 opts[b'date'] = statedata[b'date']
3116 if statedata.get(b'user'):
3116 if statedata.get(b'user'):
3117 opts[b'user'] = statedata[b'user']
3117 opts[b'user'] = statedata[b'user']
3118 if statedata.get(b'log'):
3118 if statedata.get(b'log'):
3119 opts[b'log'] = True
3119 opts[b'log'] = True
3120 if statedata.get(b'no_commit'):
3120 if statedata.get(b'no_commit'):
3121 opts[b'no_commit'] = statedata.get(b'no_commit')
3121 opts[b'no_commit'] = statedata.get(b'no_commit')
3122 if statedata.get(b'base'):
3122 if statedata.get(b'base'):
3123 opts[b'base'] = statedata.get(b'base')
3123 opts[b'base'] = statedata.get(b'base')
3124 nodes = statedata[b'nodes']
3124 nodes = statedata[b'nodes']
3125 revs = [repo[node].rev() for node in nodes]
3125 revs = [repo[node].rev() for node in nodes]
3126 else:
3126 else:
3127 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3127 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3128 else:
3128 else:
3129 if not revs:
3129 if not revs:
3130 raise error.InputError(_(b'no revisions specified'))
3130 raise error.InputError(_(b'no revisions specified'))
3131 cmdutil.checkunfinished(repo)
3131 cmdutil.checkunfinished(repo)
3132 cmdutil.bailifchanged(repo)
3132 cmdutil.bailifchanged(repo)
3133 revs = scmutil.revrange(repo, revs)
3133 revs = scmutil.revrange(repo, revs)
3134
3134
3135 skipped = set()
3135 skipped = set()
3136 basectx = None
3136 basectx = None
3137 if opts.get(b'base'):
3137 if opts.get(b'base'):
3138 basectx = scmutil.revsingle(repo, opts[b'base'], None)
3138 basectx = scmutil.revsingle(repo, opts[b'base'], None)
3139 if basectx is None:
3139 if basectx is None:
3140 # check for merges
3140 # check for merges
3141 for rev in repo.revs(b'%ld and merge()', revs):
3141 for rev in repo.revs(b'%ld and merge()', revs):
3142 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3142 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3143 skipped.add(rev)
3143 skipped.add(rev)
3144 revs = [r for r in revs if r not in skipped]
3144 revs = [r for r in revs if r not in skipped]
3145 if not revs:
3145 if not revs:
3146 return -1
3146 return -1
3147 if basectx is not None and len(revs) != 1:
3147 if basectx is not None and len(revs) != 1:
3148 raise error.InputError(_(b'only one revision allowed with --base '))
3148 raise error.InputError(_(b'only one revision allowed with --base '))
3149
3149
3150 # Don't check in the --continue case, in effect retaining --force across
3150 # Don't check in the --continue case, in effect retaining --force across
3151 # --continues. That's because without --force, any revisions we decided to
3151 # --continues. That's because without --force, any revisions we decided to
3152 # skip would have been filtered out here, so they wouldn't have made their
3152 # skip would have been filtered out here, so they wouldn't have made their
3153 # way to the graftstate. With --force, any revisions we would have otherwise
3153 # way to the graftstate. With --force, any revisions we would have otherwise
3154 # skipped would not have been filtered out, and if they hadn't been applied
3154 # skipped would not have been filtered out, and if they hadn't been applied
3155 # already, they'd have been in the graftstate.
3155 # already, they'd have been in the graftstate.
3156 if not (cont or opts.get(b'force')) and basectx is None:
3156 if not (cont or opts.get(b'force')) and basectx is None:
3157 # check for ancestors of dest branch
3157 # check for ancestors of dest branch
3158 ancestors = repo.revs(b'%ld & (::.)', revs)
3158 ancestors = repo.revs(b'%ld & (::.)', revs)
3159 for rev in ancestors:
3159 for rev in ancestors:
3160 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3160 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3161
3161
3162 revs = [r for r in revs if r not in ancestors]
3162 revs = [r for r in revs if r not in ancestors]
3163
3163
3164 if not revs:
3164 if not revs:
3165 return -1
3165 return -1
3166
3166
3167 # analyze revs for earlier grafts
3167 # analyze revs for earlier grafts
3168 ids = {}
3168 ids = {}
3169 for ctx in repo.set(b"%ld", revs):
3169 for ctx in repo.set(b"%ld", revs):
3170 ids[ctx.hex()] = ctx.rev()
3170 ids[ctx.hex()] = ctx.rev()
3171 n = ctx.extra().get(b'source')
3171 n = ctx.extra().get(b'source')
3172 if n:
3172 if n:
3173 ids[n] = ctx.rev()
3173 ids[n] = ctx.rev()
3174
3174
3175 # check ancestors for earlier grafts
3175 # check ancestors for earlier grafts
3176 ui.debug(b'scanning for duplicate grafts\n')
3176 ui.debug(b'scanning for duplicate grafts\n')
3177
3177
3178 # The only changesets we can be sure doesn't contain grafts of any
3178 # The only changesets we can be sure doesn't contain grafts of any
3179 # revs, are the ones that are common ancestors of *all* revs:
3179 # revs, are the ones that are common ancestors of *all* revs:
3180 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3180 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3181 ctx = repo[rev]
3181 ctx = repo[rev]
3182 n = ctx.extra().get(b'source')
3182 n = ctx.extra().get(b'source')
3183 if n in ids:
3183 if n in ids:
3184 try:
3184 try:
3185 r = repo[n].rev()
3185 r = repo[n].rev()
3186 except error.RepoLookupError:
3186 except error.RepoLookupError:
3187 r = None
3187 r = None
3188 if r in revs:
3188 if r in revs:
3189 ui.warn(
3189 ui.warn(
3190 _(
3190 _(
3191 b'skipping revision %d:%s '
3191 b'skipping revision %d:%s '
3192 b'(already grafted to %d:%s)\n'
3192 b'(already grafted to %d:%s)\n'
3193 )
3193 )
3194 % (r, repo[r], rev, ctx)
3194 % (r, repo[r], rev, ctx)
3195 )
3195 )
3196 revs.remove(r)
3196 revs.remove(r)
3197 elif ids[n] in revs:
3197 elif ids[n] in revs:
3198 if r is None:
3198 if r is None:
3199 ui.warn(
3199 ui.warn(
3200 _(
3200 _(
3201 b'skipping already grafted revision %d:%s '
3201 b'skipping already grafted revision %d:%s '
3202 b'(%d:%s also has unknown origin %s)\n'
3202 b'(%d:%s also has unknown origin %s)\n'
3203 )
3203 )
3204 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3204 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3205 )
3205 )
3206 else:
3206 else:
3207 ui.warn(
3207 ui.warn(
3208 _(
3208 _(
3209 b'skipping already grafted revision %d:%s '
3209 b'skipping already grafted revision %d:%s '
3210 b'(%d:%s also has origin %d:%s)\n'
3210 b'(%d:%s also has origin %d:%s)\n'
3211 )
3211 )
3212 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3212 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3213 )
3213 )
3214 revs.remove(ids[n])
3214 revs.remove(ids[n])
3215 elif ctx.hex() in ids:
3215 elif ctx.hex() in ids:
3216 r = ids[ctx.hex()]
3216 r = ids[ctx.hex()]
3217 if r in revs:
3217 if r in revs:
3218 ui.warn(
3218 ui.warn(
3219 _(
3219 _(
3220 b'skipping already grafted revision %d:%s '
3220 b'skipping already grafted revision %d:%s '
3221 b'(was grafted from %d:%s)\n'
3221 b'(was grafted from %d:%s)\n'
3222 )
3222 )
3223 % (r, repo[r], rev, ctx)
3223 % (r, repo[r], rev, ctx)
3224 )
3224 )
3225 revs.remove(r)
3225 revs.remove(r)
3226 if not revs:
3226 if not revs:
3227 return -1
3227 return -1
3228
3228
3229 if opts.get(b'no_commit'):
3229 if opts.get(b'no_commit'):
3230 statedata[b'no_commit'] = True
3230 statedata[b'no_commit'] = True
3231 if opts.get(b'base'):
3231 if opts.get(b'base'):
3232 statedata[b'base'] = opts[b'base']
3232 statedata[b'base'] = opts[b'base']
3233 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3233 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3234 desc = b'%d:%s "%s"' % (
3234 desc = b'%d:%s "%s"' % (
3235 ctx.rev(),
3235 ctx.rev(),
3236 ctx,
3236 ctx,
3237 ctx.description().split(b'\n', 1)[0],
3237 ctx.description().split(b'\n', 1)[0],
3238 )
3238 )
3239 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3239 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3240 if names:
3240 if names:
3241 desc += b' (%s)' % b' '.join(names)
3241 desc += b' (%s)' % b' '.join(names)
3242 ui.status(_(b'grafting %s\n') % desc)
3242 ui.status(_(b'grafting %s\n') % desc)
3243 if opts.get(b'dry_run'):
3243 if opts.get(b'dry_run'):
3244 continue
3244 continue
3245
3245
3246 source = ctx.extra().get(b'source')
3246 source = ctx.extra().get(b'source')
3247 extra = {}
3247 extra = {}
3248 if source:
3248 if source:
3249 extra[b'source'] = source
3249 extra[b'source'] = source
3250 extra[b'intermediate-source'] = ctx.hex()
3250 extra[b'intermediate-source'] = ctx.hex()
3251 else:
3251 else:
3252 extra[b'source'] = ctx.hex()
3252 extra[b'source'] = ctx.hex()
3253 user = ctx.user()
3253 user = ctx.user()
3254 if opts.get(b'user'):
3254 if opts.get(b'user'):
3255 user = opts[b'user']
3255 user = opts[b'user']
3256 statedata[b'user'] = user
3256 statedata[b'user'] = user
3257 date = ctx.date()
3257 date = ctx.date()
3258 if opts.get(b'date'):
3258 if opts.get(b'date'):
3259 date = opts[b'date']
3259 date = opts[b'date']
3260 statedata[b'date'] = date
3260 statedata[b'date'] = date
3261 message = ctx.description()
3261 message = ctx.description()
3262 if opts.get(b'log'):
3262 if opts.get(b'log'):
3263 message += b'\n(grafted from %s)' % ctx.hex()
3263 message += b'\n(grafted from %s)' % ctx.hex()
3264 statedata[b'log'] = True
3264 statedata[b'log'] = True
3265
3265
3266 # we don't merge the first commit when continuing
3266 # we don't merge the first commit when continuing
3267 if not cont:
3267 if not cont:
3268 # perform the graft merge with p1(rev) as 'ancestor'
3268 # perform the graft merge with p1(rev) as 'ancestor'
3269 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3269 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3270 base = ctx.p1() if basectx is None else basectx
3270 base = ctx.p1() if basectx is None else basectx
3271 with ui.configoverride(overrides, b'graft'):
3271 with ui.configoverride(overrides, b'graft'):
3272 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3272 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3273 # report any conflicts
3273 # report any conflicts
3274 if stats.unresolvedcount > 0:
3274 if stats.unresolvedcount > 0:
3275 # write out state for --continue
3275 # write out state for --continue
3276 nodes = [repo[rev].hex() for rev in revs[pos:]]
3276 nodes = [repo[rev].hex() for rev in revs[pos:]]
3277 statedata[b'nodes'] = nodes
3277 statedata[b'nodes'] = nodes
3278 stateversion = 1
3278 stateversion = 1
3279 graftstate.save(stateversion, statedata)
3279 graftstate.save(stateversion, statedata)
3280 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3280 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3281 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3281 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3282 return 1
3282 return 1
3283 else:
3283 else:
3284 cont = False
3284 cont = False
3285
3285
3286 # commit if --no-commit is false
3286 # commit if --no-commit is false
3287 if not opts.get(b'no_commit'):
3287 if not opts.get(b'no_commit'):
3288 node = repo.commit(
3288 node = repo.commit(
3289 text=message, user=user, date=date, extra=extra, editor=editor
3289 text=message, user=user, date=date, extra=extra, editor=editor
3290 )
3290 )
3291 if node is None:
3291 if node is None:
3292 ui.warn(
3292 ui.warn(
3293 _(b'note: graft of %d:%s created no changes to commit\n')
3293 _(b'note: graft of %d:%s created no changes to commit\n')
3294 % (ctx.rev(), ctx)
3294 % (ctx.rev(), ctx)
3295 )
3295 )
3296 # checking that newnodes exist because old state files won't have it
3296 # checking that newnodes exist because old state files won't have it
3297 elif statedata.get(b'newnodes') is not None:
3297 elif statedata.get(b'newnodes') is not None:
3298 statedata[b'newnodes'].append(node)
3298 statedata[b'newnodes'].append(node)
3299
3299
3300 # remove state when we complete successfully
3300 # remove state when we complete successfully
3301 if not opts.get(b'dry_run'):
3301 if not opts.get(b'dry_run'):
3302 graftstate.delete()
3302 graftstate.delete()
3303
3303
3304 return 0
3304 return 0
3305
3305
3306
3306
3307 def _stopgraft(ui, repo, graftstate):
3307 def _stopgraft(ui, repo, graftstate):
3308 """stop the interrupted graft"""
3308 """stop the interrupted graft"""
3309 if not graftstate.exists():
3309 if not graftstate.exists():
3310 raise error.StateError(_(b"no interrupted graft found"))
3310 raise error.StateError(_(b"no interrupted graft found"))
3311 pctx = repo[b'.']
3311 pctx = repo[b'.']
3312 mergemod.clean_update(pctx)
3312 mergemod.clean_update(pctx)
3313 graftstate.delete()
3313 graftstate.delete()
3314 ui.status(_(b"stopped the interrupted graft\n"))
3314 ui.status(_(b"stopped the interrupted graft\n"))
3315 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3315 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3316 return 0
3316 return 0
3317
3317
3318
3318
3319 statemod.addunfinished(
3319 statemod.addunfinished(
3320 b'graft',
3320 b'graft',
3321 fname=b'graftstate',
3321 fname=b'graftstate',
3322 clearable=True,
3322 clearable=True,
3323 stopflag=True,
3323 stopflag=True,
3324 continueflag=True,
3324 continueflag=True,
3325 abortfunc=cmdutil.hgabortgraft,
3325 abortfunc=cmdutil.hgabortgraft,
3326 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3326 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3327 )
3327 )
3328
3328
3329
3329
3330 @command(
3330 @command(
3331 b'grep',
3331 b'grep',
3332 [
3332 [
3333 (b'0', b'print0', None, _(b'end fields with NUL')),
3333 (b'0', b'print0', None, _(b'end fields with NUL')),
3334 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3334 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3335 (
3335 (
3336 b'',
3336 b'',
3337 b'diff',
3337 b'diff',
3338 None,
3338 None,
3339 _(
3339 _(
3340 b'search revision differences for when the pattern was added '
3340 b'search revision differences for when the pattern was added '
3341 b'or removed'
3341 b'or removed'
3342 ),
3342 ),
3343 ),
3343 ),
3344 (b'a', b'text', None, _(b'treat all files as text')),
3344 (b'a', b'text', None, _(b'treat all files as text')),
3345 (
3345 (
3346 b'f',
3346 b'f',
3347 b'follow',
3347 b'follow',
3348 None,
3348 None,
3349 _(
3349 _(
3350 b'follow changeset history,'
3350 b'follow changeset history,'
3351 b' or file history across copies and renames'
3351 b' or file history across copies and renames'
3352 ),
3352 ),
3353 ),
3353 ),
3354 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3354 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3355 (
3355 (
3356 b'l',
3356 b'l',
3357 b'files-with-matches',
3357 b'files-with-matches',
3358 None,
3358 None,
3359 _(b'print only filenames and revisions that match'),
3359 _(b'print only filenames and revisions that match'),
3360 ),
3360 ),
3361 (b'n', b'line-number', None, _(b'print matching line numbers')),
3361 (b'n', b'line-number', None, _(b'print matching line numbers')),
3362 (
3362 (
3363 b'r',
3363 b'r',
3364 b'rev',
3364 b'rev',
3365 [],
3365 [],
3366 _(b'search files changed within revision range'),
3366 _(b'search files changed within revision range'),
3367 _(b'REV'),
3367 _(b'REV'),
3368 ),
3368 ),
3369 (
3369 (
3370 b'',
3370 b'',
3371 b'all-files',
3371 b'all-files',
3372 None,
3372 None,
3373 _(
3373 _(
3374 b'include all files in the changeset while grepping (DEPRECATED)'
3374 b'include all files in the changeset while grepping (DEPRECATED)'
3375 ),
3375 ),
3376 ),
3376 ),
3377 (b'u', b'user', None, _(b'list the author (long with -v)')),
3377 (b'u', b'user', None, _(b'list the author (long with -v)')),
3378 (b'd', b'date', None, _(b'list the date (short with -q)')),
3378 (b'd', b'date', None, _(b'list the date (short with -q)')),
3379 ]
3379 ]
3380 + formatteropts
3380 + formatteropts
3381 + walkopts,
3381 + walkopts,
3382 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3382 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3383 helpcategory=command.CATEGORY_FILE_CONTENTS,
3383 helpcategory=command.CATEGORY_FILE_CONTENTS,
3384 inferrepo=True,
3384 inferrepo=True,
3385 intents={INTENT_READONLY},
3385 intents={INTENT_READONLY},
3386 )
3386 )
3387 def grep(ui, repo, pattern, *pats, **opts):
3387 def grep(ui, repo, pattern, *pats, **opts):
3388 """search for a pattern in specified files
3388 """search for a pattern in specified files
3389
3389
3390 Search the working directory or revision history for a regular
3390 Search the working directory or revision history for a regular
3391 expression in the specified files for the entire repository.
3391 expression in the specified files for the entire repository.
3392
3392
3393 By default, grep searches the repository files in the working
3393 By default, grep searches the repository files in the working
3394 directory and prints the files where it finds a match. To specify
3394 directory and prints the files where it finds a match. To specify
3395 historical revisions instead of the working directory, use the
3395 historical revisions instead of the working directory, use the
3396 --rev flag.
3396 --rev flag.
3397
3397
3398 To search instead historical revision differences that contains a
3398 To search instead historical revision differences that contains a
3399 change in match status ("-" for a match that becomes a non-match,
3399 change in match status ("-" for a match that becomes a non-match,
3400 or "+" for a non-match that becomes a match), use the --diff flag.
3400 or "+" for a non-match that becomes a match), use the --diff flag.
3401
3401
3402 PATTERN can be any Python (roughly Perl-compatible) regular
3402 PATTERN can be any Python (roughly Perl-compatible) regular
3403 expression.
3403 expression.
3404
3404
3405 If no FILEs are specified and the --rev flag isn't supplied, all
3405 If no FILEs are specified and the --rev flag isn't supplied, all
3406 files in the working directory are searched. When using the --rev
3406 files in the working directory are searched. When using the --rev
3407 flag and specifying FILEs, use the --follow argument to also
3407 flag and specifying FILEs, use the --follow argument to also
3408 follow the specified FILEs across renames and copies.
3408 follow the specified FILEs across renames and copies.
3409
3409
3410 .. container:: verbose
3410 .. container:: verbose
3411
3411
3412 Template:
3412 Template:
3413
3413
3414 The following keywords are supported in addition to the common template
3414 The following keywords are supported in addition to the common template
3415 keywords and functions. See also :hg:`help templates`.
3415 keywords and functions. See also :hg:`help templates`.
3416
3416
3417 :change: String. Character denoting insertion ``+`` or removal ``-``.
3417 :change: String. Character denoting insertion ``+`` or removal ``-``.
3418 Available if ``--diff`` is specified.
3418 Available if ``--diff`` is specified.
3419 :lineno: Integer. Line number of the match.
3419 :lineno: Integer. Line number of the match.
3420 :path: String. Repository-absolute path of the file.
3420 :path: String. Repository-absolute path of the file.
3421 :texts: List of text chunks.
3421 :texts: List of text chunks.
3422
3422
3423 And each entry of ``{texts}`` provides the following sub-keywords.
3423 And each entry of ``{texts}`` provides the following sub-keywords.
3424
3424
3425 :matched: Boolean. True if the chunk matches the specified pattern.
3425 :matched: Boolean. True if the chunk matches the specified pattern.
3426 :text: String. Chunk content.
3426 :text: String. Chunk content.
3427
3427
3428 See :hg:`help templates.operators` for the list expansion syntax.
3428 See :hg:`help templates.operators` for the list expansion syntax.
3429
3429
3430 Returns 0 if a match is found, 1 otherwise.
3430 Returns 0 if a match is found, 1 otherwise.
3431
3431
3432 """
3432 """
3433 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3433 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3434 opts = pycompat.byteskwargs(opts)
3434 opts = pycompat.byteskwargs(opts)
3435 diff = opts.get(b'all') or opts.get(b'diff')
3435 diff = opts.get(b'all') or opts.get(b'diff')
3436 follow = opts.get(b'follow')
3436 follow = opts.get(b'follow')
3437 if opts.get(b'all_files') is None and not diff:
3437 if opts.get(b'all_files') is None and not diff:
3438 opts[b'all_files'] = True
3438 opts[b'all_files'] = True
3439 plaingrep = (
3439 plaingrep = (
3440 opts.get(b'all_files')
3440 opts.get(b'all_files')
3441 and not opts.get(b'rev')
3441 and not opts.get(b'rev')
3442 and not opts.get(b'follow')
3442 and not opts.get(b'follow')
3443 )
3443 )
3444 all_files = opts.get(b'all_files')
3444 all_files = opts.get(b'all_files')
3445 if plaingrep:
3445 if plaingrep:
3446 opts[b'rev'] = [b'wdir()']
3446 opts[b'rev'] = [b'wdir()']
3447
3447
3448 reflags = re.M
3448 reflags = re.M
3449 if opts.get(b'ignore_case'):
3449 if opts.get(b'ignore_case'):
3450 reflags |= re.I
3450 reflags |= re.I
3451 try:
3451 try:
3452 regexp = util.re.compile(pattern, reflags)
3452 regexp = util.re.compile(pattern, reflags)
3453 except re.error as inst:
3453 except re.error as inst:
3454 ui.warn(
3454 ui.warn(
3455 _(b"grep: invalid match pattern: %s\n")
3455 _(b"grep: invalid match pattern: %s\n")
3456 % stringutil.forcebytestr(inst)
3456 % stringutil.forcebytestr(inst)
3457 )
3457 )
3458 return 1
3458 return 1
3459 sep, eol = b':', b'\n'
3459 sep, eol = b':', b'\n'
3460 if opts.get(b'print0'):
3460 if opts.get(b'print0'):
3461 sep = eol = b'\0'
3461 sep = eol = b'\0'
3462
3462
3463 searcher = grepmod.grepsearcher(
3463 searcher = grepmod.grepsearcher(
3464 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3464 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3465 )
3465 )
3466
3466
3467 getfile = searcher._getfile
3467 getfile = searcher._getfile
3468
3468
3469 uipathfn = scmutil.getuipathfn(repo)
3469 uipathfn = scmutil.getuipathfn(repo)
3470
3470
3471 def display(fm, fn, ctx, pstates, states):
3471 def display(fm, fn, ctx, pstates, states):
3472 rev = scmutil.intrev(ctx)
3472 rev = scmutil.intrev(ctx)
3473 if fm.isplain():
3473 if fm.isplain():
3474 formatuser = ui.shortuser
3474 formatuser = ui.shortuser
3475 else:
3475 else:
3476 formatuser = pycompat.bytestr
3476 formatuser = pycompat.bytestr
3477 if ui.quiet:
3477 if ui.quiet:
3478 datefmt = b'%Y-%m-%d'
3478 datefmt = b'%Y-%m-%d'
3479 else:
3479 else:
3480 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3480 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3481 found = False
3481 found = False
3482
3482
3483 @util.cachefunc
3483 @util.cachefunc
3484 def binary():
3484 def binary():
3485 flog = getfile(fn)
3485 flog = getfile(fn)
3486 try:
3486 try:
3487 return stringutil.binary(flog.read(ctx.filenode(fn)))
3487 return stringutil.binary(flog.read(ctx.filenode(fn)))
3488 except error.WdirUnsupported:
3488 except error.WdirUnsupported:
3489 return ctx[fn].isbinary()
3489 return ctx[fn].isbinary()
3490
3490
3491 fieldnamemap = {b'linenumber': b'lineno'}
3491 fieldnamemap = {b'linenumber': b'lineno'}
3492 if diff:
3492 if diff:
3493 iter = grepmod.difflinestates(pstates, states)
3493 iter = grepmod.difflinestates(pstates, states)
3494 else:
3494 else:
3495 iter = [(b'', l) for l in states]
3495 iter = [(b'', l) for l in states]
3496 for change, l in iter:
3496 for change, l in iter:
3497 fm.startitem()
3497 fm.startitem()
3498 fm.context(ctx=ctx)
3498 fm.context(ctx=ctx)
3499 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3499 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3500 fm.plain(uipathfn(fn), label=b'grep.filename')
3500 fm.plain(uipathfn(fn), label=b'grep.filename')
3501
3501
3502 cols = [
3502 cols = [
3503 (b'rev', b'%d', rev, not plaingrep, b''),
3503 (b'rev', b'%d', rev, not plaingrep, b''),
3504 (
3504 (
3505 b'linenumber',
3505 b'linenumber',
3506 b'%d',
3506 b'%d',
3507 l.linenum,
3507 l.linenum,
3508 opts.get(b'line_number'),
3508 opts.get(b'line_number'),
3509 b'',
3509 b'',
3510 ),
3510 ),
3511 ]
3511 ]
3512 if diff:
3512 if diff:
3513 cols.append(
3513 cols.append(
3514 (
3514 (
3515 b'change',
3515 b'change',
3516 b'%s',
3516 b'%s',
3517 change,
3517 change,
3518 True,
3518 True,
3519 b'grep.inserted '
3519 b'grep.inserted '
3520 if change == b'+'
3520 if change == b'+'
3521 else b'grep.deleted ',
3521 else b'grep.deleted ',
3522 )
3522 )
3523 )
3523 )
3524 cols.extend(
3524 cols.extend(
3525 [
3525 [
3526 (
3526 (
3527 b'user',
3527 b'user',
3528 b'%s',
3528 b'%s',
3529 formatuser(ctx.user()),
3529 formatuser(ctx.user()),
3530 opts.get(b'user'),
3530 opts.get(b'user'),
3531 b'',
3531 b'',
3532 ),
3532 ),
3533 (
3533 (
3534 b'date',
3534 b'date',
3535 b'%s',
3535 b'%s',
3536 fm.formatdate(ctx.date(), datefmt),
3536 fm.formatdate(ctx.date(), datefmt),
3537 opts.get(b'date'),
3537 opts.get(b'date'),
3538 b'',
3538 b'',
3539 ),
3539 ),
3540 ]
3540 ]
3541 )
3541 )
3542 for name, fmt, data, cond, extra_label in cols:
3542 for name, fmt, data, cond, extra_label in cols:
3543 if cond:
3543 if cond:
3544 fm.plain(sep, label=b'grep.sep')
3544 fm.plain(sep, label=b'grep.sep')
3545 field = fieldnamemap.get(name, name)
3545 field = fieldnamemap.get(name, name)
3546 label = extra_label + (b'grep.%s' % name)
3546 label = extra_label + (b'grep.%s' % name)
3547 fm.condwrite(cond, field, fmt, data, label=label)
3547 fm.condwrite(cond, field, fmt, data, label=label)
3548 if not opts.get(b'files_with_matches'):
3548 if not opts.get(b'files_with_matches'):
3549 fm.plain(sep, label=b'grep.sep')
3549 fm.plain(sep, label=b'grep.sep')
3550 if not opts.get(b'text') and binary():
3550 if not opts.get(b'text') and binary():
3551 fm.plain(_(b" Binary file matches"))
3551 fm.plain(_(b" Binary file matches"))
3552 else:
3552 else:
3553 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3553 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3554 fm.plain(eol)
3554 fm.plain(eol)
3555 found = True
3555 found = True
3556 if opts.get(b'files_with_matches'):
3556 if opts.get(b'files_with_matches'):
3557 break
3557 break
3558 return found
3558 return found
3559
3559
3560 def displaymatches(fm, l):
3560 def displaymatches(fm, l):
3561 p = 0
3561 p = 0
3562 for s, e in l.findpos(regexp):
3562 for s, e in l.findpos(regexp):
3563 if p < s:
3563 if p < s:
3564 fm.startitem()
3564 fm.startitem()
3565 fm.write(b'text', b'%s', l.line[p:s])
3565 fm.write(b'text', b'%s', l.line[p:s])
3566 fm.data(matched=False)
3566 fm.data(matched=False)
3567 fm.startitem()
3567 fm.startitem()
3568 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3568 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3569 fm.data(matched=True)
3569 fm.data(matched=True)
3570 p = e
3570 p = e
3571 if p < len(l.line):
3571 if p < len(l.line):
3572 fm.startitem()
3572 fm.startitem()
3573 fm.write(b'text', b'%s', l.line[p:])
3573 fm.write(b'text', b'%s', l.line[p:])
3574 fm.data(matched=False)
3574 fm.data(matched=False)
3575 fm.end()
3575 fm.end()
3576
3576
3577 found = False
3577 found = False
3578
3578
3579 wopts = logcmdutil.walkopts(
3579 wopts = logcmdutil.walkopts(
3580 pats=pats,
3580 pats=pats,
3581 opts=opts,
3581 opts=opts,
3582 revspec=opts[b'rev'],
3582 revspec=opts[b'rev'],
3583 include_pats=opts[b'include'],
3583 include_pats=opts[b'include'],
3584 exclude_pats=opts[b'exclude'],
3584 exclude_pats=opts[b'exclude'],
3585 follow=follow,
3585 follow=follow,
3586 force_changelog_traversal=all_files,
3586 force_changelog_traversal=all_files,
3587 filter_revisions_by_pats=not all_files,
3587 filter_revisions_by_pats=not all_files,
3588 )
3588 )
3589 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3589 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3590
3590
3591 ui.pager(b'grep')
3591 ui.pager(b'grep')
3592 fm = ui.formatter(b'grep', opts)
3592 fm = ui.formatter(b'grep', opts)
3593 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3593 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3594 r = display(fm, fn, ctx, pstates, states)
3594 r = display(fm, fn, ctx, pstates, states)
3595 found = found or r
3595 found = found or r
3596 if r and not diff and not all_files:
3596 if r and not diff and not all_files:
3597 searcher.skipfile(fn, ctx.rev())
3597 searcher.skipfile(fn, ctx.rev())
3598 fm.end()
3598 fm.end()
3599
3599
3600 return not found
3600 return not found
3601
3601
3602
3602
3603 @command(
3603 @command(
3604 b'heads',
3604 b'heads',
3605 [
3605 [
3606 (
3606 (
3607 b'r',
3607 b'r',
3608 b'rev',
3608 b'rev',
3609 b'',
3609 b'',
3610 _(b'show only heads which are descendants of STARTREV'),
3610 _(b'show only heads which are descendants of STARTREV'),
3611 _(b'STARTREV'),
3611 _(b'STARTREV'),
3612 ),
3612 ),
3613 (b't', b'topo', False, _(b'show topological heads only')),
3613 (b't', b'topo', False, _(b'show topological heads only')),
3614 (
3614 (
3615 b'a',
3615 b'a',
3616 b'active',
3616 b'active',
3617 False,
3617 False,
3618 _(b'show active branchheads only (DEPRECATED)'),
3618 _(b'show active branchheads only (DEPRECATED)'),
3619 ),
3619 ),
3620 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3620 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3621 ]
3621 ]
3622 + templateopts,
3622 + templateopts,
3623 _(b'[-ct] [-r STARTREV] [REV]...'),
3623 _(b'[-ct] [-r STARTREV] [REV]...'),
3624 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3624 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3625 intents={INTENT_READONLY},
3625 intents={INTENT_READONLY},
3626 )
3626 )
3627 def heads(ui, repo, *branchrevs, **opts):
3627 def heads(ui, repo, *branchrevs, **opts):
3628 """show branch heads
3628 """show branch heads
3629
3629
3630 With no arguments, show all open branch heads in the repository.
3630 With no arguments, show all open branch heads in the repository.
3631 Branch heads are changesets that have no descendants on the
3631 Branch heads are changesets that have no descendants on the
3632 same branch. They are where development generally takes place and
3632 same branch. They are where development generally takes place and
3633 are the usual targets for update and merge operations.
3633 are the usual targets for update and merge operations.
3634
3634
3635 If one or more REVs are given, only open branch heads on the
3635 If one or more REVs are given, only open branch heads on the
3636 branches associated with the specified changesets are shown. This
3636 branches associated with the specified changesets are shown. This
3637 means that you can use :hg:`heads .` to see the heads on the
3637 means that you can use :hg:`heads .` to see the heads on the
3638 currently checked-out branch.
3638 currently checked-out branch.
3639
3639
3640 If -c/--closed is specified, also show branch heads marked closed
3640 If -c/--closed is specified, also show branch heads marked closed
3641 (see :hg:`commit --close-branch`).
3641 (see :hg:`commit --close-branch`).
3642
3642
3643 If STARTREV is specified, only those heads that are descendants of
3643 If STARTREV is specified, only those heads that are descendants of
3644 STARTREV will be displayed.
3644 STARTREV will be displayed.
3645
3645
3646 If -t/--topo is specified, named branch mechanics will be ignored and only
3646 If -t/--topo is specified, named branch mechanics will be ignored and only
3647 topological heads (changesets with no children) will be shown.
3647 topological heads (changesets with no children) will be shown.
3648
3648
3649 Returns 0 if matching heads are found, 1 if not.
3649 Returns 0 if matching heads are found, 1 if not.
3650 """
3650 """
3651
3651
3652 opts = pycompat.byteskwargs(opts)
3652 opts = pycompat.byteskwargs(opts)
3653 start = None
3653 start = None
3654 rev = opts.get(b'rev')
3654 rev = opts.get(b'rev')
3655 if rev:
3655 if rev:
3656 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3656 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3657 start = scmutil.revsingle(repo, rev, None).node()
3657 start = scmutil.revsingle(repo, rev, None).node()
3658
3658
3659 if opts.get(b'topo'):
3659 if opts.get(b'topo'):
3660 heads = [repo[h] for h in repo.heads(start)]
3660 heads = [repo[h] for h in repo.heads(start)]
3661 else:
3661 else:
3662 heads = []
3662 heads = []
3663 for branch in repo.branchmap():
3663 for branch in repo.branchmap():
3664 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3664 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3665 heads = [repo[h] for h in heads]
3665 heads = [repo[h] for h in heads]
3666
3666
3667 if branchrevs:
3667 if branchrevs:
3668 branches = {
3668 branches = {
3669 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3669 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3670 }
3670 }
3671 heads = [h for h in heads if h.branch() in branches]
3671 heads = [h for h in heads if h.branch() in branches]
3672
3672
3673 if opts.get(b'active') and branchrevs:
3673 if opts.get(b'active') and branchrevs:
3674 dagheads = repo.heads(start)
3674 dagheads = repo.heads(start)
3675 heads = [h for h in heads if h.node() in dagheads]
3675 heads = [h for h in heads if h.node() in dagheads]
3676
3676
3677 if branchrevs:
3677 if branchrevs:
3678 haveheads = {h.branch() for h in heads}
3678 haveheads = {h.branch() for h in heads}
3679 if branches - haveheads:
3679 if branches - haveheads:
3680 headless = b', '.join(b for b in branches - haveheads)
3680 headless = b', '.join(b for b in branches - haveheads)
3681 msg = _(b'no open branch heads found on branches %s')
3681 msg = _(b'no open branch heads found on branches %s')
3682 if opts.get(b'rev'):
3682 if opts.get(b'rev'):
3683 msg += _(b' (started at %s)') % opts[b'rev']
3683 msg += _(b' (started at %s)') % opts[b'rev']
3684 ui.warn((msg + b'\n') % headless)
3684 ui.warn((msg + b'\n') % headless)
3685
3685
3686 if not heads:
3686 if not heads:
3687 return 1
3687 return 1
3688
3688
3689 ui.pager(b'heads')
3689 ui.pager(b'heads')
3690 heads = sorted(heads, key=lambda x: -(x.rev()))
3690 heads = sorted(heads, key=lambda x: -(x.rev()))
3691 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3691 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3692 for ctx in heads:
3692 for ctx in heads:
3693 displayer.show(ctx)
3693 displayer.show(ctx)
3694 displayer.close()
3694 displayer.close()
3695
3695
3696
3696
3697 @command(
3697 @command(
3698 b'help',
3698 b'help',
3699 [
3699 [
3700 (b'e', b'extension', None, _(b'show only help for extensions')),
3700 (b'e', b'extension', None, _(b'show only help for extensions')),
3701 (b'c', b'command', None, _(b'show only help for commands')),
3701 (b'c', b'command', None, _(b'show only help for commands')),
3702 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3702 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3703 (
3703 (
3704 b's',
3704 b's',
3705 b'system',
3705 b'system',
3706 [],
3706 [],
3707 _(b'show help for specific platform(s)'),
3707 _(b'show help for specific platform(s)'),
3708 _(b'PLATFORM'),
3708 _(b'PLATFORM'),
3709 ),
3709 ),
3710 ],
3710 ],
3711 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3711 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3712 helpcategory=command.CATEGORY_HELP,
3712 helpcategory=command.CATEGORY_HELP,
3713 norepo=True,
3713 norepo=True,
3714 intents={INTENT_READONLY},
3714 intents={INTENT_READONLY},
3715 )
3715 )
3716 def help_(ui, name=None, **opts):
3716 def help_(ui, name=None, **opts):
3717 """show help for a given topic or a help overview
3717 """show help for a given topic or a help overview
3718
3718
3719 With no arguments, print a list of commands with short help messages.
3719 With no arguments, print a list of commands with short help messages.
3720
3720
3721 Given a topic, extension, or command name, print help for that
3721 Given a topic, extension, or command name, print help for that
3722 topic.
3722 topic.
3723
3723
3724 Returns 0 if successful.
3724 Returns 0 if successful.
3725 """
3725 """
3726
3726
3727 keep = opts.get('system') or []
3727 keep = opts.get('system') or []
3728 if len(keep) == 0:
3728 if len(keep) == 0:
3729 if pycompat.sysplatform.startswith(b'win'):
3729 if pycompat.sysplatform.startswith(b'win'):
3730 keep.append(b'windows')
3730 keep.append(b'windows')
3731 elif pycompat.sysplatform == b'OpenVMS':
3731 elif pycompat.sysplatform == b'OpenVMS':
3732 keep.append(b'vms')
3732 keep.append(b'vms')
3733 elif pycompat.sysplatform == b'plan9':
3733 elif pycompat.sysplatform == b'plan9':
3734 keep.append(b'plan9')
3734 keep.append(b'plan9')
3735 else:
3735 else:
3736 keep.append(b'unix')
3736 keep.append(b'unix')
3737 keep.append(pycompat.sysplatform.lower())
3737 keep.append(pycompat.sysplatform.lower())
3738 if ui.verbose:
3738 if ui.verbose:
3739 keep.append(b'verbose')
3739 keep.append(b'verbose')
3740
3740
3741 commands = sys.modules[__name__]
3741 commands = sys.modules[__name__]
3742 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3742 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3743 ui.pager(b'help')
3743 ui.pager(b'help')
3744 ui.write(formatted)
3744 ui.write(formatted)
3745
3745
3746
3746
3747 @command(
3747 @command(
3748 b'identify|id',
3748 b'identify|id',
3749 [
3749 [
3750 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3750 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3751 (b'n', b'num', None, _(b'show local revision number')),
3751 (b'n', b'num', None, _(b'show local revision number')),
3752 (b'i', b'id', None, _(b'show global revision id')),
3752 (b'i', b'id', None, _(b'show global revision id')),
3753 (b'b', b'branch', None, _(b'show branch')),
3753 (b'b', b'branch', None, _(b'show branch')),
3754 (b't', b'tags', None, _(b'show tags')),
3754 (b't', b'tags', None, _(b'show tags')),
3755 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3755 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3756 ]
3756 ]
3757 + remoteopts
3757 + remoteopts
3758 + formatteropts,
3758 + formatteropts,
3759 _(b'[-nibtB] [-r REV] [SOURCE]'),
3759 _(b'[-nibtB] [-r REV] [SOURCE]'),
3760 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3760 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3761 optionalrepo=True,
3761 optionalrepo=True,
3762 intents={INTENT_READONLY},
3762 intents={INTENT_READONLY},
3763 )
3763 )
3764 def identify(
3764 def identify(
3765 ui,
3765 ui,
3766 repo,
3766 repo,
3767 source=None,
3767 source=None,
3768 rev=None,
3768 rev=None,
3769 num=None,
3769 num=None,
3770 id=None,
3770 id=None,
3771 branch=None,
3771 branch=None,
3772 tags=None,
3772 tags=None,
3773 bookmarks=None,
3773 bookmarks=None,
3774 **opts
3774 **opts
3775 ):
3775 ):
3776 """identify the working directory or specified revision
3776 """identify the working directory or specified revision
3777
3777
3778 Print a summary identifying the repository state at REV using one or
3778 Print a summary identifying the repository state at REV using one or
3779 two parent hash identifiers, followed by a "+" if the working
3779 two parent hash identifiers, followed by a "+" if the working
3780 directory has uncommitted changes, the branch name (if not default),
3780 directory has uncommitted changes, the branch name (if not default),
3781 a list of tags, and a list of bookmarks.
3781 a list of tags, and a list of bookmarks.
3782
3782
3783 When REV is not given, print a summary of the current state of the
3783 When REV is not given, print a summary of the current state of the
3784 repository including the working directory. Specify -r. to get information
3784 repository including the working directory. Specify -r. to get information
3785 of the working directory parent without scanning uncommitted changes.
3785 of the working directory parent without scanning uncommitted changes.
3786
3786
3787 Specifying a path to a repository root or Mercurial bundle will
3787 Specifying a path to a repository root or Mercurial bundle will
3788 cause lookup to operate on that repository/bundle.
3788 cause lookup to operate on that repository/bundle.
3789
3789
3790 .. container:: verbose
3790 .. container:: verbose
3791
3791
3792 Template:
3792 Template:
3793
3793
3794 The following keywords are supported in addition to the common template
3794 The following keywords are supported in addition to the common template
3795 keywords and functions. See also :hg:`help templates`.
3795 keywords and functions. See also :hg:`help templates`.
3796
3796
3797 :dirty: String. Character ``+`` denoting if the working directory has
3797 :dirty: String. Character ``+`` denoting if the working directory has
3798 uncommitted changes.
3798 uncommitted changes.
3799 :id: String. One or two nodes, optionally followed by ``+``.
3799 :id: String. One or two nodes, optionally followed by ``+``.
3800 :parents: List of strings. Parent nodes of the changeset.
3800 :parents: List of strings. Parent nodes of the changeset.
3801
3801
3802 Examples:
3802 Examples:
3803
3803
3804 - generate a build identifier for the working directory::
3804 - generate a build identifier for the working directory::
3805
3805
3806 hg id --id > build-id.dat
3806 hg id --id > build-id.dat
3807
3807
3808 - find the revision corresponding to a tag::
3808 - find the revision corresponding to a tag::
3809
3809
3810 hg id -n -r 1.3
3810 hg id -n -r 1.3
3811
3811
3812 - check the most recent revision of a remote repository::
3812 - check the most recent revision of a remote repository::
3813
3813
3814 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3814 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3815
3815
3816 See :hg:`log` for generating more information about specific revisions,
3816 See :hg:`log` for generating more information about specific revisions,
3817 including full hash identifiers.
3817 including full hash identifiers.
3818
3818
3819 Returns 0 if successful.
3819 Returns 0 if successful.
3820 """
3820 """
3821
3821
3822 opts = pycompat.byteskwargs(opts)
3822 opts = pycompat.byteskwargs(opts)
3823 if not repo and not source:
3823 if not repo and not source:
3824 raise error.InputError(
3824 raise error.InputError(
3825 _(b"there is no Mercurial repository here (.hg not found)")
3825 _(b"there is no Mercurial repository here (.hg not found)")
3826 )
3826 )
3827
3827
3828 default = not (num or id or branch or tags or bookmarks)
3828 default = not (num or id or branch or tags or bookmarks)
3829 output = []
3829 output = []
3830 revs = []
3830 revs = []
3831
3831
3832 peer = None
3832 peer = None
3833 try:
3833 try:
3834 if source:
3834 if source:
3835 source, branches = hg.parseurl(ui.expandpath(source))
3835 source, branches = hg.parseurl(ui.expandpath(source))
3836 # only pass ui when no repo
3836 # only pass ui when no repo
3837 peer = hg.peer(repo or ui, opts, source)
3837 peer = hg.peer(repo or ui, opts, source)
3838 repo = peer.local()
3838 repo = peer.local()
3839 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3839 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3840
3840
3841 fm = ui.formatter(b'identify', opts)
3841 fm = ui.formatter(b'identify', opts)
3842 fm.startitem()
3842 fm.startitem()
3843
3843
3844 if not repo:
3844 if not repo:
3845 if num or branch or tags:
3845 if num or branch or tags:
3846 raise error.InputError(
3846 raise error.InputError(
3847 _(b"can't query remote revision number, branch, or tags")
3847 _(b"can't query remote revision number, branch, or tags")
3848 )
3848 )
3849 if not rev and revs:
3849 if not rev and revs:
3850 rev = revs[0]
3850 rev = revs[0]
3851 if not rev:
3851 if not rev:
3852 rev = b"tip"
3852 rev = b"tip"
3853
3853
3854 remoterev = peer.lookup(rev)
3854 remoterev = peer.lookup(rev)
3855 hexrev = fm.hexfunc(remoterev)
3855 hexrev = fm.hexfunc(remoterev)
3856 if default or id:
3856 if default or id:
3857 output = [hexrev]
3857 output = [hexrev]
3858 fm.data(id=hexrev)
3858 fm.data(id=hexrev)
3859
3859
3860 @util.cachefunc
3860 @util.cachefunc
3861 def getbms():
3861 def getbms():
3862 bms = []
3862 bms = []
3863
3863
3864 if b'bookmarks' in peer.listkeys(b'namespaces'):
3864 if b'bookmarks' in peer.listkeys(b'namespaces'):
3865 hexremoterev = hex(remoterev)
3865 hexremoterev = hex(remoterev)
3866 bms = [
3866 bms = [
3867 bm
3867 bm
3868 for bm, bmr in pycompat.iteritems(
3868 for bm, bmr in pycompat.iteritems(
3869 peer.listkeys(b'bookmarks')
3869 peer.listkeys(b'bookmarks')
3870 )
3870 )
3871 if bmr == hexremoterev
3871 if bmr == hexremoterev
3872 ]
3872 ]
3873
3873
3874 return sorted(bms)
3874 return sorted(bms)
3875
3875
3876 if fm.isplain():
3876 if fm.isplain():
3877 if bookmarks:
3877 if bookmarks:
3878 output.extend(getbms())
3878 output.extend(getbms())
3879 elif default and not ui.quiet:
3879 elif default and not ui.quiet:
3880 # multiple bookmarks for a single parent separated by '/'
3880 # multiple bookmarks for a single parent separated by '/'
3881 bm = b'/'.join(getbms())
3881 bm = b'/'.join(getbms())
3882 if bm:
3882 if bm:
3883 output.append(bm)
3883 output.append(bm)
3884 else:
3884 else:
3885 fm.data(node=hex(remoterev))
3885 fm.data(node=hex(remoterev))
3886 if bookmarks or b'bookmarks' in fm.datahint():
3886 if bookmarks or b'bookmarks' in fm.datahint():
3887 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3887 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3888 else:
3888 else:
3889 if rev:
3889 if rev:
3890 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3890 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3891 ctx = scmutil.revsingle(repo, rev, None)
3891 ctx = scmutil.revsingle(repo, rev, None)
3892
3892
3893 if ctx.rev() is None:
3893 if ctx.rev() is None:
3894 ctx = repo[None]
3894 ctx = repo[None]
3895 parents = ctx.parents()
3895 parents = ctx.parents()
3896 taglist = []
3896 taglist = []
3897 for p in parents:
3897 for p in parents:
3898 taglist.extend(p.tags())
3898 taglist.extend(p.tags())
3899
3899
3900 dirty = b""
3900 dirty = b""
3901 if ctx.dirty(missing=True, merge=False, branch=False):
3901 if ctx.dirty(missing=True, merge=False, branch=False):
3902 dirty = b'+'
3902 dirty = b'+'
3903 fm.data(dirty=dirty)
3903 fm.data(dirty=dirty)
3904
3904
3905 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3905 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3906 if default or id:
3906 if default or id:
3907 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3907 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3908 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3908 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3909
3909
3910 if num:
3910 if num:
3911 numoutput = [b"%d" % p.rev() for p in parents]
3911 numoutput = [b"%d" % p.rev() for p in parents]
3912 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3912 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3913
3913
3914 fm.data(
3914 fm.data(
3915 parents=fm.formatlist(
3915 parents=fm.formatlist(
3916 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3916 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3917 )
3917 )
3918 )
3918 )
3919 else:
3919 else:
3920 hexoutput = fm.hexfunc(ctx.node())
3920 hexoutput = fm.hexfunc(ctx.node())
3921 if default or id:
3921 if default or id:
3922 output = [hexoutput]
3922 output = [hexoutput]
3923 fm.data(id=hexoutput)
3923 fm.data(id=hexoutput)
3924
3924
3925 if num:
3925 if num:
3926 output.append(pycompat.bytestr(ctx.rev()))
3926 output.append(pycompat.bytestr(ctx.rev()))
3927 taglist = ctx.tags()
3927 taglist = ctx.tags()
3928
3928
3929 if default and not ui.quiet:
3929 if default and not ui.quiet:
3930 b = ctx.branch()
3930 b = ctx.branch()
3931 if b != b'default':
3931 if b != b'default':
3932 output.append(b"(%s)" % b)
3932 output.append(b"(%s)" % b)
3933
3933
3934 # multiple tags for a single parent separated by '/'
3934 # multiple tags for a single parent separated by '/'
3935 t = b'/'.join(taglist)
3935 t = b'/'.join(taglist)
3936 if t:
3936 if t:
3937 output.append(t)
3937 output.append(t)
3938
3938
3939 # multiple bookmarks for a single parent separated by '/'
3939 # multiple bookmarks for a single parent separated by '/'
3940 bm = b'/'.join(ctx.bookmarks())
3940 bm = b'/'.join(ctx.bookmarks())
3941 if bm:
3941 if bm:
3942 output.append(bm)
3942 output.append(bm)
3943 else:
3943 else:
3944 if branch:
3944 if branch:
3945 output.append(ctx.branch())
3945 output.append(ctx.branch())
3946
3946
3947 if tags:
3947 if tags:
3948 output.extend(taglist)
3948 output.extend(taglist)
3949
3949
3950 if bookmarks:
3950 if bookmarks:
3951 output.extend(ctx.bookmarks())
3951 output.extend(ctx.bookmarks())
3952
3952
3953 fm.data(node=ctx.hex())
3953 fm.data(node=ctx.hex())
3954 fm.data(branch=ctx.branch())
3954 fm.data(branch=ctx.branch())
3955 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
3955 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
3956 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
3956 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
3957 fm.context(ctx=ctx)
3957 fm.context(ctx=ctx)
3958
3958
3959 fm.plain(b"%s\n" % b' '.join(output))
3959 fm.plain(b"%s\n" % b' '.join(output))
3960 fm.end()
3960 fm.end()
3961 finally:
3961 finally:
3962 if peer:
3962 if peer:
3963 peer.close()
3963 peer.close()
3964
3964
3965
3965
3966 @command(
3966 @command(
3967 b'import|patch',
3967 b'import|patch',
3968 [
3968 [
3969 (
3969 (
3970 b'p',
3970 b'p',
3971 b'strip',
3971 b'strip',
3972 1,
3972 1,
3973 _(
3973 _(
3974 b'directory strip option for patch. This has the same '
3974 b'directory strip option for patch. This has the same '
3975 b'meaning as the corresponding patch option'
3975 b'meaning as the corresponding patch option'
3976 ),
3976 ),
3977 _(b'NUM'),
3977 _(b'NUM'),
3978 ),
3978 ),
3979 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
3979 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
3980 (b'', b'secret', None, _(b'use the secret phase for committing')),
3980 (b'', b'secret', None, _(b'use the secret phase for committing')),
3981 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3981 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3982 (
3982 (
3983 b'f',
3983 b'f',
3984 b'force',
3984 b'force',
3985 None,
3985 None,
3986 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
3986 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
3987 ),
3987 ),
3988 (
3988 (
3989 b'',
3989 b'',
3990 b'no-commit',
3990 b'no-commit',
3991 None,
3991 None,
3992 _(b"don't commit, just update the working directory"),
3992 _(b"don't commit, just update the working directory"),
3993 ),
3993 ),
3994 (
3994 (
3995 b'',
3995 b'',
3996 b'bypass',
3996 b'bypass',
3997 None,
3997 None,
3998 _(b"apply patch without touching the working directory"),
3998 _(b"apply patch without touching the working directory"),
3999 ),
3999 ),
4000 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4000 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4001 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4001 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4002 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4002 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4003 (
4003 (
4004 b'',
4004 b'',
4005 b'import-branch',
4005 b'import-branch',
4006 None,
4006 None,
4007 _(b'use any branch information in patch (implied by --exact)'),
4007 _(b'use any branch information in patch (implied by --exact)'),
4008 ),
4008 ),
4009 ]
4009 ]
4010 + commitopts
4010 + commitopts
4011 + commitopts2
4011 + commitopts2
4012 + similarityopts,
4012 + similarityopts,
4013 _(b'[OPTION]... PATCH...'),
4013 _(b'[OPTION]... PATCH...'),
4014 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4014 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4015 )
4015 )
4016 def import_(ui, repo, patch1=None, *patches, **opts):
4016 def import_(ui, repo, patch1=None, *patches, **opts):
4017 """import an ordered set of patches
4017 """import an ordered set of patches
4018
4018
4019 Import a list of patches and commit them individually (unless
4019 Import a list of patches and commit them individually (unless
4020 --no-commit is specified).
4020 --no-commit is specified).
4021
4021
4022 To read a patch from standard input (stdin), use "-" as the patch
4022 To read a patch from standard input (stdin), use "-" as the patch
4023 name. If a URL is specified, the patch will be downloaded from
4023 name. If a URL is specified, the patch will be downloaded from
4024 there.
4024 there.
4025
4025
4026 Import first applies changes to the working directory (unless
4026 Import first applies changes to the working directory (unless
4027 --bypass is specified), import will abort if there are outstanding
4027 --bypass is specified), import will abort if there are outstanding
4028 changes.
4028 changes.
4029
4029
4030 Use --bypass to apply and commit patches directly to the
4030 Use --bypass to apply and commit patches directly to the
4031 repository, without affecting the working directory. Without
4031 repository, without affecting the working directory. Without
4032 --exact, patches will be applied on top of the working directory
4032 --exact, patches will be applied on top of the working directory
4033 parent revision.
4033 parent revision.
4034
4034
4035 You can import a patch straight from a mail message. Even patches
4035 You can import a patch straight from a mail message. Even patches
4036 as attachments work (to use the body part, it must have type
4036 as attachments work (to use the body part, it must have type
4037 text/plain or text/x-patch). From and Subject headers of email
4037 text/plain or text/x-patch). From and Subject headers of email
4038 message are used as default committer and commit message. All
4038 message are used as default committer and commit message. All
4039 text/plain body parts before first diff are added to the commit
4039 text/plain body parts before first diff are added to the commit
4040 message.
4040 message.
4041
4041
4042 If the imported patch was generated by :hg:`export`, user and
4042 If the imported patch was generated by :hg:`export`, user and
4043 description from patch override values from message headers and
4043 description from patch override values from message headers and
4044 body. Values given on command line with -m/--message and -u/--user
4044 body. Values given on command line with -m/--message and -u/--user
4045 override these.
4045 override these.
4046
4046
4047 If --exact is specified, import will set the working directory to
4047 If --exact is specified, import will set the working directory to
4048 the parent of each patch before applying it, and will abort if the
4048 the parent of each patch before applying it, and will abort if the
4049 resulting changeset has a different ID than the one recorded in
4049 resulting changeset has a different ID than the one recorded in
4050 the patch. This will guard against various ways that portable
4050 the patch. This will guard against various ways that portable
4051 patch formats and mail systems might fail to transfer Mercurial
4051 patch formats and mail systems might fail to transfer Mercurial
4052 data or metadata. See :hg:`bundle` for lossless transmission.
4052 data or metadata. See :hg:`bundle` for lossless transmission.
4053
4053
4054 Use --partial to ensure a changeset will be created from the patch
4054 Use --partial to ensure a changeset will be created from the patch
4055 even if some hunks fail to apply. Hunks that fail to apply will be
4055 even if some hunks fail to apply. Hunks that fail to apply will be
4056 written to a <target-file>.rej file. Conflicts can then be resolved
4056 written to a <target-file>.rej file. Conflicts can then be resolved
4057 by hand before :hg:`commit --amend` is run to update the created
4057 by hand before :hg:`commit --amend` is run to update the created
4058 changeset. This flag exists to let people import patches that
4058 changeset. This flag exists to let people import patches that
4059 partially apply without losing the associated metadata (author,
4059 partially apply without losing the associated metadata (author,
4060 date, description, ...).
4060 date, description, ...).
4061
4061
4062 .. note::
4062 .. note::
4063
4063
4064 When no hunks apply cleanly, :hg:`import --partial` will create
4064 When no hunks apply cleanly, :hg:`import --partial` will create
4065 an empty changeset, importing only the patch metadata.
4065 an empty changeset, importing only the patch metadata.
4066
4066
4067 With -s/--similarity, hg will attempt to discover renames and
4067 With -s/--similarity, hg will attempt to discover renames and
4068 copies in the patch in the same way as :hg:`addremove`.
4068 copies in the patch in the same way as :hg:`addremove`.
4069
4069
4070 It is possible to use external patch programs to perform the patch
4070 It is possible to use external patch programs to perform the patch
4071 by setting the ``ui.patch`` configuration option. For the default
4071 by setting the ``ui.patch`` configuration option. For the default
4072 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4072 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4073 See :hg:`help config` for more information about configuration
4073 See :hg:`help config` for more information about configuration
4074 files and how to use these options.
4074 files and how to use these options.
4075
4075
4076 See :hg:`help dates` for a list of formats valid for -d/--date.
4076 See :hg:`help dates` for a list of formats valid for -d/--date.
4077
4077
4078 .. container:: verbose
4078 .. container:: verbose
4079
4079
4080 Examples:
4080 Examples:
4081
4081
4082 - import a traditional patch from a website and detect renames::
4082 - import a traditional patch from a website and detect renames::
4083
4083
4084 hg import -s 80 http://example.com/bugfix.patch
4084 hg import -s 80 http://example.com/bugfix.patch
4085
4085
4086 - import a changeset from an hgweb server::
4086 - import a changeset from an hgweb server::
4087
4087
4088 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4088 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4089
4089
4090 - import all the patches in an Unix-style mbox::
4090 - import all the patches in an Unix-style mbox::
4091
4091
4092 hg import incoming-patches.mbox
4092 hg import incoming-patches.mbox
4093
4093
4094 - import patches from stdin::
4094 - import patches from stdin::
4095
4095
4096 hg import -
4096 hg import -
4097
4097
4098 - attempt to exactly restore an exported changeset (not always
4098 - attempt to exactly restore an exported changeset (not always
4099 possible)::
4099 possible)::
4100
4100
4101 hg import --exact proposed-fix.patch
4101 hg import --exact proposed-fix.patch
4102
4102
4103 - use an external tool to apply a patch which is too fuzzy for
4103 - use an external tool to apply a patch which is too fuzzy for
4104 the default internal tool.
4104 the default internal tool.
4105
4105
4106 hg import --config ui.patch="patch --merge" fuzzy.patch
4106 hg import --config ui.patch="patch --merge" fuzzy.patch
4107
4107
4108 - change the default fuzzing from 2 to a less strict 7
4108 - change the default fuzzing from 2 to a less strict 7
4109
4109
4110 hg import --config ui.fuzz=7 fuzz.patch
4110 hg import --config ui.fuzz=7 fuzz.patch
4111
4111
4112 Returns 0 on success, 1 on partial success (see --partial).
4112 Returns 0 on success, 1 on partial success (see --partial).
4113 """
4113 """
4114
4114
4115 cmdutil.check_incompatible_arguments(
4115 cmdutil.check_incompatible_arguments(
4116 opts, 'no_commit', ['bypass', 'secret']
4116 opts, 'no_commit', ['bypass', 'secret']
4117 )
4117 )
4118 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4118 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4119 opts = pycompat.byteskwargs(opts)
4119 opts = pycompat.byteskwargs(opts)
4120 if not patch1:
4120 if not patch1:
4121 raise error.InputError(_(b'need at least one patch to import'))
4121 raise error.InputError(_(b'need at least one patch to import'))
4122
4122
4123 patches = (patch1,) + patches
4123 patches = (patch1,) + patches
4124
4124
4125 date = opts.get(b'date')
4125 date = opts.get(b'date')
4126 if date:
4126 if date:
4127 opts[b'date'] = dateutil.parsedate(date)
4127 opts[b'date'] = dateutil.parsedate(date)
4128
4128
4129 exact = opts.get(b'exact')
4129 exact = opts.get(b'exact')
4130 update = not opts.get(b'bypass')
4130 update = not opts.get(b'bypass')
4131 try:
4131 try:
4132 sim = float(opts.get(b'similarity') or 0)
4132 sim = float(opts.get(b'similarity') or 0)
4133 except ValueError:
4133 except ValueError:
4134 raise error.InputError(_(b'similarity must be a number'))
4134 raise error.InputError(_(b'similarity must be a number'))
4135 if sim < 0 or sim > 100:
4135 if sim < 0 or sim > 100:
4136 raise error.InputError(_(b'similarity must be between 0 and 100'))
4136 raise error.InputError(_(b'similarity must be between 0 and 100'))
4137 if sim and not update:
4137 if sim and not update:
4138 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4138 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4139
4139
4140 base = opts[b"base"]
4140 base = opts[b"base"]
4141 msgs = []
4141 msgs = []
4142 ret = 0
4142 ret = 0
4143
4143
4144 with repo.wlock():
4144 with repo.wlock():
4145 if update:
4145 if update:
4146 cmdutil.checkunfinished(repo)
4146 cmdutil.checkunfinished(repo)
4147 if exact or not opts.get(b'force'):
4147 if exact or not opts.get(b'force'):
4148 cmdutil.bailifchanged(repo)
4148 cmdutil.bailifchanged(repo)
4149
4149
4150 if not opts.get(b'no_commit'):
4150 if not opts.get(b'no_commit'):
4151 lock = repo.lock
4151 lock = repo.lock
4152 tr = lambda: repo.transaction(b'import')
4152 tr = lambda: repo.transaction(b'import')
4153 dsguard = util.nullcontextmanager
4153 dsguard = util.nullcontextmanager
4154 else:
4154 else:
4155 lock = util.nullcontextmanager
4155 lock = util.nullcontextmanager
4156 tr = util.nullcontextmanager
4156 tr = util.nullcontextmanager
4157 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4157 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4158 with lock(), tr(), dsguard():
4158 with lock(), tr(), dsguard():
4159 parents = repo[None].parents()
4159 parents = repo[None].parents()
4160 for patchurl in patches:
4160 for patchurl in patches:
4161 if patchurl == b'-':
4161 if patchurl == b'-':
4162 ui.status(_(b'applying patch from stdin\n'))
4162 ui.status(_(b'applying patch from stdin\n'))
4163 patchfile = ui.fin
4163 patchfile = ui.fin
4164 patchurl = b'stdin' # for error message
4164 patchurl = b'stdin' # for error message
4165 else:
4165 else:
4166 patchurl = os.path.join(base, patchurl)
4166 patchurl = os.path.join(base, patchurl)
4167 ui.status(_(b'applying %s\n') % patchurl)
4167 ui.status(_(b'applying %s\n') % patchurl)
4168 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4168 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4169
4169
4170 haspatch = False
4170 haspatch = False
4171 for hunk in patch.split(patchfile):
4171 for hunk in patch.split(patchfile):
4172 with patch.extract(ui, hunk) as patchdata:
4172 with patch.extract(ui, hunk) as patchdata:
4173 msg, node, rej = cmdutil.tryimportone(
4173 msg, node, rej = cmdutil.tryimportone(
4174 ui, repo, patchdata, parents, opts, msgs, hg.clean
4174 ui, repo, patchdata, parents, opts, msgs, hg.clean
4175 )
4175 )
4176 if msg:
4176 if msg:
4177 haspatch = True
4177 haspatch = True
4178 ui.note(msg + b'\n')
4178 ui.note(msg + b'\n')
4179 if update or exact:
4179 if update or exact:
4180 parents = repo[None].parents()
4180 parents = repo[None].parents()
4181 else:
4181 else:
4182 parents = [repo[node]]
4182 parents = [repo[node]]
4183 if rej:
4183 if rej:
4184 ui.write_err(_(b"patch applied partially\n"))
4184 ui.write_err(_(b"patch applied partially\n"))
4185 ui.write_err(
4185 ui.write_err(
4186 _(
4186 _(
4187 b"(fix the .rej files and run "
4187 b"(fix the .rej files and run "
4188 b"`hg commit --amend`)\n"
4188 b"`hg commit --amend`)\n"
4189 )
4189 )
4190 )
4190 )
4191 ret = 1
4191 ret = 1
4192 break
4192 break
4193
4193
4194 if not haspatch:
4194 if not haspatch:
4195 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4195 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4196
4196
4197 if msgs:
4197 if msgs:
4198 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4198 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4199 return ret
4199 return ret
4200
4200
4201
4201
4202 @command(
4202 @command(
4203 b'incoming|in',
4203 b'incoming|in',
4204 [
4204 [
4205 (
4205 (
4206 b'f',
4206 b'f',
4207 b'force',
4207 b'force',
4208 None,
4208 None,
4209 _(b'run even if remote repository is unrelated'),
4209 _(b'run even if remote repository is unrelated'),
4210 ),
4210 ),
4211 (b'n', b'newest-first', None, _(b'show newest record first')),
4211 (b'n', b'newest-first', None, _(b'show newest record first')),
4212 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4212 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4213 (
4213 (
4214 b'r',
4214 b'r',
4215 b'rev',
4215 b'rev',
4216 [],
4216 [],
4217 _(b'a remote changeset intended to be added'),
4217 _(b'a remote changeset intended to be added'),
4218 _(b'REV'),
4218 _(b'REV'),
4219 ),
4219 ),
4220 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4220 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4221 (
4221 (
4222 b'b',
4222 b'b',
4223 b'branch',
4223 b'branch',
4224 [],
4224 [],
4225 _(b'a specific branch you would like to pull'),
4225 _(b'a specific branch you would like to pull'),
4226 _(b'BRANCH'),
4226 _(b'BRANCH'),
4227 ),
4227 ),
4228 ]
4228 ]
4229 + logopts
4229 + logopts
4230 + remoteopts
4230 + remoteopts
4231 + subrepoopts,
4231 + subrepoopts,
4232 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4232 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4233 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4233 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4234 )
4234 )
4235 def incoming(ui, repo, source=b"default", **opts):
4235 def incoming(ui, repo, source=b"default", **opts):
4236 """show new changesets found in source
4236 """show new changesets found in source
4237
4237
4238 Show new changesets found in the specified path/URL or the default
4238 Show new changesets found in the specified path/URL or the default
4239 pull location. These are the changesets that would have been pulled
4239 pull location. These are the changesets that would have been pulled
4240 by :hg:`pull` at the time you issued this command.
4240 by :hg:`pull` at the time you issued this command.
4241
4241
4242 See pull for valid source format details.
4242 See pull for valid source format details.
4243
4243
4244 .. container:: verbose
4244 .. container:: verbose
4245
4245
4246 With -B/--bookmarks, the result of bookmark comparison between
4246 With -B/--bookmarks, the result of bookmark comparison between
4247 local and remote repositories is displayed. With -v/--verbose,
4247 local and remote repositories is displayed. With -v/--verbose,
4248 status is also displayed for each bookmark like below::
4248 status is also displayed for each bookmark like below::
4249
4249
4250 BM1 01234567890a added
4250 BM1 01234567890a added
4251 BM2 1234567890ab advanced
4251 BM2 1234567890ab advanced
4252 BM3 234567890abc diverged
4252 BM3 234567890abc diverged
4253 BM4 34567890abcd changed
4253 BM4 34567890abcd changed
4254
4254
4255 The action taken locally when pulling depends on the
4255 The action taken locally when pulling depends on the
4256 status of each bookmark:
4256 status of each bookmark:
4257
4257
4258 :``added``: pull will create it
4258 :``added``: pull will create it
4259 :``advanced``: pull will update it
4259 :``advanced``: pull will update it
4260 :``diverged``: pull will create a divergent bookmark
4260 :``diverged``: pull will create a divergent bookmark
4261 :``changed``: result depends on remote changesets
4261 :``changed``: result depends on remote changesets
4262
4262
4263 From the point of view of pulling behavior, bookmark
4263 From the point of view of pulling behavior, bookmark
4264 existing only in the remote repository are treated as ``added``,
4264 existing only in the remote repository are treated as ``added``,
4265 even if it is in fact locally deleted.
4265 even if it is in fact locally deleted.
4266
4266
4267 .. container:: verbose
4267 .. container:: verbose
4268
4268
4269 For remote repository, using --bundle avoids downloading the
4269 For remote repository, using --bundle avoids downloading the
4270 changesets twice if the incoming is followed by a pull.
4270 changesets twice if the incoming is followed by a pull.
4271
4271
4272 Examples:
4272 Examples:
4273
4273
4274 - show incoming changes with patches and full description::
4274 - show incoming changes with patches and full description::
4275
4275
4276 hg incoming -vp
4276 hg incoming -vp
4277
4277
4278 - show incoming changes excluding merges, store a bundle::
4278 - show incoming changes excluding merges, store a bundle::
4279
4279
4280 hg in -vpM --bundle incoming.hg
4280 hg in -vpM --bundle incoming.hg
4281 hg pull incoming.hg
4281 hg pull incoming.hg
4282
4282
4283 - briefly list changes inside a bundle::
4283 - briefly list changes inside a bundle::
4284
4284
4285 hg in changes.hg -T "{desc|firstline}\\n"
4285 hg in changes.hg -T "{desc|firstline}\\n"
4286
4286
4287 Returns 0 if there are incoming changes, 1 otherwise.
4287 Returns 0 if there are incoming changes, 1 otherwise.
4288 """
4288 """
4289 opts = pycompat.byteskwargs(opts)
4289 opts = pycompat.byteskwargs(opts)
4290 if opts.get(b'graph'):
4290 if opts.get(b'graph'):
4291 logcmdutil.checkunsupportedgraphflags([], opts)
4291 logcmdutil.checkunsupportedgraphflags([], opts)
4292
4292
4293 def display(other, chlist, displayer):
4293 def display(other, chlist, displayer):
4294 revdag = logcmdutil.graphrevs(other, chlist, opts)
4294 revdag = logcmdutil.graphrevs(other, chlist, opts)
4295 logcmdutil.displaygraph(
4295 logcmdutil.displaygraph(
4296 ui, repo, revdag, displayer, graphmod.asciiedges
4296 ui, repo, revdag, displayer, graphmod.asciiedges
4297 )
4297 )
4298
4298
4299 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4299 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4300 return 0
4300 return 0
4301
4301
4302 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4302 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4303
4303
4304 if opts.get(b'bookmarks'):
4304 if opts.get(b'bookmarks'):
4305 source, branches = hg.parseurl(
4305 source, branches = hg.parseurl(
4306 ui.expandpath(source), opts.get(b'branch')
4306 ui.expandpath(source), opts.get(b'branch')
4307 )
4307 )
4308 other = hg.peer(repo, opts, source)
4308 other = hg.peer(repo, opts, source)
4309 try:
4309 try:
4310 if b'bookmarks' not in other.listkeys(b'namespaces'):
4310 if b'bookmarks' not in other.listkeys(b'namespaces'):
4311 ui.warn(_(b"remote doesn't support bookmarks\n"))
4311 ui.warn(_(b"remote doesn't support bookmarks\n"))
4312 return 0
4312 return 0
4313 ui.pager(b'incoming')
4313 ui.pager(b'incoming')
4314 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4314 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4315 return bookmarks.incoming(ui, repo, other)
4315 return bookmarks.incoming(ui, repo, other)
4316 finally:
4316 finally:
4317 other.close()
4317 other.close()
4318
4318
4319 repo._subtoppath = ui.expandpath(source)
4319 repo._subtoppath = ui.expandpath(source)
4320 try:
4320 try:
4321 return hg.incoming(ui, repo, source, opts)
4321 return hg.incoming(ui, repo, source, opts)
4322 finally:
4322 finally:
4323 del repo._subtoppath
4323 del repo._subtoppath
4324
4324
4325
4325
4326 @command(
4326 @command(
4327 b'init',
4327 b'init',
4328 remoteopts,
4328 remoteopts,
4329 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4329 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4330 helpcategory=command.CATEGORY_REPO_CREATION,
4330 helpcategory=command.CATEGORY_REPO_CREATION,
4331 helpbasic=True,
4331 helpbasic=True,
4332 norepo=True,
4332 norepo=True,
4333 )
4333 )
4334 def init(ui, dest=b".", **opts):
4334 def init(ui, dest=b".", **opts):
4335 """create a new repository in the given directory
4335 """create a new repository in the given directory
4336
4336
4337 Initialize a new repository in the given directory. If the given
4337 Initialize a new repository in the given directory. If the given
4338 directory does not exist, it will be created.
4338 directory does not exist, it will be created.
4339
4339
4340 If no directory is given, the current directory is used.
4340 If no directory is given, the current directory is used.
4341
4341
4342 It is possible to specify an ``ssh://`` URL as the destination.
4342 It is possible to specify an ``ssh://`` URL as the destination.
4343 See :hg:`help urls` for more information.
4343 See :hg:`help urls` for more information.
4344
4344
4345 Returns 0 on success.
4345 Returns 0 on success.
4346 """
4346 """
4347 opts = pycompat.byteskwargs(opts)
4347 opts = pycompat.byteskwargs(opts)
4348 peer = hg.peer(ui, opts, ui.expandpath(dest), create=True)
4348 peer = hg.peer(ui, opts, ui.expandpath(dest), create=True)
4349 peer.close()
4349 peer.close()
4350
4350
4351
4351
4352 @command(
4352 @command(
4353 b'locate',
4353 b'locate',
4354 [
4354 [
4355 (
4355 (
4356 b'r',
4356 b'r',
4357 b'rev',
4357 b'rev',
4358 b'',
4358 b'',
4359 _(b'search the repository as it is in REV'),
4359 _(b'search the repository as it is in REV'),
4360 _(b'REV'),
4360 _(b'REV'),
4361 ),
4361 ),
4362 (
4362 (
4363 b'0',
4363 b'0',
4364 b'print0',
4364 b'print0',
4365 None,
4365 None,
4366 _(b'end filenames with NUL, for use with xargs'),
4366 _(b'end filenames with NUL, for use with xargs'),
4367 ),
4367 ),
4368 (
4368 (
4369 b'f',
4369 b'f',
4370 b'fullpath',
4370 b'fullpath',
4371 None,
4371 None,
4372 _(b'print complete paths from the filesystem root'),
4372 _(b'print complete paths from the filesystem root'),
4373 ),
4373 ),
4374 ]
4374 ]
4375 + walkopts,
4375 + walkopts,
4376 _(b'[OPTION]... [PATTERN]...'),
4376 _(b'[OPTION]... [PATTERN]...'),
4377 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4377 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4378 )
4378 )
4379 def locate(ui, repo, *pats, **opts):
4379 def locate(ui, repo, *pats, **opts):
4380 """locate files matching specific patterns (DEPRECATED)
4380 """locate files matching specific patterns (DEPRECATED)
4381
4381
4382 Print files under Mercurial control in the working directory whose
4382 Print files under Mercurial control in the working directory whose
4383 names match the given patterns.
4383 names match the given patterns.
4384
4384
4385 By default, this command searches all directories in the working
4385 By default, this command searches all directories in the working
4386 directory. To search just the current directory and its
4386 directory. To search just the current directory and its
4387 subdirectories, use "--include .".
4387 subdirectories, use "--include .".
4388
4388
4389 If no patterns are given to match, this command prints the names
4389 If no patterns are given to match, this command prints the names
4390 of all files under Mercurial control in the working directory.
4390 of all files under Mercurial control in the working directory.
4391
4391
4392 If you want to feed the output of this command into the "xargs"
4392 If you want to feed the output of this command into the "xargs"
4393 command, use the -0 option to both this command and "xargs". This
4393 command, use the -0 option to both this command and "xargs". This
4394 will avoid the problem of "xargs" treating single filenames that
4394 will avoid the problem of "xargs" treating single filenames that
4395 contain whitespace as multiple filenames.
4395 contain whitespace as multiple filenames.
4396
4396
4397 See :hg:`help files` for a more versatile command.
4397 See :hg:`help files` for a more versatile command.
4398
4398
4399 Returns 0 if a match is found, 1 otherwise.
4399 Returns 0 if a match is found, 1 otherwise.
4400 """
4400 """
4401 opts = pycompat.byteskwargs(opts)
4401 opts = pycompat.byteskwargs(opts)
4402 if opts.get(b'print0'):
4402 if opts.get(b'print0'):
4403 end = b'\0'
4403 end = b'\0'
4404 else:
4404 else:
4405 end = b'\n'
4405 end = b'\n'
4406 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4406 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4407
4407
4408 ret = 1
4408 ret = 1
4409 m = scmutil.match(
4409 m = scmutil.match(
4410 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4410 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4411 )
4411 )
4412
4412
4413 ui.pager(b'locate')
4413 ui.pager(b'locate')
4414 if ctx.rev() is None:
4414 if ctx.rev() is None:
4415 # When run on the working copy, "locate" includes removed files, so
4415 # When run on the working copy, "locate" includes removed files, so
4416 # we get the list of files from the dirstate.
4416 # we get the list of files from the dirstate.
4417 filesgen = sorted(repo.dirstate.matches(m))
4417 filesgen = sorted(repo.dirstate.matches(m))
4418 else:
4418 else:
4419 filesgen = ctx.matches(m)
4419 filesgen = ctx.matches(m)
4420 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4420 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4421 for abs in filesgen:
4421 for abs in filesgen:
4422 if opts.get(b'fullpath'):
4422 if opts.get(b'fullpath'):
4423 ui.write(repo.wjoin(abs), end)
4423 ui.write(repo.wjoin(abs), end)
4424 else:
4424 else:
4425 ui.write(uipathfn(abs), end)
4425 ui.write(uipathfn(abs), end)
4426 ret = 0
4426 ret = 0
4427
4427
4428 return ret
4428 return ret
4429
4429
4430
4430
4431 @command(
4431 @command(
4432 b'log|history',
4432 b'log|history',
4433 [
4433 [
4434 (
4434 (
4435 b'f',
4435 b'f',
4436 b'follow',
4436 b'follow',
4437 None,
4437 None,
4438 _(
4438 _(
4439 b'follow changeset history, or file history across copies and renames'
4439 b'follow changeset history, or file history across copies and renames'
4440 ),
4440 ),
4441 ),
4441 ),
4442 (
4442 (
4443 b'',
4443 b'',
4444 b'follow-first',
4444 b'follow-first',
4445 None,
4445 None,
4446 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4446 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4447 ),
4447 ),
4448 (
4448 (
4449 b'd',
4449 b'd',
4450 b'date',
4450 b'date',
4451 b'',
4451 b'',
4452 _(b'show revisions matching date spec'),
4452 _(b'show revisions matching date spec'),
4453 _(b'DATE'),
4453 _(b'DATE'),
4454 ),
4454 ),
4455 (b'C', b'copies', None, _(b'show copied files')),
4455 (b'C', b'copies', None, _(b'show copied files')),
4456 (
4456 (
4457 b'k',
4457 b'k',
4458 b'keyword',
4458 b'keyword',
4459 [],
4459 [],
4460 _(b'do case-insensitive search for a given text'),
4460 _(b'do case-insensitive search for a given text'),
4461 _(b'TEXT'),
4461 _(b'TEXT'),
4462 ),
4462 ),
4463 (
4463 (
4464 b'r',
4464 b'r',
4465 b'rev',
4465 b'rev',
4466 [],
4466 [],
4467 _(b'revisions to select or follow from'),
4467 _(b'revisions to select or follow from'),
4468 _(b'REV'),
4468 _(b'REV'),
4469 ),
4469 ),
4470 (
4470 (
4471 b'L',
4471 b'L',
4472 b'line-range',
4472 b'line-range',
4473 [],
4473 [],
4474 _(b'follow line range of specified file (EXPERIMENTAL)'),
4474 _(b'follow line range of specified file (EXPERIMENTAL)'),
4475 _(b'FILE,RANGE'),
4475 _(b'FILE,RANGE'),
4476 ),
4476 ),
4477 (
4477 (
4478 b'',
4478 b'',
4479 b'removed',
4479 b'removed',
4480 None,
4480 None,
4481 _(b'include revisions where files were removed'),
4481 _(b'include revisions where files were removed'),
4482 ),
4482 ),
4483 (
4483 (
4484 b'm',
4484 b'm',
4485 b'only-merges',
4485 b'only-merges',
4486 None,
4486 None,
4487 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4487 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4488 ),
4488 ),
4489 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4489 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4490 (
4490 (
4491 b'',
4491 b'',
4492 b'only-branch',
4492 b'only-branch',
4493 [],
4493 [],
4494 _(
4494 _(
4495 b'show only changesets within the given named branch (DEPRECATED)'
4495 b'show only changesets within the given named branch (DEPRECATED)'
4496 ),
4496 ),
4497 _(b'BRANCH'),
4497 _(b'BRANCH'),
4498 ),
4498 ),
4499 (
4499 (
4500 b'b',
4500 b'b',
4501 b'branch',
4501 b'branch',
4502 [],
4502 [],
4503 _(b'show changesets within the given named branch'),
4503 _(b'show changesets within the given named branch'),
4504 _(b'BRANCH'),
4504 _(b'BRANCH'),
4505 ),
4505 ),
4506 (
4506 (
4507 b'B',
4507 b'B',
4508 b'bookmark',
4508 b'bookmark',
4509 [],
4509 [],
4510 _(b"show changesets within the given bookmark"),
4510 _(b"show changesets within the given bookmark"),
4511 _(b'BOOKMARK'),
4511 _(b'BOOKMARK'),
4512 ),
4512 ),
4513 (
4513 (
4514 b'P',
4514 b'P',
4515 b'prune',
4515 b'prune',
4516 [],
4516 [],
4517 _(b'do not display revision or any of its ancestors'),
4517 _(b'do not display revision or any of its ancestors'),
4518 _(b'REV'),
4518 _(b'REV'),
4519 ),
4519 ),
4520 ]
4520 ]
4521 + logopts
4521 + logopts
4522 + walkopts,
4522 + walkopts,
4523 _(b'[OPTION]... [FILE]'),
4523 _(b'[OPTION]... [FILE]'),
4524 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4524 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4525 helpbasic=True,
4525 helpbasic=True,
4526 inferrepo=True,
4526 inferrepo=True,
4527 intents={INTENT_READONLY},
4527 intents={INTENT_READONLY},
4528 )
4528 )
4529 def log(ui, repo, *pats, **opts):
4529 def log(ui, repo, *pats, **opts):
4530 """show revision history of entire repository or files
4530 """show revision history of entire repository or files
4531
4531
4532 Print the revision history of the specified files or the entire
4532 Print the revision history of the specified files or the entire
4533 project.
4533 project.
4534
4534
4535 If no revision range is specified, the default is ``tip:0`` unless
4535 If no revision range is specified, the default is ``tip:0`` unless
4536 --follow is set.
4536 --follow is set.
4537
4537
4538 File history is shown without following rename or copy history of
4538 File history is shown without following rename or copy history of
4539 files. Use -f/--follow with a filename to follow history across
4539 files. Use -f/--follow with a filename to follow history across
4540 renames and copies. --follow without a filename will only show
4540 renames and copies. --follow without a filename will only show
4541 ancestors of the starting revisions. The starting revisions can be
4541 ancestors of the starting revisions. The starting revisions can be
4542 specified by -r/--rev, which default to the working directory parent.
4542 specified by -r/--rev, which default to the working directory parent.
4543
4543
4544 By default this command prints revision number and changeset id,
4544 By default this command prints revision number and changeset id,
4545 tags, non-trivial parents, user, date and time, and a summary for
4545 tags, non-trivial parents, user, date and time, and a summary for
4546 each commit. When the -v/--verbose switch is used, the list of
4546 each commit. When the -v/--verbose switch is used, the list of
4547 changed files and full commit message are shown.
4547 changed files and full commit message are shown.
4548
4548
4549 With --graph the revisions are shown as an ASCII art DAG with the most
4549 With --graph the revisions are shown as an ASCII art DAG with the most
4550 recent changeset at the top.
4550 recent changeset at the top.
4551 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4551 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4552 involved in an unresolved merge conflict, '_' closes a branch,
4552 involved in an unresolved merge conflict, '_' closes a branch,
4553 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4553 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4554 changeset from the lines below is a parent of the 'o' merge on the same
4554 changeset from the lines below is a parent of the 'o' merge on the same
4555 line.
4555 line.
4556 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4556 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4557 of a '|' indicates one or more revisions in a path are omitted.
4557 of a '|' indicates one or more revisions in a path are omitted.
4558
4558
4559 .. container:: verbose
4559 .. container:: verbose
4560
4560
4561 Use -L/--line-range FILE,M:N options to follow the history of lines
4561 Use -L/--line-range FILE,M:N options to follow the history of lines
4562 from M to N in FILE. With -p/--patch only diff hunks affecting
4562 from M to N in FILE. With -p/--patch only diff hunks affecting
4563 specified line range will be shown. This option requires --follow;
4563 specified line range will be shown. This option requires --follow;
4564 it can be specified multiple times. Currently, this option is not
4564 it can be specified multiple times. Currently, this option is not
4565 compatible with --graph. This option is experimental.
4565 compatible with --graph. This option is experimental.
4566
4566
4567 .. note::
4567 .. note::
4568
4568
4569 :hg:`log --patch` may generate unexpected diff output for merge
4569 :hg:`log --patch` may generate unexpected diff output for merge
4570 changesets, as it will only compare the merge changeset against
4570 changesets, as it will only compare the merge changeset against
4571 its first parent. Also, only files different from BOTH parents
4571 its first parent. Also, only files different from BOTH parents
4572 will appear in files:.
4572 will appear in files:.
4573
4573
4574 .. note::
4574 .. note::
4575
4575
4576 For performance reasons, :hg:`log FILE` may omit duplicate changes
4576 For performance reasons, :hg:`log FILE` may omit duplicate changes
4577 made on branches and will not show removals or mode changes. To
4577 made on branches and will not show removals or mode changes. To
4578 see all such changes, use the --removed switch.
4578 see all such changes, use the --removed switch.
4579
4579
4580 .. container:: verbose
4580 .. container:: verbose
4581
4581
4582 .. note::
4582 .. note::
4583
4583
4584 The history resulting from -L/--line-range options depends on diff
4584 The history resulting from -L/--line-range options depends on diff
4585 options; for instance if white-spaces are ignored, respective changes
4585 options; for instance if white-spaces are ignored, respective changes
4586 with only white-spaces in specified line range will not be listed.
4586 with only white-spaces in specified line range will not be listed.
4587
4587
4588 .. container:: verbose
4588 .. container:: verbose
4589
4589
4590 Some examples:
4590 Some examples:
4591
4591
4592 - changesets with full descriptions and file lists::
4592 - changesets with full descriptions and file lists::
4593
4593
4594 hg log -v
4594 hg log -v
4595
4595
4596 - changesets ancestral to the working directory::
4596 - changesets ancestral to the working directory::
4597
4597
4598 hg log -f
4598 hg log -f
4599
4599
4600 - last 10 commits on the current branch::
4600 - last 10 commits on the current branch::
4601
4601
4602 hg log -l 10 -b .
4602 hg log -l 10 -b .
4603
4603
4604 - changesets showing all modifications of a file, including removals::
4604 - changesets showing all modifications of a file, including removals::
4605
4605
4606 hg log --removed file.c
4606 hg log --removed file.c
4607
4607
4608 - all changesets that touch a directory, with diffs, excluding merges::
4608 - all changesets that touch a directory, with diffs, excluding merges::
4609
4609
4610 hg log -Mp lib/
4610 hg log -Mp lib/
4611
4611
4612 - all revision numbers that match a keyword::
4612 - all revision numbers that match a keyword::
4613
4613
4614 hg log -k bug --template "{rev}\\n"
4614 hg log -k bug --template "{rev}\\n"
4615
4615
4616 - the full hash identifier of the working directory parent::
4616 - the full hash identifier of the working directory parent::
4617
4617
4618 hg log -r . --template "{node}\\n"
4618 hg log -r . --template "{node}\\n"
4619
4619
4620 - list available log templates::
4620 - list available log templates::
4621
4621
4622 hg log -T list
4622 hg log -T list
4623
4623
4624 - check if a given changeset is included in a tagged release::
4624 - check if a given changeset is included in a tagged release::
4625
4625
4626 hg log -r "a21ccf and ancestor(1.9)"
4626 hg log -r "a21ccf and ancestor(1.9)"
4627
4627
4628 - find all changesets by some user in a date range::
4628 - find all changesets by some user in a date range::
4629
4629
4630 hg log -k alice -d "may 2008 to jul 2008"
4630 hg log -k alice -d "may 2008 to jul 2008"
4631
4631
4632 - summary of all changesets after the last tag::
4632 - summary of all changesets after the last tag::
4633
4633
4634 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4634 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4635
4635
4636 - changesets touching lines 13 to 23 for file.c::
4636 - changesets touching lines 13 to 23 for file.c::
4637
4637
4638 hg log -L file.c,13:23
4638 hg log -L file.c,13:23
4639
4639
4640 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4640 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4641 main.c with patch::
4641 main.c with patch::
4642
4642
4643 hg log -L file.c,13:23 -L main.c,2:6 -p
4643 hg log -L file.c,13:23 -L main.c,2:6 -p
4644
4644
4645 See :hg:`help dates` for a list of formats valid for -d/--date.
4645 See :hg:`help dates` for a list of formats valid for -d/--date.
4646
4646
4647 See :hg:`help revisions` for more about specifying and ordering
4647 See :hg:`help revisions` for more about specifying and ordering
4648 revisions.
4648 revisions.
4649
4649
4650 See :hg:`help templates` for more about pre-packaged styles and
4650 See :hg:`help templates` for more about pre-packaged styles and
4651 specifying custom templates. The default template used by the log
4651 specifying custom templates. The default template used by the log
4652 command can be customized via the ``command-templates.log`` configuration
4652 command can be customized via the ``command-templates.log`` configuration
4653 setting.
4653 setting.
4654
4654
4655 Returns 0 on success.
4655 Returns 0 on success.
4656
4656
4657 """
4657 """
4658 opts = pycompat.byteskwargs(opts)
4658 opts = pycompat.byteskwargs(opts)
4659 linerange = opts.get(b'line_range')
4659 linerange = opts.get(b'line_range')
4660
4660
4661 if linerange and not opts.get(b'follow'):
4661 if linerange and not opts.get(b'follow'):
4662 raise error.InputError(_(b'--line-range requires --follow'))
4662 raise error.InputError(_(b'--line-range requires --follow'))
4663
4663
4664 if linerange and pats:
4664 if linerange and pats:
4665 # TODO: take pats as patterns with no line-range filter
4665 # TODO: take pats as patterns with no line-range filter
4666 raise error.InputError(
4666 raise error.InputError(
4667 _(b'FILE arguments are not compatible with --line-range option')
4667 _(b'FILE arguments are not compatible with --line-range option')
4668 )
4668 )
4669
4669
4670 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4670 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4671 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4671 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4672 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4672 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4673 if linerange:
4673 if linerange:
4674 # TODO: should follow file history from logcmdutil._initialrevs(),
4674 # TODO: should follow file history from logcmdutil._initialrevs(),
4675 # then filter the result by logcmdutil._makerevset() and --limit
4675 # then filter the result by logcmdutil._makerevset() and --limit
4676 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4676 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4677
4677
4678 getcopies = None
4678 getcopies = None
4679 if opts.get(b'copies'):
4679 if opts.get(b'copies'):
4680 endrev = None
4680 endrev = None
4681 if revs:
4681 if revs:
4682 endrev = revs.max() + 1
4682 endrev = revs.max() + 1
4683 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4683 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4684
4684
4685 ui.pager(b'log')
4685 ui.pager(b'log')
4686 displayer = logcmdutil.changesetdisplayer(
4686 displayer = logcmdutil.changesetdisplayer(
4687 ui, repo, opts, differ, buffered=True
4687 ui, repo, opts, differ, buffered=True
4688 )
4688 )
4689 if opts.get(b'graph'):
4689 if opts.get(b'graph'):
4690 displayfn = logcmdutil.displaygraphrevs
4690 displayfn = logcmdutil.displaygraphrevs
4691 else:
4691 else:
4692 displayfn = logcmdutil.displayrevs
4692 displayfn = logcmdutil.displayrevs
4693 displayfn(ui, repo, revs, displayer, getcopies)
4693 displayfn(ui, repo, revs, displayer, getcopies)
4694
4694
4695
4695
4696 @command(
4696 @command(
4697 b'manifest',
4697 b'manifest',
4698 [
4698 [
4699 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4699 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4700 (b'', b'all', False, _(b"list files from all revisions")),
4700 (b'', b'all', False, _(b"list files from all revisions")),
4701 ]
4701 ]
4702 + formatteropts,
4702 + formatteropts,
4703 _(b'[-r REV]'),
4703 _(b'[-r REV]'),
4704 helpcategory=command.CATEGORY_MAINTENANCE,
4704 helpcategory=command.CATEGORY_MAINTENANCE,
4705 intents={INTENT_READONLY},
4705 intents={INTENT_READONLY},
4706 )
4706 )
4707 def manifest(ui, repo, node=None, rev=None, **opts):
4707 def manifest(ui, repo, node=None, rev=None, **opts):
4708 """output the current or given revision of the project manifest
4708 """output the current or given revision of the project manifest
4709
4709
4710 Print a list of version controlled files for the given revision.
4710 Print a list of version controlled files for the given revision.
4711 If no revision is given, the first parent of the working directory
4711 If no revision is given, the first parent of the working directory
4712 is used, or the null revision if no revision is checked out.
4712 is used, or the null revision if no revision is checked out.
4713
4713
4714 With -v, print file permissions, symlink and executable bits.
4714 With -v, print file permissions, symlink and executable bits.
4715 With --debug, print file revision hashes.
4715 With --debug, print file revision hashes.
4716
4716
4717 If option --all is specified, the list of all files from all revisions
4717 If option --all is specified, the list of all files from all revisions
4718 is printed. This includes deleted and renamed files.
4718 is printed. This includes deleted and renamed files.
4719
4719
4720 Returns 0 on success.
4720 Returns 0 on success.
4721 """
4721 """
4722 opts = pycompat.byteskwargs(opts)
4722 opts = pycompat.byteskwargs(opts)
4723 fm = ui.formatter(b'manifest', opts)
4723 fm = ui.formatter(b'manifest', opts)
4724
4724
4725 if opts.get(b'all'):
4725 if opts.get(b'all'):
4726 if rev or node:
4726 if rev or node:
4727 raise error.InputError(_(b"can't specify a revision with --all"))
4727 raise error.InputError(_(b"can't specify a revision with --all"))
4728
4728
4729 res = set()
4729 res = set()
4730 for rev in repo:
4730 for rev in repo:
4731 ctx = repo[rev]
4731 ctx = repo[rev]
4732 res |= set(ctx.files())
4732 res |= set(ctx.files())
4733
4733
4734 ui.pager(b'manifest')
4734 ui.pager(b'manifest')
4735 for f in sorted(res):
4735 for f in sorted(res):
4736 fm.startitem()
4736 fm.startitem()
4737 fm.write(b"path", b'%s\n', f)
4737 fm.write(b"path", b'%s\n', f)
4738 fm.end()
4738 fm.end()
4739 return
4739 return
4740
4740
4741 if rev and node:
4741 if rev and node:
4742 raise error.InputError(_(b"please specify just one revision"))
4742 raise error.InputError(_(b"please specify just one revision"))
4743
4743
4744 if not node:
4744 if not node:
4745 node = rev
4745 node = rev
4746
4746
4747 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4747 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4748 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4748 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4749 if node:
4749 if node:
4750 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4750 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4751 ctx = scmutil.revsingle(repo, node)
4751 ctx = scmutil.revsingle(repo, node)
4752 mf = ctx.manifest()
4752 mf = ctx.manifest()
4753 ui.pager(b'manifest')
4753 ui.pager(b'manifest')
4754 for f in ctx:
4754 for f in ctx:
4755 fm.startitem()
4755 fm.startitem()
4756 fm.context(ctx=ctx)
4756 fm.context(ctx=ctx)
4757 fl = ctx[f].flags()
4757 fl = ctx[f].flags()
4758 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4758 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4759 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4759 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4760 fm.write(b'path', b'%s\n', f)
4760 fm.write(b'path', b'%s\n', f)
4761 fm.end()
4761 fm.end()
4762
4762
4763
4763
4764 @command(
4764 @command(
4765 b'merge',
4765 b'merge',
4766 [
4766 [
4767 (
4767 (
4768 b'f',
4768 b'f',
4769 b'force',
4769 b'force',
4770 None,
4770 None,
4771 _(b'force a merge including outstanding changes (DEPRECATED)'),
4771 _(b'force a merge including outstanding changes (DEPRECATED)'),
4772 ),
4772 ),
4773 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4773 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4774 (
4774 (
4775 b'P',
4775 b'P',
4776 b'preview',
4776 b'preview',
4777 None,
4777 None,
4778 _(b'review revisions to merge (no merge is performed)'),
4778 _(b'review revisions to merge (no merge is performed)'),
4779 ),
4779 ),
4780 (b'', b'abort', None, _(b'abort the ongoing merge')),
4780 (b'', b'abort', None, _(b'abort the ongoing merge')),
4781 ]
4781 ]
4782 + mergetoolopts,
4782 + mergetoolopts,
4783 _(b'[-P] [[-r] REV]'),
4783 _(b'[-P] [[-r] REV]'),
4784 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4784 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4785 helpbasic=True,
4785 helpbasic=True,
4786 )
4786 )
4787 def merge(ui, repo, node=None, **opts):
4787 def merge(ui, repo, node=None, **opts):
4788 """merge another revision into working directory
4788 """merge another revision into working directory
4789
4789
4790 The current working directory is updated with all changes made in
4790 The current working directory is updated with all changes made in
4791 the requested revision since the last common predecessor revision.
4791 the requested revision since the last common predecessor revision.
4792
4792
4793 Files that changed between either parent are marked as changed for
4793 Files that changed between either parent are marked as changed for
4794 the next commit and a commit must be performed before any further
4794 the next commit and a commit must be performed before any further
4795 updates to the repository are allowed. The next commit will have
4795 updates to the repository are allowed. The next commit will have
4796 two parents.
4796 two parents.
4797
4797
4798 ``--tool`` can be used to specify the merge tool used for file
4798 ``--tool`` can be used to specify the merge tool used for file
4799 merges. It overrides the HGMERGE environment variable and your
4799 merges. It overrides the HGMERGE environment variable and your
4800 configuration files. See :hg:`help merge-tools` for options.
4800 configuration files. See :hg:`help merge-tools` for options.
4801
4801
4802 If no revision is specified, the working directory's parent is a
4802 If no revision is specified, the working directory's parent is a
4803 head revision, and the current branch contains exactly one other
4803 head revision, and the current branch contains exactly one other
4804 head, the other head is merged with by default. Otherwise, an
4804 head, the other head is merged with by default. Otherwise, an
4805 explicit revision with which to merge must be provided.
4805 explicit revision with which to merge must be provided.
4806
4806
4807 See :hg:`help resolve` for information on handling file conflicts.
4807 See :hg:`help resolve` for information on handling file conflicts.
4808
4808
4809 To undo an uncommitted merge, use :hg:`merge --abort` which
4809 To undo an uncommitted merge, use :hg:`merge --abort` which
4810 will check out a clean copy of the original merge parent, losing
4810 will check out a clean copy of the original merge parent, losing
4811 all changes.
4811 all changes.
4812
4812
4813 Returns 0 on success, 1 if there are unresolved files.
4813 Returns 0 on success, 1 if there are unresolved files.
4814 """
4814 """
4815
4815
4816 opts = pycompat.byteskwargs(opts)
4816 opts = pycompat.byteskwargs(opts)
4817 abort = opts.get(b'abort')
4817 abort = opts.get(b'abort')
4818 if abort and repo.dirstate.p2() == nullid:
4818 if abort and repo.dirstate.p2() == nullid:
4819 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4819 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4820 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4820 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4821 if abort:
4821 if abort:
4822 state = cmdutil.getunfinishedstate(repo)
4822 state = cmdutil.getunfinishedstate(repo)
4823 if state and state._opname != b'merge':
4823 if state and state._opname != b'merge':
4824 raise error.StateError(
4824 raise error.StateError(
4825 _(b'cannot abort merge with %s in progress') % (state._opname),
4825 _(b'cannot abort merge with %s in progress') % (state._opname),
4826 hint=state.hint(),
4826 hint=state.hint(),
4827 )
4827 )
4828 if node:
4828 if node:
4829 raise error.InputError(_(b"cannot specify a node with --abort"))
4829 raise error.InputError(_(b"cannot specify a node with --abort"))
4830 return hg.abortmerge(repo.ui, repo)
4830 return hg.abortmerge(repo.ui, repo)
4831
4831
4832 if opts.get(b'rev') and node:
4832 if opts.get(b'rev') and node:
4833 raise error.InputError(_(b"please specify just one revision"))
4833 raise error.InputError(_(b"please specify just one revision"))
4834 if not node:
4834 if not node:
4835 node = opts.get(b'rev')
4835 node = opts.get(b'rev')
4836
4836
4837 if node:
4837 if node:
4838 ctx = scmutil.revsingle(repo, node)
4838 ctx = scmutil.revsingle(repo, node)
4839 else:
4839 else:
4840 if ui.configbool(b'commands', b'merge.require-rev'):
4840 if ui.configbool(b'commands', b'merge.require-rev'):
4841 raise error.InputError(
4841 raise error.InputError(
4842 _(
4842 _(
4843 b'configuration requires specifying revision to merge '
4843 b'configuration requires specifying revision to merge '
4844 b'with'
4844 b'with'
4845 )
4845 )
4846 )
4846 )
4847 ctx = repo[destutil.destmerge(repo)]
4847 ctx = repo[destutil.destmerge(repo)]
4848
4848
4849 if ctx.node() is None:
4849 if ctx.node() is None:
4850 raise error.InputError(
4850 raise error.InputError(
4851 _(b'merging with the working copy has no effect')
4851 _(b'merging with the working copy has no effect')
4852 )
4852 )
4853
4853
4854 if opts.get(b'preview'):
4854 if opts.get(b'preview'):
4855 # find nodes that are ancestors of p2 but not of p1
4855 # find nodes that are ancestors of p2 but not of p1
4856 p1 = repo[b'.'].node()
4856 p1 = repo[b'.'].node()
4857 p2 = ctx.node()
4857 p2 = ctx.node()
4858 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4858 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4859
4859
4860 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4860 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4861 for node in nodes:
4861 for node in nodes:
4862 displayer.show(repo[node])
4862 displayer.show(repo[node])
4863 displayer.close()
4863 displayer.close()
4864 return 0
4864 return 0
4865
4865
4866 # ui.forcemerge is an internal variable, do not document
4866 # ui.forcemerge is an internal variable, do not document
4867 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4867 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4868 with ui.configoverride(overrides, b'merge'):
4868 with ui.configoverride(overrides, b'merge'):
4869 force = opts.get(b'force')
4869 force = opts.get(b'force')
4870 labels = [b'working copy', b'merge rev']
4870 labels = [b'working copy', b'merge rev']
4871 return hg.merge(ctx, force=force, labels=labels)
4871 return hg.merge(ctx, force=force, labels=labels)
4872
4872
4873
4873
4874 statemod.addunfinished(
4874 statemod.addunfinished(
4875 b'merge',
4875 b'merge',
4876 fname=None,
4876 fname=None,
4877 clearable=True,
4877 clearable=True,
4878 allowcommit=True,
4878 allowcommit=True,
4879 cmdmsg=_(b'outstanding uncommitted merge'),
4879 cmdmsg=_(b'outstanding uncommitted merge'),
4880 abortfunc=hg.abortmerge,
4880 abortfunc=hg.abortmerge,
4881 statushint=_(
4881 statushint=_(
4882 b'To continue: hg commit\nTo abort: hg merge --abort'
4882 b'To continue: hg commit\nTo abort: hg merge --abort'
4883 ),
4883 ),
4884 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4884 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4885 )
4885 )
4886
4886
4887
4887
4888 @command(
4888 @command(
4889 b'outgoing|out',
4889 b'outgoing|out',
4890 [
4890 [
4891 (
4891 (
4892 b'f',
4892 b'f',
4893 b'force',
4893 b'force',
4894 None,
4894 None,
4895 _(b'run even when the destination is unrelated'),
4895 _(b'run even when the destination is unrelated'),
4896 ),
4896 ),
4897 (
4897 (
4898 b'r',
4898 b'r',
4899 b'rev',
4899 b'rev',
4900 [],
4900 [],
4901 _(b'a changeset intended to be included in the destination'),
4901 _(b'a changeset intended to be included in the destination'),
4902 _(b'REV'),
4902 _(b'REV'),
4903 ),
4903 ),
4904 (b'n', b'newest-first', None, _(b'show newest record first')),
4904 (b'n', b'newest-first', None, _(b'show newest record first')),
4905 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4905 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4906 (
4906 (
4907 b'b',
4907 b'b',
4908 b'branch',
4908 b'branch',
4909 [],
4909 [],
4910 _(b'a specific branch you would like to push'),
4910 _(b'a specific branch you would like to push'),
4911 _(b'BRANCH'),
4911 _(b'BRANCH'),
4912 ),
4912 ),
4913 ]
4913 ]
4914 + logopts
4914 + logopts
4915 + remoteopts
4915 + remoteopts
4916 + subrepoopts,
4916 + subrepoopts,
4917 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4917 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4918 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4918 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4919 )
4919 )
4920 def outgoing(ui, repo, dest=None, **opts):
4920 def outgoing(ui, repo, dest=None, **opts):
4921 """show changesets not found in the destination
4921 """show changesets not found in the destination
4922
4922
4923 Show changesets not found in the specified destination repository
4923 Show changesets not found in the specified destination repository
4924 or the default push location. These are the changesets that would
4924 or the default push location. These are the changesets that would
4925 be pushed if a push was requested.
4925 be pushed if a push was requested.
4926
4926
4927 See pull for details of valid destination formats.
4927 See pull for details of valid destination formats.
4928
4928
4929 .. container:: verbose
4929 .. container:: verbose
4930
4930
4931 With -B/--bookmarks, the result of bookmark comparison between
4931 With -B/--bookmarks, the result of bookmark comparison between
4932 local and remote repositories is displayed. With -v/--verbose,
4932 local and remote repositories is displayed. With -v/--verbose,
4933 status is also displayed for each bookmark like below::
4933 status is also displayed for each bookmark like below::
4934
4934
4935 BM1 01234567890a added
4935 BM1 01234567890a added
4936 BM2 deleted
4936 BM2 deleted
4937 BM3 234567890abc advanced
4937 BM3 234567890abc advanced
4938 BM4 34567890abcd diverged
4938 BM4 34567890abcd diverged
4939 BM5 4567890abcde changed
4939 BM5 4567890abcde changed
4940
4940
4941 The action taken when pushing depends on the
4941 The action taken when pushing depends on the
4942 status of each bookmark:
4942 status of each bookmark:
4943
4943
4944 :``added``: push with ``-B`` will create it
4944 :``added``: push with ``-B`` will create it
4945 :``deleted``: push with ``-B`` will delete it
4945 :``deleted``: push with ``-B`` will delete it
4946 :``advanced``: push will update it
4946 :``advanced``: push will update it
4947 :``diverged``: push with ``-B`` will update it
4947 :``diverged``: push with ``-B`` will update it
4948 :``changed``: push with ``-B`` will update it
4948 :``changed``: push with ``-B`` will update it
4949
4949
4950 From the point of view of pushing behavior, bookmarks
4950 From the point of view of pushing behavior, bookmarks
4951 existing only in the remote repository are treated as
4951 existing only in the remote repository are treated as
4952 ``deleted``, even if it is in fact added remotely.
4952 ``deleted``, even if it is in fact added remotely.
4953
4953
4954 Returns 0 if there are outgoing changes, 1 otherwise.
4954 Returns 0 if there are outgoing changes, 1 otherwise.
4955 """
4955 """
4956 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4956 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4957 # style URLs, so don't overwrite dest.
4957 # style URLs, so don't overwrite dest.
4958 path = ui.getpath(dest, default=(b'default-push', b'default'))
4958 path = ui.getpath(dest, default=(b'default-push', b'default'))
4959 if not path:
4959 if not path:
4960 raise error.ConfigError(
4960 raise error.ConfigError(
4961 _(b'default repository not configured!'),
4961 _(b'default repository not configured!'),
4962 hint=_(b"see 'hg help config.paths'"),
4962 hint=_(b"see 'hg help config.paths'"),
4963 )
4963 )
4964
4964
4965 opts = pycompat.byteskwargs(opts)
4965 opts = pycompat.byteskwargs(opts)
4966 if opts.get(b'graph'):
4966 if opts.get(b'graph'):
4967 logcmdutil.checkunsupportedgraphflags([], opts)
4967 logcmdutil.checkunsupportedgraphflags([], opts)
4968 o, other = hg._outgoing(ui, repo, dest, opts)
4968 o, other = hg._outgoing(ui, repo, dest, opts)
4969 if not o:
4969 if not o:
4970 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4970 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4971 return
4971 return
4972
4972
4973 revdag = logcmdutil.graphrevs(repo, o, opts)
4973 revdag = logcmdutil.graphrevs(repo, o, opts)
4974 ui.pager(b'outgoing')
4974 ui.pager(b'outgoing')
4975 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4975 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4976 logcmdutil.displaygraph(
4976 logcmdutil.displaygraph(
4977 ui, repo, revdag, displayer, graphmod.asciiedges
4977 ui, repo, revdag, displayer, graphmod.asciiedges
4978 )
4978 )
4979 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4979 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4980 return 0
4980 return 0
4981
4981
4982 if opts.get(b'bookmarks'):
4982 if opts.get(b'bookmarks'):
4983 dest = path.pushloc or path.loc
4983 dest = path.pushloc or path.loc
4984 other = hg.peer(repo, opts, dest)
4984 other = hg.peer(repo, opts, dest)
4985 try:
4985 try:
4986 if b'bookmarks' not in other.listkeys(b'namespaces'):
4986 if b'bookmarks' not in other.listkeys(b'namespaces'):
4987 ui.warn(_(b"remote doesn't support bookmarks\n"))
4987 ui.warn(_(b"remote doesn't support bookmarks\n"))
4988 return 0
4988 return 0
4989 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
4989 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
4990 ui.pager(b'outgoing')
4990 ui.pager(b'outgoing')
4991 return bookmarks.outgoing(ui, repo, other)
4991 return bookmarks.outgoing(ui, repo, other)
4992 finally:
4992 finally:
4993 other.close()
4993 other.close()
4994
4994
4995 repo._subtoppath = path.pushloc or path.loc
4995 repo._subtoppath = path.pushloc or path.loc
4996 try:
4996 try:
4997 return hg.outgoing(ui, repo, dest, opts)
4997 return hg.outgoing(ui, repo, dest, opts)
4998 finally:
4998 finally:
4999 del repo._subtoppath
4999 del repo._subtoppath
5000
5000
5001
5001
5002 @command(
5002 @command(
5003 b'parents',
5003 b'parents',
5004 [
5004 [
5005 (
5005 (
5006 b'r',
5006 b'r',
5007 b'rev',
5007 b'rev',
5008 b'',
5008 b'',
5009 _(b'show parents of the specified revision'),
5009 _(b'show parents of the specified revision'),
5010 _(b'REV'),
5010 _(b'REV'),
5011 ),
5011 ),
5012 ]
5012 ]
5013 + templateopts,
5013 + templateopts,
5014 _(b'[-r REV] [FILE]'),
5014 _(b'[-r REV] [FILE]'),
5015 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5015 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5016 inferrepo=True,
5016 inferrepo=True,
5017 )
5017 )
5018 def parents(ui, repo, file_=None, **opts):
5018 def parents(ui, repo, file_=None, **opts):
5019 """show the parents of the working directory or revision (DEPRECATED)
5019 """show the parents of the working directory or revision (DEPRECATED)
5020
5020
5021 Print the working directory's parent revisions. If a revision is
5021 Print the working directory's parent revisions. If a revision is
5022 given via -r/--rev, the parent of that revision will be printed.
5022 given via -r/--rev, the parent of that revision will be printed.
5023 If a file argument is given, the revision in which the file was
5023 If a file argument is given, the revision in which the file was
5024 last changed (before the working directory revision or the
5024 last changed (before the working directory revision or the
5025 argument to --rev if given) is printed.
5025 argument to --rev if given) is printed.
5026
5026
5027 This command is equivalent to::
5027 This command is equivalent to::
5028
5028
5029 hg log -r "p1()+p2()" or
5029 hg log -r "p1()+p2()" or
5030 hg log -r "p1(REV)+p2(REV)" or
5030 hg log -r "p1(REV)+p2(REV)" or
5031 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5031 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5032 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5032 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5033
5033
5034 See :hg:`summary` and :hg:`help revsets` for related information.
5034 See :hg:`summary` and :hg:`help revsets` for related information.
5035
5035
5036 Returns 0 on success.
5036 Returns 0 on success.
5037 """
5037 """
5038
5038
5039 opts = pycompat.byteskwargs(opts)
5039 opts = pycompat.byteskwargs(opts)
5040 rev = opts.get(b'rev')
5040 rev = opts.get(b'rev')
5041 if rev:
5041 if rev:
5042 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5042 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5043 ctx = scmutil.revsingle(repo, rev, None)
5043 ctx = scmutil.revsingle(repo, rev, None)
5044
5044
5045 if file_:
5045 if file_:
5046 m = scmutil.match(ctx, (file_,), opts)
5046 m = scmutil.match(ctx, (file_,), opts)
5047 if m.anypats() or len(m.files()) != 1:
5047 if m.anypats() or len(m.files()) != 1:
5048 raise error.InputError(_(b'can only specify an explicit filename'))
5048 raise error.InputError(_(b'can only specify an explicit filename'))
5049 file_ = m.files()[0]
5049 file_ = m.files()[0]
5050 filenodes = []
5050 filenodes = []
5051 for cp in ctx.parents():
5051 for cp in ctx.parents():
5052 if not cp:
5052 if not cp:
5053 continue
5053 continue
5054 try:
5054 try:
5055 filenodes.append(cp.filenode(file_))
5055 filenodes.append(cp.filenode(file_))
5056 except error.LookupError:
5056 except error.LookupError:
5057 pass
5057 pass
5058 if not filenodes:
5058 if not filenodes:
5059 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5059 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5060 p = []
5060 p = []
5061 for fn in filenodes:
5061 for fn in filenodes:
5062 fctx = repo.filectx(file_, fileid=fn)
5062 fctx = repo.filectx(file_, fileid=fn)
5063 p.append(fctx.node())
5063 p.append(fctx.node())
5064 else:
5064 else:
5065 p = [cp.node() for cp in ctx.parents()]
5065 p = [cp.node() for cp in ctx.parents()]
5066
5066
5067 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5067 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5068 for n in p:
5068 for n in p:
5069 if n != nullid:
5069 if n != nullid:
5070 displayer.show(repo[n])
5070 displayer.show(repo[n])
5071 displayer.close()
5071 displayer.close()
5072
5072
5073
5073
5074 @command(
5074 @command(
5075 b'paths',
5075 b'paths',
5076 formatteropts,
5076 formatteropts,
5077 _(b'[NAME]'),
5077 _(b'[NAME]'),
5078 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5078 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5079 optionalrepo=True,
5079 optionalrepo=True,
5080 intents={INTENT_READONLY},
5080 intents={INTENT_READONLY},
5081 )
5081 )
5082 def paths(ui, repo, search=None, **opts):
5082 def paths(ui, repo, search=None, **opts):
5083 """show aliases for remote repositories
5083 """show aliases for remote repositories
5084
5084
5085 Show definition of symbolic path name NAME. If no name is given,
5085 Show definition of symbolic path name NAME. If no name is given,
5086 show definition of all available names.
5086 show definition of all available names.
5087
5087
5088 Option -q/--quiet suppresses all output when searching for NAME
5088 Option -q/--quiet suppresses all output when searching for NAME
5089 and shows only the path names when listing all definitions.
5089 and shows only the path names when listing all definitions.
5090
5090
5091 Path names are defined in the [paths] section of your
5091 Path names are defined in the [paths] section of your
5092 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5092 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5093 repository, ``.hg/hgrc`` is used, too.
5093 repository, ``.hg/hgrc`` is used, too.
5094
5094
5095 The path names ``default`` and ``default-push`` have a special
5095 The path names ``default`` and ``default-push`` have a special
5096 meaning. When performing a push or pull operation, they are used
5096 meaning. When performing a push or pull operation, they are used
5097 as fallbacks if no location is specified on the command-line.
5097 as fallbacks if no location is specified on the command-line.
5098 When ``default-push`` is set, it will be used for push and
5098 When ``default-push`` is set, it will be used for push and
5099 ``default`` will be used for pull; otherwise ``default`` is used
5099 ``default`` will be used for pull; otherwise ``default`` is used
5100 as the fallback for both. When cloning a repository, the clone
5100 as the fallback for both. When cloning a repository, the clone
5101 source is written as ``default`` in ``.hg/hgrc``.
5101 source is written as ``default`` in ``.hg/hgrc``.
5102
5102
5103 .. note::
5103 .. note::
5104
5104
5105 ``default`` and ``default-push`` apply to all inbound (e.g.
5105 ``default`` and ``default-push`` apply to all inbound (e.g.
5106 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5106 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5107 and :hg:`bundle`) operations.
5107 and :hg:`bundle`) operations.
5108
5108
5109 See :hg:`help urls` for more information.
5109 See :hg:`help urls` for more information.
5110
5110
5111 .. container:: verbose
5111 .. container:: verbose
5112
5112
5113 Template:
5113 Template:
5114
5114
5115 The following keywords are supported. See also :hg:`help templates`.
5115 The following keywords are supported. See also :hg:`help templates`.
5116
5116
5117 :name: String. Symbolic name of the path alias.
5117 :name: String. Symbolic name of the path alias.
5118 :pushurl: String. URL for push operations.
5118 :pushurl: String. URL for push operations.
5119 :url: String. URL or directory path for the other operations.
5119 :url: String. URL or directory path for the other operations.
5120
5120
5121 Returns 0 on success.
5121 Returns 0 on success.
5122 """
5122 """
5123
5123
5124 opts = pycompat.byteskwargs(opts)
5124 opts = pycompat.byteskwargs(opts)
5125 ui.pager(b'paths')
5125 ui.pager(b'paths')
5126 if search:
5126 if search:
5127 pathitems = [
5127 pathitems = [
5128 (name, path)
5128 (name, path)
5129 for name, path in pycompat.iteritems(ui.paths)
5129 for name, path in pycompat.iteritems(ui.paths)
5130 if name == search
5130 if name == search
5131 ]
5131 ]
5132 else:
5132 else:
5133 pathitems = sorted(pycompat.iteritems(ui.paths))
5133 pathitems = sorted(pycompat.iteritems(ui.paths))
5134
5134
5135 fm = ui.formatter(b'paths', opts)
5135 fm = ui.formatter(b'paths', opts)
5136 if fm.isplain():
5136 if fm.isplain():
5137 hidepassword = util.hidepassword
5137 hidepassword = util.hidepassword
5138 else:
5138 else:
5139 hidepassword = bytes
5139 hidepassword = bytes
5140 if ui.quiet:
5140 if ui.quiet:
5141 namefmt = b'%s\n'
5141 namefmt = b'%s\n'
5142 else:
5142 else:
5143 namefmt = b'%s = '
5143 namefmt = b'%s = '
5144 showsubopts = not search and not ui.quiet
5144 showsubopts = not search and not ui.quiet
5145
5145
5146 for name, path in pathitems:
5146 for name, path in pathitems:
5147 fm.startitem()
5147 fm.startitem()
5148 fm.condwrite(not search, b'name', namefmt, name)
5148 fm.condwrite(not search, b'name', namefmt, name)
5149 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5149 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5150 for subopt, value in sorted(path.suboptions.items()):
5150 for subopt, value in sorted(path.suboptions.items()):
5151 assert subopt not in (b'name', b'url')
5151 assert subopt not in (b'name', b'url')
5152 if showsubopts:
5152 if showsubopts:
5153 fm.plain(b'%s:%s = ' % (name, subopt))
5153 fm.plain(b'%s:%s = ' % (name, subopt))
5154 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5154 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5155
5155
5156 fm.end()
5156 fm.end()
5157
5157
5158 if search and not pathitems:
5158 if search and not pathitems:
5159 if not ui.quiet:
5159 if not ui.quiet:
5160 ui.warn(_(b"not found!\n"))
5160 ui.warn(_(b"not found!\n"))
5161 return 1
5161 return 1
5162 else:
5162 else:
5163 return 0
5163 return 0
5164
5164
5165
5165
5166 @command(
5166 @command(
5167 b'phase',
5167 b'phase',
5168 [
5168 [
5169 (b'p', b'public', False, _(b'set changeset phase to public')),
5169 (b'p', b'public', False, _(b'set changeset phase to public')),
5170 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5170 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5171 (b's', b'secret', False, _(b'set changeset phase to secret')),
5171 (b's', b'secret', False, _(b'set changeset phase to secret')),
5172 (b'f', b'force', False, _(b'allow to move boundary backward')),
5172 (b'f', b'force', False, _(b'allow to move boundary backward')),
5173 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5173 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5174 ],
5174 ],
5175 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5175 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5176 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5176 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5177 )
5177 )
5178 def phase(ui, repo, *revs, **opts):
5178 def phase(ui, repo, *revs, **opts):
5179 """set or show the current phase name
5179 """set or show the current phase name
5180
5180
5181 With no argument, show the phase name of the current revision(s).
5181 With no argument, show the phase name of the current revision(s).
5182
5182
5183 With one of -p/--public, -d/--draft or -s/--secret, change the
5183 With one of -p/--public, -d/--draft or -s/--secret, change the
5184 phase value of the specified revisions.
5184 phase value of the specified revisions.
5185
5185
5186 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5186 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5187 lower phase to a higher phase. Phases are ordered as follows::
5187 lower phase to a higher phase. Phases are ordered as follows::
5188
5188
5189 public < draft < secret
5189 public < draft < secret
5190
5190
5191 Returns 0 on success, 1 if some phases could not be changed.
5191 Returns 0 on success, 1 if some phases could not be changed.
5192
5192
5193 (For more information about the phases concept, see :hg:`help phases`.)
5193 (For more information about the phases concept, see :hg:`help phases`.)
5194 """
5194 """
5195 opts = pycompat.byteskwargs(opts)
5195 opts = pycompat.byteskwargs(opts)
5196 # search for a unique phase argument
5196 # search for a unique phase argument
5197 targetphase = None
5197 targetphase = None
5198 for idx, name in enumerate(phases.cmdphasenames):
5198 for idx, name in enumerate(phases.cmdphasenames):
5199 if opts[name]:
5199 if opts[name]:
5200 if targetphase is not None:
5200 if targetphase is not None:
5201 raise error.InputError(_(b'only one phase can be specified'))
5201 raise error.InputError(_(b'only one phase can be specified'))
5202 targetphase = idx
5202 targetphase = idx
5203
5203
5204 # look for specified revision
5204 # look for specified revision
5205 revs = list(revs)
5205 revs = list(revs)
5206 revs.extend(opts[b'rev'])
5206 revs.extend(opts[b'rev'])
5207 if not revs:
5207 if not revs:
5208 # display both parents as the second parent phase can influence
5208 # display both parents as the second parent phase can influence
5209 # the phase of a merge commit
5209 # the phase of a merge commit
5210 revs = [c.rev() for c in repo[None].parents()]
5210 revs = [c.rev() for c in repo[None].parents()]
5211
5211
5212 revs = scmutil.revrange(repo, revs)
5212 revs = scmutil.revrange(repo, revs)
5213
5213
5214 ret = 0
5214 ret = 0
5215 if targetphase is None:
5215 if targetphase is None:
5216 # display
5216 # display
5217 for r in revs:
5217 for r in revs:
5218 ctx = repo[r]
5218 ctx = repo[r]
5219 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5219 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5220 else:
5220 else:
5221 with repo.lock(), repo.transaction(b"phase") as tr:
5221 with repo.lock(), repo.transaction(b"phase") as tr:
5222 # set phase
5222 # set phase
5223 if not revs:
5223 if not revs:
5224 raise error.InputError(_(b'empty revision set'))
5224 raise error.InputError(_(b'empty revision set'))
5225 nodes = [repo[r].node() for r in revs]
5225 nodes = [repo[r].node() for r in revs]
5226 # moving revision from public to draft may hide them
5226 # moving revision from public to draft may hide them
5227 # We have to check result on an unfiltered repository
5227 # We have to check result on an unfiltered repository
5228 unfi = repo.unfiltered()
5228 unfi = repo.unfiltered()
5229 getphase = unfi._phasecache.phase
5229 getphase = unfi._phasecache.phase
5230 olddata = [getphase(unfi, r) for r in unfi]
5230 olddata = [getphase(unfi, r) for r in unfi]
5231 phases.advanceboundary(repo, tr, targetphase, nodes)
5231 phases.advanceboundary(repo, tr, targetphase, nodes)
5232 if opts[b'force']:
5232 if opts[b'force']:
5233 phases.retractboundary(repo, tr, targetphase, nodes)
5233 phases.retractboundary(repo, tr, targetphase, nodes)
5234 getphase = unfi._phasecache.phase
5234 getphase = unfi._phasecache.phase
5235 newdata = [getphase(unfi, r) for r in unfi]
5235 newdata = [getphase(unfi, r) for r in unfi]
5236 changes = sum(newdata[r] != olddata[r] for r in unfi)
5236 changes = sum(newdata[r] != olddata[r] for r in unfi)
5237 cl = unfi.changelog
5237 cl = unfi.changelog
5238 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5238 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5239 if rejected:
5239 if rejected:
5240 ui.warn(
5240 ui.warn(
5241 _(
5241 _(
5242 b'cannot move %i changesets to a higher '
5242 b'cannot move %i changesets to a higher '
5243 b'phase, use --force\n'
5243 b'phase, use --force\n'
5244 )
5244 )
5245 % len(rejected)
5245 % len(rejected)
5246 )
5246 )
5247 ret = 1
5247 ret = 1
5248 if changes:
5248 if changes:
5249 msg = _(b'phase changed for %i changesets\n') % changes
5249 msg = _(b'phase changed for %i changesets\n') % changes
5250 if ret:
5250 if ret:
5251 ui.status(msg)
5251 ui.status(msg)
5252 else:
5252 else:
5253 ui.note(msg)
5253 ui.note(msg)
5254 else:
5254 else:
5255 ui.warn(_(b'no phases changed\n'))
5255 ui.warn(_(b'no phases changed\n'))
5256 return ret
5256 return ret
5257
5257
5258
5258
5259 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5259 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5260 """Run after a changegroup has been added via pull/unbundle
5260 """Run after a changegroup has been added via pull/unbundle
5261
5261
5262 This takes arguments below:
5262 This takes arguments below:
5263
5263
5264 :modheads: change of heads by pull/unbundle
5264 :modheads: change of heads by pull/unbundle
5265 :optupdate: updating working directory is needed or not
5265 :optupdate: updating working directory is needed or not
5266 :checkout: update destination revision (or None to default destination)
5266 :checkout: update destination revision (or None to default destination)
5267 :brev: a name, which might be a bookmark to be activated after updating
5267 :brev: a name, which might be a bookmark to be activated after updating
5268
5268
5269 return True if update raise any conflict, False otherwise.
5269 return True if update raise any conflict, False otherwise.
5270 """
5270 """
5271 if modheads == 0:
5271 if modheads == 0:
5272 return False
5272 return False
5273 if optupdate:
5273 if optupdate:
5274 try:
5274 try:
5275 return hg.updatetotally(ui, repo, checkout, brev)
5275 return hg.updatetotally(ui, repo, checkout, brev)
5276 except error.UpdateAbort as inst:
5276 except error.UpdateAbort as inst:
5277 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5277 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5278 hint = inst.hint
5278 hint = inst.hint
5279 raise error.UpdateAbort(msg, hint=hint)
5279 raise error.UpdateAbort(msg, hint=hint)
5280 if modheads is not None and modheads > 1:
5280 if modheads is not None and modheads > 1:
5281 currentbranchheads = len(repo.branchheads())
5281 currentbranchheads = len(repo.branchheads())
5282 if currentbranchheads == modheads:
5282 if currentbranchheads == modheads:
5283 ui.status(
5283 ui.status(
5284 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5284 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5285 )
5285 )
5286 elif currentbranchheads > 1:
5286 elif currentbranchheads > 1:
5287 ui.status(
5287 ui.status(
5288 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5288 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5289 )
5289 )
5290 else:
5290 else:
5291 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5291 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5292 elif not ui.configbool(b'commands', b'update.requiredest'):
5292 elif not ui.configbool(b'commands', b'update.requiredest'):
5293 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5293 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5294 return False
5294 return False
5295
5295
5296
5296
5297 @command(
5297 @command(
5298 b'pull',
5298 b'pull',
5299 [
5299 [
5300 (
5300 (
5301 b'u',
5301 b'u',
5302 b'update',
5302 b'update',
5303 None,
5303 None,
5304 _(b'update to new branch head if new descendants were pulled'),
5304 _(b'update to new branch head if new descendants were pulled'),
5305 ),
5305 ),
5306 (
5306 (
5307 b'f',
5307 b'f',
5308 b'force',
5308 b'force',
5309 None,
5309 None,
5310 _(b'run even when remote repository is unrelated'),
5310 _(b'run even when remote repository is unrelated'),
5311 ),
5311 ),
5312 (
5312 (
5313 b'',
5313 b'',
5314 b'confirm',
5314 b'confirm',
5315 None,
5315 None,
5316 _(b'confirm pull before applying changes'),
5316 _(b'confirm pull before applying changes'),
5317 ),
5317 ),
5318 (
5318 (
5319 b'r',
5319 b'r',
5320 b'rev',
5320 b'rev',
5321 [],
5321 [],
5322 _(b'a remote changeset intended to be added'),
5322 _(b'a remote changeset intended to be added'),
5323 _(b'REV'),
5323 _(b'REV'),
5324 ),
5324 ),
5325 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5325 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5326 (
5326 (
5327 b'b',
5327 b'b',
5328 b'branch',
5328 b'branch',
5329 [],
5329 [],
5330 _(b'a specific branch you would like to pull'),
5330 _(b'a specific branch you would like to pull'),
5331 _(b'BRANCH'),
5331 _(b'BRANCH'),
5332 ),
5332 ),
5333 ]
5333 ]
5334 + remoteopts,
5334 + remoteopts,
5335 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]...'),
5335 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]...'),
5336 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5336 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5337 helpbasic=True,
5337 helpbasic=True,
5338 )
5338 )
5339 def pull(ui, repo, *sources, **opts):
5339 def pull(ui, repo, *sources, **opts):
5340 """pull changes from the specified source
5340 """pull changes from the specified source
5341
5341
5342 Pull changes from a remote repository to a local one.
5342 Pull changes from a remote repository to a local one.
5343
5343
5344 This finds all changes from the repository at the specified path
5344 This finds all changes from the repository at the specified path
5345 or URL and adds them to a local repository (the current one unless
5345 or URL and adds them to a local repository (the current one unless
5346 -R is specified). By default, this does not update the copy of the
5346 -R is specified). By default, this does not update the copy of the
5347 project in the working directory.
5347 project in the working directory.
5348
5348
5349 When cloning from servers that support it, Mercurial may fetch
5349 When cloning from servers that support it, Mercurial may fetch
5350 pre-generated data. When this is done, hooks operating on incoming
5350 pre-generated data. When this is done, hooks operating on incoming
5351 changesets and changegroups may fire more than once, once for each
5351 changesets and changegroups may fire more than once, once for each
5352 pre-generated bundle and as well as for any additional remaining
5352 pre-generated bundle and as well as for any additional remaining
5353 data. See :hg:`help -e clonebundles` for more.
5353 data. See :hg:`help -e clonebundles` for more.
5354
5354
5355 Use :hg:`incoming` if you want to see what would have been added
5355 Use :hg:`incoming` if you want to see what would have been added
5356 by a pull at the time you issued this command. If you then decide
5356 by a pull at the time you issued this command. If you then decide
5357 to add those changes to the repository, you should use :hg:`pull
5357 to add those changes to the repository, you should use :hg:`pull
5358 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5358 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5359
5359
5360 If SOURCE is omitted, the 'default' path will be used.
5360 If SOURCE is omitted, the 'default' path will be used.
5361 See :hg:`help urls` for more information.
5361 See :hg:`help urls` for more information.
5362
5362
5363 If multiple sources are specified, they will be pulled sequentially as if
5363 If multiple sources are specified, they will be pulled sequentially as if
5364 the command was run multiple time. If --update is specify and the command
5364 the command was run multiple time. If --update is specify and the command
5365 will stop at the first failed --update.
5365 will stop at the first failed --update.
5366
5366
5367 Specifying bookmark as ``.`` is equivalent to specifying the active
5367 Specifying bookmark as ``.`` is equivalent to specifying the active
5368 bookmark's name.
5368 bookmark's name.
5369
5369
5370 Returns 0 on success, 1 if an update had unresolved files.
5370 Returns 0 on success, 1 if an update had unresolved files.
5371 """
5371 """
5372
5372
5373 opts = pycompat.byteskwargs(opts)
5373 opts = pycompat.byteskwargs(opts)
5374 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5374 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5375 b'update'
5375 b'update'
5376 ):
5376 ):
5377 msg = _(b'update destination required by configuration')
5377 msg = _(b'update destination required by configuration')
5378 hint = _(b'use hg pull followed by hg update DEST')
5378 hint = _(b'use hg pull followed by hg update DEST')
5379 raise error.InputError(msg, hint=hint)
5379 raise error.InputError(msg, hint=hint)
5380
5380
5381 if not sources:
5381 if not sources:
5382 sources = [b'default']
5382 sources = [b'default']
5383 for source in sources:
5383 for source in sources:
5384 source, branches = hg.parseurl(
5384 source, branches = hg.parseurl(
5385 ui.expandpath(source), opts.get(b'branch')
5385 ui.expandpath(source), opts.get(b'branch')
5386 )
5386 )
5387 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5387 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5388 ui.flush()
5388 ui.flush()
5389 other = hg.peer(repo, opts, source)
5389 other = hg.peer(repo, opts, source)
5390 update_conflict = None
5390 update_conflict = None
5391 try:
5391 try:
5392 revs, checkout = hg.addbranchrevs(
5392 revs, checkout = hg.addbranchrevs(
5393 repo, other, branches, opts.get(b'rev')
5393 repo, other, branches, opts.get(b'rev')
5394 )
5394 )
5395
5395
5396 pullopargs = {}
5396 pullopargs = {}
5397
5397
5398 nodes = None
5398 nodes = None
5399 if opts.get(b'bookmark') or revs:
5399 if opts.get(b'bookmark') or revs:
5400 # The list of bookmark used here is the same used to actually update
5400 # The list of bookmark used here is the same used to actually update
5401 # the bookmark names, to avoid the race from issue 4689 and we do
5401 # the bookmark names, to avoid the race from issue 4689 and we do
5402 # all lookup and bookmark queries in one go so they see the same
5402 # all lookup and bookmark queries in one go so they see the same
5403 # version of the server state (issue 4700).
5403 # version of the server state (issue 4700).
5404 nodes = []
5404 nodes = []
5405 fnodes = []
5405 fnodes = []
5406 revs = revs or []
5406 revs = revs or []
5407 if revs and not other.capable(b'lookup'):
5407 if revs and not other.capable(b'lookup'):
5408 err = _(
5408 err = _(
5409 b"other repository doesn't support revision lookup, "
5409 b"other repository doesn't support revision lookup, "
5410 b"so a rev cannot be specified."
5410 b"so a rev cannot be specified."
5411 )
5411 )
5412 raise error.Abort(err)
5412 raise error.Abort(err)
5413 with other.commandexecutor() as e:
5413 with other.commandexecutor() as e:
5414 fremotebookmarks = e.callcommand(
5414 fremotebookmarks = e.callcommand(
5415 b'listkeys', {b'namespace': b'bookmarks'}
5415 b'listkeys', {b'namespace': b'bookmarks'}
5416 )
5416 )
5417 for r in revs:
5417 for r in revs:
5418 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5418 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5419 remotebookmarks = fremotebookmarks.result()
5419 remotebookmarks = fremotebookmarks.result()
5420 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5420 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5421 pullopargs[b'remotebookmarks'] = remotebookmarks
5421 pullopargs[b'remotebookmarks'] = remotebookmarks
5422 for b in opts.get(b'bookmark', []):
5422 for b in opts.get(b'bookmark', []):
5423 b = repo._bookmarks.expandname(b)
5423 b = repo._bookmarks.expandname(b)
5424 if b not in remotebookmarks:
5424 if b not in remotebookmarks:
5425 raise error.InputError(
5425 raise error.InputError(
5426 _(b'remote bookmark %s not found!') % b
5426 _(b'remote bookmark %s not found!') % b
5427 )
5427 )
5428 nodes.append(remotebookmarks[b])
5428 nodes.append(remotebookmarks[b])
5429 for i, rev in enumerate(revs):
5429 for i, rev in enumerate(revs):
5430 node = fnodes[i].result()
5430 node = fnodes[i].result()
5431 nodes.append(node)
5431 nodes.append(node)
5432 if rev == checkout:
5432 if rev == checkout:
5433 checkout = node
5433 checkout = node
5434
5434
5435 wlock = util.nullcontextmanager()
5435 wlock = util.nullcontextmanager()
5436 if opts.get(b'update'):
5436 if opts.get(b'update'):
5437 wlock = repo.wlock()
5437 wlock = repo.wlock()
5438 with wlock:
5438 with wlock:
5439 pullopargs.update(opts.get(b'opargs', {}))
5439 pullopargs.update(opts.get(b'opargs', {}))
5440 modheads = exchange.pull(
5440 modheads = exchange.pull(
5441 repo,
5441 repo,
5442 other,
5442 other,
5443 heads=nodes,
5443 heads=nodes,
5444 force=opts.get(b'force'),
5444 force=opts.get(b'force'),
5445 bookmarks=opts.get(b'bookmark', ()),
5445 bookmarks=opts.get(b'bookmark', ()),
5446 opargs=pullopargs,
5446 opargs=pullopargs,
5447 confirm=opts.get(b'confirm'),
5447 confirm=opts.get(b'confirm'),
5448 ).cgresult
5448 ).cgresult
5449
5449
5450 # brev is a name, which might be a bookmark to be activated at
5450 # brev is a name, which might be a bookmark to be activated at
5451 # the end of the update. In other words, it is an explicit
5451 # the end of the update. In other words, it is an explicit
5452 # destination of the update
5452 # destination of the update
5453 brev = None
5453 brev = None
5454
5454
5455 if checkout:
5455 if checkout:
5456 checkout = repo.unfiltered().changelog.rev(checkout)
5456 checkout = repo.unfiltered().changelog.rev(checkout)
5457
5457
5458 # order below depends on implementation of
5458 # order below depends on implementation of
5459 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5459 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5460 # because 'checkout' is determined without it.
5460 # because 'checkout' is determined without it.
5461 if opts.get(b'rev'):
5461 if opts.get(b'rev'):
5462 brev = opts[b'rev'][0]
5462 brev = opts[b'rev'][0]
5463 elif opts.get(b'branch'):
5463 elif opts.get(b'branch'):
5464 brev = opts[b'branch'][0]
5464 brev = opts[b'branch'][0]
5465 else:
5465 else:
5466 brev = branches[0]
5466 brev = branches[0]
5467 repo._subtoppath = source
5467 repo._subtoppath = source
5468 try:
5468 try:
5469 update_conflict = postincoming(
5469 update_conflict = postincoming(
5470 ui, repo, modheads, opts.get(b'update'), checkout, brev
5470 ui, repo, modheads, opts.get(b'update'), checkout, brev
5471 )
5471 )
5472 except error.FilteredRepoLookupError as exc:
5472 except error.FilteredRepoLookupError as exc:
5473 msg = _(b'cannot update to target: %s') % exc.args[0]
5473 msg = _(b'cannot update to target: %s') % exc.args[0]
5474 exc.args = (msg,) + exc.args[1:]
5474 exc.args = (msg,) + exc.args[1:]
5475 raise
5475 raise
5476 finally:
5476 finally:
5477 del repo._subtoppath
5477 del repo._subtoppath
5478
5478
5479 finally:
5479 finally:
5480 other.close()
5480 other.close()
5481 # skip the remaining pull source if they are some conflict.
5481 # skip the remaining pull source if they are some conflict.
5482 if update_conflict:
5482 if update_conflict:
5483 break
5483 break
5484 if update_conflict:
5484 if update_conflict:
5485 return 1
5485 return 1
5486 else:
5486 else:
5487 return 0
5487 return 0
5488
5488
5489
5489
5490 @command(
5490 @command(
5491 b'purge|clean',
5491 b'purge|clean',
5492 [
5492 [
5493 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5493 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5494 (b'', b'all', None, _(b'purge ignored files too')),
5494 (b'', b'all', None, _(b'purge ignored files too')),
5495 (b'i', b'ignored', None, _(b'purge only ignored files')),
5495 (b'i', b'ignored', None, _(b'purge only ignored files')),
5496 (b'', b'dirs', None, _(b'purge empty directories')),
5496 (b'', b'dirs', None, _(b'purge empty directories')),
5497 (b'', b'files', None, _(b'purge files')),
5497 (b'', b'files', None, _(b'purge files')),
5498 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5498 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5499 (
5499 (
5500 b'0',
5500 b'0',
5501 b'print0',
5501 b'print0',
5502 None,
5502 None,
5503 _(
5503 _(
5504 b'end filenames with NUL, for use with xargs'
5504 b'end filenames with NUL, for use with xargs'
5505 b' (implies -p/--print)'
5505 b' (implies -p/--print)'
5506 ),
5506 ),
5507 ),
5507 ),
5508 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5508 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5509 ]
5509 ]
5510 + cmdutil.walkopts,
5510 + cmdutil.walkopts,
5511 _(b'hg purge [OPTION]... [DIR]...'),
5511 _(b'hg purge [OPTION]... [DIR]...'),
5512 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5512 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5513 )
5513 )
5514 def purge(ui, repo, *dirs, **opts):
5514 def purge(ui, repo, *dirs, **opts):
5515 """removes files not tracked by Mercurial
5515 """removes files not tracked by Mercurial
5516
5516
5517 Delete files not known to Mercurial. This is useful to test local
5517 Delete files not known to Mercurial. This is useful to test local
5518 and uncommitted changes in an otherwise-clean source tree.
5518 and uncommitted changes in an otherwise-clean source tree.
5519
5519
5520 This means that purge will delete the following by default:
5520 This means that purge will delete the following by default:
5521
5521
5522 - Unknown files: files marked with "?" by :hg:`status`
5522 - Unknown files: files marked with "?" by :hg:`status`
5523 - Empty directories: in fact Mercurial ignores directories unless
5523 - Empty directories: in fact Mercurial ignores directories unless
5524 they contain files under source control management
5524 they contain files under source control management
5525
5525
5526 But it will leave untouched:
5526 But it will leave untouched:
5527
5527
5528 - Modified and unmodified tracked files
5528 - Modified and unmodified tracked files
5529 - Ignored files (unless -i or --all is specified)
5529 - Ignored files (unless -i or --all is specified)
5530 - New files added to the repository (with :hg:`add`)
5530 - New files added to the repository (with :hg:`add`)
5531
5531
5532 The --files and --dirs options can be used to direct purge to delete
5532 The --files and --dirs options can be used to direct purge to delete
5533 only files, only directories, or both. If neither option is given,
5533 only files, only directories, or both. If neither option is given,
5534 both will be deleted.
5534 both will be deleted.
5535
5535
5536 If directories are given on the command line, only files in these
5536 If directories are given on the command line, only files in these
5537 directories are considered.
5537 directories are considered.
5538
5538
5539 Be careful with purge, as you could irreversibly delete some files
5539 Be careful with purge, as you could irreversibly delete some files
5540 you forgot to add to the repository. If you only want to print the
5540 you forgot to add to the repository. If you only want to print the
5541 list of files that this program would delete, use the --print
5541 list of files that this program would delete, use the --print
5542 option.
5542 option.
5543 """
5543 """
5544 opts = pycompat.byteskwargs(opts)
5544 opts = pycompat.byteskwargs(opts)
5545 cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
5545 cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
5546
5546
5547 act = not opts.get(b'print')
5547 act = not opts.get(b'print')
5548 eol = b'\n'
5548 eol = b'\n'
5549 if opts.get(b'print0'):
5549 if opts.get(b'print0'):
5550 eol = b'\0'
5550 eol = b'\0'
5551 act = False # --print0 implies --print
5551 act = False # --print0 implies --print
5552 if opts.get(b'all', False):
5552 if opts.get(b'all', False):
5553 ignored = True
5553 ignored = True
5554 unknown = True
5554 unknown = True
5555 else:
5555 else:
5556 ignored = opts.get(b'ignored', False)
5556 ignored = opts.get(b'ignored', False)
5557 unknown = not ignored
5557 unknown = not ignored
5558
5558
5559 removefiles = opts.get(b'files')
5559 removefiles = opts.get(b'files')
5560 removedirs = opts.get(b'dirs')
5560 removedirs = opts.get(b'dirs')
5561 confirm = opts.get(b'confirm')
5561 confirm = opts.get(b'confirm')
5562 if confirm is None:
5562 if confirm is None:
5563 try:
5563 try:
5564 extensions.find(b'purge')
5564 extensions.find(b'purge')
5565 confirm = False
5565 confirm = False
5566 except KeyError:
5566 except KeyError:
5567 confirm = True
5567 confirm = True
5568
5568
5569 if not removefiles and not removedirs:
5569 if not removefiles and not removedirs:
5570 removefiles = True
5570 removefiles = True
5571 removedirs = True
5571 removedirs = True
5572
5572
5573 match = scmutil.match(repo[None], dirs, opts)
5573 match = scmutil.match(repo[None], dirs, opts)
5574
5574
5575 paths = mergemod.purge(
5575 paths = mergemod.purge(
5576 repo,
5576 repo,
5577 match,
5577 match,
5578 unknown=unknown,
5578 unknown=unknown,
5579 ignored=ignored,
5579 ignored=ignored,
5580 removeemptydirs=removedirs,
5580 removeemptydirs=removedirs,
5581 removefiles=removefiles,
5581 removefiles=removefiles,
5582 abortonerror=opts.get(b'abort_on_err'),
5582 abortonerror=opts.get(b'abort_on_err'),
5583 noop=not act,
5583 noop=not act,
5584 confirm=confirm,
5584 confirm=confirm,
5585 )
5585 )
5586
5586
5587 for path in paths:
5587 for path in paths:
5588 if not act:
5588 if not act:
5589 ui.write(b'%s%s' % (path, eol))
5589 ui.write(b'%s%s' % (path, eol))
5590
5590
5591
5591
5592 @command(
5592 @command(
5593 b'push',
5593 b'push',
5594 [
5594 [
5595 (b'f', b'force', None, _(b'force push')),
5595 (b'f', b'force', None, _(b'force push')),
5596 (
5596 (
5597 b'r',
5597 b'r',
5598 b'rev',
5598 b'rev',
5599 [],
5599 [],
5600 _(b'a changeset intended to be included in the destination'),
5600 _(b'a changeset intended to be included in the destination'),
5601 _(b'REV'),
5601 _(b'REV'),
5602 ),
5602 ),
5603 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5603 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5604 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5604 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5605 (
5605 (
5606 b'b',
5606 b'b',
5607 b'branch',
5607 b'branch',
5608 [],
5608 [],
5609 _(b'a specific branch you would like to push'),
5609 _(b'a specific branch you would like to push'),
5610 _(b'BRANCH'),
5610 _(b'BRANCH'),
5611 ),
5611 ),
5612 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5612 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5613 (
5613 (
5614 b'',
5614 b'',
5615 b'pushvars',
5615 b'pushvars',
5616 [],
5616 [],
5617 _(b'variables that can be sent to server (ADVANCED)'),
5617 _(b'variables that can be sent to server (ADVANCED)'),
5618 ),
5618 ),
5619 (
5619 (
5620 b'',
5620 b'',
5621 b'publish',
5621 b'publish',
5622 False,
5622 False,
5623 _(b'push the changeset as public (EXPERIMENTAL)'),
5623 _(b'push the changeset as public (EXPERIMENTAL)'),
5624 ),
5624 ),
5625 ]
5625 ]
5626 + remoteopts,
5626 + remoteopts,
5627 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]...'),
5627 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]...'),
5628 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5628 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5629 helpbasic=True,
5629 helpbasic=True,
5630 )
5630 )
5631 def push(ui, repo, *dests, **opts):
5631 def push(ui, repo, *dests, **opts):
5632 """push changes to the specified destination
5632 """push changes to the specified destination
5633
5633
5634 Push changesets from the local repository to the specified
5634 Push changesets from the local repository to the specified
5635 destination.
5635 destination.
5636
5636
5637 This operation is symmetrical to pull: it is identical to a pull
5637 This operation is symmetrical to pull: it is identical to a pull
5638 in the destination repository from the current one.
5638 in the destination repository from the current one.
5639
5639
5640 By default, push will not allow creation of new heads at the
5640 By default, push will not allow creation of new heads at the
5641 destination, since multiple heads would make it unclear which head
5641 destination, since multiple heads would make it unclear which head
5642 to use. In this situation, it is recommended to pull and merge
5642 to use. In this situation, it is recommended to pull and merge
5643 before pushing.
5643 before pushing.
5644
5644
5645 Use --new-branch if you want to allow push to create a new named
5645 Use --new-branch if you want to allow push to create a new named
5646 branch that is not present at the destination. This allows you to
5646 branch that is not present at the destination. This allows you to
5647 only create a new branch without forcing other changes.
5647 only create a new branch without forcing other changes.
5648
5648
5649 .. note::
5649 .. note::
5650
5650
5651 Extra care should be taken with the -f/--force option,
5651 Extra care should be taken with the -f/--force option,
5652 which will push all new heads on all branches, an action which will
5652 which will push all new heads on all branches, an action which will
5653 almost always cause confusion for collaborators.
5653 almost always cause confusion for collaborators.
5654
5654
5655 If -r/--rev is used, the specified revision and all its ancestors
5655 If -r/--rev is used, the specified revision and all its ancestors
5656 will be pushed to the remote repository.
5656 will be pushed to the remote repository.
5657
5657
5658 If -B/--bookmark is used, the specified bookmarked revision, its
5658 If -B/--bookmark is used, the specified bookmarked revision, its
5659 ancestors, and the bookmark will be pushed to the remote
5659 ancestors, and the bookmark will be pushed to the remote
5660 repository. Specifying ``.`` is equivalent to specifying the active
5660 repository. Specifying ``.`` is equivalent to specifying the active
5661 bookmark's name. Use the --all-bookmarks option for pushing all
5661 bookmark's name. Use the --all-bookmarks option for pushing all
5662 current bookmarks.
5662 current bookmarks.
5663
5663
5664 Please see :hg:`help urls` for important details about ``ssh://``
5664 Please see :hg:`help urls` for important details about ``ssh://``
5665 URLs. If DESTINATION is omitted, a default path will be used.
5665 URLs. If DESTINATION is omitted, a default path will be used.
5666
5666
5667 When passed multiple destinations, push will process them one after the
5667 When passed multiple destinations, push will process them one after the
5668 other, but stop should an error occur.
5668 other, but stop should an error occur.
5669
5669
5670 .. container:: verbose
5670 .. container:: verbose
5671
5671
5672 The --pushvars option sends strings to the server that become
5672 The --pushvars option sends strings to the server that become
5673 environment variables prepended with ``HG_USERVAR_``. For example,
5673 environment variables prepended with ``HG_USERVAR_``. For example,
5674 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5674 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5675 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5675 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5676
5676
5677 pushvars can provide for user-overridable hooks as well as set debug
5677 pushvars can provide for user-overridable hooks as well as set debug
5678 levels. One example is having a hook that blocks commits containing
5678 levels. One example is having a hook that blocks commits containing
5679 conflict markers, but enables the user to override the hook if the file
5679 conflict markers, but enables the user to override the hook if the file
5680 is using conflict markers for testing purposes or the file format has
5680 is using conflict markers for testing purposes or the file format has
5681 strings that look like conflict markers.
5681 strings that look like conflict markers.
5682
5682
5683 By default, servers will ignore `--pushvars`. To enable it add the
5683 By default, servers will ignore `--pushvars`. To enable it add the
5684 following to your configuration file::
5684 following to your configuration file::
5685
5685
5686 [push]
5686 [push]
5687 pushvars.server = true
5687 pushvars.server = true
5688
5688
5689 Returns 0 if push was successful, 1 if nothing to push.
5689 Returns 0 if push was successful, 1 if nothing to push.
5690 """
5690 """
5691
5691
5692 opts = pycompat.byteskwargs(opts)
5692 opts = pycompat.byteskwargs(opts)
5693
5693
5694 if opts.get(b'all_bookmarks'):
5694 if opts.get(b'all_bookmarks'):
5695 cmdutil.check_incompatible_arguments(
5695 cmdutil.check_incompatible_arguments(
5696 opts,
5696 opts,
5697 b'all_bookmarks',
5697 b'all_bookmarks',
5698 [b'bookmark', b'rev'],
5698 [b'bookmark', b'rev'],
5699 )
5699 )
5700 opts[b'bookmark'] = list(repo._bookmarks)
5700 opts[b'bookmark'] = list(repo._bookmarks)
5701
5701
5702 if opts.get(b'bookmark'):
5702 if opts.get(b'bookmark'):
5703 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5703 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5704 for b in opts[b'bookmark']:
5704 for b in opts[b'bookmark']:
5705 # translate -B options to -r so changesets get pushed
5705 # translate -B options to -r so changesets get pushed
5706 b = repo._bookmarks.expandname(b)
5706 b = repo._bookmarks.expandname(b)
5707 if b in repo._bookmarks:
5707 if b in repo._bookmarks:
5708 opts.setdefault(b'rev', []).append(b)
5708 opts.setdefault(b'rev', []).append(b)
5709 else:
5709 else:
5710 # if we try to push a deleted bookmark, translate it to null
5710 # if we try to push a deleted bookmark, translate it to null
5711 # this lets simultaneous -r, -b options continue working
5711 # this lets simultaneous -r, -b options continue working
5712 opts.setdefault(b'rev', []).append(b"null")
5712 opts.setdefault(b'rev', []).append(b"null")
5713
5713
5714 if not dests:
5714 if not dests:
5715 dests = [None]
5715 dests = [None]
5716 some_pushed = False
5716 some_pushed = False
5717 result = 0
5717 result = 0
5718 for dest in dests:
5718 for dest in dests:
5719 path = ui.getpath(dest, default=(b'default-push', b'default'))
5719 path = ui.getpath(dest, default=(b'default-push', b'default'))
5720 if not path:
5720 if not path:
5721 raise error.ConfigError(
5721 raise error.ConfigError(
5722 _(b'default repository not configured!'),
5722 _(b'default repository not configured!'),
5723 hint=_(b"see 'hg help config.paths'"),
5723 hint=_(b"see 'hg help config.paths'"),
5724 )
5724 )
5725 dest = path.pushloc or path.loc
5725 dest = path.pushloc or path.loc
5726 branches = (path.branch, opts.get(b'branch') or [])
5726 branches = (path.branch, opts.get(b'branch') or [])
5727 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5727 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5728 revs, checkout = hg.addbranchrevs(
5728 revs, checkout = hg.addbranchrevs(
5729 repo, repo, branches, opts.get(b'rev')
5729 repo, repo, branches, opts.get(b'rev')
5730 )
5730 )
5731 other = hg.peer(repo, opts, dest)
5731 other = hg.peer(repo, opts, dest)
5732
5732
5733 try:
5733 try:
5734 if revs:
5734 if revs:
5735 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5735 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5736 if not revs:
5736 if not revs:
5737 raise error.InputError(
5737 raise error.InputError(
5738 _(b"specified revisions evaluate to an empty set"),
5738 _(b"specified revisions evaluate to an empty set"),
5739 hint=_(b"use different revision arguments"),
5739 hint=_(b"use different revision arguments"),
5740 )
5740 )
5741 elif path.pushrev:
5741 elif path.pushrev:
5742 # It doesn't make any sense to specify ancestor revisions. So limit
5742 # It doesn't make any sense to specify ancestor revisions. So limit
5743 # to DAG heads to make discovery simpler.
5743 # to DAG heads to make discovery simpler.
5744 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5744 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5745 revs = scmutil.revrange(repo, [expr])
5745 revs = scmutil.revrange(repo, [expr])
5746 revs = [repo[rev].node() for rev in revs]
5746 revs = [repo[rev].node() for rev in revs]
5747 if not revs:
5747 if not revs:
5748 raise error.InputError(
5748 raise error.InputError(
5749 _(
5749 _(
5750 b'default push revset for path evaluates to an empty set'
5750 b'default push revset for path evaluates to an empty set'
5751 )
5751 )
5752 )
5752 )
5753 elif ui.configbool(b'commands', b'push.require-revs'):
5753 elif ui.configbool(b'commands', b'push.require-revs'):
5754 raise error.InputError(
5754 raise error.InputError(
5755 _(b'no revisions specified to push'),
5755 _(b'no revisions specified to push'),
5756 hint=_(b'did you mean "hg push -r ."?'),
5756 hint=_(b'did you mean "hg push -r ."?'),
5757 )
5757 )
5758
5758
5759 repo._subtoppath = dest
5759 repo._subtoppath = dest
5760 try:
5760 try:
5761 # push subrepos depth-first for coherent ordering
5761 # push subrepos depth-first for coherent ordering
5762 c = repo[b'.']
5762 c = repo[b'.']
5763 subs = c.substate # only repos that are committed
5763 subs = c.substate # only repos that are committed
5764 for s in sorted(subs):
5764 for s in sorted(subs):
5765 sub_result = c.sub(s).push(opts)
5765 sub_result = c.sub(s).push(opts)
5766 if sub_result == 0:
5766 if sub_result == 0:
5767 return 1
5767 return 1
5768 finally:
5768 finally:
5769 del repo._subtoppath
5769 del repo._subtoppath
5770
5770
5771 opargs = dict(
5771 opargs = dict(
5772 opts.get(b'opargs', {})
5772 opts.get(b'opargs', {})
5773 ) # copy opargs since we may mutate it
5773 ) # copy opargs since we may mutate it
5774 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5774 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5775
5775
5776 pushop = exchange.push(
5776 pushop = exchange.push(
5777 repo,
5777 repo,
5778 other,
5778 other,
5779 opts.get(b'force'),
5779 opts.get(b'force'),
5780 revs=revs,
5780 revs=revs,
5781 newbranch=opts.get(b'new_branch'),
5781 newbranch=opts.get(b'new_branch'),
5782 bookmarks=opts.get(b'bookmark', ()),
5782 bookmarks=opts.get(b'bookmark', ()),
5783 publish=opts.get(b'publish'),
5783 publish=opts.get(b'publish'),
5784 opargs=opargs,
5784 opargs=opargs,
5785 )
5785 )
5786
5786
5787 if pushop.cgresult == 0:
5787 if pushop.cgresult == 0:
5788 result = 1
5788 result = 1
5789 elif pushop.cgresult is not None:
5789 elif pushop.cgresult is not None:
5790 some_pushed = True
5790 some_pushed = True
5791
5791
5792 if pushop.bkresult is not None:
5792 if pushop.bkresult is not None:
5793 if pushop.bkresult == 2:
5793 if pushop.bkresult == 2:
5794 result = 2
5794 result = 2
5795 elif not result and pushop.bkresult:
5795 elif not result and pushop.bkresult:
5796 result = 2
5796 result = 2
5797
5797
5798 if result:
5798 if result:
5799 break
5799 break
5800
5800
5801 finally:
5801 finally:
5802 other.close()
5802 other.close()
5803 if result == 0 and not some_pushed:
5803 if result == 0 and not some_pushed:
5804 result = 1
5804 result = 1
5805 return result
5805 return result
5806
5806
5807
5807
5808 @command(
5808 @command(
5809 b'recover',
5809 b'recover',
5810 [
5810 [
5811 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5811 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5812 ],
5812 ],
5813 helpcategory=command.CATEGORY_MAINTENANCE,
5813 helpcategory=command.CATEGORY_MAINTENANCE,
5814 )
5814 )
5815 def recover(ui, repo, **opts):
5815 def recover(ui, repo, **opts):
5816 """roll back an interrupted transaction
5816 """roll back an interrupted transaction
5817
5817
5818 Recover from an interrupted commit or pull.
5818 Recover from an interrupted commit or pull.
5819
5819
5820 This command tries to fix the repository status after an
5820 This command tries to fix the repository status after an
5821 interrupted operation. It should only be necessary when Mercurial
5821 interrupted operation. It should only be necessary when Mercurial
5822 suggests it.
5822 suggests it.
5823
5823
5824 Returns 0 if successful, 1 if nothing to recover or verify fails.
5824 Returns 0 if successful, 1 if nothing to recover or verify fails.
5825 """
5825 """
5826 ret = repo.recover()
5826 ret = repo.recover()
5827 if ret:
5827 if ret:
5828 if opts['verify']:
5828 if opts['verify']:
5829 return hg.verify(repo)
5829 return hg.verify(repo)
5830 else:
5830 else:
5831 msg = _(
5831 msg = _(
5832 b"(verify step skipped, run `hg verify` to check your "
5832 b"(verify step skipped, run `hg verify` to check your "
5833 b"repository content)\n"
5833 b"repository content)\n"
5834 )
5834 )
5835 ui.warn(msg)
5835 ui.warn(msg)
5836 return 0
5836 return 0
5837 return 1
5837 return 1
5838
5838
5839
5839
5840 @command(
5840 @command(
5841 b'remove|rm',
5841 b'remove|rm',
5842 [
5842 [
5843 (b'A', b'after', None, _(b'record delete for missing files')),
5843 (b'A', b'after', None, _(b'record delete for missing files')),
5844 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5844 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5845 ]
5845 ]
5846 + subrepoopts
5846 + subrepoopts
5847 + walkopts
5847 + walkopts
5848 + dryrunopts,
5848 + dryrunopts,
5849 _(b'[OPTION]... FILE...'),
5849 _(b'[OPTION]... FILE...'),
5850 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5850 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5851 helpbasic=True,
5851 helpbasic=True,
5852 inferrepo=True,
5852 inferrepo=True,
5853 )
5853 )
5854 def remove(ui, repo, *pats, **opts):
5854 def remove(ui, repo, *pats, **opts):
5855 """remove the specified files on the next commit
5855 """remove the specified files on the next commit
5856
5856
5857 Schedule the indicated files for removal from the current branch.
5857 Schedule the indicated files for removal from the current branch.
5858
5858
5859 This command schedules the files to be removed at the next commit.
5859 This command schedules the files to be removed at the next commit.
5860 To undo a remove before that, see :hg:`revert`. To undo added
5860 To undo a remove before that, see :hg:`revert`. To undo added
5861 files, see :hg:`forget`.
5861 files, see :hg:`forget`.
5862
5862
5863 .. container:: verbose
5863 .. container:: verbose
5864
5864
5865 -A/--after can be used to remove only files that have already
5865 -A/--after can be used to remove only files that have already
5866 been deleted, -f/--force can be used to force deletion, and -Af
5866 been deleted, -f/--force can be used to force deletion, and -Af
5867 can be used to remove files from the next revision without
5867 can be used to remove files from the next revision without
5868 deleting them from the working directory.
5868 deleting them from the working directory.
5869
5869
5870 The following table details the behavior of remove for different
5870 The following table details the behavior of remove for different
5871 file states (columns) and option combinations (rows). The file
5871 file states (columns) and option combinations (rows). The file
5872 states are Added [A], Clean [C], Modified [M] and Missing [!]
5872 states are Added [A], Clean [C], Modified [M] and Missing [!]
5873 (as reported by :hg:`status`). The actions are Warn, Remove
5873 (as reported by :hg:`status`). The actions are Warn, Remove
5874 (from branch) and Delete (from disk):
5874 (from branch) and Delete (from disk):
5875
5875
5876 ========= == == == ==
5876 ========= == == == ==
5877 opt/state A C M !
5877 opt/state A C M !
5878 ========= == == == ==
5878 ========= == == == ==
5879 none W RD W R
5879 none W RD W R
5880 -f R RD RD R
5880 -f R RD RD R
5881 -A W W W R
5881 -A W W W R
5882 -Af R R R R
5882 -Af R R R R
5883 ========= == == == ==
5883 ========= == == == ==
5884
5884
5885 .. note::
5885 .. note::
5886
5886
5887 :hg:`remove` never deletes files in Added [A] state from the
5887 :hg:`remove` never deletes files in Added [A] state from the
5888 working directory, not even if ``--force`` is specified.
5888 working directory, not even if ``--force`` is specified.
5889
5889
5890 Returns 0 on success, 1 if any warnings encountered.
5890 Returns 0 on success, 1 if any warnings encountered.
5891 """
5891 """
5892
5892
5893 opts = pycompat.byteskwargs(opts)
5893 opts = pycompat.byteskwargs(opts)
5894 after, force = opts.get(b'after'), opts.get(b'force')
5894 after, force = opts.get(b'after'), opts.get(b'force')
5895 dryrun = opts.get(b'dry_run')
5895 dryrun = opts.get(b'dry_run')
5896 if not pats and not after:
5896 if not pats and not after:
5897 raise error.InputError(_(b'no files specified'))
5897 raise error.InputError(_(b'no files specified'))
5898
5898
5899 m = scmutil.match(repo[None], pats, opts)
5899 m = scmutil.match(repo[None], pats, opts)
5900 subrepos = opts.get(b'subrepos')
5900 subrepos = opts.get(b'subrepos')
5901 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5901 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5902 return cmdutil.remove(
5902 return cmdutil.remove(
5903 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5903 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5904 )
5904 )
5905
5905
5906
5906
5907 @command(
5907 @command(
5908 b'rename|move|mv',
5908 b'rename|move|mv',
5909 [
5909 [
5910 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5910 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5911 (
5911 (
5912 b'',
5912 b'',
5913 b'at-rev',
5913 b'at-rev',
5914 b'',
5914 b'',
5915 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5915 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5916 _(b'REV'),
5916 _(b'REV'),
5917 ),
5917 ),
5918 (
5918 (
5919 b'f',
5919 b'f',
5920 b'force',
5920 b'force',
5921 None,
5921 None,
5922 _(b'forcibly move over an existing managed file'),
5922 _(b'forcibly move over an existing managed file'),
5923 ),
5923 ),
5924 ]
5924 ]
5925 + walkopts
5925 + walkopts
5926 + dryrunopts,
5926 + dryrunopts,
5927 _(b'[OPTION]... SOURCE... DEST'),
5927 _(b'[OPTION]... SOURCE... DEST'),
5928 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5928 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5929 )
5929 )
5930 def rename(ui, repo, *pats, **opts):
5930 def rename(ui, repo, *pats, **opts):
5931 """rename files; equivalent of copy + remove
5931 """rename files; equivalent of copy + remove
5932
5932
5933 Mark dest as copies of sources; mark sources for deletion. If dest
5933 Mark dest as copies of sources; mark sources for deletion. If dest
5934 is a directory, copies are put in that directory. If dest is a
5934 is a directory, copies are put in that directory. If dest is a
5935 file, there can only be one source.
5935 file, there can only be one source.
5936
5936
5937 By default, this command copies the contents of files as they
5937 By default, this command copies the contents of files as they
5938 exist in the working directory. If invoked with -A/--after, the
5938 exist in the working directory. If invoked with -A/--after, the
5939 operation is recorded, but no copying is performed.
5939 operation is recorded, but no copying is performed.
5940
5940
5941 This command takes effect at the next commit. To undo a rename
5941 This command takes effect at the next commit. To undo a rename
5942 before that, see :hg:`revert`.
5942 before that, see :hg:`revert`.
5943
5943
5944 Returns 0 on success, 1 if errors are encountered.
5944 Returns 0 on success, 1 if errors are encountered.
5945 """
5945 """
5946 opts = pycompat.byteskwargs(opts)
5946 opts = pycompat.byteskwargs(opts)
5947 with repo.wlock():
5947 with repo.wlock():
5948 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5948 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5949
5949
5950
5950
5951 @command(
5951 @command(
5952 b'resolve',
5952 b'resolve',
5953 [
5953 [
5954 (b'a', b'all', None, _(b'select all unresolved files')),
5954 (b'a', b'all', None, _(b'select all unresolved files')),
5955 (b'l', b'list', None, _(b'list state of files needing merge')),
5955 (b'l', b'list', None, _(b'list state of files needing merge')),
5956 (b'm', b'mark', None, _(b'mark files as resolved')),
5956 (b'm', b'mark', None, _(b'mark files as resolved')),
5957 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5957 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5958 (b'n', b'no-status', None, _(b'hide status prefix')),
5958 (b'n', b'no-status', None, _(b'hide status prefix')),
5959 (b'', b're-merge', None, _(b're-merge files')),
5959 (b'', b're-merge', None, _(b're-merge files')),
5960 ]
5960 ]
5961 + mergetoolopts
5961 + mergetoolopts
5962 + walkopts
5962 + walkopts
5963 + formatteropts,
5963 + formatteropts,
5964 _(b'[OPTION]... [FILE]...'),
5964 _(b'[OPTION]... [FILE]...'),
5965 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5965 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5966 inferrepo=True,
5966 inferrepo=True,
5967 )
5967 )
5968 def resolve(ui, repo, *pats, **opts):
5968 def resolve(ui, repo, *pats, **opts):
5969 """redo merges or set/view the merge status of files
5969 """redo merges or set/view the merge status of files
5970
5970
5971 Merges with unresolved conflicts are often the result of
5971 Merges with unresolved conflicts are often the result of
5972 non-interactive merging using the ``internal:merge`` configuration
5972 non-interactive merging using the ``internal:merge`` configuration
5973 setting, or a command-line merge tool like ``diff3``. The resolve
5973 setting, or a command-line merge tool like ``diff3``. The resolve
5974 command is used to manage the files involved in a merge, after
5974 command is used to manage the files involved in a merge, after
5975 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5975 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5976 working directory must have two parents). See :hg:`help
5976 working directory must have two parents). See :hg:`help
5977 merge-tools` for information on configuring merge tools.
5977 merge-tools` for information on configuring merge tools.
5978
5978
5979 The resolve command can be used in the following ways:
5979 The resolve command can be used in the following ways:
5980
5980
5981 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5981 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5982 the specified files, discarding any previous merge attempts. Re-merging
5982 the specified files, discarding any previous merge attempts. Re-merging
5983 is not performed for files already marked as resolved. Use ``--all/-a``
5983 is not performed for files already marked as resolved. Use ``--all/-a``
5984 to select all unresolved files. ``--tool`` can be used to specify
5984 to select all unresolved files. ``--tool`` can be used to specify
5985 the merge tool used for the given files. It overrides the HGMERGE
5985 the merge tool used for the given files. It overrides the HGMERGE
5986 environment variable and your configuration files. Previous file
5986 environment variable and your configuration files. Previous file
5987 contents are saved with a ``.orig`` suffix.
5987 contents are saved with a ``.orig`` suffix.
5988
5988
5989 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5989 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5990 (e.g. after having manually fixed-up the files). The default is
5990 (e.g. after having manually fixed-up the files). The default is
5991 to mark all unresolved files.
5991 to mark all unresolved files.
5992
5992
5993 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5993 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5994 default is to mark all resolved files.
5994 default is to mark all resolved files.
5995
5995
5996 - :hg:`resolve -l`: list files which had or still have conflicts.
5996 - :hg:`resolve -l`: list files which had or still have conflicts.
5997 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5997 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5998 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5998 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5999 the list. See :hg:`help filesets` for details.
5999 the list. See :hg:`help filesets` for details.
6000
6000
6001 .. note::
6001 .. note::
6002
6002
6003 Mercurial will not let you commit files with unresolved merge
6003 Mercurial will not let you commit files with unresolved merge
6004 conflicts. You must use :hg:`resolve -m ...` before you can
6004 conflicts. You must use :hg:`resolve -m ...` before you can
6005 commit after a conflicting merge.
6005 commit after a conflicting merge.
6006
6006
6007 .. container:: verbose
6007 .. container:: verbose
6008
6008
6009 Template:
6009 Template:
6010
6010
6011 The following keywords are supported in addition to the common template
6011 The following keywords are supported in addition to the common template
6012 keywords and functions. See also :hg:`help templates`.
6012 keywords and functions. See also :hg:`help templates`.
6013
6013
6014 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
6014 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
6015 :path: String. Repository-absolute path of the file.
6015 :path: String. Repository-absolute path of the file.
6016
6016
6017 Returns 0 on success, 1 if any files fail a resolve attempt.
6017 Returns 0 on success, 1 if any files fail a resolve attempt.
6018 """
6018 """
6019
6019
6020 opts = pycompat.byteskwargs(opts)
6020 opts = pycompat.byteskwargs(opts)
6021 confirm = ui.configbool(b'commands', b'resolve.confirm')
6021 confirm = ui.configbool(b'commands', b'resolve.confirm')
6022 flaglist = b'all mark unmark list no_status re_merge'.split()
6022 flaglist = b'all mark unmark list no_status re_merge'.split()
6023 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
6023 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
6024
6024
6025 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
6025 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
6026 if actioncount > 1:
6026 if actioncount > 1:
6027 raise error.InputError(_(b"too many actions specified"))
6027 raise error.InputError(_(b"too many actions specified"))
6028 elif actioncount == 0 and ui.configbool(
6028 elif actioncount == 0 and ui.configbool(
6029 b'commands', b'resolve.explicit-re-merge'
6029 b'commands', b'resolve.explicit-re-merge'
6030 ):
6030 ):
6031 hint = _(b'use --mark, --unmark, --list or --re-merge')
6031 hint = _(b'use --mark, --unmark, --list or --re-merge')
6032 raise error.InputError(_(b'no action specified'), hint=hint)
6032 raise error.InputError(_(b'no action specified'), hint=hint)
6033 if pats and all:
6033 if pats and all:
6034 raise error.InputError(_(b"can't specify --all and patterns"))
6034 raise error.InputError(_(b"can't specify --all and patterns"))
6035 if not (all or pats or show or mark or unmark):
6035 if not (all or pats or show or mark or unmark):
6036 raise error.InputError(
6036 raise error.InputError(
6037 _(b'no files or directories specified'),
6037 _(b'no files or directories specified'),
6038 hint=b'use --all to re-merge all unresolved files',
6038 hint=b'use --all to re-merge all unresolved files',
6039 )
6039 )
6040
6040
6041 if confirm:
6041 if confirm:
6042 if all:
6042 if all:
6043 if ui.promptchoice(
6043 if ui.promptchoice(
6044 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
6044 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
6045 ):
6045 ):
6046 raise error.CanceledError(_(b'user quit'))
6046 raise error.CanceledError(_(b'user quit'))
6047 if mark and not pats:
6047 if mark and not pats:
6048 if ui.promptchoice(
6048 if ui.promptchoice(
6049 _(
6049 _(
6050 b'mark all unresolved files as resolved (yn)?'
6050 b'mark all unresolved files as resolved (yn)?'
6051 b'$$ &Yes $$ &No'
6051 b'$$ &Yes $$ &No'
6052 )
6052 )
6053 ):
6053 ):
6054 raise error.CanceledError(_(b'user quit'))
6054 raise error.CanceledError(_(b'user quit'))
6055 if unmark and not pats:
6055 if unmark and not pats:
6056 if ui.promptchoice(
6056 if ui.promptchoice(
6057 _(
6057 _(
6058 b'mark all resolved files as unresolved (yn)?'
6058 b'mark all resolved files as unresolved (yn)?'
6059 b'$$ &Yes $$ &No'
6059 b'$$ &Yes $$ &No'
6060 )
6060 )
6061 ):
6061 ):
6062 raise error.CanceledError(_(b'user quit'))
6062 raise error.CanceledError(_(b'user quit'))
6063
6063
6064 uipathfn = scmutil.getuipathfn(repo)
6064 uipathfn = scmutil.getuipathfn(repo)
6065
6065
6066 if show:
6066 if show:
6067 ui.pager(b'resolve')
6067 ui.pager(b'resolve')
6068 fm = ui.formatter(b'resolve', opts)
6068 fm = ui.formatter(b'resolve', opts)
6069 ms = mergestatemod.mergestate.read(repo)
6069 ms = mergestatemod.mergestate.read(repo)
6070 wctx = repo[None]
6070 wctx = repo[None]
6071 m = scmutil.match(wctx, pats, opts)
6071 m = scmutil.match(wctx, pats, opts)
6072
6072
6073 # Labels and keys based on merge state. Unresolved path conflicts show
6073 # Labels and keys based on merge state. Unresolved path conflicts show
6074 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6074 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6075 # resolved conflicts.
6075 # resolved conflicts.
6076 mergestateinfo = {
6076 mergestateinfo = {
6077 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6077 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6078 b'resolve.unresolved',
6078 b'resolve.unresolved',
6079 b'U',
6079 b'U',
6080 ),
6080 ),
6081 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6081 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6082 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6082 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6083 b'resolve.unresolved',
6083 b'resolve.unresolved',
6084 b'P',
6084 b'P',
6085 ),
6085 ),
6086 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6086 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6087 b'resolve.resolved',
6087 b'resolve.resolved',
6088 b'R',
6088 b'R',
6089 ),
6089 ),
6090 }
6090 }
6091
6091
6092 for f in ms:
6092 for f in ms:
6093 if not m(f):
6093 if not m(f):
6094 continue
6094 continue
6095
6095
6096 label, key = mergestateinfo[ms[f]]
6096 label, key = mergestateinfo[ms[f]]
6097 fm.startitem()
6097 fm.startitem()
6098 fm.context(ctx=wctx)
6098 fm.context(ctx=wctx)
6099 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6099 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6100 fm.data(path=f)
6100 fm.data(path=f)
6101 fm.plain(b'%s\n' % uipathfn(f), label=label)
6101 fm.plain(b'%s\n' % uipathfn(f), label=label)
6102 fm.end()
6102 fm.end()
6103 return 0
6103 return 0
6104
6104
6105 with repo.wlock():
6105 with repo.wlock():
6106 ms = mergestatemod.mergestate.read(repo)
6106 ms = mergestatemod.mergestate.read(repo)
6107
6107
6108 if not (ms.active() or repo.dirstate.p2() != nullid):
6108 if not (ms.active() or repo.dirstate.p2() != nullid):
6109 raise error.StateError(
6109 raise error.StateError(
6110 _(b'resolve command not applicable when not merging')
6110 _(b'resolve command not applicable when not merging')
6111 )
6111 )
6112
6112
6113 wctx = repo[None]
6113 wctx = repo[None]
6114 m = scmutil.match(wctx, pats, opts)
6114 m = scmutil.match(wctx, pats, opts)
6115 ret = 0
6115 ret = 0
6116 didwork = False
6116 didwork = False
6117
6117
6118 tocomplete = []
6118 tocomplete = []
6119 hasconflictmarkers = []
6119 hasconflictmarkers = []
6120 if mark:
6120 if mark:
6121 markcheck = ui.config(b'commands', b'resolve.mark-check')
6121 markcheck = ui.config(b'commands', b'resolve.mark-check')
6122 if markcheck not in [b'warn', b'abort']:
6122 if markcheck not in [b'warn', b'abort']:
6123 # Treat all invalid / unrecognized values as 'none'.
6123 # Treat all invalid / unrecognized values as 'none'.
6124 markcheck = False
6124 markcheck = False
6125 for f in ms:
6125 for f in ms:
6126 if not m(f):
6126 if not m(f):
6127 continue
6127 continue
6128
6128
6129 didwork = True
6129 didwork = True
6130
6130
6131 # path conflicts must be resolved manually
6131 # path conflicts must be resolved manually
6132 if ms[f] in (
6132 if ms[f] in (
6133 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6133 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6134 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6134 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6135 ):
6135 ):
6136 if mark:
6136 if mark:
6137 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6137 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6138 elif unmark:
6138 elif unmark:
6139 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6139 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6140 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6140 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6141 ui.warn(
6141 ui.warn(
6142 _(b'%s: path conflict must be resolved manually\n')
6142 _(b'%s: path conflict must be resolved manually\n')
6143 % uipathfn(f)
6143 % uipathfn(f)
6144 )
6144 )
6145 continue
6145 continue
6146
6146
6147 if mark:
6147 if mark:
6148 if markcheck:
6148 if markcheck:
6149 fdata = repo.wvfs.tryread(f)
6149 fdata = repo.wvfs.tryread(f)
6150 if (
6150 if (
6151 filemerge.hasconflictmarkers(fdata)
6151 filemerge.hasconflictmarkers(fdata)
6152 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6152 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6153 ):
6153 ):
6154 hasconflictmarkers.append(f)
6154 hasconflictmarkers.append(f)
6155 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6155 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6156 elif unmark:
6156 elif unmark:
6157 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6157 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6158 else:
6158 else:
6159 # backup pre-resolve (merge uses .orig for its own purposes)
6159 # backup pre-resolve (merge uses .orig for its own purposes)
6160 a = repo.wjoin(f)
6160 a = repo.wjoin(f)
6161 try:
6161 try:
6162 util.copyfile(a, a + b".resolve")
6162 util.copyfile(a, a + b".resolve")
6163 except (IOError, OSError) as inst:
6163 except (IOError, OSError) as inst:
6164 if inst.errno != errno.ENOENT:
6164 if inst.errno != errno.ENOENT:
6165 raise
6165 raise
6166
6166
6167 try:
6167 try:
6168 # preresolve file
6168 # preresolve file
6169 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6169 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6170 with ui.configoverride(overrides, b'resolve'):
6170 with ui.configoverride(overrides, b'resolve'):
6171 complete, r = ms.preresolve(f, wctx)
6171 complete, r = ms.preresolve(f, wctx)
6172 if not complete:
6172 if not complete:
6173 tocomplete.append(f)
6173 tocomplete.append(f)
6174 elif r:
6174 elif r:
6175 ret = 1
6175 ret = 1
6176 finally:
6176 finally:
6177 ms.commit()
6177 ms.commit()
6178
6178
6179 # replace filemerge's .orig file with our resolve file, but only
6179 # replace filemerge's .orig file with our resolve file, but only
6180 # for merges that are complete
6180 # for merges that are complete
6181 if complete:
6181 if complete:
6182 try:
6182 try:
6183 util.rename(
6183 util.rename(
6184 a + b".resolve", scmutil.backuppath(ui, repo, f)
6184 a + b".resolve", scmutil.backuppath(ui, repo, f)
6185 )
6185 )
6186 except OSError as inst:
6186 except OSError as inst:
6187 if inst.errno != errno.ENOENT:
6187 if inst.errno != errno.ENOENT:
6188 raise
6188 raise
6189
6189
6190 if hasconflictmarkers:
6190 if hasconflictmarkers:
6191 ui.warn(
6191 ui.warn(
6192 _(
6192 _(
6193 b'warning: the following files still have conflict '
6193 b'warning: the following files still have conflict '
6194 b'markers:\n'
6194 b'markers:\n'
6195 )
6195 )
6196 + b''.join(
6196 + b''.join(
6197 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6197 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6198 )
6198 )
6199 )
6199 )
6200 if markcheck == b'abort' and not all and not pats:
6200 if markcheck == b'abort' and not all and not pats:
6201 raise error.StateError(
6201 raise error.StateError(
6202 _(b'conflict markers detected'),
6202 _(b'conflict markers detected'),
6203 hint=_(b'use --all to mark anyway'),
6203 hint=_(b'use --all to mark anyway'),
6204 )
6204 )
6205
6205
6206 for f in tocomplete:
6206 for f in tocomplete:
6207 try:
6207 try:
6208 # resolve file
6208 # resolve file
6209 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6209 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6210 with ui.configoverride(overrides, b'resolve'):
6210 with ui.configoverride(overrides, b'resolve'):
6211 r = ms.resolve(f, wctx)
6211 r = ms.resolve(f, wctx)
6212 if r:
6212 if r:
6213 ret = 1
6213 ret = 1
6214 finally:
6214 finally:
6215 ms.commit()
6215 ms.commit()
6216
6216
6217 # replace filemerge's .orig file with our resolve file
6217 # replace filemerge's .orig file with our resolve file
6218 a = repo.wjoin(f)
6218 a = repo.wjoin(f)
6219 try:
6219 try:
6220 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
6220 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
6221 except OSError as inst:
6221 except OSError as inst:
6222 if inst.errno != errno.ENOENT:
6222 if inst.errno != errno.ENOENT:
6223 raise
6223 raise
6224
6224
6225 ms.commit()
6225 ms.commit()
6226 branchmerge = repo.dirstate.p2() != nullid
6226 branchmerge = repo.dirstate.p2() != nullid
6227 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6227 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6228
6228
6229 if not didwork and pats:
6229 if not didwork and pats:
6230 hint = None
6230 hint = None
6231 if not any([p for p in pats if p.find(b':') >= 0]):
6231 if not any([p for p in pats if p.find(b':') >= 0]):
6232 pats = [b'path:%s' % p for p in pats]
6232 pats = [b'path:%s' % p for p in pats]
6233 m = scmutil.match(wctx, pats, opts)
6233 m = scmutil.match(wctx, pats, opts)
6234 for f in ms:
6234 for f in ms:
6235 if not m(f):
6235 if not m(f):
6236 continue
6236 continue
6237
6237
6238 def flag(o):
6238 def flag(o):
6239 if o == b're_merge':
6239 if o == b're_merge':
6240 return b'--re-merge '
6240 return b'--re-merge '
6241 return b'-%s ' % o[0:1]
6241 return b'-%s ' % o[0:1]
6242
6242
6243 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6243 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6244 hint = _(b"(try: hg resolve %s%s)\n") % (
6244 hint = _(b"(try: hg resolve %s%s)\n") % (
6245 flags,
6245 flags,
6246 b' '.join(pats),
6246 b' '.join(pats),
6247 )
6247 )
6248 break
6248 break
6249 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6249 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6250 if hint:
6250 if hint:
6251 ui.warn(hint)
6251 ui.warn(hint)
6252
6252
6253 unresolvedf = ms.unresolvedcount()
6253 unresolvedf = ms.unresolvedcount()
6254 if not unresolvedf:
6254 if not unresolvedf:
6255 ui.status(_(b'(no more unresolved files)\n'))
6255 ui.status(_(b'(no more unresolved files)\n'))
6256 cmdutil.checkafterresolved(repo)
6256 cmdutil.checkafterresolved(repo)
6257
6257
6258 return ret
6258 return ret
6259
6259
6260
6260
6261 @command(
6261 @command(
6262 b'revert',
6262 b'revert',
6263 [
6263 [
6264 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6264 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6265 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6265 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6266 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6266 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6267 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6267 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6268 (b'i', b'interactive', None, _(b'interactively select the changes')),
6268 (b'i', b'interactive', None, _(b'interactively select the changes')),
6269 ]
6269 ]
6270 + walkopts
6270 + walkopts
6271 + dryrunopts,
6271 + dryrunopts,
6272 _(b'[OPTION]... [-r REV] [NAME]...'),
6272 _(b'[OPTION]... [-r REV] [NAME]...'),
6273 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6273 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6274 )
6274 )
6275 def revert(ui, repo, *pats, **opts):
6275 def revert(ui, repo, *pats, **opts):
6276 """restore files to their checkout state
6276 """restore files to their checkout state
6277
6277
6278 .. note::
6278 .. note::
6279
6279
6280 To check out earlier revisions, you should use :hg:`update REV`.
6280 To check out earlier revisions, you should use :hg:`update REV`.
6281 To cancel an uncommitted merge (and lose your changes),
6281 To cancel an uncommitted merge (and lose your changes),
6282 use :hg:`merge --abort`.
6282 use :hg:`merge --abort`.
6283
6283
6284 With no revision specified, revert the specified files or directories
6284 With no revision specified, revert the specified files or directories
6285 to the contents they had in the parent of the working directory.
6285 to the contents they had in the parent of the working directory.
6286 This restores the contents of files to an unmodified
6286 This restores the contents of files to an unmodified
6287 state and unschedules adds, removes, copies, and renames. If the
6287 state and unschedules adds, removes, copies, and renames. If the
6288 working directory has two parents, you must explicitly specify a
6288 working directory has two parents, you must explicitly specify a
6289 revision.
6289 revision.
6290
6290
6291 Using the -r/--rev or -d/--date options, revert the given files or
6291 Using the -r/--rev or -d/--date options, revert the given files or
6292 directories to their states as of a specific revision. Because
6292 directories to their states as of a specific revision. Because
6293 revert does not change the working directory parents, this will
6293 revert does not change the working directory parents, this will
6294 cause these files to appear modified. This can be helpful to "back
6294 cause these files to appear modified. This can be helpful to "back
6295 out" some or all of an earlier change. See :hg:`backout` for a
6295 out" some or all of an earlier change. See :hg:`backout` for a
6296 related method.
6296 related method.
6297
6297
6298 Modified files are saved with a .orig suffix before reverting.
6298 Modified files are saved with a .orig suffix before reverting.
6299 To disable these backups, use --no-backup. It is possible to store
6299 To disable these backups, use --no-backup. It is possible to store
6300 the backup files in a custom directory relative to the root of the
6300 the backup files in a custom directory relative to the root of the
6301 repository by setting the ``ui.origbackuppath`` configuration
6301 repository by setting the ``ui.origbackuppath`` configuration
6302 option.
6302 option.
6303
6303
6304 See :hg:`help dates` for a list of formats valid for -d/--date.
6304 See :hg:`help dates` for a list of formats valid for -d/--date.
6305
6305
6306 See :hg:`help backout` for a way to reverse the effect of an
6306 See :hg:`help backout` for a way to reverse the effect of an
6307 earlier changeset.
6307 earlier changeset.
6308
6308
6309 Returns 0 on success.
6309 Returns 0 on success.
6310 """
6310 """
6311
6311
6312 opts = pycompat.byteskwargs(opts)
6312 opts = pycompat.byteskwargs(opts)
6313 if opts.get(b"date"):
6313 if opts.get(b"date"):
6314 cmdutil.check_incompatible_arguments(opts, b'date', [b'rev'])
6314 cmdutil.check_incompatible_arguments(opts, b'date', [b'rev'])
6315 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6315 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6316
6316
6317 parent, p2 = repo.dirstate.parents()
6317 parent, p2 = repo.dirstate.parents()
6318 if not opts.get(b'rev') and p2 != nullid:
6318 if not opts.get(b'rev') and p2 != nullid:
6319 # revert after merge is a trap for new users (issue2915)
6319 # revert after merge is a trap for new users (issue2915)
6320 raise error.InputError(
6320 raise error.InputError(
6321 _(b'uncommitted merge with no revision specified'),
6321 _(b'uncommitted merge with no revision specified'),
6322 hint=_(b"use 'hg update' or see 'hg help revert'"),
6322 hint=_(b"use 'hg update' or see 'hg help revert'"),
6323 )
6323 )
6324
6324
6325 rev = opts.get(b'rev')
6325 rev = opts.get(b'rev')
6326 if rev:
6326 if rev:
6327 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6327 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6328 ctx = scmutil.revsingle(repo, rev)
6328 ctx = scmutil.revsingle(repo, rev)
6329
6329
6330 if not (
6330 if not (
6331 pats
6331 pats
6332 or opts.get(b'include')
6332 or opts.get(b'include')
6333 or opts.get(b'exclude')
6333 or opts.get(b'exclude')
6334 or opts.get(b'all')
6334 or opts.get(b'all')
6335 or opts.get(b'interactive')
6335 or opts.get(b'interactive')
6336 ):
6336 ):
6337 msg = _(b"no files or directories specified")
6337 msg = _(b"no files or directories specified")
6338 if p2 != nullid:
6338 if p2 != nullid:
6339 hint = _(
6339 hint = _(
6340 b"uncommitted merge, use --all to discard all changes,"
6340 b"uncommitted merge, use --all to discard all changes,"
6341 b" or 'hg update -C .' to abort the merge"
6341 b" or 'hg update -C .' to abort the merge"
6342 )
6342 )
6343 raise error.InputError(msg, hint=hint)
6343 raise error.InputError(msg, hint=hint)
6344 dirty = any(repo.status())
6344 dirty = any(repo.status())
6345 node = ctx.node()
6345 node = ctx.node()
6346 if node != parent:
6346 if node != parent:
6347 if dirty:
6347 if dirty:
6348 hint = (
6348 hint = (
6349 _(
6349 _(
6350 b"uncommitted changes, use --all to discard all"
6350 b"uncommitted changes, use --all to discard all"
6351 b" changes, or 'hg update %d' to update"
6351 b" changes, or 'hg update %d' to update"
6352 )
6352 )
6353 % ctx.rev()
6353 % ctx.rev()
6354 )
6354 )
6355 else:
6355 else:
6356 hint = (
6356 hint = (
6357 _(
6357 _(
6358 b"use --all to revert all files,"
6358 b"use --all to revert all files,"
6359 b" or 'hg update %d' to update"
6359 b" or 'hg update %d' to update"
6360 )
6360 )
6361 % ctx.rev()
6361 % ctx.rev()
6362 )
6362 )
6363 elif dirty:
6363 elif dirty:
6364 hint = _(b"uncommitted changes, use --all to discard all changes")
6364 hint = _(b"uncommitted changes, use --all to discard all changes")
6365 else:
6365 else:
6366 hint = _(b"use --all to revert all files")
6366 hint = _(b"use --all to revert all files")
6367 raise error.InputError(msg, hint=hint)
6367 raise error.InputError(msg, hint=hint)
6368
6368
6369 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6369 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6370
6370
6371
6371
6372 @command(
6372 @command(
6373 b'rollback',
6373 b'rollback',
6374 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6374 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6375 helpcategory=command.CATEGORY_MAINTENANCE,
6375 helpcategory=command.CATEGORY_MAINTENANCE,
6376 )
6376 )
6377 def rollback(ui, repo, **opts):
6377 def rollback(ui, repo, **opts):
6378 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6378 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6379
6379
6380 Please use :hg:`commit --amend` instead of rollback to correct
6380 Please use :hg:`commit --amend` instead of rollback to correct
6381 mistakes in the last commit.
6381 mistakes in the last commit.
6382
6382
6383 This command should be used with care. There is only one level of
6383 This command should be used with care. There is only one level of
6384 rollback, and there is no way to undo a rollback. It will also
6384 rollback, and there is no way to undo a rollback. It will also
6385 restore the dirstate at the time of the last transaction, losing
6385 restore the dirstate at the time of the last transaction, losing
6386 any dirstate changes since that time. This command does not alter
6386 any dirstate changes since that time. This command does not alter
6387 the working directory.
6387 the working directory.
6388
6388
6389 Transactions are used to encapsulate the effects of all commands
6389 Transactions are used to encapsulate the effects of all commands
6390 that create new changesets or propagate existing changesets into a
6390 that create new changesets or propagate existing changesets into a
6391 repository.
6391 repository.
6392
6392
6393 .. container:: verbose
6393 .. container:: verbose
6394
6394
6395 For example, the following commands are transactional, and their
6395 For example, the following commands are transactional, and their
6396 effects can be rolled back:
6396 effects can be rolled back:
6397
6397
6398 - commit
6398 - commit
6399 - import
6399 - import
6400 - pull
6400 - pull
6401 - push (with this repository as the destination)
6401 - push (with this repository as the destination)
6402 - unbundle
6402 - unbundle
6403
6403
6404 To avoid permanent data loss, rollback will refuse to rollback a
6404 To avoid permanent data loss, rollback will refuse to rollback a
6405 commit transaction if it isn't checked out. Use --force to
6405 commit transaction if it isn't checked out. Use --force to
6406 override this protection.
6406 override this protection.
6407
6407
6408 The rollback command can be entirely disabled by setting the
6408 The rollback command can be entirely disabled by setting the
6409 ``ui.rollback`` configuration setting to false. If you're here
6409 ``ui.rollback`` configuration setting to false. If you're here
6410 because you want to use rollback and it's disabled, you can
6410 because you want to use rollback and it's disabled, you can
6411 re-enable the command by setting ``ui.rollback`` to true.
6411 re-enable the command by setting ``ui.rollback`` to true.
6412
6412
6413 This command is not intended for use on public repositories. Once
6413 This command is not intended for use on public repositories. Once
6414 changes are visible for pull by other users, rolling a transaction
6414 changes are visible for pull by other users, rolling a transaction
6415 back locally is ineffective (someone else may already have pulled
6415 back locally is ineffective (someone else may already have pulled
6416 the changes). Furthermore, a race is possible with readers of the
6416 the changes). Furthermore, a race is possible with readers of the
6417 repository; for example an in-progress pull from the repository
6417 repository; for example an in-progress pull from the repository
6418 may fail if a rollback is performed.
6418 may fail if a rollback is performed.
6419
6419
6420 Returns 0 on success, 1 if no rollback data is available.
6420 Returns 0 on success, 1 if no rollback data is available.
6421 """
6421 """
6422 if not ui.configbool(b'ui', b'rollback'):
6422 if not ui.configbool(b'ui', b'rollback'):
6423 raise error.Abort(
6423 raise error.Abort(
6424 _(b'rollback is disabled because it is unsafe'),
6424 _(b'rollback is disabled because it is unsafe'),
6425 hint=b'see `hg help -v rollback` for information',
6425 hint=b'see `hg help -v rollback` for information',
6426 )
6426 )
6427 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6427 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6428
6428
6429
6429
6430 @command(
6430 @command(
6431 b'root',
6431 b'root',
6432 [] + formatteropts,
6432 [] + formatteropts,
6433 intents={INTENT_READONLY},
6433 intents={INTENT_READONLY},
6434 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6434 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6435 )
6435 )
6436 def root(ui, repo, **opts):
6436 def root(ui, repo, **opts):
6437 """print the root (top) of the current working directory
6437 """print the root (top) of the current working directory
6438
6438
6439 Print the root directory of the current repository.
6439 Print the root directory of the current repository.
6440
6440
6441 .. container:: verbose
6441 .. container:: verbose
6442
6442
6443 Template:
6443 Template:
6444
6444
6445 The following keywords are supported in addition to the common template
6445 The following keywords are supported in addition to the common template
6446 keywords and functions. See also :hg:`help templates`.
6446 keywords and functions. See also :hg:`help templates`.
6447
6447
6448 :hgpath: String. Path to the .hg directory.
6448 :hgpath: String. Path to the .hg directory.
6449 :storepath: String. Path to the directory holding versioned data.
6449 :storepath: String. Path to the directory holding versioned data.
6450
6450
6451 Returns 0 on success.
6451 Returns 0 on success.
6452 """
6452 """
6453 opts = pycompat.byteskwargs(opts)
6453 opts = pycompat.byteskwargs(opts)
6454 with ui.formatter(b'root', opts) as fm:
6454 with ui.formatter(b'root', opts) as fm:
6455 fm.startitem()
6455 fm.startitem()
6456 fm.write(b'reporoot', b'%s\n', repo.root)
6456 fm.write(b'reporoot', b'%s\n', repo.root)
6457 fm.data(hgpath=repo.path, storepath=repo.spath)
6457 fm.data(hgpath=repo.path, storepath=repo.spath)
6458
6458
6459
6459
6460 @command(
6460 @command(
6461 b'serve',
6461 b'serve',
6462 [
6462 [
6463 (
6463 (
6464 b'A',
6464 b'A',
6465 b'accesslog',
6465 b'accesslog',
6466 b'',
6466 b'',
6467 _(b'name of access log file to write to'),
6467 _(b'name of access log file to write to'),
6468 _(b'FILE'),
6468 _(b'FILE'),
6469 ),
6469 ),
6470 (b'd', b'daemon', None, _(b'run server in background')),
6470 (b'd', b'daemon', None, _(b'run server in background')),
6471 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6471 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6472 (
6472 (
6473 b'E',
6473 b'E',
6474 b'errorlog',
6474 b'errorlog',
6475 b'',
6475 b'',
6476 _(b'name of error log file to write to'),
6476 _(b'name of error log file to write to'),
6477 _(b'FILE'),
6477 _(b'FILE'),
6478 ),
6478 ),
6479 # use string type, then we can check if something was passed
6479 # use string type, then we can check if something was passed
6480 (
6480 (
6481 b'p',
6481 b'p',
6482 b'port',
6482 b'port',
6483 b'',
6483 b'',
6484 _(b'port to listen on (default: 8000)'),
6484 _(b'port to listen on (default: 8000)'),
6485 _(b'PORT'),
6485 _(b'PORT'),
6486 ),
6486 ),
6487 (
6487 (
6488 b'a',
6488 b'a',
6489 b'address',
6489 b'address',
6490 b'',
6490 b'',
6491 _(b'address to listen on (default: all interfaces)'),
6491 _(b'address to listen on (default: all interfaces)'),
6492 _(b'ADDR'),
6492 _(b'ADDR'),
6493 ),
6493 ),
6494 (
6494 (
6495 b'',
6495 b'',
6496 b'prefix',
6496 b'prefix',
6497 b'',
6497 b'',
6498 _(b'prefix path to serve from (default: server root)'),
6498 _(b'prefix path to serve from (default: server root)'),
6499 _(b'PREFIX'),
6499 _(b'PREFIX'),
6500 ),
6500 ),
6501 (
6501 (
6502 b'n',
6502 b'n',
6503 b'name',
6503 b'name',
6504 b'',
6504 b'',
6505 _(b'name to show in web pages (default: working directory)'),
6505 _(b'name to show in web pages (default: working directory)'),
6506 _(b'NAME'),
6506 _(b'NAME'),
6507 ),
6507 ),
6508 (
6508 (
6509 b'',
6509 b'',
6510 b'web-conf',
6510 b'web-conf',
6511 b'',
6511 b'',
6512 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6512 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6513 _(b'FILE'),
6513 _(b'FILE'),
6514 ),
6514 ),
6515 (
6515 (
6516 b'',
6516 b'',
6517 b'webdir-conf',
6517 b'webdir-conf',
6518 b'',
6518 b'',
6519 _(b'name of the hgweb config file (DEPRECATED)'),
6519 _(b'name of the hgweb config file (DEPRECATED)'),
6520 _(b'FILE'),
6520 _(b'FILE'),
6521 ),
6521 ),
6522 (
6522 (
6523 b'',
6523 b'',
6524 b'pid-file',
6524 b'pid-file',
6525 b'',
6525 b'',
6526 _(b'name of file to write process ID to'),
6526 _(b'name of file to write process ID to'),
6527 _(b'FILE'),
6527 _(b'FILE'),
6528 ),
6528 ),
6529 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6529 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6530 (
6530 (
6531 b'',
6531 b'',
6532 b'cmdserver',
6532 b'cmdserver',
6533 b'',
6533 b'',
6534 _(b'for remote clients (ADVANCED)'),
6534 _(b'for remote clients (ADVANCED)'),
6535 _(b'MODE'),
6535 _(b'MODE'),
6536 ),
6536 ),
6537 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6537 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6538 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6538 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6539 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6539 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6540 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6540 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6541 (b'', b'print-url', None, _(b'start and print only the URL')),
6541 (b'', b'print-url', None, _(b'start and print only the URL')),
6542 ]
6542 ]
6543 + subrepoopts,
6543 + subrepoopts,
6544 _(b'[OPTION]...'),
6544 _(b'[OPTION]...'),
6545 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6545 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6546 helpbasic=True,
6546 helpbasic=True,
6547 optionalrepo=True,
6547 optionalrepo=True,
6548 )
6548 )
6549 def serve(ui, repo, **opts):
6549 def serve(ui, repo, **opts):
6550 """start stand-alone webserver
6550 """start stand-alone webserver
6551
6551
6552 Start a local HTTP repository browser and pull server. You can use
6552 Start a local HTTP repository browser and pull server. You can use
6553 this for ad-hoc sharing and browsing of repositories. It is
6553 this for ad-hoc sharing and browsing of repositories. It is
6554 recommended to use a real web server to serve a repository for
6554 recommended to use a real web server to serve a repository for
6555 longer periods of time.
6555 longer periods of time.
6556
6556
6557 Please note that the server does not implement access control.
6557 Please note that the server does not implement access control.
6558 This means that, by default, anybody can read from the server and
6558 This means that, by default, anybody can read from the server and
6559 nobody can write to it by default. Set the ``web.allow-push``
6559 nobody can write to it by default. Set the ``web.allow-push``
6560 option to ``*`` to allow everybody to push to the server. You
6560 option to ``*`` to allow everybody to push to the server. You
6561 should use a real web server if you need to authenticate users.
6561 should use a real web server if you need to authenticate users.
6562
6562
6563 By default, the server logs accesses to stdout and errors to
6563 By default, the server logs accesses to stdout and errors to
6564 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6564 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6565 files.
6565 files.
6566
6566
6567 To have the server choose a free port number to listen on, specify
6567 To have the server choose a free port number to listen on, specify
6568 a port number of 0; in this case, the server will print the port
6568 a port number of 0; in this case, the server will print the port
6569 number it uses.
6569 number it uses.
6570
6570
6571 Returns 0 on success.
6571 Returns 0 on success.
6572 """
6572 """
6573
6573
6574 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6574 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6575 opts = pycompat.byteskwargs(opts)
6575 opts = pycompat.byteskwargs(opts)
6576 if opts[b"print_url"] and ui.verbose:
6576 if opts[b"print_url"] and ui.verbose:
6577 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6577 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6578
6578
6579 if opts[b"stdio"]:
6579 if opts[b"stdio"]:
6580 if repo is None:
6580 if repo is None:
6581 raise error.RepoError(
6581 raise error.RepoError(
6582 _(b"there is no Mercurial repository here (.hg not found)")
6582 _(b"there is no Mercurial repository here (.hg not found)")
6583 )
6583 )
6584 s = wireprotoserver.sshserver(ui, repo)
6584 s = wireprotoserver.sshserver(ui, repo)
6585 s.serve_forever()
6585 s.serve_forever()
6586 return
6586 return
6587
6587
6588 service = server.createservice(ui, repo, opts)
6588 service = server.createservice(ui, repo, opts)
6589 return server.runservice(opts, initfn=service.init, runfn=service.run)
6589 return server.runservice(opts, initfn=service.init, runfn=service.run)
6590
6590
6591
6591
6592 @command(
6592 @command(
6593 b'shelve',
6593 b'shelve',
6594 [
6594 [
6595 (
6595 (
6596 b'A',
6596 b'A',
6597 b'addremove',
6597 b'addremove',
6598 None,
6598 None,
6599 _(b'mark new/missing files as added/removed before shelving'),
6599 _(b'mark new/missing files as added/removed before shelving'),
6600 ),
6600 ),
6601 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6601 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6602 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6602 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6603 (
6603 (
6604 b'',
6604 b'',
6605 b'date',
6605 b'date',
6606 b'',
6606 b'',
6607 _(b'shelve with the specified commit date'),
6607 _(b'shelve with the specified commit date'),
6608 _(b'DATE'),
6608 _(b'DATE'),
6609 ),
6609 ),
6610 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6610 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6611 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6611 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6612 (
6612 (
6613 b'k',
6613 b'k',
6614 b'keep',
6614 b'keep',
6615 False,
6615 False,
6616 _(b'shelve, but keep changes in the working directory'),
6616 _(b'shelve, but keep changes in the working directory'),
6617 ),
6617 ),
6618 (b'l', b'list', None, _(b'list current shelves')),
6618 (b'l', b'list', None, _(b'list current shelves')),
6619 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6619 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6620 (
6620 (
6621 b'n',
6621 b'n',
6622 b'name',
6622 b'name',
6623 b'',
6623 b'',
6624 _(b'use the given name for the shelved commit'),
6624 _(b'use the given name for the shelved commit'),
6625 _(b'NAME'),
6625 _(b'NAME'),
6626 ),
6626 ),
6627 (
6627 (
6628 b'p',
6628 b'p',
6629 b'patch',
6629 b'patch',
6630 None,
6630 None,
6631 _(
6631 _(
6632 b'output patches for changes (provide the names of the shelved '
6632 b'output patches for changes (provide the names of the shelved '
6633 b'changes as positional arguments)'
6633 b'changes as positional arguments)'
6634 ),
6634 ),
6635 ),
6635 ),
6636 (b'i', b'interactive', None, _(b'interactive mode')),
6636 (b'i', b'interactive', None, _(b'interactive mode')),
6637 (
6637 (
6638 b'',
6638 b'',
6639 b'stat',
6639 b'stat',
6640 None,
6640 None,
6641 _(
6641 _(
6642 b'output diffstat-style summary of changes (provide the names of '
6642 b'output diffstat-style summary of changes (provide the names of '
6643 b'the shelved changes as positional arguments)'
6643 b'the shelved changes as positional arguments)'
6644 ),
6644 ),
6645 ),
6645 ),
6646 ]
6646 ]
6647 + cmdutil.walkopts,
6647 + cmdutil.walkopts,
6648 _(b'hg shelve [OPTION]... [FILE]...'),
6648 _(b'hg shelve [OPTION]... [FILE]...'),
6649 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6649 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6650 )
6650 )
6651 def shelve(ui, repo, *pats, **opts):
6651 def shelve(ui, repo, *pats, **opts):
6652 """save and set aside changes from the working directory
6652 """save and set aside changes from the working directory
6653
6653
6654 Shelving takes files that "hg status" reports as not clean, saves
6654 Shelving takes files that "hg status" reports as not clean, saves
6655 the modifications to a bundle (a shelved change), and reverts the
6655 the modifications to a bundle (a shelved change), and reverts the
6656 files so that their state in the working directory becomes clean.
6656 files so that their state in the working directory becomes clean.
6657
6657
6658 To restore these changes to the working directory, using "hg
6658 To restore these changes to the working directory, using "hg
6659 unshelve"; this will work even if you switch to a different
6659 unshelve"; this will work even if you switch to a different
6660 commit.
6660 commit.
6661
6661
6662 When no files are specified, "hg shelve" saves all not-clean
6662 When no files are specified, "hg shelve" saves all not-clean
6663 files. If specific files or directories are named, only changes to
6663 files. If specific files or directories are named, only changes to
6664 those files are shelved.
6664 those files are shelved.
6665
6665
6666 In bare shelve (when no files are specified, without interactive,
6666 In bare shelve (when no files are specified, without interactive,
6667 include and exclude option), shelving remembers information if the
6667 include and exclude option), shelving remembers information if the
6668 working directory was on newly created branch, in other words working
6668 working directory was on newly created branch, in other words working
6669 directory was on different branch than its first parent. In this
6669 directory was on different branch than its first parent. In this
6670 situation unshelving restores branch information to the working directory.
6670 situation unshelving restores branch information to the working directory.
6671
6671
6672 Each shelved change has a name that makes it easier to find later.
6672 Each shelved change has a name that makes it easier to find later.
6673 The name of a shelved change defaults to being based on the active
6673 The name of a shelved change defaults to being based on the active
6674 bookmark, or if there is no active bookmark, the current named
6674 bookmark, or if there is no active bookmark, the current named
6675 branch. To specify a different name, use ``--name``.
6675 branch. To specify a different name, use ``--name``.
6676
6676
6677 To see a list of existing shelved changes, use the ``--list``
6677 To see a list of existing shelved changes, use the ``--list``
6678 option. For each shelved change, this will print its name, age,
6678 option. For each shelved change, this will print its name, age,
6679 and description; use ``--patch`` or ``--stat`` for more details.
6679 and description; use ``--patch`` or ``--stat`` for more details.
6680
6680
6681 To delete specific shelved changes, use ``--delete``. To delete
6681 To delete specific shelved changes, use ``--delete``. To delete
6682 all shelved changes, use ``--cleanup``.
6682 all shelved changes, use ``--cleanup``.
6683 """
6683 """
6684 opts = pycompat.byteskwargs(opts)
6684 opts = pycompat.byteskwargs(opts)
6685 allowables = [
6685 allowables = [
6686 (b'addremove', {b'create'}), # 'create' is pseudo action
6686 (b'addremove', {b'create'}), # 'create' is pseudo action
6687 (b'unknown', {b'create'}),
6687 (b'unknown', {b'create'}),
6688 (b'cleanup', {b'cleanup'}),
6688 (b'cleanup', {b'cleanup'}),
6689 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6689 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6690 (b'delete', {b'delete'}),
6690 (b'delete', {b'delete'}),
6691 (b'edit', {b'create'}),
6691 (b'edit', {b'create'}),
6692 (b'keep', {b'create'}),
6692 (b'keep', {b'create'}),
6693 (b'list', {b'list'}),
6693 (b'list', {b'list'}),
6694 (b'message', {b'create'}),
6694 (b'message', {b'create'}),
6695 (b'name', {b'create'}),
6695 (b'name', {b'create'}),
6696 (b'patch', {b'patch', b'list'}),
6696 (b'patch', {b'patch', b'list'}),
6697 (b'stat', {b'stat', b'list'}),
6697 (b'stat', {b'stat', b'list'}),
6698 ]
6698 ]
6699
6699
6700 def checkopt(opt):
6700 def checkopt(opt):
6701 if opts.get(opt):
6701 if opts.get(opt):
6702 for i, allowable in allowables:
6702 for i, allowable in allowables:
6703 if opts[i] and opt not in allowable:
6703 if opts[i] and opt not in allowable:
6704 raise error.InputError(
6704 raise error.InputError(
6705 _(
6705 _(
6706 b"options '--%s' and '--%s' may not be "
6706 b"options '--%s' and '--%s' may not be "
6707 b"used together"
6707 b"used together"
6708 )
6708 )
6709 % (opt, i)
6709 % (opt, i)
6710 )
6710 )
6711 return True
6711 return True
6712
6712
6713 if checkopt(b'cleanup'):
6713 if checkopt(b'cleanup'):
6714 if pats:
6714 if pats:
6715 raise error.InputError(
6715 raise error.InputError(
6716 _(b"cannot specify names when using '--cleanup'")
6716 _(b"cannot specify names when using '--cleanup'")
6717 )
6717 )
6718 return shelvemod.cleanupcmd(ui, repo)
6718 return shelvemod.cleanupcmd(ui, repo)
6719 elif checkopt(b'delete'):
6719 elif checkopt(b'delete'):
6720 return shelvemod.deletecmd(ui, repo, pats)
6720 return shelvemod.deletecmd(ui, repo, pats)
6721 elif checkopt(b'list'):
6721 elif checkopt(b'list'):
6722 return shelvemod.listcmd(ui, repo, pats, opts)
6722 return shelvemod.listcmd(ui, repo, pats, opts)
6723 elif checkopt(b'patch') or checkopt(b'stat'):
6723 elif checkopt(b'patch') or checkopt(b'stat'):
6724 return shelvemod.patchcmds(ui, repo, pats, opts)
6724 return shelvemod.patchcmds(ui, repo, pats, opts)
6725 else:
6725 else:
6726 return shelvemod.createcmd(ui, repo, pats, opts)
6726 return shelvemod.createcmd(ui, repo, pats, opts)
6727
6727
6728
6728
6729 _NOTTERSE = b'nothing'
6729 _NOTTERSE = b'nothing'
6730
6730
6731
6731
6732 @command(
6732 @command(
6733 b'status|st',
6733 b'status|st',
6734 [
6734 [
6735 (b'A', b'all', None, _(b'show status of all files')),
6735 (b'A', b'all', None, _(b'show status of all files')),
6736 (b'm', b'modified', None, _(b'show only modified files')),
6736 (b'm', b'modified', None, _(b'show only modified files')),
6737 (b'a', b'added', None, _(b'show only added files')),
6737 (b'a', b'added', None, _(b'show only added files')),
6738 (b'r', b'removed', None, _(b'show only removed files')),
6738 (b'r', b'removed', None, _(b'show only removed files')),
6739 (b'd', b'deleted', None, _(b'show only missing files')),
6739 (b'd', b'deleted', None, _(b'show only missing files')),
6740 (b'c', b'clean', None, _(b'show only files without changes')),
6740 (b'c', b'clean', None, _(b'show only files without changes')),
6741 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6741 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6742 (b'i', b'ignored', None, _(b'show only ignored files')),
6742 (b'i', b'ignored', None, _(b'show only ignored files')),
6743 (b'n', b'no-status', None, _(b'hide status prefix')),
6743 (b'n', b'no-status', None, _(b'hide status prefix')),
6744 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6744 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6745 (
6745 (
6746 b'C',
6746 b'C',
6747 b'copies',
6747 b'copies',
6748 None,
6748 None,
6749 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6749 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6750 ),
6750 ),
6751 (
6751 (
6752 b'0',
6752 b'0',
6753 b'print0',
6753 b'print0',
6754 None,
6754 None,
6755 _(b'end filenames with NUL, for use with xargs'),
6755 _(b'end filenames with NUL, for use with xargs'),
6756 ),
6756 ),
6757 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6757 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6758 (
6758 (
6759 b'',
6759 b'',
6760 b'change',
6760 b'change',
6761 b'',
6761 b'',
6762 _(b'list the changed files of a revision'),
6762 _(b'list the changed files of a revision'),
6763 _(b'REV'),
6763 _(b'REV'),
6764 ),
6764 ),
6765 ]
6765 ]
6766 + walkopts
6766 + walkopts
6767 + subrepoopts
6767 + subrepoopts
6768 + formatteropts,
6768 + formatteropts,
6769 _(b'[OPTION]... [FILE]...'),
6769 _(b'[OPTION]... [FILE]...'),
6770 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6770 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6771 helpbasic=True,
6771 helpbasic=True,
6772 inferrepo=True,
6772 inferrepo=True,
6773 intents={INTENT_READONLY},
6773 intents={INTENT_READONLY},
6774 )
6774 )
6775 def status(ui, repo, *pats, **opts):
6775 def status(ui, repo, *pats, **opts):
6776 """show changed files in the working directory
6776 """show changed files in the working directory
6777
6777
6778 Show status of files in the repository. If names are given, only
6778 Show status of files in the repository. If names are given, only
6779 files that match are shown. Files that are clean or ignored or
6779 files that match are shown. Files that are clean or ignored or
6780 the source of a copy/move operation, are not listed unless
6780 the source of a copy/move operation, are not listed unless
6781 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6781 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6782 Unless options described with "show only ..." are given, the
6782 Unless options described with "show only ..." are given, the
6783 options -mardu are used.
6783 options -mardu are used.
6784
6784
6785 Option -q/--quiet hides untracked (unknown and ignored) files
6785 Option -q/--quiet hides untracked (unknown and ignored) files
6786 unless explicitly requested with -u/--unknown or -i/--ignored.
6786 unless explicitly requested with -u/--unknown or -i/--ignored.
6787
6787
6788 .. note::
6788 .. note::
6789
6789
6790 :hg:`status` may appear to disagree with diff if permissions have
6790 :hg:`status` may appear to disagree with diff if permissions have
6791 changed or a merge has occurred. The standard diff format does
6791 changed or a merge has occurred. The standard diff format does
6792 not report permission changes and diff only reports changes
6792 not report permission changes and diff only reports changes
6793 relative to one merge parent.
6793 relative to one merge parent.
6794
6794
6795 If one revision is given, it is used as the base revision.
6795 If one revision is given, it is used as the base revision.
6796 If two revisions are given, the differences between them are
6796 If two revisions are given, the differences between them are
6797 shown. The --change option can also be used as a shortcut to list
6797 shown. The --change option can also be used as a shortcut to list
6798 the changed files of a revision from its first parent.
6798 the changed files of a revision from its first parent.
6799
6799
6800 The codes used to show the status of files are::
6800 The codes used to show the status of files are::
6801
6801
6802 M = modified
6802 M = modified
6803 A = added
6803 A = added
6804 R = removed
6804 R = removed
6805 C = clean
6805 C = clean
6806 ! = missing (deleted by non-hg command, but still tracked)
6806 ! = missing (deleted by non-hg command, but still tracked)
6807 ? = not tracked
6807 ? = not tracked
6808 I = ignored
6808 I = ignored
6809 = origin of the previous file (with --copies)
6809 = origin of the previous file (with --copies)
6810
6810
6811 .. container:: verbose
6811 .. container:: verbose
6812
6812
6813 The -t/--terse option abbreviates the output by showing only the directory
6813 The -t/--terse option abbreviates the output by showing only the directory
6814 name if all the files in it share the same status. The option takes an
6814 name if all the files in it share the same status. The option takes an
6815 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6815 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6816 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6816 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6817 for 'ignored' and 'c' for clean.
6817 for 'ignored' and 'c' for clean.
6818
6818
6819 It abbreviates only those statuses which are passed. Note that clean and
6819 It abbreviates only those statuses which are passed. Note that clean and
6820 ignored files are not displayed with '--terse ic' unless the -c/--clean
6820 ignored files are not displayed with '--terse ic' unless the -c/--clean
6821 and -i/--ignored options are also used.
6821 and -i/--ignored options are also used.
6822
6822
6823 The -v/--verbose option shows information when the repository is in an
6823 The -v/--verbose option shows information when the repository is in an
6824 unfinished merge, shelve, rebase state etc. You can have this behavior
6824 unfinished merge, shelve, rebase state etc. You can have this behavior
6825 turned on by default by enabling the ``commands.status.verbose`` option.
6825 turned on by default by enabling the ``commands.status.verbose`` option.
6826
6826
6827 You can skip displaying some of these states by setting
6827 You can skip displaying some of these states by setting
6828 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6828 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6829 'histedit', 'merge', 'rebase', or 'unshelve'.
6829 'histedit', 'merge', 'rebase', or 'unshelve'.
6830
6830
6831 Template:
6831 Template:
6832
6832
6833 The following keywords are supported in addition to the common template
6833 The following keywords are supported in addition to the common template
6834 keywords and functions. See also :hg:`help templates`.
6834 keywords and functions. See also :hg:`help templates`.
6835
6835
6836 :path: String. Repository-absolute path of the file.
6836 :path: String. Repository-absolute path of the file.
6837 :source: String. Repository-absolute path of the file originated from.
6837 :source: String. Repository-absolute path of the file originated from.
6838 Available if ``--copies`` is specified.
6838 Available if ``--copies`` is specified.
6839 :status: String. Character denoting file's status.
6839 :status: String. Character denoting file's status.
6840
6840
6841 Examples:
6841 Examples:
6842
6842
6843 - show changes in the working directory relative to a
6843 - show changes in the working directory relative to a
6844 changeset::
6844 changeset::
6845
6845
6846 hg status --rev 9353
6846 hg status --rev 9353
6847
6847
6848 - show changes in the working directory relative to the
6848 - show changes in the working directory relative to the
6849 current directory (see :hg:`help patterns` for more information)::
6849 current directory (see :hg:`help patterns` for more information)::
6850
6850
6851 hg status re:
6851 hg status re:
6852
6852
6853 - show all changes including copies in an existing changeset::
6853 - show all changes including copies in an existing changeset::
6854
6854
6855 hg status --copies --change 9353
6855 hg status --copies --change 9353
6856
6856
6857 - get a NUL separated list of added files, suitable for xargs::
6857 - get a NUL separated list of added files, suitable for xargs::
6858
6858
6859 hg status -an0
6859 hg status -an0
6860
6860
6861 - show more information about the repository status, abbreviating
6861 - show more information about the repository status, abbreviating
6862 added, removed, modified, deleted, and untracked paths::
6862 added, removed, modified, deleted, and untracked paths::
6863
6863
6864 hg status -v -t mardu
6864 hg status -v -t mardu
6865
6865
6866 Returns 0 on success.
6866 Returns 0 on success.
6867
6867
6868 """
6868 """
6869
6869
6870 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6870 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6871 opts = pycompat.byteskwargs(opts)
6871 opts = pycompat.byteskwargs(opts)
6872 revs = opts.get(b'rev')
6872 revs = opts.get(b'rev')
6873 change = opts.get(b'change')
6873 change = opts.get(b'change')
6874 terse = opts.get(b'terse')
6874 terse = opts.get(b'terse')
6875 if terse is _NOTTERSE:
6875 if terse is _NOTTERSE:
6876 if revs:
6876 if revs:
6877 terse = b''
6877 terse = b''
6878 else:
6878 else:
6879 terse = ui.config(b'commands', b'status.terse')
6879 terse = ui.config(b'commands', b'status.terse')
6880
6880
6881 if revs and terse:
6881 if revs and terse:
6882 msg = _(b'cannot use --terse with --rev')
6882 msg = _(b'cannot use --terse with --rev')
6883 raise error.InputError(msg)
6883 raise error.InputError(msg)
6884 elif change:
6884 elif change:
6885 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6885 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6886 ctx2 = scmutil.revsingle(repo, change, None)
6886 ctx2 = scmutil.revsingle(repo, change, None)
6887 ctx1 = ctx2.p1()
6887 ctx1 = ctx2.p1()
6888 else:
6888 else:
6889 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6889 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6890 ctx1, ctx2 = scmutil.revpair(repo, revs)
6890 ctx1, ctx2 = scmutil.revpair(repo, revs)
6891
6891
6892 forcerelativevalue = None
6892 forcerelativevalue = None
6893 if ui.hasconfig(b'commands', b'status.relative'):
6893 if ui.hasconfig(b'commands', b'status.relative'):
6894 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6894 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6895 uipathfn = scmutil.getuipathfn(
6895 uipathfn = scmutil.getuipathfn(
6896 repo,
6896 repo,
6897 legacyrelativevalue=bool(pats),
6897 legacyrelativevalue=bool(pats),
6898 forcerelativevalue=forcerelativevalue,
6898 forcerelativevalue=forcerelativevalue,
6899 )
6899 )
6900
6900
6901 if opts.get(b'print0'):
6901 if opts.get(b'print0'):
6902 end = b'\0'
6902 end = b'\0'
6903 else:
6903 else:
6904 end = b'\n'
6904 end = b'\n'
6905 states = b'modified added removed deleted unknown ignored clean'.split()
6905 states = b'modified added removed deleted unknown ignored clean'.split()
6906 show = [k for k in states if opts.get(k)]
6906 show = [k for k in states if opts.get(k)]
6907 if opts.get(b'all'):
6907 if opts.get(b'all'):
6908 show += ui.quiet and (states[:4] + [b'clean']) or states
6908 show += ui.quiet and (states[:4] + [b'clean']) or states
6909
6909
6910 if not show:
6910 if not show:
6911 if ui.quiet:
6911 if ui.quiet:
6912 show = states[:4]
6912 show = states[:4]
6913 else:
6913 else:
6914 show = states[:5]
6914 show = states[:5]
6915
6915
6916 m = scmutil.match(ctx2, pats, opts)
6916 m = scmutil.match(ctx2, pats, opts)
6917 if terse:
6917 if terse:
6918 # we need to compute clean and unknown to terse
6918 # we need to compute clean and unknown to terse
6919 stat = repo.status(
6919 stat = repo.status(
6920 ctx1.node(),
6920 ctx1.node(),
6921 ctx2.node(),
6921 ctx2.node(),
6922 m,
6922 m,
6923 b'ignored' in show or b'i' in terse,
6923 b'ignored' in show or b'i' in terse,
6924 clean=True,
6924 clean=True,
6925 unknown=True,
6925 unknown=True,
6926 listsubrepos=opts.get(b'subrepos'),
6926 listsubrepos=opts.get(b'subrepos'),
6927 )
6927 )
6928
6928
6929 stat = cmdutil.tersedir(stat, terse)
6929 stat = cmdutil.tersedir(stat, terse)
6930 else:
6930 else:
6931 stat = repo.status(
6931 stat = repo.status(
6932 ctx1.node(),
6932 ctx1.node(),
6933 ctx2.node(),
6933 ctx2.node(),
6934 m,
6934 m,
6935 b'ignored' in show,
6935 b'ignored' in show,
6936 b'clean' in show,
6936 b'clean' in show,
6937 b'unknown' in show,
6937 b'unknown' in show,
6938 opts.get(b'subrepos'),
6938 opts.get(b'subrepos'),
6939 )
6939 )
6940
6940
6941 changestates = zip(
6941 changestates = zip(
6942 states,
6942 states,
6943 pycompat.iterbytestr(b'MAR!?IC'),
6943 pycompat.iterbytestr(b'MAR!?IC'),
6944 [getattr(stat, s.decode('utf8')) for s in states],
6944 [getattr(stat, s.decode('utf8')) for s in states],
6945 )
6945 )
6946
6946
6947 copy = {}
6947 copy = {}
6948 if (
6948 if (
6949 opts.get(b'all')
6949 opts.get(b'all')
6950 or opts.get(b'copies')
6950 or opts.get(b'copies')
6951 or ui.configbool(b'ui', b'statuscopies')
6951 or ui.configbool(b'ui', b'statuscopies')
6952 ) and not opts.get(b'no_status'):
6952 ) and not opts.get(b'no_status'):
6953 copy = copies.pathcopies(ctx1, ctx2, m)
6953 copy = copies.pathcopies(ctx1, ctx2, m)
6954
6954
6955 morestatus = None
6955 morestatus = None
6956 if (
6956 if (
6957 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
6957 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
6958 and not ui.plain()
6958 and not ui.plain()
6959 and not opts.get(b'print0')
6959 and not opts.get(b'print0')
6960 ):
6960 ):
6961 morestatus = cmdutil.readmorestatus(repo)
6961 morestatus = cmdutil.readmorestatus(repo)
6962
6962
6963 ui.pager(b'status')
6963 ui.pager(b'status')
6964 fm = ui.formatter(b'status', opts)
6964 fm = ui.formatter(b'status', opts)
6965 fmt = b'%s' + end
6965 fmt = b'%s' + end
6966 showchar = not opts.get(b'no_status')
6966 showchar = not opts.get(b'no_status')
6967
6967
6968 for state, char, files in changestates:
6968 for state, char, files in changestates:
6969 if state in show:
6969 if state in show:
6970 label = b'status.' + state
6970 label = b'status.' + state
6971 for f in files:
6971 for f in files:
6972 fm.startitem()
6972 fm.startitem()
6973 fm.context(ctx=ctx2)
6973 fm.context(ctx=ctx2)
6974 fm.data(itemtype=b'file', path=f)
6974 fm.data(itemtype=b'file', path=f)
6975 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6975 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6976 fm.plain(fmt % uipathfn(f), label=label)
6976 fm.plain(fmt % uipathfn(f), label=label)
6977 if f in copy:
6977 if f in copy:
6978 fm.data(source=copy[f])
6978 fm.data(source=copy[f])
6979 fm.plain(
6979 fm.plain(
6980 (b' %s' + end) % uipathfn(copy[f]),
6980 (b' %s' + end) % uipathfn(copy[f]),
6981 label=b'status.copied',
6981 label=b'status.copied',
6982 )
6982 )
6983 if morestatus:
6983 if morestatus:
6984 morestatus.formatfile(f, fm)
6984 morestatus.formatfile(f, fm)
6985
6985
6986 if morestatus:
6986 if morestatus:
6987 morestatus.formatfooter(fm)
6987 morestatus.formatfooter(fm)
6988 fm.end()
6988 fm.end()
6989
6989
6990
6990
6991 @command(
6991 @command(
6992 b'summary|sum',
6992 b'summary|sum',
6993 [(b'', b'remote', None, _(b'check for push and pull'))],
6993 [(b'', b'remote', None, _(b'check for push and pull'))],
6994 b'[--remote]',
6994 b'[--remote]',
6995 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6995 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6996 helpbasic=True,
6996 helpbasic=True,
6997 intents={INTENT_READONLY},
6997 intents={INTENT_READONLY},
6998 )
6998 )
6999 def summary(ui, repo, **opts):
6999 def summary(ui, repo, **opts):
7000 """summarize working directory state
7000 """summarize working directory state
7001
7001
7002 This generates a brief summary of the working directory state,
7002 This generates a brief summary of the working directory state,
7003 including parents, branch, commit status, phase and available updates.
7003 including parents, branch, commit status, phase and available updates.
7004
7004
7005 With the --remote option, this will check the default paths for
7005 With the --remote option, this will check the default paths for
7006 incoming and outgoing changes. This can be time-consuming.
7006 incoming and outgoing changes. This can be time-consuming.
7007
7007
7008 Returns 0 on success.
7008 Returns 0 on success.
7009 """
7009 """
7010
7010
7011 opts = pycompat.byteskwargs(opts)
7011 opts = pycompat.byteskwargs(opts)
7012 ui.pager(b'summary')
7012 ui.pager(b'summary')
7013 ctx = repo[None]
7013 ctx = repo[None]
7014 parents = ctx.parents()
7014 parents = ctx.parents()
7015 pnode = parents[0].node()
7015 pnode = parents[0].node()
7016 marks = []
7016 marks = []
7017
7017
7018 try:
7018 try:
7019 ms = mergestatemod.mergestate.read(repo)
7019 ms = mergestatemod.mergestate.read(repo)
7020 except error.UnsupportedMergeRecords as e:
7020 except error.UnsupportedMergeRecords as e:
7021 s = b' '.join(e.recordtypes)
7021 s = b' '.join(e.recordtypes)
7022 ui.warn(
7022 ui.warn(
7023 _(b'warning: merge state has unsupported record types: %s\n') % s
7023 _(b'warning: merge state has unsupported record types: %s\n') % s
7024 )
7024 )
7025 unresolved = []
7025 unresolved = []
7026 else:
7026 else:
7027 unresolved = list(ms.unresolved())
7027 unresolved = list(ms.unresolved())
7028
7028
7029 for p in parents:
7029 for p in parents:
7030 # label with log.changeset (instead of log.parent) since this
7030 # label with log.changeset (instead of log.parent) since this
7031 # shows a working directory parent *changeset*:
7031 # shows a working directory parent *changeset*:
7032 # i18n: column positioning for "hg summary"
7032 # i18n: column positioning for "hg summary"
7033 ui.write(
7033 ui.write(
7034 _(b'parent: %d:%s ') % (p.rev(), p),
7034 _(b'parent: %d:%s ') % (p.rev(), p),
7035 label=logcmdutil.changesetlabels(p),
7035 label=logcmdutil.changesetlabels(p),
7036 )
7036 )
7037 ui.write(b' '.join(p.tags()), label=b'log.tag')
7037 ui.write(b' '.join(p.tags()), label=b'log.tag')
7038 if p.bookmarks():
7038 if p.bookmarks():
7039 marks.extend(p.bookmarks())
7039 marks.extend(p.bookmarks())
7040 if p.rev() == -1:
7040 if p.rev() == -1:
7041 if not len(repo):
7041 if not len(repo):
7042 ui.write(_(b' (empty repository)'))
7042 ui.write(_(b' (empty repository)'))
7043 else:
7043 else:
7044 ui.write(_(b' (no revision checked out)'))
7044 ui.write(_(b' (no revision checked out)'))
7045 if p.obsolete():
7045 if p.obsolete():
7046 ui.write(_(b' (obsolete)'))
7046 ui.write(_(b' (obsolete)'))
7047 if p.isunstable():
7047 if p.isunstable():
7048 instabilities = (
7048 instabilities = (
7049 ui.label(instability, b'trouble.%s' % instability)
7049 ui.label(instability, b'trouble.%s' % instability)
7050 for instability in p.instabilities()
7050 for instability in p.instabilities()
7051 )
7051 )
7052 ui.write(b' (' + b', '.join(instabilities) + b')')
7052 ui.write(b' (' + b', '.join(instabilities) + b')')
7053 ui.write(b'\n')
7053 ui.write(b'\n')
7054 if p.description():
7054 if p.description():
7055 ui.status(
7055 ui.status(
7056 b' ' + p.description().splitlines()[0].strip() + b'\n',
7056 b' ' + p.description().splitlines()[0].strip() + b'\n',
7057 label=b'log.summary',
7057 label=b'log.summary',
7058 )
7058 )
7059
7059
7060 branch = ctx.branch()
7060 branch = ctx.branch()
7061 bheads = repo.branchheads(branch)
7061 bheads = repo.branchheads(branch)
7062 # i18n: column positioning for "hg summary"
7062 # i18n: column positioning for "hg summary"
7063 m = _(b'branch: %s\n') % branch
7063 m = _(b'branch: %s\n') % branch
7064 if branch != b'default':
7064 if branch != b'default':
7065 ui.write(m, label=b'log.branch')
7065 ui.write(m, label=b'log.branch')
7066 else:
7066 else:
7067 ui.status(m, label=b'log.branch')
7067 ui.status(m, label=b'log.branch')
7068
7068
7069 if marks:
7069 if marks:
7070 active = repo._activebookmark
7070 active = repo._activebookmark
7071 # i18n: column positioning for "hg summary"
7071 # i18n: column positioning for "hg summary"
7072 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7072 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7073 if active is not None:
7073 if active is not None:
7074 if active in marks:
7074 if active in marks:
7075 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7075 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7076 marks.remove(active)
7076 marks.remove(active)
7077 else:
7077 else:
7078 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7078 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7079 for m in marks:
7079 for m in marks:
7080 ui.write(b' ' + m, label=b'log.bookmark')
7080 ui.write(b' ' + m, label=b'log.bookmark')
7081 ui.write(b'\n', label=b'log.bookmark')
7081 ui.write(b'\n', label=b'log.bookmark')
7082
7082
7083 status = repo.status(unknown=True)
7083 status = repo.status(unknown=True)
7084
7084
7085 c = repo.dirstate.copies()
7085 c = repo.dirstate.copies()
7086 copied, renamed = [], []
7086 copied, renamed = [], []
7087 for d, s in pycompat.iteritems(c):
7087 for d, s in pycompat.iteritems(c):
7088 if s in status.removed:
7088 if s in status.removed:
7089 status.removed.remove(s)
7089 status.removed.remove(s)
7090 renamed.append(d)
7090 renamed.append(d)
7091 else:
7091 else:
7092 copied.append(d)
7092 copied.append(d)
7093 if d in status.added:
7093 if d in status.added:
7094 status.added.remove(d)
7094 status.added.remove(d)
7095
7095
7096 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7096 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7097
7097
7098 labels = [
7098 labels = [
7099 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7099 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7100 (ui.label(_(b'%d added'), b'status.added'), status.added),
7100 (ui.label(_(b'%d added'), b'status.added'), status.added),
7101 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7101 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7102 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7102 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7103 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7103 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7104 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7104 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7105 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7105 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7106 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7106 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7107 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7107 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7108 ]
7108 ]
7109 t = []
7109 t = []
7110 for l, s in labels:
7110 for l, s in labels:
7111 if s:
7111 if s:
7112 t.append(l % len(s))
7112 t.append(l % len(s))
7113
7113
7114 t = b', '.join(t)
7114 t = b', '.join(t)
7115 cleanworkdir = False
7115 cleanworkdir = False
7116
7116
7117 if repo.vfs.exists(b'graftstate'):
7117 if repo.vfs.exists(b'graftstate'):
7118 t += _(b' (graft in progress)')
7118 t += _(b' (graft in progress)')
7119 if repo.vfs.exists(b'updatestate'):
7119 if repo.vfs.exists(b'updatestate'):
7120 t += _(b' (interrupted update)')
7120 t += _(b' (interrupted update)')
7121 elif len(parents) > 1:
7121 elif len(parents) > 1:
7122 t += _(b' (merge)')
7122 t += _(b' (merge)')
7123 elif branch != parents[0].branch():
7123 elif branch != parents[0].branch():
7124 t += _(b' (new branch)')
7124 t += _(b' (new branch)')
7125 elif parents[0].closesbranch() and pnode in repo.branchheads(
7125 elif parents[0].closesbranch() and pnode in repo.branchheads(
7126 branch, closed=True
7126 branch, closed=True
7127 ):
7127 ):
7128 t += _(b' (head closed)')
7128 t += _(b' (head closed)')
7129 elif not (
7129 elif not (
7130 status.modified
7130 status.modified
7131 or status.added
7131 or status.added
7132 or status.removed
7132 or status.removed
7133 or renamed
7133 or renamed
7134 or copied
7134 or copied
7135 or subs
7135 or subs
7136 ):
7136 ):
7137 t += _(b' (clean)')
7137 t += _(b' (clean)')
7138 cleanworkdir = True
7138 cleanworkdir = True
7139 elif pnode not in bheads:
7139 elif pnode not in bheads:
7140 t += _(b' (new branch head)')
7140 t += _(b' (new branch head)')
7141
7141
7142 if parents:
7142 if parents:
7143 pendingphase = max(p.phase() for p in parents)
7143 pendingphase = max(p.phase() for p in parents)
7144 else:
7144 else:
7145 pendingphase = phases.public
7145 pendingphase = phases.public
7146
7146
7147 if pendingphase > phases.newcommitphase(ui):
7147 if pendingphase > phases.newcommitphase(ui):
7148 t += b' (%s)' % phases.phasenames[pendingphase]
7148 t += b' (%s)' % phases.phasenames[pendingphase]
7149
7149
7150 if cleanworkdir:
7150 if cleanworkdir:
7151 # i18n: column positioning for "hg summary"
7151 # i18n: column positioning for "hg summary"
7152 ui.status(_(b'commit: %s\n') % t.strip())
7152 ui.status(_(b'commit: %s\n') % t.strip())
7153 else:
7153 else:
7154 # i18n: column positioning for "hg summary"
7154 # i18n: column positioning for "hg summary"
7155 ui.write(_(b'commit: %s\n') % t.strip())
7155 ui.write(_(b'commit: %s\n') % t.strip())
7156
7156
7157 # all ancestors of branch heads - all ancestors of parent = new csets
7157 # all ancestors of branch heads - all ancestors of parent = new csets
7158 new = len(
7158 new = len(
7159 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7159 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7160 )
7160 )
7161
7161
7162 if new == 0:
7162 if new == 0:
7163 # i18n: column positioning for "hg summary"
7163 # i18n: column positioning for "hg summary"
7164 ui.status(_(b'update: (current)\n'))
7164 ui.status(_(b'update: (current)\n'))
7165 elif pnode not in bheads:
7165 elif pnode not in bheads:
7166 # i18n: column positioning for "hg summary"
7166 # i18n: column positioning for "hg summary"
7167 ui.write(_(b'update: %d new changesets (update)\n') % new)
7167 ui.write(_(b'update: %d new changesets (update)\n') % new)
7168 else:
7168 else:
7169 # i18n: column positioning for "hg summary"
7169 # i18n: column positioning for "hg summary"
7170 ui.write(
7170 ui.write(
7171 _(b'update: %d new changesets, %d branch heads (merge)\n')
7171 _(b'update: %d new changesets, %d branch heads (merge)\n')
7172 % (new, len(bheads))
7172 % (new, len(bheads))
7173 )
7173 )
7174
7174
7175 t = []
7175 t = []
7176 draft = len(repo.revs(b'draft()'))
7176 draft = len(repo.revs(b'draft()'))
7177 if draft:
7177 if draft:
7178 t.append(_(b'%d draft') % draft)
7178 t.append(_(b'%d draft') % draft)
7179 secret = len(repo.revs(b'secret()'))
7179 secret = len(repo.revs(b'secret()'))
7180 if secret:
7180 if secret:
7181 t.append(_(b'%d secret') % secret)
7181 t.append(_(b'%d secret') % secret)
7182
7182
7183 if draft or secret:
7183 if draft or secret:
7184 ui.status(_(b'phases: %s\n') % b', '.join(t))
7184 ui.status(_(b'phases: %s\n') % b', '.join(t))
7185
7185
7186 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7186 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7187 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7187 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7188 numtrouble = len(repo.revs(trouble + b"()"))
7188 numtrouble = len(repo.revs(trouble + b"()"))
7189 # We write all the possibilities to ease translation
7189 # We write all the possibilities to ease translation
7190 troublemsg = {
7190 troublemsg = {
7191 b"orphan": _(b"orphan: %d changesets"),
7191 b"orphan": _(b"orphan: %d changesets"),
7192 b"contentdivergent": _(b"content-divergent: %d changesets"),
7192 b"contentdivergent": _(b"content-divergent: %d changesets"),
7193 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7193 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7194 }
7194 }
7195 if numtrouble > 0:
7195 if numtrouble > 0:
7196 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7196 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7197
7197
7198 cmdutil.summaryhooks(ui, repo)
7198 cmdutil.summaryhooks(ui, repo)
7199
7199
7200 if opts.get(b'remote'):
7200 if opts.get(b'remote'):
7201 needsincoming, needsoutgoing = True, True
7201 needsincoming, needsoutgoing = True, True
7202 else:
7202 else:
7203 needsincoming, needsoutgoing = False, False
7203 needsincoming, needsoutgoing = False, False
7204 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7204 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7205 if i:
7205 if i:
7206 needsincoming = True
7206 needsincoming = True
7207 if o:
7207 if o:
7208 needsoutgoing = True
7208 needsoutgoing = True
7209 if not needsincoming and not needsoutgoing:
7209 if not needsincoming and not needsoutgoing:
7210 return
7210 return
7211
7211
7212 def getincoming():
7212 def getincoming():
7213 source, branches = hg.parseurl(ui.expandpath(b'default'))
7213 source, branches = hg.parseurl(ui.expandpath(b'default'))
7214 sbranch = branches[0]
7214 sbranch = branches[0]
7215 try:
7215 try:
7216 other = hg.peer(repo, {}, source)
7216 other = hg.peer(repo, {}, source)
7217 except error.RepoError:
7217 except error.RepoError:
7218 if opts.get(b'remote'):
7218 if opts.get(b'remote'):
7219 raise
7219 raise
7220 return source, sbranch, None, None, None
7220 return source, sbranch, None, None, None
7221 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7221 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7222 if revs:
7222 if revs:
7223 revs = [other.lookup(rev) for rev in revs]
7223 revs = [other.lookup(rev) for rev in revs]
7224 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
7224 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
7225 repo.ui.pushbuffer()
7225 repo.ui.pushbuffer()
7226 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7226 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7227 repo.ui.popbuffer()
7227 repo.ui.popbuffer()
7228 return source, sbranch, other, commoninc, commoninc[1]
7228 return source, sbranch, other, commoninc, commoninc[1]
7229
7229
7230 if needsincoming:
7230 if needsincoming:
7231 source, sbranch, sother, commoninc, incoming = getincoming()
7231 source, sbranch, sother, commoninc, incoming = getincoming()
7232 else:
7232 else:
7233 source = sbranch = sother = commoninc = incoming = None
7233 source = sbranch = sother = commoninc = incoming = None
7234
7234
7235 def getoutgoing():
7235 def getoutgoing():
7236 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
7236 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
7237 dbranch = branches[0]
7237 dbranch = branches[0]
7238 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
7238 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
7239 if source != dest:
7239 if source != dest:
7240 try:
7240 try:
7241 dother = hg.peer(repo, {}, dest)
7241 dother = hg.peer(repo, {}, dest)
7242 except error.RepoError:
7242 except error.RepoError:
7243 if opts.get(b'remote'):
7243 if opts.get(b'remote'):
7244 raise
7244 raise
7245 return dest, dbranch, None, None
7245 return dest, dbranch, None, None
7246 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7246 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7247 elif sother is None:
7247 elif sother is None:
7248 # there is no explicit destination peer, but source one is invalid
7248 # there is no explicit destination peer, but source one is invalid
7249 return dest, dbranch, None, None
7249 return dest, dbranch, None, None
7250 else:
7250 else:
7251 dother = sother
7251 dother = sother
7252 if source != dest or (sbranch is not None and sbranch != dbranch):
7252 if source != dest or (sbranch is not None and sbranch != dbranch):
7253 common = None
7253 common = None
7254 else:
7254 else:
7255 common = commoninc
7255 common = commoninc
7256 if revs:
7256 if revs:
7257 revs = [repo.lookup(rev) for rev in revs]
7257 revs = [repo.lookup(rev) for rev in revs]
7258 repo.ui.pushbuffer()
7258 repo.ui.pushbuffer()
7259 outgoing = discovery.findcommonoutgoing(
7259 outgoing = discovery.findcommonoutgoing(
7260 repo, dother, onlyheads=revs, commoninc=common
7260 repo, dother, onlyheads=revs, commoninc=common
7261 )
7261 )
7262 repo.ui.popbuffer()
7262 repo.ui.popbuffer()
7263 return dest, dbranch, dother, outgoing
7263 return dest, dbranch, dother, outgoing
7264
7264
7265 if needsoutgoing:
7265 if needsoutgoing:
7266 dest, dbranch, dother, outgoing = getoutgoing()
7266 dest, dbranch, dother, outgoing = getoutgoing()
7267 else:
7267 else:
7268 dest = dbranch = dother = outgoing = None
7268 dest = dbranch = dother = outgoing = None
7269
7269
7270 if opts.get(b'remote'):
7270 if opts.get(b'remote'):
7271 t = []
7271 t = []
7272 if incoming:
7272 if incoming:
7273 t.append(_(b'1 or more incoming'))
7273 t.append(_(b'1 or more incoming'))
7274 o = outgoing.missing
7274 o = outgoing.missing
7275 if o:
7275 if o:
7276 t.append(_(b'%d outgoing') % len(o))
7276 t.append(_(b'%d outgoing') % len(o))
7277 other = dother or sother
7277 other = dother or sother
7278 if b'bookmarks' in other.listkeys(b'namespaces'):
7278 if b'bookmarks' in other.listkeys(b'namespaces'):
7279 counts = bookmarks.summary(repo, other)
7279 counts = bookmarks.summary(repo, other)
7280 if counts[0] > 0:
7280 if counts[0] > 0:
7281 t.append(_(b'%d incoming bookmarks') % counts[0])
7281 t.append(_(b'%d incoming bookmarks') % counts[0])
7282 if counts[1] > 0:
7282 if counts[1] > 0:
7283 t.append(_(b'%d outgoing bookmarks') % counts[1])
7283 t.append(_(b'%d outgoing bookmarks') % counts[1])
7284
7284
7285 if t:
7285 if t:
7286 # i18n: column positioning for "hg summary"
7286 # i18n: column positioning for "hg summary"
7287 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7287 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7288 else:
7288 else:
7289 # i18n: column positioning for "hg summary"
7289 # i18n: column positioning for "hg summary"
7290 ui.status(_(b'remote: (synced)\n'))
7290 ui.status(_(b'remote: (synced)\n'))
7291
7291
7292 cmdutil.summaryremotehooks(
7292 cmdutil.summaryremotehooks(
7293 ui,
7293 ui,
7294 repo,
7294 repo,
7295 opts,
7295 opts,
7296 (
7296 (
7297 (source, sbranch, sother, commoninc),
7297 (source, sbranch, sother, commoninc),
7298 (dest, dbranch, dother, outgoing),
7298 (dest, dbranch, dother, outgoing),
7299 ),
7299 ),
7300 )
7300 )
7301
7301
7302
7302
7303 @command(
7303 @command(
7304 b'tag',
7304 b'tag',
7305 [
7305 [
7306 (b'f', b'force', None, _(b'force tag')),
7306 (b'f', b'force', None, _(b'force tag')),
7307 (b'l', b'local', None, _(b'make the tag local')),
7307 (b'l', b'local', None, _(b'make the tag local')),
7308 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7308 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7309 (b'', b'remove', None, _(b'remove a tag')),
7309 (b'', b'remove', None, _(b'remove a tag')),
7310 # -l/--local is already there, commitopts cannot be used
7310 # -l/--local is already there, commitopts cannot be used
7311 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7311 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7312 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7312 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7313 ]
7313 ]
7314 + commitopts2,
7314 + commitopts2,
7315 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7315 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7316 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7316 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7317 )
7317 )
7318 def tag(ui, repo, name1, *names, **opts):
7318 def tag(ui, repo, name1, *names, **opts):
7319 """add one or more tags for the current or given revision
7319 """add one or more tags for the current or given revision
7320
7320
7321 Name a particular revision using <name>.
7321 Name a particular revision using <name>.
7322
7322
7323 Tags are used to name particular revisions of the repository and are
7323 Tags are used to name particular revisions of the repository and are
7324 very useful to compare different revisions, to go back to significant
7324 very useful to compare different revisions, to go back to significant
7325 earlier versions or to mark branch points as releases, etc. Changing
7325 earlier versions or to mark branch points as releases, etc. Changing
7326 an existing tag is normally disallowed; use -f/--force to override.
7326 an existing tag is normally disallowed; use -f/--force to override.
7327
7327
7328 If no revision is given, the parent of the working directory is
7328 If no revision is given, the parent of the working directory is
7329 used.
7329 used.
7330
7330
7331 To facilitate version control, distribution, and merging of tags,
7331 To facilitate version control, distribution, and merging of tags,
7332 they are stored as a file named ".hgtags" which is managed similarly
7332 they are stored as a file named ".hgtags" which is managed similarly
7333 to other project files and can be hand-edited if necessary. This
7333 to other project files and can be hand-edited if necessary. This
7334 also means that tagging creates a new commit. The file
7334 also means that tagging creates a new commit. The file
7335 ".hg/localtags" is used for local tags (not shared among
7335 ".hg/localtags" is used for local tags (not shared among
7336 repositories).
7336 repositories).
7337
7337
7338 Tag commits are usually made at the head of a branch. If the parent
7338 Tag commits are usually made at the head of a branch. If the parent
7339 of the working directory is not a branch head, :hg:`tag` aborts; use
7339 of the working directory is not a branch head, :hg:`tag` aborts; use
7340 -f/--force to force the tag commit to be based on a non-head
7340 -f/--force to force the tag commit to be based on a non-head
7341 changeset.
7341 changeset.
7342
7342
7343 See :hg:`help dates` for a list of formats valid for -d/--date.
7343 See :hg:`help dates` for a list of formats valid for -d/--date.
7344
7344
7345 Since tag names have priority over branch names during revision
7345 Since tag names have priority over branch names during revision
7346 lookup, using an existing branch name as a tag name is discouraged.
7346 lookup, using an existing branch name as a tag name is discouraged.
7347
7347
7348 Returns 0 on success.
7348 Returns 0 on success.
7349 """
7349 """
7350 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7350 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7351 opts = pycompat.byteskwargs(opts)
7351 opts = pycompat.byteskwargs(opts)
7352 with repo.wlock(), repo.lock():
7352 with repo.wlock(), repo.lock():
7353 rev_ = b"."
7353 rev_ = b"."
7354 names = [t.strip() for t in (name1,) + names]
7354 names = [t.strip() for t in (name1,) + names]
7355 if len(names) != len(set(names)):
7355 if len(names) != len(set(names)):
7356 raise error.InputError(_(b'tag names must be unique'))
7356 raise error.InputError(_(b'tag names must be unique'))
7357 for n in names:
7357 for n in names:
7358 scmutil.checknewlabel(repo, n, b'tag')
7358 scmutil.checknewlabel(repo, n, b'tag')
7359 if not n:
7359 if not n:
7360 raise error.InputError(
7360 raise error.InputError(
7361 _(b'tag names cannot consist entirely of whitespace')
7361 _(b'tag names cannot consist entirely of whitespace')
7362 )
7362 )
7363 if opts.get(b'rev'):
7363 if opts.get(b'rev'):
7364 rev_ = opts[b'rev']
7364 rev_ = opts[b'rev']
7365 message = opts.get(b'message')
7365 message = opts.get(b'message')
7366 if opts.get(b'remove'):
7366 if opts.get(b'remove'):
7367 if opts.get(b'local'):
7367 if opts.get(b'local'):
7368 expectedtype = b'local'
7368 expectedtype = b'local'
7369 else:
7369 else:
7370 expectedtype = b'global'
7370 expectedtype = b'global'
7371
7371
7372 for n in names:
7372 for n in names:
7373 if repo.tagtype(n) == b'global':
7373 if repo.tagtype(n) == b'global':
7374 alltags = tagsmod.findglobaltags(ui, repo)
7374 alltags = tagsmod.findglobaltags(ui, repo)
7375 if alltags[n][0] == nullid:
7375 if alltags[n][0] == nullid:
7376 raise error.InputError(
7376 raise error.InputError(
7377 _(b"tag '%s' is already removed") % n
7377 _(b"tag '%s' is already removed") % n
7378 )
7378 )
7379 if not repo.tagtype(n):
7379 if not repo.tagtype(n):
7380 raise error.InputError(_(b"tag '%s' does not exist") % n)
7380 raise error.InputError(_(b"tag '%s' does not exist") % n)
7381 if repo.tagtype(n) != expectedtype:
7381 if repo.tagtype(n) != expectedtype:
7382 if expectedtype == b'global':
7382 if expectedtype == b'global':
7383 raise error.InputError(
7383 raise error.InputError(
7384 _(b"tag '%s' is not a global tag") % n
7384 _(b"tag '%s' is not a global tag") % n
7385 )
7385 )
7386 else:
7386 else:
7387 raise error.InputError(
7387 raise error.InputError(
7388 _(b"tag '%s' is not a local tag") % n
7388 _(b"tag '%s' is not a local tag") % n
7389 )
7389 )
7390 rev_ = b'null'
7390 rev_ = b'null'
7391 if not message:
7391 if not message:
7392 # we don't translate commit messages
7392 # we don't translate commit messages
7393 message = b'Removed tag %s' % b', '.join(names)
7393 message = b'Removed tag %s' % b', '.join(names)
7394 elif not opts.get(b'force'):
7394 elif not opts.get(b'force'):
7395 for n in names:
7395 for n in names:
7396 if n in repo.tags():
7396 if n in repo.tags():
7397 raise error.InputError(
7397 raise error.InputError(
7398 _(b"tag '%s' already exists (use -f to force)") % n
7398 _(b"tag '%s' already exists (use -f to force)") % n
7399 )
7399 )
7400 if not opts.get(b'local'):
7400 if not opts.get(b'local'):
7401 p1, p2 = repo.dirstate.parents()
7401 p1, p2 = repo.dirstate.parents()
7402 if p2 != nullid:
7402 if p2 != nullid:
7403 raise error.StateError(_(b'uncommitted merge'))
7403 raise error.StateError(_(b'uncommitted merge'))
7404 bheads = repo.branchheads()
7404 bheads = repo.branchheads()
7405 if not opts.get(b'force') and bheads and p1 not in bheads:
7405 if not opts.get(b'force') and bheads and p1 not in bheads:
7406 raise error.InputError(
7406 raise error.InputError(
7407 _(
7407 _(
7408 b'working directory is not at a branch head '
7408 b'working directory is not at a branch head '
7409 b'(use -f to force)'
7409 b'(use -f to force)'
7410 )
7410 )
7411 )
7411 )
7412 node = scmutil.revsingle(repo, rev_).node()
7412 node = scmutil.revsingle(repo, rev_).node()
7413
7413
7414 if not message:
7414 if not message:
7415 # we don't translate commit messages
7415 # we don't translate commit messages
7416 message = b'Added tag %s for changeset %s' % (
7416 message = b'Added tag %s for changeset %s' % (
7417 b', '.join(names),
7417 b', '.join(names),
7418 short(node),
7418 short(node),
7419 )
7419 )
7420
7420
7421 date = opts.get(b'date')
7421 date = opts.get(b'date')
7422 if date:
7422 if date:
7423 date = dateutil.parsedate(date)
7423 date = dateutil.parsedate(date)
7424
7424
7425 if opts.get(b'remove'):
7425 if opts.get(b'remove'):
7426 editform = b'tag.remove'
7426 editform = b'tag.remove'
7427 else:
7427 else:
7428 editform = b'tag.add'
7428 editform = b'tag.add'
7429 editor = cmdutil.getcommiteditor(
7429 editor = cmdutil.getcommiteditor(
7430 editform=editform, **pycompat.strkwargs(opts)
7430 editform=editform, **pycompat.strkwargs(opts)
7431 )
7431 )
7432
7432
7433 # don't allow tagging the null rev
7433 # don't allow tagging the null rev
7434 if (
7434 if (
7435 not opts.get(b'remove')
7435 not opts.get(b'remove')
7436 and scmutil.revsingle(repo, rev_).rev() == nullrev
7436 and scmutil.revsingle(repo, rev_).rev() == nullrev
7437 ):
7437 ):
7438 raise error.InputError(_(b"cannot tag null revision"))
7438 raise error.InputError(_(b"cannot tag null revision"))
7439
7439
7440 tagsmod.tag(
7440 tagsmod.tag(
7441 repo,
7441 repo,
7442 names,
7442 names,
7443 node,
7443 node,
7444 message,
7444 message,
7445 opts.get(b'local'),
7445 opts.get(b'local'),
7446 opts.get(b'user'),
7446 opts.get(b'user'),
7447 date,
7447 date,
7448 editor=editor,
7448 editor=editor,
7449 )
7449 )
7450
7450
7451
7451
7452 @command(
7452 @command(
7453 b'tags',
7453 b'tags',
7454 formatteropts,
7454 formatteropts,
7455 b'',
7455 b'',
7456 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7456 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7457 intents={INTENT_READONLY},
7457 intents={INTENT_READONLY},
7458 )
7458 )
7459 def tags(ui, repo, **opts):
7459 def tags(ui, repo, **opts):
7460 """list repository tags
7460 """list repository tags
7461
7461
7462 This lists both regular and local tags. When the -v/--verbose
7462 This lists both regular and local tags. When the -v/--verbose
7463 switch is used, a third column "local" is printed for local tags.
7463 switch is used, a third column "local" is printed for local tags.
7464 When the -q/--quiet switch is used, only the tag name is printed.
7464 When the -q/--quiet switch is used, only the tag name is printed.
7465
7465
7466 .. container:: verbose
7466 .. container:: verbose
7467
7467
7468 Template:
7468 Template:
7469
7469
7470 The following keywords are supported in addition to the common template
7470 The following keywords are supported in addition to the common template
7471 keywords and functions such as ``{tag}``. See also
7471 keywords and functions such as ``{tag}``. See also
7472 :hg:`help templates`.
7472 :hg:`help templates`.
7473
7473
7474 :type: String. ``local`` for local tags.
7474 :type: String. ``local`` for local tags.
7475
7475
7476 Returns 0 on success.
7476 Returns 0 on success.
7477 """
7477 """
7478
7478
7479 opts = pycompat.byteskwargs(opts)
7479 opts = pycompat.byteskwargs(opts)
7480 ui.pager(b'tags')
7480 ui.pager(b'tags')
7481 fm = ui.formatter(b'tags', opts)
7481 fm = ui.formatter(b'tags', opts)
7482 hexfunc = fm.hexfunc
7482 hexfunc = fm.hexfunc
7483
7483
7484 for t, n in reversed(repo.tagslist()):
7484 for t, n in reversed(repo.tagslist()):
7485 hn = hexfunc(n)
7485 hn = hexfunc(n)
7486 label = b'tags.normal'
7486 label = b'tags.normal'
7487 tagtype = repo.tagtype(t)
7487 tagtype = repo.tagtype(t)
7488 if not tagtype or tagtype == b'global':
7488 if not tagtype or tagtype == b'global':
7489 tagtype = b''
7489 tagtype = b''
7490 else:
7490 else:
7491 label = b'tags.' + tagtype
7491 label = b'tags.' + tagtype
7492
7492
7493 fm.startitem()
7493 fm.startitem()
7494 fm.context(repo=repo)
7494 fm.context(repo=repo)
7495 fm.write(b'tag', b'%s', t, label=label)
7495 fm.write(b'tag', b'%s', t, label=label)
7496 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7496 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7497 fm.condwrite(
7497 fm.condwrite(
7498 not ui.quiet,
7498 not ui.quiet,
7499 b'rev node',
7499 b'rev node',
7500 fmt,
7500 fmt,
7501 repo.changelog.rev(n),
7501 repo.changelog.rev(n),
7502 hn,
7502 hn,
7503 label=label,
7503 label=label,
7504 )
7504 )
7505 fm.condwrite(
7505 fm.condwrite(
7506 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7506 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7507 )
7507 )
7508 fm.plain(b'\n')
7508 fm.plain(b'\n')
7509 fm.end()
7509 fm.end()
7510
7510
7511
7511
7512 @command(
7512 @command(
7513 b'tip',
7513 b'tip',
7514 [
7514 [
7515 (b'p', b'patch', None, _(b'show patch')),
7515 (b'p', b'patch', None, _(b'show patch')),
7516 (b'g', b'git', None, _(b'use git extended diff format')),
7516 (b'g', b'git', None, _(b'use git extended diff format')),
7517 ]
7517 ]
7518 + templateopts,
7518 + templateopts,
7519 _(b'[-p] [-g]'),
7519 _(b'[-p] [-g]'),
7520 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7520 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7521 )
7521 )
7522 def tip(ui, repo, **opts):
7522 def tip(ui, repo, **opts):
7523 """show the tip revision (DEPRECATED)
7523 """show the tip revision (DEPRECATED)
7524
7524
7525 The tip revision (usually just called the tip) is the changeset
7525 The tip revision (usually just called the tip) is the changeset
7526 most recently added to the repository (and therefore the most
7526 most recently added to the repository (and therefore the most
7527 recently changed head).
7527 recently changed head).
7528
7528
7529 If you have just made a commit, that commit will be the tip. If
7529 If you have just made a commit, that commit will be the tip. If
7530 you have just pulled changes from another repository, the tip of
7530 you have just pulled changes from another repository, the tip of
7531 that repository becomes the current tip. The "tip" tag is special
7531 that repository becomes the current tip. The "tip" tag is special
7532 and cannot be renamed or assigned to a different changeset.
7532 and cannot be renamed or assigned to a different changeset.
7533
7533
7534 This command is deprecated, please use :hg:`heads` instead.
7534 This command is deprecated, please use :hg:`heads` instead.
7535
7535
7536 Returns 0 on success.
7536 Returns 0 on success.
7537 """
7537 """
7538 opts = pycompat.byteskwargs(opts)
7538 opts = pycompat.byteskwargs(opts)
7539 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7539 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7540 displayer.show(repo[b'tip'])
7540 displayer.show(repo[b'tip'])
7541 displayer.close()
7541 displayer.close()
7542
7542
7543
7543
7544 @command(
7544 @command(
7545 b'unbundle',
7545 b'unbundle',
7546 [
7546 [
7547 (
7547 (
7548 b'u',
7548 b'u',
7549 b'update',
7549 b'update',
7550 None,
7550 None,
7551 _(b'update to new branch head if changesets were unbundled'),
7551 _(b'update to new branch head if changesets were unbundled'),
7552 )
7552 )
7553 ],
7553 ],
7554 _(b'[-u] FILE...'),
7554 _(b'[-u] FILE...'),
7555 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7555 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7556 )
7556 )
7557 def unbundle(ui, repo, fname1, *fnames, **opts):
7557 def unbundle(ui, repo, fname1, *fnames, **opts):
7558 """apply one or more bundle files
7558 """apply one or more bundle files
7559
7559
7560 Apply one or more bundle files generated by :hg:`bundle`.
7560 Apply one or more bundle files generated by :hg:`bundle`.
7561
7561
7562 Returns 0 on success, 1 if an update has unresolved files.
7562 Returns 0 on success, 1 if an update has unresolved files.
7563 """
7563 """
7564 fnames = (fname1,) + fnames
7564 fnames = (fname1,) + fnames
7565
7565
7566 with repo.lock():
7566 with repo.lock():
7567 for fname in fnames:
7567 for fname in fnames:
7568 f = hg.openpath(ui, fname)
7568 f = hg.openpath(ui, fname)
7569 gen = exchange.readbundle(ui, f, fname)
7569 gen = exchange.readbundle(ui, f, fname)
7570 if isinstance(gen, streamclone.streamcloneapplier):
7570 if isinstance(gen, streamclone.streamcloneapplier):
7571 raise error.InputError(
7571 raise error.InputError(
7572 _(
7572 _(
7573 b'packed bundles cannot be applied with '
7573 b'packed bundles cannot be applied with '
7574 b'"hg unbundle"'
7574 b'"hg unbundle"'
7575 ),
7575 ),
7576 hint=_(b'use "hg debugapplystreamclonebundle"'),
7576 hint=_(b'use "hg debugapplystreamclonebundle"'),
7577 )
7577 )
7578 url = b'bundle:' + fname
7578 url = b'bundle:' + fname
7579 try:
7579 try:
7580 txnname = b'unbundle'
7580 txnname = b'unbundle'
7581 if not isinstance(gen, bundle2.unbundle20):
7581 if not isinstance(gen, bundle2.unbundle20):
7582 txnname = b'unbundle\n%s' % util.hidepassword(url)
7582 txnname = b'unbundle\n%s' % util.hidepassword(url)
7583 with repo.transaction(txnname) as tr:
7583 with repo.transaction(txnname) as tr:
7584 op = bundle2.applybundle(
7584 op = bundle2.applybundle(
7585 repo, gen, tr, source=b'unbundle', url=url
7585 repo, gen, tr, source=b'unbundle', url=url
7586 )
7586 )
7587 except error.BundleUnknownFeatureError as exc:
7587 except error.BundleUnknownFeatureError as exc:
7588 raise error.Abort(
7588 raise error.Abort(
7589 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7589 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7590 hint=_(
7590 hint=_(
7591 b"see https://mercurial-scm.org/"
7591 b"see https://mercurial-scm.org/"
7592 b"wiki/BundleFeature for more "
7592 b"wiki/BundleFeature for more "
7593 b"information"
7593 b"information"
7594 ),
7594 ),
7595 )
7595 )
7596 modheads = bundle2.combinechangegroupresults(op)
7596 modheads = bundle2.combinechangegroupresults(op)
7597
7597
7598 if postincoming(ui, repo, modheads, opts.get('update'), None, None):
7598 if postincoming(ui, repo, modheads, opts.get('update'), None, None):
7599 return 1
7599 return 1
7600 else:
7600 else:
7601 return 0
7601 return 0
7602
7602
7603
7603
7604 @command(
7604 @command(
7605 b'unshelve',
7605 b'unshelve',
7606 [
7606 [
7607 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7607 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7608 (
7608 (
7609 b'c',
7609 b'c',
7610 b'continue',
7610 b'continue',
7611 None,
7611 None,
7612 _(b'continue an incomplete unshelve operation'),
7612 _(b'continue an incomplete unshelve operation'),
7613 ),
7613 ),
7614 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7614 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7615 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7615 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7616 (
7616 (
7617 b'n',
7617 b'n',
7618 b'name',
7618 b'name',
7619 b'',
7619 b'',
7620 _(b'restore shelved change with given name'),
7620 _(b'restore shelved change with given name'),
7621 _(b'NAME'),
7621 _(b'NAME'),
7622 ),
7622 ),
7623 (b't', b'tool', b'', _(b'specify merge tool')),
7623 (b't', b'tool', b'', _(b'specify merge tool')),
7624 (
7624 (
7625 b'',
7625 b'',
7626 b'date',
7626 b'date',
7627 b'',
7627 b'',
7628 _(b'set date for temporary commits (DEPRECATED)'),
7628 _(b'set date for temporary commits (DEPRECATED)'),
7629 _(b'DATE'),
7629 _(b'DATE'),
7630 ),
7630 ),
7631 ],
7631 ],
7632 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7632 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7633 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7633 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7634 )
7634 )
7635 def unshelve(ui, repo, *shelved, **opts):
7635 def unshelve(ui, repo, *shelved, **opts):
7636 """restore a shelved change to the working directory
7636 """restore a shelved change to the working directory
7637
7637
7638 This command accepts an optional name of a shelved change to
7638 This command accepts an optional name of a shelved change to
7639 restore. If none is given, the most recent shelved change is used.
7639 restore. If none is given, the most recent shelved change is used.
7640
7640
7641 If a shelved change is applied successfully, the bundle that
7641 If a shelved change is applied successfully, the bundle that
7642 contains the shelved changes is moved to a backup location
7642 contains the shelved changes is moved to a backup location
7643 (.hg/shelve-backup).
7643 (.hg/shelve-backup).
7644
7644
7645 Since you can restore a shelved change on top of an arbitrary
7645 Since you can restore a shelved change on top of an arbitrary
7646 commit, it is possible that unshelving will result in a conflict
7646 commit, it is possible that unshelving will result in a conflict
7647 between your changes and the commits you are unshelving onto. If
7647 between your changes and the commits you are unshelving onto. If
7648 this occurs, you must resolve the conflict, then use
7648 this occurs, you must resolve the conflict, then use
7649 ``--continue`` to complete the unshelve operation. (The bundle
7649 ``--continue`` to complete the unshelve operation. (The bundle
7650 will not be moved until you successfully complete the unshelve.)
7650 will not be moved until you successfully complete the unshelve.)
7651
7651
7652 (Alternatively, you can use ``--abort`` to abandon an unshelve
7652 (Alternatively, you can use ``--abort`` to abandon an unshelve
7653 that causes a conflict. This reverts the unshelved changes, and
7653 that causes a conflict. This reverts the unshelved changes, and
7654 leaves the bundle in place.)
7654 leaves the bundle in place.)
7655
7655
7656 If bare shelved change (without interactive, include and exclude
7656 If bare shelved change (without interactive, include and exclude
7657 option) was done on newly created branch it would restore branch
7657 option) was done on newly created branch it would restore branch
7658 information to the working directory.
7658 information to the working directory.
7659
7659
7660 After a successful unshelve, the shelved changes are stored in a
7660 After a successful unshelve, the shelved changes are stored in a
7661 backup directory. Only the N most recent backups are kept. N
7661 backup directory. Only the N most recent backups are kept. N
7662 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7662 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7663 configuration option.
7663 configuration option.
7664
7664
7665 .. container:: verbose
7665 .. container:: verbose
7666
7666
7667 Timestamp in seconds is used to decide order of backups. More
7667 Timestamp in seconds is used to decide order of backups. More
7668 than ``maxbackups`` backups are kept, if same timestamp
7668 than ``maxbackups`` backups are kept, if same timestamp
7669 prevents from deciding exact order of them, for safety.
7669 prevents from deciding exact order of them, for safety.
7670
7670
7671 Selected changes can be unshelved with ``--interactive`` flag.
7671 Selected changes can be unshelved with ``--interactive`` flag.
7672 The working directory is updated with the selected changes, and
7672 The working directory is updated with the selected changes, and
7673 only the unselected changes remain shelved.
7673 only the unselected changes remain shelved.
7674 Note: The whole shelve is applied to working directory first before
7674 Note: The whole shelve is applied to working directory first before
7675 running interactively. So, this will bring up all the conflicts between
7675 running interactively. So, this will bring up all the conflicts between
7676 working directory and the shelve, irrespective of which changes will be
7676 working directory and the shelve, irrespective of which changes will be
7677 unshelved.
7677 unshelved.
7678 """
7678 """
7679 with repo.wlock():
7679 with repo.wlock():
7680 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7680 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7681
7681
7682
7682
7683 statemod.addunfinished(
7683 statemod.addunfinished(
7684 b'unshelve',
7684 b'unshelve',
7685 fname=b'shelvedstate',
7685 fname=b'shelvedstate',
7686 continueflag=True,
7686 continueflag=True,
7687 abortfunc=shelvemod.hgabortunshelve,
7687 abortfunc=shelvemod.hgabortunshelve,
7688 continuefunc=shelvemod.hgcontinueunshelve,
7688 continuefunc=shelvemod.hgcontinueunshelve,
7689 cmdmsg=_(b'unshelve already in progress'),
7689 cmdmsg=_(b'unshelve already in progress'),
7690 )
7690 )
7691
7691
7692
7692
7693 @command(
7693 @command(
7694 b'update|up|checkout|co',
7694 b'update|up|checkout|co',
7695 [
7695 [
7696 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7696 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7697 (b'c', b'check', None, _(b'require clean working directory')),
7697 (b'c', b'check', None, _(b'require clean working directory')),
7698 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7698 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7699 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7699 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7700 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7700 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7701 ]
7701 ]
7702 + mergetoolopts,
7702 + mergetoolopts,
7703 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7703 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7704 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7704 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7705 helpbasic=True,
7705 helpbasic=True,
7706 )
7706 )
7707 def update(ui, repo, node=None, **opts):
7707 def update(ui, repo, node=None, **opts):
7708 """update working directory (or switch revisions)
7708 """update working directory (or switch revisions)
7709
7709
7710 Update the repository's working directory to the specified
7710 Update the repository's working directory to the specified
7711 changeset. If no changeset is specified, update to the tip of the
7711 changeset. If no changeset is specified, update to the tip of the
7712 current named branch and move the active bookmark (see :hg:`help
7712 current named branch and move the active bookmark (see :hg:`help
7713 bookmarks`).
7713 bookmarks`).
7714
7714
7715 Update sets the working directory's parent revision to the specified
7715 Update sets the working directory's parent revision to the specified
7716 changeset (see :hg:`help parents`).
7716 changeset (see :hg:`help parents`).
7717
7717
7718 If the changeset is not a descendant or ancestor of the working
7718 If the changeset is not a descendant or ancestor of the working
7719 directory's parent and there are uncommitted changes, the update is
7719 directory's parent and there are uncommitted changes, the update is
7720 aborted. With the -c/--check option, the working directory is checked
7720 aborted. With the -c/--check option, the working directory is checked
7721 for uncommitted changes; if none are found, the working directory is
7721 for uncommitted changes; if none are found, the working directory is
7722 updated to the specified changeset.
7722 updated to the specified changeset.
7723
7723
7724 .. container:: verbose
7724 .. container:: verbose
7725
7725
7726 The -C/--clean, -c/--check, and -m/--merge options control what
7726 The -C/--clean, -c/--check, and -m/--merge options control what
7727 happens if the working directory contains uncommitted changes.
7727 happens if the working directory contains uncommitted changes.
7728 At most of one of them can be specified.
7728 At most of one of them can be specified.
7729
7729
7730 1. If no option is specified, and if
7730 1. If no option is specified, and if
7731 the requested changeset is an ancestor or descendant of
7731 the requested changeset is an ancestor or descendant of
7732 the working directory's parent, the uncommitted changes
7732 the working directory's parent, the uncommitted changes
7733 are merged into the requested changeset and the merged
7733 are merged into the requested changeset and the merged
7734 result is left uncommitted. If the requested changeset is
7734 result is left uncommitted. If the requested changeset is
7735 not an ancestor or descendant (that is, it is on another
7735 not an ancestor or descendant (that is, it is on another
7736 branch), the update is aborted and the uncommitted changes
7736 branch), the update is aborted and the uncommitted changes
7737 are preserved.
7737 are preserved.
7738
7738
7739 2. With the -m/--merge option, the update is allowed even if the
7739 2. With the -m/--merge option, the update is allowed even if the
7740 requested changeset is not an ancestor or descendant of
7740 requested changeset is not an ancestor or descendant of
7741 the working directory's parent.
7741 the working directory's parent.
7742
7742
7743 3. With the -c/--check option, the update is aborted and the
7743 3. With the -c/--check option, the update is aborted and the
7744 uncommitted changes are preserved.
7744 uncommitted changes are preserved.
7745
7745
7746 4. With the -C/--clean option, uncommitted changes are discarded and
7746 4. With the -C/--clean option, uncommitted changes are discarded and
7747 the working directory is updated to the requested changeset.
7747 the working directory is updated to the requested changeset.
7748
7748
7749 To cancel an uncommitted merge (and lose your changes), use
7749 To cancel an uncommitted merge (and lose your changes), use
7750 :hg:`merge --abort`.
7750 :hg:`merge --abort`.
7751
7751
7752 Use null as the changeset to remove the working directory (like
7752 Use null as the changeset to remove the working directory (like
7753 :hg:`clone -U`).
7753 :hg:`clone -U`).
7754
7754
7755 If you want to revert just one file to an older revision, use
7755 If you want to revert just one file to an older revision, use
7756 :hg:`revert [-r REV] NAME`.
7756 :hg:`revert [-r REV] NAME`.
7757
7757
7758 See :hg:`help dates` for a list of formats valid for -d/--date.
7758 See :hg:`help dates` for a list of formats valid for -d/--date.
7759
7759
7760 Returns 0 on success, 1 if there are unresolved files.
7760 Returns 0 on success, 1 if there are unresolved files.
7761 """
7761 """
7762 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7762 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7763 rev = opts.get('rev')
7763 rev = opts.get('rev')
7764 date = opts.get('date')
7764 date = opts.get('date')
7765 clean = opts.get('clean')
7765 clean = opts.get('clean')
7766 check = opts.get('check')
7766 check = opts.get('check')
7767 merge = opts.get('merge')
7767 merge = opts.get('merge')
7768 if rev and node:
7768 if rev and node:
7769 raise error.InputError(_(b"please specify just one revision"))
7769 raise error.InputError(_(b"please specify just one revision"))
7770
7770
7771 if ui.configbool(b'commands', b'update.requiredest'):
7771 if ui.configbool(b'commands', b'update.requiredest'):
7772 if not node and not rev and not date:
7772 if not node and not rev and not date:
7773 raise error.InputError(
7773 raise error.InputError(
7774 _(b'you must specify a destination'),
7774 _(b'you must specify a destination'),
7775 hint=_(b'for example: hg update ".::"'),
7775 hint=_(b'for example: hg update ".::"'),
7776 )
7776 )
7777
7777
7778 if rev is None or rev == b'':
7778 if rev is None or rev == b'':
7779 rev = node
7779 rev = node
7780
7780
7781 if date and rev is not None:
7781 if date and rev is not None:
7782 raise error.InputError(_(b"you can't specify a revision and a date"))
7782 raise error.InputError(_(b"you can't specify a revision and a date"))
7783
7783
7784 updatecheck = None
7784 updatecheck = None
7785 if check:
7785 if check:
7786 updatecheck = b'abort'
7786 updatecheck = b'abort'
7787 elif merge:
7787 elif merge:
7788 updatecheck = b'none'
7788 updatecheck = b'none'
7789
7789
7790 with repo.wlock():
7790 with repo.wlock():
7791 cmdutil.clearunfinished(repo)
7791 cmdutil.clearunfinished(repo)
7792 if date:
7792 if date:
7793 rev = cmdutil.finddate(ui, repo, date)
7793 rev = cmdutil.finddate(ui, repo, date)
7794
7794
7795 # if we defined a bookmark, we have to remember the original name
7795 # if we defined a bookmark, we have to remember the original name
7796 brev = rev
7796 brev = rev
7797 if rev:
7797 if rev:
7798 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7798 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7799 ctx = scmutil.revsingle(repo, rev, default=None)
7799 ctx = scmutil.revsingle(repo, rev, default=None)
7800 rev = ctx.rev()
7800 rev = ctx.rev()
7801 hidden = ctx.hidden()
7801 hidden = ctx.hidden()
7802 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7802 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7803 with ui.configoverride(overrides, b'update'):
7803 with ui.configoverride(overrides, b'update'):
7804 ret = hg.updatetotally(
7804 ret = hg.updatetotally(
7805 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7805 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7806 )
7806 )
7807 if hidden:
7807 if hidden:
7808 ctxstr = ctx.hex()[:12]
7808 ctxstr = ctx.hex()[:12]
7809 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7809 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7810
7810
7811 if ctx.obsolete():
7811 if ctx.obsolete():
7812 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7812 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7813 ui.warn(b"(%s)\n" % obsfatemsg)
7813 ui.warn(b"(%s)\n" % obsfatemsg)
7814 return ret
7814 return ret
7815
7815
7816
7816
7817 @command(
7817 @command(
7818 b'verify',
7818 b'verify',
7819 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7819 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7820 helpcategory=command.CATEGORY_MAINTENANCE,
7820 helpcategory=command.CATEGORY_MAINTENANCE,
7821 )
7821 )
7822 def verify(ui, repo, **opts):
7822 def verify(ui, repo, **opts):
7823 """verify the integrity of the repository
7823 """verify the integrity of the repository
7824
7824
7825 Verify the integrity of the current repository.
7825 Verify the integrity of the current repository.
7826
7826
7827 This will perform an extensive check of the repository's
7827 This will perform an extensive check of the repository's
7828 integrity, validating the hashes and checksums of each entry in
7828 integrity, validating the hashes and checksums of each entry in
7829 the changelog, manifest, and tracked files, as well as the
7829 the changelog, manifest, and tracked files, as well as the
7830 integrity of their crosslinks and indices.
7830 integrity of their crosslinks and indices.
7831
7831
7832 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7832 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7833 for more information about recovery from corruption of the
7833 for more information about recovery from corruption of the
7834 repository.
7834 repository.
7835
7835
7836 Returns 0 on success, 1 if errors are encountered.
7836 Returns 0 on success, 1 if errors are encountered.
7837 """
7837 """
7838 opts = pycompat.byteskwargs(opts)
7838 opts = pycompat.byteskwargs(opts)
7839
7839
7840 level = None
7840 level = None
7841 if opts[b'full']:
7841 if opts[b'full']:
7842 level = verifymod.VERIFY_FULL
7842 level = verifymod.VERIFY_FULL
7843 return hg.verify(repo, level)
7843 return hg.verify(repo, level)
7844
7844
7845
7845
7846 @command(
7846 @command(
7847 b'version',
7847 b'version',
7848 [] + formatteropts,
7848 [] + formatteropts,
7849 helpcategory=command.CATEGORY_HELP,
7849 helpcategory=command.CATEGORY_HELP,
7850 norepo=True,
7850 norepo=True,
7851 intents={INTENT_READONLY},
7851 intents={INTENT_READONLY},
7852 )
7852 )
7853 def version_(ui, **opts):
7853 def version_(ui, **opts):
7854 """output version and copyright information
7854 """output version and copyright information
7855
7855
7856 .. container:: verbose
7856 .. container:: verbose
7857
7857
7858 Template:
7858 Template:
7859
7859
7860 The following keywords are supported. See also :hg:`help templates`.
7860 The following keywords are supported. See also :hg:`help templates`.
7861
7861
7862 :extensions: List of extensions.
7862 :extensions: List of extensions.
7863 :ver: String. Version number.
7863 :ver: String. Version number.
7864
7864
7865 And each entry of ``{extensions}`` provides the following sub-keywords
7865 And each entry of ``{extensions}`` provides the following sub-keywords
7866 in addition to ``{ver}``.
7866 in addition to ``{ver}``.
7867
7867
7868 :bundled: Boolean. True if included in the release.
7868 :bundled: Boolean. True if included in the release.
7869 :name: String. Extension name.
7869 :name: String. Extension name.
7870 """
7870 """
7871 opts = pycompat.byteskwargs(opts)
7871 opts = pycompat.byteskwargs(opts)
7872 if ui.verbose:
7872 if ui.verbose:
7873 ui.pager(b'version')
7873 ui.pager(b'version')
7874 fm = ui.formatter(b"version", opts)
7874 fm = ui.formatter(b"version", opts)
7875 fm.startitem()
7875 fm.startitem()
7876 fm.write(
7876 fm.write(
7877 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7877 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7878 )
7878 )
7879 license = _(
7879 license = _(
7880 b"(see https://mercurial-scm.org for more information)\n"
7880 b"(see https://mercurial-scm.org for more information)\n"
7881 b"\nCopyright (C) 2005-2021 Matt Mackall and others\n"
7881 b"\nCopyright (C) 2005-2021 Matt Mackall and others\n"
7882 b"This is free software; see the source for copying conditions. "
7882 b"This is free software; see the source for copying conditions. "
7883 b"There is NO\nwarranty; "
7883 b"There is NO\nwarranty; "
7884 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7884 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7885 )
7885 )
7886 if not ui.quiet:
7886 if not ui.quiet:
7887 fm.plain(license)
7887 fm.plain(license)
7888
7888
7889 if ui.verbose:
7889 if ui.verbose:
7890 fm.plain(_(b"\nEnabled extensions:\n\n"))
7890 fm.plain(_(b"\nEnabled extensions:\n\n"))
7891 # format names and versions into columns
7891 # format names and versions into columns
7892 names = []
7892 names = []
7893 vers = []
7893 vers = []
7894 isinternals = []
7894 isinternals = []
7895 for name, module in sorted(extensions.extensions()):
7895 for name, module in sorted(extensions.extensions()):
7896 names.append(name)
7896 names.append(name)
7897 vers.append(extensions.moduleversion(module) or None)
7897 vers.append(extensions.moduleversion(module) or None)
7898 isinternals.append(extensions.ismoduleinternal(module))
7898 isinternals.append(extensions.ismoduleinternal(module))
7899 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7899 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7900 if names:
7900 if names:
7901 namefmt = b" %%-%ds " % max(len(n) for n in names)
7901 namefmt = b" %%-%ds " % max(len(n) for n in names)
7902 places = [_(b"external"), _(b"internal")]
7902 places = [_(b"external"), _(b"internal")]
7903 for n, v, p in zip(names, vers, isinternals):
7903 for n, v, p in zip(names, vers, isinternals):
7904 fn.startitem()
7904 fn.startitem()
7905 fn.condwrite(ui.verbose, b"name", namefmt, n)
7905 fn.condwrite(ui.verbose, b"name", namefmt, n)
7906 if ui.verbose:
7906 if ui.verbose:
7907 fn.plain(b"%s " % places[p])
7907 fn.plain(b"%s " % places[p])
7908 fn.data(bundled=p)
7908 fn.data(bundled=p)
7909 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7909 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7910 if ui.verbose:
7910 if ui.verbose:
7911 fn.plain(b"\n")
7911 fn.plain(b"\n")
7912 fn.end()
7912 fn.end()
7913 fm.end()
7913 fm.end()
7914
7914
7915
7915
7916 def loadcmdtable(ui, name, cmdtable):
7916 def loadcmdtable(ui, name, cmdtable):
7917 """Load command functions from specified cmdtable"""
7917 """Load command functions from specified cmdtable"""
7918 overrides = [cmd for cmd in cmdtable if cmd in table]
7918 overrides = [cmd for cmd in cmdtable if cmd in table]
7919 if overrides:
7919 if overrides:
7920 ui.warn(
7920 ui.warn(
7921 _(b"extension '%s' overrides commands: %s\n")
7921 _(b"extension '%s' overrides commands: %s\n")
7922 % (name, b" ".join(overrides))
7922 % (name, b" ".join(overrides))
7923 )
7923 )
7924 table.update(cmdtable)
7924 table.update(cmdtable)
@@ -1,796 +1,796 b''
1 $ hg init
1 $ hg init
2
2
3
3
4 committing changes
4 committing changes
5
5
6 $ count=0
6 $ count=0
7 $ echo > a
7 $ echo > a
8 $ while test $count -lt 32 ; do
8 $ while test $count -lt 32 ; do
9 > echo 'a' >> a
9 > echo 'a' >> a
10 > test $count -eq 0 && hg add
10 > test $count -eq 0 && hg add
11 > hg ci -m "msg $count" -d "$count 0"
11 > hg ci -m "msg $count" -d "$count 0"
12 > count=`expr $count + 1`
12 > count=`expr $count + 1`
13 > done
13 > done
14 adding a
14 adding a
15
15
16
16
17 $ hg log -G
17 $ hg log -G
18 @ changeset: 31:58c80a7c8a40
18 @ changeset: 31:58c80a7c8a40
19 | tag: tip
19 | tag: tip
20 | user: test
20 | user: test
21 | date: Thu Jan 01 00:00:31 1970 +0000
21 | date: Thu Jan 01 00:00:31 1970 +0000
22 | summary: msg 31
22 | summary: msg 31
23 |
23 |
24 o changeset: 30:ed2d2f24b11c
24 o changeset: 30:ed2d2f24b11c
25 | user: test
25 | user: test
26 | date: Thu Jan 01 00:00:30 1970 +0000
26 | date: Thu Jan 01 00:00:30 1970 +0000
27 | summary: msg 30
27 | summary: msg 30
28 |
28 |
29 o changeset: 29:b5bd63375ab9
29 o changeset: 29:b5bd63375ab9
30 | user: test
30 | user: test
31 | date: Thu Jan 01 00:00:29 1970 +0000
31 | date: Thu Jan 01 00:00:29 1970 +0000
32 | summary: msg 29
32 | summary: msg 29
33 |
33 |
34 o changeset: 28:8e0c2264c8af
34 o changeset: 28:8e0c2264c8af
35 | user: test
35 | user: test
36 | date: Thu Jan 01 00:00:28 1970 +0000
36 | date: Thu Jan 01 00:00:28 1970 +0000
37 | summary: msg 28
37 | summary: msg 28
38 |
38 |
39 o changeset: 27:288867a866e9
39 o changeset: 27:288867a866e9
40 | user: test
40 | user: test
41 | date: Thu Jan 01 00:00:27 1970 +0000
41 | date: Thu Jan 01 00:00:27 1970 +0000
42 | summary: msg 27
42 | summary: msg 27
43 |
43 |
44 o changeset: 26:3efc6fd51aeb
44 o changeset: 26:3efc6fd51aeb
45 | user: test
45 | user: test
46 | date: Thu Jan 01 00:00:26 1970 +0000
46 | date: Thu Jan 01 00:00:26 1970 +0000
47 | summary: msg 26
47 | summary: msg 26
48 |
48 |
49 o changeset: 25:02a84173a97a
49 o changeset: 25:02a84173a97a
50 | user: test
50 | user: test
51 | date: Thu Jan 01 00:00:25 1970 +0000
51 | date: Thu Jan 01 00:00:25 1970 +0000
52 | summary: msg 25
52 | summary: msg 25
53 |
53 |
54 o changeset: 24:10e0acd3809e
54 o changeset: 24:10e0acd3809e
55 | user: test
55 | user: test
56 | date: Thu Jan 01 00:00:24 1970 +0000
56 | date: Thu Jan 01 00:00:24 1970 +0000
57 | summary: msg 24
57 | summary: msg 24
58 |
58 |
59 o changeset: 23:5ec79163bff4
59 o changeset: 23:5ec79163bff4
60 | user: test
60 | user: test
61 | date: Thu Jan 01 00:00:23 1970 +0000
61 | date: Thu Jan 01 00:00:23 1970 +0000
62 | summary: msg 23
62 | summary: msg 23
63 |
63 |
64 o changeset: 22:06c7993750ce
64 o changeset: 22:06c7993750ce
65 | user: test
65 | user: test
66 | date: Thu Jan 01 00:00:22 1970 +0000
66 | date: Thu Jan 01 00:00:22 1970 +0000
67 | summary: msg 22
67 | summary: msg 22
68 |
68 |
69 o changeset: 21:e5db6aa3fe2a
69 o changeset: 21:e5db6aa3fe2a
70 | user: test
70 | user: test
71 | date: Thu Jan 01 00:00:21 1970 +0000
71 | date: Thu Jan 01 00:00:21 1970 +0000
72 | summary: msg 21
72 | summary: msg 21
73 |
73 |
74 o changeset: 20:7128fb4fdbc9
74 o changeset: 20:7128fb4fdbc9
75 | user: test
75 | user: test
76 | date: Thu Jan 01 00:00:20 1970 +0000
76 | date: Thu Jan 01 00:00:20 1970 +0000
77 | summary: msg 20
77 | summary: msg 20
78 |
78 |
79 o changeset: 19:52798545b482
79 o changeset: 19:52798545b482
80 | user: test
80 | user: test
81 | date: Thu Jan 01 00:00:19 1970 +0000
81 | date: Thu Jan 01 00:00:19 1970 +0000
82 | summary: msg 19
82 | summary: msg 19
83 |
83 |
84 o changeset: 18:86977a90077e
84 o changeset: 18:86977a90077e
85 | user: test
85 | user: test
86 | date: Thu Jan 01 00:00:18 1970 +0000
86 | date: Thu Jan 01 00:00:18 1970 +0000
87 | summary: msg 18
87 | summary: msg 18
88 |
88 |
89 o changeset: 17:03515f4a9080
89 o changeset: 17:03515f4a9080
90 | user: test
90 | user: test
91 | date: Thu Jan 01 00:00:17 1970 +0000
91 | date: Thu Jan 01 00:00:17 1970 +0000
92 | summary: msg 17
92 | summary: msg 17
93 |
93 |
94 o changeset: 16:a2e6ea4973e9
94 o changeset: 16:a2e6ea4973e9
95 | user: test
95 | user: test
96 | date: Thu Jan 01 00:00:16 1970 +0000
96 | date: Thu Jan 01 00:00:16 1970 +0000
97 | summary: msg 16
97 | summary: msg 16
98 |
98 |
99 o changeset: 15:e7fa0811edb0
99 o changeset: 15:e7fa0811edb0
100 | user: test
100 | user: test
101 | date: Thu Jan 01 00:00:15 1970 +0000
101 | date: Thu Jan 01 00:00:15 1970 +0000
102 | summary: msg 15
102 | summary: msg 15
103 |
103 |
104 o changeset: 14:ce8f0998e922
104 o changeset: 14:ce8f0998e922
105 | user: test
105 | user: test
106 | date: Thu Jan 01 00:00:14 1970 +0000
106 | date: Thu Jan 01 00:00:14 1970 +0000
107 | summary: msg 14
107 | summary: msg 14
108 |
108 |
109 o changeset: 13:9d7d07bc967c
109 o changeset: 13:9d7d07bc967c
110 | user: test
110 | user: test
111 | date: Thu Jan 01 00:00:13 1970 +0000
111 | date: Thu Jan 01 00:00:13 1970 +0000
112 | summary: msg 13
112 | summary: msg 13
113 |
113 |
114 o changeset: 12:1941b52820a5
114 o changeset: 12:1941b52820a5
115 | user: test
115 | user: test
116 | date: Thu Jan 01 00:00:12 1970 +0000
116 | date: Thu Jan 01 00:00:12 1970 +0000
117 | summary: msg 12
117 | summary: msg 12
118 |
118 |
119 o changeset: 11:7b4cd9578619
119 o changeset: 11:7b4cd9578619
120 | user: test
120 | user: test
121 | date: Thu Jan 01 00:00:11 1970 +0000
121 | date: Thu Jan 01 00:00:11 1970 +0000
122 | summary: msg 11
122 | summary: msg 11
123 |
123 |
124 o changeset: 10:7c5eff49a6b6
124 o changeset: 10:7c5eff49a6b6
125 | user: test
125 | user: test
126 | date: Thu Jan 01 00:00:10 1970 +0000
126 | date: Thu Jan 01 00:00:10 1970 +0000
127 | summary: msg 10
127 | summary: msg 10
128 |
128 |
129 o changeset: 9:eb44510ef29a
129 o changeset: 9:eb44510ef29a
130 | user: test
130 | user: test
131 | date: Thu Jan 01 00:00:09 1970 +0000
131 | date: Thu Jan 01 00:00:09 1970 +0000
132 | summary: msg 9
132 | summary: msg 9
133 |
133 |
134 o changeset: 8:453eb4dba229
134 o changeset: 8:453eb4dba229
135 | user: test
135 | user: test
136 | date: Thu Jan 01 00:00:08 1970 +0000
136 | date: Thu Jan 01 00:00:08 1970 +0000
137 | summary: msg 8
137 | summary: msg 8
138 |
138 |
139 o changeset: 7:03750880c6b5
139 o changeset: 7:03750880c6b5
140 | user: test
140 | user: test
141 | date: Thu Jan 01 00:00:07 1970 +0000
141 | date: Thu Jan 01 00:00:07 1970 +0000
142 | summary: msg 7
142 | summary: msg 7
143 |
143 |
144 o changeset: 6:a3d5c6fdf0d3
144 o changeset: 6:a3d5c6fdf0d3
145 | user: test
145 | user: test
146 | date: Thu Jan 01 00:00:06 1970 +0000
146 | date: Thu Jan 01 00:00:06 1970 +0000
147 | summary: msg 6
147 | summary: msg 6
148 |
148 |
149 o changeset: 5:7874a09ea728
149 o changeset: 5:7874a09ea728
150 | user: test
150 | user: test
151 | date: Thu Jan 01 00:00:05 1970 +0000
151 | date: Thu Jan 01 00:00:05 1970 +0000
152 | summary: msg 5
152 | summary: msg 5
153 |
153 |
154 o changeset: 4:9b2ba8336a65
154 o changeset: 4:9b2ba8336a65
155 | user: test
155 | user: test
156 | date: Thu Jan 01 00:00:04 1970 +0000
156 | date: Thu Jan 01 00:00:04 1970 +0000
157 | summary: msg 4
157 | summary: msg 4
158 |
158 |
159 o changeset: 3:b53bea5e2fcb
159 o changeset: 3:b53bea5e2fcb
160 | user: test
160 | user: test
161 | date: Thu Jan 01 00:00:03 1970 +0000
161 | date: Thu Jan 01 00:00:03 1970 +0000
162 | summary: msg 3
162 | summary: msg 3
163 |
163 |
164 o changeset: 2:db07c04beaca
164 o changeset: 2:db07c04beaca
165 | user: test
165 | user: test
166 | date: Thu Jan 01 00:00:02 1970 +0000
166 | date: Thu Jan 01 00:00:02 1970 +0000
167 | summary: msg 2
167 | summary: msg 2
168 |
168 |
169 o changeset: 1:5cd978ea5149
169 o changeset: 1:5cd978ea5149
170 | user: test
170 | user: test
171 | date: Thu Jan 01 00:00:01 1970 +0000
171 | date: Thu Jan 01 00:00:01 1970 +0000
172 | summary: msg 1
172 | summary: msg 1
173 |
173 |
174 o changeset: 0:b99c7b9c8e11
174 o changeset: 0:b99c7b9c8e11
175 user: test
175 user: test
176 date: Thu Jan 01 00:00:00 1970 +0000
176 date: Thu Jan 01 00:00:00 1970 +0000
177 summary: msg 0
177 summary: msg 0
178
178
179
179
180 $ hg up -C
180 $ hg up -C
181 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
181 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
182
182
183 bisect test
183 bisect test
184
184
185 $ hg bisect -r
185 $ hg bisect -r
186 $ hg bisect -b
186 $ hg bisect -b
187 $ hg status -v
187 $ hg status -v
188 # The repository is in an unfinished *bisect* state.
188 # The repository is in an unfinished *bisect* state.
189
189
190 # To mark the changeset good: hg bisect --good
190 # To mark the changeset good: hg bisect --good
191 # To mark the changeset bad: hg bisect --bad
191 # To mark the changeset bad: hg bisect --bad
192 # To abort: hg bisect --reset
192 # To abort: hg bisect --reset
193
193
194 $ hg status -v --config commands.status.skipstates=bisect
194 $ hg status -v --config commands.status.skipstates=bisect
195 $ hg summary
195 $ hg summary
196 parent: 31:58c80a7c8a40 tip
196 parent: 31:58c80a7c8a40 tip
197 msg 31
197 msg 31
198 branch: default
198 branch: default
199 commit: (clean)
199 commit: (clean)
200 update: (current)
200 update: (current)
201 phases: 32 draft
201 phases: 32 draft
202 $ hg bisect -g 1
202 $ hg bisect -g 1
203 Testing changeset 16:a2e6ea4973e9 (30 changesets remaining, ~4 tests)
203 Testing changeset 16:a2e6ea4973e9 "msg 16" (30 changesets remaining, ~4 tests)
204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 $ hg bisect -g
205 $ hg bisect -g
206 Testing changeset 23:5ec79163bff4 (15 changesets remaining, ~3 tests)
206 Testing changeset 23:5ec79163bff4 "msg 23" (15 changesets remaining, ~3 tests)
207 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
208
208
209 skip
209 skip
210
210
211 $ hg bisect -s
211 $ hg bisect -s
212 Testing changeset 24:10e0acd3809e (15 changesets remaining, ~3 tests)
212 Testing changeset 24:10e0acd3809e "msg 24" (15 changesets remaining, ~3 tests)
213 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 $ hg bisect -g
214 $ hg bisect -g
215 Testing changeset 27:288867a866e9 (7 changesets remaining, ~2 tests)
215 Testing changeset 27:288867a866e9 "msg 27" (7 changesets remaining, ~2 tests)
216 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
217 $ hg bisect -g
217 $ hg bisect -g
218 Testing changeset 29:b5bd63375ab9 (4 changesets remaining, ~2 tests)
218 Testing changeset 29:b5bd63375ab9 "msg 29" (4 changesets remaining, ~2 tests)
219 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 $ hg bisect -b
220 $ hg bisect -b
221 Testing changeset 28:8e0c2264c8af (2 changesets remaining, ~1 tests)
221 Testing changeset 28:8e0c2264c8af "msg 28" (2 changesets remaining, ~1 tests)
222 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
223 $ hg bisect -g
223 $ hg bisect -g
224 The first bad revision is:
224 The first bad revision is:
225 changeset: 29:b5bd63375ab9
225 changeset: 29:b5bd63375ab9
226 user: test
226 user: test
227 date: Thu Jan 01 00:00:29 1970 +0000
227 date: Thu Jan 01 00:00:29 1970 +0000
228 summary: msg 29
228 summary: msg 29
229
229
230
230
231 mark revsets instead of single revs
231 mark revsets instead of single revs
232
232
233 $ hg bisect -r
233 $ hg bisect -r
234 $ hg bisect -b "0::3"
234 $ hg bisect -b "0::3"
235 $ hg bisect -s "13::16"
235 $ hg bisect -s "13::16"
236 $ hg bisect -g "26::tip"
236 $ hg bisect -g "26::tip"
237 Testing changeset 12:1941b52820a5 (23 changesets remaining, ~4 tests)
237 Testing changeset 12:1941b52820a5 "msg 12" (23 changesets remaining, ~4 tests)
238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
238 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
239 $ cat .hg/bisect.state
239 $ cat .hg/bisect.state
240 bad b99c7b9c8e11558adef3fad9af211c58d46f325b
240 bad b99c7b9c8e11558adef3fad9af211c58d46f325b
241 bad 5cd978ea51499179507ee7b6f340d2dbaa401185
241 bad 5cd978ea51499179507ee7b6f340d2dbaa401185
242 bad db07c04beaca44cf24832541e7f4a2346a95275b
242 bad db07c04beaca44cf24832541e7f4a2346a95275b
243 bad b53bea5e2fcb30d3e00bd3409507a5659ce0fd8b
243 bad b53bea5e2fcb30d3e00bd3409507a5659ce0fd8b
244 current 1941b52820a544549596820a8ae006842b0e2c64
244 current 1941b52820a544549596820a8ae006842b0e2c64
245 good 3efc6fd51aeb8594398044c6c846ca59ae021203
245 good 3efc6fd51aeb8594398044c6c846ca59ae021203
246 good 288867a866e9adb7a29880b66936c874b80f4651
246 good 288867a866e9adb7a29880b66936c874b80f4651
247 good 8e0c2264c8af790daf3585ada0669d93dee09c83
247 good 8e0c2264c8af790daf3585ada0669d93dee09c83
248 good b5bd63375ab9a290419f2024b7f4ee9ea7ce90a8
248 good b5bd63375ab9a290419f2024b7f4ee9ea7ce90a8
249 good ed2d2f24b11c368fa8aa0da9f4e1db580abade59
249 good ed2d2f24b11c368fa8aa0da9f4e1db580abade59
250 good 58c80a7c8a4025a94cedaf7b4a4e3124e8909a96
250 good 58c80a7c8a4025a94cedaf7b4a4e3124e8909a96
251 skip 9d7d07bc967ca98ad0600c24953fd289ad5fa991
251 skip 9d7d07bc967ca98ad0600c24953fd289ad5fa991
252 skip ce8f0998e922c179e80819d5066fbe46e2998784
252 skip ce8f0998e922c179e80819d5066fbe46e2998784
253 skip e7fa0811edb063f6319531f0d0a865882138e180
253 skip e7fa0811edb063f6319531f0d0a865882138e180
254 skip a2e6ea4973e9196ddd3386493b0c214b41fd97d3
254 skip a2e6ea4973e9196ddd3386493b0c214b41fd97d3
255
255
256 bisect reverse test
256 bisect reverse test
257
257
258 $ hg bisect -r
258 $ hg bisect -r
259 $ hg bisect -b null
259 $ hg bisect -b null
260 $ hg bisect -g tip
260 $ hg bisect -g tip
261 Testing changeset 15:e7fa0811edb0 (32 changesets remaining, ~5 tests)
261 Testing changeset 15:e7fa0811edb0 "msg 15" (32 changesets remaining, ~5 tests)
262 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
262 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 $ hg bisect -g
263 $ hg bisect -g
264 Testing changeset 7:03750880c6b5 (16 changesets remaining, ~4 tests)
264 Testing changeset 7:03750880c6b5 "msg 7" (16 changesets remaining, ~4 tests)
265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
265 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
266
266
267 skip
267 skip
268
268
269 $ hg bisect -s
269 $ hg bisect -s
270 Testing changeset 6:a3d5c6fdf0d3 (16 changesets remaining, ~4 tests)
270 Testing changeset 6:a3d5c6fdf0d3 "msg 6" (16 changesets remaining, ~4 tests)
271 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
271 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
272 $ hg bisect -g
272 $ hg bisect -g
273 Testing changeset 2:db07c04beaca (7 changesets remaining, ~2 tests)
273 Testing changeset 2:db07c04beaca "msg 2" (7 changesets remaining, ~2 tests)
274 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
274 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
275 $ hg bisect -g
275 $ hg bisect -g
276 Testing changeset 0:b99c7b9c8e11 (3 changesets remaining, ~1 tests)
276 Testing changeset 0:b99c7b9c8e11 "msg 0" (3 changesets remaining, ~1 tests)
277 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
278 $ hg bisect -b
278 $ hg bisect -b
279 Testing changeset 1:5cd978ea5149 (2 changesets remaining, ~1 tests)
279 Testing changeset 1:5cd978ea5149 "msg 1" (2 changesets remaining, ~1 tests)
280 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
281 $ hg bisect -g
281 $ hg bisect -g
282 The first good revision is:
282 The first good revision is:
283 changeset: 1:5cd978ea5149
283 changeset: 1:5cd978ea5149
284 user: test
284 user: test
285 date: Thu Jan 01 00:00:01 1970 +0000
285 date: Thu Jan 01 00:00:01 1970 +0000
286 summary: msg 1
286 summary: msg 1
287
287
288
288
289 $ hg bisect -r
289 $ hg bisect -r
290 $ hg bisect -g tip
290 $ hg bisect -g tip
291 $ hg bisect -b tip
291 $ hg bisect -b tip
292 abort: inconsistent state, 31:58c80a7c8a40 is good and bad
292 abort: inconsistent state, 31:58c80a7c8a40 is good and bad
293 [255]
293 [255]
294
294
295 $ hg bisect -r
295 $ hg bisect -r
296 $ hg bisect -g null
296 $ hg bisect -g null
297 $ hg bisect -bU tip
297 $ hg bisect -bU tip
298 Testing changeset 15:e7fa0811edb0 (32 changesets remaining, ~5 tests)
298 Testing changeset 15:e7fa0811edb0 "msg 15" (32 changesets remaining, ~5 tests)
299 $ hg id
299 $ hg id
300 5cd978ea5149
300 5cd978ea5149
301
301
302
302
303 Issue1228: hg bisect crashes when you skip the last rev in bisection
303 Issue1228: hg bisect crashes when you skip the last rev in bisection
304 Issue1182: hg bisect exception
304 Issue1182: hg bisect exception
305
305
306 $ hg bisect -r
306 $ hg bisect -r
307 $ hg bisect -b 4
307 $ hg bisect -b 4
308 $ hg bisect -g 0
308 $ hg bisect -g 0
309 Testing changeset 2:db07c04beaca (4 changesets remaining, ~2 tests)
309 Testing changeset 2:db07c04beaca "msg 2" (4 changesets remaining, ~2 tests)
310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 $ hg bisect -s
311 $ hg bisect -s
312 Testing changeset 1:5cd978ea5149 (4 changesets remaining, ~2 tests)
312 Testing changeset 1:5cd978ea5149 "msg 1" (4 changesets remaining, ~2 tests)
313 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
313 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 $ hg bisect -s
314 $ hg bisect -s
315 Testing changeset 3:b53bea5e2fcb (4 changesets remaining, ~2 tests)
315 Testing changeset 3:b53bea5e2fcb "msg 3" (4 changesets remaining, ~2 tests)
316 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
316 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
317 $ hg bisect -s
317 $ hg bisect -s
318 Due to skipped revisions, the first bad revision could be any of:
318 Due to skipped revisions, the first bad revision could be any of:
319 changeset: 1:5cd978ea5149
319 changeset: 1:5cd978ea5149
320 user: test
320 user: test
321 date: Thu Jan 01 00:00:01 1970 +0000
321 date: Thu Jan 01 00:00:01 1970 +0000
322 summary: msg 1
322 summary: msg 1
323
323
324 changeset: 2:db07c04beaca
324 changeset: 2:db07c04beaca
325 user: test
325 user: test
326 date: Thu Jan 01 00:00:02 1970 +0000
326 date: Thu Jan 01 00:00:02 1970 +0000
327 summary: msg 2
327 summary: msg 2
328
328
329 changeset: 3:b53bea5e2fcb
329 changeset: 3:b53bea5e2fcb
330 user: test
330 user: test
331 date: Thu Jan 01 00:00:03 1970 +0000
331 date: Thu Jan 01 00:00:03 1970 +0000
332 summary: msg 3
332 summary: msg 3
333
333
334 changeset: 4:9b2ba8336a65
334 changeset: 4:9b2ba8336a65
335 user: test
335 user: test
336 date: Thu Jan 01 00:00:04 1970 +0000
336 date: Thu Jan 01 00:00:04 1970 +0000
337 summary: msg 4
337 summary: msg 4
338
338
339
339
340
340
341 reproduce non converging bisect, issue1182
341 reproduce non converging bisect, issue1182
342
342
343 $ hg bisect -r
343 $ hg bisect -r
344 $ hg bisect -g 0
344 $ hg bisect -g 0
345 $ hg bisect -b 2
345 $ hg bisect -b 2
346 Testing changeset 1:5cd978ea5149 (2 changesets remaining, ~1 tests)
346 Testing changeset 1:5cd978ea5149 "msg 1" (2 changesets remaining, ~1 tests)
347 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
347 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 $ hg bisect -s
348 $ hg bisect -s
349 Due to skipped revisions, the first bad revision could be any of:
349 Due to skipped revisions, the first bad revision could be any of:
350 changeset: 1:5cd978ea5149
350 changeset: 1:5cd978ea5149
351 user: test
351 user: test
352 date: Thu Jan 01 00:00:01 1970 +0000
352 date: Thu Jan 01 00:00:01 1970 +0000
353 summary: msg 1
353 summary: msg 1
354
354
355 changeset: 2:db07c04beaca
355 changeset: 2:db07c04beaca
356 user: test
356 user: test
357 date: Thu Jan 01 00:00:02 1970 +0000
357 date: Thu Jan 01 00:00:02 1970 +0000
358 summary: msg 2
358 summary: msg 2
359
359
360
360
361
361
362 test no action
362 test no action
363
363
364 $ hg bisect -r
364 $ hg bisect -r
365 $ hg bisect
365 $ hg bisect
366 abort: cannot bisect (no known good revisions)
366 abort: cannot bisect (no known good revisions)
367 [20]
367 [20]
368
368
369
369
370 reproduce AssertionError, issue1445
370 reproduce AssertionError, issue1445
371
371
372 $ hg bisect -r
372 $ hg bisect -r
373 $ hg bisect -b 6
373 $ hg bisect -b 6
374 $ hg bisect -g 0
374 $ hg bisect -g 0
375 Testing changeset 3:b53bea5e2fcb (6 changesets remaining, ~2 tests)
375 Testing changeset 3:b53bea5e2fcb "msg 3" (6 changesets remaining, ~2 tests)
376 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 $ hg bisect -s
377 $ hg bisect -s
378 Testing changeset 2:db07c04beaca (6 changesets remaining, ~2 tests)
378 Testing changeset 2:db07c04beaca "msg 2" (6 changesets remaining, ~2 tests)
379 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
379 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
380 $ hg bisect -s
380 $ hg bisect -s
381 Testing changeset 4:9b2ba8336a65 (6 changesets remaining, ~2 tests)
381 Testing changeset 4:9b2ba8336a65 "msg 4" (6 changesets remaining, ~2 tests)
382 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
382 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
383 $ hg bisect -s
383 $ hg bisect -s
384 Testing changeset 1:5cd978ea5149 (6 changesets remaining, ~2 tests)
384 Testing changeset 1:5cd978ea5149 "msg 1" (6 changesets remaining, ~2 tests)
385 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
385 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
386 $ hg bisect -s
386 $ hg bisect -s
387 Testing changeset 5:7874a09ea728 (6 changesets remaining, ~2 tests)
387 Testing changeset 5:7874a09ea728 "msg 5" (6 changesets remaining, ~2 tests)
388 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
388 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
389 $ hg bisect -g
389 $ hg bisect -g
390 The first bad revision is:
390 The first bad revision is:
391 changeset: 6:a3d5c6fdf0d3
391 changeset: 6:a3d5c6fdf0d3
392 user: test
392 user: test
393 date: Thu Jan 01 00:00:06 1970 +0000
393 date: Thu Jan 01 00:00:06 1970 +0000
394 summary: msg 6
394 summary: msg 6
395
395
396 $ hg log -r "bisect(good)"
396 $ hg log -r "bisect(good)"
397 changeset: 0:b99c7b9c8e11
397 changeset: 0:b99c7b9c8e11
398 user: test
398 user: test
399 date: Thu Jan 01 00:00:00 1970 +0000
399 date: Thu Jan 01 00:00:00 1970 +0000
400 summary: msg 0
400 summary: msg 0
401
401
402 changeset: 5:7874a09ea728
402 changeset: 5:7874a09ea728
403 user: test
403 user: test
404 date: Thu Jan 01 00:00:05 1970 +0000
404 date: Thu Jan 01 00:00:05 1970 +0000
405 summary: msg 5
405 summary: msg 5
406
406
407 $ hg log -r "bisect(bad)"
407 $ hg log -r "bisect(bad)"
408 changeset: 6:a3d5c6fdf0d3
408 changeset: 6:a3d5c6fdf0d3
409 user: test
409 user: test
410 date: Thu Jan 01 00:00:06 1970 +0000
410 date: Thu Jan 01 00:00:06 1970 +0000
411 summary: msg 6
411 summary: msg 6
412
412
413 $ hg log -r "bisect(current)"
413 $ hg log -r "bisect(current)"
414 changeset: 5:7874a09ea728
414 changeset: 5:7874a09ea728
415 user: test
415 user: test
416 date: Thu Jan 01 00:00:05 1970 +0000
416 date: Thu Jan 01 00:00:05 1970 +0000
417 summary: msg 5
417 summary: msg 5
418
418
419 $ hg log -r "bisect(skip)"
419 $ hg log -r "bisect(skip)"
420 changeset: 1:5cd978ea5149
420 changeset: 1:5cd978ea5149
421 user: test
421 user: test
422 date: Thu Jan 01 00:00:01 1970 +0000
422 date: Thu Jan 01 00:00:01 1970 +0000
423 summary: msg 1
423 summary: msg 1
424
424
425 changeset: 2:db07c04beaca
425 changeset: 2:db07c04beaca
426 user: test
426 user: test
427 date: Thu Jan 01 00:00:02 1970 +0000
427 date: Thu Jan 01 00:00:02 1970 +0000
428 summary: msg 2
428 summary: msg 2
429
429
430 changeset: 3:b53bea5e2fcb
430 changeset: 3:b53bea5e2fcb
431 user: test
431 user: test
432 date: Thu Jan 01 00:00:03 1970 +0000
432 date: Thu Jan 01 00:00:03 1970 +0000
433 summary: msg 3
433 summary: msg 3
434
434
435 changeset: 4:9b2ba8336a65
435 changeset: 4:9b2ba8336a65
436 user: test
436 user: test
437 date: Thu Jan 01 00:00:04 1970 +0000
437 date: Thu Jan 01 00:00:04 1970 +0000
438 summary: msg 4
438 summary: msg 4
439
439
440
440
441 test legacy bisected() keyword
441 test legacy bisected() keyword
442
442
443 $ hg log -r "bisected(bad)"
443 $ hg log -r "bisected(bad)"
444 changeset: 6:a3d5c6fdf0d3
444 changeset: 6:a3d5c6fdf0d3
445 user: test
445 user: test
446 date: Thu Jan 01 00:00:06 1970 +0000
446 date: Thu Jan 01 00:00:06 1970 +0000
447 summary: msg 6
447 summary: msg 6
448
448
449
449
450 $ set +e
450 $ set +e
451
451
452 test invalid command
452 test invalid command
453 assuming that the shell returns 127 if command not found ...
453 assuming that the shell returns 127 if command not found ...
454
454
455 $ hg bisect -r
455 $ hg bisect -r
456 $ hg bisect --command 'exit 127'
456 $ hg bisect --command 'exit 127'
457 abort: failed to execute exit 127
457 abort: failed to execute exit 127
458 [255]
458 [255]
459
459
460
460
461 test bisecting command
461 test bisecting command
462
462
463 $ cat > script.py <<EOF
463 $ cat > script.py <<EOF
464 > #!$PYTHON
464 > #!$PYTHON
465 > from __future__ import absolute_import
465 > from __future__ import absolute_import
466 > import sys
466 > import sys
467 > from mercurial import hg, ui as uimod
467 > from mercurial import hg, ui as uimod
468 > repo = hg.repository(uimod.ui.load(), b'.')
468 > repo = hg.repository(uimod.ui.load(), b'.')
469 > if repo[b'.'].rev() < 6:
469 > if repo[b'.'].rev() < 6:
470 > sys.exit(1)
470 > sys.exit(1)
471 > EOF
471 > EOF
472 $ chmod +x script.py
472 $ chmod +x script.py
473 $ hg bisect -r
473 $ hg bisect -r
474 $ hg up -qr tip
474 $ hg up -qr tip
475 $ hg bisect --command "\"$PYTHON\" \"$TESTTMP/script.py\" and some parameters"
475 $ hg bisect --command "\"$PYTHON\" \"$TESTTMP/script.py\" and some parameters"
476 changeset 31:58c80a7c8a40: good
476 changeset 31:58c80a7c8a40 tip "msg 31": good
477 abort: cannot bisect (no known bad revisions)
477 abort: cannot bisect (no known bad revisions)
478 [20]
478 [20]
479 $ hg up -qr 0
479 $ hg up -qr 0
480 $ hg bisect --command "\"$PYTHON\" \"$TESTTMP/script.py\" and some parameters"
480 $ hg bisect --command "\"$PYTHON\" \"$TESTTMP/script.py\" and some parameters"
481 changeset 0:b99c7b9c8e11: bad
481 changeset 0:b99c7b9c8e11 "msg 0": bad
482 changeset 15:e7fa0811edb0: good
482 changeset 15:e7fa0811edb0 "msg 15": good
483 changeset 7:03750880c6b5: good
483 changeset 7:03750880c6b5 "msg 7": good
484 changeset 3:b53bea5e2fcb: bad
484 changeset 3:b53bea5e2fcb "msg 3": bad
485 changeset 5:7874a09ea728: bad
485 changeset 5:7874a09ea728 "msg 5": bad
486 changeset 6:a3d5c6fdf0d3: good
486 changeset 6:a3d5c6fdf0d3 "msg 6": good
487 The first good revision is:
487 The first good revision is:
488 changeset: 6:a3d5c6fdf0d3
488 changeset: 6:a3d5c6fdf0d3
489 user: test
489 user: test
490 date: Thu Jan 01 00:00:06 1970 +0000
490 date: Thu Jan 01 00:00:06 1970 +0000
491 summary: msg 6
491 summary: msg 6
492
492
493
493
494
494
495 test bisecting via a command without updating the working dir, and
495 test bisecting via a command without updating the working dir, and
496 ensure that the bisect state file is updated before running a test
496 ensure that the bisect state file is updated before running a test
497 command
497 command
498
498
499 $ hg update null
499 $ hg update null
500 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
500 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
501 $ cat > script.sh <<'EOF'
501 $ cat > script.sh <<'EOF'
502 > #!/bin/sh
502 > #!/bin/sh
503 > test -n "$HG_NODE" || (echo HG_NODE missing; exit 127)
503 > test -n "$HG_NODE" || (echo HG_NODE missing; exit 127)
504 > current="`hg log -r \"bisect(current)\" --template {node}`"
504 > current="`hg log -r \"bisect(current)\" --template {node}`"
505 > test "$current" = "$HG_NODE" || (echo current is bad: $current; exit 127)
505 > test "$current" = "$HG_NODE" || (echo current is bad: $current; exit 127)
506 > rev="`hg log -r $HG_NODE --template {rev}`"
506 > rev="`hg log -r $HG_NODE --template {rev}`"
507 > test "$rev" -ge 6
507 > test "$rev" -ge 6
508 > EOF
508 > EOF
509 $ chmod +x script.sh
509 $ chmod +x script.sh
510 $ hg bisect -r
510 $ hg bisect -r
511 $ hg bisect --good tip --noupdate
511 $ hg bisect --good tip --noupdate
512 $ hg bisect --bad 0 --noupdate
512 $ hg bisect --bad 0 --noupdate
513 Testing changeset 15:e7fa0811edb0 (31 changesets remaining, ~4 tests)
513 Testing changeset 15:e7fa0811edb0 "msg 15" (31 changesets remaining, ~4 tests)
514 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params" --noupdate
514 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params" --noupdate
515 changeset 15:e7fa0811edb0: good
515 changeset 15:e7fa0811edb0 "msg 15": good
516 changeset 7:03750880c6b5: good
516 changeset 7:03750880c6b5 "msg 7": good
517 changeset 3:b53bea5e2fcb: bad
517 changeset 3:b53bea5e2fcb "msg 3": bad
518 changeset 5:7874a09ea728: bad
518 changeset 5:7874a09ea728 "msg 5": bad
519 changeset 6:a3d5c6fdf0d3: good
519 changeset 6:a3d5c6fdf0d3 "msg 6": good
520 The first good revision is:
520 The first good revision is:
521 changeset: 6:a3d5c6fdf0d3
521 changeset: 6:a3d5c6fdf0d3
522 user: test
522 user: test
523 date: Thu Jan 01 00:00:06 1970 +0000
523 date: Thu Jan 01 00:00:06 1970 +0000
524 summary: msg 6
524 summary: msg 6
525
525
526
526
527 ensure that we still don't have a working dir
527 ensure that we still don't have a working dir
528
528
529 $ hg parents
529 $ hg parents
530
530
531
531
532 test the same case, this time with updating
532 test the same case, this time with updating
533
533
534 $ cat > script.sh <<'EOF'
534 $ cat > script.sh <<'EOF'
535 > #!/bin/sh
535 > #!/bin/sh
536 > test -n "$HG_NODE" || (echo HG_NODE missing; exit 127)
536 > test -n "$HG_NODE" || (echo HG_NODE missing; exit 127)
537 > current="`hg log -r \"bisect(current)\" --template {node}`"
537 > current="`hg log -r \"bisect(current)\" --template {node}`"
538 > test "$current" = "$HG_NODE" || (echo current is bad: $current; exit 127)
538 > test "$current" = "$HG_NODE" || (echo current is bad: $current; exit 127)
539 > rev="`hg log -r . --template {rev}`"
539 > rev="`hg log -r . --template {rev}`"
540 > test "$rev" -ge 6
540 > test "$rev" -ge 6
541 > EOF
541 > EOF
542 $ chmod +x script.sh
542 $ chmod +x script.sh
543 $ hg bisect -r
543 $ hg bisect -r
544 $ hg up -qr tip
544 $ hg up -qr tip
545 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params"
545 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params"
546 changeset 31:58c80a7c8a40: good
546 changeset 31:58c80a7c8a40 tip "msg 31": good
547 abort: cannot bisect (no known bad revisions)
547 abort: cannot bisect (no known bad revisions)
548 [20]
548 [20]
549 $ hg up -qr 0
549 $ hg up -qr 0
550 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params"
550 $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params"
551 changeset 0:b99c7b9c8e11: bad
551 changeset 0:b99c7b9c8e11 "msg 0": bad
552 changeset 15:e7fa0811edb0: good
552 changeset 15:e7fa0811edb0 "msg 15": good
553 changeset 7:03750880c6b5: good
553 changeset 7:03750880c6b5 "msg 7": good
554 changeset 3:b53bea5e2fcb: bad
554 changeset 3:b53bea5e2fcb "msg 3": bad
555 changeset 5:7874a09ea728: bad
555 changeset 5:7874a09ea728 "msg 5": bad
556 changeset 6:a3d5c6fdf0d3: good
556 changeset 6:a3d5c6fdf0d3 "msg 6": good
557 The first good revision is:
557 The first good revision is:
558 changeset: 6:a3d5c6fdf0d3
558 changeset: 6:a3d5c6fdf0d3
559 user: test
559 user: test
560 date: Thu Jan 01 00:00:06 1970 +0000
560 date: Thu Jan 01 00:00:06 1970 +0000
561 summary: msg 6
561 summary: msg 6
562
562
563 $ hg graft -q 15
563 $ hg graft -q 15
564 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
564 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
565 abort: unresolved conflicts, can't continue
565 abort: unresolved conflicts, can't continue
566 (use 'hg resolve' and 'hg graft --continue')
566 (use 'hg resolve' and 'hg graft --continue')
567 [1]
567 [1]
568 $ hg bisect --reset
568 $ hg bisect --reset
569 $ hg up -C .
569 $ hg up -C .
570 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
570 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
571
571
572 Check that bisect does not break on obsolete changesets
572 Check that bisect does not break on obsolete changesets
573 =========================================================
573 =========================================================
574
574
575 $ cat >> $HGRCPATH << EOF
575 $ cat >> $HGRCPATH << EOF
576 > [experimental]
576 > [experimental]
577 > evolution.createmarkers=True
577 > evolution.createmarkers=True
578 > EOF
578 > EOF
579
579
580 tip is obsolete
580 tip is obsolete
581 ---------------------
581 ---------------------
582
582
583 $ hg debugobsolete `hg id --debug -i -r tip`
583 $ hg debugobsolete `hg id --debug -i -r tip`
584 1 new obsolescence markers
584 1 new obsolescence markers
585 obsoleted 1 changesets
585 obsoleted 1 changesets
586 $ hg bisect --reset
586 $ hg bisect --reset
587 $ hg bisect --good 15
587 $ hg bisect --good 15
588 $ hg bisect --bad 30
588 $ hg bisect --bad 30
589 Testing changeset 22:06c7993750ce (15 changesets remaining, ~3 tests)
589 Testing changeset 22:06c7993750ce "msg 22" (15 changesets remaining, ~3 tests)
590 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
590 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
591 $ hg bisect --command true
591 $ hg bisect --command true
592 changeset 22:06c7993750ce: good
592 changeset 22:06c7993750ce "msg 22": good
593 changeset 26:3efc6fd51aeb: good
593 changeset 26:3efc6fd51aeb "msg 26": good
594 changeset 28:8e0c2264c8af: good
594 changeset 28:8e0c2264c8af "msg 28": good
595 changeset 29:b5bd63375ab9: good
595 changeset 29:b5bd63375ab9 "msg 29": good
596 The first bad revision is:
596 The first bad revision is:
597 changeset: 30:ed2d2f24b11c
597 changeset: 30:ed2d2f24b11c
598 tag: tip
598 tag: tip
599 user: test
599 user: test
600 date: Thu Jan 01 00:00:30 1970 +0000
600 date: Thu Jan 01 00:00:30 1970 +0000
601 summary: msg 30
601 summary: msg 30
602
602
603
603
604 Rewritten commits should not crash
604 Rewritten commits should not crash
605
605
606 $ hg co 29
606 $ hg co 29
607 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
607 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
608 $ hg revert --all -r 30
608 $ hg revert --all -r 30
609 reverting a
609 reverting a
610 $ hg commit -m 'msg 30 -- fixed'
610 $ hg commit -m 'msg 30 -- fixed'
611 created new head
611 created new head
612 $ hg debugobsolete `hg id --debug -i -r 30` `hg id --debug -i -r .`
612 $ hg debugobsolete `hg id --debug -i -r 30` `hg id --debug -i -r .`
613 1 new obsolescence markers
613 1 new obsolescence markers
614 obsoleted 1 changesets
614 obsoleted 1 changesets
615 $ hg bisect
615 $ hg bisect
616 The first bad revision is:
616 The first bad revision is:
617 changeset: 30:ed2d2f24b11c
617 changeset: 30:ed2d2f24b11c
618 user: test
618 user: test
619 date: Thu Jan 01 00:00:30 1970 +0000
619 date: Thu Jan 01 00:00:30 1970 +0000
620 obsolete: rewritten as 32:8a638ebd1122
620 obsolete: rewritten as 32:8a638ebd1122
621 summary: msg 30
621 summary: msg 30
622
622
623
623
624 Log template does not crash
624 Log template does not crash
625
625
626 $ hg log -GTbisect -r 15::
626 $ hg log -GTbisect -r 15::
627 @ changeset: 32:8a638ebd1122
627 @ changeset: 32:8a638ebd1122
628 | bisect: good (implicit)
628 | bisect: good (implicit)
629 | tag: tip
629 | tag: tip
630 | parent: 29:b5bd63375ab9
630 | parent: 29:b5bd63375ab9
631 | user: test
631 | user: test
632 | date: Thu Jan 01 00:00:00 1970 +0000
632 | date: Thu Jan 01 00:00:00 1970 +0000
633 | summary: msg 30 -- fixed
633 | summary: msg 30 -- fixed
634 |
634 |
635 o changeset: 29:b5bd63375ab9
635 o changeset: 29:b5bd63375ab9
636 | bisect: good
636 | bisect: good
637 | user: test
637 | user: test
638 | date: Thu Jan 01 00:00:29 1970 +0000
638 | date: Thu Jan 01 00:00:29 1970 +0000
639 | summary: msg 29
639 | summary: msg 29
640 |
640 |
641 o changeset: 28:8e0c2264c8af
641 o changeset: 28:8e0c2264c8af
642 | bisect: good
642 | bisect: good
643 | user: test
643 | user: test
644 | date: Thu Jan 01 00:00:28 1970 +0000
644 | date: Thu Jan 01 00:00:28 1970 +0000
645 | summary: msg 28
645 | summary: msg 28
646 |
646 |
647 o changeset: 27:288867a866e9
647 o changeset: 27:288867a866e9
648 | bisect: ignored
648 | bisect: ignored
649 | user: test
649 | user: test
650 | date: Thu Jan 01 00:00:27 1970 +0000
650 | date: Thu Jan 01 00:00:27 1970 +0000
651 | summary: msg 27
651 | summary: msg 27
652 |
652 |
653 o changeset: 26:3efc6fd51aeb
653 o changeset: 26:3efc6fd51aeb
654 | bisect: good
654 | bisect: good
655 | user: test
655 | user: test
656 | date: Thu Jan 01 00:00:26 1970 +0000
656 | date: Thu Jan 01 00:00:26 1970 +0000
657 | summary: msg 26
657 | summary: msg 26
658 |
658 |
659 o changeset: 25:02a84173a97a
659 o changeset: 25:02a84173a97a
660 | bisect: ignored
660 | bisect: ignored
661 | user: test
661 | user: test
662 | date: Thu Jan 01 00:00:25 1970 +0000
662 | date: Thu Jan 01 00:00:25 1970 +0000
663 | summary: msg 25
663 | summary: msg 25
664 |
664 |
665 o changeset: 24:10e0acd3809e
665 o changeset: 24:10e0acd3809e
666 | bisect: ignored
666 | bisect: ignored
667 | user: test
667 | user: test
668 | date: Thu Jan 01 00:00:24 1970 +0000
668 | date: Thu Jan 01 00:00:24 1970 +0000
669 | summary: msg 24
669 | summary: msg 24
670 |
670 |
671 o changeset: 23:5ec79163bff4
671 o changeset: 23:5ec79163bff4
672 | bisect: ignored
672 | bisect: ignored
673 | user: test
673 | user: test
674 | date: Thu Jan 01 00:00:23 1970 +0000
674 | date: Thu Jan 01 00:00:23 1970 +0000
675 | summary: msg 23
675 | summary: msg 23
676 |
676 |
677 o changeset: 22:06c7993750ce
677 o changeset: 22:06c7993750ce
678 | bisect: good
678 | bisect: good
679 | user: test
679 | user: test
680 | date: Thu Jan 01 00:00:22 1970 +0000
680 | date: Thu Jan 01 00:00:22 1970 +0000
681 | summary: msg 22
681 | summary: msg 22
682 |
682 |
683 o changeset: 21:e5db6aa3fe2a
683 o changeset: 21:e5db6aa3fe2a
684 | bisect: ignored
684 | bisect: ignored
685 | user: test
685 | user: test
686 | date: Thu Jan 01 00:00:21 1970 +0000
686 | date: Thu Jan 01 00:00:21 1970 +0000
687 | summary: msg 21
687 | summary: msg 21
688 |
688 |
689 o changeset: 20:7128fb4fdbc9
689 o changeset: 20:7128fb4fdbc9
690 | bisect: ignored
690 | bisect: ignored
691 | user: test
691 | user: test
692 | date: Thu Jan 01 00:00:20 1970 +0000
692 | date: Thu Jan 01 00:00:20 1970 +0000
693 | summary: msg 20
693 | summary: msg 20
694 |
694 |
695 o changeset: 19:52798545b482
695 o changeset: 19:52798545b482
696 | bisect: ignored
696 | bisect: ignored
697 | user: test
697 | user: test
698 | date: Thu Jan 01 00:00:19 1970 +0000
698 | date: Thu Jan 01 00:00:19 1970 +0000
699 | summary: msg 19
699 | summary: msg 19
700 |
700 |
701 o changeset: 18:86977a90077e
701 o changeset: 18:86977a90077e
702 | bisect: ignored
702 | bisect: ignored
703 | user: test
703 | user: test
704 | date: Thu Jan 01 00:00:18 1970 +0000
704 | date: Thu Jan 01 00:00:18 1970 +0000
705 | summary: msg 18
705 | summary: msg 18
706 |
706 |
707 o changeset: 17:03515f4a9080
707 o changeset: 17:03515f4a9080
708 | bisect: ignored
708 | bisect: ignored
709 | user: test
709 | user: test
710 | date: Thu Jan 01 00:00:17 1970 +0000
710 | date: Thu Jan 01 00:00:17 1970 +0000
711 | summary: msg 17
711 | summary: msg 17
712 |
712 |
713 o changeset: 16:a2e6ea4973e9
713 o changeset: 16:a2e6ea4973e9
714 | bisect: ignored
714 | bisect: ignored
715 | user: test
715 | user: test
716 | date: Thu Jan 01 00:00:16 1970 +0000
716 | date: Thu Jan 01 00:00:16 1970 +0000
717 | summary: msg 16
717 | summary: msg 16
718 |
718 |
719 o changeset: 15:e7fa0811edb0
719 o changeset: 15:e7fa0811edb0
720 | bisect: good
720 | bisect: good
721 ~ user: test
721 ~ user: test
722 date: Thu Jan 01 00:00:15 1970 +0000
722 date: Thu Jan 01 00:00:15 1970 +0000
723 summary: msg 15
723 summary: msg 15
724
724
725 $ hg debugobsolete --delete `hg debugobsolete --index -T'{index}\n' | tail -1`
725 $ hg debugobsolete --delete `hg debugobsolete --index -T'{index}\n' | tail -1`
726 deleted 1 obsolescence markers
726 deleted 1 obsolescence markers
727
727
728 Changeset in the bad:good range is obsolete
728 Changeset in the bad:good range is obsolete
729 ---------------------------------------------
729 ---------------------------------------------
730
730
731 $ hg up 30
731 $ hg up 30
732 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
732 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
733 $ echo 'a' >> a
733 $ echo 'a' >> a
734 $ hg ci -m "msg 32" -d "32 0"
734 $ hg ci -m "msg 32" -d "32 0"
735 $ hg bisect --reset
735 $ hg bisect --reset
736 $ hg bisect --good .
736 $ hg bisect --good .
737 $ hg bisect --bad 25
737 $ hg bisect --bad 25
738 Testing changeset 28:8e0c2264c8af (6 changesets remaining, ~2 tests)
738 Testing changeset 28:8e0c2264c8af "msg 28" (6 changesets remaining, ~2 tests)
739 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
739 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
740 $ hg bisect --command true
740 $ hg bisect --command true
741 changeset 28:8e0c2264c8af: good
741 changeset 28:8e0c2264c8af "msg 28": good
742 changeset 26:3efc6fd51aeb: good
742 changeset 26:3efc6fd51aeb "msg 26": good
743 The first good revision is:
743 The first good revision is:
744 changeset: 26:3efc6fd51aeb
744 changeset: 26:3efc6fd51aeb
745 user: test
745 user: test
746 date: Thu Jan 01 00:00:26 1970 +0000
746 date: Thu Jan 01 00:00:26 1970 +0000
747 summary: msg 26
747 summary: msg 26
748
748
749 Test the validation message when exclusive options are used:
749 Test the validation message when exclusive options are used:
750
750
751 $ hg bisect -r
751 $ hg bisect -r
752 $ hg bisect -b -c false
752 $ hg bisect -b -c false
753 abort: --bad and --command are incompatible
753 abort: --bad and --command are incompatible
754 [10]
754 [10]
755 $ hg bisect -b -e
755 $ hg bisect -b -e
756 abort: --bad and --extend are incompatible
756 abort: --bad and --extend are incompatible
757 [10]
757 [10]
758 $ hg bisect -b -g
758 $ hg bisect -b -g
759 abort: --bad and --good are incompatible
759 abort: --bad and --good are incompatible
760 [10]
760 [10]
761 $ hg bisect -b -r
761 $ hg bisect -b -r
762 abort: --bad and --reset are incompatible
762 abort: --bad and --reset are incompatible
763 [10]
763 [10]
764 $ hg bisect -b -s
764 $ hg bisect -b -s
765 abort: --bad and --skip are incompatible
765 abort: --bad and --skip are incompatible
766 [10]
766 [10]
767 $ hg bisect -c false -e
767 $ hg bisect -c false -e
768 abort: --command and --extend are incompatible
768 abort: --command and --extend are incompatible
769 [10]
769 [10]
770 $ hg bisect -c false -g
770 $ hg bisect -c false -g
771 abort: --command and --good are incompatible
771 abort: --command and --good are incompatible
772 [10]
772 [10]
773 $ hg bisect -c false -r
773 $ hg bisect -c false -r
774 abort: --command and --reset are incompatible
774 abort: --command and --reset are incompatible
775 [10]
775 [10]
776 $ hg bisect -c false -s
776 $ hg bisect -c false -s
777 abort: --command and --skip are incompatible
777 abort: --command and --skip are incompatible
778 [10]
778 [10]
779 $ hg bisect -e -g
779 $ hg bisect -e -g
780 abort: --extend and --good are incompatible
780 abort: --extend and --good are incompatible
781 [10]
781 [10]
782 $ hg bisect -e -r
782 $ hg bisect -e -r
783 abort: --extend and --reset are incompatible
783 abort: --extend and --reset are incompatible
784 [10]
784 [10]
785 $ hg bisect -e -s
785 $ hg bisect -e -s
786 abort: --extend and --skip are incompatible
786 abort: --extend and --skip are incompatible
787 [10]
787 [10]
788 $ hg bisect -g -r
788 $ hg bisect -g -r
789 abort: --good and --reset are incompatible
789 abort: --good and --reset are incompatible
790 [10]
790 [10]
791 $ hg bisect -g -s
791 $ hg bisect -g -s
792 abort: --good and --skip are incompatible
792 abort: --good and --skip are incompatible
793 [10]
793 [10]
794 $ hg bisect -r -s
794 $ hg bisect -r -s
795 abort: --reset and --skip are incompatible
795 abort: --reset and --skip are incompatible
796 [10]
796 [10]
@@ -1,797 +1,797 b''
1 # The tests in test-bisect are done on a linear history. Here the
1 # The tests in test-bisect are done on a linear history. Here the
2 # following repository history is used for testing:
2 # following repository history is used for testing:
3 #
3 #
4 # 17
4 # 17
5 # |
5 # |
6 # 18 16
6 # 18 16
7 # \ /
7 # \ /
8 # 15
8 # 15
9 # / \
9 # / \
10 # / \
10 # / \
11 # 10 13
11 # 10 13
12 # / \ |
12 # / \ |
13 # / \ | 14
13 # / \ | 14
14 # 7 6 9 12 /
14 # 7 6 9 12 /
15 # \ / \ | |/
15 # \ / \ | |/
16 # 4 \ | 11
16 # 4 \ | 11
17 # \ \ | /
17 # \ \ | /
18 # 3 5 | /
18 # 3 5 | /
19 # \ / |/
19 # \ / |/
20 # 2 8
20 # 2 8
21 # \ /
21 # \ /
22 # 1
22 # 1
23 # |
23 # |
24 # 0
24 # 0
25
25
26 init
26 init
27
27
28 $ hg init
28 $ hg init
29
29
30 committing changes
30 committing changes
31
31
32 $ echo > a
32 $ echo > a
33 $ echo '0' >> a
33 $ echo '0' >> a
34 $ hg add a
34 $ hg add a
35 $ hg ci -m "0" -d "0 0"
35 $ hg ci -m "0" -d "0 0"
36 $ echo '1' >> a
36 $ echo '1' >> a
37 $ hg ci -m "1" -d "1 0"
37 $ hg ci -m "1" -d "1 0"
38 $ echo '2' >> a
38 $ echo '2' >> a
39 $ hg ci -m "2" -d "2 0"
39 $ hg ci -m "2" -d "2 0"
40 $ echo '3' >> a
40 $ echo '3' >> a
41 $ hg ci -m "3" -d "3 0"
41 $ hg ci -m "3" -d "3 0"
42 $ echo '4' >> a
42 $ echo '4' >> a
43 $ hg ci -m "4" -d "4 0"
43 $ hg ci -m "4" -d "4 0"
44
44
45 create branch
45 create branch
46
46
47 $ hg up -r 2
47 $ hg up -r 2
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 $ echo '5' >> b
49 $ echo '5' >> b
50 $ hg add b
50 $ hg add b
51 $ hg ci -m "5" -d "5 0"
51 $ hg ci -m "5" -d "5 0"
52 created new head
52 created new head
53
53
54 merge
54 merge
55
55
56 $ hg merge
56 $ hg merge
57 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
57 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 (branch merge, don't forget to commit)
58 (branch merge, don't forget to commit)
59 $ hg ci -m "merge 4,5" -d "6 0"
59 $ hg ci -m "merge 4,5" -d "6 0"
60
60
61 create branch
61 create branch
62
62
63 $ hg up -r 4
63 $ hg up -r 4
64 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
64 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
65 $ echo '7' > c
65 $ echo '7' > c
66 $ hg add c
66 $ hg add c
67 $ hg ci -m "7" -d "7 0"
67 $ hg ci -m "7" -d "7 0"
68 created new head
68 created new head
69
69
70 create branch
70 create branch
71
71
72 $ hg up -r 1
72 $ hg up -r 1
73 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
73 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
74 $ echo '8' > d
74 $ echo '8' > d
75 $ hg add d
75 $ hg add d
76 $ hg ci -m "8" -d "8 0"
76 $ hg ci -m "8" -d "8 0"
77 created new head
77 created new head
78 $ echo '9' >> d
78 $ echo '9' >> d
79 $ hg ci -m "9" -d "9 0"
79 $ hg ci -m "9" -d "9 0"
80
80
81 merge
81 merge
82
82
83 $ hg merge -r 6
83 $ hg merge -r 6
84 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 (branch merge, don't forget to commit)
85 (branch merge, don't forget to commit)
86 $ hg ci -m "merge 6,9" -d "10 0"
86 $ hg ci -m "merge 6,9" -d "10 0"
87
87
88 create branch
88 create branch
89
89
90 $ hg up -r 8
90 $ hg up -r 8
91 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
91 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
92 $ echo '11' > e
92 $ echo '11' > e
93 $ hg add e
93 $ hg add e
94 $ hg ci -m "11" -d "11 0"
94 $ hg ci -m "11" -d "11 0"
95 created new head
95 created new head
96 $ echo '12' >> e
96 $ echo '12' >> e
97 $ hg ci -m "12" -d "12 0"
97 $ hg ci -m "12" -d "12 0"
98 $ echo '13' >> e
98 $ echo '13' >> e
99 $ hg ci -m "13" -d "13 0"
99 $ hg ci -m "13" -d "13 0"
100
100
101 create branch
101 create branch
102
102
103 $ hg up -r 11
103 $ hg up -r 11
104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
105 $ echo '14' > f
105 $ echo '14' > f
106 $ hg add f
106 $ hg add f
107 $ hg ci -m "14" -d "14 0"
107 $ hg ci -m "14" -d "14 0"
108 created new head
108 created new head
109
109
110 merge
110 merge
111
111
112 $ hg up -r 13 -C
112 $ hg up -r 13 -C
113 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
113 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
114 $ hg merge -r 10
114 $ hg merge -r 10
115 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
115 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 (branch merge, don't forget to commit)
116 (branch merge, don't forget to commit)
117 $ hg ci -m "merge 10,13" -d "15 0"
117 $ hg ci -m "merge 10,13" -d "15 0"
118 $ echo '16' >> e
118 $ echo '16' >> e
119 $ hg ci -m "16" -d "16 0"
119 $ hg ci -m "16" -d "16 0"
120 $ echo '17' >> e
120 $ echo '17' >> e
121 $ hg ci -m "17" -d "17 0"
121 $ hg ci -m "17" -d "17 0"
122
122
123 create branch
123 create branch
124
124
125 $ hg up -r 15
125 $ hg up -r 15
126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 $ echo '18' >> e
127 $ echo '18' >> e
128 $ hg ci -m "18" -d "18 0"
128 $ hg ci -m "18" -d "18 0"
129 created new head
129 created new head
130
130
131 log
131 log
132
132
133 $ hg log
133 $ hg log
134 changeset: 18:d42e18c7bc9b
134 changeset: 18:d42e18c7bc9b
135 tag: tip
135 tag: tip
136 parent: 15:857b178a7cf3
136 parent: 15:857b178a7cf3
137 user: test
137 user: test
138 date: Thu Jan 01 00:00:18 1970 +0000
138 date: Thu Jan 01 00:00:18 1970 +0000
139 summary: 18
139 summary: 18
140
140
141 changeset: 17:228c06deef46
141 changeset: 17:228c06deef46
142 user: test
142 user: test
143 date: Thu Jan 01 00:00:17 1970 +0000
143 date: Thu Jan 01 00:00:17 1970 +0000
144 summary: 17
144 summary: 17
145
145
146 changeset: 16:609d82a7ebae
146 changeset: 16:609d82a7ebae
147 user: test
147 user: test
148 date: Thu Jan 01 00:00:16 1970 +0000
148 date: Thu Jan 01 00:00:16 1970 +0000
149 summary: 16
149 summary: 16
150
150
151 changeset: 15:857b178a7cf3
151 changeset: 15:857b178a7cf3
152 parent: 13:b0a32c86eb31
152 parent: 13:b0a32c86eb31
153 parent: 10:429fcd26f52d
153 parent: 10:429fcd26f52d
154 user: test
154 user: test
155 date: Thu Jan 01 00:00:15 1970 +0000
155 date: Thu Jan 01 00:00:15 1970 +0000
156 summary: merge 10,13
156 summary: merge 10,13
157
157
158 changeset: 14:faa450606157
158 changeset: 14:faa450606157
159 parent: 11:82ca6f06eccd
159 parent: 11:82ca6f06eccd
160 user: test
160 user: test
161 date: Thu Jan 01 00:00:14 1970 +0000
161 date: Thu Jan 01 00:00:14 1970 +0000
162 summary: 14
162 summary: 14
163
163
164 changeset: 13:b0a32c86eb31
164 changeset: 13:b0a32c86eb31
165 user: test
165 user: test
166 date: Thu Jan 01 00:00:13 1970 +0000
166 date: Thu Jan 01 00:00:13 1970 +0000
167 summary: 13
167 summary: 13
168
168
169 changeset: 12:9f259202bbe7
169 changeset: 12:9f259202bbe7
170 user: test
170 user: test
171 date: Thu Jan 01 00:00:12 1970 +0000
171 date: Thu Jan 01 00:00:12 1970 +0000
172 summary: 12
172 summary: 12
173
173
174 changeset: 11:82ca6f06eccd
174 changeset: 11:82ca6f06eccd
175 parent: 8:dab8161ac8fc
175 parent: 8:dab8161ac8fc
176 user: test
176 user: test
177 date: Thu Jan 01 00:00:11 1970 +0000
177 date: Thu Jan 01 00:00:11 1970 +0000
178 summary: 11
178 summary: 11
179
179
180 changeset: 10:429fcd26f52d
180 changeset: 10:429fcd26f52d
181 parent: 9:3c77083deb4a
181 parent: 9:3c77083deb4a
182 parent: 6:a214d5d3811a
182 parent: 6:a214d5d3811a
183 user: test
183 user: test
184 date: Thu Jan 01 00:00:10 1970 +0000
184 date: Thu Jan 01 00:00:10 1970 +0000
185 summary: merge 6,9
185 summary: merge 6,9
186
186
187 changeset: 9:3c77083deb4a
187 changeset: 9:3c77083deb4a
188 user: test
188 user: test
189 date: Thu Jan 01 00:00:09 1970 +0000
189 date: Thu Jan 01 00:00:09 1970 +0000
190 summary: 9
190 summary: 9
191
191
192 changeset: 8:dab8161ac8fc
192 changeset: 8:dab8161ac8fc
193 parent: 1:4ca5088da217
193 parent: 1:4ca5088da217
194 user: test
194 user: test
195 date: Thu Jan 01 00:00:08 1970 +0000
195 date: Thu Jan 01 00:00:08 1970 +0000
196 summary: 8
196 summary: 8
197
197
198 changeset: 7:50c76098bbf2
198 changeset: 7:50c76098bbf2
199 parent: 4:5c668c22234f
199 parent: 4:5c668c22234f
200 user: test
200 user: test
201 date: Thu Jan 01 00:00:07 1970 +0000
201 date: Thu Jan 01 00:00:07 1970 +0000
202 summary: 7
202 summary: 7
203
203
204 changeset: 6:a214d5d3811a
204 changeset: 6:a214d5d3811a
205 parent: 5:385a529b6670
205 parent: 5:385a529b6670
206 parent: 4:5c668c22234f
206 parent: 4:5c668c22234f
207 user: test
207 user: test
208 date: Thu Jan 01 00:00:06 1970 +0000
208 date: Thu Jan 01 00:00:06 1970 +0000
209 summary: merge 4,5
209 summary: merge 4,5
210
210
211 changeset: 5:385a529b6670
211 changeset: 5:385a529b6670
212 parent: 2:051e12f87bf1
212 parent: 2:051e12f87bf1
213 user: test
213 user: test
214 date: Thu Jan 01 00:00:05 1970 +0000
214 date: Thu Jan 01 00:00:05 1970 +0000
215 summary: 5
215 summary: 5
216
216
217 changeset: 4:5c668c22234f
217 changeset: 4:5c668c22234f
218 user: test
218 user: test
219 date: Thu Jan 01 00:00:04 1970 +0000
219 date: Thu Jan 01 00:00:04 1970 +0000
220 summary: 4
220 summary: 4
221
221
222 changeset: 3:0950834f0a9c
222 changeset: 3:0950834f0a9c
223 user: test
223 user: test
224 date: Thu Jan 01 00:00:03 1970 +0000
224 date: Thu Jan 01 00:00:03 1970 +0000
225 summary: 3
225 summary: 3
226
226
227 changeset: 2:051e12f87bf1
227 changeset: 2:051e12f87bf1
228 user: test
228 user: test
229 date: Thu Jan 01 00:00:02 1970 +0000
229 date: Thu Jan 01 00:00:02 1970 +0000
230 summary: 2
230 summary: 2
231
231
232 changeset: 1:4ca5088da217
232 changeset: 1:4ca5088da217
233 user: test
233 user: test
234 date: Thu Jan 01 00:00:01 1970 +0000
234 date: Thu Jan 01 00:00:01 1970 +0000
235 summary: 1
235 summary: 1
236
236
237 changeset: 0:33b1f9bc8bc5
237 changeset: 0:33b1f9bc8bc5
238 user: test
238 user: test
239 date: Thu Jan 01 00:00:00 1970 +0000
239 date: Thu Jan 01 00:00:00 1970 +0000
240 summary: 0
240 summary: 0
241
241
242
242
243 hg up -C
243 hg up -C
244
244
245 $ hg up -C
245 $ hg up -C
246 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
246 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
247 updated to "d42e18c7bc9b: 18"
247 updated to "d42e18c7bc9b: 18"
248 3 other heads for branch "default"
248 3 other heads for branch "default"
249
249
250 complex bisect test 1 # first bad rev is 9
250 complex bisect test 1 # first bad rev is 9
251
251
252 $ hg bisect -r
252 $ hg bisect -r
253 $ hg bisect -g 0
253 $ hg bisect -g 0
254 $ hg bisect -b 17 # -> update to rev 6
254 $ hg bisect -b 17 # -> update to rev 6
255 Testing changeset 6:a214d5d3811a (15 changesets remaining, ~3 tests)
255 Testing changeset 6:a214d5d3811a "merge 4,5" (15 changesets remaining, ~3 tests)
256 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
256 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
257 $ hg log -q -r 'bisect(pruned)'
257 $ hg log -q -r 'bisect(pruned)'
258 0:33b1f9bc8bc5
258 0:33b1f9bc8bc5
259 17:228c06deef46
259 17:228c06deef46
260 $ hg log -q -r 'bisect(untested)'
260 $ hg log -q -r 'bisect(untested)'
261 1:4ca5088da217
261 1:4ca5088da217
262 2:051e12f87bf1
262 2:051e12f87bf1
263 3:0950834f0a9c
263 3:0950834f0a9c
264 4:5c668c22234f
264 4:5c668c22234f
265 5:385a529b6670
265 5:385a529b6670
266 6:a214d5d3811a
266 6:a214d5d3811a
267 8:dab8161ac8fc
267 8:dab8161ac8fc
268 9:3c77083deb4a
268 9:3c77083deb4a
269 10:429fcd26f52d
269 10:429fcd26f52d
270 11:82ca6f06eccd
270 11:82ca6f06eccd
271 12:9f259202bbe7
271 12:9f259202bbe7
272 13:b0a32c86eb31
272 13:b0a32c86eb31
273 15:857b178a7cf3
273 15:857b178a7cf3
274 16:609d82a7ebae
274 16:609d82a7ebae
275 $ hg log -q -r 'bisect(ignored)'
275 $ hg log -q -r 'bisect(ignored)'
276 $ hg bisect -g # -> update to rev 13
276 $ hg bisect -g # -> update to rev 13
277 Testing changeset 13:b0a32c86eb31 (9 changesets remaining, ~3 tests)
277 Testing changeset 13:b0a32c86eb31 "13" (9 changesets remaining, ~3 tests)
278 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
278 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
279 $ hg bisect -s # -> update to rev 10
279 $ hg bisect -s # -> update to rev 10
280 Testing changeset 10:429fcd26f52d (9 changesets remaining, ~3 tests)
280 Testing changeset 10:429fcd26f52d "merge 6,9" (9 changesets remaining, ~3 tests)
281 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
281 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
282 $ hg bisect -b # -> update to rev 8
282 $ hg bisect -b # -> update to rev 8
283 Testing changeset 8:dab8161ac8fc (3 changesets remaining, ~1 tests)
283 Testing changeset 8:dab8161ac8fc "8" (3 changesets remaining, ~1 tests)
284 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
284 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
285 $ hg bisect -g # -> update to rev 9
285 $ hg bisect -g # -> update to rev 9
286 Testing changeset 9:3c77083deb4a (2 changesets remaining, ~1 tests)
286 Testing changeset 9:3c77083deb4a "9" (2 changesets remaining, ~1 tests)
287 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
287 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
288 $ hg bisect -b
288 $ hg bisect -b
289 The first bad revision is:
289 The first bad revision is:
290 changeset: 9:3c77083deb4a
290 changeset: 9:3c77083deb4a
291 user: test
291 user: test
292 date: Thu Jan 01 00:00:09 1970 +0000
292 date: Thu Jan 01 00:00:09 1970 +0000
293 summary: 9
293 summary: 9
294
294
295 $ hg log -q -r 'bisect(range)'
295 $ hg log -q -r 'bisect(range)'
296 0:33b1f9bc8bc5
296 0:33b1f9bc8bc5
297 1:4ca5088da217
297 1:4ca5088da217
298 2:051e12f87bf1
298 2:051e12f87bf1
299 3:0950834f0a9c
299 3:0950834f0a9c
300 4:5c668c22234f
300 4:5c668c22234f
301 5:385a529b6670
301 5:385a529b6670
302 6:a214d5d3811a
302 6:a214d5d3811a
303 8:dab8161ac8fc
303 8:dab8161ac8fc
304 9:3c77083deb4a
304 9:3c77083deb4a
305 10:429fcd26f52d
305 10:429fcd26f52d
306 11:82ca6f06eccd
306 11:82ca6f06eccd
307 12:9f259202bbe7
307 12:9f259202bbe7
308 13:b0a32c86eb31
308 13:b0a32c86eb31
309 15:857b178a7cf3
309 15:857b178a7cf3
310 16:609d82a7ebae
310 16:609d82a7ebae
311 17:228c06deef46
311 17:228c06deef46
312 $ hg log -q -r 'bisect(pruned)'
312 $ hg log -q -r 'bisect(pruned)'
313 0:33b1f9bc8bc5
313 0:33b1f9bc8bc5
314 1:4ca5088da217
314 1:4ca5088da217
315 2:051e12f87bf1
315 2:051e12f87bf1
316 3:0950834f0a9c
316 3:0950834f0a9c
317 4:5c668c22234f
317 4:5c668c22234f
318 5:385a529b6670
318 5:385a529b6670
319 6:a214d5d3811a
319 6:a214d5d3811a
320 8:dab8161ac8fc
320 8:dab8161ac8fc
321 9:3c77083deb4a
321 9:3c77083deb4a
322 10:429fcd26f52d
322 10:429fcd26f52d
323 13:b0a32c86eb31
323 13:b0a32c86eb31
324 15:857b178a7cf3
324 15:857b178a7cf3
325 16:609d82a7ebae
325 16:609d82a7ebae
326 17:228c06deef46
326 17:228c06deef46
327 18:d42e18c7bc9b
327 18:d42e18c7bc9b
328 $ hg log -q -r 'bisect(untested)'
328 $ hg log -q -r 'bisect(untested)'
329 11:82ca6f06eccd
329 11:82ca6f06eccd
330 12:9f259202bbe7
330 12:9f259202bbe7
331 $ hg log -q -r 'bisect(goods)'
331 $ hg log -q -r 'bisect(goods)'
332 0:33b1f9bc8bc5
332 0:33b1f9bc8bc5
333 1:4ca5088da217
333 1:4ca5088da217
334 2:051e12f87bf1
334 2:051e12f87bf1
335 3:0950834f0a9c
335 3:0950834f0a9c
336 4:5c668c22234f
336 4:5c668c22234f
337 5:385a529b6670
337 5:385a529b6670
338 6:a214d5d3811a
338 6:a214d5d3811a
339 8:dab8161ac8fc
339 8:dab8161ac8fc
340 $ hg log -q -r 'bisect(bads)'
340 $ hg log -q -r 'bisect(bads)'
341 9:3c77083deb4a
341 9:3c77083deb4a
342 10:429fcd26f52d
342 10:429fcd26f52d
343 15:857b178a7cf3
343 15:857b178a7cf3
344 16:609d82a7ebae
344 16:609d82a7ebae
345 17:228c06deef46
345 17:228c06deef46
346 18:d42e18c7bc9b
346 18:d42e18c7bc9b
347
347
348 complex bisect test 2 # first good rev is 13
348 complex bisect test 2 # first good rev is 13
349
349
350 $ hg bisect -r
350 $ hg bisect -r
351 $ hg bisect -g 18
351 $ hg bisect -g 18
352 $ hg bisect -b 1 # -> update to rev 6
352 $ hg bisect -b 1 # -> update to rev 6
353 Testing changeset 6:a214d5d3811a (13 changesets remaining, ~3 tests)
353 Testing changeset 6:a214d5d3811a "merge 4,5" (13 changesets remaining, ~3 tests)
354 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
354 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
355 $ hg bisect -s # -> update to rev 10
355 $ hg bisect -s # -> update to rev 10
356 Testing changeset 10:429fcd26f52d (13 changesets remaining, ~3 tests)
356 Testing changeset 10:429fcd26f52d "merge 6,9" (13 changesets remaining, ~3 tests)
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 $ hg log -q -r 'bisect(pruned)'
358 $ hg log -q -r 'bisect(pruned)'
359 0:33b1f9bc8bc5
359 0:33b1f9bc8bc5
360 1:4ca5088da217
360 1:4ca5088da217
361 6:a214d5d3811a
361 6:a214d5d3811a
362 18:d42e18c7bc9b
362 18:d42e18c7bc9b
363 $ hg bisect -b # -> update to rev 12
363 $ hg bisect -b # -> update to rev 12
364 Testing changeset 12:9f259202bbe7 (5 changesets remaining, ~2 tests)
364 Testing changeset 12:9f259202bbe7 "12" (5 changesets remaining, ~2 tests)
365 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
365 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
366 $ hg log -q -r 'bisect(pruned)'
366 $ hg log -q -r 'bisect(pruned)'
367 0:33b1f9bc8bc5
367 0:33b1f9bc8bc5
368 1:4ca5088da217
368 1:4ca5088da217
369 2:051e12f87bf1
369 2:051e12f87bf1
370 3:0950834f0a9c
370 3:0950834f0a9c
371 4:5c668c22234f
371 4:5c668c22234f
372 5:385a529b6670
372 5:385a529b6670
373 6:a214d5d3811a
373 6:a214d5d3811a
374 8:dab8161ac8fc
374 8:dab8161ac8fc
375 9:3c77083deb4a
375 9:3c77083deb4a
376 10:429fcd26f52d
376 10:429fcd26f52d
377 18:d42e18c7bc9b
377 18:d42e18c7bc9b
378 $ hg log -q -r 'bisect(untested)'
378 $ hg log -q -r 'bisect(untested)'
379 11:82ca6f06eccd
379 11:82ca6f06eccd
380 12:9f259202bbe7
380 12:9f259202bbe7
381 13:b0a32c86eb31
381 13:b0a32c86eb31
382 15:857b178a7cf3
382 15:857b178a7cf3
383 $ hg bisect -b # -> update to rev 13
383 $ hg bisect -b # -> update to rev 13
384 Testing changeset 13:b0a32c86eb31 (3 changesets remaining, ~1 tests)
384 Testing changeset 13:b0a32c86eb31 "13" (3 changesets remaining, ~1 tests)
385 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
385 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
386 $ hg bisect -g
386 $ hg bisect -g
387 The first good revision is:
387 The first good revision is:
388 changeset: 13:b0a32c86eb31
388 changeset: 13:b0a32c86eb31
389 user: test
389 user: test
390 date: Thu Jan 01 00:00:13 1970 +0000
390 date: Thu Jan 01 00:00:13 1970 +0000
391 summary: 13
391 summary: 13
392
392
393 $ hg log -q -r 'bisect(range)'
393 $ hg log -q -r 'bisect(range)'
394 1:4ca5088da217
394 1:4ca5088da217
395 2:051e12f87bf1
395 2:051e12f87bf1
396 3:0950834f0a9c
396 3:0950834f0a9c
397 4:5c668c22234f
397 4:5c668c22234f
398 5:385a529b6670
398 5:385a529b6670
399 6:a214d5d3811a
399 6:a214d5d3811a
400 8:dab8161ac8fc
400 8:dab8161ac8fc
401 9:3c77083deb4a
401 9:3c77083deb4a
402 10:429fcd26f52d
402 10:429fcd26f52d
403 11:82ca6f06eccd
403 11:82ca6f06eccd
404 12:9f259202bbe7
404 12:9f259202bbe7
405 13:b0a32c86eb31
405 13:b0a32c86eb31
406 15:857b178a7cf3
406 15:857b178a7cf3
407 18:d42e18c7bc9b
407 18:d42e18c7bc9b
408
408
409 complex bisect test 3
409 complex bisect test 3
410
410
411 first bad rev is 15
411 first bad rev is 15
412 10,9,13 are skipped an might be the first bad revisions as well
412 10,9,13 are skipped an might be the first bad revisions as well
413
413
414 $ hg bisect -r
414 $ hg bisect -r
415 $ hg bisect -g 1
415 $ hg bisect -g 1
416 $ hg bisect -b 16 # -> update to rev 6
416 $ hg bisect -b 16 # -> update to rev 6
417 Testing changeset 6:a214d5d3811a (13 changesets remaining, ~3 tests)
417 Testing changeset 6:a214d5d3811a "merge 4,5" (13 changesets remaining, ~3 tests)
418 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
418 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
419 $ hg log -q -r 'bisect(pruned)'
419 $ hg log -q -r 'bisect(pruned)'
420 0:33b1f9bc8bc5
420 0:33b1f9bc8bc5
421 1:4ca5088da217
421 1:4ca5088da217
422 16:609d82a7ebae
422 16:609d82a7ebae
423 17:228c06deef46
423 17:228c06deef46
424 $ hg bisect -g # -> update to rev 13
424 $ hg bisect -g # -> update to rev 13
425 Testing changeset 13:b0a32c86eb31 (8 changesets remaining, ~3 tests)
425 Testing changeset 13:b0a32c86eb31 "13" (8 changesets remaining, ~3 tests)
426 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
426 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
427 $ hg bisect -s # -> update to rev 10
427 $ hg bisect -s # -> update to rev 10
428 Testing changeset 10:429fcd26f52d (8 changesets remaining, ~3 tests)
428 Testing changeset 10:429fcd26f52d "merge 6,9" (8 changesets remaining, ~3 tests)
429 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
429 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
430 $ hg bisect -s # -> update to rev 12
430 $ hg bisect -s # -> update to rev 12
431 Testing changeset 12:9f259202bbe7 (8 changesets remaining, ~3 tests)
431 Testing changeset 12:9f259202bbe7 "12" (8 changesets remaining, ~3 tests)
432 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
432 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
433 $ hg log -q -r 'bisect(pruned)'
433 $ hg log -q -r 'bisect(pruned)'
434 0:33b1f9bc8bc5
434 0:33b1f9bc8bc5
435 1:4ca5088da217
435 1:4ca5088da217
436 2:051e12f87bf1
436 2:051e12f87bf1
437 3:0950834f0a9c
437 3:0950834f0a9c
438 4:5c668c22234f
438 4:5c668c22234f
439 5:385a529b6670
439 5:385a529b6670
440 6:a214d5d3811a
440 6:a214d5d3811a
441 10:429fcd26f52d
441 10:429fcd26f52d
442 13:b0a32c86eb31
442 13:b0a32c86eb31
443 16:609d82a7ebae
443 16:609d82a7ebae
444 17:228c06deef46
444 17:228c06deef46
445 $ hg bisect -g # -> update to rev 9
445 $ hg bisect -g # -> update to rev 9
446 Testing changeset 9:3c77083deb4a (5 changesets remaining, ~2 tests)
446 Testing changeset 9:3c77083deb4a "9" (5 changesets remaining, ~2 tests)
447 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
447 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
448 $ hg bisect -s # -> update to rev 15
448 $ hg bisect -s # -> update to rev 15
449 Testing changeset 15:857b178a7cf3 (5 changesets remaining, ~2 tests)
449 Testing changeset 15:857b178a7cf3 "merge 10,13" (5 changesets remaining, ~2 tests)
450 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
450 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
451 $ hg log -q -r 'bisect(ignored)'
451 $ hg log -q -r 'bisect(ignored)'
452 $ hg bisect -b
452 $ hg bisect -b
453 Due to skipped revisions, the first bad revision could be any of:
453 Due to skipped revisions, the first bad revision could be any of:
454 changeset: 9:3c77083deb4a
454 changeset: 9:3c77083deb4a
455 user: test
455 user: test
456 date: Thu Jan 01 00:00:09 1970 +0000
456 date: Thu Jan 01 00:00:09 1970 +0000
457 summary: 9
457 summary: 9
458
458
459 changeset: 10:429fcd26f52d
459 changeset: 10:429fcd26f52d
460 parent: 9:3c77083deb4a
460 parent: 9:3c77083deb4a
461 parent: 6:a214d5d3811a
461 parent: 6:a214d5d3811a
462 user: test
462 user: test
463 date: Thu Jan 01 00:00:10 1970 +0000
463 date: Thu Jan 01 00:00:10 1970 +0000
464 summary: merge 6,9
464 summary: merge 6,9
465
465
466 changeset: 13:b0a32c86eb31
466 changeset: 13:b0a32c86eb31
467 user: test
467 user: test
468 date: Thu Jan 01 00:00:13 1970 +0000
468 date: Thu Jan 01 00:00:13 1970 +0000
469 summary: 13
469 summary: 13
470
470
471 changeset: 15:857b178a7cf3
471 changeset: 15:857b178a7cf3
472 parent: 13:b0a32c86eb31
472 parent: 13:b0a32c86eb31
473 parent: 10:429fcd26f52d
473 parent: 10:429fcd26f52d
474 user: test
474 user: test
475 date: Thu Jan 01 00:00:15 1970 +0000
475 date: Thu Jan 01 00:00:15 1970 +0000
476 summary: merge 10,13
476 summary: merge 10,13
477
477
478 $ hg log -q -r 'bisect(range)'
478 $ hg log -q -r 'bisect(range)'
479 1:4ca5088da217
479 1:4ca5088da217
480 2:051e12f87bf1
480 2:051e12f87bf1
481 3:0950834f0a9c
481 3:0950834f0a9c
482 4:5c668c22234f
482 4:5c668c22234f
483 5:385a529b6670
483 5:385a529b6670
484 6:a214d5d3811a
484 6:a214d5d3811a
485 8:dab8161ac8fc
485 8:dab8161ac8fc
486 9:3c77083deb4a
486 9:3c77083deb4a
487 10:429fcd26f52d
487 10:429fcd26f52d
488 11:82ca6f06eccd
488 11:82ca6f06eccd
489 12:9f259202bbe7
489 12:9f259202bbe7
490 13:b0a32c86eb31
490 13:b0a32c86eb31
491 15:857b178a7cf3
491 15:857b178a7cf3
492 16:609d82a7ebae
492 16:609d82a7ebae
493 $ hg log -q -r 'bisect(ignored)'
493 $ hg log -q -r 'bisect(ignored)'
494
494
495 complex bisect test 4
495 complex bisect test 4
496
496
497 first good revision is 17
497 first good revision is 17
498 15,16 are skipped an might be the first good revisions as well
498 15,16 are skipped an might be the first good revisions as well
499
499
500 $ hg bisect -r
500 $ hg bisect -r
501 $ hg bisect -g 17
501 $ hg bisect -g 17
502 $ hg bisect -b 8 # -> update to rev 10
502 $ hg bisect -b 8 # -> update to rev 10
503 Testing changeset 13:b0a32c86eb31 (8 changesets remaining, ~3 tests)
503 Testing changeset 13:b0a32c86eb31 "13" (8 changesets remaining, ~3 tests)
504 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
504 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
505 $ hg bisect -b # -> update to rev 13
505 $ hg bisect -b # -> update to rev 13
506 Testing changeset 10:429fcd26f52d (5 changesets remaining, ~2 tests)
506 Testing changeset 10:429fcd26f52d "merge 6,9" (5 changesets remaining, ~2 tests)
507 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
507 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
508 $ hg bisect -b # -> update to rev 15
508 $ hg bisect -b # -> update to rev 15
509 Testing changeset 15:857b178a7cf3 (3 changesets remaining, ~1 tests)
509 Testing changeset 15:857b178a7cf3 "merge 10,13" (3 changesets remaining, ~1 tests)
510 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
510 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
511 $ hg log -q -r 'bisect(pruned)'
511 $ hg log -q -r 'bisect(pruned)'
512 0:33b1f9bc8bc5
512 0:33b1f9bc8bc5
513 1:4ca5088da217
513 1:4ca5088da217
514 2:051e12f87bf1
514 2:051e12f87bf1
515 3:0950834f0a9c
515 3:0950834f0a9c
516 4:5c668c22234f
516 4:5c668c22234f
517 5:385a529b6670
517 5:385a529b6670
518 6:a214d5d3811a
518 6:a214d5d3811a
519 8:dab8161ac8fc
519 8:dab8161ac8fc
520 9:3c77083deb4a
520 9:3c77083deb4a
521 10:429fcd26f52d
521 10:429fcd26f52d
522 11:82ca6f06eccd
522 11:82ca6f06eccd
523 12:9f259202bbe7
523 12:9f259202bbe7
524 13:b0a32c86eb31
524 13:b0a32c86eb31
525 17:228c06deef46
525 17:228c06deef46
526 $ hg bisect -s # -> update to rev 16
526 $ hg bisect -s # -> update to rev 16
527 Testing changeset 16:609d82a7ebae (3 changesets remaining, ~1 tests)
527 Testing changeset 16:609d82a7ebae "16" (3 changesets remaining, ~1 tests)
528 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
528 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
529 $ hg log -q -r 'bisect(pruned)'
529 $ hg log -q -r 'bisect(pruned)'
530 0:33b1f9bc8bc5
530 0:33b1f9bc8bc5
531 1:4ca5088da217
531 1:4ca5088da217
532 2:051e12f87bf1
532 2:051e12f87bf1
533 3:0950834f0a9c
533 3:0950834f0a9c
534 4:5c668c22234f
534 4:5c668c22234f
535 5:385a529b6670
535 5:385a529b6670
536 6:a214d5d3811a
536 6:a214d5d3811a
537 8:dab8161ac8fc
537 8:dab8161ac8fc
538 9:3c77083deb4a
538 9:3c77083deb4a
539 10:429fcd26f52d
539 10:429fcd26f52d
540 11:82ca6f06eccd
540 11:82ca6f06eccd
541 12:9f259202bbe7
541 12:9f259202bbe7
542 13:b0a32c86eb31
542 13:b0a32c86eb31
543 15:857b178a7cf3
543 15:857b178a7cf3
544 17:228c06deef46
544 17:228c06deef46
545 $ hg bisect -s
545 $ hg bisect -s
546 Due to skipped revisions, the first good revision could be any of:
546 Due to skipped revisions, the first good revision could be any of:
547 changeset: 15:857b178a7cf3
547 changeset: 15:857b178a7cf3
548 parent: 13:b0a32c86eb31
548 parent: 13:b0a32c86eb31
549 parent: 10:429fcd26f52d
549 parent: 10:429fcd26f52d
550 user: test
550 user: test
551 date: Thu Jan 01 00:00:15 1970 +0000
551 date: Thu Jan 01 00:00:15 1970 +0000
552 summary: merge 10,13
552 summary: merge 10,13
553
553
554 changeset: 16:609d82a7ebae
554 changeset: 16:609d82a7ebae
555 user: test
555 user: test
556 date: Thu Jan 01 00:00:16 1970 +0000
556 date: Thu Jan 01 00:00:16 1970 +0000
557 summary: 16
557 summary: 16
558
558
559 changeset: 17:228c06deef46
559 changeset: 17:228c06deef46
560 user: test
560 user: test
561 date: Thu Jan 01 00:00:17 1970 +0000
561 date: Thu Jan 01 00:00:17 1970 +0000
562 summary: 17
562 summary: 17
563
563
564 $ hg log -q -r 'bisect(range)'
564 $ hg log -q -r 'bisect(range)'
565 8:dab8161ac8fc
565 8:dab8161ac8fc
566 9:3c77083deb4a
566 9:3c77083deb4a
567 10:429fcd26f52d
567 10:429fcd26f52d
568 11:82ca6f06eccd
568 11:82ca6f06eccd
569 12:9f259202bbe7
569 12:9f259202bbe7
570 13:b0a32c86eb31
570 13:b0a32c86eb31
571 15:857b178a7cf3
571 15:857b178a7cf3
572 16:609d82a7ebae
572 16:609d82a7ebae
573 17:228c06deef46
573 17:228c06deef46
574 $ hg log -q -r 'bisect(pruned)'
574 $ hg log -q -r 'bisect(pruned)'
575 0:33b1f9bc8bc5
575 0:33b1f9bc8bc5
576 1:4ca5088da217
576 1:4ca5088da217
577 2:051e12f87bf1
577 2:051e12f87bf1
578 3:0950834f0a9c
578 3:0950834f0a9c
579 4:5c668c22234f
579 4:5c668c22234f
580 5:385a529b6670
580 5:385a529b6670
581 6:a214d5d3811a
581 6:a214d5d3811a
582 8:dab8161ac8fc
582 8:dab8161ac8fc
583 9:3c77083deb4a
583 9:3c77083deb4a
584 10:429fcd26f52d
584 10:429fcd26f52d
585 11:82ca6f06eccd
585 11:82ca6f06eccd
586 12:9f259202bbe7
586 12:9f259202bbe7
587 13:b0a32c86eb31
587 13:b0a32c86eb31
588 15:857b178a7cf3
588 15:857b178a7cf3
589 16:609d82a7ebae
589 16:609d82a7ebae
590 17:228c06deef46
590 17:228c06deef46
591
591
592 test unrelated revs:
592 test unrelated revs:
593
593
594 $ hg bisect --reset
594 $ hg bisect --reset
595 $ hg bisect -b 7
595 $ hg bisect -b 7
596 $ hg bisect -g 14
596 $ hg bisect -g 14
597 abort: starting revisions are not directly related
597 abort: starting revisions are not directly related
598 [255]
598 [255]
599 $ hg log -q -r 'bisect(range)'
599 $ hg log -q -r 'bisect(range)'
600 $ hg log -q -r 'bisect(pruned)'
600 $ hg log -q -r 'bisect(pruned)'
601 0:33b1f9bc8bc5
601 0:33b1f9bc8bc5
602 1:4ca5088da217
602 1:4ca5088da217
603 2:051e12f87bf1
603 2:051e12f87bf1
604 3:0950834f0a9c
604 3:0950834f0a9c
605 4:5c668c22234f
605 4:5c668c22234f
606 7:50c76098bbf2
606 7:50c76098bbf2
607 14:faa450606157
607 14:faa450606157
608 $ hg bisect --reset
608 $ hg bisect --reset
609
609
610 end at merge: 17 bad, 11 good (but 9 is first bad)
610 end at merge: 17 bad, 11 good (but 9 is first bad)
611
611
612 $ hg bisect -r
612 $ hg bisect -r
613 $ hg bisect -b 17
613 $ hg bisect -b 17
614 $ hg bisect -g 11
614 $ hg bisect -g 11
615 Testing changeset 13:b0a32c86eb31 (5 changesets remaining, ~2 tests)
615 Testing changeset 13:b0a32c86eb31 "13" (5 changesets remaining, ~2 tests)
616 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
616 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
617 $ hg log -q -r 'bisect(ignored)'
617 $ hg log -q -r 'bisect(ignored)'
618 2:051e12f87bf1
618 2:051e12f87bf1
619 3:0950834f0a9c
619 3:0950834f0a9c
620 4:5c668c22234f
620 4:5c668c22234f
621 5:385a529b6670
621 5:385a529b6670
622 6:a214d5d3811a
622 6:a214d5d3811a
623 9:3c77083deb4a
623 9:3c77083deb4a
624 10:429fcd26f52d
624 10:429fcd26f52d
625 $ hg bisect -g
625 $ hg bisect -g
626 Testing changeset 15:857b178a7cf3 (3 changesets remaining, ~1 tests)
626 Testing changeset 15:857b178a7cf3 "merge 10,13" (3 changesets remaining, ~1 tests)
627 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
627 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
628 $ hg bisect -b
628 $ hg bisect -b
629 The first bad revision is:
629 The first bad revision is:
630 changeset: 15:857b178a7cf3
630 changeset: 15:857b178a7cf3
631 parent: 13:b0a32c86eb31
631 parent: 13:b0a32c86eb31
632 parent: 10:429fcd26f52d
632 parent: 10:429fcd26f52d
633 user: test
633 user: test
634 date: Thu Jan 01 00:00:15 1970 +0000
634 date: Thu Jan 01 00:00:15 1970 +0000
635 summary: merge 10,13
635 summary: merge 10,13
636
636
637 Not all ancestors of this changeset have been checked.
637 Not all ancestors of this changeset have been checked.
638 Use bisect --extend to continue the bisection from
638 Use bisect --extend to continue the bisection from
639 the common ancestor, dab8161ac8fc.
639 the common ancestor, dab8161ac8fc.
640 $ hg log -q -r 'bisect(range)'
640 $ hg log -q -r 'bisect(range)'
641 11:82ca6f06eccd
641 11:82ca6f06eccd
642 12:9f259202bbe7
642 12:9f259202bbe7
643 13:b0a32c86eb31
643 13:b0a32c86eb31
644 15:857b178a7cf3
644 15:857b178a7cf3
645 16:609d82a7ebae
645 16:609d82a7ebae
646 17:228c06deef46
646 17:228c06deef46
647 $ hg log -q -r 'bisect(pruned)'
647 $ hg log -q -r 'bisect(pruned)'
648 0:33b1f9bc8bc5
648 0:33b1f9bc8bc5
649 1:4ca5088da217
649 1:4ca5088da217
650 8:dab8161ac8fc
650 8:dab8161ac8fc
651 11:82ca6f06eccd
651 11:82ca6f06eccd
652 12:9f259202bbe7
652 12:9f259202bbe7
653 13:b0a32c86eb31
653 13:b0a32c86eb31
654 15:857b178a7cf3
654 15:857b178a7cf3
655 16:609d82a7ebae
655 16:609d82a7ebae
656 17:228c06deef46
656 17:228c06deef46
657 18:d42e18c7bc9b
657 18:d42e18c7bc9b
658 $ hg log -q -r 'bisect(untested)'
658 $ hg log -q -r 'bisect(untested)'
659 $ hg log -q -r 'bisect(ignored)'
659 $ hg log -q -r 'bisect(ignored)'
660 2:051e12f87bf1
660 2:051e12f87bf1
661 3:0950834f0a9c
661 3:0950834f0a9c
662 4:5c668c22234f
662 4:5c668c22234f
663 5:385a529b6670
663 5:385a529b6670
664 6:a214d5d3811a
664 6:a214d5d3811a
665 9:3c77083deb4a
665 9:3c77083deb4a
666 10:429fcd26f52d
666 10:429fcd26f52d
667 $ hg bisect --extend
667 $ hg bisect --extend
668 Extending search to changeset 8:dab8161ac8fc
668 Extending search to changeset 8:dab8161ac8fc "8"
669 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
669 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
670 $ hg log -q -r 'bisect(untested)'
670 $ hg log -q -r 'bisect(untested)'
671 $ hg log -q -r 'bisect(ignored)'
671 $ hg log -q -r 'bisect(ignored)'
672 2:051e12f87bf1
672 2:051e12f87bf1
673 3:0950834f0a9c
673 3:0950834f0a9c
674 4:5c668c22234f
674 4:5c668c22234f
675 5:385a529b6670
675 5:385a529b6670
676 6:a214d5d3811a
676 6:a214d5d3811a
677 9:3c77083deb4a
677 9:3c77083deb4a
678 10:429fcd26f52d
678 10:429fcd26f52d
679 $ hg bisect -g # dab8161ac8fc
679 $ hg bisect -g # dab8161ac8fc
680 Testing changeset 9:3c77083deb4a (3 changesets remaining, ~1 tests)
680 Testing changeset 9:3c77083deb4a "9" (3 changesets remaining, ~1 tests)
681 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
681 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
682 $ hg log -q -r 'bisect(untested)'
682 $ hg log -q -r 'bisect(untested)'
683 9:3c77083deb4a
683 9:3c77083deb4a
684 10:429fcd26f52d
684 10:429fcd26f52d
685 $ hg log -q -r 'bisect(ignored)'
685 $ hg log -q -r 'bisect(ignored)'
686 2:051e12f87bf1
686 2:051e12f87bf1
687 3:0950834f0a9c
687 3:0950834f0a9c
688 4:5c668c22234f
688 4:5c668c22234f
689 5:385a529b6670
689 5:385a529b6670
690 6:a214d5d3811a
690 6:a214d5d3811a
691 $ hg log -q -r 'bisect(goods)'
691 $ hg log -q -r 'bisect(goods)'
692 0:33b1f9bc8bc5
692 0:33b1f9bc8bc5
693 1:4ca5088da217
693 1:4ca5088da217
694 8:dab8161ac8fc
694 8:dab8161ac8fc
695 11:82ca6f06eccd
695 11:82ca6f06eccd
696 12:9f259202bbe7
696 12:9f259202bbe7
697 13:b0a32c86eb31
697 13:b0a32c86eb31
698 $ hg log -q -r 'bisect(bads)'
698 $ hg log -q -r 'bisect(bads)'
699 15:857b178a7cf3
699 15:857b178a7cf3
700 16:609d82a7ebae
700 16:609d82a7ebae
701 17:228c06deef46
701 17:228c06deef46
702 18:d42e18c7bc9b
702 18:d42e18c7bc9b
703 $ hg bisect -b
703 $ hg bisect -b
704 The first bad revision is:
704 The first bad revision is:
705 changeset: 9:3c77083deb4a
705 changeset: 9:3c77083deb4a
706 user: test
706 user: test
707 date: Thu Jan 01 00:00:09 1970 +0000
707 date: Thu Jan 01 00:00:09 1970 +0000
708 summary: 9
708 summary: 9
709
709
710 $ hg log -q -r 'bisect(range)'
710 $ hg log -q -r 'bisect(range)'
711 8:dab8161ac8fc
711 8:dab8161ac8fc
712 9:3c77083deb4a
712 9:3c77083deb4a
713 10:429fcd26f52d
713 10:429fcd26f52d
714 11:82ca6f06eccd
714 11:82ca6f06eccd
715 12:9f259202bbe7
715 12:9f259202bbe7
716 13:b0a32c86eb31
716 13:b0a32c86eb31
717 15:857b178a7cf3
717 15:857b178a7cf3
718 16:609d82a7ebae
718 16:609d82a7ebae
719 17:228c06deef46
719 17:228c06deef46
720 $ hg log -q -r 'bisect(pruned)'
720 $ hg log -q -r 'bisect(pruned)'
721 0:33b1f9bc8bc5
721 0:33b1f9bc8bc5
722 1:4ca5088da217
722 1:4ca5088da217
723 8:dab8161ac8fc
723 8:dab8161ac8fc
724 9:3c77083deb4a
724 9:3c77083deb4a
725 10:429fcd26f52d
725 10:429fcd26f52d
726 11:82ca6f06eccd
726 11:82ca6f06eccd
727 12:9f259202bbe7
727 12:9f259202bbe7
728 13:b0a32c86eb31
728 13:b0a32c86eb31
729 15:857b178a7cf3
729 15:857b178a7cf3
730 16:609d82a7ebae
730 16:609d82a7ebae
731 17:228c06deef46
731 17:228c06deef46
732 18:d42e18c7bc9b
732 18:d42e18c7bc9b
733 $ hg log -q -r 'bisect(untested)'
733 $ hg log -q -r 'bisect(untested)'
734 $ hg log -q -r 'bisect(ignored)'
734 $ hg log -q -r 'bisect(ignored)'
735 2:051e12f87bf1
735 2:051e12f87bf1
736 3:0950834f0a9c
736 3:0950834f0a9c
737 4:5c668c22234f
737 4:5c668c22234f
738 5:385a529b6670
738 5:385a529b6670
739 6:a214d5d3811a
739 6:a214d5d3811a
740 $ hg log -q -r 'bisect(goods)'
740 $ hg log -q -r 'bisect(goods)'
741 0:33b1f9bc8bc5
741 0:33b1f9bc8bc5
742 1:4ca5088da217
742 1:4ca5088da217
743 8:dab8161ac8fc
743 8:dab8161ac8fc
744 11:82ca6f06eccd
744 11:82ca6f06eccd
745 12:9f259202bbe7
745 12:9f259202bbe7
746 13:b0a32c86eb31
746 13:b0a32c86eb31
747 $ hg log -q -r 'bisect(bads)'
747 $ hg log -q -r 'bisect(bads)'
748 9:3c77083deb4a
748 9:3c77083deb4a
749 10:429fcd26f52d
749 10:429fcd26f52d
750 15:857b178a7cf3
750 15:857b178a7cf3
751 16:609d82a7ebae
751 16:609d82a7ebae
752 17:228c06deef46
752 17:228c06deef46
753 18:d42e18c7bc9b
753 18:d42e18c7bc9b
754
754
755 user adds irrelevant but consistent information (here: -g 2) to bisect state
755 user adds irrelevant but consistent information (here: -g 2) to bisect state
756
756
757 $ hg bisect -r
757 $ hg bisect -r
758 $ hg bisect -b 13
758 $ hg bisect -b 13
759 $ hg bisect -g 8
759 $ hg bisect -g 8
760 Testing changeset 11:82ca6f06eccd (3 changesets remaining, ~1 tests)
760 Testing changeset 11:82ca6f06eccd "11" (3 changesets remaining, ~1 tests)
761 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
761 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
762 $ hg log -q -r 'bisect(untested)'
762 $ hg log -q -r 'bisect(untested)'
763 11:82ca6f06eccd
763 11:82ca6f06eccd
764 12:9f259202bbe7
764 12:9f259202bbe7
765 $ hg bisect -g 2
765 $ hg bisect -g 2
766 Testing changeset 11:82ca6f06eccd (3 changesets remaining, ~1 tests)
766 Testing changeset 11:82ca6f06eccd "11" (3 changesets remaining, ~1 tests)
767 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
767 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
768 $ hg log -q -r 'bisect(untested)'
768 $ hg log -q -r 'bisect(untested)'
769 11:82ca6f06eccd
769 11:82ca6f06eccd
770 12:9f259202bbe7
770 12:9f259202bbe7
771 $ hg bisect -b
771 $ hg bisect -b
772 The first bad revision is:
772 The first bad revision is:
773 changeset: 11:82ca6f06eccd
773 changeset: 11:82ca6f06eccd
774 parent: 8:dab8161ac8fc
774 parent: 8:dab8161ac8fc
775 user: test
775 user: test
776 date: Thu Jan 01 00:00:11 1970 +0000
776 date: Thu Jan 01 00:00:11 1970 +0000
777 summary: 11
777 summary: 11
778
778
779 $ hg log -q -r 'bisect(range)'
779 $ hg log -q -r 'bisect(range)'
780 8:dab8161ac8fc
780 8:dab8161ac8fc
781 11:82ca6f06eccd
781 11:82ca6f06eccd
782 12:9f259202bbe7
782 12:9f259202bbe7
783 13:b0a32c86eb31
783 13:b0a32c86eb31
784 $ hg log -q -r 'bisect(pruned)'
784 $ hg log -q -r 'bisect(pruned)'
785 0:33b1f9bc8bc5
785 0:33b1f9bc8bc5
786 1:4ca5088da217
786 1:4ca5088da217
787 2:051e12f87bf1
787 2:051e12f87bf1
788 8:dab8161ac8fc
788 8:dab8161ac8fc
789 11:82ca6f06eccd
789 11:82ca6f06eccd
790 12:9f259202bbe7
790 12:9f259202bbe7
791 13:b0a32c86eb31
791 13:b0a32c86eb31
792 14:faa450606157
792 14:faa450606157
793 15:857b178a7cf3
793 15:857b178a7cf3
794 16:609d82a7ebae
794 16:609d82a7ebae
795 17:228c06deef46
795 17:228c06deef46
796 18:d42e18c7bc9b
796 18:d42e18c7bc9b
797 $ hg log -q -r 'bisect(untested)'
797 $ hg log -q -r 'bisect(untested)'
@@ -1,249 +1,249 b''
1 # Here we create a simple DAG which has just enough of the required
1 # Here we create a simple DAG which has just enough of the required
2 # topology to test all the bisection status labels:
2 # topology to test all the bisection status labels:
3 #
3 #
4 # 13--14
4 # 13--14
5 # /
5 # /
6 # 0--1--2--3---------9--10--11--12
6 # 0--1--2--3---------9--10--11--12
7 # \ /
7 # \ /
8 # 4--5--6--7--8
8 # 4--5--6--7--8
9
9
10
10
11 $ hg init
11 $ hg init
12
12
13 $ echo '0' >a
13 $ echo '0' >a
14 $ hg add a
14 $ hg add a
15 $ hg ci -u test -d '0 0' -m '0'
15 $ hg ci -u test -d '0 0' -m '0'
16 $ echo '1' >a
16 $ echo '1' >a
17 $ hg ci -u test -d '1 0' -m '1'
17 $ hg ci -u test -d '1 0' -m '1'
18
18
19 branch 2-3
19 branch 2-3
20
20
21 $ echo '2' >b
21 $ echo '2' >b
22 $ hg add b
22 $ hg add b
23 $ hg ci -u test -d '2 0' -m '2'
23 $ hg ci -u test -d '2 0' -m '2'
24 $ echo '3' >b
24 $ echo '3' >b
25 $ hg ci -u test -d '3 0' -m '3'
25 $ hg ci -u test -d '3 0' -m '3'
26
26
27 branch 4-8
27 branch 4-8
28
28
29 $ hg up -r 1
29 $ hg up -r 1
30 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
30 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
31 $ echo '4' >c
31 $ echo '4' >c
32 $ hg add c
32 $ hg add c
33 $ hg ci -u test -d '4 0' -m '4'
33 $ hg ci -u test -d '4 0' -m '4'
34 created new head
34 created new head
35 $ echo '5' >c
35 $ echo '5' >c
36 $ hg ci -u test -d '5 0' -m '5'
36 $ hg ci -u test -d '5 0' -m '5'
37 $ echo '6' >c
37 $ echo '6' >c
38 $ hg ci -u test -d '6 0' -m '6'
38 $ hg ci -u test -d '6 0' -m '6'
39 $ echo '7' >c
39 $ echo '7' >c
40 $ hg ci -u test -d '7 0' -m '7'
40 $ hg ci -u test -d '7 0' -m '7'
41 $ echo '8' >c
41 $ echo '8' >c
42 $ hg ci -u test -d '8 0' -m '8'
42 $ hg ci -u test -d '8 0' -m '8'
43
43
44 merge
44 merge
45
45
46 $ hg merge -r 3
46 $ hg merge -r 3
47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 (branch merge, don't forget to commit)
48 (branch merge, don't forget to commit)
49 $ hg ci -u test -d '9 0' -m '9=8+3'
49 $ hg ci -u test -d '9 0' -m '9=8+3'
50
50
51 $ echo '10' >a
51 $ echo '10' >a
52 $ hg ci -u test -d '10 0' -m '10'
52 $ hg ci -u test -d '10 0' -m '10'
53 $ echo '11' >a
53 $ echo '11' >a
54 $ hg ci -u test -d '11 0' -m '11'
54 $ hg ci -u test -d '11 0' -m '11'
55 $ echo '12' >a
55 $ echo '12' >a
56 $ hg ci -u test -d '12 0' -m '12'
56 $ hg ci -u test -d '12 0' -m '12'
57
57
58 unrelated branch
58 unrelated branch
59
59
60 $ hg up -r 3
60 $ hg up -r 3
61 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
61 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
62 $ echo '13' >d
62 $ echo '13' >d
63 $ hg add d
63 $ hg add d
64 $ hg ci -u test -d '13 0' -m '13'
64 $ hg ci -u test -d '13 0' -m '13'
65 created new head
65 created new head
66 $ echo '14' >d
66 $ echo '14' >d
67 $ hg ci -u test -d '14 0' -m '14'
67 $ hg ci -u test -d '14 0' -m '14'
68
68
69 mark changesets
69 mark changesets
70
70
71 $ hg bisect --reset
71 $ hg bisect --reset
72 $ hg bisect --good 4
72 $ hg bisect --good 4
73 $ hg bisect --good 6
73 $ hg bisect --good 6
74 $ hg bisect --bad 12
74 $ hg bisect --bad 12
75 Testing changeset 9:2197c557e14c (6 changesets remaining, ~2 tests)
75 Testing changeset 9:2197c557e14c "9=8+3" (6 changesets remaining, ~2 tests)
76 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
76 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
77 $ hg bisect --bad 10
77 $ hg bisect --bad 10
78 Testing changeset 8:e74a86251f58 (4 changesets remaining, ~2 tests)
78 Testing changeset 8:e74a86251f58 "8" (4 changesets remaining, ~2 tests)
79 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
79 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
80 $ hg bisect --skip 7
80 $ hg bisect --skip 7
81 Testing changeset 8:e74a86251f58 (4 changesets remaining, ~2 tests)
81 Testing changeset 8:e74a86251f58 "8" (4 changesets remaining, ~2 tests)
82 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
83
83
84 test template
84 test template
85
85
86 $ hg log --template '{rev}:{node|short} {bisect}\n'
86 $ hg log --template '{rev}:{node|short} {bisect}\n'
87 14:cbf2f3105bbf
87 14:cbf2f3105bbf
88 13:e07efca37c43
88 13:e07efca37c43
89 12:98c6b56349c0 bad
89 12:98c6b56349c0 bad
90 11:03f491376e63 bad (implicit)
90 11:03f491376e63 bad (implicit)
91 10:c012b15e2409 bad
91 10:c012b15e2409 bad
92 9:2197c557e14c untested
92 9:2197c557e14c untested
93 8:e74a86251f58 untested
93 8:e74a86251f58 untested
94 7:a5f87041c899 skipped
94 7:a5f87041c899 skipped
95 6:7d997bedcd8d good
95 6:7d997bedcd8d good
96 5:2dd1875f1028 good (implicit)
96 5:2dd1875f1028 good (implicit)
97 4:2a1daef14cd4 good
97 4:2a1daef14cd4 good
98 3:8417d459b90c ignored
98 3:8417d459b90c ignored
99 2:e1355ee1f23e ignored
99 2:e1355ee1f23e ignored
100 1:ce7c85e06a9f good (implicit)
100 1:ce7c85e06a9f good (implicit)
101 0:b4e73ffab476 good (implicit)
101 0:b4e73ffab476 good (implicit)
102 $ hg log --template '{bisect|shortbisect} {rev}:{node|short}\n'
102 $ hg log --template '{bisect|shortbisect} {rev}:{node|short}\n'
103 14:cbf2f3105bbf
103 14:cbf2f3105bbf
104 13:e07efca37c43
104 13:e07efca37c43
105 B 12:98c6b56349c0
105 B 12:98c6b56349c0
106 B 11:03f491376e63
106 B 11:03f491376e63
107 B 10:c012b15e2409
107 B 10:c012b15e2409
108 U 9:2197c557e14c
108 U 9:2197c557e14c
109 U 8:e74a86251f58
109 U 8:e74a86251f58
110 S 7:a5f87041c899
110 S 7:a5f87041c899
111 G 6:7d997bedcd8d
111 G 6:7d997bedcd8d
112 G 5:2dd1875f1028
112 G 5:2dd1875f1028
113 G 4:2a1daef14cd4
113 G 4:2a1daef14cd4
114 I 3:8417d459b90c
114 I 3:8417d459b90c
115 I 2:e1355ee1f23e
115 I 2:e1355ee1f23e
116 G 1:ce7c85e06a9f
116 G 1:ce7c85e06a9f
117 G 0:b4e73ffab476
117 G 0:b4e73ffab476
118
118
119 test style
119 test style
120
120
121 $ hg log --style bisect
121 $ hg log --style bisect
122 changeset: 14:cbf2f3105bbf
122 changeset: 14:cbf2f3105bbf
123 bisect:
123 bisect:
124 tag: tip
124 tag: tip
125 user: test
125 user: test
126 date: Thu Jan 01 00:00:14 1970 +0000
126 date: Thu Jan 01 00:00:14 1970 +0000
127 summary: 14
127 summary: 14
128
128
129 changeset: 13:e07efca37c43
129 changeset: 13:e07efca37c43
130 bisect:
130 bisect:
131 parent: 3:8417d459b90c
131 parent: 3:8417d459b90c
132 user: test
132 user: test
133 date: Thu Jan 01 00:00:13 1970 +0000
133 date: Thu Jan 01 00:00:13 1970 +0000
134 summary: 13
134 summary: 13
135
135
136 changeset: 12:98c6b56349c0
136 changeset: 12:98c6b56349c0
137 bisect: bad
137 bisect: bad
138 user: test
138 user: test
139 date: Thu Jan 01 00:00:12 1970 +0000
139 date: Thu Jan 01 00:00:12 1970 +0000
140 summary: 12
140 summary: 12
141
141
142 changeset: 11:03f491376e63
142 changeset: 11:03f491376e63
143 bisect: bad (implicit)
143 bisect: bad (implicit)
144 user: test
144 user: test
145 date: Thu Jan 01 00:00:11 1970 +0000
145 date: Thu Jan 01 00:00:11 1970 +0000
146 summary: 11
146 summary: 11
147
147
148 changeset: 10:c012b15e2409
148 changeset: 10:c012b15e2409
149 bisect: bad
149 bisect: bad
150 user: test
150 user: test
151 date: Thu Jan 01 00:00:10 1970 +0000
151 date: Thu Jan 01 00:00:10 1970 +0000
152 summary: 10
152 summary: 10
153
153
154 changeset: 9:2197c557e14c
154 changeset: 9:2197c557e14c
155 bisect: untested
155 bisect: untested
156 parent: 8:e74a86251f58
156 parent: 8:e74a86251f58
157 parent: 3:8417d459b90c
157 parent: 3:8417d459b90c
158 user: test
158 user: test
159 date: Thu Jan 01 00:00:09 1970 +0000
159 date: Thu Jan 01 00:00:09 1970 +0000
160 summary: 9=8+3
160 summary: 9=8+3
161
161
162 changeset: 8:e74a86251f58
162 changeset: 8:e74a86251f58
163 bisect: untested
163 bisect: untested
164 user: test
164 user: test
165 date: Thu Jan 01 00:00:08 1970 +0000
165 date: Thu Jan 01 00:00:08 1970 +0000
166 summary: 8
166 summary: 8
167
167
168 changeset: 7:a5f87041c899
168 changeset: 7:a5f87041c899
169 bisect: skipped
169 bisect: skipped
170 user: test
170 user: test
171 date: Thu Jan 01 00:00:07 1970 +0000
171 date: Thu Jan 01 00:00:07 1970 +0000
172 summary: 7
172 summary: 7
173
173
174 changeset: 6:7d997bedcd8d
174 changeset: 6:7d997bedcd8d
175 bisect: good
175 bisect: good
176 user: test
176 user: test
177 date: Thu Jan 01 00:00:06 1970 +0000
177 date: Thu Jan 01 00:00:06 1970 +0000
178 summary: 6
178 summary: 6
179
179
180 changeset: 5:2dd1875f1028
180 changeset: 5:2dd1875f1028
181 bisect: good (implicit)
181 bisect: good (implicit)
182 user: test
182 user: test
183 date: Thu Jan 01 00:00:05 1970 +0000
183 date: Thu Jan 01 00:00:05 1970 +0000
184 summary: 5
184 summary: 5
185
185
186 changeset: 4:2a1daef14cd4
186 changeset: 4:2a1daef14cd4
187 bisect: good
187 bisect: good
188 parent: 1:ce7c85e06a9f
188 parent: 1:ce7c85e06a9f
189 user: test
189 user: test
190 date: Thu Jan 01 00:00:04 1970 +0000
190 date: Thu Jan 01 00:00:04 1970 +0000
191 summary: 4
191 summary: 4
192
192
193 changeset: 3:8417d459b90c
193 changeset: 3:8417d459b90c
194 bisect: ignored
194 bisect: ignored
195 user: test
195 user: test
196 date: Thu Jan 01 00:00:03 1970 +0000
196 date: Thu Jan 01 00:00:03 1970 +0000
197 summary: 3
197 summary: 3
198
198
199 changeset: 2:e1355ee1f23e
199 changeset: 2:e1355ee1f23e
200 bisect: ignored
200 bisect: ignored
201 user: test
201 user: test
202 date: Thu Jan 01 00:00:02 1970 +0000
202 date: Thu Jan 01 00:00:02 1970 +0000
203 summary: 2
203 summary: 2
204
204
205 changeset: 1:ce7c85e06a9f
205 changeset: 1:ce7c85e06a9f
206 bisect: good (implicit)
206 bisect: good (implicit)
207 user: test
207 user: test
208 date: Thu Jan 01 00:00:01 1970 +0000
208 date: Thu Jan 01 00:00:01 1970 +0000
209 summary: 1
209 summary: 1
210
210
211 changeset: 0:b4e73ffab476
211 changeset: 0:b4e73ffab476
212 bisect: good (implicit)
212 bisect: good (implicit)
213 user: test
213 user: test
214 date: Thu Jan 01 00:00:00 1970 +0000
214 date: Thu Jan 01 00:00:00 1970 +0000
215 summary: 0
215 summary: 0
216
216
217 $ hg log --quiet --style bisect
217 $ hg log --quiet --style bisect
218 14:cbf2f3105bbf
218 14:cbf2f3105bbf
219 13:e07efca37c43
219 13:e07efca37c43
220 B 12:98c6b56349c0
220 B 12:98c6b56349c0
221 B 11:03f491376e63
221 B 11:03f491376e63
222 B 10:c012b15e2409
222 B 10:c012b15e2409
223 U 9:2197c557e14c
223 U 9:2197c557e14c
224 U 8:e74a86251f58
224 U 8:e74a86251f58
225 S 7:a5f87041c899
225 S 7:a5f87041c899
226 G 6:7d997bedcd8d
226 G 6:7d997bedcd8d
227 G 5:2dd1875f1028
227 G 5:2dd1875f1028
228 G 4:2a1daef14cd4
228 G 4:2a1daef14cd4
229 I 3:8417d459b90c
229 I 3:8417d459b90c
230 I 2:e1355ee1f23e
230 I 2:e1355ee1f23e
231 G 1:ce7c85e06a9f
231 G 1:ce7c85e06a9f
232 G 0:b4e73ffab476
232 G 0:b4e73ffab476
233
233
234 $ hg --config extensions.color= --color=debug log --quiet --style bisect
234 $ hg --config extensions.color= --color=debug log --quiet --style bisect
235 [log.bisect| ] 14:cbf2f3105bbf
235 [log.bisect| ] 14:cbf2f3105bbf
236 [log.bisect| ] 13:e07efca37c43
236 [log.bisect| ] 13:e07efca37c43
237 [log.bisect bisect.bad|B] 12:98c6b56349c0
237 [log.bisect bisect.bad|B] 12:98c6b56349c0
238 [log.bisect bisect.bad|B] 11:03f491376e63
238 [log.bisect bisect.bad|B] 11:03f491376e63
239 [log.bisect bisect.bad|B] 10:c012b15e2409
239 [log.bisect bisect.bad|B] 10:c012b15e2409
240 [log.bisect bisect.untested|U] 9:2197c557e14c
240 [log.bisect bisect.untested|U] 9:2197c557e14c
241 [log.bisect bisect.untested|U] 8:e74a86251f58
241 [log.bisect bisect.untested|U] 8:e74a86251f58
242 [log.bisect bisect.skipped|S] 7:a5f87041c899
242 [log.bisect bisect.skipped|S] 7:a5f87041c899
243 [log.bisect bisect.good|G] 6:7d997bedcd8d
243 [log.bisect bisect.good|G] 6:7d997bedcd8d
244 [log.bisect bisect.good|G] 5:2dd1875f1028
244 [log.bisect bisect.good|G] 5:2dd1875f1028
245 [log.bisect bisect.good|G] 4:2a1daef14cd4
245 [log.bisect bisect.good|G] 4:2a1daef14cd4
246 [log.bisect bisect.ignored|I] 3:8417d459b90c
246 [log.bisect bisect.ignored|I] 3:8417d459b90c
247 [log.bisect bisect.ignored|I] 2:e1355ee1f23e
247 [log.bisect bisect.ignored|I] 2:e1355ee1f23e
248 [log.bisect bisect.good|G] 1:ce7c85e06a9f
248 [log.bisect bisect.good|G] 1:ce7c85e06a9f
249 [log.bisect bisect.good|G] 0:b4e73ffab476
249 [log.bisect bisect.good|G] 0:b4e73ffab476
@@ -1,1997 +1,1997 b''
1 Test template map files and styles
1 Test template map files and styles
2 ==================================
2 ==================================
3
3
4 $ hg init a
4 $ hg init a
5 $ cd a
5 $ cd a
6 $ echo a > a
6 $ echo a > a
7 $ hg add a
7 $ hg add a
8 $ echo line 1 > b
8 $ echo line 1 > b
9 $ echo line 2 >> b
9 $ echo line 2 >> b
10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
10 $ hg commit -l b -d '1000000 0' -u 'User Name <user@hostname>'
11
11
12 $ hg add b
12 $ hg add b
13 $ echo other 1 > c
13 $ echo other 1 > c
14 $ echo other 2 >> c
14 $ echo other 2 >> c
15 $ echo >> c
15 $ echo >> c
16 $ echo other 3 >> c
16 $ echo other 3 >> c
17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
17 $ hg commit -l c -d '1100000 0' -u 'A. N. Other <other@place>'
18
18
19 $ hg add c
19 $ hg add c
20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
20 $ hg commit -m 'no person' -d '1200000 0' -u 'other@place'
21 $ echo c >> c
21 $ echo c >> c
22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
22 $ hg commit -m 'no user, no domain' -d '1300000 0' -u 'person'
23
23
24 $ echo foo > .hg/branch
24 $ echo foo > .hg/branch
25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
25 $ hg commit -m 'new branch' -d '1400000 0' -u 'person'
26
26
27 $ hg co -q 3
27 $ hg co -q 3
28 $ echo other 4 >> d
28 $ echo other 4 >> d
29 $ hg add d
29 $ hg add d
30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
30 $ hg commit -m 'new head' -d '1500000 0' -u 'person'
31
31
32 $ hg merge -q foo
32 $ hg merge -q foo
33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
33 $ hg commit -m 'merge' -d '1500001 0' -u 'person'
34
34
35 Second branch starting at nullrev:
35 Second branch starting at nullrev:
36
36
37 $ hg update null
37 $ hg update null
38 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
38 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
39 $ echo second > second
39 $ echo second > second
40 $ hg add second
40 $ hg add second
41 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
41 $ hg commit -m second -d '1000000 0' -u 'User Name <user@hostname>'
42 created new head
42 created new head
43
43
44 $ echo third > third
44 $ echo third > third
45 $ hg add third
45 $ hg add third
46 $ hg mv second fourth
46 $ hg mv second fourth
47 $ hg commit -m third -d "2020-01-01 10:01"
47 $ hg commit -m third -d "2020-01-01 10:01"
48
48
49 Make sure user/global hgrc does not affect tests
49 Make sure user/global hgrc does not affect tests
50
50
51 $ echo '[command-templates]' > .hg/hgrc
51 $ echo '[command-templates]' > .hg/hgrc
52 $ echo 'log =' >> .hg/hgrc
52 $ echo 'log =' >> .hg/hgrc
53 $ echo '[ui]' > .hg/hgrc
53 $ echo '[ui]' > .hg/hgrc
54 $ echo 'style =' >> .hg/hgrc
54 $ echo 'style =' >> .hg/hgrc
55
55
56 Add some simple styles to settings
56 Add some simple styles to settings
57
57
58 $ cat <<'EOF' >> .hg/hgrc
58 $ cat <<'EOF' >> .hg/hgrc
59 > [templates]
59 > [templates]
60 > simple = "{rev}\n"
60 > simple = "{rev}\n"
61 > simple2 = {rev}\n
61 > simple2 = {rev}\n
62 > rev = "should not precede {rev} keyword\n"
62 > rev = "should not precede {rev} keyword\n"
63 > EOF
63 > EOF
64
64
65 $ hg log -l1 -Tsimple
65 $ hg log -l1 -Tsimple
66 8
66 8
67 $ hg log -l1 -Tsimple2
67 $ hg log -l1 -Tsimple2
68 8
68 8
69 $ hg log -l1 -Trev
69 $ hg log -l1 -Trev
70 should not precede 8 keyword
70 should not precede 8 keyword
71 $ hg log -l1 -T '{simple}'
71 $ hg log -l1 -T '{simple}'
72 8
72 8
73
73
74 Map file shouldn't see user templates:
74 Map file shouldn't see user templates:
75
75
76 $ cat <<EOF > tmpl
76 $ cat <<EOF > tmpl
77 > changeset = 'nothing expanded:{simple}\n'
77 > changeset = 'nothing expanded:{simple}\n'
78 > EOF
78 > EOF
79 $ hg log -l1 --style ./tmpl
79 $ hg log -l1 --style ./tmpl
80 nothing expanded:
80 nothing expanded:
81
81
82 Test templates and style maps in files:
82 Test templates and style maps in files:
83
83
84 $ echo "{rev}" > tmpl
84 $ echo "{rev}" > tmpl
85 $ hg log -l1 -T./tmpl
85 $ hg log -l1 -T./tmpl
86 8
86 8
87 $ hg log -l1 -Tblah/blah
87 $ hg log -l1 -Tblah/blah
88 blah/blah (no-eol)
88 blah/blah (no-eol)
89
89
90 $ printf 'changeset = "{rev}\\n"\n' > map-simple
90 $ printf 'changeset = "{rev}\\n"\n' > map-simple
91 $ hg log -l1 -T./map-simple
91 $ hg log -l1 -T./map-simple
92 8
92 8
93
93
94 a map file may have [templates] and [templatealias] sections:
94 a map file may have [templates] and [templatealias] sections:
95
95
96 $ cat <<'EOF' > map-simple
96 $ cat <<'EOF' > map-simple
97 > [templates]
97 > [templates]
98 > changeset = "{a}\n"
98 > changeset = "{a}\n"
99 > [templatealias]
99 > [templatealias]
100 > a = rev
100 > a = rev
101 > EOF
101 > EOF
102 $ hg log -l1 -T./map-simple
102 $ hg log -l1 -T./map-simple
103 8
103 8
104
104
105 so it can be included in hgrc
105 so it can be included in hgrc
106
106
107 $ cat <<EOF > myhgrc
107 $ cat <<EOF > myhgrc
108 > %include $HGRCPATH
108 > %include $HGRCPATH
109 > %include map-simple
109 > %include map-simple
110 > [templates]
110 > [templates]
111 > foo = "{changeset}"
111 > foo = "{changeset}"
112 > EOF
112 > EOF
113 $ HGRCPATH=./myhgrc hg log -l1 -Tfoo
113 $ HGRCPATH=./myhgrc hg log -l1 -Tfoo
114 8
114 8
115 $ HGRCPATH=./myhgrc hg log -l1 -T'{a}\n'
115 $ HGRCPATH=./myhgrc hg log -l1 -T'{a}\n'
116 8
116 8
117
117
118 Test template map inheritance
118 Test template map inheritance
119
119
120 $ echo "__base__ = map-cmdline.default" > map-simple
120 $ echo "__base__ = map-cmdline.default" > map-simple
121 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
121 $ printf 'cset = "changeset: ***{rev}***\\n"\n' >> map-simple
122 $ hg log -l1 -T./map-simple
122 $ hg log -l1 -T./map-simple
123 changeset: ***8***
123 changeset: ***8***
124 tag: tip
124 tag: tip
125 user: test
125 user: test
126 date: Wed Jan 01 10:01:00 2020 +0000
126 date: Wed Jan 01 10:01:00 2020 +0000
127 summary: third
127 summary: third
128
128
129 Test map inheritance with non-existent base
129 Test map inheritance with non-existent base
130
130
131 $ echo "__base__ = non-existent" > map-base-nonexistent
131 $ echo "__base__ = non-existent" > map-base-nonexistent
132 $ hg log -l1 -T./map-base-nonexistent
132 $ hg log -l1 -T./map-base-nonexistent
133 abort: style '$TESTTMP/a/non-existent' not found
133 abort: style '$TESTTMP/a/non-existent' not found
134 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
134 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
135 [255]
135 [255]
136
136
137 Test map inheritance with directory as base
137 Test map inheritance with directory as base
138
138
139 $ mkdir somedir
139 $ mkdir somedir
140 $ echo "__base__ = somedir" > map-base-dir
140 $ echo "__base__ = somedir" > map-base-dir
141 $ hg log -l1 -T./map-base-dir
141 $ hg log -l1 -T./map-base-dir
142 abort: Is a directory: '$TESTTMP/a/somedir' (no-windows !)
142 abort: Is a directory: '$TESTTMP/a/somedir' (no-windows !)
143 abort: $TESTTMP/a/somedir: Access is denied (windows !)
143 abort: $TESTTMP/a/somedir: Access is denied (windows !)
144 [255]
144 [255]
145
145
146 Test including a built-in template map
146 Test including a built-in template map
147
147
148 $ cat <<'EOF' > map-include-builtin
148 $ cat <<'EOF' > map-include-builtin
149 > %include map-cmdline.default
149 > %include map-cmdline.default
150 > [templates]
150 > [templates]
151 > changeset = "{changeset_quiet}\n"
151 > changeset = "{changeset_quiet}\n"
152 > EOF
152 > EOF
153 $ hg log -l1 -T./map-include-builtin
153 $ hg log -l1 -T./map-include-builtin
154 8:95c24699272e
154 8:95c24699272e
155
155
156
156
157 Test including a nonexistent template map
157 Test including a nonexistent template map
158 BROKEN: This should probably be an error just like the bad __base__ above
158 BROKEN: This should probably be an error just like the bad __base__ above
159
159
160 $ cat <<'EOF' > map-include-nonexistent
160 $ cat <<'EOF' > map-include-nonexistent
161 > %include nonexistent
161 > %include nonexistent
162 > [templates]
162 > [templates]
163 > changeset = "test\n"
163 > changeset = "test\n"
164 > EOF
164 > EOF
165 $ hg log -l1 -T./map-include-nonexistent
165 $ hg log -l1 -T./map-include-nonexistent
166 test
166 test
167
167
168 Test including a directory as template map
168 Test including a directory as template map
169 BROKEN: This should probably be an error just like the bad __base__ above
169 BROKEN: This should probably be an error just like the bad __base__ above
170
170
171 $ cat <<'EOF' > map-include-dir
171 $ cat <<'EOF' > map-include-dir
172 > %include somedir
172 > %include somedir
173 > [templates]
173 > [templates]
174 > changeset = "test\n"
174 > changeset = "test\n"
175 > EOF
175 > EOF
176 $ hg log -l1 -T./map-include-dir
176 $ hg log -l1 -T./map-include-dir
177 test
177 test
178
178
179 Test docheader, docfooter and separator in template map
179 Test docheader, docfooter and separator in template map
180
180
181 $ cat <<'EOF' > map-myjson
181 $ cat <<'EOF' > map-myjson
182 > docheader = '\{\n'
182 > docheader = '\{\n'
183 > docfooter = '\n}\n'
183 > docfooter = '\n}\n'
184 > separator = ',\n'
184 > separator = ',\n'
185 > changeset = ' {dict(rev, node|short)|json}'
185 > changeset = ' {dict(rev, node|short)|json}'
186 > EOF
186 > EOF
187 $ hg log -l2 -T./map-myjson
187 $ hg log -l2 -T./map-myjson
188 {
188 {
189 {"node": "95c24699272e", "rev": 8},
189 {"node": "95c24699272e", "rev": 8},
190 {"node": "29114dbae42b", "rev": 7}
190 {"node": "29114dbae42b", "rev": 7}
191 }
191 }
192
192
193 Test docheader, docfooter and separator in [templates] section
193 Test docheader, docfooter and separator in [templates] section
194
194
195 $ cat <<'EOF' >> .hg/hgrc
195 $ cat <<'EOF' >> .hg/hgrc
196 > [templates]
196 > [templates]
197 > myjson = ' {dict(rev, node|short)|json}'
197 > myjson = ' {dict(rev, node|short)|json}'
198 > myjson:docheader = '\{\n'
198 > myjson:docheader = '\{\n'
199 > myjson:docfooter = '\n}\n'
199 > myjson:docfooter = '\n}\n'
200 > myjson:separator = ',\n'
200 > myjson:separator = ',\n'
201 > :docheader = 'should not be selected as a docheader for literal templates\n'
201 > :docheader = 'should not be selected as a docheader for literal templates\n'
202 > EOF
202 > EOF
203 $ hg log -l2 -Tmyjson
203 $ hg log -l2 -Tmyjson
204 {
204 {
205 {"node": "95c24699272e", "rev": 8},
205 {"node": "95c24699272e", "rev": 8},
206 {"node": "29114dbae42b", "rev": 7}
206 {"node": "29114dbae42b", "rev": 7}
207 }
207 }
208 $ hg log -l1 -T'{rev}\n'
208 $ hg log -l1 -T'{rev}\n'
209 8
209 8
210
210
211 Template should precede style option
211 Template should precede style option
212
212
213 $ hg log -l1 --style default -T '{rev}\n'
213 $ hg log -l1 --style default -T '{rev}\n'
214 8
214 8
215
215
216 Add a commit with empty description, to ensure that the templates
216 Add a commit with empty description, to ensure that the templates
217 below will omit the description line.
217 below will omit the description line.
218
218
219 $ echo c >> c
219 $ echo c >> c
220 $ hg add c
220 $ hg add c
221 $ hg commit -qm ' '
221 $ hg commit -qm ' '
222
222
223 Default style is like normal output. Phases style should be the same
223 Default style is like normal output. Phases style should be the same
224 as default style, except for extra phase lines.
224 as default style, except for extra phase lines.
225
225
226 $ hg log > log.out
226 $ hg log > log.out
227 $ hg log --style default > style.out
227 $ hg log --style default > style.out
228 $ cmp log.out style.out || diff -u log.out style.out
228 $ cmp log.out style.out || diff -u log.out style.out
229 $ hg log -T phases > phases.out
229 $ hg log -T phases > phases.out
230 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
230 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
231 +phase: draft
231 +phase: draft
232 +phase: draft
232 +phase: draft
233 +phase: draft
233 +phase: draft
234 +phase: draft
234 +phase: draft
235 +phase: draft
235 +phase: draft
236 +phase: draft
236 +phase: draft
237 +phase: draft
237 +phase: draft
238 +phase: draft
238 +phase: draft
239 +phase: draft
239 +phase: draft
240 +phase: draft
240 +phase: draft
241
241
242 $ hg log -v > log.out
242 $ hg log -v > log.out
243 $ hg log -v --style default > style.out
243 $ hg log -v --style default > style.out
244 $ cmp log.out style.out || diff -u log.out style.out
244 $ cmp log.out style.out || diff -u log.out style.out
245 $ hg log -v -T phases > phases.out
245 $ hg log -v -T phases > phases.out
246 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
246 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
247 +phase: draft
247 +phase: draft
248 +phase: draft
248 +phase: draft
249 +phase: draft
249 +phase: draft
250 +phase: draft
250 +phase: draft
251 +phase: draft
251 +phase: draft
252 +phase: draft
252 +phase: draft
253 +phase: draft
253 +phase: draft
254 +phase: draft
254 +phase: draft
255 +phase: draft
255 +phase: draft
256 +phase: draft
256 +phase: draft
257
257
258 $ hg log -q > log.out
258 $ hg log -q > log.out
259 $ hg log -q --style default > style.out
259 $ hg log -q --style default > style.out
260 $ cmp log.out style.out || diff -u log.out style.out
260 $ cmp log.out style.out || diff -u log.out style.out
261 $ hg log -q -T phases > phases.out
261 $ hg log -q -T phases > phases.out
262 $ cmp log.out phases.out || diff -u log.out phases.out
262 $ cmp log.out phases.out || diff -u log.out phases.out
263
263
264 $ hg log --debug > log.out
264 $ hg log --debug > log.out
265 $ hg log --debug --style default > style.out
265 $ hg log --debug --style default > style.out
266 $ cmp log.out style.out || diff -u log.out style.out
266 $ cmp log.out style.out || diff -u log.out style.out
267 $ hg log --debug -T phases > phases.out
267 $ hg log --debug -T phases > phases.out
268 $ cmp log.out phases.out || diff -u log.out phases.out
268 $ cmp log.out phases.out || diff -u log.out phases.out
269
269
270 Default style of working-directory revision should also be the same (but
270 Default style of working-directory revision should also be the same (but
271 date may change while running tests):
271 date may change while running tests):
272
272
273 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
273 $ hg log -r 'wdir()' | sed 's|^date:.*|date:|' > log.out
274 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
274 $ hg log -r 'wdir()' --style default | sed 's|^date:.*|date:|' > style.out
275 $ cmp log.out style.out || diff -u log.out style.out
275 $ cmp log.out style.out || diff -u log.out style.out
276
276
277 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
277 $ hg log -r 'wdir()' -v | sed 's|^date:.*|date:|' > log.out
278 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
278 $ hg log -r 'wdir()' -v --style default | sed 's|^date:.*|date:|' > style.out
279 $ cmp log.out style.out || diff -u log.out style.out
279 $ cmp log.out style.out || diff -u log.out style.out
280
280
281 $ hg log -r 'wdir()' -q > log.out
281 $ hg log -r 'wdir()' -q > log.out
282 $ hg log -r 'wdir()' -q --style default > style.out
282 $ hg log -r 'wdir()' -q --style default > style.out
283 $ cmp log.out style.out || diff -u log.out style.out
283 $ cmp log.out style.out || diff -u log.out style.out
284
284
285 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
285 $ hg log -r 'wdir()' --debug | sed 's|^date:.*|date:|' > log.out
286 $ hg log -r 'wdir()' --debug --style default \
286 $ hg log -r 'wdir()' --debug --style default \
287 > | sed 's|^date:.*|date:|' > style.out
287 > | sed 's|^date:.*|date:|' > style.out
288 $ cmp log.out style.out || diff -u log.out style.out
288 $ cmp log.out style.out || diff -u log.out style.out
289
289
290 Default style should also preserve color information (issue2866):
290 Default style should also preserve color information (issue2866):
291
291
292 $ cp $HGRCPATH $HGRCPATH-bak
292 $ cp $HGRCPATH $HGRCPATH-bak
293 $ cat <<EOF >> $HGRCPATH
293 $ cat <<EOF >> $HGRCPATH
294 > [extensions]
294 > [extensions]
295 > color=
295 > color=
296 > EOF
296 > EOF
297
297
298 $ hg --color=debug log > log.out
298 $ hg --color=debug log > log.out
299 $ hg --color=debug log --style default > style.out
299 $ hg --color=debug log --style default > style.out
300 $ cmp log.out style.out || diff -u log.out style.out
300 $ cmp log.out style.out || diff -u log.out style.out
301 $ hg --color=debug log -T phases > phases.out
301 $ hg --color=debug log -T phases > phases.out
302 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
302 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
303 +[log.phase|phase: draft]
303 +[log.phase|phase: draft]
304 +[log.phase|phase: draft]
304 +[log.phase|phase: draft]
305 +[log.phase|phase: draft]
305 +[log.phase|phase: draft]
306 +[log.phase|phase: draft]
306 +[log.phase|phase: draft]
307 +[log.phase|phase: draft]
307 +[log.phase|phase: draft]
308 +[log.phase|phase: draft]
308 +[log.phase|phase: draft]
309 +[log.phase|phase: draft]
309 +[log.phase|phase: draft]
310 +[log.phase|phase: draft]
310 +[log.phase|phase: draft]
311 +[log.phase|phase: draft]
311 +[log.phase|phase: draft]
312 +[log.phase|phase: draft]
312 +[log.phase|phase: draft]
313
313
314 $ hg --color=debug -v log > log.out
314 $ hg --color=debug -v log > log.out
315 $ hg --color=debug -v log --style default > style.out
315 $ hg --color=debug -v log --style default > style.out
316 $ cmp log.out style.out || diff -u log.out style.out
316 $ cmp log.out style.out || diff -u log.out style.out
317 $ hg --color=debug -v log -T phases > phases.out
317 $ hg --color=debug -v log -T phases > phases.out
318 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
318 $ diff -U 0 log.out phases.out | egrep -v '^---|^\+\+\+|^@@'
319 +[log.phase|phase: draft]
319 +[log.phase|phase: draft]
320 +[log.phase|phase: draft]
320 +[log.phase|phase: draft]
321 +[log.phase|phase: draft]
321 +[log.phase|phase: draft]
322 +[log.phase|phase: draft]
322 +[log.phase|phase: draft]
323 +[log.phase|phase: draft]
323 +[log.phase|phase: draft]
324 +[log.phase|phase: draft]
324 +[log.phase|phase: draft]
325 +[log.phase|phase: draft]
325 +[log.phase|phase: draft]
326 +[log.phase|phase: draft]
326 +[log.phase|phase: draft]
327 +[log.phase|phase: draft]
327 +[log.phase|phase: draft]
328 +[log.phase|phase: draft]
328 +[log.phase|phase: draft]
329
329
330 $ hg --color=debug -q log > log.out
330 $ hg --color=debug -q log > log.out
331 $ hg --color=debug -q log --style default > style.out
331 $ hg --color=debug -q log --style default > style.out
332 $ cmp log.out style.out || diff -u log.out style.out
332 $ cmp log.out style.out || diff -u log.out style.out
333 $ hg --color=debug -q log -T phases > phases.out
333 $ hg --color=debug -q log -T phases > phases.out
334 $ cmp log.out phases.out || diff -u log.out phases.out
334 $ cmp log.out phases.out || diff -u log.out phases.out
335
335
336 $ hg --color=debug --debug log > log.out
336 $ hg --color=debug --debug log > log.out
337 $ hg --color=debug --debug log --style default > style.out
337 $ hg --color=debug --debug log --style default > style.out
338 $ cmp log.out style.out || diff -u log.out style.out
338 $ cmp log.out style.out || diff -u log.out style.out
339 $ hg --color=debug --debug log -T phases > phases.out
339 $ hg --color=debug --debug log -T phases > phases.out
340 $ cmp log.out phases.out || diff -u log.out phases.out
340 $ cmp log.out phases.out || diff -u log.out phases.out
341
341
342 $ mv $HGRCPATH-bak $HGRCPATH
342 $ mv $HGRCPATH-bak $HGRCPATH
343
343
344 Remove commit with empty commit message, so as to not pollute further
344 Remove commit with empty commit message, so as to not pollute further
345 tests.
345 tests.
346
346
347 $ hg --config extensions.strip= strip -q .
347 $ hg --config extensions.strip= strip -q .
348
348
349 Revision with no copies (used to print a traceback):
349 Revision with no copies (used to print a traceback):
350
350
351 $ hg tip -v --template '\n'
351 $ hg tip -v --template '\n'
352
352
353
353
354 Compact style works:
354 Compact style works:
355
355
356 $ hg log -Tcompact
356 $ hg log -Tcompact
357 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
357 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
358 third
358 third
359
359
360 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
360 7:-1 29114dbae42b 1970-01-12 13:46 +0000 user
361 second
361 second
362
362
363 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
363 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
364 merge
364 merge
365
365
366 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
366 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
367 new head
367 new head
368
368
369 4 bbe44766e73d 1970-01-17 04:53 +0000 person
369 4 bbe44766e73d 1970-01-17 04:53 +0000 person
370 new branch
370 new branch
371
371
372 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
372 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
373 no user, no domain
373 no user, no domain
374
374
375 2 97054abb4ab8 1970-01-14 21:20 +0000 other
375 2 97054abb4ab8 1970-01-14 21:20 +0000 other
376 no person
376 no person
377
377
378 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
378 1 b608e9d1a3f0 1970-01-13 17:33 +0000 other
379 other 1
379 other 1
380
380
381 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
381 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 user
382 line 1
382 line 1
383
383
384
384
385 $ hg log -v --style compact
385 $ hg log -v --style compact
386 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
386 8[tip] 95c24699272e 2020-01-01 10:01 +0000 test
387 third
387 third
388
388
389 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
389 7:-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
390 second
390 second
391
391
392 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
392 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
393 merge
393 merge
394
394
395 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
395 5:3 13207e5a10d9 1970-01-18 08:40 +0000 person
396 new head
396 new head
397
397
398 4 bbe44766e73d 1970-01-17 04:53 +0000 person
398 4 bbe44766e73d 1970-01-17 04:53 +0000 person
399 new branch
399 new branch
400
400
401 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
401 3 10e46f2dcbf4 1970-01-16 01:06 +0000 person
402 no user, no domain
402 no user, no domain
403
403
404 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
404 2 97054abb4ab8 1970-01-14 21:20 +0000 other@place
405 no person
405 no person
406
406
407 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
407 1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
408 other 1
408 other 1
409 other 2
409 other 2
410
410
411 other 3
411 other 3
412
412
413 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
413 0 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
414 line 1
414 line 1
415 line 2
415 line 2
416
416
417
417
418 $ hg log --debug --style compact
418 $ hg log --debug --style compact
419 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
419 8[tip]:7,-1 95c24699272e 2020-01-01 10:01 +0000 test
420 third
420 third
421
421
422 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
422 7:-1,-1 29114dbae42b 1970-01-12 13:46 +0000 User Name <user@hostname>
423 second
423 second
424
424
425 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
425 6:5,4 d41e714fe50d 1970-01-18 08:40 +0000 person
426 merge
426 merge
427
427
428 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
428 5:3,-1 13207e5a10d9 1970-01-18 08:40 +0000 person
429 new head
429 new head
430
430
431 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
431 4:3,-1 bbe44766e73d 1970-01-17 04:53 +0000 person
432 new branch
432 new branch
433
433
434 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
434 3:2,-1 10e46f2dcbf4 1970-01-16 01:06 +0000 person
435 no user, no domain
435 no user, no domain
436
436
437 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
437 2:1,-1 97054abb4ab8 1970-01-14 21:20 +0000 other@place
438 no person
438 no person
439
439
440 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
440 1:0,-1 b608e9d1a3f0 1970-01-13 17:33 +0000 A. N. Other <other@place>
441 other 1
441 other 1
442 other 2
442 other 2
443
443
444 other 3
444 other 3
445
445
446 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
446 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:46 +0000 User Name <user@hostname>
447 line 1
447 line 1
448 line 2
448 line 2
449
449
450
450
451 Test xml styles:
451 Test xml styles:
452
452
453 $ hg log --style xml -r 'not all()'
453 $ hg log --style xml -r 'not all()'
454 <?xml version="1.0"?>
454 <?xml version="1.0"?>
455 <log>
455 <log>
456 </log>
456 </log>
457
457
458 $ hg log --style xml
458 $ hg log --style xml
459 <?xml version="1.0"?>
459 <?xml version="1.0"?>
460 <log>
460 <log>
461 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
461 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
462 <tag>tip</tag>
462 <tag>tip</tag>
463 <author email="test">test</author>
463 <author email="test">test</author>
464 <date>2020-01-01T10:01:00+00:00</date>
464 <date>2020-01-01T10:01:00+00:00</date>
465 <msg xml:space="preserve">third</msg>
465 <msg xml:space="preserve">third</msg>
466 </logentry>
466 </logentry>
467 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
467 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
468 <parent revision="-1" node="0000000000000000000000000000000000000000" />
468 <parent revision="-1" node="0000000000000000000000000000000000000000" />
469 <author email="user@hostname">User Name</author>
469 <author email="user@hostname">User Name</author>
470 <date>1970-01-12T13:46:40+00:00</date>
470 <date>1970-01-12T13:46:40+00:00</date>
471 <msg xml:space="preserve">second</msg>
471 <msg xml:space="preserve">second</msg>
472 </logentry>
472 </logentry>
473 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
473 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
474 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
474 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
475 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
475 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
476 <author email="person">person</author>
476 <author email="person">person</author>
477 <date>1970-01-18T08:40:01+00:00</date>
477 <date>1970-01-18T08:40:01+00:00</date>
478 <msg xml:space="preserve">merge</msg>
478 <msg xml:space="preserve">merge</msg>
479 </logentry>
479 </logentry>
480 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
480 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
481 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
481 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
482 <author email="person">person</author>
482 <author email="person">person</author>
483 <date>1970-01-18T08:40:00+00:00</date>
483 <date>1970-01-18T08:40:00+00:00</date>
484 <msg xml:space="preserve">new head</msg>
484 <msg xml:space="preserve">new head</msg>
485 </logentry>
485 </logentry>
486 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
486 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
487 <branch>foo</branch>
487 <branch>foo</branch>
488 <author email="person">person</author>
488 <author email="person">person</author>
489 <date>1970-01-17T04:53:20+00:00</date>
489 <date>1970-01-17T04:53:20+00:00</date>
490 <msg xml:space="preserve">new branch</msg>
490 <msg xml:space="preserve">new branch</msg>
491 </logentry>
491 </logentry>
492 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
492 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
493 <author email="person">person</author>
493 <author email="person">person</author>
494 <date>1970-01-16T01:06:40+00:00</date>
494 <date>1970-01-16T01:06:40+00:00</date>
495 <msg xml:space="preserve">no user, no domain</msg>
495 <msg xml:space="preserve">no user, no domain</msg>
496 </logentry>
496 </logentry>
497 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
497 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
498 <author email="other@place">other</author>
498 <author email="other@place">other</author>
499 <date>1970-01-14T21:20:00+00:00</date>
499 <date>1970-01-14T21:20:00+00:00</date>
500 <msg xml:space="preserve">no person</msg>
500 <msg xml:space="preserve">no person</msg>
501 </logentry>
501 </logentry>
502 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
502 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
503 <author email="other@place">A. N. Other</author>
503 <author email="other@place">A. N. Other</author>
504 <date>1970-01-13T17:33:20+00:00</date>
504 <date>1970-01-13T17:33:20+00:00</date>
505 <msg xml:space="preserve">other 1
505 <msg xml:space="preserve">other 1
506 other 2
506 other 2
507
507
508 other 3</msg>
508 other 3</msg>
509 </logentry>
509 </logentry>
510 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
510 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
511 <author email="user@hostname">User Name</author>
511 <author email="user@hostname">User Name</author>
512 <date>1970-01-12T13:46:40+00:00</date>
512 <date>1970-01-12T13:46:40+00:00</date>
513 <msg xml:space="preserve">line 1
513 <msg xml:space="preserve">line 1
514 line 2</msg>
514 line 2</msg>
515 </logentry>
515 </logentry>
516 </log>
516 </log>
517
517
518 $ hg log -v --style xml
518 $ hg log -v --style xml
519 <?xml version="1.0"?>
519 <?xml version="1.0"?>
520 <log>
520 <log>
521 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
521 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
522 <tag>tip</tag>
522 <tag>tip</tag>
523 <author email="test">test</author>
523 <author email="test">test</author>
524 <date>2020-01-01T10:01:00+00:00</date>
524 <date>2020-01-01T10:01:00+00:00</date>
525 <msg xml:space="preserve">third</msg>
525 <msg xml:space="preserve">third</msg>
526 <paths>
526 <paths>
527 <path action="A">fourth</path>
527 <path action="A">fourth</path>
528 <path action="A">third</path>
528 <path action="A">third</path>
529 <path action="R">second</path>
529 <path action="R">second</path>
530 </paths>
530 </paths>
531 <copies>
531 <copies>
532 <copy source="second">fourth</copy>
532 <copy source="second">fourth</copy>
533 </copies>
533 </copies>
534 </logentry>
534 </logentry>
535 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
535 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
536 <parent revision="-1" node="0000000000000000000000000000000000000000" />
536 <parent revision="-1" node="0000000000000000000000000000000000000000" />
537 <author email="user@hostname">User Name</author>
537 <author email="user@hostname">User Name</author>
538 <date>1970-01-12T13:46:40+00:00</date>
538 <date>1970-01-12T13:46:40+00:00</date>
539 <msg xml:space="preserve">second</msg>
539 <msg xml:space="preserve">second</msg>
540 <paths>
540 <paths>
541 <path action="A">second</path>
541 <path action="A">second</path>
542 </paths>
542 </paths>
543 </logentry>
543 </logentry>
544 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
544 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
545 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
545 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
546 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
546 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
547 <author email="person">person</author>
547 <author email="person">person</author>
548 <date>1970-01-18T08:40:01+00:00</date>
548 <date>1970-01-18T08:40:01+00:00</date>
549 <msg xml:space="preserve">merge</msg>
549 <msg xml:space="preserve">merge</msg>
550 <paths>
550 <paths>
551 </paths>
551 </paths>
552 </logentry>
552 </logentry>
553 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
553 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
554 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
554 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
555 <author email="person">person</author>
555 <author email="person">person</author>
556 <date>1970-01-18T08:40:00+00:00</date>
556 <date>1970-01-18T08:40:00+00:00</date>
557 <msg xml:space="preserve">new head</msg>
557 <msg xml:space="preserve">new head</msg>
558 <paths>
558 <paths>
559 <path action="A">d</path>
559 <path action="A">d</path>
560 </paths>
560 </paths>
561 </logentry>
561 </logentry>
562 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
562 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
563 <branch>foo</branch>
563 <branch>foo</branch>
564 <author email="person">person</author>
564 <author email="person">person</author>
565 <date>1970-01-17T04:53:20+00:00</date>
565 <date>1970-01-17T04:53:20+00:00</date>
566 <msg xml:space="preserve">new branch</msg>
566 <msg xml:space="preserve">new branch</msg>
567 <paths>
567 <paths>
568 </paths>
568 </paths>
569 </logentry>
569 </logentry>
570 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
570 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
571 <author email="person">person</author>
571 <author email="person">person</author>
572 <date>1970-01-16T01:06:40+00:00</date>
572 <date>1970-01-16T01:06:40+00:00</date>
573 <msg xml:space="preserve">no user, no domain</msg>
573 <msg xml:space="preserve">no user, no domain</msg>
574 <paths>
574 <paths>
575 <path action="M">c</path>
575 <path action="M">c</path>
576 </paths>
576 </paths>
577 </logentry>
577 </logentry>
578 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
578 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
579 <author email="other@place">other</author>
579 <author email="other@place">other</author>
580 <date>1970-01-14T21:20:00+00:00</date>
580 <date>1970-01-14T21:20:00+00:00</date>
581 <msg xml:space="preserve">no person</msg>
581 <msg xml:space="preserve">no person</msg>
582 <paths>
582 <paths>
583 <path action="A">c</path>
583 <path action="A">c</path>
584 </paths>
584 </paths>
585 </logentry>
585 </logentry>
586 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
586 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
587 <author email="other@place">A. N. Other</author>
587 <author email="other@place">A. N. Other</author>
588 <date>1970-01-13T17:33:20+00:00</date>
588 <date>1970-01-13T17:33:20+00:00</date>
589 <msg xml:space="preserve">other 1
589 <msg xml:space="preserve">other 1
590 other 2
590 other 2
591
591
592 other 3</msg>
592 other 3</msg>
593 <paths>
593 <paths>
594 <path action="A">b</path>
594 <path action="A">b</path>
595 </paths>
595 </paths>
596 </logentry>
596 </logentry>
597 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
597 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
598 <author email="user@hostname">User Name</author>
598 <author email="user@hostname">User Name</author>
599 <date>1970-01-12T13:46:40+00:00</date>
599 <date>1970-01-12T13:46:40+00:00</date>
600 <msg xml:space="preserve">line 1
600 <msg xml:space="preserve">line 1
601 line 2</msg>
601 line 2</msg>
602 <paths>
602 <paths>
603 <path action="A">a</path>
603 <path action="A">a</path>
604 </paths>
604 </paths>
605 </logentry>
605 </logentry>
606 </log>
606 </log>
607
607
608 $ hg log --debug --style xml
608 $ hg log --debug --style xml
609 <?xml version="1.0"?>
609 <?xml version="1.0"?>
610 <log>
610 <log>
611 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
611 <logentry revision="8" node="95c24699272ef57d062b8bccc32c878bf841784a">
612 <tag>tip</tag>
612 <tag>tip</tag>
613 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
613 <parent revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453" />
614 <parent revision="-1" node="0000000000000000000000000000000000000000" />
614 <parent revision="-1" node="0000000000000000000000000000000000000000" />
615 <author email="test">test</author>
615 <author email="test">test</author>
616 <date>2020-01-01T10:01:00+00:00</date>
616 <date>2020-01-01T10:01:00+00:00</date>
617 <msg xml:space="preserve">third</msg>
617 <msg xml:space="preserve">third</msg>
618 <paths>
618 <paths>
619 <path action="A">fourth</path>
619 <path action="A">fourth</path>
620 <path action="A">third</path>
620 <path action="A">third</path>
621 <path action="R">second</path>
621 <path action="R">second</path>
622 </paths>
622 </paths>
623 <copies>
623 <copies>
624 <copy source="second">fourth</copy>
624 <copy source="second">fourth</copy>
625 </copies>
625 </copies>
626 <extra key="branch">default</extra>
626 <extra key="branch">default</extra>
627 </logentry>
627 </logentry>
628 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
628 <logentry revision="7" node="29114dbae42b9f078cf2714dbe3a86bba8ec7453">
629 <parent revision="-1" node="0000000000000000000000000000000000000000" />
629 <parent revision="-1" node="0000000000000000000000000000000000000000" />
630 <parent revision="-1" node="0000000000000000000000000000000000000000" />
630 <parent revision="-1" node="0000000000000000000000000000000000000000" />
631 <author email="user@hostname">User Name</author>
631 <author email="user@hostname">User Name</author>
632 <date>1970-01-12T13:46:40+00:00</date>
632 <date>1970-01-12T13:46:40+00:00</date>
633 <msg xml:space="preserve">second</msg>
633 <msg xml:space="preserve">second</msg>
634 <paths>
634 <paths>
635 <path action="A">second</path>
635 <path action="A">second</path>
636 </paths>
636 </paths>
637 <extra key="branch">default</extra>
637 <extra key="branch">default</extra>
638 </logentry>
638 </logentry>
639 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
639 <logentry revision="6" node="d41e714fe50d9e4a5f11b4d595d543481b5f980b">
640 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
640 <parent revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f" />
641 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
641 <parent revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74" />
642 <author email="person">person</author>
642 <author email="person">person</author>
643 <date>1970-01-18T08:40:01+00:00</date>
643 <date>1970-01-18T08:40:01+00:00</date>
644 <msg xml:space="preserve">merge</msg>
644 <msg xml:space="preserve">merge</msg>
645 <paths>
645 <paths>
646 </paths>
646 </paths>
647 <extra key="branch">default</extra>
647 <extra key="branch">default</extra>
648 </logentry>
648 </logentry>
649 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
649 <logentry revision="5" node="13207e5a10d9fd28ec424934298e176197f2c67f">
650 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
650 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
651 <parent revision="-1" node="0000000000000000000000000000000000000000" />
651 <parent revision="-1" node="0000000000000000000000000000000000000000" />
652 <author email="person">person</author>
652 <author email="person">person</author>
653 <date>1970-01-18T08:40:00+00:00</date>
653 <date>1970-01-18T08:40:00+00:00</date>
654 <msg xml:space="preserve">new head</msg>
654 <msg xml:space="preserve">new head</msg>
655 <paths>
655 <paths>
656 <path action="A">d</path>
656 <path action="A">d</path>
657 </paths>
657 </paths>
658 <extra key="branch">default</extra>
658 <extra key="branch">default</extra>
659 </logentry>
659 </logentry>
660 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
660 <logentry revision="4" node="bbe44766e73d5f11ed2177f1838de10c53ef3e74">
661 <branch>foo</branch>
661 <branch>foo</branch>
662 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
662 <parent revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47" />
663 <parent revision="-1" node="0000000000000000000000000000000000000000" />
663 <parent revision="-1" node="0000000000000000000000000000000000000000" />
664 <author email="person">person</author>
664 <author email="person">person</author>
665 <date>1970-01-17T04:53:20+00:00</date>
665 <date>1970-01-17T04:53:20+00:00</date>
666 <msg xml:space="preserve">new branch</msg>
666 <msg xml:space="preserve">new branch</msg>
667 <paths>
667 <paths>
668 </paths>
668 </paths>
669 <extra key="branch">foo</extra>
669 <extra key="branch">foo</extra>
670 </logentry>
670 </logentry>
671 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
671 <logentry revision="3" node="10e46f2dcbf4823578cf180f33ecf0b957964c47">
672 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
672 <parent revision="2" node="97054abb4ab824450e9164180baf491ae0078465" />
673 <parent revision="-1" node="0000000000000000000000000000000000000000" />
673 <parent revision="-1" node="0000000000000000000000000000000000000000" />
674 <author email="person">person</author>
674 <author email="person">person</author>
675 <date>1970-01-16T01:06:40+00:00</date>
675 <date>1970-01-16T01:06:40+00:00</date>
676 <msg xml:space="preserve">no user, no domain</msg>
676 <msg xml:space="preserve">no user, no domain</msg>
677 <paths>
677 <paths>
678 <path action="M">c</path>
678 <path action="M">c</path>
679 </paths>
679 </paths>
680 <extra key="branch">default</extra>
680 <extra key="branch">default</extra>
681 </logentry>
681 </logentry>
682 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
682 <logentry revision="2" node="97054abb4ab824450e9164180baf491ae0078465">
683 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
683 <parent revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965" />
684 <parent revision="-1" node="0000000000000000000000000000000000000000" />
684 <parent revision="-1" node="0000000000000000000000000000000000000000" />
685 <author email="other@place">other</author>
685 <author email="other@place">other</author>
686 <date>1970-01-14T21:20:00+00:00</date>
686 <date>1970-01-14T21:20:00+00:00</date>
687 <msg xml:space="preserve">no person</msg>
687 <msg xml:space="preserve">no person</msg>
688 <paths>
688 <paths>
689 <path action="A">c</path>
689 <path action="A">c</path>
690 </paths>
690 </paths>
691 <extra key="branch">default</extra>
691 <extra key="branch">default</extra>
692 </logentry>
692 </logentry>
693 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
693 <logentry revision="1" node="b608e9d1a3f0273ccf70fb85fd6866b3482bf965">
694 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
694 <parent revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f" />
695 <parent revision="-1" node="0000000000000000000000000000000000000000" />
695 <parent revision="-1" node="0000000000000000000000000000000000000000" />
696 <author email="other@place">A. N. Other</author>
696 <author email="other@place">A. N. Other</author>
697 <date>1970-01-13T17:33:20+00:00</date>
697 <date>1970-01-13T17:33:20+00:00</date>
698 <msg xml:space="preserve">other 1
698 <msg xml:space="preserve">other 1
699 other 2
699 other 2
700
700
701 other 3</msg>
701 other 3</msg>
702 <paths>
702 <paths>
703 <path action="A">b</path>
703 <path action="A">b</path>
704 </paths>
704 </paths>
705 <extra key="branch">default</extra>
705 <extra key="branch">default</extra>
706 </logentry>
706 </logentry>
707 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
707 <logentry revision="0" node="1e4e1b8f71e05681d422154f5421e385fec3454f">
708 <parent revision="-1" node="0000000000000000000000000000000000000000" />
708 <parent revision="-1" node="0000000000000000000000000000000000000000" />
709 <parent revision="-1" node="0000000000000000000000000000000000000000" />
709 <parent revision="-1" node="0000000000000000000000000000000000000000" />
710 <author email="user@hostname">User Name</author>
710 <author email="user@hostname">User Name</author>
711 <date>1970-01-12T13:46:40+00:00</date>
711 <date>1970-01-12T13:46:40+00:00</date>
712 <msg xml:space="preserve">line 1
712 <msg xml:space="preserve">line 1
713 line 2</msg>
713 line 2</msg>
714 <paths>
714 <paths>
715 <path action="A">a</path>
715 <path action="A">a</path>
716 </paths>
716 </paths>
717 <extra key="branch">default</extra>
717 <extra key="branch">default</extra>
718 </logentry>
718 </logentry>
719 </log>
719 </log>
720
720
721
721
722 test CBOR style:
722 test CBOR style:
723
723
724 $ cat <<'EOF' > "$TESTTMP/decodecborarray.py"
724 $ cat <<'EOF' > "$TESTTMP/decodecborarray.py"
725 > from __future__ import absolute_import
725 > from __future__ import absolute_import
726 > from mercurial import (
726 > from mercurial import (
727 > dispatch,
727 > dispatch,
728 > )
728 > )
729 > from mercurial.utils import (
729 > from mercurial.utils import (
730 > cborutil,
730 > cborutil,
731 > procutil,
731 > procutil,
732 > stringutil,
732 > stringutil,
733 > )
733 > )
734 > dispatch.initstdio()
734 > dispatch.initstdio()
735 > data = procutil.stdin.read()
735 > data = procutil.stdin.read()
736 > # our CBOR decoder doesn't support parsing indefinite-length arrays,
736 > # our CBOR decoder doesn't support parsing indefinite-length arrays,
737 > # but the log output is indefinite stream by nature.
737 > # but the log output is indefinite stream by nature.
738 > assert data[:1] == cborutil.BEGIN_INDEFINITE_ARRAY
738 > assert data[:1] == cborutil.BEGIN_INDEFINITE_ARRAY
739 > assert data[-1:] == cborutil.BREAK
739 > assert data[-1:] == cborutil.BREAK
740 > items = cborutil.decodeall(data[1:-1])
740 > items = cborutil.decodeall(data[1:-1])
741 > procutil.stdout.write(stringutil.pprint(items, indent=1) + b'\n')
741 > procutil.stdout.write(stringutil.pprint(items, indent=1) + b'\n')
742 > EOF
742 > EOF
743
743
744 $ hg log -k nosuch -Tcbor | "$PYTHON" "$TESTTMP/decodecborarray.py"
744 $ hg log -k nosuch -Tcbor | "$PYTHON" "$TESTTMP/decodecborarray.py"
745 []
745 []
746
746
747 $ hg log -qr0:1 -Tcbor | "$PYTHON" "$TESTTMP/decodecborarray.py"
747 $ hg log -qr0:1 -Tcbor | "$PYTHON" "$TESTTMP/decodecborarray.py"
748 [
748 [
749 {
749 {
750 'node': '1e4e1b8f71e05681d422154f5421e385fec3454f',
750 'node': '1e4e1b8f71e05681d422154f5421e385fec3454f',
751 'rev': 0
751 'rev': 0
752 },
752 },
753 {
753 {
754 'node': 'b608e9d1a3f0273ccf70fb85fd6866b3482bf965',
754 'node': 'b608e9d1a3f0273ccf70fb85fd6866b3482bf965',
755 'rev': 1
755 'rev': 1
756 }
756 }
757 ]
757 ]
758
758
759 $ hg log -vpr . -Tcbor --stat | "$PYTHON" "$TESTTMP/decodecborarray.py"
759 $ hg log -vpr . -Tcbor --stat | "$PYTHON" "$TESTTMP/decodecborarray.py"
760 [
760 [
761 {
761 {
762 'bookmarks': [],
762 'bookmarks': [],
763 'branch': 'default',
763 'branch': 'default',
764 'date': [
764 'date': [
765 1577872860,
765 1577872860,
766 0
766 0
767 ],
767 ],
768 'desc': 'third',
768 'desc': 'third',
769 'diff': 'diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n',
769 'diff': 'diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n',
770 'diffstat': ' fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n',
770 'diffstat': ' fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n',
771 'files': [
771 'files': [
772 'fourth',
772 'fourth',
773 'second',
773 'second',
774 'third'
774 'third'
775 ],
775 ],
776 'node': '95c24699272ef57d062b8bccc32c878bf841784a',
776 'node': '95c24699272ef57d062b8bccc32c878bf841784a',
777 'parents': [
777 'parents': [
778 '29114dbae42b9f078cf2714dbe3a86bba8ec7453'
778 '29114dbae42b9f078cf2714dbe3a86bba8ec7453'
779 ],
779 ],
780 'phase': 'draft',
780 'phase': 'draft',
781 'rev': 8,
781 'rev': 8,
782 'tags': [
782 'tags': [
783 'tip'
783 'tip'
784 ],
784 ],
785 'user': 'test'
785 'user': 'test'
786 }
786 }
787 ]
787 ]
788
788
789 $ hg log -r . -T'cbor(rev, node|short)' | "$PYTHON" "$TESTTMP/decodecborarray.py"
789 $ hg log -r . -T'cbor(rev, node|short)' | "$PYTHON" "$TESTTMP/decodecborarray.py"
790 [
790 [
791 {
791 {
792 'node': '95c24699272e',
792 'node': '95c24699272e',
793 'rev': 8
793 'rev': 8
794 }
794 }
795 ]
795 ]
796
796
797 $ hg log -r . -T'cbor()' | "$PYTHON" "$TESTTMP/decodecborarray.py"
797 $ hg log -r . -T'cbor()' | "$PYTHON" "$TESTTMP/decodecborarray.py"
798 [
798 [
799 {}
799 {}
800 ]
800 ]
801
801
802 Test JSON style:
802 Test JSON style:
803
803
804 $ hg log -k nosuch -Tjson
804 $ hg log -k nosuch -Tjson
805 [
805 [
806 ]
806 ]
807
807
808 $ hg log -qr . -Tjson
808 $ hg log -qr . -Tjson
809 [
809 [
810 {
810 {
811 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
811 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
812 "rev": 8
812 "rev": 8
813 }
813 }
814 ]
814 ]
815
815
816 $ hg log -vpr . -Tjson --stat
816 $ hg log -vpr . -Tjson --stat
817 [
817 [
818 {
818 {
819 "bookmarks": [],
819 "bookmarks": [],
820 "branch": "default",
820 "branch": "default",
821 "date": [1577872860, 0],
821 "date": [1577872860, 0],
822 "desc": "third",
822 "desc": "third",
823 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n",
823 "diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n",
824 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
824 "diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n",
825 "files": ["fourth", "second", "third"],
825 "files": ["fourth", "second", "third"],
826 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
826 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
827 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
827 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
828 "phase": "draft",
828 "phase": "draft",
829 "rev": 8,
829 "rev": 8,
830 "tags": ["tip"],
830 "tags": ["tip"],
831 "user": "test"
831 "user": "test"
832 }
832 }
833 ]
833 ]
834
834
835 honor --git but not format-breaking diffopts
835 honor --git but not format-breaking diffopts
836 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
836 $ hg --config diff.noprefix=True log --git -vpr . -Tjson
837 [
837 [
838 {
838 {
839 "bookmarks": [],
839 "bookmarks": [],
840 "branch": "default",
840 "branch": "default",
841 "date": [1577872860, 0],
841 "date": [1577872860, 0],
842 "desc": "third",
842 "desc": "third",
843 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n",
843 "diff": "diff --git a/second b/fourth\nrename from second\nrename to fourth\ndiff --git a/third b/third\nnew file mode 100644\n--- /dev/null\n+++ b/third\n@@ -0,0 +1,1 @@\n+third\n",
844 "files": ["fourth", "second", "third"],
844 "files": ["fourth", "second", "third"],
845 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
845 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
846 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
846 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
847 "phase": "draft",
847 "phase": "draft",
848 "rev": 8,
848 "rev": 8,
849 "tags": ["tip"],
849 "tags": ["tip"],
850 "user": "test"
850 "user": "test"
851 }
851 }
852 ]
852 ]
853
853
854 $ hg log -T json
854 $ hg log -T json
855 [
855 [
856 {
856 {
857 "bookmarks": [],
857 "bookmarks": [],
858 "branch": "default",
858 "branch": "default",
859 "date": [1577872860, 0],
859 "date": [1577872860, 0],
860 "desc": "third",
860 "desc": "third",
861 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
861 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
862 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
862 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
863 "phase": "draft",
863 "phase": "draft",
864 "rev": 8,
864 "rev": 8,
865 "tags": ["tip"],
865 "tags": ["tip"],
866 "user": "test"
866 "user": "test"
867 },
867 },
868 {
868 {
869 "bookmarks": [],
869 "bookmarks": [],
870 "branch": "default",
870 "branch": "default",
871 "date": [1000000, 0],
871 "date": [1000000, 0],
872 "desc": "second",
872 "desc": "second",
873 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
873 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
874 "parents": ["0000000000000000000000000000000000000000"],
874 "parents": ["0000000000000000000000000000000000000000"],
875 "phase": "draft",
875 "phase": "draft",
876 "rev": 7,
876 "rev": 7,
877 "tags": [],
877 "tags": [],
878 "user": "User Name <user@hostname>"
878 "user": "User Name <user@hostname>"
879 },
879 },
880 {
880 {
881 "bookmarks": [],
881 "bookmarks": [],
882 "branch": "default",
882 "branch": "default",
883 "date": [1500001, 0],
883 "date": [1500001, 0],
884 "desc": "merge",
884 "desc": "merge",
885 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
885 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
886 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
886 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
887 "phase": "draft",
887 "phase": "draft",
888 "rev": 6,
888 "rev": 6,
889 "tags": [],
889 "tags": [],
890 "user": "person"
890 "user": "person"
891 },
891 },
892 {
892 {
893 "bookmarks": [],
893 "bookmarks": [],
894 "branch": "default",
894 "branch": "default",
895 "date": [1500000, 0],
895 "date": [1500000, 0],
896 "desc": "new head",
896 "desc": "new head",
897 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
897 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
898 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
898 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
899 "phase": "draft",
899 "phase": "draft",
900 "rev": 5,
900 "rev": 5,
901 "tags": [],
901 "tags": [],
902 "user": "person"
902 "user": "person"
903 },
903 },
904 {
904 {
905 "bookmarks": [],
905 "bookmarks": [],
906 "branch": "foo",
906 "branch": "foo",
907 "date": [1400000, 0],
907 "date": [1400000, 0],
908 "desc": "new branch",
908 "desc": "new branch",
909 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
909 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
910 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
910 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
911 "phase": "draft",
911 "phase": "draft",
912 "rev": 4,
912 "rev": 4,
913 "tags": [],
913 "tags": [],
914 "user": "person"
914 "user": "person"
915 },
915 },
916 {
916 {
917 "bookmarks": [],
917 "bookmarks": [],
918 "branch": "default",
918 "branch": "default",
919 "date": [1300000, 0],
919 "date": [1300000, 0],
920 "desc": "no user, no domain",
920 "desc": "no user, no domain",
921 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
921 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
922 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
922 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
923 "phase": "draft",
923 "phase": "draft",
924 "rev": 3,
924 "rev": 3,
925 "tags": [],
925 "tags": [],
926 "user": "person"
926 "user": "person"
927 },
927 },
928 {
928 {
929 "bookmarks": [],
929 "bookmarks": [],
930 "branch": "default",
930 "branch": "default",
931 "date": [1200000, 0],
931 "date": [1200000, 0],
932 "desc": "no person",
932 "desc": "no person",
933 "node": "97054abb4ab824450e9164180baf491ae0078465",
933 "node": "97054abb4ab824450e9164180baf491ae0078465",
934 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
934 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
935 "phase": "draft",
935 "phase": "draft",
936 "rev": 2,
936 "rev": 2,
937 "tags": [],
937 "tags": [],
938 "user": "other@place"
938 "user": "other@place"
939 },
939 },
940 {
940 {
941 "bookmarks": [],
941 "bookmarks": [],
942 "branch": "default",
942 "branch": "default",
943 "date": [1100000, 0],
943 "date": [1100000, 0],
944 "desc": "other 1\nother 2\n\nother 3",
944 "desc": "other 1\nother 2\n\nother 3",
945 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
945 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
946 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
946 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
947 "phase": "draft",
947 "phase": "draft",
948 "rev": 1,
948 "rev": 1,
949 "tags": [],
949 "tags": [],
950 "user": "A. N. Other <other@place>"
950 "user": "A. N. Other <other@place>"
951 },
951 },
952 {
952 {
953 "bookmarks": [],
953 "bookmarks": [],
954 "branch": "default",
954 "branch": "default",
955 "date": [1000000, 0],
955 "date": [1000000, 0],
956 "desc": "line 1\nline 2",
956 "desc": "line 1\nline 2",
957 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
957 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
958 "parents": ["0000000000000000000000000000000000000000"],
958 "parents": ["0000000000000000000000000000000000000000"],
959 "phase": "draft",
959 "phase": "draft",
960 "rev": 0,
960 "rev": 0,
961 "tags": [],
961 "tags": [],
962 "user": "User Name <user@hostname>"
962 "user": "User Name <user@hostname>"
963 }
963 }
964 ]
964 ]
965
965
966 $ hg heads -v -Tjson
966 $ hg heads -v -Tjson
967 [
967 [
968 {
968 {
969 "bookmarks": [],
969 "bookmarks": [],
970 "branch": "default",
970 "branch": "default",
971 "date": [1577872860, 0],
971 "date": [1577872860, 0],
972 "desc": "third",
972 "desc": "third",
973 "files": ["fourth", "second", "third"],
973 "files": ["fourth", "second", "third"],
974 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
974 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
975 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
975 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
976 "phase": "draft",
976 "phase": "draft",
977 "rev": 8,
977 "rev": 8,
978 "tags": ["tip"],
978 "tags": ["tip"],
979 "user": "test"
979 "user": "test"
980 },
980 },
981 {
981 {
982 "bookmarks": [],
982 "bookmarks": [],
983 "branch": "default",
983 "branch": "default",
984 "date": [1500001, 0],
984 "date": [1500001, 0],
985 "desc": "merge",
985 "desc": "merge",
986 "files": [],
986 "files": [],
987 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
987 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
988 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
988 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
989 "phase": "draft",
989 "phase": "draft",
990 "rev": 6,
990 "rev": 6,
991 "tags": [],
991 "tags": [],
992 "user": "person"
992 "user": "person"
993 },
993 },
994 {
994 {
995 "bookmarks": [],
995 "bookmarks": [],
996 "branch": "foo",
996 "branch": "foo",
997 "date": [1400000, 0],
997 "date": [1400000, 0],
998 "desc": "new branch",
998 "desc": "new branch",
999 "files": [],
999 "files": [],
1000 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1000 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1001 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1001 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1002 "phase": "draft",
1002 "phase": "draft",
1003 "rev": 4,
1003 "rev": 4,
1004 "tags": [],
1004 "tags": [],
1005 "user": "person"
1005 "user": "person"
1006 }
1006 }
1007 ]
1007 ]
1008
1008
1009 $ hg log --debug -Tjson
1009 $ hg log --debug -Tjson
1010 [
1010 [
1011 {
1011 {
1012 "added": ["fourth", "third"],
1012 "added": ["fourth", "third"],
1013 "bookmarks": [],
1013 "bookmarks": [],
1014 "branch": "default",
1014 "branch": "default",
1015 "date": [1577872860, 0],
1015 "date": [1577872860, 0],
1016 "desc": "third",
1016 "desc": "third",
1017 "extra": {"branch": "default"},
1017 "extra": {"branch": "default"},
1018 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
1018 "manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64",
1019 "modified": [],
1019 "modified": [],
1020 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1020 "node": "95c24699272ef57d062b8bccc32c878bf841784a",
1021 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1021 "parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"],
1022 "phase": "draft",
1022 "phase": "draft",
1023 "removed": ["second"],
1023 "removed": ["second"],
1024 "rev": 8,
1024 "rev": 8,
1025 "tags": ["tip"],
1025 "tags": ["tip"],
1026 "user": "test"
1026 "user": "test"
1027 },
1027 },
1028 {
1028 {
1029 "added": ["second"],
1029 "added": ["second"],
1030 "bookmarks": [],
1030 "bookmarks": [],
1031 "branch": "default",
1031 "branch": "default",
1032 "date": [1000000, 0],
1032 "date": [1000000, 0],
1033 "desc": "second",
1033 "desc": "second",
1034 "extra": {"branch": "default"},
1034 "extra": {"branch": "default"},
1035 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
1035 "manifest": "f2dbc354b94e5ec0b4f10680ee0cee816101d0bf",
1036 "modified": [],
1036 "modified": [],
1037 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
1037 "node": "29114dbae42b9f078cf2714dbe3a86bba8ec7453",
1038 "parents": ["0000000000000000000000000000000000000000"],
1038 "parents": ["0000000000000000000000000000000000000000"],
1039 "phase": "draft",
1039 "phase": "draft",
1040 "removed": [],
1040 "removed": [],
1041 "rev": 7,
1041 "rev": 7,
1042 "tags": [],
1042 "tags": [],
1043 "user": "User Name <user@hostname>"
1043 "user": "User Name <user@hostname>"
1044 },
1044 },
1045 {
1045 {
1046 "added": [],
1046 "added": [],
1047 "bookmarks": [],
1047 "bookmarks": [],
1048 "branch": "default",
1048 "branch": "default",
1049 "date": [1500001, 0],
1049 "date": [1500001, 0],
1050 "desc": "merge",
1050 "desc": "merge",
1051 "extra": {"branch": "default"},
1051 "extra": {"branch": "default"},
1052 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1052 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1053 "modified": [],
1053 "modified": [],
1054 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1054 "node": "d41e714fe50d9e4a5f11b4d595d543481b5f980b",
1055 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1055 "parents": ["13207e5a10d9fd28ec424934298e176197f2c67f", "bbe44766e73d5f11ed2177f1838de10c53ef3e74"],
1056 "phase": "draft",
1056 "phase": "draft",
1057 "removed": [],
1057 "removed": [],
1058 "rev": 6,
1058 "rev": 6,
1059 "tags": [],
1059 "tags": [],
1060 "user": "person"
1060 "user": "person"
1061 },
1061 },
1062 {
1062 {
1063 "added": ["d"],
1063 "added": ["d"],
1064 "bookmarks": [],
1064 "bookmarks": [],
1065 "branch": "default",
1065 "branch": "default",
1066 "date": [1500000, 0],
1066 "date": [1500000, 0],
1067 "desc": "new head",
1067 "desc": "new head",
1068 "extra": {"branch": "default"},
1068 "extra": {"branch": "default"},
1069 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1069 "manifest": "4dc3def4f9b4c6e8de820f6ee74737f91e96a216",
1070 "modified": [],
1070 "modified": [],
1071 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1071 "node": "13207e5a10d9fd28ec424934298e176197f2c67f",
1072 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1072 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1073 "phase": "draft",
1073 "phase": "draft",
1074 "removed": [],
1074 "removed": [],
1075 "rev": 5,
1075 "rev": 5,
1076 "tags": [],
1076 "tags": [],
1077 "user": "person"
1077 "user": "person"
1078 },
1078 },
1079 {
1079 {
1080 "added": [],
1080 "added": [],
1081 "bookmarks": [],
1081 "bookmarks": [],
1082 "branch": "foo",
1082 "branch": "foo",
1083 "date": [1400000, 0],
1083 "date": [1400000, 0],
1084 "desc": "new branch",
1084 "desc": "new branch",
1085 "extra": {"branch": "foo"},
1085 "extra": {"branch": "foo"},
1086 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1086 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1087 "modified": [],
1087 "modified": [],
1088 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1088 "node": "bbe44766e73d5f11ed2177f1838de10c53ef3e74",
1089 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1089 "parents": ["10e46f2dcbf4823578cf180f33ecf0b957964c47"],
1090 "phase": "draft",
1090 "phase": "draft",
1091 "removed": [],
1091 "removed": [],
1092 "rev": 4,
1092 "rev": 4,
1093 "tags": [],
1093 "tags": [],
1094 "user": "person"
1094 "user": "person"
1095 },
1095 },
1096 {
1096 {
1097 "added": [],
1097 "added": [],
1098 "bookmarks": [],
1098 "bookmarks": [],
1099 "branch": "default",
1099 "branch": "default",
1100 "date": [1300000, 0],
1100 "date": [1300000, 0],
1101 "desc": "no user, no domain",
1101 "desc": "no user, no domain",
1102 "extra": {"branch": "default"},
1102 "extra": {"branch": "default"},
1103 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1103 "manifest": "cb5a1327723bada42f117e4c55a303246eaf9ccc",
1104 "modified": ["c"],
1104 "modified": ["c"],
1105 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1105 "node": "10e46f2dcbf4823578cf180f33ecf0b957964c47",
1106 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1106 "parents": ["97054abb4ab824450e9164180baf491ae0078465"],
1107 "phase": "draft",
1107 "phase": "draft",
1108 "removed": [],
1108 "removed": [],
1109 "rev": 3,
1109 "rev": 3,
1110 "tags": [],
1110 "tags": [],
1111 "user": "person"
1111 "user": "person"
1112 },
1112 },
1113 {
1113 {
1114 "added": ["c"],
1114 "added": ["c"],
1115 "bookmarks": [],
1115 "bookmarks": [],
1116 "branch": "default",
1116 "branch": "default",
1117 "date": [1200000, 0],
1117 "date": [1200000, 0],
1118 "desc": "no person",
1118 "desc": "no person",
1119 "extra": {"branch": "default"},
1119 "extra": {"branch": "default"},
1120 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1120 "manifest": "6e0e82995c35d0d57a52aca8da4e56139e06b4b1",
1121 "modified": [],
1121 "modified": [],
1122 "node": "97054abb4ab824450e9164180baf491ae0078465",
1122 "node": "97054abb4ab824450e9164180baf491ae0078465",
1123 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1123 "parents": ["b608e9d1a3f0273ccf70fb85fd6866b3482bf965"],
1124 "phase": "draft",
1124 "phase": "draft",
1125 "removed": [],
1125 "removed": [],
1126 "rev": 2,
1126 "rev": 2,
1127 "tags": [],
1127 "tags": [],
1128 "user": "other@place"
1128 "user": "other@place"
1129 },
1129 },
1130 {
1130 {
1131 "added": ["b"],
1131 "added": ["b"],
1132 "bookmarks": [],
1132 "bookmarks": [],
1133 "branch": "default",
1133 "branch": "default",
1134 "date": [1100000, 0],
1134 "date": [1100000, 0],
1135 "desc": "other 1\nother 2\n\nother 3",
1135 "desc": "other 1\nother 2\n\nother 3",
1136 "extra": {"branch": "default"},
1136 "extra": {"branch": "default"},
1137 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1137 "manifest": "4e8d705b1e53e3f9375e0e60dc7b525d8211fe55",
1138 "modified": [],
1138 "modified": [],
1139 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1139 "node": "b608e9d1a3f0273ccf70fb85fd6866b3482bf965",
1140 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1140 "parents": ["1e4e1b8f71e05681d422154f5421e385fec3454f"],
1141 "phase": "draft",
1141 "phase": "draft",
1142 "removed": [],
1142 "removed": [],
1143 "rev": 1,
1143 "rev": 1,
1144 "tags": [],
1144 "tags": [],
1145 "user": "A. N. Other <other@place>"
1145 "user": "A. N. Other <other@place>"
1146 },
1146 },
1147 {
1147 {
1148 "added": ["a"],
1148 "added": ["a"],
1149 "bookmarks": [],
1149 "bookmarks": [],
1150 "branch": "default",
1150 "branch": "default",
1151 "date": [1000000, 0],
1151 "date": [1000000, 0],
1152 "desc": "line 1\nline 2",
1152 "desc": "line 1\nline 2",
1153 "extra": {"branch": "default"},
1153 "extra": {"branch": "default"},
1154 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1154 "manifest": "a0c8bcbbb45c63b90b70ad007bf38961f64f2af0",
1155 "modified": [],
1155 "modified": [],
1156 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1156 "node": "1e4e1b8f71e05681d422154f5421e385fec3454f",
1157 "parents": ["0000000000000000000000000000000000000000"],
1157 "parents": ["0000000000000000000000000000000000000000"],
1158 "phase": "draft",
1158 "phase": "draft",
1159 "removed": [],
1159 "removed": [],
1160 "rev": 0,
1160 "rev": 0,
1161 "tags": [],
1161 "tags": [],
1162 "user": "User Name <user@hostname>"
1162 "user": "User Name <user@hostname>"
1163 }
1163 }
1164 ]
1164 ]
1165
1165
1166 $ hg log -l2 -T'json(rev, parents)'
1166 $ hg log -l2 -T'json(rev, parents)'
1167 [
1167 [
1168 {"parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"], "rev": 8},
1168 {"parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"], "rev": 8},
1169 {"parents": ["0000000000000000000000000000000000000000"], "rev": 7}
1169 {"parents": ["0000000000000000000000000000000000000000"], "rev": 7}
1170 ]
1170 ]
1171
1171
1172 $ hg log -qr. -T'json(rev, parents)'
1172 $ hg log -qr. -T'json(rev, parents)'
1173 [
1173 [
1174 {"parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"], "rev": 8}
1174 {"parents": ["29114dbae42b9f078cf2714dbe3a86bba8ec7453"], "rev": 8}
1175 ]
1175 ]
1176
1176
1177 $ hg log -r. -T'json(diff)'
1177 $ hg log -r. -T'json(diff)'
1178 [
1178 [
1179 {"diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"}
1179 {"diff": "diff -r 29114dbae42b -r 95c24699272e fourth\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/fourth\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+second\ndiff -r 29114dbae42b -r 95c24699272e second\n--- a/second\tMon Jan 12 13:46:40 1970 +0000\n+++ /dev/null\tThu Jan 01 00:00:00 1970 +0000\n@@ -1,1 +0,0 @@\n-second\ndiff -r 29114dbae42b -r 95c24699272e third\n--- /dev/null\tThu Jan 01 00:00:00 1970 +0000\n+++ b/third\tWed Jan 01 10:01:00 2020 +0000\n@@ -0,0 +1,1 @@\n+third\n"}
1180 ]
1180 ]
1181
1181
1182 $ hg log -r. -T'json(diffstat)'
1182 $ hg log -r. -T'json(diffstat)'
1183 [
1183 [
1184 {"diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n"}
1184 {"diffstat": " fourth | 1 +\n second | 1 -\n third | 1 +\n 3 files changed, 2 insertions(+), 1 deletions(-)\n"}
1185 ]
1185 ]
1186
1186
1187 $ hg log -r. -T'json(manifest)'
1187 $ hg log -r. -T'json(manifest)'
1188 [
1188 [
1189 {"manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64"}
1189 {"manifest": "94961b75a2da554b4df6fb599e5bfc7d48de0c64"}
1190 ]
1190 ]
1191
1191
1192 $ hg log -r. -T'json(extra)'
1192 $ hg log -r. -T'json(extra)'
1193 [
1193 [
1194 {"extra": {"branch": "default"}}
1194 {"extra": {"branch": "default"}}
1195 ]
1195 ]
1196
1196
1197 $ hg log -r3 -T'json(modified)'
1197 $ hg log -r3 -T'json(modified)'
1198 [
1198 [
1199 {"modified": ["c"]}
1199 {"modified": ["c"]}
1200 ]
1200 ]
1201
1201
1202 $ hg log -r. -T'json(added)'
1202 $ hg log -r. -T'json(added)'
1203 [
1203 [
1204 {"added": ["fourth", "third"]}
1204 {"added": ["fourth", "third"]}
1205 ]
1205 ]
1206
1206
1207 $ hg log -r. -T'json(removed)'
1207 $ hg log -r. -T'json(removed)'
1208 [
1208 [
1209 {"removed": ["second"]}
1209 {"removed": ["second"]}
1210 ]
1210 ]
1211
1211
1212 $ hg log -r. -T'json(files)'
1212 $ hg log -r. -T'json(files)'
1213 [
1213 [
1214 {"files": ["fourth", "second", "third"]}
1214 {"files": ["fourth", "second", "third"]}
1215 ]
1215 ]
1216
1216
1217 --copies is the exception. copies dict is built only when --copies switch
1217 --copies is the exception. copies dict is built only when --copies switch
1218 is on:
1218 is on:
1219
1219
1220 $ hg log -r'.^:' -T'json(copies)' --copies
1220 $ hg log -r'.^:' -T'json(copies)' --copies
1221 [
1221 [
1222 {"copies": {}},
1222 {"copies": {}},
1223 {"copies": {"fourth": "second"}}
1223 {"copies": {"fourth": "second"}}
1224 ]
1224 ]
1225
1225
1226 $ hg log -r. -T'json()'
1226 $ hg log -r. -T'json()'
1227 [
1227 [
1228 {}
1228 {}
1229 ]
1229 ]
1230
1230
1231 Other unsupported formatter styles:
1231 Other unsupported formatter styles:
1232
1232
1233 $ hg log -qr . -Tpickle
1233 $ hg log -qr . -Tpickle
1234 abort: "pickle" not in template map
1234 abort: "pickle" not in template map
1235 [255]
1235 [255]
1236 $ hg log -qr . -Tdebug
1236 $ hg log -qr . -Tdebug
1237 abort: "debug" not in template map
1237 abort: "debug" not in template map
1238 [255]
1238 [255]
1239
1239
1240 Unparsable function-style references:
1240 Unparsable function-style references:
1241
1241
1242 $ hg log -qr . -T'json(-)'
1242 $ hg log -qr . -T'json(-)'
1243 hg: parse error at 6: not a prefix: )
1243 hg: parse error at 6: not a prefix: )
1244 (json(-)
1244 (json(-)
1245 ^ here)
1245 ^ here)
1246 [10]
1246 [10]
1247
1247
1248 For backward compatibility, the following examples are not parsed as
1248 For backward compatibility, the following examples are not parsed as
1249 function-style references:
1249 function-style references:
1250
1250
1251 $ hg log -qr . -T'cbor(rev'
1251 $ hg log -qr . -T'cbor(rev'
1252 cbor(rev (no-eol)
1252 cbor(rev (no-eol)
1253 $ hg log -qr . -T'json (rev)'
1253 $ hg log -qr . -T'json (rev)'
1254 json (rev) (no-eol)
1254 json (rev) (no-eol)
1255 $ hg log -qr . -T'json(x="{rev}")'
1255 $ hg log -qr . -T'json(x="{rev}")'
1256 json(x="8") (no-eol)
1256 json(x="8") (no-eol)
1257
1257
1258 Error if style not readable:
1258 Error if style not readable:
1259
1259
1260 #if unix-permissions no-root
1260 #if unix-permissions no-root
1261 $ touch q
1261 $ touch q
1262 $ chmod 0 q
1262 $ chmod 0 q
1263 $ hg log --style ./q
1263 $ hg log --style ./q
1264 abort: Permission denied: './q'
1264 abort: Permission denied: './q'
1265 [255]
1265 [255]
1266 #endif
1266 #endif
1267
1267
1268 Error if no style:
1268 Error if no style:
1269
1269
1270 $ hg log --style notexist
1270 $ hg log --style notexist
1271 abort: style 'notexist' not found
1271 abort: style 'notexist' not found
1272 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1272 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1273 [255]
1273 [255]
1274
1274
1275 $ hg log -T list
1275 $ hg log -T list
1276 available styles: bisect, changelog, compact, default, phases, show, status, xml
1276 available styles: bisect, changelog, compact, default, phases, show, status, xml
1277 abort: specify a template
1277 abort: specify a template
1278 [255]
1278 [255]
1279
1279
1280 Error if style is a directory:
1280 Error if style is a directory:
1281
1281
1282 $ hg log --style somedir
1282 $ hg log --style somedir
1283 abort: Is a directory: 'somedir' (no-windows !)
1283 abort: Is a directory: 'somedir' (no-windows !)
1284 abort: somedir: Access is denied (windows !)
1284 abort: somedir: Access is denied (windows !)
1285 [255]
1285 [255]
1286
1286
1287 Error if style is a directory whose name is a built-in style:
1287 Error if style is a directory whose name is a built-in style:
1288
1288
1289 $ hg log --style coal
1289 $ hg log --style coal
1290 abort: style 'coal' not found
1290 abort: style 'coal' not found
1291 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1291 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
1292 [255]
1292 [255]
1293
1293
1294 Error if style missing key:
1294 Error if style missing key:
1295
1295
1296 $ echo 'q = q' > t
1296 $ echo 'q = q' > t
1297 $ hg log --style ./t
1297 $ hg log --style ./t
1298 abort: "changeset" not in template map
1298 abort: "changeset" not in template map
1299 [255]
1299 [255]
1300
1300
1301 Error if style missing value:
1301 Error if style missing value:
1302
1302
1303 $ echo 'changeset =' > t
1303 $ echo 'changeset =' > t
1304 $ hg log --style t
1304 $ hg log --style t
1305 hg: parse error at t:1: missing value
1305 hg: parse error at t:1: missing value
1306 [10]
1306 [10]
1307
1307
1308 Error if include fails:
1308 Error if include fails:
1309
1309
1310 $ echo 'changeset = q' >> t
1310 $ echo 'changeset = q' >> t
1311 #if unix-permissions no-root
1311 #if unix-permissions no-root
1312 $ hg log --style ./t
1312 $ hg log --style ./t
1313 abort: template file ./q: Permission denied
1313 abort: template file ./q: Permission denied
1314 [255]
1314 [255]
1315 $ rm -f q
1315 $ rm -f q
1316 #endif
1316 #endif
1317
1317
1318 Include works:
1318 Include works:
1319
1319
1320 $ echo '{rev}' > q
1320 $ echo '{rev}' > q
1321 $ hg log --style ./t
1321 $ hg log --style ./t
1322 8
1322 8
1323 7
1323 7
1324 6
1324 6
1325 5
1325 5
1326 4
1326 4
1327 3
1327 3
1328 2
1328 2
1329 1
1329 1
1330 0
1330 0
1331
1331
1332 $ hg phase -r 5 --public
1332 $ hg phase -r 5 --public
1333 $ hg phase -r 7 --secret --force
1333 $ hg phase -r 7 --secret --force
1334
1334
1335 Missing non-standard names give no error (backward compatibility):
1335 Missing non-standard names give no error (backward compatibility):
1336
1336
1337 $ echo "changeset = '{c}'" > t
1337 $ echo "changeset = '{c}'" > t
1338 $ hg log --style ./t
1338 $ hg log --style ./t
1339
1339
1340 Defining non-standard name works:
1340 Defining non-standard name works:
1341
1341
1342 $ cat <<EOF > t
1342 $ cat <<EOF > t
1343 > changeset = '{c}'
1343 > changeset = '{c}'
1344 > c = q
1344 > c = q
1345 > EOF
1345 > EOF
1346 $ hg log --style ./t
1346 $ hg log --style ./t
1347 8
1347 8
1348 7
1348 7
1349 6
1349 6
1350 5
1350 5
1351 4
1351 4
1352 3
1352 3
1353 2
1353 2
1354 1
1354 1
1355 0
1355 0
1356
1356
1357 ui.style works:
1357 ui.style works:
1358
1358
1359 $ echo '[ui]' > .hg/hgrc
1359 $ echo '[ui]' > .hg/hgrc
1360 $ echo 'style = t' >> .hg/hgrc
1360 $ echo 'style = t' >> .hg/hgrc
1361 $ hg log
1361 $ hg log
1362 8
1362 8
1363 7
1363 7
1364 6
1364 6
1365 5
1365 5
1366 4
1366 4
1367 3
1367 3
1368 2
1368 2
1369 1
1369 1
1370 0
1370 0
1371
1371
1372 Issue338:
1372 Issue338:
1373
1373
1374 $ hg log --style=changelog > changelog
1374 $ hg log --style=changelog > changelog
1375
1375
1376 $ cat changelog
1376 $ cat changelog
1377 2020-01-01 test <test>
1377 2020-01-01 test <test>
1378
1378
1379 * fourth, second, third:
1379 * fourth, second, third:
1380 third
1380 third
1381 [95c24699272e] [tip]
1381 [95c24699272e] [tip]
1382
1382
1383 1970-01-12 User Name <user@hostname>
1383 1970-01-12 User Name <user@hostname>
1384
1384
1385 * second:
1385 * second:
1386 second
1386 second
1387 [29114dbae42b]
1387 [29114dbae42b]
1388
1388
1389 1970-01-18 person <person>
1389 1970-01-18 person <person>
1390
1390
1391 * merge
1391 * merge
1392 [d41e714fe50d]
1392 [d41e714fe50d]
1393
1393
1394 * d:
1394 * d:
1395 new head
1395 new head
1396 [13207e5a10d9]
1396 [13207e5a10d9]
1397
1397
1398 1970-01-17 person <person>
1398 1970-01-17 person <person>
1399
1399
1400 * new branch
1400 * new branch
1401 [bbe44766e73d] <foo>
1401 [bbe44766e73d] <foo>
1402
1402
1403 1970-01-16 person <person>
1403 1970-01-16 person <person>
1404
1404
1405 * c:
1405 * c:
1406 no user, no domain
1406 no user, no domain
1407 [10e46f2dcbf4]
1407 [10e46f2dcbf4]
1408
1408
1409 1970-01-14 other <other@place>
1409 1970-01-14 other <other@place>
1410
1410
1411 * c:
1411 * c:
1412 no person
1412 no person
1413 [97054abb4ab8]
1413 [97054abb4ab8]
1414
1414
1415 1970-01-13 A. N. Other <other@place>
1415 1970-01-13 A. N. Other <other@place>
1416
1416
1417 * b:
1417 * b:
1418 other 1 other 2
1418 other 1 other 2
1419
1419
1420 other 3
1420 other 3
1421 [b608e9d1a3f0]
1421 [b608e9d1a3f0]
1422
1422
1423 1970-01-12 User Name <user@hostname>
1423 1970-01-12 User Name <user@hostname>
1424
1424
1425 * a:
1425 * a:
1426 line 1 line 2
1426 line 1 line 2
1427 [1e4e1b8f71e0]
1427 [1e4e1b8f71e0]
1428
1428
1429
1429
1430 Issue2130: xml output for 'hg heads' is malformed
1430 Issue2130: xml output for 'hg heads' is malformed
1431
1431
1432 $ hg heads --style changelog
1432 $ hg heads --style changelog
1433 2020-01-01 test <test>
1433 2020-01-01 test <test>
1434
1434
1435 * fourth, second, third:
1435 * fourth, second, third:
1436 third
1436 third
1437 [95c24699272e] [tip]
1437 [95c24699272e] [tip]
1438
1438
1439 1970-01-18 person <person>
1439 1970-01-18 person <person>
1440
1440
1441 * merge
1441 * merge
1442 [d41e714fe50d]
1442 [d41e714fe50d]
1443
1443
1444 1970-01-17 person <person>
1444 1970-01-17 person <person>
1445
1445
1446 * new branch
1446 * new branch
1447 [bbe44766e73d] <foo>
1447 [bbe44766e73d] <foo>
1448
1448
1449
1449
1450 Add a dummy commit to make up for the instability of the above:
1450 Add a dummy commit to make up for the instability of the above:
1451
1451
1452 $ echo a > a
1452 $ echo a > a
1453 $ hg add a
1453 $ hg add a
1454 $ hg ci -m future
1454 $ hg ci -m future
1455
1455
1456 Add a commit that does all possible modifications at once
1456 Add a commit that does all possible modifications at once
1457
1457
1458 $ echo modify >> third
1458 $ echo modify >> third
1459 $ touch b
1459 $ touch b
1460 $ hg add b
1460 $ hg add b
1461 $ hg mv fourth fifth
1461 $ hg mv fourth fifth
1462 $ hg rm a
1462 $ hg rm a
1463 $ hg ci -m "Modify, add, remove, rename"
1463 $ hg ci -m "Modify, add, remove, rename"
1464
1464
1465 Check the status template
1465 Check the status template
1466
1466
1467 $ cat <<EOF >> $HGRCPATH
1467 $ cat <<EOF >> $HGRCPATH
1468 > [extensions]
1468 > [extensions]
1469 > color=
1469 > color=
1470 > EOF
1470 > EOF
1471
1471
1472 $ hg log -T status -r 10
1472 $ hg log -T status -r 10
1473 changeset: 10:0f9759ec227a
1473 changeset: 10:0f9759ec227a
1474 tag: tip
1474 tag: tip
1475 user: test
1475 user: test
1476 date: Thu Jan 01 00:00:00 1970 +0000
1476 date: Thu Jan 01 00:00:00 1970 +0000
1477 summary: Modify, add, remove, rename
1477 summary: Modify, add, remove, rename
1478 files:
1478 files:
1479 M third
1479 M third
1480 A b
1480 A b
1481 A fifth
1481 A fifth
1482 R a
1482 R a
1483 R fourth
1483 R fourth
1484
1484
1485 $ hg log -T status -C -r 10
1485 $ hg log -T status -C -r 10
1486 changeset: 10:0f9759ec227a
1486 changeset: 10:0f9759ec227a
1487 tag: tip
1487 tag: tip
1488 user: test
1488 user: test
1489 date: Thu Jan 01 00:00:00 1970 +0000
1489 date: Thu Jan 01 00:00:00 1970 +0000
1490 summary: Modify, add, remove, rename
1490 summary: Modify, add, remove, rename
1491 files:
1491 files:
1492 M third
1492 M third
1493 A b
1493 A b
1494 A fifth
1494 A fifth
1495 fourth
1495 fourth
1496 R a
1496 R a
1497 R fourth
1497 R fourth
1498
1498
1499 $ hg log -T status -C -r 10 -v
1499 $ hg log -T status -C -r 10 -v
1500 changeset: 10:0f9759ec227a
1500 changeset: 10:0f9759ec227a
1501 tag: tip
1501 tag: tip
1502 user: test
1502 user: test
1503 date: Thu Jan 01 00:00:00 1970 +0000
1503 date: Thu Jan 01 00:00:00 1970 +0000
1504 description:
1504 description:
1505 Modify, add, remove, rename
1505 Modify, add, remove, rename
1506
1506
1507 files:
1507 files:
1508 M third
1508 M third
1509 A b
1509 A b
1510 A fifth
1510 A fifth
1511 fourth
1511 fourth
1512 R a
1512 R a
1513 R fourth
1513 R fourth
1514
1514
1515 $ hg log -T status -C -r 10 --debug
1515 $ hg log -T status -C -r 10 --debug
1516 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
1516 changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c
1517 tag: tip
1517 tag: tip
1518 phase: secret
1518 phase: secret
1519 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
1519 parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066
1520 parent: -1:0000000000000000000000000000000000000000
1520 parent: -1:0000000000000000000000000000000000000000
1521 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
1521 manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567
1522 user: test
1522 user: test
1523 date: Thu Jan 01 00:00:00 1970 +0000
1523 date: Thu Jan 01 00:00:00 1970 +0000
1524 extra: branch=default
1524 extra: branch=default
1525 description:
1525 description:
1526 Modify, add, remove, rename
1526 Modify, add, remove, rename
1527
1527
1528 files:
1528 files:
1529 M third
1529 M third
1530 A b
1530 A b
1531 A fifth
1531 A fifth
1532 fourth
1532 fourth
1533 R a
1533 R a
1534 R fourth
1534 R fourth
1535
1535
1536 $ hg log -T status -C -r 10 --quiet
1536 $ hg log -T status -C -r 10 --quiet
1537 10:0f9759ec227a
1537 10:0f9759ec227a
1538 $ hg --color=debug log -T status -r 10
1538 $ hg --color=debug log -T status -r 10
1539 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1539 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1540 [log.tag|tag: tip]
1540 [log.tag|tag: tip]
1541 [log.user|user: test]
1541 [log.user|user: test]
1542 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1542 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1543 [log.summary|summary: Modify, add, remove, rename]
1543 [log.summary|summary: Modify, add, remove, rename]
1544 [ui.note log.files|files:]
1544 [ui.note log.files|files:]
1545 [status.modified|M third]
1545 [status.modified|M third]
1546 [status.added|A b]
1546 [status.added|A b]
1547 [status.added|A fifth]
1547 [status.added|A fifth]
1548 [status.removed|R a]
1548 [status.removed|R a]
1549 [status.removed|R fourth]
1549 [status.removed|R fourth]
1550
1550
1551 $ hg --color=debug log -T status -C -r 10
1551 $ hg --color=debug log -T status -C -r 10
1552 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1552 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1553 [log.tag|tag: tip]
1553 [log.tag|tag: tip]
1554 [log.user|user: test]
1554 [log.user|user: test]
1555 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1555 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1556 [log.summary|summary: Modify, add, remove, rename]
1556 [log.summary|summary: Modify, add, remove, rename]
1557 [ui.note log.files|files:]
1557 [ui.note log.files|files:]
1558 [status.modified|M third]
1558 [status.modified|M third]
1559 [status.added|A b]
1559 [status.added|A b]
1560 [status.added|A fifth]
1560 [status.added|A fifth]
1561 [status.copied| fourth]
1561 [status.copied| fourth]
1562 [status.removed|R a]
1562 [status.removed|R a]
1563 [status.removed|R fourth]
1563 [status.removed|R fourth]
1564
1564
1565 $ hg --color=debug log -T status -C -r 10 -v
1565 $ hg --color=debug log -T status -C -r 10 -v
1566 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1566 [log.changeset changeset.secret|changeset: 10:0f9759ec227a]
1567 [log.tag|tag: tip]
1567 [log.tag|tag: tip]
1568 [log.user|user: test]
1568 [log.user|user: test]
1569 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1569 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1570 [ui.note log.description|description:]
1570 [ui.note log.description|description:]
1571 [ui.note log.description|Modify, add, remove, rename]
1571 [ui.note log.description|Modify, add, remove, rename]
1572
1572
1573 [ui.note log.files|files:]
1573 [ui.note log.files|files:]
1574 [status.modified|M third]
1574 [status.modified|M third]
1575 [status.added|A b]
1575 [status.added|A b]
1576 [status.added|A fifth]
1576 [status.added|A fifth]
1577 [status.copied| fourth]
1577 [status.copied| fourth]
1578 [status.removed|R a]
1578 [status.removed|R a]
1579 [status.removed|R fourth]
1579 [status.removed|R fourth]
1580
1580
1581 $ hg --color=debug log -T status -C -r 10 --debug
1581 $ hg --color=debug log -T status -C -r 10 --debug
1582 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
1582 [log.changeset changeset.secret|changeset: 10:0f9759ec227a4859c2014a345cd8a859022b7c6c]
1583 [log.tag|tag: tip]
1583 [log.tag|tag: tip]
1584 [log.phase|phase: secret]
1584 [log.phase|phase: secret]
1585 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
1585 [log.parent changeset.secret|parent: 9:bf9dfba36635106d6a73ccc01e28b762da60e066]
1586 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1586 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1587 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
1587 [ui.debug log.manifest|manifest: 8:89dd546f2de0a9d6d664f58d86097eb97baba567]
1588 [log.user|user: test]
1588 [log.user|user: test]
1589 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1589 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
1590 [ui.debug log.extra|extra: branch=default]
1590 [ui.debug log.extra|extra: branch=default]
1591 [ui.note log.description|description:]
1591 [ui.note log.description|description:]
1592 [ui.note log.description|Modify, add, remove, rename]
1592 [ui.note log.description|Modify, add, remove, rename]
1593
1593
1594 [ui.note log.files|files:]
1594 [ui.note log.files|files:]
1595 [status.modified|M third]
1595 [status.modified|M third]
1596 [status.added|A b]
1596 [status.added|A b]
1597 [status.added|A fifth]
1597 [status.added|A fifth]
1598 [status.copied| fourth]
1598 [status.copied| fourth]
1599 [status.removed|R a]
1599 [status.removed|R a]
1600 [status.removed|R fourth]
1600 [status.removed|R fourth]
1601
1601
1602 $ hg --color=debug log -T status -C -r 10 --quiet
1602 $ hg --color=debug log -T status -C -r 10 --quiet
1603 [log.node|10:0f9759ec227a]
1603 [log.node|10:0f9759ec227a]
1604
1604
1605 Check the bisect template
1605 Check the bisect template
1606
1606
1607 $ hg bisect -g 1
1607 $ hg bisect -g 1
1608 $ hg bisect -b 3 --noupdate
1608 $ hg bisect -b 3 --noupdate
1609 Testing changeset 2:97054abb4ab8 (2 changesets remaining, ~1 tests)
1609 Testing changeset 2:97054abb4ab8 "no person" (2 changesets remaining, ~1 tests)
1610 $ hg log -T bisect -r 0:4
1610 $ hg log -T bisect -r 0:4
1611 changeset: 0:1e4e1b8f71e0
1611 changeset: 0:1e4e1b8f71e0
1612 bisect: good (implicit)
1612 bisect: good (implicit)
1613 user: User Name <user@hostname>
1613 user: User Name <user@hostname>
1614 date: Mon Jan 12 13:46:40 1970 +0000
1614 date: Mon Jan 12 13:46:40 1970 +0000
1615 summary: line 1
1615 summary: line 1
1616
1616
1617 changeset: 1:b608e9d1a3f0
1617 changeset: 1:b608e9d1a3f0
1618 bisect: good
1618 bisect: good
1619 user: A. N. Other <other@place>
1619 user: A. N. Other <other@place>
1620 date: Tue Jan 13 17:33:20 1970 +0000
1620 date: Tue Jan 13 17:33:20 1970 +0000
1621 summary: other 1
1621 summary: other 1
1622
1622
1623 changeset: 2:97054abb4ab8
1623 changeset: 2:97054abb4ab8
1624 bisect: untested
1624 bisect: untested
1625 user: other@place
1625 user: other@place
1626 date: Wed Jan 14 21:20:00 1970 +0000
1626 date: Wed Jan 14 21:20:00 1970 +0000
1627 summary: no person
1627 summary: no person
1628
1628
1629 changeset: 3:10e46f2dcbf4
1629 changeset: 3:10e46f2dcbf4
1630 bisect: bad
1630 bisect: bad
1631 user: person
1631 user: person
1632 date: Fri Jan 16 01:06:40 1970 +0000
1632 date: Fri Jan 16 01:06:40 1970 +0000
1633 summary: no user, no domain
1633 summary: no user, no domain
1634
1634
1635 changeset: 4:bbe44766e73d
1635 changeset: 4:bbe44766e73d
1636 bisect: bad (implicit)
1636 bisect: bad (implicit)
1637 branch: foo
1637 branch: foo
1638 user: person
1638 user: person
1639 date: Sat Jan 17 04:53:20 1970 +0000
1639 date: Sat Jan 17 04:53:20 1970 +0000
1640 summary: new branch
1640 summary: new branch
1641
1641
1642 $ hg log --debug -T bisect -r 0:4
1642 $ hg log --debug -T bisect -r 0:4
1643 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
1643 changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
1644 bisect: good (implicit)
1644 bisect: good (implicit)
1645 phase: public
1645 phase: public
1646 parent: -1:0000000000000000000000000000000000000000
1646 parent: -1:0000000000000000000000000000000000000000
1647 parent: -1:0000000000000000000000000000000000000000
1647 parent: -1:0000000000000000000000000000000000000000
1648 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1648 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
1649 user: User Name <user@hostname>
1649 user: User Name <user@hostname>
1650 date: Mon Jan 12 13:46:40 1970 +0000
1650 date: Mon Jan 12 13:46:40 1970 +0000
1651 files+: a
1651 files+: a
1652 extra: branch=default
1652 extra: branch=default
1653 description:
1653 description:
1654 line 1
1654 line 1
1655 line 2
1655 line 2
1656
1656
1657
1657
1658 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1658 changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1659 bisect: good
1659 bisect: good
1660 phase: public
1660 phase: public
1661 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
1661 parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f
1662 parent: -1:0000000000000000000000000000000000000000
1662 parent: -1:0000000000000000000000000000000000000000
1663 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1663 manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55
1664 user: A. N. Other <other@place>
1664 user: A. N. Other <other@place>
1665 date: Tue Jan 13 17:33:20 1970 +0000
1665 date: Tue Jan 13 17:33:20 1970 +0000
1666 files+: b
1666 files+: b
1667 extra: branch=default
1667 extra: branch=default
1668 description:
1668 description:
1669 other 1
1669 other 1
1670 other 2
1670 other 2
1671
1671
1672 other 3
1672 other 3
1673
1673
1674
1674
1675 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
1675 changeset: 2:97054abb4ab824450e9164180baf491ae0078465
1676 bisect: untested
1676 bisect: untested
1677 phase: public
1677 phase: public
1678 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1678 parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965
1679 parent: -1:0000000000000000000000000000000000000000
1679 parent: -1:0000000000000000000000000000000000000000
1680 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1680 manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1
1681 user: other@place
1681 user: other@place
1682 date: Wed Jan 14 21:20:00 1970 +0000
1682 date: Wed Jan 14 21:20:00 1970 +0000
1683 files+: c
1683 files+: c
1684 extra: branch=default
1684 extra: branch=default
1685 description:
1685 description:
1686 no person
1686 no person
1687
1687
1688
1688
1689 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
1689 changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
1690 bisect: bad
1690 bisect: bad
1691 phase: public
1691 phase: public
1692 parent: 2:97054abb4ab824450e9164180baf491ae0078465
1692 parent: 2:97054abb4ab824450e9164180baf491ae0078465
1693 parent: -1:0000000000000000000000000000000000000000
1693 parent: -1:0000000000000000000000000000000000000000
1694 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1694 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1695 user: person
1695 user: person
1696 date: Fri Jan 16 01:06:40 1970 +0000
1696 date: Fri Jan 16 01:06:40 1970 +0000
1697 files: c
1697 files: c
1698 extra: branch=default
1698 extra: branch=default
1699 description:
1699 description:
1700 no user, no domain
1700 no user, no domain
1701
1701
1702
1702
1703 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1703 changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74
1704 bisect: bad (implicit)
1704 bisect: bad (implicit)
1705 branch: foo
1705 branch: foo
1706 phase: draft
1706 phase: draft
1707 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
1707 parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47
1708 parent: -1:0000000000000000000000000000000000000000
1708 parent: -1:0000000000000000000000000000000000000000
1709 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1709 manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc
1710 user: person
1710 user: person
1711 date: Sat Jan 17 04:53:20 1970 +0000
1711 date: Sat Jan 17 04:53:20 1970 +0000
1712 extra: branch=foo
1712 extra: branch=foo
1713 description:
1713 description:
1714 new branch
1714 new branch
1715
1715
1716
1716
1717 $ hg log -v -T bisect -r 0:4
1717 $ hg log -v -T bisect -r 0:4
1718 changeset: 0:1e4e1b8f71e0
1718 changeset: 0:1e4e1b8f71e0
1719 bisect: good (implicit)
1719 bisect: good (implicit)
1720 user: User Name <user@hostname>
1720 user: User Name <user@hostname>
1721 date: Mon Jan 12 13:46:40 1970 +0000
1721 date: Mon Jan 12 13:46:40 1970 +0000
1722 files: a
1722 files: a
1723 description:
1723 description:
1724 line 1
1724 line 1
1725 line 2
1725 line 2
1726
1726
1727
1727
1728 changeset: 1:b608e9d1a3f0
1728 changeset: 1:b608e9d1a3f0
1729 bisect: good
1729 bisect: good
1730 user: A. N. Other <other@place>
1730 user: A. N. Other <other@place>
1731 date: Tue Jan 13 17:33:20 1970 +0000
1731 date: Tue Jan 13 17:33:20 1970 +0000
1732 files: b
1732 files: b
1733 description:
1733 description:
1734 other 1
1734 other 1
1735 other 2
1735 other 2
1736
1736
1737 other 3
1737 other 3
1738
1738
1739
1739
1740 changeset: 2:97054abb4ab8
1740 changeset: 2:97054abb4ab8
1741 bisect: untested
1741 bisect: untested
1742 user: other@place
1742 user: other@place
1743 date: Wed Jan 14 21:20:00 1970 +0000
1743 date: Wed Jan 14 21:20:00 1970 +0000
1744 files: c
1744 files: c
1745 description:
1745 description:
1746 no person
1746 no person
1747
1747
1748
1748
1749 changeset: 3:10e46f2dcbf4
1749 changeset: 3:10e46f2dcbf4
1750 bisect: bad
1750 bisect: bad
1751 user: person
1751 user: person
1752 date: Fri Jan 16 01:06:40 1970 +0000
1752 date: Fri Jan 16 01:06:40 1970 +0000
1753 files: c
1753 files: c
1754 description:
1754 description:
1755 no user, no domain
1755 no user, no domain
1756
1756
1757
1757
1758 changeset: 4:bbe44766e73d
1758 changeset: 4:bbe44766e73d
1759 bisect: bad (implicit)
1759 bisect: bad (implicit)
1760 branch: foo
1760 branch: foo
1761 user: person
1761 user: person
1762 date: Sat Jan 17 04:53:20 1970 +0000
1762 date: Sat Jan 17 04:53:20 1970 +0000
1763 description:
1763 description:
1764 new branch
1764 new branch
1765
1765
1766
1766
1767 $ hg --color=debug log -T bisect -r 0:4
1767 $ hg --color=debug log -T bisect -r 0:4
1768 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
1768 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
1769 [log.bisect bisect.good|bisect: good (implicit)]
1769 [log.bisect bisect.good|bisect: good (implicit)]
1770 [log.user|user: User Name <user@hostname>]
1770 [log.user|user: User Name <user@hostname>]
1771 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1771 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1772 [log.summary|summary: line 1]
1772 [log.summary|summary: line 1]
1773
1773
1774 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
1774 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
1775 [log.bisect bisect.good|bisect: good]
1775 [log.bisect bisect.good|bisect: good]
1776 [log.user|user: A. N. Other <other@place>]
1776 [log.user|user: A. N. Other <other@place>]
1777 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1777 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1778 [log.summary|summary: other 1]
1778 [log.summary|summary: other 1]
1779
1779
1780 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
1780 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
1781 [log.bisect bisect.untested|bisect: untested]
1781 [log.bisect bisect.untested|bisect: untested]
1782 [log.user|user: other@place]
1782 [log.user|user: other@place]
1783 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1783 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1784 [log.summary|summary: no person]
1784 [log.summary|summary: no person]
1785
1785
1786 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
1786 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
1787 [log.bisect bisect.bad|bisect: bad]
1787 [log.bisect bisect.bad|bisect: bad]
1788 [log.user|user: person]
1788 [log.user|user: person]
1789 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1789 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1790 [log.summary|summary: no user, no domain]
1790 [log.summary|summary: no user, no domain]
1791
1791
1792 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
1792 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
1793 [log.bisect bisect.bad|bisect: bad (implicit)]
1793 [log.bisect bisect.bad|bisect: bad (implicit)]
1794 [log.branch|branch: foo]
1794 [log.branch|branch: foo]
1795 [log.user|user: person]
1795 [log.user|user: person]
1796 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1796 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1797 [log.summary|summary: new branch]
1797 [log.summary|summary: new branch]
1798
1798
1799 $ hg --color=debug log --debug -T bisect -r 0:4
1799 $ hg --color=debug log --debug -T bisect -r 0:4
1800 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
1800 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
1801 [log.bisect bisect.good|bisect: good (implicit)]
1801 [log.bisect bisect.good|bisect: good (implicit)]
1802 [log.phase|phase: public]
1802 [log.phase|phase: public]
1803 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1803 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1804 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1804 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1805 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
1805 [ui.debug log.manifest|manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0]
1806 [log.user|user: User Name <user@hostname>]
1806 [log.user|user: User Name <user@hostname>]
1807 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1807 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1808 [ui.debug log.files|files+: a]
1808 [ui.debug log.files|files+: a]
1809 [ui.debug log.extra|extra: branch=default]
1809 [ui.debug log.extra|extra: branch=default]
1810 [ui.note log.description|description:]
1810 [ui.note log.description|description:]
1811 [ui.note log.description|line 1
1811 [ui.note log.description|line 1
1812 line 2]
1812 line 2]
1813
1813
1814
1814
1815 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
1815 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
1816 [log.bisect bisect.good|bisect: good]
1816 [log.bisect bisect.good|bisect: good]
1817 [log.phase|phase: public]
1817 [log.phase|phase: public]
1818 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
1818 [log.parent changeset.public|parent: 0:1e4e1b8f71e05681d422154f5421e385fec3454f]
1819 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1819 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1820 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
1820 [ui.debug log.manifest|manifest: 1:4e8d705b1e53e3f9375e0e60dc7b525d8211fe55]
1821 [log.user|user: A. N. Other <other@place>]
1821 [log.user|user: A. N. Other <other@place>]
1822 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1822 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1823 [ui.debug log.files|files+: b]
1823 [ui.debug log.files|files+: b]
1824 [ui.debug log.extra|extra: branch=default]
1824 [ui.debug log.extra|extra: branch=default]
1825 [ui.note log.description|description:]
1825 [ui.note log.description|description:]
1826 [ui.note log.description|other 1
1826 [ui.note log.description|other 1
1827 other 2
1827 other 2
1828
1828
1829 other 3]
1829 other 3]
1830
1830
1831
1831
1832 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
1832 [log.changeset changeset.public|changeset: 2:97054abb4ab824450e9164180baf491ae0078465]
1833 [log.bisect bisect.untested|bisect: untested]
1833 [log.bisect bisect.untested|bisect: untested]
1834 [log.phase|phase: public]
1834 [log.phase|phase: public]
1835 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
1835 [log.parent changeset.public|parent: 1:b608e9d1a3f0273ccf70fb85fd6866b3482bf965]
1836 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1836 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1837 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
1837 [ui.debug log.manifest|manifest: 2:6e0e82995c35d0d57a52aca8da4e56139e06b4b1]
1838 [log.user|user: other@place]
1838 [log.user|user: other@place]
1839 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1839 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1840 [ui.debug log.files|files+: c]
1840 [ui.debug log.files|files+: c]
1841 [ui.debug log.extra|extra: branch=default]
1841 [ui.debug log.extra|extra: branch=default]
1842 [ui.note log.description|description:]
1842 [ui.note log.description|description:]
1843 [ui.note log.description|no person]
1843 [ui.note log.description|no person]
1844
1844
1845
1845
1846 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
1846 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
1847 [log.bisect bisect.bad|bisect: bad]
1847 [log.bisect bisect.bad|bisect: bad]
1848 [log.phase|phase: public]
1848 [log.phase|phase: public]
1849 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
1849 [log.parent changeset.public|parent: 2:97054abb4ab824450e9164180baf491ae0078465]
1850 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1850 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1851 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
1851 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
1852 [log.user|user: person]
1852 [log.user|user: person]
1853 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1853 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1854 [ui.debug log.files|files: c]
1854 [ui.debug log.files|files: c]
1855 [ui.debug log.extra|extra: branch=default]
1855 [ui.debug log.extra|extra: branch=default]
1856 [ui.note log.description|description:]
1856 [ui.note log.description|description:]
1857 [ui.note log.description|no user, no domain]
1857 [ui.note log.description|no user, no domain]
1858
1858
1859
1859
1860 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
1860 [log.changeset changeset.draft|changeset: 4:bbe44766e73d5f11ed2177f1838de10c53ef3e74]
1861 [log.bisect bisect.bad|bisect: bad (implicit)]
1861 [log.bisect bisect.bad|bisect: bad (implicit)]
1862 [log.branch|branch: foo]
1862 [log.branch|branch: foo]
1863 [log.phase|phase: draft]
1863 [log.phase|phase: draft]
1864 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
1864 [log.parent changeset.public|parent: 3:10e46f2dcbf4823578cf180f33ecf0b957964c47]
1865 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1865 [log.parent changeset.public|parent: -1:0000000000000000000000000000000000000000]
1866 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
1866 [ui.debug log.manifest|manifest: 3:cb5a1327723bada42f117e4c55a303246eaf9ccc]
1867 [log.user|user: person]
1867 [log.user|user: person]
1868 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1868 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1869 [ui.debug log.extra|extra: branch=foo]
1869 [ui.debug log.extra|extra: branch=foo]
1870 [ui.note log.description|description:]
1870 [ui.note log.description|description:]
1871 [ui.note log.description|new branch]
1871 [ui.note log.description|new branch]
1872
1872
1873
1873
1874 $ hg --color=debug log -v -T bisect -r 0:4
1874 $ hg --color=debug log -v -T bisect -r 0:4
1875 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
1875 [log.changeset changeset.public|changeset: 0:1e4e1b8f71e0]
1876 [log.bisect bisect.good|bisect: good (implicit)]
1876 [log.bisect bisect.good|bisect: good (implicit)]
1877 [log.user|user: User Name <user@hostname>]
1877 [log.user|user: User Name <user@hostname>]
1878 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1878 [log.date|date: Mon Jan 12 13:46:40 1970 +0000]
1879 [ui.note log.files|files: a]
1879 [ui.note log.files|files: a]
1880 [ui.note log.description|description:]
1880 [ui.note log.description|description:]
1881 [ui.note log.description|line 1
1881 [ui.note log.description|line 1
1882 line 2]
1882 line 2]
1883
1883
1884
1884
1885 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
1885 [log.changeset changeset.public|changeset: 1:b608e9d1a3f0]
1886 [log.bisect bisect.good|bisect: good]
1886 [log.bisect bisect.good|bisect: good]
1887 [log.user|user: A. N. Other <other@place>]
1887 [log.user|user: A. N. Other <other@place>]
1888 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1888 [log.date|date: Tue Jan 13 17:33:20 1970 +0000]
1889 [ui.note log.files|files: b]
1889 [ui.note log.files|files: b]
1890 [ui.note log.description|description:]
1890 [ui.note log.description|description:]
1891 [ui.note log.description|other 1
1891 [ui.note log.description|other 1
1892 other 2
1892 other 2
1893
1893
1894 other 3]
1894 other 3]
1895
1895
1896
1896
1897 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
1897 [log.changeset changeset.public|changeset: 2:97054abb4ab8]
1898 [log.bisect bisect.untested|bisect: untested]
1898 [log.bisect bisect.untested|bisect: untested]
1899 [log.user|user: other@place]
1899 [log.user|user: other@place]
1900 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1900 [log.date|date: Wed Jan 14 21:20:00 1970 +0000]
1901 [ui.note log.files|files: c]
1901 [ui.note log.files|files: c]
1902 [ui.note log.description|description:]
1902 [ui.note log.description|description:]
1903 [ui.note log.description|no person]
1903 [ui.note log.description|no person]
1904
1904
1905
1905
1906 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
1906 [log.changeset changeset.public|changeset: 3:10e46f2dcbf4]
1907 [log.bisect bisect.bad|bisect: bad]
1907 [log.bisect bisect.bad|bisect: bad]
1908 [log.user|user: person]
1908 [log.user|user: person]
1909 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1909 [log.date|date: Fri Jan 16 01:06:40 1970 +0000]
1910 [ui.note log.files|files: c]
1910 [ui.note log.files|files: c]
1911 [ui.note log.description|description:]
1911 [ui.note log.description|description:]
1912 [ui.note log.description|no user, no domain]
1912 [ui.note log.description|no user, no domain]
1913
1913
1914
1914
1915 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
1915 [log.changeset changeset.draft|changeset: 4:bbe44766e73d]
1916 [log.bisect bisect.bad|bisect: bad (implicit)]
1916 [log.bisect bisect.bad|bisect: bad (implicit)]
1917 [log.branch|branch: foo]
1917 [log.branch|branch: foo]
1918 [log.user|user: person]
1918 [log.user|user: person]
1919 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1919 [log.date|date: Sat Jan 17 04:53:20 1970 +0000]
1920 [ui.note log.description|description:]
1920 [ui.note log.description|description:]
1921 [ui.note log.description|new branch]
1921 [ui.note log.description|new branch]
1922
1922
1923
1923
1924 $ hg bisect --reset
1924 $ hg bisect --reset
1925
1925
1926 $ cd ..
1926 $ cd ..
1927
1927
1928 Set up latesttag repository:
1928 Set up latesttag repository:
1929
1929
1930 $ hg init latesttag
1930 $ hg init latesttag
1931 $ cd latesttag
1931 $ cd latesttag
1932
1932
1933 $ echo a > file
1933 $ echo a > file
1934 $ hg ci -Am a -d '0 0'
1934 $ hg ci -Am a -d '0 0'
1935 adding file
1935 adding file
1936
1936
1937 $ echo b >> file
1937 $ echo b >> file
1938 $ hg ci -m b -d '1 0'
1938 $ hg ci -m b -d '1 0'
1939
1939
1940 $ echo c >> head1
1940 $ echo c >> head1
1941 $ hg ci -Am h1c -d '2 0'
1941 $ hg ci -Am h1c -d '2 0'
1942 adding head1
1942 adding head1
1943
1943
1944 $ hg update -q 1
1944 $ hg update -q 1
1945 $ echo d >> head2
1945 $ echo d >> head2
1946 $ hg ci -Am h2d -d '3 0'
1946 $ hg ci -Am h2d -d '3 0'
1947 adding head2
1947 adding head2
1948 created new head
1948 created new head
1949
1949
1950 $ echo e >> head2
1950 $ echo e >> head2
1951 $ hg ci -m h2e -d '4 0'
1951 $ hg ci -m h2e -d '4 0'
1952
1952
1953 $ hg merge -q
1953 $ hg merge -q
1954 $ hg ci -m merge -d '5 -3600'
1954 $ hg ci -m merge -d '5 -3600'
1955
1955
1956 $ hg tag -r 1 -m t1 -d '6 0' t1
1956 $ hg tag -r 1 -m t1 -d '6 0' t1
1957 $ hg tag -r 2 -m t2 -d '7 0' t2
1957 $ hg tag -r 2 -m t2 -d '7 0' t2
1958 $ hg tag -r 3 -m t3 -d '8 0' t3
1958 $ hg tag -r 3 -m t3 -d '8 0' t3
1959 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
1959 $ hg tag -r 4 -m t4 -d '4 0' t4 # older than t2, but should not matter
1960 $ hg tag -r 5 -m t5 -d '9 0' t5
1960 $ hg tag -r 5 -m t5 -d '9 0' t5
1961 $ hg tag -r 3 -m at3 -d '10 0' at3
1961 $ hg tag -r 3 -m at3 -d '10 0' at3
1962
1962
1963 $ cd ..
1963 $ cd ..
1964
1964
1965 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1965 Style path expansion: issue1948 - ui.style option doesn't work on OSX
1966 if it is a relative path
1966 if it is a relative path
1967
1967
1968 $ mkdir -p home/styles
1968 $ mkdir -p home/styles
1969
1969
1970 $ cat > home/styles/teststyle <<EOF
1970 $ cat > home/styles/teststyle <<EOF
1971 > changeset = 'test {rev}:{node|short}\n'
1971 > changeset = 'test {rev}:{node|short}\n'
1972 > EOF
1972 > EOF
1973
1973
1974 $ HOME=`pwd`/home; export HOME
1974 $ HOME=`pwd`/home; export HOME
1975 $ USERPROFILE=`pwd`/home; export USERPROFILE
1975 $ USERPROFILE=`pwd`/home; export USERPROFILE
1976
1976
1977 $ cat > latesttag/.hg/hgrc <<EOF
1977 $ cat > latesttag/.hg/hgrc <<EOF
1978 > [ui]
1978 > [ui]
1979 > style = ~/styles/teststyle
1979 > style = ~/styles/teststyle
1980 > EOF
1980 > EOF
1981
1981
1982 $ hg -R latesttag tip
1982 $ hg -R latesttag tip
1983 test 11:97e5943b523a
1983 test 11:97e5943b523a
1984
1984
1985 Test recursive showlist template (issue1989):
1985 Test recursive showlist template (issue1989):
1986
1986
1987 $ cat > style1989 <<EOF
1987 $ cat > style1989 <<EOF
1988 > changeset = '{file_mods}{manifest}{extras}'
1988 > changeset = '{file_mods}{manifest}{extras}'
1989 > file_mod = 'M|{author|person}\n'
1989 > file_mod = 'M|{author|person}\n'
1990 > manifest = '{rev},{author}\n'
1990 > manifest = '{rev},{author}\n'
1991 > extra = '{key}: {author}\n'
1991 > extra = '{key}: {author}\n'
1992 > EOF
1992 > EOF
1993
1993
1994 $ hg -R latesttag log -r tip --style=style1989
1994 $ hg -R latesttag log -r tip --style=style1989
1995 M|test
1995 M|test
1996 11,
1996 11,
1997 branch: test
1997 branch: test
General Comments 0
You need to be logged in to leave comments. Login now