##// END OF EJS Templates
graft: exit 1 on conflicts, like merge...
Valentin Gatien-Baron -
r45219:16c36115 default
parent child Browse files
Show More
@@ -1,7838 +1,7837 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 difflib
10 import difflib
11 import errno
11 import errno
12 import os
12 import os
13 import re
13 import re
14 import sys
14 import sys
15
15
16 from .i18n import _
16 from .i18n import _
17 from .node import (
17 from .node import (
18 hex,
18 hex,
19 nullid,
19 nullid,
20 nullrev,
20 nullrev,
21 short,
21 short,
22 wdirhex,
22 wdirhex,
23 wdirrev,
23 wdirrev,
24 )
24 )
25 from .pycompat import open
25 from .pycompat import open
26 from . import (
26 from . import (
27 archival,
27 archival,
28 bookmarks,
28 bookmarks,
29 bundle2,
29 bundle2,
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 hbisect,
44 hbisect,
45 help,
45 help,
46 hg,
46 hg,
47 logcmdutil,
47 logcmdutil,
48 merge as mergemod,
48 merge as mergemod,
49 narrowspec,
49 narrowspec,
50 obsolete,
50 obsolete,
51 obsutil,
51 obsutil,
52 patch,
52 patch,
53 phases,
53 phases,
54 pycompat,
54 pycompat,
55 rcutil,
55 rcutil,
56 registrar,
56 registrar,
57 revsetlang,
57 revsetlang,
58 rewriteutil,
58 rewriteutil,
59 scmutil,
59 scmutil,
60 server,
60 server,
61 shelve as shelvemod,
61 shelve as shelvemod,
62 state as statemod,
62 state as statemod,
63 streamclone,
63 streamclone,
64 tags as tagsmod,
64 tags as tagsmod,
65 ui as uimod,
65 ui as uimod,
66 util,
66 util,
67 verify as verifymod,
67 verify as verifymod,
68 wireprotoserver,
68 wireprotoserver,
69 )
69 )
70 from .utils import (
70 from .utils import (
71 dateutil,
71 dateutil,
72 stringutil,
72 stringutil,
73 )
73 )
74
74
75 table = {}
75 table = {}
76 table.update(debugcommandsmod.command._table)
76 table.update(debugcommandsmod.command._table)
77
77
78 command = registrar.command(table)
78 command = registrar.command(table)
79 INTENT_READONLY = registrar.INTENT_READONLY
79 INTENT_READONLY = registrar.INTENT_READONLY
80
80
81 # common command options
81 # common command options
82
82
83 globalopts = [
83 globalopts = [
84 (
84 (
85 b'R',
85 b'R',
86 b'repository',
86 b'repository',
87 b'',
87 b'',
88 _(b'repository root directory or name of overlay bundle file'),
88 _(b'repository root directory or name of overlay bundle file'),
89 _(b'REPO'),
89 _(b'REPO'),
90 ),
90 ),
91 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
91 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
92 (
92 (
93 b'y',
93 b'y',
94 b'noninteractive',
94 b'noninteractive',
95 None,
95 None,
96 _(
96 _(
97 b'do not prompt, automatically pick the first choice for all prompts'
97 b'do not prompt, automatically pick the first choice for all prompts'
98 ),
98 ),
99 ),
99 ),
100 (b'q', b'quiet', None, _(b'suppress output')),
100 (b'q', b'quiet', None, _(b'suppress output')),
101 (b'v', b'verbose', None, _(b'enable additional output')),
101 (b'v', b'verbose', None, _(b'enable additional output')),
102 (
102 (
103 b'',
103 b'',
104 b'color',
104 b'color',
105 b'',
105 b'',
106 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
106 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
107 # and should not be translated
107 # and should not be translated
108 _(b"when to colorize (boolean, always, auto, never, or debug)"),
108 _(b"when to colorize (boolean, always, auto, never, or debug)"),
109 _(b'TYPE'),
109 _(b'TYPE'),
110 ),
110 ),
111 (
111 (
112 b'',
112 b'',
113 b'config',
113 b'config',
114 [],
114 [],
115 _(b'set/override config option (use \'section.name=value\')'),
115 _(b'set/override config option (use \'section.name=value\')'),
116 _(b'CONFIG'),
116 _(b'CONFIG'),
117 ),
117 ),
118 (b'', b'debug', None, _(b'enable debugging output')),
118 (b'', b'debug', None, _(b'enable debugging output')),
119 (b'', b'debugger', None, _(b'start debugger')),
119 (b'', b'debugger', None, _(b'start debugger')),
120 (
120 (
121 b'',
121 b'',
122 b'encoding',
122 b'encoding',
123 encoding.encoding,
123 encoding.encoding,
124 _(b'set the charset encoding'),
124 _(b'set the charset encoding'),
125 _(b'ENCODE'),
125 _(b'ENCODE'),
126 ),
126 ),
127 (
127 (
128 b'',
128 b'',
129 b'encodingmode',
129 b'encodingmode',
130 encoding.encodingmode,
130 encoding.encodingmode,
131 _(b'set the charset encoding mode'),
131 _(b'set the charset encoding mode'),
132 _(b'MODE'),
132 _(b'MODE'),
133 ),
133 ),
134 (b'', b'traceback', None, _(b'always print a traceback on exception')),
134 (b'', b'traceback', None, _(b'always print a traceback on exception')),
135 (b'', b'time', None, _(b'time how long the command takes')),
135 (b'', b'time', None, _(b'time how long the command takes')),
136 (b'', b'profile', None, _(b'print command execution profile')),
136 (b'', b'profile', None, _(b'print command execution profile')),
137 (b'', b'version', None, _(b'output version information and exit')),
137 (b'', b'version', None, _(b'output version information and exit')),
138 (b'h', b'help', None, _(b'display help and exit')),
138 (b'h', b'help', None, _(b'display help and exit')),
139 (b'', b'hidden', False, _(b'consider hidden changesets')),
139 (b'', b'hidden', False, _(b'consider hidden changesets')),
140 (
140 (
141 b'',
141 b'',
142 b'pager',
142 b'pager',
143 b'auto',
143 b'auto',
144 _(b"when to paginate (boolean, always, auto, or never)"),
144 _(b"when to paginate (boolean, always, auto, or never)"),
145 _(b'TYPE'),
145 _(b'TYPE'),
146 ),
146 ),
147 ]
147 ]
148
148
149 dryrunopts = cmdutil.dryrunopts
149 dryrunopts = cmdutil.dryrunopts
150 remoteopts = cmdutil.remoteopts
150 remoteopts = cmdutil.remoteopts
151 walkopts = cmdutil.walkopts
151 walkopts = cmdutil.walkopts
152 commitopts = cmdutil.commitopts
152 commitopts = cmdutil.commitopts
153 commitopts2 = cmdutil.commitopts2
153 commitopts2 = cmdutil.commitopts2
154 commitopts3 = cmdutil.commitopts3
154 commitopts3 = cmdutil.commitopts3
155 formatteropts = cmdutil.formatteropts
155 formatteropts = cmdutil.formatteropts
156 templateopts = cmdutil.templateopts
156 templateopts = cmdutil.templateopts
157 logopts = cmdutil.logopts
157 logopts = cmdutil.logopts
158 diffopts = cmdutil.diffopts
158 diffopts = cmdutil.diffopts
159 diffwsopts = cmdutil.diffwsopts
159 diffwsopts = cmdutil.diffwsopts
160 diffopts2 = cmdutil.diffopts2
160 diffopts2 = cmdutil.diffopts2
161 mergetoolopts = cmdutil.mergetoolopts
161 mergetoolopts = cmdutil.mergetoolopts
162 similarityopts = cmdutil.similarityopts
162 similarityopts = cmdutil.similarityopts
163 subrepoopts = cmdutil.subrepoopts
163 subrepoopts = cmdutil.subrepoopts
164 debugrevlogopts = cmdutil.debugrevlogopts
164 debugrevlogopts = cmdutil.debugrevlogopts
165
165
166 # Commands start here, listed alphabetically
166 # Commands start here, listed alphabetically
167
167
168
168
169 @command(
169 @command(
170 b'abort',
170 b'abort',
171 dryrunopts,
171 dryrunopts,
172 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
172 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
173 helpbasic=True,
173 helpbasic=True,
174 )
174 )
175 def abort(ui, repo, **opts):
175 def abort(ui, repo, **opts):
176 """abort an unfinished operation (EXPERIMENTAL)
176 """abort an unfinished operation (EXPERIMENTAL)
177
177
178 Aborts a multistep operation like graft, histedit, rebase, merge,
178 Aborts a multistep operation like graft, histedit, rebase, merge,
179 and unshelve if they are in an unfinished state.
179 and unshelve if they are in an unfinished state.
180
180
181 use --dry-run/-n to dry run the command.
181 use --dry-run/-n to dry run the command.
182 """
182 """
183 dryrun = opts.get('dry_run')
183 dryrun = opts.get('dry_run')
184 abortstate = cmdutil.getunfinishedstate(repo)
184 abortstate = cmdutil.getunfinishedstate(repo)
185 if not abortstate:
185 if not abortstate:
186 raise error.Abort(_(b'no operation in progress'))
186 raise error.Abort(_(b'no operation in progress'))
187 if not abortstate.abortfunc:
187 if not abortstate.abortfunc:
188 raise error.Abort(
188 raise error.Abort(
189 (
189 (
190 _(b"%s in progress but does not support 'hg abort'")
190 _(b"%s in progress but does not support 'hg abort'")
191 % (abortstate._opname)
191 % (abortstate._opname)
192 ),
192 ),
193 hint=abortstate.hint(),
193 hint=abortstate.hint(),
194 )
194 )
195 if dryrun:
195 if dryrun:
196 ui.status(
196 ui.status(
197 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
197 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
198 )
198 )
199 return
199 return
200 return abortstate.abortfunc(ui, repo)
200 return abortstate.abortfunc(ui, repo)
201
201
202
202
203 @command(
203 @command(
204 b'add',
204 b'add',
205 walkopts + subrepoopts + dryrunopts,
205 walkopts + subrepoopts + dryrunopts,
206 _(b'[OPTION]... [FILE]...'),
206 _(b'[OPTION]... [FILE]...'),
207 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
207 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
208 helpbasic=True,
208 helpbasic=True,
209 inferrepo=True,
209 inferrepo=True,
210 )
210 )
211 def add(ui, repo, *pats, **opts):
211 def add(ui, repo, *pats, **opts):
212 """add the specified files on the next commit
212 """add the specified files on the next commit
213
213
214 Schedule files to be version controlled and added to the
214 Schedule files to be version controlled and added to the
215 repository.
215 repository.
216
216
217 The files will be added to the repository at the next commit. To
217 The files will be added to the repository at the next commit. To
218 undo an add before that, see :hg:`forget`.
218 undo an add before that, see :hg:`forget`.
219
219
220 If no names are given, add all files to the repository (except
220 If no names are given, add all files to the repository (except
221 files matching ``.hgignore``).
221 files matching ``.hgignore``).
222
222
223 .. container:: verbose
223 .. container:: verbose
224
224
225 Examples:
225 Examples:
226
226
227 - New (unknown) files are added
227 - New (unknown) files are added
228 automatically by :hg:`add`::
228 automatically by :hg:`add`::
229
229
230 $ ls
230 $ ls
231 foo.c
231 foo.c
232 $ hg status
232 $ hg status
233 ? foo.c
233 ? foo.c
234 $ hg add
234 $ hg add
235 adding foo.c
235 adding foo.c
236 $ hg status
236 $ hg status
237 A foo.c
237 A foo.c
238
238
239 - Specific files to be added can be specified::
239 - Specific files to be added can be specified::
240
240
241 $ ls
241 $ ls
242 bar.c foo.c
242 bar.c foo.c
243 $ hg status
243 $ hg status
244 ? bar.c
244 ? bar.c
245 ? foo.c
245 ? foo.c
246 $ hg add bar.c
246 $ hg add bar.c
247 $ hg status
247 $ hg status
248 A bar.c
248 A bar.c
249 ? foo.c
249 ? foo.c
250
250
251 Returns 0 if all files are successfully added.
251 Returns 0 if all files are successfully added.
252 """
252 """
253
253
254 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
254 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
255 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
255 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
256 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
256 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
257 return rejected and 1 or 0
257 return rejected and 1 or 0
258
258
259
259
260 @command(
260 @command(
261 b'addremove',
261 b'addremove',
262 similarityopts + subrepoopts + walkopts + dryrunopts,
262 similarityopts + subrepoopts + walkopts + dryrunopts,
263 _(b'[OPTION]... [FILE]...'),
263 _(b'[OPTION]... [FILE]...'),
264 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
264 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
265 inferrepo=True,
265 inferrepo=True,
266 )
266 )
267 def addremove(ui, repo, *pats, **opts):
267 def addremove(ui, repo, *pats, **opts):
268 """add all new files, delete all missing files
268 """add all new files, delete all missing files
269
269
270 Add all new files and remove all missing files from the
270 Add all new files and remove all missing files from the
271 repository.
271 repository.
272
272
273 Unless names are given, new files are ignored if they match any of
273 Unless names are given, new files are ignored if they match any of
274 the patterns in ``.hgignore``. As with add, these changes take
274 the patterns in ``.hgignore``. As with add, these changes take
275 effect at the next commit.
275 effect at the next commit.
276
276
277 Use the -s/--similarity option to detect renamed files. This
277 Use the -s/--similarity option to detect renamed files. This
278 option takes a percentage between 0 (disabled) and 100 (files must
278 option takes a percentage between 0 (disabled) and 100 (files must
279 be identical) as its parameter. With a parameter greater than 0,
279 be identical) as its parameter. With a parameter greater than 0,
280 this compares every removed file with every added file and records
280 this compares every removed file with every added file and records
281 those similar enough as renames. Detecting renamed files this way
281 those similar enough as renames. Detecting renamed files this way
282 can be expensive. After using this option, :hg:`status -C` can be
282 can be expensive. After using this option, :hg:`status -C` can be
283 used to check which files were identified as moved or renamed. If
283 used to check which files were identified as moved or renamed. If
284 not specified, -s/--similarity defaults to 100 and only renames of
284 not specified, -s/--similarity defaults to 100 and only renames of
285 identical files are detected.
285 identical files are detected.
286
286
287 .. container:: verbose
287 .. container:: verbose
288
288
289 Examples:
289 Examples:
290
290
291 - A number of files (bar.c and foo.c) are new,
291 - A number of files (bar.c and foo.c) are new,
292 while foobar.c has been removed (without using :hg:`remove`)
292 while foobar.c has been removed (without using :hg:`remove`)
293 from the repository::
293 from the repository::
294
294
295 $ ls
295 $ ls
296 bar.c foo.c
296 bar.c foo.c
297 $ hg status
297 $ hg status
298 ! foobar.c
298 ! foobar.c
299 ? bar.c
299 ? bar.c
300 ? foo.c
300 ? foo.c
301 $ hg addremove
301 $ hg addremove
302 adding bar.c
302 adding bar.c
303 adding foo.c
303 adding foo.c
304 removing foobar.c
304 removing foobar.c
305 $ hg status
305 $ hg status
306 A bar.c
306 A bar.c
307 A foo.c
307 A foo.c
308 R foobar.c
308 R foobar.c
309
309
310 - A file foobar.c was moved to foo.c without using :hg:`rename`.
310 - A file foobar.c was moved to foo.c without using :hg:`rename`.
311 Afterwards, it was edited slightly::
311 Afterwards, it was edited slightly::
312
312
313 $ ls
313 $ ls
314 foo.c
314 foo.c
315 $ hg status
315 $ hg status
316 ! foobar.c
316 ! foobar.c
317 ? foo.c
317 ? foo.c
318 $ hg addremove --similarity 90
318 $ hg addremove --similarity 90
319 removing foobar.c
319 removing foobar.c
320 adding foo.c
320 adding foo.c
321 recording removal of foobar.c as rename to foo.c (94% similar)
321 recording removal of foobar.c as rename to foo.c (94% similar)
322 $ hg status -C
322 $ hg status -C
323 A foo.c
323 A foo.c
324 foobar.c
324 foobar.c
325 R foobar.c
325 R foobar.c
326
326
327 Returns 0 if all files are successfully added.
327 Returns 0 if all files are successfully added.
328 """
328 """
329 opts = pycompat.byteskwargs(opts)
329 opts = pycompat.byteskwargs(opts)
330 if not opts.get(b'similarity'):
330 if not opts.get(b'similarity'):
331 opts[b'similarity'] = b'100'
331 opts[b'similarity'] = b'100'
332 matcher = scmutil.match(repo[None], pats, opts)
332 matcher = scmutil.match(repo[None], pats, opts)
333 relative = scmutil.anypats(pats, opts)
333 relative = scmutil.anypats(pats, opts)
334 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
334 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
335 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
335 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
336
336
337
337
338 @command(
338 @command(
339 b'annotate|blame',
339 b'annotate|blame',
340 [
340 [
341 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
341 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
342 (
342 (
343 b'',
343 b'',
344 b'follow',
344 b'follow',
345 None,
345 None,
346 _(b'follow copies/renames and list the filename (DEPRECATED)'),
346 _(b'follow copies/renames and list the filename (DEPRECATED)'),
347 ),
347 ),
348 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
348 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
349 (b'a', b'text', None, _(b'treat all files as text')),
349 (b'a', b'text', None, _(b'treat all files as text')),
350 (b'u', b'user', None, _(b'list the author (long with -v)')),
350 (b'u', b'user', None, _(b'list the author (long with -v)')),
351 (b'f', b'file', None, _(b'list the filename')),
351 (b'f', b'file', None, _(b'list the filename')),
352 (b'd', b'date', None, _(b'list the date (short with -q)')),
352 (b'd', b'date', None, _(b'list the date (short with -q)')),
353 (b'n', b'number', None, _(b'list the revision number (default)')),
353 (b'n', b'number', None, _(b'list the revision number (default)')),
354 (b'c', b'changeset', None, _(b'list the changeset')),
354 (b'c', b'changeset', None, _(b'list the changeset')),
355 (
355 (
356 b'l',
356 b'l',
357 b'line-number',
357 b'line-number',
358 None,
358 None,
359 _(b'show line number at the first appearance'),
359 _(b'show line number at the first appearance'),
360 ),
360 ),
361 (
361 (
362 b'',
362 b'',
363 b'skip',
363 b'skip',
364 [],
364 [],
365 _(b'revset to not display (EXPERIMENTAL)'),
365 _(b'revset to not display (EXPERIMENTAL)'),
366 _(b'REV'),
366 _(b'REV'),
367 ),
367 ),
368 ]
368 ]
369 + diffwsopts
369 + diffwsopts
370 + walkopts
370 + walkopts
371 + formatteropts,
371 + formatteropts,
372 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
372 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
373 helpcategory=command.CATEGORY_FILE_CONTENTS,
373 helpcategory=command.CATEGORY_FILE_CONTENTS,
374 helpbasic=True,
374 helpbasic=True,
375 inferrepo=True,
375 inferrepo=True,
376 )
376 )
377 def annotate(ui, repo, *pats, **opts):
377 def annotate(ui, repo, *pats, **opts):
378 """show changeset information by line for each file
378 """show changeset information by line for each file
379
379
380 List changes in files, showing the revision id responsible for
380 List changes in files, showing the revision id responsible for
381 each line.
381 each line.
382
382
383 This command is useful for discovering when a change was made and
383 This command is useful for discovering when a change was made and
384 by whom.
384 by whom.
385
385
386 If you include --file, --user, or --date, the revision number is
386 If you include --file, --user, or --date, the revision number is
387 suppressed unless you also include --number.
387 suppressed unless you also include --number.
388
388
389 Without the -a/--text option, annotate will avoid processing files
389 Without the -a/--text option, annotate will avoid processing files
390 it detects as binary. With -a, annotate will annotate the file
390 it detects as binary. With -a, annotate will annotate the file
391 anyway, although the results will probably be neither useful
391 anyway, although the results will probably be neither useful
392 nor desirable.
392 nor desirable.
393
393
394 .. container:: verbose
394 .. container:: verbose
395
395
396 Template:
396 Template:
397
397
398 The following keywords are supported in addition to the common template
398 The following keywords are supported in addition to the common template
399 keywords and functions. See also :hg:`help templates`.
399 keywords and functions. See also :hg:`help templates`.
400
400
401 :lines: List of lines with annotation data.
401 :lines: List of lines with annotation data.
402 :path: String. Repository-absolute path of the specified file.
402 :path: String. Repository-absolute path of the specified file.
403
403
404 And each entry of ``{lines}`` provides the following sub-keywords in
404 And each entry of ``{lines}`` provides the following sub-keywords in
405 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
405 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
406
406
407 :line: String. Line content.
407 :line: String. Line content.
408 :lineno: Integer. Line number at that revision.
408 :lineno: Integer. Line number at that revision.
409 :path: String. Repository-absolute path of the file at that revision.
409 :path: String. Repository-absolute path of the file at that revision.
410
410
411 See :hg:`help templates.operators` for the list expansion syntax.
411 See :hg:`help templates.operators` for the list expansion syntax.
412
412
413 Returns 0 on success.
413 Returns 0 on success.
414 """
414 """
415 opts = pycompat.byteskwargs(opts)
415 opts = pycompat.byteskwargs(opts)
416 if not pats:
416 if not pats:
417 raise error.Abort(_(b'at least one filename or pattern is required'))
417 raise error.Abort(_(b'at least one filename or pattern is required'))
418
418
419 if opts.get(b'follow'):
419 if opts.get(b'follow'):
420 # --follow is deprecated and now just an alias for -f/--file
420 # --follow is deprecated and now just an alias for -f/--file
421 # to mimic the behavior of Mercurial before version 1.5
421 # to mimic the behavior of Mercurial before version 1.5
422 opts[b'file'] = True
422 opts[b'file'] = True
423
423
424 if (
424 if (
425 not opts.get(b'user')
425 not opts.get(b'user')
426 and not opts.get(b'changeset')
426 and not opts.get(b'changeset')
427 and not opts.get(b'date')
427 and not opts.get(b'date')
428 and not opts.get(b'file')
428 and not opts.get(b'file')
429 ):
429 ):
430 opts[b'number'] = True
430 opts[b'number'] = True
431
431
432 linenumber = opts.get(b'line_number') is not None
432 linenumber = opts.get(b'line_number') is not None
433 if (
433 if (
434 linenumber
434 linenumber
435 and (not opts.get(b'changeset'))
435 and (not opts.get(b'changeset'))
436 and (not opts.get(b'number'))
436 and (not opts.get(b'number'))
437 ):
437 ):
438 raise error.Abort(_(b'at least one of -n/-c is required for -l'))
438 raise error.Abort(_(b'at least one of -n/-c is required for -l'))
439
439
440 rev = opts.get(b'rev')
440 rev = opts.get(b'rev')
441 if rev:
441 if rev:
442 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
442 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
443 ctx = scmutil.revsingle(repo, rev)
443 ctx = scmutil.revsingle(repo, rev)
444
444
445 ui.pager(b'annotate')
445 ui.pager(b'annotate')
446 rootfm = ui.formatter(b'annotate', opts)
446 rootfm = ui.formatter(b'annotate', opts)
447 if ui.debugflag:
447 if ui.debugflag:
448 shorthex = pycompat.identity
448 shorthex = pycompat.identity
449 else:
449 else:
450
450
451 def shorthex(h):
451 def shorthex(h):
452 return h[:12]
452 return h[:12]
453
453
454 if ui.quiet:
454 if ui.quiet:
455 datefunc = dateutil.shortdate
455 datefunc = dateutil.shortdate
456 else:
456 else:
457 datefunc = dateutil.datestr
457 datefunc = dateutil.datestr
458 if ctx.rev() is None:
458 if ctx.rev() is None:
459 if opts.get(b'changeset'):
459 if opts.get(b'changeset'):
460 # omit "+" suffix which is appended to node hex
460 # omit "+" suffix which is appended to node hex
461 def formatrev(rev):
461 def formatrev(rev):
462 if rev == wdirrev:
462 if rev == wdirrev:
463 return b'%d' % ctx.p1().rev()
463 return b'%d' % ctx.p1().rev()
464 else:
464 else:
465 return b'%d' % rev
465 return b'%d' % rev
466
466
467 else:
467 else:
468
468
469 def formatrev(rev):
469 def formatrev(rev):
470 if rev == wdirrev:
470 if rev == wdirrev:
471 return b'%d+' % ctx.p1().rev()
471 return b'%d+' % ctx.p1().rev()
472 else:
472 else:
473 return b'%d ' % rev
473 return b'%d ' % rev
474
474
475 def formathex(h):
475 def formathex(h):
476 if h == wdirhex:
476 if h == wdirhex:
477 return b'%s+' % shorthex(hex(ctx.p1().node()))
477 return b'%s+' % shorthex(hex(ctx.p1().node()))
478 else:
478 else:
479 return b'%s ' % shorthex(h)
479 return b'%s ' % shorthex(h)
480
480
481 else:
481 else:
482 formatrev = b'%d'.__mod__
482 formatrev = b'%d'.__mod__
483 formathex = shorthex
483 formathex = shorthex
484
484
485 opmap = [
485 opmap = [
486 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
486 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
487 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
487 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
488 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
488 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
489 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
489 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
490 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
490 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
491 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
491 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
492 ]
492 ]
493 opnamemap = {
493 opnamemap = {
494 b'rev': b'number',
494 b'rev': b'number',
495 b'node': b'changeset',
495 b'node': b'changeset',
496 b'path': b'file',
496 b'path': b'file',
497 b'lineno': b'line_number',
497 b'lineno': b'line_number',
498 }
498 }
499
499
500 if rootfm.isplain():
500 if rootfm.isplain():
501
501
502 def makefunc(get, fmt):
502 def makefunc(get, fmt):
503 return lambda x: fmt(get(x))
503 return lambda x: fmt(get(x))
504
504
505 else:
505 else:
506
506
507 def makefunc(get, fmt):
507 def makefunc(get, fmt):
508 return get
508 return get
509
509
510 datahint = rootfm.datahint()
510 datahint = rootfm.datahint()
511 funcmap = [
511 funcmap = [
512 (makefunc(get, fmt), sep)
512 (makefunc(get, fmt), sep)
513 for fn, sep, get, fmt in opmap
513 for fn, sep, get, fmt in opmap
514 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
514 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
515 ]
515 ]
516 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
516 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
517 fields = b' '.join(
517 fields = b' '.join(
518 fn
518 fn
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
522
523 def bad(x, y):
523 def bad(x, y):
524 raise error.Abort(b"%s: %s" % (x, y))
524 raise error.Abort(b"%s: %s" % (x, y))
525
525
526 m = scmutil.match(ctx, pats, opts, badfn=bad)
526 m = scmutil.match(ctx, pats, opts, badfn=bad)
527
527
528 follow = not opts.get(b'no_follow')
528 follow = not opts.get(b'no_follow')
529 diffopts = patch.difffeatureopts(
529 diffopts = patch.difffeatureopts(
530 ui, opts, section=b'annotate', whitespace=True
530 ui, opts, section=b'annotate', whitespace=True
531 )
531 )
532 skiprevs = opts.get(b'skip')
532 skiprevs = opts.get(b'skip')
533 if skiprevs:
533 if skiprevs:
534 skiprevs = scmutil.revrange(repo, skiprevs)
534 skiprevs = scmutil.revrange(repo, skiprevs)
535
535
536 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
536 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
537 for abs in ctx.walk(m):
537 for abs in ctx.walk(m):
538 fctx = ctx[abs]
538 fctx = ctx[abs]
539 rootfm.startitem()
539 rootfm.startitem()
540 rootfm.data(path=abs)
540 rootfm.data(path=abs)
541 if not opts.get(b'text') and fctx.isbinary():
541 if not opts.get(b'text') and fctx.isbinary():
542 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
542 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
543 continue
543 continue
544
544
545 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
545 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
546 lines = fctx.annotate(
546 lines = fctx.annotate(
547 follow=follow, skiprevs=skiprevs, diffopts=diffopts
547 follow=follow, skiprevs=skiprevs, diffopts=diffopts
548 )
548 )
549 if not lines:
549 if not lines:
550 fm.end()
550 fm.end()
551 continue
551 continue
552 formats = []
552 formats = []
553 pieces = []
553 pieces = []
554
554
555 for f, sep in funcmap:
555 for f, sep in funcmap:
556 l = [f(n) for n in lines]
556 l = [f(n) for n in lines]
557 if fm.isplain():
557 if fm.isplain():
558 sizes = [encoding.colwidth(x) for x in l]
558 sizes = [encoding.colwidth(x) for x in l]
559 ml = max(sizes)
559 ml = max(sizes)
560 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
560 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
561 else:
561 else:
562 formats.append([b'%s'] * len(l))
562 formats.append([b'%s'] * len(l))
563 pieces.append(l)
563 pieces.append(l)
564
564
565 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
565 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
566 fm.startitem()
566 fm.startitem()
567 fm.context(fctx=n.fctx)
567 fm.context(fctx=n.fctx)
568 fm.write(fields, b"".join(f), *p)
568 fm.write(fields, b"".join(f), *p)
569 if n.skip:
569 if n.skip:
570 fmt = b"* %s"
570 fmt = b"* %s"
571 else:
571 else:
572 fmt = b": %s"
572 fmt = b": %s"
573 fm.write(b'line', fmt, n.text)
573 fm.write(b'line', fmt, n.text)
574
574
575 if not lines[-1].text.endswith(b'\n'):
575 if not lines[-1].text.endswith(b'\n'):
576 fm.plain(b'\n')
576 fm.plain(b'\n')
577 fm.end()
577 fm.end()
578
578
579 rootfm.end()
579 rootfm.end()
580
580
581
581
582 @command(
582 @command(
583 b'archive',
583 b'archive',
584 [
584 [
585 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
585 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
586 (
586 (
587 b'p',
587 b'p',
588 b'prefix',
588 b'prefix',
589 b'',
589 b'',
590 _(b'directory prefix for files in archive'),
590 _(b'directory prefix for files in archive'),
591 _(b'PREFIX'),
591 _(b'PREFIX'),
592 ),
592 ),
593 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
593 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
594 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
594 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
595 ]
595 ]
596 + subrepoopts
596 + subrepoopts
597 + walkopts,
597 + walkopts,
598 _(b'[OPTION]... DEST'),
598 _(b'[OPTION]... DEST'),
599 helpcategory=command.CATEGORY_IMPORT_EXPORT,
599 helpcategory=command.CATEGORY_IMPORT_EXPORT,
600 )
600 )
601 def archive(ui, repo, dest, **opts):
601 def archive(ui, repo, dest, **opts):
602 '''create an unversioned archive of a repository revision
602 '''create an unversioned archive of a repository revision
603
603
604 By default, the revision used is the parent of the working
604 By default, the revision used is the parent of the working
605 directory; use -r/--rev to specify a different revision.
605 directory; use -r/--rev to specify a different revision.
606
606
607 The archive type is automatically detected based on file
607 The archive type is automatically detected based on file
608 extension (to override, use -t/--type).
608 extension (to override, use -t/--type).
609
609
610 .. container:: verbose
610 .. container:: verbose
611
611
612 Examples:
612 Examples:
613
613
614 - create a zip file containing the 1.0 release::
614 - create a zip file containing the 1.0 release::
615
615
616 hg archive -r 1.0 project-1.0.zip
616 hg archive -r 1.0 project-1.0.zip
617
617
618 - create a tarball excluding .hg files::
618 - create a tarball excluding .hg files::
619
619
620 hg archive project.tar.gz -X ".hg*"
620 hg archive project.tar.gz -X ".hg*"
621
621
622 Valid types are:
622 Valid types are:
623
623
624 :``files``: a directory full of files (default)
624 :``files``: a directory full of files (default)
625 :``tar``: tar archive, uncompressed
625 :``tar``: tar archive, uncompressed
626 :``tbz2``: tar archive, compressed using bzip2
626 :``tbz2``: tar archive, compressed using bzip2
627 :``tgz``: tar archive, compressed using gzip
627 :``tgz``: tar archive, compressed using gzip
628 :``txz``: tar archive, compressed using lzma (only in Python 3)
628 :``txz``: tar archive, compressed using lzma (only in Python 3)
629 :``uzip``: zip archive, uncompressed
629 :``uzip``: zip archive, uncompressed
630 :``zip``: zip archive, compressed using deflate
630 :``zip``: zip archive, compressed using deflate
631
631
632 The exact name of the destination archive or directory is given
632 The exact name of the destination archive or directory is given
633 using a format string; see :hg:`help export` for details.
633 using a format string; see :hg:`help export` for details.
634
634
635 Each member added to an archive file has a directory prefix
635 Each member added to an archive file has a directory prefix
636 prepended. Use -p/--prefix to specify a format string for the
636 prepended. Use -p/--prefix to specify a format string for the
637 prefix. The default is the basename of the archive, with suffixes
637 prefix. The default is the basename of the archive, with suffixes
638 removed.
638 removed.
639
639
640 Returns 0 on success.
640 Returns 0 on success.
641 '''
641 '''
642
642
643 opts = pycompat.byteskwargs(opts)
643 opts = pycompat.byteskwargs(opts)
644 rev = opts.get(b'rev')
644 rev = opts.get(b'rev')
645 if rev:
645 if rev:
646 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
646 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
647 ctx = scmutil.revsingle(repo, rev)
647 ctx = scmutil.revsingle(repo, rev)
648 if not ctx:
648 if not ctx:
649 raise error.Abort(_(b'no working directory: please specify a revision'))
649 raise error.Abort(_(b'no working directory: please specify a revision'))
650 node = ctx.node()
650 node = ctx.node()
651 dest = cmdutil.makefilename(ctx, dest)
651 dest = cmdutil.makefilename(ctx, dest)
652 if os.path.realpath(dest) == repo.root:
652 if os.path.realpath(dest) == repo.root:
653 raise error.Abort(_(b'repository root cannot be destination'))
653 raise error.Abort(_(b'repository root cannot be destination'))
654
654
655 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
655 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
656 prefix = opts.get(b'prefix')
656 prefix = opts.get(b'prefix')
657
657
658 if dest == b'-':
658 if dest == b'-':
659 if kind == b'files':
659 if kind == b'files':
660 raise error.Abort(_(b'cannot archive plain files to stdout'))
660 raise error.Abort(_(b'cannot archive plain files to stdout'))
661 dest = cmdutil.makefileobj(ctx, dest)
661 dest = cmdutil.makefileobj(ctx, dest)
662 if not prefix:
662 if not prefix:
663 prefix = os.path.basename(repo.root) + b'-%h'
663 prefix = os.path.basename(repo.root) + b'-%h'
664
664
665 prefix = cmdutil.makefilename(ctx, prefix)
665 prefix = cmdutil.makefilename(ctx, prefix)
666 match = scmutil.match(ctx, [], opts)
666 match = scmutil.match(ctx, [], opts)
667 archival.archive(
667 archival.archive(
668 repo,
668 repo,
669 dest,
669 dest,
670 node,
670 node,
671 kind,
671 kind,
672 not opts.get(b'no_decode'),
672 not opts.get(b'no_decode'),
673 match,
673 match,
674 prefix,
674 prefix,
675 subrepos=opts.get(b'subrepos'),
675 subrepos=opts.get(b'subrepos'),
676 )
676 )
677
677
678
678
679 @command(
679 @command(
680 b'backout',
680 b'backout',
681 [
681 [
682 (
682 (
683 b'',
683 b'',
684 b'merge',
684 b'merge',
685 None,
685 None,
686 _(b'merge with old dirstate parent after backout'),
686 _(b'merge with old dirstate parent after backout'),
687 ),
687 ),
688 (
688 (
689 b'',
689 b'',
690 b'commit',
690 b'commit',
691 None,
691 None,
692 _(b'commit if no conflicts were encountered (DEPRECATED)'),
692 _(b'commit if no conflicts were encountered (DEPRECATED)'),
693 ),
693 ),
694 (b'', b'no-commit', None, _(b'do not commit')),
694 (b'', b'no-commit', None, _(b'do not commit')),
695 (
695 (
696 b'',
696 b'',
697 b'parent',
697 b'parent',
698 b'',
698 b'',
699 _(b'parent to choose when backing out merge (DEPRECATED)'),
699 _(b'parent to choose when backing out merge (DEPRECATED)'),
700 _(b'REV'),
700 _(b'REV'),
701 ),
701 ),
702 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
702 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
703 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
703 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
704 ]
704 ]
705 + mergetoolopts
705 + mergetoolopts
706 + walkopts
706 + walkopts
707 + commitopts
707 + commitopts
708 + commitopts2,
708 + commitopts2,
709 _(b'[OPTION]... [-r] REV'),
709 _(b'[OPTION]... [-r] REV'),
710 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
710 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
711 )
711 )
712 def backout(ui, repo, node=None, rev=None, **opts):
712 def backout(ui, repo, node=None, rev=None, **opts):
713 '''reverse effect of earlier changeset
713 '''reverse effect of earlier changeset
714
714
715 Prepare a new changeset with the effect of REV undone in the
715 Prepare a new changeset with the effect of REV undone in the
716 current working directory. If no conflicts were encountered,
716 current working directory. If no conflicts were encountered,
717 it will be committed immediately.
717 it will be committed immediately.
718
718
719 If REV is the parent of the working directory, then this new changeset
719 If REV is the parent of the working directory, then this new changeset
720 is committed automatically (unless --no-commit is specified).
720 is committed automatically (unless --no-commit is specified).
721
721
722 .. note::
722 .. note::
723
723
724 :hg:`backout` cannot be used to fix either an unwanted or
724 :hg:`backout` cannot be used to fix either an unwanted or
725 incorrect merge.
725 incorrect merge.
726
726
727 .. container:: verbose
727 .. container:: verbose
728
728
729 Examples:
729 Examples:
730
730
731 - Reverse the effect of the parent of the working directory.
731 - Reverse the effect of the parent of the working directory.
732 This backout will be committed immediately::
732 This backout will be committed immediately::
733
733
734 hg backout -r .
734 hg backout -r .
735
735
736 - Reverse the effect of previous bad revision 23::
736 - Reverse the effect of previous bad revision 23::
737
737
738 hg backout -r 23
738 hg backout -r 23
739
739
740 - Reverse the effect of previous bad revision 23 and
740 - Reverse the effect of previous bad revision 23 and
741 leave changes uncommitted::
741 leave changes uncommitted::
742
742
743 hg backout -r 23 --no-commit
743 hg backout -r 23 --no-commit
744 hg commit -m "Backout revision 23"
744 hg commit -m "Backout revision 23"
745
745
746 By default, the pending changeset will have one parent,
746 By default, the pending changeset will have one parent,
747 maintaining a linear history. With --merge, the pending
747 maintaining a linear history. With --merge, the pending
748 changeset will instead have two parents: the old parent of the
748 changeset will instead have two parents: the old parent of the
749 working directory and a new child of REV that simply undoes REV.
749 working directory and a new child of REV that simply undoes REV.
750
750
751 Before version 1.7, the behavior without --merge was equivalent
751 Before version 1.7, the behavior without --merge was equivalent
752 to specifying --merge followed by :hg:`update --clean .` to
752 to specifying --merge followed by :hg:`update --clean .` to
753 cancel the merge and leave the child of REV as a head to be
753 cancel the merge and leave the child of REV as a head to be
754 merged separately.
754 merged separately.
755
755
756 See :hg:`help dates` for a list of formats valid for -d/--date.
756 See :hg:`help dates` for a list of formats valid for -d/--date.
757
757
758 See :hg:`help revert` for a way to restore files to the state
758 See :hg:`help revert` for a way to restore files to the state
759 of another revision.
759 of another revision.
760
760
761 Returns 0 on success, 1 if nothing to backout or there are unresolved
761 Returns 0 on success, 1 if nothing to backout or there are unresolved
762 files.
762 files.
763 '''
763 '''
764 with repo.wlock(), repo.lock():
764 with repo.wlock(), repo.lock():
765 return _dobackout(ui, repo, node, rev, **opts)
765 return _dobackout(ui, repo, node, rev, **opts)
766
766
767
767
768 def _dobackout(ui, repo, node=None, rev=None, **opts):
768 def _dobackout(ui, repo, node=None, rev=None, **opts):
769 opts = pycompat.byteskwargs(opts)
769 opts = pycompat.byteskwargs(opts)
770 if opts.get(b'commit') and opts.get(b'no_commit'):
770 if opts.get(b'commit') and opts.get(b'no_commit'):
771 raise error.Abort(_(b"cannot use --commit with --no-commit"))
771 raise error.Abort(_(b"cannot use --commit with --no-commit"))
772 if opts.get(b'merge') and opts.get(b'no_commit'):
772 if opts.get(b'merge') and opts.get(b'no_commit'):
773 raise error.Abort(_(b"cannot use --merge with --no-commit"))
773 raise error.Abort(_(b"cannot use --merge with --no-commit"))
774
774
775 if rev and node:
775 if rev and node:
776 raise error.Abort(_(b"please specify just one revision"))
776 raise error.Abort(_(b"please specify just one revision"))
777
777
778 if not rev:
778 if not rev:
779 rev = node
779 rev = node
780
780
781 if not rev:
781 if not rev:
782 raise error.Abort(_(b"please specify a revision to backout"))
782 raise error.Abort(_(b"please specify a revision to backout"))
783
783
784 date = opts.get(b'date')
784 date = opts.get(b'date')
785 if date:
785 if date:
786 opts[b'date'] = dateutil.parsedate(date)
786 opts[b'date'] = dateutil.parsedate(date)
787
787
788 cmdutil.checkunfinished(repo)
788 cmdutil.checkunfinished(repo)
789 cmdutil.bailifchanged(repo)
789 cmdutil.bailifchanged(repo)
790 node = scmutil.revsingle(repo, rev).node()
790 node = scmutil.revsingle(repo, rev).node()
791
791
792 op1, op2 = repo.dirstate.parents()
792 op1, op2 = repo.dirstate.parents()
793 if not repo.changelog.isancestor(node, op1):
793 if not repo.changelog.isancestor(node, op1):
794 raise error.Abort(_(b'cannot backout change that is not an ancestor'))
794 raise error.Abort(_(b'cannot backout change that is not an ancestor'))
795
795
796 p1, p2 = repo.changelog.parents(node)
796 p1, p2 = repo.changelog.parents(node)
797 if p1 == nullid:
797 if p1 == nullid:
798 raise error.Abort(_(b'cannot backout a change with no parents'))
798 raise error.Abort(_(b'cannot backout a change with no parents'))
799 if p2 != nullid:
799 if p2 != nullid:
800 if not opts.get(b'parent'):
800 if not opts.get(b'parent'):
801 raise error.Abort(_(b'cannot backout a merge changeset'))
801 raise error.Abort(_(b'cannot backout a merge changeset'))
802 p = repo.lookup(opts[b'parent'])
802 p = repo.lookup(opts[b'parent'])
803 if p not in (p1, p2):
803 if p not in (p1, p2):
804 raise error.Abort(
804 raise error.Abort(
805 _(b'%s is not a parent of %s') % (short(p), short(node))
805 _(b'%s is not a parent of %s') % (short(p), short(node))
806 )
806 )
807 parent = p
807 parent = p
808 else:
808 else:
809 if opts.get(b'parent'):
809 if opts.get(b'parent'):
810 raise error.Abort(_(b'cannot use --parent on non-merge changeset'))
810 raise error.Abort(_(b'cannot use --parent on non-merge changeset'))
811 parent = p1
811 parent = p1
812
812
813 # the backout should appear on the same branch
813 # the backout should appear on the same branch
814 branch = repo.dirstate.branch()
814 branch = repo.dirstate.branch()
815 bheads = repo.branchheads(branch)
815 bheads = repo.branchheads(branch)
816 rctx = scmutil.revsingle(repo, hex(parent))
816 rctx = scmutil.revsingle(repo, hex(parent))
817 if not opts.get(b'merge') and op1 != node:
817 if not opts.get(b'merge') and op1 != node:
818 with dirstateguard.dirstateguard(repo, b'backout'):
818 with dirstateguard.dirstateguard(repo, b'backout'):
819 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
819 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
820 with ui.configoverride(overrides, b'backout'):
820 with ui.configoverride(overrides, b'backout'):
821 stats = mergemod.update(
821 stats = mergemod.update(
822 repo,
822 repo,
823 parent,
823 parent,
824 branchmerge=True,
824 branchmerge=True,
825 force=True,
825 force=True,
826 ancestor=node,
826 ancestor=node,
827 mergeancestor=False,
827 mergeancestor=False,
828 )
828 )
829 repo.setparents(op1, op2)
829 repo.setparents(op1, op2)
830 hg._showstats(repo, stats)
830 hg._showstats(repo, stats)
831 if stats.unresolvedcount:
831 if stats.unresolvedcount:
832 repo.ui.status(
832 repo.ui.status(
833 _(b"use 'hg resolve' to retry unresolved file merges\n")
833 _(b"use 'hg resolve' to retry unresolved file merges\n")
834 )
834 )
835 return 1
835 return 1
836 else:
836 else:
837 hg.clean(repo, node, show_stats=False)
837 hg.clean(repo, node, show_stats=False)
838 repo.dirstate.setbranch(branch)
838 repo.dirstate.setbranch(branch)
839 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
839 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
840
840
841 if opts.get(b'no_commit'):
841 if opts.get(b'no_commit'):
842 msg = _(b"changeset %s backed out, don't forget to commit.\n")
842 msg = _(b"changeset %s backed out, don't forget to commit.\n")
843 ui.status(msg % short(node))
843 ui.status(msg % short(node))
844 return 0
844 return 0
845
845
846 def commitfunc(ui, repo, message, match, opts):
846 def commitfunc(ui, repo, message, match, opts):
847 editform = b'backout'
847 editform = b'backout'
848 e = cmdutil.getcommiteditor(
848 e = cmdutil.getcommiteditor(
849 editform=editform, **pycompat.strkwargs(opts)
849 editform=editform, **pycompat.strkwargs(opts)
850 )
850 )
851 if not message:
851 if not message:
852 # we don't translate commit messages
852 # we don't translate commit messages
853 message = b"Backed out changeset %s" % short(node)
853 message = b"Backed out changeset %s" % short(node)
854 e = cmdutil.getcommiteditor(edit=True, editform=editform)
854 e = cmdutil.getcommiteditor(edit=True, editform=editform)
855 return repo.commit(
855 return repo.commit(
856 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
856 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
857 )
857 )
858
858
859 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
859 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
860 if not newnode:
860 if not newnode:
861 ui.status(_(b"nothing changed\n"))
861 ui.status(_(b"nothing changed\n"))
862 return 1
862 return 1
863 cmdutil.commitstatus(repo, newnode, branch, bheads)
863 cmdutil.commitstatus(repo, newnode, branch, bheads)
864
864
865 def nice(node):
865 def nice(node):
866 return b'%d:%s' % (repo.changelog.rev(node), short(node))
866 return b'%d:%s' % (repo.changelog.rev(node), short(node))
867
867
868 ui.status(
868 ui.status(
869 _(b'changeset %s backs out changeset %s\n')
869 _(b'changeset %s backs out changeset %s\n')
870 % (nice(repo.changelog.tip()), nice(node))
870 % (nice(repo.changelog.tip()), nice(node))
871 )
871 )
872 if opts.get(b'merge') and op1 != node:
872 if opts.get(b'merge') and op1 != node:
873 hg.clean(repo, op1, show_stats=False)
873 hg.clean(repo, op1, show_stats=False)
874 ui.status(
874 ui.status(
875 _(b'merging with changeset %s\n') % nice(repo.changelog.tip())
875 _(b'merging with changeset %s\n') % nice(repo.changelog.tip())
876 )
876 )
877 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
877 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
878 with ui.configoverride(overrides, b'backout'):
878 with ui.configoverride(overrides, b'backout'):
879 return hg.merge(repo[b'tip'])
879 return hg.merge(repo[b'tip'])
880 return 0
880 return 0
881
881
882
882
883 @command(
883 @command(
884 b'bisect',
884 b'bisect',
885 [
885 [
886 (b'r', b'reset', False, _(b'reset bisect state')),
886 (b'r', b'reset', False, _(b'reset bisect state')),
887 (b'g', b'good', False, _(b'mark changeset good')),
887 (b'g', b'good', False, _(b'mark changeset good')),
888 (b'b', b'bad', False, _(b'mark changeset bad')),
888 (b'b', b'bad', False, _(b'mark changeset bad')),
889 (b's', b'skip', False, _(b'skip testing changeset')),
889 (b's', b'skip', False, _(b'skip testing changeset')),
890 (b'e', b'extend', False, _(b'extend the bisect range')),
890 (b'e', b'extend', False, _(b'extend the bisect range')),
891 (
891 (
892 b'c',
892 b'c',
893 b'command',
893 b'command',
894 b'',
894 b'',
895 _(b'use command to check changeset state'),
895 _(b'use command to check changeset state'),
896 _(b'CMD'),
896 _(b'CMD'),
897 ),
897 ),
898 (b'U', b'noupdate', False, _(b'do not update to target')),
898 (b'U', b'noupdate', False, _(b'do not update to target')),
899 ],
899 ],
900 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
900 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
901 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
901 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
902 )
902 )
903 def bisect(
903 def bisect(
904 ui,
904 ui,
905 repo,
905 repo,
906 rev=None,
906 rev=None,
907 extra=None,
907 extra=None,
908 command=None,
908 command=None,
909 reset=None,
909 reset=None,
910 good=None,
910 good=None,
911 bad=None,
911 bad=None,
912 skip=None,
912 skip=None,
913 extend=None,
913 extend=None,
914 noupdate=None,
914 noupdate=None,
915 ):
915 ):
916 """subdivision search of changesets
916 """subdivision search of changesets
917
917
918 This command helps to find changesets which introduce problems. To
918 This command helps to find changesets which introduce problems. To
919 use, mark the earliest changeset you know exhibits the problem as
919 use, mark the earliest changeset you know exhibits the problem as
920 bad, then mark the latest changeset which is free from the problem
920 bad, then mark the latest changeset which is free from the problem
921 as good. Bisect will update your working directory to a revision
921 as good. Bisect will update your working directory to a revision
922 for testing (unless the -U/--noupdate option is specified). Once
922 for testing (unless the -U/--noupdate option is specified). Once
923 you have performed tests, mark the working directory as good or
923 you have performed tests, mark the working directory as good or
924 bad, and bisect will either update to another candidate changeset
924 bad, and bisect will either update to another candidate changeset
925 or announce that it has found the bad revision.
925 or announce that it has found the bad revision.
926
926
927 As a shortcut, you can also use the revision argument to mark a
927 As a shortcut, you can also use the revision argument to mark a
928 revision as good or bad without checking it out first.
928 revision as good or bad without checking it out first.
929
929
930 If you supply a command, it will be used for automatic bisection.
930 If you supply a command, it will be used for automatic bisection.
931 The environment variable HG_NODE will contain the ID of the
931 The environment variable HG_NODE will contain the ID of the
932 changeset being tested. The exit status of the command will be
932 changeset being tested. The exit status of the command will be
933 used to mark revisions as good or bad: status 0 means good, 125
933 used to mark revisions as good or bad: status 0 means good, 125
934 means to skip the revision, 127 (command not found) will abort the
934 means to skip the revision, 127 (command not found) will abort the
935 bisection, and any other non-zero exit status means the revision
935 bisection, and any other non-zero exit status means the revision
936 is bad.
936 is bad.
937
937
938 .. container:: verbose
938 .. container:: verbose
939
939
940 Some examples:
940 Some examples:
941
941
942 - start a bisection with known bad revision 34, and good revision 12::
942 - start a bisection with known bad revision 34, and good revision 12::
943
943
944 hg bisect --bad 34
944 hg bisect --bad 34
945 hg bisect --good 12
945 hg bisect --good 12
946
946
947 - advance the current bisection by marking current revision as good or
947 - advance the current bisection by marking current revision as good or
948 bad::
948 bad::
949
949
950 hg bisect --good
950 hg bisect --good
951 hg bisect --bad
951 hg bisect --bad
952
952
953 - mark the current revision, or a known revision, to be skipped (e.g. if
953 - mark the current revision, or a known revision, to be skipped (e.g. if
954 that revision is not usable because of another issue)::
954 that revision is not usable because of another issue)::
955
955
956 hg bisect --skip
956 hg bisect --skip
957 hg bisect --skip 23
957 hg bisect --skip 23
958
958
959 - skip all revisions that do not touch directories ``foo`` or ``bar``::
959 - skip all revisions that do not touch directories ``foo`` or ``bar``::
960
960
961 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
961 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
962
962
963 - forget the current bisection::
963 - forget the current bisection::
964
964
965 hg bisect --reset
965 hg bisect --reset
966
966
967 - use 'make && make tests' to automatically find the first broken
967 - use 'make && make tests' to automatically find the first broken
968 revision::
968 revision::
969
969
970 hg bisect --reset
970 hg bisect --reset
971 hg bisect --bad 34
971 hg bisect --bad 34
972 hg bisect --good 12
972 hg bisect --good 12
973 hg bisect --command "make && make tests"
973 hg bisect --command "make && make tests"
974
974
975 - see all changesets whose states are already known in the current
975 - see all changesets whose states are already known in the current
976 bisection::
976 bisection::
977
977
978 hg log -r "bisect(pruned)"
978 hg log -r "bisect(pruned)"
979
979
980 - see the changeset currently being bisected (especially useful
980 - see the changeset currently being bisected (especially useful
981 if running with -U/--noupdate)::
981 if running with -U/--noupdate)::
982
982
983 hg log -r "bisect(current)"
983 hg log -r "bisect(current)"
984
984
985 - see all changesets that took part in the current bisection::
985 - see all changesets that took part in the current bisection::
986
986
987 hg log -r "bisect(range)"
987 hg log -r "bisect(range)"
988
988
989 - you can even get a nice graph::
989 - you can even get a nice graph::
990
990
991 hg log --graph -r "bisect(range)"
991 hg log --graph -r "bisect(range)"
992
992
993 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
993 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
994
994
995 Returns 0 on success.
995 Returns 0 on success.
996 """
996 """
997 # backward compatibility
997 # backward compatibility
998 if rev in b"good bad reset init".split():
998 if rev in b"good bad reset init".split():
999 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
999 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1000 cmd, rev, extra = rev, extra, None
1000 cmd, rev, extra = rev, extra, None
1001 if cmd == b"good":
1001 if cmd == b"good":
1002 good = True
1002 good = True
1003 elif cmd == b"bad":
1003 elif cmd == b"bad":
1004 bad = True
1004 bad = True
1005 else:
1005 else:
1006 reset = True
1006 reset = True
1007 elif extra:
1007 elif extra:
1008 raise error.Abort(_(b'incompatible arguments'))
1008 raise error.Abort(_(b'incompatible arguments'))
1009
1009
1010 incompatibles = {
1010 incompatibles = {
1011 b'--bad': bad,
1011 b'--bad': bad,
1012 b'--command': bool(command),
1012 b'--command': bool(command),
1013 b'--extend': extend,
1013 b'--extend': extend,
1014 b'--good': good,
1014 b'--good': good,
1015 b'--reset': reset,
1015 b'--reset': reset,
1016 b'--skip': skip,
1016 b'--skip': skip,
1017 }
1017 }
1018
1018
1019 enabled = [x for x in incompatibles if incompatibles[x]]
1019 enabled = [x for x in incompatibles if incompatibles[x]]
1020
1020
1021 if len(enabled) > 1:
1021 if len(enabled) > 1:
1022 raise error.Abort(
1022 raise error.Abort(
1023 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1023 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1024 )
1024 )
1025
1025
1026 if reset:
1026 if reset:
1027 hbisect.resetstate(repo)
1027 hbisect.resetstate(repo)
1028 return
1028 return
1029
1029
1030 state = hbisect.load_state(repo)
1030 state = hbisect.load_state(repo)
1031
1031
1032 # update state
1032 # update state
1033 if good or bad or skip:
1033 if good or bad or skip:
1034 if rev:
1034 if rev:
1035 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
1035 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
1036 else:
1036 else:
1037 nodes = [repo.lookup(b'.')]
1037 nodes = [repo.lookup(b'.')]
1038 if good:
1038 if good:
1039 state[b'good'] += nodes
1039 state[b'good'] += nodes
1040 elif bad:
1040 elif bad:
1041 state[b'bad'] += nodes
1041 state[b'bad'] += nodes
1042 elif skip:
1042 elif skip:
1043 state[b'skip'] += nodes
1043 state[b'skip'] += nodes
1044 hbisect.save_state(repo, state)
1044 hbisect.save_state(repo, state)
1045 if not (state[b'good'] and state[b'bad']):
1045 if not (state[b'good'] and state[b'bad']):
1046 return
1046 return
1047
1047
1048 def mayupdate(repo, node, show_stats=True):
1048 def mayupdate(repo, node, show_stats=True):
1049 """common used update sequence"""
1049 """common used update sequence"""
1050 if noupdate:
1050 if noupdate:
1051 return
1051 return
1052 cmdutil.checkunfinished(repo)
1052 cmdutil.checkunfinished(repo)
1053 cmdutil.bailifchanged(repo)
1053 cmdutil.bailifchanged(repo)
1054 return hg.clean(repo, node, show_stats=show_stats)
1054 return hg.clean(repo, node, show_stats=show_stats)
1055
1055
1056 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1056 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1057
1057
1058 if command:
1058 if command:
1059 changesets = 1
1059 changesets = 1
1060 if noupdate:
1060 if noupdate:
1061 try:
1061 try:
1062 node = state[b'current'][0]
1062 node = state[b'current'][0]
1063 except LookupError:
1063 except LookupError:
1064 raise error.Abort(
1064 raise error.Abort(
1065 _(
1065 _(
1066 b'current bisect revision is unknown - '
1066 b'current bisect revision is unknown - '
1067 b'start a new bisect to fix'
1067 b'start a new bisect to fix'
1068 )
1068 )
1069 )
1069 )
1070 else:
1070 else:
1071 node, p2 = repo.dirstate.parents()
1071 node, p2 = repo.dirstate.parents()
1072 if p2 != nullid:
1072 if p2 != nullid:
1073 raise error.Abort(_(b'current bisect revision is a merge'))
1073 raise error.Abort(_(b'current bisect revision is a merge'))
1074 if rev:
1074 if rev:
1075 node = repo[scmutil.revsingle(repo, rev, node)].node()
1075 node = repo[scmutil.revsingle(repo, rev, node)].node()
1076 with hbisect.restore_state(repo, state, node):
1076 with hbisect.restore_state(repo, state, node):
1077 while changesets:
1077 while changesets:
1078 # update state
1078 # update state
1079 state[b'current'] = [node]
1079 state[b'current'] = [node]
1080 hbisect.save_state(repo, state)
1080 hbisect.save_state(repo, state)
1081 status = ui.system(
1081 status = ui.system(
1082 command,
1082 command,
1083 environ={b'HG_NODE': hex(node)},
1083 environ={b'HG_NODE': hex(node)},
1084 blockedtag=b'bisect_check',
1084 blockedtag=b'bisect_check',
1085 )
1085 )
1086 if status == 125:
1086 if status == 125:
1087 transition = b"skip"
1087 transition = b"skip"
1088 elif status == 0:
1088 elif status == 0:
1089 transition = b"good"
1089 transition = b"good"
1090 # status < 0 means process was killed
1090 # status < 0 means process was killed
1091 elif status == 127:
1091 elif status == 127:
1092 raise error.Abort(_(b"failed to execute %s") % command)
1092 raise error.Abort(_(b"failed to execute %s") % command)
1093 elif status < 0:
1093 elif status < 0:
1094 raise error.Abort(_(b"%s killed") % command)
1094 raise error.Abort(_(b"%s killed") % command)
1095 else:
1095 else:
1096 transition = b"bad"
1096 transition = b"bad"
1097 state[transition].append(node)
1097 state[transition].append(node)
1098 ctx = repo[node]
1098 ctx = repo[node]
1099 ui.status(
1099 ui.status(
1100 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1100 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1101 )
1101 )
1102 hbisect.checkstate(state)
1102 hbisect.checkstate(state)
1103 # bisect
1103 # bisect
1104 nodes, changesets, bgood = hbisect.bisect(repo, state)
1104 nodes, changesets, bgood = hbisect.bisect(repo, state)
1105 # update to next check
1105 # update to next check
1106 node = nodes[0]
1106 node = nodes[0]
1107 mayupdate(repo, node, show_stats=False)
1107 mayupdate(repo, node, show_stats=False)
1108 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1108 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1109 return
1109 return
1110
1110
1111 hbisect.checkstate(state)
1111 hbisect.checkstate(state)
1112
1112
1113 # actually bisect
1113 # actually bisect
1114 nodes, changesets, good = hbisect.bisect(repo, state)
1114 nodes, changesets, good = hbisect.bisect(repo, state)
1115 if extend:
1115 if extend:
1116 if not changesets:
1116 if not changesets:
1117 extendnode = hbisect.extendrange(repo, state, nodes, good)
1117 extendnode = hbisect.extendrange(repo, state, nodes, good)
1118 if extendnode is not None:
1118 if extendnode is not None:
1119 ui.write(
1119 ui.write(
1120 _(b"Extending search to changeset %d:%s\n")
1120 _(b"Extending search to changeset %d:%s\n")
1121 % (extendnode.rev(), extendnode)
1121 % (extendnode.rev(), extendnode)
1122 )
1122 )
1123 state[b'current'] = [extendnode.node()]
1123 state[b'current'] = [extendnode.node()]
1124 hbisect.save_state(repo, state)
1124 hbisect.save_state(repo, state)
1125 return mayupdate(repo, extendnode.node())
1125 return mayupdate(repo, extendnode.node())
1126 raise error.Abort(_(b"nothing to extend"))
1126 raise error.Abort(_(b"nothing to extend"))
1127
1127
1128 if changesets == 0:
1128 if changesets == 0:
1129 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1129 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1130 else:
1130 else:
1131 assert len(nodes) == 1 # only a single node can be tested next
1131 assert len(nodes) == 1 # only a single node can be tested next
1132 node = nodes[0]
1132 node = nodes[0]
1133 # compute the approximate number of remaining tests
1133 # compute the approximate number of remaining tests
1134 tests, size = 0, 2
1134 tests, size = 0, 2
1135 while size <= changesets:
1135 while size <= changesets:
1136 tests, size = tests + 1, size * 2
1136 tests, size = tests + 1, size * 2
1137 rev = repo.changelog.rev(node)
1137 rev = repo.changelog.rev(node)
1138 ui.write(
1138 ui.write(
1139 _(
1139 _(
1140 b"Testing changeset %d:%s "
1140 b"Testing changeset %d:%s "
1141 b"(%d changesets remaining, ~%d tests)\n"
1141 b"(%d changesets remaining, ~%d tests)\n"
1142 )
1142 )
1143 % (rev, short(node), changesets, tests)
1143 % (rev, short(node), changesets, tests)
1144 )
1144 )
1145 state[b'current'] = [node]
1145 state[b'current'] = [node]
1146 hbisect.save_state(repo, state)
1146 hbisect.save_state(repo, state)
1147 return mayupdate(repo, node)
1147 return mayupdate(repo, node)
1148
1148
1149
1149
1150 @command(
1150 @command(
1151 b'bookmarks|bookmark',
1151 b'bookmarks|bookmark',
1152 [
1152 [
1153 (b'f', b'force', False, _(b'force')),
1153 (b'f', b'force', False, _(b'force')),
1154 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1154 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1155 (b'd', b'delete', False, _(b'delete a given bookmark')),
1155 (b'd', b'delete', False, _(b'delete a given bookmark')),
1156 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1156 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1157 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1157 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1158 (b'l', b'list', False, _(b'list existing bookmarks')),
1158 (b'l', b'list', False, _(b'list existing bookmarks')),
1159 ]
1159 ]
1160 + formatteropts,
1160 + formatteropts,
1161 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1161 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1162 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1162 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1163 )
1163 )
1164 def bookmark(ui, repo, *names, **opts):
1164 def bookmark(ui, repo, *names, **opts):
1165 '''create a new bookmark or list existing bookmarks
1165 '''create a new bookmark or list existing bookmarks
1166
1166
1167 Bookmarks are labels on changesets to help track lines of development.
1167 Bookmarks are labels on changesets to help track lines of development.
1168 Bookmarks are unversioned and can be moved, renamed and deleted.
1168 Bookmarks are unversioned and can be moved, renamed and deleted.
1169 Deleting or moving a bookmark has no effect on the associated changesets.
1169 Deleting or moving a bookmark has no effect on the associated changesets.
1170
1170
1171 Creating or updating to a bookmark causes it to be marked as 'active'.
1171 Creating or updating to a bookmark causes it to be marked as 'active'.
1172 The active bookmark is indicated with a '*'.
1172 The active bookmark is indicated with a '*'.
1173 When a commit is made, the active bookmark will advance to the new commit.
1173 When a commit is made, the active bookmark will advance to the new commit.
1174 A plain :hg:`update` will also advance an active bookmark, if possible.
1174 A plain :hg:`update` will also advance an active bookmark, if possible.
1175 Updating away from a bookmark will cause it to be deactivated.
1175 Updating away from a bookmark will cause it to be deactivated.
1176
1176
1177 Bookmarks can be pushed and pulled between repositories (see
1177 Bookmarks can be pushed and pulled between repositories (see
1178 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1178 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1179 diverged, a new 'divergent bookmark' of the form 'name@path' will
1179 diverged, a new 'divergent bookmark' of the form 'name@path' will
1180 be created. Using :hg:`merge` will resolve the divergence.
1180 be created. Using :hg:`merge` will resolve the divergence.
1181
1181
1182 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1182 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1183 the active bookmark's name.
1183 the active bookmark's name.
1184
1184
1185 A bookmark named '@' has the special property that :hg:`clone` will
1185 A bookmark named '@' has the special property that :hg:`clone` will
1186 check it out by default if it exists.
1186 check it out by default if it exists.
1187
1187
1188 .. container:: verbose
1188 .. container:: verbose
1189
1189
1190 Template:
1190 Template:
1191
1191
1192 The following keywords are supported in addition to the common template
1192 The following keywords are supported in addition to the common template
1193 keywords and functions such as ``{bookmark}``. See also
1193 keywords and functions such as ``{bookmark}``. See also
1194 :hg:`help templates`.
1194 :hg:`help templates`.
1195
1195
1196 :active: Boolean. True if the bookmark is active.
1196 :active: Boolean. True if the bookmark is active.
1197
1197
1198 Examples:
1198 Examples:
1199
1199
1200 - create an active bookmark for a new line of development::
1200 - create an active bookmark for a new line of development::
1201
1201
1202 hg book new-feature
1202 hg book new-feature
1203
1203
1204 - create an inactive bookmark as a place marker::
1204 - create an inactive bookmark as a place marker::
1205
1205
1206 hg book -i reviewed
1206 hg book -i reviewed
1207
1207
1208 - create an inactive bookmark on another changeset::
1208 - create an inactive bookmark on another changeset::
1209
1209
1210 hg book -r .^ tested
1210 hg book -r .^ tested
1211
1211
1212 - rename bookmark turkey to dinner::
1212 - rename bookmark turkey to dinner::
1213
1213
1214 hg book -m turkey dinner
1214 hg book -m turkey dinner
1215
1215
1216 - move the '@' bookmark from another branch::
1216 - move the '@' bookmark from another branch::
1217
1217
1218 hg book -f @
1218 hg book -f @
1219
1219
1220 - print only the active bookmark name::
1220 - print only the active bookmark name::
1221
1221
1222 hg book -ql .
1222 hg book -ql .
1223 '''
1223 '''
1224 opts = pycompat.byteskwargs(opts)
1224 opts = pycompat.byteskwargs(opts)
1225 force = opts.get(b'force')
1225 force = opts.get(b'force')
1226 rev = opts.get(b'rev')
1226 rev = opts.get(b'rev')
1227 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1227 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1228
1228
1229 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1229 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1230 if action:
1230 if action:
1231 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1231 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1232 elif names or rev:
1232 elif names or rev:
1233 action = b'add'
1233 action = b'add'
1234 elif inactive:
1234 elif inactive:
1235 action = b'inactive' # meaning deactivate
1235 action = b'inactive' # meaning deactivate
1236 else:
1236 else:
1237 action = b'list'
1237 action = b'list'
1238
1238
1239 cmdutil.check_incompatible_arguments(
1239 cmdutil.check_incompatible_arguments(
1240 opts, b'inactive', [b'delete', b'list']
1240 opts, b'inactive', [b'delete', b'list']
1241 )
1241 )
1242 if not names and action in {b'add', b'delete'}:
1242 if not names and action in {b'add', b'delete'}:
1243 raise error.Abort(_(b"bookmark name required"))
1243 raise error.Abort(_(b"bookmark name required"))
1244
1244
1245 if action in {b'add', b'delete', b'rename', b'inactive'}:
1245 if action in {b'add', b'delete', b'rename', b'inactive'}:
1246 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1246 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1247 if action == b'delete':
1247 if action == b'delete':
1248 names = pycompat.maplist(repo._bookmarks.expandname, names)
1248 names = pycompat.maplist(repo._bookmarks.expandname, names)
1249 bookmarks.delete(repo, tr, names)
1249 bookmarks.delete(repo, tr, names)
1250 elif action == b'rename':
1250 elif action == b'rename':
1251 if not names:
1251 if not names:
1252 raise error.Abort(_(b"new bookmark name required"))
1252 raise error.Abort(_(b"new bookmark name required"))
1253 elif len(names) > 1:
1253 elif len(names) > 1:
1254 raise error.Abort(_(b"only one new bookmark name allowed"))
1254 raise error.Abort(_(b"only one new bookmark name allowed"))
1255 oldname = repo._bookmarks.expandname(opts[b'rename'])
1255 oldname = repo._bookmarks.expandname(opts[b'rename'])
1256 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1256 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1257 elif action == b'add':
1257 elif action == b'add':
1258 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1258 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1259 elif action == b'inactive':
1259 elif action == b'inactive':
1260 if len(repo._bookmarks) == 0:
1260 if len(repo._bookmarks) == 0:
1261 ui.status(_(b"no bookmarks set\n"))
1261 ui.status(_(b"no bookmarks set\n"))
1262 elif not repo._activebookmark:
1262 elif not repo._activebookmark:
1263 ui.status(_(b"no active bookmark\n"))
1263 ui.status(_(b"no active bookmark\n"))
1264 else:
1264 else:
1265 bookmarks.deactivate(repo)
1265 bookmarks.deactivate(repo)
1266 elif action == b'list':
1266 elif action == b'list':
1267 names = pycompat.maplist(repo._bookmarks.expandname, names)
1267 names = pycompat.maplist(repo._bookmarks.expandname, names)
1268 with ui.formatter(b'bookmarks', opts) as fm:
1268 with ui.formatter(b'bookmarks', opts) as fm:
1269 bookmarks.printbookmarks(ui, repo, fm, names)
1269 bookmarks.printbookmarks(ui, repo, fm, names)
1270 else:
1270 else:
1271 raise error.ProgrammingError(b'invalid action: %s' % action)
1271 raise error.ProgrammingError(b'invalid action: %s' % action)
1272
1272
1273
1273
1274 @command(
1274 @command(
1275 b'branch',
1275 b'branch',
1276 [
1276 [
1277 (
1277 (
1278 b'f',
1278 b'f',
1279 b'force',
1279 b'force',
1280 None,
1280 None,
1281 _(b'set branch name even if it shadows an existing branch'),
1281 _(b'set branch name even if it shadows an existing branch'),
1282 ),
1282 ),
1283 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1283 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1284 (
1284 (
1285 b'r',
1285 b'r',
1286 b'rev',
1286 b'rev',
1287 [],
1287 [],
1288 _(b'change branches of the given revs (EXPERIMENTAL)'),
1288 _(b'change branches of the given revs (EXPERIMENTAL)'),
1289 ),
1289 ),
1290 ],
1290 ],
1291 _(b'[-fC] [NAME]'),
1291 _(b'[-fC] [NAME]'),
1292 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1292 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1293 )
1293 )
1294 def branch(ui, repo, label=None, **opts):
1294 def branch(ui, repo, label=None, **opts):
1295 """set or show the current branch name
1295 """set or show the current branch name
1296
1296
1297 .. note::
1297 .. note::
1298
1298
1299 Branch names are permanent and global. Use :hg:`bookmark` to create a
1299 Branch names are permanent and global. Use :hg:`bookmark` to create a
1300 light-weight bookmark instead. See :hg:`help glossary` for more
1300 light-weight bookmark instead. See :hg:`help glossary` for more
1301 information about named branches and bookmarks.
1301 information about named branches and bookmarks.
1302
1302
1303 With no argument, show the current branch name. With one argument,
1303 With no argument, show the current branch name. With one argument,
1304 set the working directory branch name (the branch will not exist
1304 set the working directory branch name (the branch will not exist
1305 in the repository until the next commit). Standard practice
1305 in the repository until the next commit). Standard practice
1306 recommends that primary development take place on the 'default'
1306 recommends that primary development take place on the 'default'
1307 branch.
1307 branch.
1308
1308
1309 Unless -f/--force is specified, branch will not let you set a
1309 Unless -f/--force is specified, branch will not let you set a
1310 branch name that already exists.
1310 branch name that already exists.
1311
1311
1312 Use -C/--clean to reset the working directory branch to that of
1312 Use -C/--clean to reset the working directory branch to that of
1313 the parent of the working directory, negating a previous branch
1313 the parent of the working directory, negating a previous branch
1314 change.
1314 change.
1315
1315
1316 Use the command :hg:`update` to switch to an existing branch. Use
1316 Use the command :hg:`update` to switch to an existing branch. Use
1317 :hg:`commit --close-branch` to mark this branch head as closed.
1317 :hg:`commit --close-branch` to mark this branch head as closed.
1318 When all heads of a branch are closed, the branch will be
1318 When all heads of a branch are closed, the branch will be
1319 considered closed.
1319 considered closed.
1320
1320
1321 Returns 0 on success.
1321 Returns 0 on success.
1322 """
1322 """
1323 opts = pycompat.byteskwargs(opts)
1323 opts = pycompat.byteskwargs(opts)
1324 revs = opts.get(b'rev')
1324 revs = opts.get(b'rev')
1325 if label:
1325 if label:
1326 label = label.strip()
1326 label = label.strip()
1327
1327
1328 if not opts.get(b'clean') and not label:
1328 if not opts.get(b'clean') and not label:
1329 if revs:
1329 if revs:
1330 raise error.Abort(_(b"no branch name specified for the revisions"))
1330 raise error.Abort(_(b"no branch name specified for the revisions"))
1331 ui.write(b"%s\n" % repo.dirstate.branch())
1331 ui.write(b"%s\n" % repo.dirstate.branch())
1332 return
1332 return
1333
1333
1334 with repo.wlock():
1334 with repo.wlock():
1335 if opts.get(b'clean'):
1335 if opts.get(b'clean'):
1336 label = repo[b'.'].branch()
1336 label = repo[b'.'].branch()
1337 repo.dirstate.setbranch(label)
1337 repo.dirstate.setbranch(label)
1338 ui.status(_(b'reset working directory to branch %s\n') % label)
1338 ui.status(_(b'reset working directory to branch %s\n') % label)
1339 elif label:
1339 elif label:
1340
1340
1341 scmutil.checknewlabel(repo, label, b'branch')
1341 scmutil.checknewlabel(repo, label, b'branch')
1342 if revs:
1342 if revs:
1343 return cmdutil.changebranch(ui, repo, revs, label, opts)
1343 return cmdutil.changebranch(ui, repo, revs, label, opts)
1344
1344
1345 if not opts.get(b'force') and label in repo.branchmap():
1345 if not opts.get(b'force') and label in repo.branchmap():
1346 if label not in [p.branch() for p in repo[None].parents()]:
1346 if label not in [p.branch() for p in repo[None].parents()]:
1347 raise error.Abort(
1347 raise error.Abort(
1348 _(b'a branch of the same name already exists'),
1348 _(b'a branch of the same name already exists'),
1349 # i18n: "it" refers to an existing branch
1349 # i18n: "it" refers to an existing branch
1350 hint=_(b"use 'hg update' to switch to it"),
1350 hint=_(b"use 'hg update' to switch to it"),
1351 )
1351 )
1352
1352
1353 repo.dirstate.setbranch(label)
1353 repo.dirstate.setbranch(label)
1354 ui.status(_(b'marked working directory as branch %s\n') % label)
1354 ui.status(_(b'marked working directory as branch %s\n') % label)
1355
1355
1356 # find any open named branches aside from default
1356 # find any open named branches aside from default
1357 for n, h, t, c in repo.branchmap().iterbranches():
1357 for n, h, t, c in repo.branchmap().iterbranches():
1358 if n != b"default" and not c:
1358 if n != b"default" and not c:
1359 return 0
1359 return 0
1360 ui.status(
1360 ui.status(
1361 _(
1361 _(
1362 b'(branches are permanent and global, '
1362 b'(branches are permanent and global, '
1363 b'did you want a bookmark?)\n'
1363 b'did you want a bookmark?)\n'
1364 )
1364 )
1365 )
1365 )
1366
1366
1367
1367
1368 @command(
1368 @command(
1369 b'branches',
1369 b'branches',
1370 [
1370 [
1371 (
1371 (
1372 b'a',
1372 b'a',
1373 b'active',
1373 b'active',
1374 False,
1374 False,
1375 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1375 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1376 ),
1376 ),
1377 (b'c', b'closed', False, _(b'show normal and closed branches')),
1377 (b'c', b'closed', False, _(b'show normal and closed branches')),
1378 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1378 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1379 ]
1379 ]
1380 + formatteropts,
1380 + formatteropts,
1381 _(b'[-c]'),
1381 _(b'[-c]'),
1382 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1382 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1383 intents={INTENT_READONLY},
1383 intents={INTENT_READONLY},
1384 )
1384 )
1385 def branches(ui, repo, active=False, closed=False, **opts):
1385 def branches(ui, repo, active=False, closed=False, **opts):
1386 """list repository named branches
1386 """list repository named branches
1387
1387
1388 List the repository's named branches, indicating which ones are
1388 List the repository's named branches, indicating which ones are
1389 inactive. If -c/--closed is specified, also list branches which have
1389 inactive. If -c/--closed is specified, also list branches which have
1390 been marked closed (see :hg:`commit --close-branch`).
1390 been marked closed (see :hg:`commit --close-branch`).
1391
1391
1392 Use the command :hg:`update` to switch to an existing branch.
1392 Use the command :hg:`update` to switch to an existing branch.
1393
1393
1394 .. container:: verbose
1394 .. container:: verbose
1395
1395
1396 Template:
1396 Template:
1397
1397
1398 The following keywords are supported in addition to the common template
1398 The following keywords are supported in addition to the common template
1399 keywords and functions such as ``{branch}``. See also
1399 keywords and functions such as ``{branch}``. See also
1400 :hg:`help templates`.
1400 :hg:`help templates`.
1401
1401
1402 :active: Boolean. True if the branch is active.
1402 :active: Boolean. True if the branch is active.
1403 :closed: Boolean. True if the branch is closed.
1403 :closed: Boolean. True if the branch is closed.
1404 :current: Boolean. True if it is the current branch.
1404 :current: Boolean. True if it is the current branch.
1405
1405
1406 Returns 0.
1406 Returns 0.
1407 """
1407 """
1408
1408
1409 opts = pycompat.byteskwargs(opts)
1409 opts = pycompat.byteskwargs(opts)
1410 revs = opts.get(b'rev')
1410 revs = opts.get(b'rev')
1411 selectedbranches = None
1411 selectedbranches = None
1412 if revs:
1412 if revs:
1413 revs = scmutil.revrange(repo, revs)
1413 revs = scmutil.revrange(repo, revs)
1414 getbi = repo.revbranchcache().branchinfo
1414 getbi = repo.revbranchcache().branchinfo
1415 selectedbranches = {getbi(r)[0] for r in revs}
1415 selectedbranches = {getbi(r)[0] for r in revs}
1416
1416
1417 ui.pager(b'branches')
1417 ui.pager(b'branches')
1418 fm = ui.formatter(b'branches', opts)
1418 fm = ui.formatter(b'branches', opts)
1419 hexfunc = fm.hexfunc
1419 hexfunc = fm.hexfunc
1420
1420
1421 allheads = set(repo.heads())
1421 allheads = set(repo.heads())
1422 branches = []
1422 branches = []
1423 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1423 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1424 if selectedbranches is not None and tag not in selectedbranches:
1424 if selectedbranches is not None and tag not in selectedbranches:
1425 continue
1425 continue
1426 isactive = False
1426 isactive = False
1427 if not isclosed:
1427 if not isclosed:
1428 openheads = set(repo.branchmap().iteropen(heads))
1428 openheads = set(repo.branchmap().iteropen(heads))
1429 isactive = bool(openheads & allheads)
1429 isactive = bool(openheads & allheads)
1430 branches.append((tag, repo[tip], isactive, not isclosed))
1430 branches.append((tag, repo[tip], isactive, not isclosed))
1431 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1431 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1432
1432
1433 for tag, ctx, isactive, isopen in branches:
1433 for tag, ctx, isactive, isopen in branches:
1434 if active and not isactive:
1434 if active and not isactive:
1435 continue
1435 continue
1436 if isactive:
1436 if isactive:
1437 label = b'branches.active'
1437 label = b'branches.active'
1438 notice = b''
1438 notice = b''
1439 elif not isopen:
1439 elif not isopen:
1440 if not closed:
1440 if not closed:
1441 continue
1441 continue
1442 label = b'branches.closed'
1442 label = b'branches.closed'
1443 notice = _(b' (closed)')
1443 notice = _(b' (closed)')
1444 else:
1444 else:
1445 label = b'branches.inactive'
1445 label = b'branches.inactive'
1446 notice = _(b' (inactive)')
1446 notice = _(b' (inactive)')
1447 current = tag == repo.dirstate.branch()
1447 current = tag == repo.dirstate.branch()
1448 if current:
1448 if current:
1449 label = b'branches.current'
1449 label = b'branches.current'
1450
1450
1451 fm.startitem()
1451 fm.startitem()
1452 fm.write(b'branch', b'%s', tag, label=label)
1452 fm.write(b'branch', b'%s', tag, label=label)
1453 rev = ctx.rev()
1453 rev = ctx.rev()
1454 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1454 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1455 fmt = b' ' * padsize + b' %d:%s'
1455 fmt = b' ' * padsize + b' %d:%s'
1456 fm.condwrite(
1456 fm.condwrite(
1457 not ui.quiet,
1457 not ui.quiet,
1458 b'rev node',
1458 b'rev node',
1459 fmt,
1459 fmt,
1460 rev,
1460 rev,
1461 hexfunc(ctx.node()),
1461 hexfunc(ctx.node()),
1462 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1462 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1463 )
1463 )
1464 fm.context(ctx=ctx)
1464 fm.context(ctx=ctx)
1465 fm.data(active=isactive, closed=not isopen, current=current)
1465 fm.data(active=isactive, closed=not isopen, current=current)
1466 if not ui.quiet:
1466 if not ui.quiet:
1467 fm.plain(notice)
1467 fm.plain(notice)
1468 fm.plain(b'\n')
1468 fm.plain(b'\n')
1469 fm.end()
1469 fm.end()
1470
1470
1471
1471
1472 @command(
1472 @command(
1473 b'bundle',
1473 b'bundle',
1474 [
1474 [
1475 (
1475 (
1476 b'f',
1476 b'f',
1477 b'force',
1477 b'force',
1478 None,
1478 None,
1479 _(b'run even when the destination is unrelated'),
1479 _(b'run even when the destination is unrelated'),
1480 ),
1480 ),
1481 (
1481 (
1482 b'r',
1482 b'r',
1483 b'rev',
1483 b'rev',
1484 [],
1484 [],
1485 _(b'a changeset intended to be added to the destination'),
1485 _(b'a changeset intended to be added to the destination'),
1486 _(b'REV'),
1486 _(b'REV'),
1487 ),
1487 ),
1488 (
1488 (
1489 b'b',
1489 b'b',
1490 b'branch',
1490 b'branch',
1491 [],
1491 [],
1492 _(b'a specific branch you would like to bundle'),
1492 _(b'a specific branch you would like to bundle'),
1493 _(b'BRANCH'),
1493 _(b'BRANCH'),
1494 ),
1494 ),
1495 (
1495 (
1496 b'',
1496 b'',
1497 b'base',
1497 b'base',
1498 [],
1498 [],
1499 _(b'a base changeset assumed to be available at the destination'),
1499 _(b'a base changeset assumed to be available at the destination'),
1500 _(b'REV'),
1500 _(b'REV'),
1501 ),
1501 ),
1502 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1502 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1503 (
1503 (
1504 b't',
1504 b't',
1505 b'type',
1505 b'type',
1506 b'bzip2',
1506 b'bzip2',
1507 _(b'bundle compression type to use'),
1507 _(b'bundle compression type to use'),
1508 _(b'TYPE'),
1508 _(b'TYPE'),
1509 ),
1509 ),
1510 ]
1510 ]
1511 + remoteopts,
1511 + remoteopts,
1512 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1512 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1513 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1513 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1514 )
1514 )
1515 def bundle(ui, repo, fname, dest=None, **opts):
1515 def bundle(ui, repo, fname, dest=None, **opts):
1516 """create a bundle file
1516 """create a bundle file
1517
1517
1518 Generate a bundle file containing data to be transferred to another
1518 Generate a bundle file containing data to be transferred to another
1519 repository.
1519 repository.
1520
1520
1521 To create a bundle containing all changesets, use -a/--all
1521 To create a bundle containing all changesets, use -a/--all
1522 (or --base null). Otherwise, hg assumes the destination will have
1522 (or --base null). Otherwise, hg assumes the destination will have
1523 all the nodes you specify with --base parameters. Otherwise, hg
1523 all the nodes you specify with --base parameters. Otherwise, hg
1524 will assume the repository has all the nodes in destination, or
1524 will assume the repository has all the nodes in destination, or
1525 default-push/default if no destination is specified, where destination
1525 default-push/default if no destination is specified, where destination
1526 is the repository you provide through DEST option.
1526 is the repository you provide through DEST option.
1527
1527
1528 You can change bundle format with the -t/--type option. See
1528 You can change bundle format with the -t/--type option. See
1529 :hg:`help bundlespec` for documentation on this format. By default,
1529 :hg:`help bundlespec` for documentation on this format. By default,
1530 the most appropriate format is used and compression defaults to
1530 the most appropriate format is used and compression defaults to
1531 bzip2.
1531 bzip2.
1532
1532
1533 The bundle file can then be transferred using conventional means
1533 The bundle file can then be transferred using conventional means
1534 and applied to another repository with the unbundle or pull
1534 and applied to another repository with the unbundle or pull
1535 command. This is useful when direct push and pull are not
1535 command. This is useful when direct push and pull are not
1536 available or when exporting an entire repository is undesirable.
1536 available or when exporting an entire repository is undesirable.
1537
1537
1538 Applying bundles preserves all changeset contents including
1538 Applying bundles preserves all changeset contents including
1539 permissions, copy/rename information, and revision history.
1539 permissions, copy/rename information, and revision history.
1540
1540
1541 Returns 0 on success, 1 if no changes found.
1541 Returns 0 on success, 1 if no changes found.
1542 """
1542 """
1543 opts = pycompat.byteskwargs(opts)
1543 opts = pycompat.byteskwargs(opts)
1544 revs = None
1544 revs = None
1545 if b'rev' in opts:
1545 if b'rev' in opts:
1546 revstrings = opts[b'rev']
1546 revstrings = opts[b'rev']
1547 revs = scmutil.revrange(repo, revstrings)
1547 revs = scmutil.revrange(repo, revstrings)
1548 if revstrings and not revs:
1548 if revstrings and not revs:
1549 raise error.Abort(_(b'no commits to bundle'))
1549 raise error.Abort(_(b'no commits to bundle'))
1550
1550
1551 bundletype = opts.get(b'type', b'bzip2').lower()
1551 bundletype = opts.get(b'type', b'bzip2').lower()
1552 try:
1552 try:
1553 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1553 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1554 except error.UnsupportedBundleSpecification as e:
1554 except error.UnsupportedBundleSpecification as e:
1555 raise error.Abort(
1555 raise error.Abort(
1556 pycompat.bytestr(e),
1556 pycompat.bytestr(e),
1557 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1557 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1558 )
1558 )
1559 cgversion = bundlespec.contentopts[b"cg.version"]
1559 cgversion = bundlespec.contentopts[b"cg.version"]
1560
1560
1561 # Packed bundles are a pseudo bundle format for now.
1561 # Packed bundles are a pseudo bundle format for now.
1562 if cgversion == b's1':
1562 if cgversion == b's1':
1563 raise error.Abort(
1563 raise error.Abort(
1564 _(b'packed bundles cannot be produced by "hg bundle"'),
1564 _(b'packed bundles cannot be produced by "hg bundle"'),
1565 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1565 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1566 )
1566 )
1567
1567
1568 if opts.get(b'all'):
1568 if opts.get(b'all'):
1569 if dest:
1569 if dest:
1570 raise error.Abort(
1570 raise error.Abort(
1571 _(b"--all is incompatible with specifying a destination")
1571 _(b"--all is incompatible with specifying a destination")
1572 )
1572 )
1573 if opts.get(b'base'):
1573 if opts.get(b'base'):
1574 ui.warn(_(b"ignoring --base because --all was specified\n"))
1574 ui.warn(_(b"ignoring --base because --all was specified\n"))
1575 base = [nullrev]
1575 base = [nullrev]
1576 else:
1576 else:
1577 base = scmutil.revrange(repo, opts.get(b'base'))
1577 base = scmutil.revrange(repo, opts.get(b'base'))
1578 if cgversion not in changegroup.supportedoutgoingversions(repo):
1578 if cgversion not in changegroup.supportedoutgoingversions(repo):
1579 raise error.Abort(
1579 raise error.Abort(
1580 _(b"repository does not support bundle version %s") % cgversion
1580 _(b"repository does not support bundle version %s") % cgversion
1581 )
1581 )
1582
1582
1583 if base:
1583 if base:
1584 if dest:
1584 if dest:
1585 raise error.Abort(
1585 raise error.Abort(
1586 _(b"--base is incompatible with specifying a destination")
1586 _(b"--base is incompatible with specifying a destination")
1587 )
1587 )
1588 common = [repo[rev].node() for rev in base]
1588 common = [repo[rev].node() for rev in base]
1589 heads = [repo[r].node() for r in revs] if revs else None
1589 heads = [repo[r].node() for r in revs] if revs else None
1590 outgoing = discovery.outgoing(repo, common, heads)
1590 outgoing = discovery.outgoing(repo, common, heads)
1591 else:
1591 else:
1592 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1592 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1593 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1593 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1594 other = hg.peer(repo, opts, dest)
1594 other = hg.peer(repo, opts, dest)
1595 revs = [repo[r].hex() for r in revs]
1595 revs = [repo[r].hex() for r in revs]
1596 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1596 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1597 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1597 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1598 outgoing = discovery.findcommonoutgoing(
1598 outgoing = discovery.findcommonoutgoing(
1599 repo,
1599 repo,
1600 other,
1600 other,
1601 onlyheads=heads,
1601 onlyheads=heads,
1602 force=opts.get(b'force'),
1602 force=opts.get(b'force'),
1603 portable=True,
1603 portable=True,
1604 )
1604 )
1605
1605
1606 if not outgoing.missing:
1606 if not outgoing.missing:
1607 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1607 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1608 return 1
1608 return 1
1609
1609
1610 if cgversion == b'01': # bundle1
1610 if cgversion == b'01': # bundle1
1611 bversion = b'HG10' + bundlespec.wirecompression
1611 bversion = b'HG10' + bundlespec.wirecompression
1612 bcompression = None
1612 bcompression = None
1613 elif cgversion in (b'02', b'03'):
1613 elif cgversion in (b'02', b'03'):
1614 bversion = b'HG20'
1614 bversion = b'HG20'
1615 bcompression = bundlespec.wirecompression
1615 bcompression = bundlespec.wirecompression
1616 else:
1616 else:
1617 raise error.ProgrammingError(
1617 raise error.ProgrammingError(
1618 b'bundle: unexpected changegroup version %s' % cgversion
1618 b'bundle: unexpected changegroup version %s' % cgversion
1619 )
1619 )
1620
1620
1621 # TODO compression options should be derived from bundlespec parsing.
1621 # TODO compression options should be derived from bundlespec parsing.
1622 # This is a temporary hack to allow adjusting bundle compression
1622 # This is a temporary hack to allow adjusting bundle compression
1623 # level without a) formalizing the bundlespec changes to declare it
1623 # level without a) formalizing the bundlespec changes to declare it
1624 # b) introducing a command flag.
1624 # b) introducing a command flag.
1625 compopts = {}
1625 compopts = {}
1626 complevel = ui.configint(
1626 complevel = ui.configint(
1627 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1627 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1628 )
1628 )
1629 if complevel is None:
1629 if complevel is None:
1630 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1630 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1631 if complevel is not None:
1631 if complevel is not None:
1632 compopts[b'level'] = complevel
1632 compopts[b'level'] = complevel
1633
1633
1634 # Allow overriding the bundling of obsmarker in phases through
1634 # Allow overriding the bundling of obsmarker in phases through
1635 # configuration while we don't have a bundle version that include them
1635 # configuration while we don't have a bundle version that include them
1636 if repo.ui.configbool(b'experimental', b'evolution.bundle-obsmarker'):
1636 if repo.ui.configbool(b'experimental', b'evolution.bundle-obsmarker'):
1637 bundlespec.contentopts[b'obsolescence'] = True
1637 bundlespec.contentopts[b'obsolescence'] = True
1638 if repo.ui.configbool(b'experimental', b'bundle-phases'):
1638 if repo.ui.configbool(b'experimental', b'bundle-phases'):
1639 bundlespec.contentopts[b'phases'] = True
1639 bundlespec.contentopts[b'phases'] = True
1640
1640
1641 bundle2.writenewbundle(
1641 bundle2.writenewbundle(
1642 ui,
1642 ui,
1643 repo,
1643 repo,
1644 b'bundle',
1644 b'bundle',
1645 fname,
1645 fname,
1646 bversion,
1646 bversion,
1647 outgoing,
1647 outgoing,
1648 bundlespec.contentopts,
1648 bundlespec.contentopts,
1649 compression=bcompression,
1649 compression=bcompression,
1650 compopts=compopts,
1650 compopts=compopts,
1651 )
1651 )
1652
1652
1653
1653
1654 @command(
1654 @command(
1655 b'cat',
1655 b'cat',
1656 [
1656 [
1657 (
1657 (
1658 b'o',
1658 b'o',
1659 b'output',
1659 b'output',
1660 b'',
1660 b'',
1661 _(b'print output to file with formatted name'),
1661 _(b'print output to file with formatted name'),
1662 _(b'FORMAT'),
1662 _(b'FORMAT'),
1663 ),
1663 ),
1664 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1664 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1665 (b'', b'decode', None, _(b'apply any matching decode filter')),
1665 (b'', b'decode', None, _(b'apply any matching decode filter')),
1666 ]
1666 ]
1667 + walkopts
1667 + walkopts
1668 + formatteropts,
1668 + formatteropts,
1669 _(b'[OPTION]... FILE...'),
1669 _(b'[OPTION]... FILE...'),
1670 helpcategory=command.CATEGORY_FILE_CONTENTS,
1670 helpcategory=command.CATEGORY_FILE_CONTENTS,
1671 inferrepo=True,
1671 inferrepo=True,
1672 intents={INTENT_READONLY},
1672 intents={INTENT_READONLY},
1673 )
1673 )
1674 def cat(ui, repo, file1, *pats, **opts):
1674 def cat(ui, repo, file1, *pats, **opts):
1675 """output the current or given revision of files
1675 """output the current or given revision of files
1676
1676
1677 Print the specified files as they were at the given revision. If
1677 Print the specified files as they were at the given revision. If
1678 no revision is given, the parent of the working directory is used.
1678 no revision is given, the parent of the working directory is used.
1679
1679
1680 Output may be to a file, in which case the name of the file is
1680 Output may be to a file, in which case the name of the file is
1681 given using a template string. See :hg:`help templates`. In addition
1681 given using a template string. See :hg:`help templates`. In addition
1682 to the common template keywords, the following formatting rules are
1682 to the common template keywords, the following formatting rules are
1683 supported:
1683 supported:
1684
1684
1685 :``%%``: literal "%" character
1685 :``%%``: literal "%" character
1686 :``%s``: basename of file being printed
1686 :``%s``: basename of file being printed
1687 :``%d``: dirname of file being printed, or '.' if in repository root
1687 :``%d``: dirname of file being printed, or '.' if in repository root
1688 :``%p``: root-relative path name of file being printed
1688 :``%p``: root-relative path name of file being printed
1689 :``%H``: changeset hash (40 hexadecimal digits)
1689 :``%H``: changeset hash (40 hexadecimal digits)
1690 :``%R``: changeset revision number
1690 :``%R``: changeset revision number
1691 :``%h``: short-form changeset hash (12 hexadecimal digits)
1691 :``%h``: short-form changeset hash (12 hexadecimal digits)
1692 :``%r``: zero-padded changeset revision number
1692 :``%r``: zero-padded changeset revision number
1693 :``%b``: basename of the exporting repository
1693 :``%b``: basename of the exporting repository
1694 :``\\``: literal "\\" character
1694 :``\\``: literal "\\" character
1695
1695
1696 .. container:: verbose
1696 .. container:: verbose
1697
1697
1698 Template:
1698 Template:
1699
1699
1700 The following keywords are supported in addition to the common template
1700 The following keywords are supported in addition to the common template
1701 keywords and functions. See also :hg:`help templates`.
1701 keywords and functions. See also :hg:`help templates`.
1702
1702
1703 :data: String. File content.
1703 :data: String. File content.
1704 :path: String. Repository-absolute path of the file.
1704 :path: String. Repository-absolute path of the file.
1705
1705
1706 Returns 0 on success.
1706 Returns 0 on success.
1707 """
1707 """
1708 opts = pycompat.byteskwargs(opts)
1708 opts = pycompat.byteskwargs(opts)
1709 rev = opts.get(b'rev')
1709 rev = opts.get(b'rev')
1710 if rev:
1710 if rev:
1711 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1711 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1712 ctx = scmutil.revsingle(repo, rev)
1712 ctx = scmutil.revsingle(repo, rev)
1713 m = scmutil.match(ctx, (file1,) + pats, opts)
1713 m = scmutil.match(ctx, (file1,) + pats, opts)
1714 fntemplate = opts.pop(b'output', b'')
1714 fntemplate = opts.pop(b'output', b'')
1715 if cmdutil.isstdiofilename(fntemplate):
1715 if cmdutil.isstdiofilename(fntemplate):
1716 fntemplate = b''
1716 fntemplate = b''
1717
1717
1718 if fntemplate:
1718 if fntemplate:
1719 fm = formatter.nullformatter(ui, b'cat', opts)
1719 fm = formatter.nullformatter(ui, b'cat', opts)
1720 else:
1720 else:
1721 ui.pager(b'cat')
1721 ui.pager(b'cat')
1722 fm = ui.formatter(b'cat', opts)
1722 fm = ui.formatter(b'cat', opts)
1723 with fm:
1723 with fm:
1724 return cmdutil.cat(
1724 return cmdutil.cat(
1725 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1725 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1726 )
1726 )
1727
1727
1728
1728
1729 @command(
1729 @command(
1730 b'clone',
1730 b'clone',
1731 [
1731 [
1732 (
1732 (
1733 b'U',
1733 b'U',
1734 b'noupdate',
1734 b'noupdate',
1735 None,
1735 None,
1736 _(
1736 _(
1737 b'the clone will include an empty working '
1737 b'the clone will include an empty working '
1738 b'directory (only a repository)'
1738 b'directory (only a repository)'
1739 ),
1739 ),
1740 ),
1740 ),
1741 (
1741 (
1742 b'u',
1742 b'u',
1743 b'updaterev',
1743 b'updaterev',
1744 b'',
1744 b'',
1745 _(b'revision, tag, or branch to check out'),
1745 _(b'revision, tag, or branch to check out'),
1746 _(b'REV'),
1746 _(b'REV'),
1747 ),
1747 ),
1748 (
1748 (
1749 b'r',
1749 b'r',
1750 b'rev',
1750 b'rev',
1751 [],
1751 [],
1752 _(
1752 _(
1753 b'do not clone everything, but include this changeset'
1753 b'do not clone everything, but include this changeset'
1754 b' and its ancestors'
1754 b' and its ancestors'
1755 ),
1755 ),
1756 _(b'REV'),
1756 _(b'REV'),
1757 ),
1757 ),
1758 (
1758 (
1759 b'b',
1759 b'b',
1760 b'branch',
1760 b'branch',
1761 [],
1761 [],
1762 _(
1762 _(
1763 b'do not clone everything, but include this branch\'s'
1763 b'do not clone everything, but include this branch\'s'
1764 b' changesets and their ancestors'
1764 b' changesets and their ancestors'
1765 ),
1765 ),
1766 _(b'BRANCH'),
1766 _(b'BRANCH'),
1767 ),
1767 ),
1768 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1768 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1769 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1769 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1770 (b'', b'stream', None, _(b'clone with minimal data processing')),
1770 (b'', b'stream', None, _(b'clone with minimal data processing')),
1771 ]
1771 ]
1772 + remoteopts,
1772 + remoteopts,
1773 _(b'[OPTION]... SOURCE [DEST]'),
1773 _(b'[OPTION]... SOURCE [DEST]'),
1774 helpcategory=command.CATEGORY_REPO_CREATION,
1774 helpcategory=command.CATEGORY_REPO_CREATION,
1775 helpbasic=True,
1775 helpbasic=True,
1776 norepo=True,
1776 norepo=True,
1777 )
1777 )
1778 def clone(ui, source, dest=None, **opts):
1778 def clone(ui, source, dest=None, **opts):
1779 """make a copy of an existing repository
1779 """make a copy of an existing repository
1780
1780
1781 Create a copy of an existing repository in a new directory.
1781 Create a copy of an existing repository in a new directory.
1782
1782
1783 If no destination directory name is specified, it defaults to the
1783 If no destination directory name is specified, it defaults to the
1784 basename of the source.
1784 basename of the source.
1785
1785
1786 The location of the source is added to the new repository's
1786 The location of the source is added to the new repository's
1787 ``.hg/hgrc`` file, as the default to be used for future pulls.
1787 ``.hg/hgrc`` file, as the default to be used for future pulls.
1788
1788
1789 Only local paths and ``ssh://`` URLs are supported as
1789 Only local paths and ``ssh://`` URLs are supported as
1790 destinations. For ``ssh://`` destinations, no working directory or
1790 destinations. For ``ssh://`` destinations, no working directory or
1791 ``.hg/hgrc`` will be created on the remote side.
1791 ``.hg/hgrc`` will be created on the remote side.
1792
1792
1793 If the source repository has a bookmark called '@' set, that
1793 If the source repository has a bookmark called '@' set, that
1794 revision will be checked out in the new repository by default.
1794 revision will be checked out in the new repository by default.
1795
1795
1796 To check out a particular version, use -u/--update, or
1796 To check out a particular version, use -u/--update, or
1797 -U/--noupdate to create a clone with no working directory.
1797 -U/--noupdate to create a clone with no working directory.
1798
1798
1799 To pull only a subset of changesets, specify one or more revisions
1799 To pull only a subset of changesets, specify one or more revisions
1800 identifiers with -r/--rev or branches with -b/--branch. The
1800 identifiers with -r/--rev or branches with -b/--branch. The
1801 resulting clone will contain only the specified changesets and
1801 resulting clone will contain only the specified changesets and
1802 their ancestors. These options (or 'clone src#rev dest') imply
1802 their ancestors. These options (or 'clone src#rev dest') imply
1803 --pull, even for local source repositories.
1803 --pull, even for local source repositories.
1804
1804
1805 In normal clone mode, the remote normalizes repository data into a common
1805 In normal clone mode, the remote normalizes repository data into a common
1806 exchange format and the receiving end translates this data into its local
1806 exchange format and the receiving end translates this data into its local
1807 storage format. --stream activates a different clone mode that essentially
1807 storage format. --stream activates a different clone mode that essentially
1808 copies repository files from the remote with minimal data processing. This
1808 copies repository files from the remote with minimal data processing. This
1809 significantly reduces the CPU cost of a clone both remotely and locally.
1809 significantly reduces the CPU cost of a clone both remotely and locally.
1810 However, it often increases the transferred data size by 30-40%. This can
1810 However, it often increases the transferred data size by 30-40%. This can
1811 result in substantially faster clones where I/O throughput is plentiful,
1811 result in substantially faster clones where I/O throughput is plentiful,
1812 especially for larger repositories. A side-effect of --stream clones is
1812 especially for larger repositories. A side-effect of --stream clones is
1813 that storage settings and requirements on the remote are applied locally:
1813 that storage settings and requirements on the remote are applied locally:
1814 a modern client may inherit legacy or inefficient storage used by the
1814 a modern client may inherit legacy or inefficient storage used by the
1815 remote or a legacy Mercurial client may not be able to clone from a
1815 remote or a legacy Mercurial client may not be able to clone from a
1816 modern Mercurial remote.
1816 modern Mercurial remote.
1817
1817
1818 .. note::
1818 .. note::
1819
1819
1820 Specifying a tag will include the tagged changeset but not the
1820 Specifying a tag will include the tagged changeset but not the
1821 changeset containing the tag.
1821 changeset containing the tag.
1822
1822
1823 .. container:: verbose
1823 .. container:: verbose
1824
1824
1825 For efficiency, hardlinks are used for cloning whenever the
1825 For efficiency, hardlinks are used for cloning whenever the
1826 source and destination are on the same filesystem (note this
1826 source and destination are on the same filesystem (note this
1827 applies only to the repository data, not to the working
1827 applies only to the repository data, not to the working
1828 directory). Some filesystems, such as AFS, implement hardlinking
1828 directory). Some filesystems, such as AFS, implement hardlinking
1829 incorrectly, but do not report errors. In these cases, use the
1829 incorrectly, but do not report errors. In these cases, use the
1830 --pull option to avoid hardlinking.
1830 --pull option to avoid hardlinking.
1831
1831
1832 Mercurial will update the working directory to the first applicable
1832 Mercurial will update the working directory to the first applicable
1833 revision from this list:
1833 revision from this list:
1834
1834
1835 a) null if -U or the source repository has no changesets
1835 a) null if -U or the source repository has no changesets
1836 b) if -u . and the source repository is local, the first parent of
1836 b) if -u . and the source repository is local, the first parent of
1837 the source repository's working directory
1837 the source repository's working directory
1838 c) the changeset specified with -u (if a branch name, this means the
1838 c) the changeset specified with -u (if a branch name, this means the
1839 latest head of that branch)
1839 latest head of that branch)
1840 d) the changeset specified with -r
1840 d) the changeset specified with -r
1841 e) the tipmost head specified with -b
1841 e) the tipmost head specified with -b
1842 f) the tipmost head specified with the url#branch source syntax
1842 f) the tipmost head specified with the url#branch source syntax
1843 g) the revision marked with the '@' bookmark, if present
1843 g) the revision marked with the '@' bookmark, if present
1844 h) the tipmost head of the default branch
1844 h) the tipmost head of the default branch
1845 i) tip
1845 i) tip
1846
1846
1847 When cloning from servers that support it, Mercurial may fetch
1847 When cloning from servers that support it, Mercurial may fetch
1848 pre-generated data from a server-advertised URL or inline from the
1848 pre-generated data from a server-advertised URL or inline from the
1849 same stream. When this is done, hooks operating on incoming changesets
1849 same stream. When this is done, hooks operating on incoming changesets
1850 and changegroups may fire more than once, once for each pre-generated
1850 and changegroups may fire more than once, once for each pre-generated
1851 bundle and as well as for any additional remaining data. In addition,
1851 bundle and as well as for any additional remaining data. In addition,
1852 if an error occurs, the repository may be rolled back to a partial
1852 if an error occurs, the repository may be rolled back to a partial
1853 clone. This behavior may change in future releases.
1853 clone. This behavior may change in future releases.
1854 See :hg:`help -e clonebundles` for more.
1854 See :hg:`help -e clonebundles` for more.
1855
1855
1856 Examples:
1856 Examples:
1857
1857
1858 - clone a remote repository to a new directory named hg/::
1858 - clone a remote repository to a new directory named hg/::
1859
1859
1860 hg clone https://www.mercurial-scm.org/repo/hg/
1860 hg clone https://www.mercurial-scm.org/repo/hg/
1861
1861
1862 - create a lightweight local clone::
1862 - create a lightweight local clone::
1863
1863
1864 hg clone project/ project-feature/
1864 hg clone project/ project-feature/
1865
1865
1866 - clone from an absolute path on an ssh server (note double-slash)::
1866 - clone from an absolute path on an ssh server (note double-slash)::
1867
1867
1868 hg clone ssh://user@server//home/projects/alpha/
1868 hg clone ssh://user@server//home/projects/alpha/
1869
1869
1870 - do a streaming clone while checking out a specified version::
1870 - do a streaming clone while checking out a specified version::
1871
1871
1872 hg clone --stream http://server/repo -u 1.5
1872 hg clone --stream http://server/repo -u 1.5
1873
1873
1874 - create a repository without changesets after a particular revision::
1874 - create a repository without changesets after a particular revision::
1875
1875
1876 hg clone -r 04e544 experimental/ good/
1876 hg clone -r 04e544 experimental/ good/
1877
1877
1878 - clone (and track) a particular named branch::
1878 - clone (and track) a particular named branch::
1879
1879
1880 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1880 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1881
1881
1882 See :hg:`help urls` for details on specifying URLs.
1882 See :hg:`help urls` for details on specifying URLs.
1883
1883
1884 Returns 0 on success.
1884 Returns 0 on success.
1885 """
1885 """
1886 opts = pycompat.byteskwargs(opts)
1886 opts = pycompat.byteskwargs(opts)
1887 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1887 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1888
1888
1889 # --include/--exclude can come from narrow or sparse.
1889 # --include/--exclude can come from narrow or sparse.
1890 includepats, excludepats = None, None
1890 includepats, excludepats = None, None
1891
1891
1892 # hg.clone() differentiates between None and an empty set. So make sure
1892 # hg.clone() differentiates between None and an empty set. So make sure
1893 # patterns are sets if narrow is requested without patterns.
1893 # patterns are sets if narrow is requested without patterns.
1894 if opts.get(b'narrow'):
1894 if opts.get(b'narrow'):
1895 includepats = set()
1895 includepats = set()
1896 excludepats = set()
1896 excludepats = set()
1897
1897
1898 if opts.get(b'include'):
1898 if opts.get(b'include'):
1899 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1899 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1900 if opts.get(b'exclude'):
1900 if opts.get(b'exclude'):
1901 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1901 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1902
1902
1903 r = hg.clone(
1903 r = hg.clone(
1904 ui,
1904 ui,
1905 opts,
1905 opts,
1906 source,
1906 source,
1907 dest,
1907 dest,
1908 pull=opts.get(b'pull'),
1908 pull=opts.get(b'pull'),
1909 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1909 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1910 revs=opts.get(b'rev'),
1910 revs=opts.get(b'rev'),
1911 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1911 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1912 branch=opts.get(b'branch'),
1912 branch=opts.get(b'branch'),
1913 shareopts=opts.get(b'shareopts'),
1913 shareopts=opts.get(b'shareopts'),
1914 storeincludepats=includepats,
1914 storeincludepats=includepats,
1915 storeexcludepats=excludepats,
1915 storeexcludepats=excludepats,
1916 depth=opts.get(b'depth') or None,
1916 depth=opts.get(b'depth') or None,
1917 )
1917 )
1918
1918
1919 return r is None
1919 return r is None
1920
1920
1921
1921
1922 @command(
1922 @command(
1923 b'commit|ci',
1923 b'commit|ci',
1924 [
1924 [
1925 (
1925 (
1926 b'A',
1926 b'A',
1927 b'addremove',
1927 b'addremove',
1928 None,
1928 None,
1929 _(b'mark new/missing files as added/removed before committing'),
1929 _(b'mark new/missing files as added/removed before committing'),
1930 ),
1930 ),
1931 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1931 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1932 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1932 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1933 (b's', b'secret', None, _(b'use the secret phase for committing')),
1933 (b's', b'secret', None, _(b'use the secret phase for committing')),
1934 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1934 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1935 (
1935 (
1936 b'',
1936 b'',
1937 b'force-close-branch',
1937 b'force-close-branch',
1938 None,
1938 None,
1939 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1939 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1940 ),
1940 ),
1941 (b'i', b'interactive', None, _(b'use interactive mode')),
1941 (b'i', b'interactive', None, _(b'use interactive mode')),
1942 ]
1942 ]
1943 + walkopts
1943 + walkopts
1944 + commitopts
1944 + commitopts
1945 + commitopts2
1945 + commitopts2
1946 + subrepoopts,
1946 + subrepoopts,
1947 _(b'[OPTION]... [FILE]...'),
1947 _(b'[OPTION]... [FILE]...'),
1948 helpcategory=command.CATEGORY_COMMITTING,
1948 helpcategory=command.CATEGORY_COMMITTING,
1949 helpbasic=True,
1949 helpbasic=True,
1950 inferrepo=True,
1950 inferrepo=True,
1951 )
1951 )
1952 def commit(ui, repo, *pats, **opts):
1952 def commit(ui, repo, *pats, **opts):
1953 """commit the specified files or all outstanding changes
1953 """commit the specified files or all outstanding changes
1954
1954
1955 Commit changes to the given files into the repository. Unlike a
1955 Commit changes to the given files into the repository. Unlike a
1956 centralized SCM, this operation is a local operation. See
1956 centralized SCM, this operation is a local operation. See
1957 :hg:`push` for a way to actively distribute your changes.
1957 :hg:`push` for a way to actively distribute your changes.
1958
1958
1959 If a list of files is omitted, all changes reported by :hg:`status`
1959 If a list of files is omitted, all changes reported by :hg:`status`
1960 will be committed.
1960 will be committed.
1961
1961
1962 If you are committing the result of a merge, do not provide any
1962 If you are committing the result of a merge, do not provide any
1963 filenames or -I/-X filters.
1963 filenames or -I/-X filters.
1964
1964
1965 If no commit message is specified, Mercurial starts your
1965 If no commit message is specified, Mercurial starts your
1966 configured editor where you can enter a message. In case your
1966 configured editor where you can enter a message. In case your
1967 commit fails, you will find a backup of your message in
1967 commit fails, you will find a backup of your message in
1968 ``.hg/last-message.txt``.
1968 ``.hg/last-message.txt``.
1969
1969
1970 The --close-branch flag can be used to mark the current branch
1970 The --close-branch flag can be used to mark the current branch
1971 head closed. When all heads of a branch are closed, the branch
1971 head closed. When all heads of a branch are closed, the branch
1972 will be considered closed and no longer listed.
1972 will be considered closed and no longer listed.
1973
1973
1974 The --amend flag can be used to amend the parent of the
1974 The --amend flag can be used to amend the parent of the
1975 working directory with a new commit that contains the changes
1975 working directory with a new commit that contains the changes
1976 in the parent in addition to those currently reported by :hg:`status`,
1976 in the parent in addition to those currently reported by :hg:`status`,
1977 if there are any. The old commit is stored in a backup bundle in
1977 if there are any. The old commit is stored in a backup bundle in
1978 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1978 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1979 on how to restore it).
1979 on how to restore it).
1980
1980
1981 Message, user and date are taken from the amended commit unless
1981 Message, user and date are taken from the amended commit unless
1982 specified. When a message isn't specified on the command line,
1982 specified. When a message isn't specified on the command line,
1983 the editor will open with the message of the amended commit.
1983 the editor will open with the message of the amended commit.
1984
1984
1985 It is not possible to amend public changesets (see :hg:`help phases`)
1985 It is not possible to amend public changesets (see :hg:`help phases`)
1986 or changesets that have children.
1986 or changesets that have children.
1987
1987
1988 See :hg:`help dates` for a list of formats valid for -d/--date.
1988 See :hg:`help dates` for a list of formats valid for -d/--date.
1989
1989
1990 Returns 0 on success, 1 if nothing changed.
1990 Returns 0 on success, 1 if nothing changed.
1991
1991
1992 .. container:: verbose
1992 .. container:: verbose
1993
1993
1994 Examples:
1994 Examples:
1995
1995
1996 - commit all files ending in .py::
1996 - commit all files ending in .py::
1997
1997
1998 hg commit --include "set:**.py"
1998 hg commit --include "set:**.py"
1999
1999
2000 - commit all non-binary files::
2000 - commit all non-binary files::
2001
2001
2002 hg commit --exclude "set:binary()"
2002 hg commit --exclude "set:binary()"
2003
2003
2004 - amend the current commit and set the date to now::
2004 - amend the current commit and set the date to now::
2005
2005
2006 hg commit --amend --date now
2006 hg commit --amend --date now
2007 """
2007 """
2008 with repo.wlock(), repo.lock():
2008 with repo.wlock(), repo.lock():
2009 return _docommit(ui, repo, *pats, **opts)
2009 return _docommit(ui, repo, *pats, **opts)
2010
2010
2011
2011
2012 def _docommit(ui, repo, *pats, **opts):
2012 def _docommit(ui, repo, *pats, **opts):
2013 if opts.get('interactive'):
2013 if opts.get('interactive'):
2014 opts.pop('interactive')
2014 opts.pop('interactive')
2015 ret = cmdutil.dorecord(
2015 ret = cmdutil.dorecord(
2016 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2016 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2017 )
2017 )
2018 # ret can be 0 (no changes to record) or the value returned by
2018 # ret can be 0 (no changes to record) or the value returned by
2019 # commit(), 1 if nothing changed or None on success.
2019 # commit(), 1 if nothing changed or None on success.
2020 return 1 if ret == 0 else ret
2020 return 1 if ret == 0 else ret
2021
2021
2022 opts = pycompat.byteskwargs(opts)
2022 opts = pycompat.byteskwargs(opts)
2023 if opts.get(b'subrepos'):
2023 if opts.get(b'subrepos'):
2024 if opts.get(b'amend'):
2024 if opts.get(b'amend'):
2025 raise error.Abort(_(b'cannot amend with --subrepos'))
2025 raise error.Abort(_(b'cannot amend with --subrepos'))
2026 # Let --subrepos on the command line override config setting.
2026 # Let --subrepos on the command line override config setting.
2027 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2027 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2028
2028
2029 cmdutil.checkunfinished(repo, commit=True)
2029 cmdutil.checkunfinished(repo, commit=True)
2030
2030
2031 branch = repo[None].branch()
2031 branch = repo[None].branch()
2032 bheads = repo.branchheads(branch)
2032 bheads = repo.branchheads(branch)
2033
2033
2034 extra = {}
2034 extra = {}
2035 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2035 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2036 extra[b'close'] = b'1'
2036 extra[b'close'] = b'1'
2037
2037
2038 if repo[b'.'].closesbranch():
2038 if repo[b'.'].closesbranch():
2039 raise error.Abort(
2039 raise error.Abort(
2040 _(b'current revision is already a branch closing head')
2040 _(b'current revision is already a branch closing head')
2041 )
2041 )
2042 elif not bheads:
2042 elif not bheads:
2043 raise error.Abort(_(b'branch "%s" has no heads to close') % branch)
2043 raise error.Abort(_(b'branch "%s" has no heads to close') % branch)
2044 elif (
2044 elif (
2045 branch == repo[b'.'].branch()
2045 branch == repo[b'.'].branch()
2046 and repo[b'.'].node() not in bheads
2046 and repo[b'.'].node() not in bheads
2047 and not opts.get(b'force_close_branch')
2047 and not opts.get(b'force_close_branch')
2048 ):
2048 ):
2049 hint = _(
2049 hint = _(
2050 b'use --force-close-branch to close branch from a non-head'
2050 b'use --force-close-branch to close branch from a non-head'
2051 b' changeset'
2051 b' changeset'
2052 )
2052 )
2053 raise error.Abort(_(b'can only close branch heads'), hint=hint)
2053 raise error.Abort(_(b'can only close branch heads'), hint=hint)
2054 elif opts.get(b'amend'):
2054 elif opts.get(b'amend'):
2055 if (
2055 if (
2056 repo[b'.'].p1().branch() != branch
2056 repo[b'.'].p1().branch() != branch
2057 and repo[b'.'].p2().branch() != branch
2057 and repo[b'.'].p2().branch() != branch
2058 ):
2058 ):
2059 raise error.Abort(_(b'can only close branch heads'))
2059 raise error.Abort(_(b'can only close branch heads'))
2060
2060
2061 if opts.get(b'amend'):
2061 if opts.get(b'amend'):
2062 if ui.configbool(b'ui', b'commitsubrepos'):
2062 if ui.configbool(b'ui', b'commitsubrepos'):
2063 raise error.Abort(_(b'cannot amend with ui.commitsubrepos enabled'))
2063 raise error.Abort(_(b'cannot amend with ui.commitsubrepos enabled'))
2064
2064
2065 old = repo[b'.']
2065 old = repo[b'.']
2066 rewriteutil.precheck(repo, [old.rev()], b'amend')
2066 rewriteutil.precheck(repo, [old.rev()], b'amend')
2067
2067
2068 # Currently histedit gets confused if an amend happens while histedit
2068 # Currently histedit gets confused if an amend happens while histedit
2069 # is in progress. Since we have a checkunfinished command, we are
2069 # is in progress. Since we have a checkunfinished command, we are
2070 # temporarily honoring it.
2070 # temporarily honoring it.
2071 #
2071 #
2072 # Note: eventually this guard will be removed. Please do not expect
2072 # Note: eventually this guard will be removed. Please do not expect
2073 # this behavior to remain.
2073 # this behavior to remain.
2074 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2074 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2075 cmdutil.checkunfinished(repo)
2075 cmdutil.checkunfinished(repo)
2076
2076
2077 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2077 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2078 if node == old.node():
2078 if node == old.node():
2079 ui.status(_(b"nothing changed\n"))
2079 ui.status(_(b"nothing changed\n"))
2080 return 1
2080 return 1
2081 else:
2081 else:
2082
2082
2083 def commitfunc(ui, repo, message, match, opts):
2083 def commitfunc(ui, repo, message, match, opts):
2084 overrides = {}
2084 overrides = {}
2085 if opts.get(b'secret'):
2085 if opts.get(b'secret'):
2086 overrides[(b'phases', b'new-commit')] = b'secret'
2086 overrides[(b'phases', b'new-commit')] = b'secret'
2087
2087
2088 baseui = repo.baseui
2088 baseui = repo.baseui
2089 with baseui.configoverride(overrides, b'commit'):
2089 with baseui.configoverride(overrides, b'commit'):
2090 with ui.configoverride(overrides, b'commit'):
2090 with ui.configoverride(overrides, b'commit'):
2091 editform = cmdutil.mergeeditform(
2091 editform = cmdutil.mergeeditform(
2092 repo[None], b'commit.normal'
2092 repo[None], b'commit.normal'
2093 )
2093 )
2094 editor = cmdutil.getcommiteditor(
2094 editor = cmdutil.getcommiteditor(
2095 editform=editform, **pycompat.strkwargs(opts)
2095 editform=editform, **pycompat.strkwargs(opts)
2096 )
2096 )
2097 return repo.commit(
2097 return repo.commit(
2098 message,
2098 message,
2099 opts.get(b'user'),
2099 opts.get(b'user'),
2100 opts.get(b'date'),
2100 opts.get(b'date'),
2101 match,
2101 match,
2102 editor=editor,
2102 editor=editor,
2103 extra=extra,
2103 extra=extra,
2104 )
2104 )
2105
2105
2106 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2106 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2107
2107
2108 if not node:
2108 if not node:
2109 stat = cmdutil.postcommitstatus(repo, pats, opts)
2109 stat = cmdutil.postcommitstatus(repo, pats, opts)
2110 if stat.deleted:
2110 if stat.deleted:
2111 ui.status(
2111 ui.status(
2112 _(
2112 _(
2113 b"nothing changed (%d missing files, see "
2113 b"nothing changed (%d missing files, see "
2114 b"'hg status')\n"
2114 b"'hg status')\n"
2115 )
2115 )
2116 % len(stat.deleted)
2116 % len(stat.deleted)
2117 )
2117 )
2118 else:
2118 else:
2119 ui.status(_(b"nothing changed\n"))
2119 ui.status(_(b"nothing changed\n"))
2120 return 1
2120 return 1
2121
2121
2122 cmdutil.commitstatus(repo, node, branch, bheads, opts)
2122 cmdutil.commitstatus(repo, node, branch, bheads, opts)
2123
2123
2124 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2124 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2125 status(
2125 status(
2126 ui,
2126 ui,
2127 repo,
2127 repo,
2128 modified=True,
2128 modified=True,
2129 added=True,
2129 added=True,
2130 removed=True,
2130 removed=True,
2131 deleted=True,
2131 deleted=True,
2132 unknown=True,
2132 unknown=True,
2133 subrepos=opts.get(b'subrepos'),
2133 subrepos=opts.get(b'subrepos'),
2134 )
2134 )
2135
2135
2136
2136
2137 @command(
2137 @command(
2138 b'config|showconfig|debugconfig',
2138 b'config|showconfig|debugconfig',
2139 [
2139 [
2140 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2140 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2141 (b'e', b'edit', None, _(b'edit user config')),
2141 (b'e', b'edit', None, _(b'edit user config')),
2142 (b'l', b'local', None, _(b'edit repository config')),
2142 (b'l', b'local', None, _(b'edit repository config')),
2143 (b'g', b'global', None, _(b'edit global config')),
2143 (b'g', b'global', None, _(b'edit global config')),
2144 ]
2144 ]
2145 + formatteropts,
2145 + formatteropts,
2146 _(b'[-u] [NAME]...'),
2146 _(b'[-u] [NAME]...'),
2147 helpcategory=command.CATEGORY_HELP,
2147 helpcategory=command.CATEGORY_HELP,
2148 optionalrepo=True,
2148 optionalrepo=True,
2149 intents={INTENT_READONLY},
2149 intents={INTENT_READONLY},
2150 )
2150 )
2151 def config(ui, repo, *values, **opts):
2151 def config(ui, repo, *values, **opts):
2152 """show combined config settings from all hgrc files
2152 """show combined config settings from all hgrc files
2153
2153
2154 With no arguments, print names and values of all config items.
2154 With no arguments, print names and values of all config items.
2155
2155
2156 With one argument of the form section.name, print just the value
2156 With one argument of the form section.name, print just the value
2157 of that config item.
2157 of that config item.
2158
2158
2159 With multiple arguments, print names and values of all config
2159 With multiple arguments, print names and values of all config
2160 items with matching section names or section.names.
2160 items with matching section names or section.names.
2161
2161
2162 With --edit, start an editor on the user-level config file. With
2162 With --edit, start an editor on the user-level config file. With
2163 --global, edit the system-wide config file. With --local, edit the
2163 --global, edit the system-wide config file. With --local, edit the
2164 repository-level config file.
2164 repository-level config file.
2165
2165
2166 With --debug, the source (filename and line number) is printed
2166 With --debug, the source (filename and line number) is printed
2167 for each config item.
2167 for each config item.
2168
2168
2169 See :hg:`help config` for more information about config files.
2169 See :hg:`help config` for more information about config files.
2170
2170
2171 .. container:: verbose
2171 .. container:: verbose
2172
2172
2173 Template:
2173 Template:
2174
2174
2175 The following keywords are supported. See also :hg:`help templates`.
2175 The following keywords are supported. See also :hg:`help templates`.
2176
2176
2177 :name: String. Config name.
2177 :name: String. Config name.
2178 :source: String. Filename and line number where the item is defined.
2178 :source: String. Filename and line number where the item is defined.
2179 :value: String. Config value.
2179 :value: String. Config value.
2180
2180
2181 Returns 0 on success, 1 if NAME does not exist.
2181 Returns 0 on success, 1 if NAME does not exist.
2182
2182
2183 """
2183 """
2184
2184
2185 opts = pycompat.byteskwargs(opts)
2185 opts = pycompat.byteskwargs(opts)
2186 if opts.get(b'edit') or opts.get(b'local') or opts.get(b'global'):
2186 if opts.get(b'edit') or opts.get(b'local') or opts.get(b'global'):
2187 if opts.get(b'local') and opts.get(b'global'):
2187 if opts.get(b'local') and opts.get(b'global'):
2188 raise error.Abort(_(b"can't use --local and --global together"))
2188 raise error.Abort(_(b"can't use --local and --global together"))
2189
2189
2190 if opts.get(b'local'):
2190 if opts.get(b'local'):
2191 if not repo:
2191 if not repo:
2192 raise error.Abort(_(b"can't use --local outside a repository"))
2192 raise error.Abort(_(b"can't use --local outside a repository"))
2193 paths = [repo.vfs.join(b'hgrc')]
2193 paths = [repo.vfs.join(b'hgrc')]
2194 elif opts.get(b'global'):
2194 elif opts.get(b'global'):
2195 paths = rcutil.systemrcpath()
2195 paths = rcutil.systemrcpath()
2196 else:
2196 else:
2197 paths = rcutil.userrcpath()
2197 paths = rcutil.userrcpath()
2198
2198
2199 for f in paths:
2199 for f in paths:
2200 if os.path.exists(f):
2200 if os.path.exists(f):
2201 break
2201 break
2202 else:
2202 else:
2203 if opts.get(b'global'):
2203 if opts.get(b'global'):
2204 samplehgrc = uimod.samplehgrcs[b'global']
2204 samplehgrc = uimod.samplehgrcs[b'global']
2205 elif opts.get(b'local'):
2205 elif opts.get(b'local'):
2206 samplehgrc = uimod.samplehgrcs[b'local']
2206 samplehgrc = uimod.samplehgrcs[b'local']
2207 else:
2207 else:
2208 samplehgrc = uimod.samplehgrcs[b'user']
2208 samplehgrc = uimod.samplehgrcs[b'user']
2209
2209
2210 f = paths[0]
2210 f = paths[0]
2211 fp = open(f, b"wb")
2211 fp = open(f, b"wb")
2212 fp.write(util.tonativeeol(samplehgrc))
2212 fp.write(util.tonativeeol(samplehgrc))
2213 fp.close()
2213 fp.close()
2214
2214
2215 editor = ui.geteditor()
2215 editor = ui.geteditor()
2216 ui.system(
2216 ui.system(
2217 b"%s \"%s\"" % (editor, f),
2217 b"%s \"%s\"" % (editor, f),
2218 onerr=error.Abort,
2218 onerr=error.Abort,
2219 errprefix=_(b"edit failed"),
2219 errprefix=_(b"edit failed"),
2220 blockedtag=b'config_edit',
2220 blockedtag=b'config_edit',
2221 )
2221 )
2222 return
2222 return
2223 ui.pager(b'config')
2223 ui.pager(b'config')
2224 fm = ui.formatter(b'config', opts)
2224 fm = ui.formatter(b'config', opts)
2225 for t, f in rcutil.rccomponents():
2225 for t, f in rcutil.rccomponents():
2226 if t == b'path':
2226 if t == b'path':
2227 ui.debug(b'read config from: %s\n' % f)
2227 ui.debug(b'read config from: %s\n' % f)
2228 elif t == b'resource':
2228 elif t == b'resource':
2229 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2229 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2230 elif t == b'items':
2230 elif t == b'items':
2231 # Don't print anything for 'items'.
2231 # Don't print anything for 'items'.
2232 pass
2232 pass
2233 else:
2233 else:
2234 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2234 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2235 untrusted = bool(opts.get(b'untrusted'))
2235 untrusted = bool(opts.get(b'untrusted'))
2236
2236
2237 selsections = selentries = []
2237 selsections = selentries = []
2238 if values:
2238 if values:
2239 selsections = [v for v in values if b'.' not in v]
2239 selsections = [v for v in values if b'.' not in v]
2240 selentries = [v for v in values if b'.' in v]
2240 selentries = [v for v in values if b'.' in v]
2241 uniquesel = len(selentries) == 1 and not selsections
2241 uniquesel = len(selentries) == 1 and not selsections
2242 selsections = set(selsections)
2242 selsections = set(selsections)
2243 selentries = set(selentries)
2243 selentries = set(selentries)
2244
2244
2245 matched = False
2245 matched = False
2246 for section, name, value in ui.walkconfig(untrusted=untrusted):
2246 for section, name, value in ui.walkconfig(untrusted=untrusted):
2247 source = ui.configsource(section, name, untrusted)
2247 source = ui.configsource(section, name, untrusted)
2248 value = pycompat.bytestr(value)
2248 value = pycompat.bytestr(value)
2249 defaultvalue = ui.configdefault(section, name)
2249 defaultvalue = ui.configdefault(section, name)
2250 if fm.isplain():
2250 if fm.isplain():
2251 source = source or b'none'
2251 source = source or b'none'
2252 value = value.replace(b'\n', b'\\n')
2252 value = value.replace(b'\n', b'\\n')
2253 entryname = section + b'.' + name
2253 entryname = section + b'.' + name
2254 if values and not (section in selsections or entryname in selentries):
2254 if values and not (section in selsections or entryname in selentries):
2255 continue
2255 continue
2256 fm.startitem()
2256 fm.startitem()
2257 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2257 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2258 if uniquesel:
2258 if uniquesel:
2259 fm.data(name=entryname)
2259 fm.data(name=entryname)
2260 fm.write(b'value', b'%s\n', value)
2260 fm.write(b'value', b'%s\n', value)
2261 else:
2261 else:
2262 fm.write(b'name value', b'%s=%s\n', entryname, value)
2262 fm.write(b'name value', b'%s=%s\n', entryname, value)
2263 if formatter.isprintable(defaultvalue):
2263 if formatter.isprintable(defaultvalue):
2264 fm.data(defaultvalue=defaultvalue)
2264 fm.data(defaultvalue=defaultvalue)
2265 elif isinstance(defaultvalue, list) and all(
2265 elif isinstance(defaultvalue, list) and all(
2266 formatter.isprintable(e) for e in defaultvalue
2266 formatter.isprintable(e) for e in defaultvalue
2267 ):
2267 ):
2268 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2268 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2269 # TODO: no idea how to process unsupported defaultvalue types
2269 # TODO: no idea how to process unsupported defaultvalue types
2270 matched = True
2270 matched = True
2271 fm.end()
2271 fm.end()
2272 if matched:
2272 if matched:
2273 return 0
2273 return 0
2274 return 1
2274 return 1
2275
2275
2276
2276
2277 @command(
2277 @command(
2278 b'continue',
2278 b'continue',
2279 dryrunopts,
2279 dryrunopts,
2280 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2280 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2281 helpbasic=True,
2281 helpbasic=True,
2282 )
2282 )
2283 def continuecmd(ui, repo, **opts):
2283 def continuecmd(ui, repo, **opts):
2284 """resumes an interrupted operation (EXPERIMENTAL)
2284 """resumes an interrupted operation (EXPERIMENTAL)
2285
2285
2286 Finishes a multistep operation like graft, histedit, rebase, merge,
2286 Finishes a multistep operation like graft, histedit, rebase, merge,
2287 and unshelve if they are in an interrupted state.
2287 and unshelve if they are in an interrupted state.
2288
2288
2289 use --dry-run/-n to dry run the command.
2289 use --dry-run/-n to dry run the command.
2290 """
2290 """
2291 dryrun = opts.get('dry_run')
2291 dryrun = opts.get('dry_run')
2292 contstate = cmdutil.getunfinishedstate(repo)
2292 contstate = cmdutil.getunfinishedstate(repo)
2293 if not contstate:
2293 if not contstate:
2294 raise error.Abort(_(b'no operation in progress'))
2294 raise error.Abort(_(b'no operation in progress'))
2295 if not contstate.continuefunc:
2295 if not contstate.continuefunc:
2296 raise error.Abort(
2296 raise error.Abort(
2297 (
2297 (
2298 _(b"%s in progress but does not support 'hg continue'")
2298 _(b"%s in progress but does not support 'hg continue'")
2299 % (contstate._opname)
2299 % (contstate._opname)
2300 ),
2300 ),
2301 hint=contstate.continuemsg(),
2301 hint=contstate.continuemsg(),
2302 )
2302 )
2303 if dryrun:
2303 if dryrun:
2304 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2304 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2305 return
2305 return
2306 return contstate.continuefunc(ui, repo)
2306 return contstate.continuefunc(ui, repo)
2307
2307
2308
2308
2309 @command(
2309 @command(
2310 b'copy|cp',
2310 b'copy|cp',
2311 [
2311 [
2312 (b'', b'forget', None, _(b'unmark a file as copied')),
2312 (b'', b'forget', None, _(b'unmark a file as copied')),
2313 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2313 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2314 (
2314 (
2315 b'',
2315 b'',
2316 b'at-rev',
2316 b'at-rev',
2317 b'',
2317 b'',
2318 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2318 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2319 _(b'REV'),
2319 _(b'REV'),
2320 ),
2320 ),
2321 (
2321 (
2322 b'f',
2322 b'f',
2323 b'force',
2323 b'force',
2324 None,
2324 None,
2325 _(b'forcibly copy over an existing managed file'),
2325 _(b'forcibly copy over an existing managed file'),
2326 ),
2326 ),
2327 ]
2327 ]
2328 + walkopts
2328 + walkopts
2329 + dryrunopts,
2329 + dryrunopts,
2330 _(b'[OPTION]... SOURCE... DEST'),
2330 _(b'[OPTION]... SOURCE... DEST'),
2331 helpcategory=command.CATEGORY_FILE_CONTENTS,
2331 helpcategory=command.CATEGORY_FILE_CONTENTS,
2332 )
2332 )
2333 def copy(ui, repo, *pats, **opts):
2333 def copy(ui, repo, *pats, **opts):
2334 """mark files as copied for the next commit
2334 """mark files as copied for the next commit
2335
2335
2336 Mark dest as having copies of source files. If dest is a
2336 Mark dest as having copies of source files. If dest is a
2337 directory, copies are put in that directory. If dest is a file,
2337 directory, copies are put in that directory. If dest is a file,
2338 the source must be a single file.
2338 the source must be a single file.
2339
2339
2340 By default, this command copies the contents of files as they
2340 By default, this command copies the contents of files as they
2341 exist in the working directory. If invoked with -A/--after, the
2341 exist in the working directory. If invoked with -A/--after, the
2342 operation is recorded, but no copying is performed.
2342 operation is recorded, but no copying is performed.
2343
2343
2344 To undo marking a file as copied, use --forget. With that option,
2344 To undo marking a file as copied, use --forget. With that option,
2345 all given (positional) arguments are unmarked as copies. The destination
2345 all given (positional) arguments are unmarked as copies. The destination
2346 file(s) will be left in place (still tracked).
2346 file(s) will be left in place (still tracked).
2347
2347
2348 This command takes effect with the next commit by default.
2348 This command takes effect with the next commit by default.
2349
2349
2350 Returns 0 on success, 1 if errors are encountered.
2350 Returns 0 on success, 1 if errors are encountered.
2351 """
2351 """
2352 opts = pycompat.byteskwargs(opts)
2352 opts = pycompat.byteskwargs(opts)
2353 with repo.wlock(False):
2353 with repo.wlock(False):
2354 return cmdutil.copy(ui, repo, pats, opts)
2354 return cmdutil.copy(ui, repo, pats, opts)
2355
2355
2356
2356
2357 @command(
2357 @command(
2358 b'debugcommands',
2358 b'debugcommands',
2359 [],
2359 [],
2360 _(b'[COMMAND]'),
2360 _(b'[COMMAND]'),
2361 helpcategory=command.CATEGORY_HELP,
2361 helpcategory=command.CATEGORY_HELP,
2362 norepo=True,
2362 norepo=True,
2363 )
2363 )
2364 def debugcommands(ui, cmd=b'', *args):
2364 def debugcommands(ui, cmd=b'', *args):
2365 """list all available commands and options"""
2365 """list all available commands and options"""
2366 for cmd, vals in sorted(pycompat.iteritems(table)):
2366 for cmd, vals in sorted(pycompat.iteritems(table)):
2367 cmd = cmd.split(b'|')[0]
2367 cmd = cmd.split(b'|')[0]
2368 opts = b', '.join([i[1] for i in vals[1]])
2368 opts = b', '.join([i[1] for i in vals[1]])
2369 ui.write(b'%s: %s\n' % (cmd, opts))
2369 ui.write(b'%s: %s\n' % (cmd, opts))
2370
2370
2371
2371
2372 @command(
2372 @command(
2373 b'debugcomplete',
2373 b'debugcomplete',
2374 [(b'o', b'options', None, _(b'show the command options'))],
2374 [(b'o', b'options', None, _(b'show the command options'))],
2375 _(b'[-o] CMD'),
2375 _(b'[-o] CMD'),
2376 helpcategory=command.CATEGORY_HELP,
2376 helpcategory=command.CATEGORY_HELP,
2377 norepo=True,
2377 norepo=True,
2378 )
2378 )
2379 def debugcomplete(ui, cmd=b'', **opts):
2379 def debugcomplete(ui, cmd=b'', **opts):
2380 """returns the completion list associated with the given command"""
2380 """returns the completion list associated with the given command"""
2381
2381
2382 if opts.get('options'):
2382 if opts.get('options'):
2383 options = []
2383 options = []
2384 otables = [globalopts]
2384 otables = [globalopts]
2385 if cmd:
2385 if cmd:
2386 aliases, entry = cmdutil.findcmd(cmd, table, False)
2386 aliases, entry = cmdutil.findcmd(cmd, table, False)
2387 otables.append(entry[1])
2387 otables.append(entry[1])
2388 for t in otables:
2388 for t in otables:
2389 for o in t:
2389 for o in t:
2390 if b"(DEPRECATED)" in o[3]:
2390 if b"(DEPRECATED)" in o[3]:
2391 continue
2391 continue
2392 if o[0]:
2392 if o[0]:
2393 options.append(b'-%s' % o[0])
2393 options.append(b'-%s' % o[0])
2394 options.append(b'--%s' % o[1])
2394 options.append(b'--%s' % o[1])
2395 ui.write(b"%s\n" % b"\n".join(options))
2395 ui.write(b"%s\n" % b"\n".join(options))
2396 return
2396 return
2397
2397
2398 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2398 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2399 if ui.verbose:
2399 if ui.verbose:
2400 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2400 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2401 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2401 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2402
2402
2403
2403
2404 @command(
2404 @command(
2405 b'diff',
2405 b'diff',
2406 [
2406 [
2407 (b'r', b'rev', [], _(b'revision'), _(b'REV')),
2407 (b'r', b'rev', [], _(b'revision'), _(b'REV')),
2408 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2408 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2409 ]
2409 ]
2410 + diffopts
2410 + diffopts
2411 + diffopts2
2411 + diffopts2
2412 + walkopts
2412 + walkopts
2413 + subrepoopts,
2413 + subrepoopts,
2414 _(b'[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2414 _(b'[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2415 helpcategory=command.CATEGORY_FILE_CONTENTS,
2415 helpcategory=command.CATEGORY_FILE_CONTENTS,
2416 helpbasic=True,
2416 helpbasic=True,
2417 inferrepo=True,
2417 inferrepo=True,
2418 intents={INTENT_READONLY},
2418 intents={INTENT_READONLY},
2419 )
2419 )
2420 def diff(ui, repo, *pats, **opts):
2420 def diff(ui, repo, *pats, **opts):
2421 """diff repository (or selected files)
2421 """diff repository (or selected files)
2422
2422
2423 Show differences between revisions for the specified files.
2423 Show differences between revisions for the specified files.
2424
2424
2425 Differences between files are shown using the unified diff format.
2425 Differences between files are shown using the unified diff format.
2426
2426
2427 .. note::
2427 .. note::
2428
2428
2429 :hg:`diff` may generate unexpected results for merges, as it will
2429 :hg:`diff` may generate unexpected results for merges, as it will
2430 default to comparing against the working directory's first
2430 default to comparing against the working directory's first
2431 parent changeset if no revisions are specified.
2431 parent changeset if no revisions are specified.
2432
2432
2433 When two revision arguments are given, then changes are shown
2433 When two revision arguments are given, then changes are shown
2434 between those revisions. If only one revision is specified then
2434 between those revisions. If only one revision is specified then
2435 that revision is compared to the working directory, and, when no
2435 that revision is compared to the working directory, and, when no
2436 revisions are specified, the working directory files are compared
2436 revisions are specified, the working directory files are compared
2437 to its first parent.
2437 to its first parent.
2438
2438
2439 Alternatively you can specify -c/--change with a revision to see
2439 Alternatively you can specify -c/--change with a revision to see
2440 the changes in that changeset relative to its first parent.
2440 the changes in that changeset relative to its first parent.
2441
2441
2442 Without the -a/--text option, diff will avoid generating diffs of
2442 Without the -a/--text option, diff will avoid generating diffs of
2443 files it detects as binary. With -a, diff will generate a diff
2443 files it detects as binary. With -a, diff will generate a diff
2444 anyway, probably with undesirable results.
2444 anyway, probably with undesirable results.
2445
2445
2446 Use the -g/--git option to generate diffs in the git extended diff
2446 Use the -g/--git option to generate diffs in the git extended diff
2447 format. For more information, read :hg:`help diffs`.
2447 format. For more information, read :hg:`help diffs`.
2448
2448
2449 .. container:: verbose
2449 .. container:: verbose
2450
2450
2451 Examples:
2451 Examples:
2452
2452
2453 - compare a file in the current working directory to its parent::
2453 - compare a file in the current working directory to its parent::
2454
2454
2455 hg diff foo.c
2455 hg diff foo.c
2456
2456
2457 - compare two historical versions of a directory, with rename info::
2457 - compare two historical versions of a directory, with rename info::
2458
2458
2459 hg diff --git -r 1.0:1.2 lib/
2459 hg diff --git -r 1.0:1.2 lib/
2460
2460
2461 - get change stats relative to the last change on some date::
2461 - get change stats relative to the last change on some date::
2462
2462
2463 hg diff --stat -r "date('may 2')"
2463 hg diff --stat -r "date('may 2')"
2464
2464
2465 - diff all newly-added files that contain a keyword::
2465 - diff all newly-added files that contain a keyword::
2466
2466
2467 hg diff "set:added() and grep(GNU)"
2467 hg diff "set:added() and grep(GNU)"
2468
2468
2469 - compare a revision and its parents::
2469 - compare a revision and its parents::
2470
2470
2471 hg diff -c 9353 # compare against first parent
2471 hg diff -c 9353 # compare against first parent
2472 hg diff -r 9353^:9353 # same using revset syntax
2472 hg diff -r 9353^:9353 # same using revset syntax
2473 hg diff -r 9353^2:9353 # compare against the second parent
2473 hg diff -r 9353^2:9353 # compare against the second parent
2474
2474
2475 Returns 0 on success.
2475 Returns 0 on success.
2476 """
2476 """
2477
2477
2478 opts = pycompat.byteskwargs(opts)
2478 opts = pycompat.byteskwargs(opts)
2479 revs = opts.get(b'rev')
2479 revs = opts.get(b'rev')
2480 change = opts.get(b'change')
2480 change = opts.get(b'change')
2481 stat = opts.get(b'stat')
2481 stat = opts.get(b'stat')
2482 reverse = opts.get(b'reverse')
2482 reverse = opts.get(b'reverse')
2483
2483
2484 if revs and change:
2484 if revs and change:
2485 msg = _(b'cannot specify --rev and --change at the same time')
2485 msg = _(b'cannot specify --rev and --change at the same time')
2486 raise error.Abort(msg)
2486 raise error.Abort(msg)
2487 elif change:
2487 elif change:
2488 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2488 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2489 ctx2 = scmutil.revsingle(repo, change, None)
2489 ctx2 = scmutil.revsingle(repo, change, None)
2490 ctx1 = ctx2.p1()
2490 ctx1 = ctx2.p1()
2491 else:
2491 else:
2492 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2492 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2493 ctx1, ctx2 = scmutil.revpair(repo, revs)
2493 ctx1, ctx2 = scmutil.revpair(repo, revs)
2494 node1, node2 = ctx1.node(), ctx2.node()
2494 node1, node2 = ctx1.node(), ctx2.node()
2495
2495
2496 if reverse:
2496 if reverse:
2497 node1, node2 = node2, node1
2497 node1, node2 = node2, node1
2498
2498
2499 diffopts = patch.diffallopts(ui, opts)
2499 diffopts = patch.diffallopts(ui, opts)
2500 m = scmutil.match(ctx2, pats, opts)
2500 m = scmutil.match(ctx2, pats, opts)
2501 m = repo.narrowmatch(m)
2501 m = repo.narrowmatch(m)
2502 ui.pager(b'diff')
2502 ui.pager(b'diff')
2503 logcmdutil.diffordiffstat(
2503 logcmdutil.diffordiffstat(
2504 ui,
2504 ui,
2505 repo,
2505 repo,
2506 diffopts,
2506 diffopts,
2507 node1,
2507 node1,
2508 node2,
2508 node2,
2509 m,
2509 m,
2510 stat=stat,
2510 stat=stat,
2511 listsubrepos=opts.get(b'subrepos'),
2511 listsubrepos=opts.get(b'subrepos'),
2512 root=opts.get(b'root'),
2512 root=opts.get(b'root'),
2513 )
2513 )
2514
2514
2515
2515
2516 @command(
2516 @command(
2517 b'export',
2517 b'export',
2518 [
2518 [
2519 (
2519 (
2520 b'B',
2520 b'B',
2521 b'bookmark',
2521 b'bookmark',
2522 b'',
2522 b'',
2523 _(b'export changes only reachable by given bookmark'),
2523 _(b'export changes only reachable by given bookmark'),
2524 _(b'BOOKMARK'),
2524 _(b'BOOKMARK'),
2525 ),
2525 ),
2526 (
2526 (
2527 b'o',
2527 b'o',
2528 b'output',
2528 b'output',
2529 b'',
2529 b'',
2530 _(b'print output to file with formatted name'),
2530 _(b'print output to file with formatted name'),
2531 _(b'FORMAT'),
2531 _(b'FORMAT'),
2532 ),
2532 ),
2533 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2533 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2534 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2534 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2535 ]
2535 ]
2536 + diffopts
2536 + diffopts
2537 + formatteropts,
2537 + formatteropts,
2538 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2538 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2539 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2539 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2540 helpbasic=True,
2540 helpbasic=True,
2541 intents={INTENT_READONLY},
2541 intents={INTENT_READONLY},
2542 )
2542 )
2543 def export(ui, repo, *changesets, **opts):
2543 def export(ui, repo, *changesets, **opts):
2544 """dump the header and diffs for one or more changesets
2544 """dump the header and diffs for one or more changesets
2545
2545
2546 Print the changeset header and diffs for one or more revisions.
2546 Print the changeset header and diffs for one or more revisions.
2547 If no revision is given, the parent of the working directory is used.
2547 If no revision is given, the parent of the working directory is used.
2548
2548
2549 The information shown in the changeset header is: author, date,
2549 The information shown in the changeset header is: author, date,
2550 branch name (if non-default), changeset hash, parent(s) and commit
2550 branch name (if non-default), changeset hash, parent(s) and commit
2551 comment.
2551 comment.
2552
2552
2553 .. note::
2553 .. note::
2554
2554
2555 :hg:`export` may generate unexpected diff output for merge
2555 :hg:`export` may generate unexpected diff output for merge
2556 changesets, as it will compare the merge changeset against its
2556 changesets, as it will compare the merge changeset against its
2557 first parent only.
2557 first parent only.
2558
2558
2559 Output may be to a file, in which case the name of the file is
2559 Output may be to a file, in which case the name of the file is
2560 given using a template string. See :hg:`help templates`. In addition
2560 given using a template string. See :hg:`help templates`. In addition
2561 to the common template keywords, the following formatting rules are
2561 to the common template keywords, the following formatting rules are
2562 supported:
2562 supported:
2563
2563
2564 :``%%``: literal "%" character
2564 :``%%``: literal "%" character
2565 :``%H``: changeset hash (40 hexadecimal digits)
2565 :``%H``: changeset hash (40 hexadecimal digits)
2566 :``%N``: number of patches being generated
2566 :``%N``: number of patches being generated
2567 :``%R``: changeset revision number
2567 :``%R``: changeset revision number
2568 :``%b``: basename of the exporting repository
2568 :``%b``: basename of the exporting repository
2569 :``%h``: short-form changeset hash (12 hexadecimal digits)
2569 :``%h``: short-form changeset hash (12 hexadecimal digits)
2570 :``%m``: first line of the commit message (only alphanumeric characters)
2570 :``%m``: first line of the commit message (only alphanumeric characters)
2571 :``%n``: zero-padded sequence number, starting at 1
2571 :``%n``: zero-padded sequence number, starting at 1
2572 :``%r``: zero-padded changeset revision number
2572 :``%r``: zero-padded changeset revision number
2573 :``\\``: literal "\\" character
2573 :``\\``: literal "\\" character
2574
2574
2575 Without the -a/--text option, export will avoid generating diffs
2575 Without the -a/--text option, export will avoid generating diffs
2576 of files it detects as binary. With -a, export will generate a
2576 of files it detects as binary. With -a, export will generate a
2577 diff anyway, probably with undesirable results.
2577 diff anyway, probably with undesirable results.
2578
2578
2579 With -B/--bookmark changesets reachable by the given bookmark are
2579 With -B/--bookmark changesets reachable by the given bookmark are
2580 selected.
2580 selected.
2581
2581
2582 Use the -g/--git option to generate diffs in the git extended diff
2582 Use the -g/--git option to generate diffs in the git extended diff
2583 format. See :hg:`help diffs` for more information.
2583 format. See :hg:`help diffs` for more information.
2584
2584
2585 With the --switch-parent option, the diff will be against the
2585 With the --switch-parent option, the diff will be against the
2586 second parent. It can be useful to review a merge.
2586 second parent. It can be useful to review a merge.
2587
2587
2588 .. container:: verbose
2588 .. container:: verbose
2589
2589
2590 Template:
2590 Template:
2591
2591
2592 The following keywords are supported in addition to the common template
2592 The following keywords are supported in addition to the common template
2593 keywords and functions. See also :hg:`help templates`.
2593 keywords and functions. See also :hg:`help templates`.
2594
2594
2595 :diff: String. Diff content.
2595 :diff: String. Diff content.
2596 :parents: List of strings. Parent nodes of the changeset.
2596 :parents: List of strings. Parent nodes of the changeset.
2597
2597
2598 Examples:
2598 Examples:
2599
2599
2600 - use export and import to transplant a bugfix to the current
2600 - use export and import to transplant a bugfix to the current
2601 branch::
2601 branch::
2602
2602
2603 hg export -r 9353 | hg import -
2603 hg export -r 9353 | hg import -
2604
2604
2605 - export all the changesets between two revisions to a file with
2605 - export all the changesets between two revisions to a file with
2606 rename information::
2606 rename information::
2607
2607
2608 hg export --git -r 123:150 > changes.txt
2608 hg export --git -r 123:150 > changes.txt
2609
2609
2610 - split outgoing changes into a series of patches with
2610 - split outgoing changes into a series of patches with
2611 descriptive names::
2611 descriptive names::
2612
2612
2613 hg export -r "outgoing()" -o "%n-%m.patch"
2613 hg export -r "outgoing()" -o "%n-%m.patch"
2614
2614
2615 Returns 0 on success.
2615 Returns 0 on success.
2616 """
2616 """
2617 opts = pycompat.byteskwargs(opts)
2617 opts = pycompat.byteskwargs(opts)
2618 bookmark = opts.get(b'bookmark')
2618 bookmark = opts.get(b'bookmark')
2619 changesets += tuple(opts.get(b'rev', []))
2619 changesets += tuple(opts.get(b'rev', []))
2620
2620
2621 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2621 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2622
2622
2623 if bookmark:
2623 if bookmark:
2624 if bookmark not in repo._bookmarks:
2624 if bookmark not in repo._bookmarks:
2625 raise error.Abort(_(b"bookmark '%s' not found") % bookmark)
2625 raise error.Abort(_(b"bookmark '%s' not found") % bookmark)
2626
2626
2627 revs = scmutil.bookmarkrevs(repo, bookmark)
2627 revs = scmutil.bookmarkrevs(repo, bookmark)
2628 else:
2628 else:
2629 if not changesets:
2629 if not changesets:
2630 changesets = [b'.']
2630 changesets = [b'.']
2631
2631
2632 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2632 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2633 revs = scmutil.revrange(repo, changesets)
2633 revs = scmutil.revrange(repo, changesets)
2634
2634
2635 if not revs:
2635 if not revs:
2636 raise error.Abort(_(b"export requires at least one changeset"))
2636 raise error.Abort(_(b"export requires at least one changeset"))
2637 if len(revs) > 1:
2637 if len(revs) > 1:
2638 ui.note(_(b'exporting patches:\n'))
2638 ui.note(_(b'exporting patches:\n'))
2639 else:
2639 else:
2640 ui.note(_(b'exporting patch:\n'))
2640 ui.note(_(b'exporting patch:\n'))
2641
2641
2642 fntemplate = opts.get(b'output')
2642 fntemplate = opts.get(b'output')
2643 if cmdutil.isstdiofilename(fntemplate):
2643 if cmdutil.isstdiofilename(fntemplate):
2644 fntemplate = b''
2644 fntemplate = b''
2645
2645
2646 if fntemplate:
2646 if fntemplate:
2647 fm = formatter.nullformatter(ui, b'export', opts)
2647 fm = formatter.nullformatter(ui, b'export', opts)
2648 else:
2648 else:
2649 ui.pager(b'export')
2649 ui.pager(b'export')
2650 fm = ui.formatter(b'export', opts)
2650 fm = ui.formatter(b'export', opts)
2651 with fm:
2651 with fm:
2652 cmdutil.export(
2652 cmdutil.export(
2653 repo,
2653 repo,
2654 revs,
2654 revs,
2655 fm,
2655 fm,
2656 fntemplate=fntemplate,
2656 fntemplate=fntemplate,
2657 switch_parent=opts.get(b'switch_parent'),
2657 switch_parent=opts.get(b'switch_parent'),
2658 opts=patch.diffallopts(ui, opts),
2658 opts=patch.diffallopts(ui, opts),
2659 )
2659 )
2660
2660
2661
2661
2662 @command(
2662 @command(
2663 b'files',
2663 b'files',
2664 [
2664 [
2665 (
2665 (
2666 b'r',
2666 b'r',
2667 b'rev',
2667 b'rev',
2668 b'',
2668 b'',
2669 _(b'search the repository as it is in REV'),
2669 _(b'search the repository as it is in REV'),
2670 _(b'REV'),
2670 _(b'REV'),
2671 ),
2671 ),
2672 (
2672 (
2673 b'0',
2673 b'0',
2674 b'print0',
2674 b'print0',
2675 None,
2675 None,
2676 _(b'end filenames with NUL, for use with xargs'),
2676 _(b'end filenames with NUL, for use with xargs'),
2677 ),
2677 ),
2678 ]
2678 ]
2679 + walkopts
2679 + walkopts
2680 + formatteropts
2680 + formatteropts
2681 + subrepoopts,
2681 + subrepoopts,
2682 _(b'[OPTION]... [FILE]...'),
2682 _(b'[OPTION]... [FILE]...'),
2683 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2683 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2684 intents={INTENT_READONLY},
2684 intents={INTENT_READONLY},
2685 )
2685 )
2686 def files(ui, repo, *pats, **opts):
2686 def files(ui, repo, *pats, **opts):
2687 """list tracked files
2687 """list tracked files
2688
2688
2689 Print files under Mercurial control in the working directory or
2689 Print files under Mercurial control in the working directory or
2690 specified revision for given files (excluding removed files).
2690 specified revision for given files (excluding removed files).
2691 Files can be specified as filenames or filesets.
2691 Files can be specified as filenames or filesets.
2692
2692
2693 If no files are given to match, this command prints the names
2693 If no files are given to match, this command prints the names
2694 of all files under Mercurial control.
2694 of all files under Mercurial control.
2695
2695
2696 .. container:: verbose
2696 .. container:: verbose
2697
2697
2698 Template:
2698 Template:
2699
2699
2700 The following keywords are supported in addition to the common template
2700 The following keywords are supported in addition to the common template
2701 keywords and functions. See also :hg:`help templates`.
2701 keywords and functions. See also :hg:`help templates`.
2702
2702
2703 :flags: String. Character denoting file's symlink and executable bits.
2703 :flags: String. Character denoting file's symlink and executable bits.
2704 :path: String. Repository-absolute path of the file.
2704 :path: String. Repository-absolute path of the file.
2705 :size: Integer. Size of the file in bytes.
2705 :size: Integer. Size of the file in bytes.
2706
2706
2707 Examples:
2707 Examples:
2708
2708
2709 - list all files under the current directory::
2709 - list all files under the current directory::
2710
2710
2711 hg files .
2711 hg files .
2712
2712
2713 - shows sizes and flags for current revision::
2713 - shows sizes and flags for current revision::
2714
2714
2715 hg files -vr .
2715 hg files -vr .
2716
2716
2717 - list all files named README::
2717 - list all files named README::
2718
2718
2719 hg files -I "**/README"
2719 hg files -I "**/README"
2720
2720
2721 - list all binary files::
2721 - list all binary files::
2722
2722
2723 hg files "set:binary()"
2723 hg files "set:binary()"
2724
2724
2725 - find files containing a regular expression::
2725 - find files containing a regular expression::
2726
2726
2727 hg files "set:grep('bob')"
2727 hg files "set:grep('bob')"
2728
2728
2729 - search tracked file contents with xargs and grep::
2729 - search tracked file contents with xargs and grep::
2730
2730
2731 hg files -0 | xargs -0 grep foo
2731 hg files -0 | xargs -0 grep foo
2732
2732
2733 See :hg:`help patterns` and :hg:`help filesets` for more information
2733 See :hg:`help patterns` and :hg:`help filesets` for more information
2734 on specifying file patterns.
2734 on specifying file patterns.
2735
2735
2736 Returns 0 if a match is found, 1 otherwise.
2736 Returns 0 if a match is found, 1 otherwise.
2737
2737
2738 """
2738 """
2739
2739
2740 opts = pycompat.byteskwargs(opts)
2740 opts = pycompat.byteskwargs(opts)
2741 rev = opts.get(b'rev')
2741 rev = opts.get(b'rev')
2742 if rev:
2742 if rev:
2743 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2743 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2744 ctx = scmutil.revsingle(repo, rev, None)
2744 ctx = scmutil.revsingle(repo, rev, None)
2745
2745
2746 end = b'\n'
2746 end = b'\n'
2747 if opts.get(b'print0'):
2747 if opts.get(b'print0'):
2748 end = b'\0'
2748 end = b'\0'
2749 fmt = b'%s' + end
2749 fmt = b'%s' + end
2750
2750
2751 m = scmutil.match(ctx, pats, opts)
2751 m = scmutil.match(ctx, pats, opts)
2752 ui.pager(b'files')
2752 ui.pager(b'files')
2753 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2753 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2754 with ui.formatter(b'files', opts) as fm:
2754 with ui.formatter(b'files', opts) as fm:
2755 return cmdutil.files(
2755 return cmdutil.files(
2756 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2756 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2757 )
2757 )
2758
2758
2759
2759
2760 @command(
2760 @command(
2761 b'forget',
2761 b'forget',
2762 [(b'i', b'interactive', None, _(b'use interactive mode')),]
2762 [(b'i', b'interactive', None, _(b'use interactive mode')),]
2763 + walkopts
2763 + walkopts
2764 + dryrunopts,
2764 + dryrunopts,
2765 _(b'[OPTION]... FILE...'),
2765 _(b'[OPTION]... FILE...'),
2766 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2766 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2767 helpbasic=True,
2767 helpbasic=True,
2768 inferrepo=True,
2768 inferrepo=True,
2769 )
2769 )
2770 def forget(ui, repo, *pats, **opts):
2770 def forget(ui, repo, *pats, **opts):
2771 """forget the specified files on the next commit
2771 """forget the specified files on the next commit
2772
2772
2773 Mark the specified files so they will no longer be tracked
2773 Mark the specified files so they will no longer be tracked
2774 after the next commit.
2774 after the next commit.
2775
2775
2776 This only removes files from the current branch, not from the
2776 This only removes files from the current branch, not from the
2777 entire project history, and it does not delete them from the
2777 entire project history, and it does not delete them from the
2778 working directory.
2778 working directory.
2779
2779
2780 To delete the file from the working directory, see :hg:`remove`.
2780 To delete the file from the working directory, see :hg:`remove`.
2781
2781
2782 To undo a forget before the next commit, see :hg:`add`.
2782 To undo a forget before the next commit, see :hg:`add`.
2783
2783
2784 .. container:: verbose
2784 .. container:: verbose
2785
2785
2786 Examples:
2786 Examples:
2787
2787
2788 - forget newly-added binary files::
2788 - forget newly-added binary files::
2789
2789
2790 hg forget "set:added() and binary()"
2790 hg forget "set:added() and binary()"
2791
2791
2792 - forget files that would be excluded by .hgignore::
2792 - forget files that would be excluded by .hgignore::
2793
2793
2794 hg forget "set:hgignore()"
2794 hg forget "set:hgignore()"
2795
2795
2796 Returns 0 on success.
2796 Returns 0 on success.
2797 """
2797 """
2798
2798
2799 opts = pycompat.byteskwargs(opts)
2799 opts = pycompat.byteskwargs(opts)
2800 if not pats:
2800 if not pats:
2801 raise error.Abort(_(b'no files specified'))
2801 raise error.Abort(_(b'no files specified'))
2802
2802
2803 m = scmutil.match(repo[None], pats, opts)
2803 m = scmutil.match(repo[None], pats, opts)
2804 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2804 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2805 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2805 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2806 rejected = cmdutil.forget(
2806 rejected = cmdutil.forget(
2807 ui,
2807 ui,
2808 repo,
2808 repo,
2809 m,
2809 m,
2810 prefix=b"",
2810 prefix=b"",
2811 uipathfn=uipathfn,
2811 uipathfn=uipathfn,
2812 explicitonly=False,
2812 explicitonly=False,
2813 dryrun=dryrun,
2813 dryrun=dryrun,
2814 interactive=interactive,
2814 interactive=interactive,
2815 )[0]
2815 )[0]
2816 return rejected and 1 or 0
2816 return rejected and 1 or 0
2817
2817
2818
2818
2819 @command(
2819 @command(
2820 b'graft',
2820 b'graft',
2821 [
2821 [
2822 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2822 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2823 (
2823 (
2824 b'',
2824 b'',
2825 b'base',
2825 b'base',
2826 b'',
2826 b'',
2827 _(b'base revision when doing the graft merge (ADVANCED)'),
2827 _(b'base revision when doing the graft merge (ADVANCED)'),
2828 _(b'REV'),
2828 _(b'REV'),
2829 ),
2829 ),
2830 (b'c', b'continue', False, _(b'resume interrupted graft')),
2830 (b'c', b'continue', False, _(b'resume interrupted graft')),
2831 (b'', b'stop', False, _(b'stop interrupted graft')),
2831 (b'', b'stop', False, _(b'stop interrupted graft')),
2832 (b'', b'abort', False, _(b'abort interrupted graft')),
2832 (b'', b'abort', False, _(b'abort interrupted graft')),
2833 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2833 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2834 (b'', b'log', None, _(b'append graft info to log message')),
2834 (b'', b'log', None, _(b'append graft info to log message')),
2835 (
2835 (
2836 b'',
2836 b'',
2837 b'no-commit',
2837 b'no-commit',
2838 None,
2838 None,
2839 _(b"don't commit, just apply the changes in working directory"),
2839 _(b"don't commit, just apply the changes in working directory"),
2840 ),
2840 ),
2841 (b'f', b'force', False, _(b'force graft')),
2841 (b'f', b'force', False, _(b'force graft')),
2842 (
2842 (
2843 b'D',
2843 b'D',
2844 b'currentdate',
2844 b'currentdate',
2845 False,
2845 False,
2846 _(b'record the current date as commit date'),
2846 _(b'record the current date as commit date'),
2847 ),
2847 ),
2848 (
2848 (
2849 b'U',
2849 b'U',
2850 b'currentuser',
2850 b'currentuser',
2851 False,
2851 False,
2852 _(b'record the current user as committer'),
2852 _(b'record the current user as committer'),
2853 ),
2853 ),
2854 ]
2854 ]
2855 + commitopts2
2855 + commitopts2
2856 + mergetoolopts
2856 + mergetoolopts
2857 + dryrunopts,
2857 + dryrunopts,
2858 _(b'[OPTION]... [-r REV]... REV...'),
2858 _(b'[OPTION]... [-r REV]... REV...'),
2859 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2859 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2860 )
2860 )
2861 def graft(ui, repo, *revs, **opts):
2861 def graft(ui, repo, *revs, **opts):
2862 '''copy changes from other branches onto the current branch
2862 '''copy changes from other branches onto the current branch
2863
2863
2864 This command uses Mercurial's merge logic to copy individual
2864 This command uses Mercurial's merge logic to copy individual
2865 changes from other branches without merging branches in the
2865 changes from other branches without merging branches in the
2866 history graph. This is sometimes known as 'backporting' or
2866 history graph. This is sometimes known as 'backporting' or
2867 'cherry-picking'. By default, graft will copy user, date, and
2867 'cherry-picking'. By default, graft will copy user, date, and
2868 description from the source changesets.
2868 description from the source changesets.
2869
2869
2870 Changesets that are ancestors of the current revision, that have
2870 Changesets that are ancestors of the current revision, that have
2871 already been grafted, or that are merges will be skipped.
2871 already been grafted, or that are merges will be skipped.
2872
2872
2873 If --log is specified, log messages will have a comment appended
2873 If --log is specified, log messages will have a comment appended
2874 of the form::
2874 of the form::
2875
2875
2876 (grafted from CHANGESETHASH)
2876 (grafted from CHANGESETHASH)
2877
2877
2878 If --force is specified, revisions will be grafted even if they
2878 If --force is specified, revisions will be grafted even if they
2879 are already ancestors of, or have been grafted to, the destination.
2879 are already ancestors of, or have been grafted to, the destination.
2880 This is useful when the revisions have since been backed out.
2880 This is useful when the revisions have since been backed out.
2881
2881
2882 If a graft merge results in conflicts, the graft process is
2882 If a graft merge results in conflicts, the graft process is
2883 interrupted so that the current merge can be manually resolved.
2883 interrupted so that the current merge can be manually resolved.
2884 Once all conflicts are addressed, the graft process can be
2884 Once all conflicts are addressed, the graft process can be
2885 continued with the -c/--continue option.
2885 continued with the -c/--continue option.
2886
2886
2887 The -c/--continue option reapplies all the earlier options.
2887 The -c/--continue option reapplies all the earlier options.
2888
2888
2889 .. container:: verbose
2889 .. container:: verbose
2890
2890
2891 The --base option exposes more of how graft internally uses merge with a
2891 The --base option exposes more of how graft internally uses merge with a
2892 custom base revision. --base can be used to specify another ancestor than
2892 custom base revision. --base can be used to specify another ancestor than
2893 the first and only parent.
2893 the first and only parent.
2894
2894
2895 The command::
2895 The command::
2896
2896
2897 hg graft -r 345 --base 234
2897 hg graft -r 345 --base 234
2898
2898
2899 is thus pretty much the same as::
2899 is thus pretty much the same as::
2900
2900
2901 hg diff -r 234 -r 345 | hg import
2901 hg diff -r 234 -r 345 | hg import
2902
2902
2903 but using merge to resolve conflicts and track moved files.
2903 but using merge to resolve conflicts and track moved files.
2904
2904
2905 The result of a merge can thus be backported as a single commit by
2905 The result of a merge can thus be backported as a single commit by
2906 specifying one of the merge parents as base, and thus effectively
2906 specifying one of the merge parents as base, and thus effectively
2907 grafting the changes from the other side.
2907 grafting the changes from the other side.
2908
2908
2909 It is also possible to collapse multiple changesets and clean up history
2909 It is also possible to collapse multiple changesets and clean up history
2910 by specifying another ancestor as base, much like rebase --collapse
2910 by specifying another ancestor as base, much like rebase --collapse
2911 --keep.
2911 --keep.
2912
2912
2913 The commit message can be tweaked after the fact using commit --amend .
2913 The commit message can be tweaked after the fact using commit --amend .
2914
2914
2915 For using non-ancestors as the base to backout changes, see the backout
2915 For using non-ancestors as the base to backout changes, see the backout
2916 command and the hidden --parent option.
2916 command and the hidden --parent option.
2917
2917
2918 .. container:: verbose
2918 .. container:: verbose
2919
2919
2920 Examples:
2920 Examples:
2921
2921
2922 - copy a single change to the stable branch and edit its description::
2922 - copy a single change to the stable branch and edit its description::
2923
2923
2924 hg update stable
2924 hg update stable
2925 hg graft --edit 9393
2925 hg graft --edit 9393
2926
2926
2927 - graft a range of changesets with one exception, updating dates::
2927 - graft a range of changesets with one exception, updating dates::
2928
2928
2929 hg graft -D "2085::2093 and not 2091"
2929 hg graft -D "2085::2093 and not 2091"
2930
2930
2931 - continue a graft after resolving conflicts::
2931 - continue a graft after resolving conflicts::
2932
2932
2933 hg graft -c
2933 hg graft -c
2934
2934
2935 - show the source of a grafted changeset::
2935 - show the source of a grafted changeset::
2936
2936
2937 hg log --debug -r .
2937 hg log --debug -r .
2938
2938
2939 - show revisions sorted by date::
2939 - show revisions sorted by date::
2940
2940
2941 hg log -r "sort(all(), date)"
2941 hg log -r "sort(all(), date)"
2942
2942
2943 - backport the result of a merge as a single commit::
2943 - backport the result of a merge as a single commit::
2944
2944
2945 hg graft -r 123 --base 123^
2945 hg graft -r 123 --base 123^
2946
2946
2947 - land a feature branch as one changeset::
2947 - land a feature branch as one changeset::
2948
2948
2949 hg up -cr default
2949 hg up -cr default
2950 hg graft -r featureX --base "ancestor('featureX', 'default')"
2950 hg graft -r featureX --base "ancestor('featureX', 'default')"
2951
2951
2952 See :hg:`help revisions` for more about specifying revisions.
2952 See :hg:`help revisions` for more about specifying revisions.
2953
2953
2954 Returns 0 on successful completion.
2954 Returns 0 on successful completion, 1 if there are unresolved files.
2955 '''
2955 '''
2956 with repo.wlock():
2956 with repo.wlock():
2957 return _dograft(ui, repo, *revs, **opts)
2957 return _dograft(ui, repo, *revs, **opts)
2958
2958
2959
2959
2960 def _dograft(ui, repo, *revs, **opts):
2960 def _dograft(ui, repo, *revs, **opts):
2961 opts = pycompat.byteskwargs(opts)
2961 opts = pycompat.byteskwargs(opts)
2962 if revs and opts.get(b'rev'):
2962 if revs and opts.get(b'rev'):
2963 ui.warn(
2963 ui.warn(
2964 _(
2964 _(
2965 b'warning: inconsistent use of --rev might give unexpected '
2965 b'warning: inconsistent use of --rev might give unexpected '
2966 b'revision ordering!\n'
2966 b'revision ordering!\n'
2967 )
2967 )
2968 )
2968 )
2969
2969
2970 revs = list(revs)
2970 revs = list(revs)
2971 revs.extend(opts.get(b'rev'))
2971 revs.extend(opts.get(b'rev'))
2972 basectx = None
2972 basectx = None
2973 if opts.get(b'base'):
2973 if opts.get(b'base'):
2974 basectx = scmutil.revsingle(repo, opts[b'base'], None)
2974 basectx = scmutil.revsingle(repo, opts[b'base'], None)
2975 # a dict of data to be stored in state file
2975 # a dict of data to be stored in state file
2976 statedata = {}
2976 statedata = {}
2977 # list of new nodes created by ongoing graft
2977 # list of new nodes created by ongoing graft
2978 statedata[b'newnodes'] = []
2978 statedata[b'newnodes'] = []
2979
2979
2980 cmdutil.resolvecommitoptions(ui, opts)
2980 cmdutil.resolvecommitoptions(ui, opts)
2981
2981
2982 editor = cmdutil.getcommiteditor(
2982 editor = cmdutil.getcommiteditor(
2983 editform=b'graft', **pycompat.strkwargs(opts)
2983 editform=b'graft', **pycompat.strkwargs(opts)
2984 )
2984 )
2985
2985
2986 cont = False
2986 cont = False
2987 if opts.get(b'no_commit'):
2987 if opts.get(b'no_commit'):
2988 if opts.get(b'edit'):
2988 if opts.get(b'edit'):
2989 raise error.Abort(
2989 raise error.Abort(
2990 _(b"cannot specify --no-commit and --edit together")
2990 _(b"cannot specify --no-commit and --edit together")
2991 )
2991 )
2992 if opts.get(b'currentuser'):
2992 if opts.get(b'currentuser'):
2993 raise error.Abort(
2993 raise error.Abort(
2994 _(b"cannot specify --no-commit and --currentuser together")
2994 _(b"cannot specify --no-commit and --currentuser together")
2995 )
2995 )
2996 if opts.get(b'currentdate'):
2996 if opts.get(b'currentdate'):
2997 raise error.Abort(
2997 raise error.Abort(
2998 _(b"cannot specify --no-commit and --currentdate together")
2998 _(b"cannot specify --no-commit and --currentdate together")
2999 )
2999 )
3000 if opts.get(b'log'):
3000 if opts.get(b'log'):
3001 raise error.Abort(
3001 raise error.Abort(
3002 _(b"cannot specify --no-commit and --log together")
3002 _(b"cannot specify --no-commit and --log together")
3003 )
3003 )
3004
3004
3005 graftstate = statemod.cmdstate(repo, b'graftstate')
3005 graftstate = statemod.cmdstate(repo, b'graftstate')
3006
3006
3007 if opts.get(b'stop'):
3007 if opts.get(b'stop'):
3008 if opts.get(b'continue'):
3008 if opts.get(b'continue'):
3009 raise error.Abort(
3009 raise error.Abort(
3010 _(b"cannot use '--continue' and '--stop' together")
3010 _(b"cannot use '--continue' and '--stop' together")
3011 )
3011 )
3012 if opts.get(b'abort'):
3012 if opts.get(b'abort'):
3013 raise error.Abort(_(b"cannot use '--abort' and '--stop' together"))
3013 raise error.Abort(_(b"cannot use '--abort' and '--stop' together"))
3014
3014
3015 if any(
3015 if any(
3016 (
3016 (
3017 opts.get(b'edit'),
3017 opts.get(b'edit'),
3018 opts.get(b'log'),
3018 opts.get(b'log'),
3019 opts.get(b'user'),
3019 opts.get(b'user'),
3020 opts.get(b'date'),
3020 opts.get(b'date'),
3021 opts.get(b'currentdate'),
3021 opts.get(b'currentdate'),
3022 opts.get(b'currentuser'),
3022 opts.get(b'currentuser'),
3023 opts.get(b'rev'),
3023 opts.get(b'rev'),
3024 )
3024 )
3025 ):
3025 ):
3026 raise error.Abort(_(b"cannot specify any other flag with '--stop'"))
3026 raise error.Abort(_(b"cannot specify any other flag with '--stop'"))
3027 return _stopgraft(ui, repo, graftstate)
3027 return _stopgraft(ui, repo, graftstate)
3028 elif opts.get(b'abort'):
3028 elif opts.get(b'abort'):
3029 if opts.get(b'continue'):
3029 if opts.get(b'continue'):
3030 raise error.Abort(
3030 raise error.Abort(
3031 _(b"cannot use '--continue' and '--abort' together")
3031 _(b"cannot use '--continue' and '--abort' together")
3032 )
3032 )
3033 if any(
3033 if any(
3034 (
3034 (
3035 opts.get(b'edit'),
3035 opts.get(b'edit'),
3036 opts.get(b'log'),
3036 opts.get(b'log'),
3037 opts.get(b'user'),
3037 opts.get(b'user'),
3038 opts.get(b'date'),
3038 opts.get(b'date'),
3039 opts.get(b'currentdate'),
3039 opts.get(b'currentdate'),
3040 opts.get(b'currentuser'),
3040 opts.get(b'currentuser'),
3041 opts.get(b'rev'),
3041 opts.get(b'rev'),
3042 )
3042 )
3043 ):
3043 ):
3044 raise error.Abort(
3044 raise error.Abort(
3045 _(b"cannot specify any other flag with '--abort'")
3045 _(b"cannot specify any other flag with '--abort'")
3046 )
3046 )
3047
3047
3048 return cmdutil.abortgraft(ui, repo, graftstate)
3048 return cmdutil.abortgraft(ui, repo, graftstate)
3049 elif opts.get(b'continue'):
3049 elif opts.get(b'continue'):
3050 cont = True
3050 cont = True
3051 if revs:
3051 if revs:
3052 raise error.Abort(_(b"can't specify --continue and revisions"))
3052 raise error.Abort(_(b"can't specify --continue and revisions"))
3053 # read in unfinished revisions
3053 # read in unfinished revisions
3054 if graftstate.exists():
3054 if graftstate.exists():
3055 statedata = cmdutil.readgraftstate(repo, graftstate)
3055 statedata = cmdutil.readgraftstate(repo, graftstate)
3056 if statedata.get(b'date'):
3056 if statedata.get(b'date'):
3057 opts[b'date'] = statedata[b'date']
3057 opts[b'date'] = statedata[b'date']
3058 if statedata.get(b'user'):
3058 if statedata.get(b'user'):
3059 opts[b'user'] = statedata[b'user']
3059 opts[b'user'] = statedata[b'user']
3060 if statedata.get(b'log'):
3060 if statedata.get(b'log'):
3061 opts[b'log'] = True
3061 opts[b'log'] = True
3062 if statedata.get(b'no_commit'):
3062 if statedata.get(b'no_commit'):
3063 opts[b'no_commit'] = statedata.get(b'no_commit')
3063 opts[b'no_commit'] = statedata.get(b'no_commit')
3064 nodes = statedata[b'nodes']
3064 nodes = statedata[b'nodes']
3065 revs = [repo[node].rev() for node in nodes]
3065 revs = [repo[node].rev() for node in nodes]
3066 else:
3066 else:
3067 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3067 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3068 else:
3068 else:
3069 if not revs:
3069 if not revs:
3070 raise error.Abort(_(b'no revisions specified'))
3070 raise error.Abort(_(b'no revisions specified'))
3071 cmdutil.checkunfinished(repo)
3071 cmdutil.checkunfinished(repo)
3072 cmdutil.bailifchanged(repo)
3072 cmdutil.bailifchanged(repo)
3073 revs = scmutil.revrange(repo, revs)
3073 revs = scmutil.revrange(repo, revs)
3074
3074
3075 skipped = set()
3075 skipped = set()
3076 if basectx is None:
3076 if basectx is None:
3077 # check for merges
3077 # check for merges
3078 for rev in repo.revs(b'%ld and merge()', revs):
3078 for rev in repo.revs(b'%ld and merge()', revs):
3079 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3079 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3080 skipped.add(rev)
3080 skipped.add(rev)
3081 revs = [r for r in revs if r not in skipped]
3081 revs = [r for r in revs if r not in skipped]
3082 if not revs:
3082 if not revs:
3083 return -1
3083 return -1
3084 if basectx is not None and len(revs) != 1:
3084 if basectx is not None and len(revs) != 1:
3085 raise error.Abort(_(b'only one revision allowed with --base '))
3085 raise error.Abort(_(b'only one revision allowed with --base '))
3086
3086
3087 # Don't check in the --continue case, in effect retaining --force across
3087 # Don't check in the --continue case, in effect retaining --force across
3088 # --continues. That's because without --force, any revisions we decided to
3088 # --continues. That's because without --force, any revisions we decided to
3089 # skip would have been filtered out here, so they wouldn't have made their
3089 # skip would have been filtered out here, so they wouldn't have made their
3090 # way to the graftstate. With --force, any revisions we would have otherwise
3090 # way to the graftstate. With --force, any revisions we would have otherwise
3091 # skipped would not have been filtered out, and if they hadn't been applied
3091 # skipped would not have been filtered out, and if they hadn't been applied
3092 # already, they'd have been in the graftstate.
3092 # already, they'd have been in the graftstate.
3093 if not (cont or opts.get(b'force')) and basectx is None:
3093 if not (cont or opts.get(b'force')) and basectx is None:
3094 # check for ancestors of dest branch
3094 # check for ancestors of dest branch
3095 ancestors = repo.revs(b'%ld & (::.)', revs)
3095 ancestors = repo.revs(b'%ld & (::.)', revs)
3096 for rev in ancestors:
3096 for rev in ancestors:
3097 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3097 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3098
3098
3099 revs = [r for r in revs if r not in ancestors]
3099 revs = [r for r in revs if r not in ancestors]
3100
3100
3101 if not revs:
3101 if not revs:
3102 return -1
3102 return -1
3103
3103
3104 # analyze revs for earlier grafts
3104 # analyze revs for earlier grafts
3105 ids = {}
3105 ids = {}
3106 for ctx in repo.set(b"%ld", revs):
3106 for ctx in repo.set(b"%ld", revs):
3107 ids[ctx.hex()] = ctx.rev()
3107 ids[ctx.hex()] = ctx.rev()
3108 n = ctx.extra().get(b'source')
3108 n = ctx.extra().get(b'source')
3109 if n:
3109 if n:
3110 ids[n] = ctx.rev()
3110 ids[n] = ctx.rev()
3111
3111
3112 # check ancestors for earlier grafts
3112 # check ancestors for earlier grafts
3113 ui.debug(b'scanning for duplicate grafts\n')
3113 ui.debug(b'scanning for duplicate grafts\n')
3114
3114
3115 # The only changesets we can be sure doesn't contain grafts of any
3115 # The only changesets we can be sure doesn't contain grafts of any
3116 # revs, are the ones that are common ancestors of *all* revs:
3116 # revs, are the ones that are common ancestors of *all* revs:
3117 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3117 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3118 ctx = repo[rev]
3118 ctx = repo[rev]
3119 n = ctx.extra().get(b'source')
3119 n = ctx.extra().get(b'source')
3120 if n in ids:
3120 if n in ids:
3121 try:
3121 try:
3122 r = repo[n].rev()
3122 r = repo[n].rev()
3123 except error.RepoLookupError:
3123 except error.RepoLookupError:
3124 r = None
3124 r = None
3125 if r in revs:
3125 if r in revs:
3126 ui.warn(
3126 ui.warn(
3127 _(
3127 _(
3128 b'skipping revision %d:%s '
3128 b'skipping revision %d:%s '
3129 b'(already grafted to %d:%s)\n'
3129 b'(already grafted to %d:%s)\n'
3130 )
3130 )
3131 % (r, repo[r], rev, ctx)
3131 % (r, repo[r], rev, ctx)
3132 )
3132 )
3133 revs.remove(r)
3133 revs.remove(r)
3134 elif ids[n] in revs:
3134 elif ids[n] in revs:
3135 if r is None:
3135 if r is None:
3136 ui.warn(
3136 ui.warn(
3137 _(
3137 _(
3138 b'skipping already grafted revision %d:%s '
3138 b'skipping already grafted revision %d:%s '
3139 b'(%d:%s also has unknown origin %s)\n'
3139 b'(%d:%s also has unknown origin %s)\n'
3140 )
3140 )
3141 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3141 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3142 )
3142 )
3143 else:
3143 else:
3144 ui.warn(
3144 ui.warn(
3145 _(
3145 _(
3146 b'skipping already grafted revision %d:%s '
3146 b'skipping already grafted revision %d:%s '
3147 b'(%d:%s also has origin %d:%s)\n'
3147 b'(%d:%s also has origin %d:%s)\n'
3148 )
3148 )
3149 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3149 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3150 )
3150 )
3151 revs.remove(ids[n])
3151 revs.remove(ids[n])
3152 elif ctx.hex() in ids:
3152 elif ctx.hex() in ids:
3153 r = ids[ctx.hex()]
3153 r = ids[ctx.hex()]
3154 if r in revs:
3154 if r in revs:
3155 ui.warn(
3155 ui.warn(
3156 _(
3156 _(
3157 b'skipping already grafted revision %d:%s '
3157 b'skipping already grafted revision %d:%s '
3158 b'(was grafted from %d:%s)\n'
3158 b'(was grafted from %d:%s)\n'
3159 )
3159 )
3160 % (r, repo[r], rev, ctx)
3160 % (r, repo[r], rev, ctx)
3161 )
3161 )
3162 revs.remove(r)
3162 revs.remove(r)
3163 if not revs:
3163 if not revs:
3164 return -1
3164 return -1
3165
3165
3166 if opts.get(b'no_commit'):
3166 if opts.get(b'no_commit'):
3167 statedata[b'no_commit'] = True
3167 statedata[b'no_commit'] = True
3168 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3168 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3169 desc = b'%d:%s "%s"' % (
3169 desc = b'%d:%s "%s"' % (
3170 ctx.rev(),
3170 ctx.rev(),
3171 ctx,
3171 ctx,
3172 ctx.description().split(b'\n', 1)[0],
3172 ctx.description().split(b'\n', 1)[0],
3173 )
3173 )
3174 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3174 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3175 if names:
3175 if names:
3176 desc += b' (%s)' % b' '.join(names)
3176 desc += b' (%s)' % b' '.join(names)
3177 ui.status(_(b'grafting %s\n') % desc)
3177 ui.status(_(b'grafting %s\n') % desc)
3178 if opts.get(b'dry_run'):
3178 if opts.get(b'dry_run'):
3179 continue
3179 continue
3180
3180
3181 source = ctx.extra().get(b'source')
3181 source = ctx.extra().get(b'source')
3182 extra = {}
3182 extra = {}
3183 if source:
3183 if source:
3184 extra[b'source'] = source
3184 extra[b'source'] = source
3185 extra[b'intermediate-source'] = ctx.hex()
3185 extra[b'intermediate-source'] = ctx.hex()
3186 else:
3186 else:
3187 extra[b'source'] = ctx.hex()
3187 extra[b'source'] = ctx.hex()
3188 user = ctx.user()
3188 user = ctx.user()
3189 if opts.get(b'user'):
3189 if opts.get(b'user'):
3190 user = opts[b'user']
3190 user = opts[b'user']
3191 statedata[b'user'] = user
3191 statedata[b'user'] = user
3192 date = ctx.date()
3192 date = ctx.date()
3193 if opts.get(b'date'):
3193 if opts.get(b'date'):
3194 date = opts[b'date']
3194 date = opts[b'date']
3195 statedata[b'date'] = date
3195 statedata[b'date'] = date
3196 message = ctx.description()
3196 message = ctx.description()
3197 if opts.get(b'log'):
3197 if opts.get(b'log'):
3198 message += b'\n(grafted from %s)' % ctx.hex()
3198 message += b'\n(grafted from %s)' % ctx.hex()
3199 statedata[b'log'] = True
3199 statedata[b'log'] = True
3200
3200
3201 # we don't merge the first commit when continuing
3201 # we don't merge the first commit when continuing
3202 if not cont:
3202 if not cont:
3203 # perform the graft merge with p1(rev) as 'ancestor'
3203 # perform the graft merge with p1(rev) as 'ancestor'
3204 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3204 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3205 base = ctx.p1() if basectx is None else basectx
3205 base = ctx.p1() if basectx is None else basectx
3206 with ui.configoverride(overrides, b'graft'):
3206 with ui.configoverride(overrides, b'graft'):
3207 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3207 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3208 # report any conflicts
3208 # report any conflicts
3209 if stats.unresolvedcount > 0:
3209 if stats.unresolvedcount > 0:
3210 # write out state for --continue
3210 # write out state for --continue
3211 nodes = [repo[rev].hex() for rev in revs[pos:]]
3211 nodes = [repo[rev].hex() for rev in revs[pos:]]
3212 statedata[b'nodes'] = nodes
3212 statedata[b'nodes'] = nodes
3213 stateversion = 1
3213 stateversion = 1
3214 graftstate.save(stateversion, statedata)
3214 graftstate.save(stateversion, statedata)
3215 hint = _(b"use 'hg resolve' and 'hg graft --continue'")
3215 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3216 raise error.Abort(
3216 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3217 _(b"unresolved conflicts, can't continue"), hint=hint
3217 return 1
3218 )
3219 else:
3218 else:
3220 cont = False
3219 cont = False
3221
3220
3222 # commit if --no-commit is false
3221 # commit if --no-commit is false
3223 if not opts.get(b'no_commit'):
3222 if not opts.get(b'no_commit'):
3224 node = repo.commit(
3223 node = repo.commit(
3225 text=message, user=user, date=date, extra=extra, editor=editor
3224 text=message, user=user, date=date, extra=extra, editor=editor
3226 )
3225 )
3227 if node is None:
3226 if node is None:
3228 ui.warn(
3227 ui.warn(
3229 _(b'note: graft of %d:%s created no changes to commit\n')
3228 _(b'note: graft of %d:%s created no changes to commit\n')
3230 % (ctx.rev(), ctx)
3229 % (ctx.rev(), ctx)
3231 )
3230 )
3232 # checking that newnodes exist because old state files won't have it
3231 # checking that newnodes exist because old state files won't have it
3233 elif statedata.get(b'newnodes') is not None:
3232 elif statedata.get(b'newnodes') is not None:
3234 statedata[b'newnodes'].append(node)
3233 statedata[b'newnodes'].append(node)
3235
3234
3236 # remove state when we complete successfully
3235 # remove state when we complete successfully
3237 if not opts.get(b'dry_run'):
3236 if not opts.get(b'dry_run'):
3238 graftstate.delete()
3237 graftstate.delete()
3239
3238
3240 return 0
3239 return 0
3241
3240
3242
3241
3243 def _stopgraft(ui, repo, graftstate):
3242 def _stopgraft(ui, repo, graftstate):
3244 """stop the interrupted graft"""
3243 """stop the interrupted graft"""
3245 if not graftstate.exists():
3244 if not graftstate.exists():
3246 raise error.Abort(_(b"no interrupted graft found"))
3245 raise error.Abort(_(b"no interrupted graft found"))
3247 pctx = repo[b'.']
3246 pctx = repo[b'.']
3248 hg.updaterepo(repo, pctx.node(), overwrite=True)
3247 hg.updaterepo(repo, pctx.node(), overwrite=True)
3249 graftstate.delete()
3248 graftstate.delete()
3250 ui.status(_(b"stopped the interrupted graft\n"))
3249 ui.status(_(b"stopped the interrupted graft\n"))
3251 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3250 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3252 return 0
3251 return 0
3253
3252
3254
3253
3255 statemod.addunfinished(
3254 statemod.addunfinished(
3256 b'graft',
3255 b'graft',
3257 fname=b'graftstate',
3256 fname=b'graftstate',
3258 clearable=True,
3257 clearable=True,
3259 stopflag=True,
3258 stopflag=True,
3260 continueflag=True,
3259 continueflag=True,
3261 abortfunc=cmdutil.hgabortgraft,
3260 abortfunc=cmdutil.hgabortgraft,
3262 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3261 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3263 )
3262 )
3264
3263
3265
3264
3266 @command(
3265 @command(
3267 b'grep',
3266 b'grep',
3268 [
3267 [
3269 (b'0', b'print0', None, _(b'end fields with NUL')),
3268 (b'0', b'print0', None, _(b'end fields with NUL')),
3270 (b'', b'all', None, _(b'print all revisions that match (DEPRECATED) ')),
3269 (b'', b'all', None, _(b'print all revisions that match (DEPRECATED) ')),
3271 (
3270 (
3272 b'',
3271 b'',
3273 b'diff',
3272 b'diff',
3274 None,
3273 None,
3275 _(
3274 _(
3276 b'search revision differences for when the pattern was added '
3275 b'search revision differences for when the pattern was added '
3277 b'or removed'
3276 b'or removed'
3278 ),
3277 ),
3279 ),
3278 ),
3280 (b'a', b'text', None, _(b'treat all files as text')),
3279 (b'a', b'text', None, _(b'treat all files as text')),
3281 (
3280 (
3282 b'f',
3281 b'f',
3283 b'follow',
3282 b'follow',
3284 None,
3283 None,
3285 _(
3284 _(
3286 b'follow changeset history,'
3285 b'follow changeset history,'
3287 b' or file history across copies and renames'
3286 b' or file history across copies and renames'
3288 ),
3287 ),
3289 ),
3288 ),
3290 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3289 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3291 (
3290 (
3292 b'l',
3291 b'l',
3293 b'files-with-matches',
3292 b'files-with-matches',
3294 None,
3293 None,
3295 _(b'print only filenames and revisions that match'),
3294 _(b'print only filenames and revisions that match'),
3296 ),
3295 ),
3297 (b'n', b'line-number', None, _(b'print matching line numbers')),
3296 (b'n', b'line-number', None, _(b'print matching line numbers')),
3298 (
3297 (
3299 b'r',
3298 b'r',
3300 b'rev',
3299 b'rev',
3301 [],
3300 [],
3302 _(b'search files changed within revision range'),
3301 _(b'search files changed within revision range'),
3303 _(b'REV'),
3302 _(b'REV'),
3304 ),
3303 ),
3305 (
3304 (
3306 b'',
3305 b'',
3307 b'all-files',
3306 b'all-files',
3308 None,
3307 None,
3309 _(
3308 _(
3310 b'include all files in the changeset while grepping (DEPRECATED)'
3309 b'include all files in the changeset while grepping (DEPRECATED)'
3311 ),
3310 ),
3312 ),
3311 ),
3313 (b'u', b'user', None, _(b'list the author (long with -v)')),
3312 (b'u', b'user', None, _(b'list the author (long with -v)')),
3314 (b'd', b'date', None, _(b'list the date (short with -q)')),
3313 (b'd', b'date', None, _(b'list the date (short with -q)')),
3315 ]
3314 ]
3316 + formatteropts
3315 + formatteropts
3317 + walkopts,
3316 + walkopts,
3318 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3317 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3319 helpcategory=command.CATEGORY_FILE_CONTENTS,
3318 helpcategory=command.CATEGORY_FILE_CONTENTS,
3320 inferrepo=True,
3319 inferrepo=True,
3321 intents={INTENT_READONLY},
3320 intents={INTENT_READONLY},
3322 )
3321 )
3323 def grep(ui, repo, pattern, *pats, **opts):
3322 def grep(ui, repo, pattern, *pats, **opts):
3324 """search for a pattern in specified files
3323 """search for a pattern in specified files
3325
3324
3326 Search the working directory or revision history for a regular
3325 Search the working directory or revision history for a regular
3327 expression in the specified files for the entire repository.
3326 expression in the specified files for the entire repository.
3328
3327
3329 By default, grep searches the repository files in the working
3328 By default, grep searches the repository files in the working
3330 directory and prints the files where it finds a match. To specify
3329 directory and prints the files where it finds a match. To specify
3331 historical revisions instead of the working directory, use the
3330 historical revisions instead of the working directory, use the
3332 --rev flag.
3331 --rev flag.
3333
3332
3334 To search instead historical revision differences that contains a
3333 To search instead historical revision differences that contains a
3335 change in match status ("-" for a match that becomes a non-match,
3334 change in match status ("-" for a match that becomes a non-match,
3336 or "+" for a non-match that becomes a match), use the --diff flag.
3335 or "+" for a non-match that becomes a match), use the --diff flag.
3337
3336
3338 PATTERN can be any Python (roughly Perl-compatible) regular
3337 PATTERN can be any Python (roughly Perl-compatible) regular
3339 expression.
3338 expression.
3340
3339
3341 If no FILEs are specified and the --rev flag isn't supplied, all
3340 If no FILEs are specified and the --rev flag isn't supplied, all
3342 files in the working directory are searched. When using the --rev
3341 files in the working directory are searched. When using the --rev
3343 flag and specifying FILEs, use the --follow argument to also
3342 flag and specifying FILEs, use the --follow argument to also
3344 follow the specified FILEs across renames and copies.
3343 follow the specified FILEs across renames and copies.
3345
3344
3346 .. container:: verbose
3345 .. container:: verbose
3347
3346
3348 Template:
3347 Template:
3349
3348
3350 The following keywords are supported in addition to the common template
3349 The following keywords are supported in addition to the common template
3351 keywords and functions. See also :hg:`help templates`.
3350 keywords and functions. See also :hg:`help templates`.
3352
3351
3353 :change: String. Character denoting insertion ``+`` or removal ``-``.
3352 :change: String. Character denoting insertion ``+`` or removal ``-``.
3354 Available if ``--diff`` is specified.
3353 Available if ``--diff`` is specified.
3355 :lineno: Integer. Line number of the match.
3354 :lineno: Integer. Line number of the match.
3356 :path: String. Repository-absolute path of the file.
3355 :path: String. Repository-absolute path of the file.
3357 :texts: List of text chunks.
3356 :texts: List of text chunks.
3358
3357
3359 And each entry of ``{texts}`` provides the following sub-keywords.
3358 And each entry of ``{texts}`` provides the following sub-keywords.
3360
3359
3361 :matched: Boolean. True if the chunk matches the specified pattern.
3360 :matched: Boolean. True if the chunk matches the specified pattern.
3362 :text: String. Chunk content.
3361 :text: String. Chunk content.
3363
3362
3364 See :hg:`help templates.operators` for the list expansion syntax.
3363 See :hg:`help templates.operators` for the list expansion syntax.
3365
3364
3366 Returns 0 if a match is found, 1 otherwise.
3365 Returns 0 if a match is found, 1 otherwise.
3367
3366
3368 """
3367 """
3369 opts = pycompat.byteskwargs(opts)
3368 opts = pycompat.byteskwargs(opts)
3370 diff = opts.get(b'all') or opts.get(b'diff')
3369 diff = opts.get(b'all') or opts.get(b'diff')
3371 if diff and opts.get(b'all_files'):
3370 if diff and opts.get(b'all_files'):
3372 raise error.Abort(_(b'--diff and --all-files are mutually exclusive'))
3371 raise error.Abort(_(b'--diff and --all-files are mutually exclusive'))
3373 if opts.get(b'all_files') is None and not diff:
3372 if opts.get(b'all_files') is None and not diff:
3374 opts[b'all_files'] = True
3373 opts[b'all_files'] = True
3375 plaingrep = opts.get(b'all_files') and not opts.get(b'rev')
3374 plaingrep = opts.get(b'all_files') and not opts.get(b'rev')
3376 all_files = opts.get(b'all_files')
3375 all_files = opts.get(b'all_files')
3377 if plaingrep:
3376 if plaingrep:
3378 opts[b'rev'] = [b'wdir()']
3377 opts[b'rev'] = [b'wdir()']
3379
3378
3380 reflags = re.M
3379 reflags = re.M
3381 if opts.get(b'ignore_case'):
3380 if opts.get(b'ignore_case'):
3382 reflags |= re.I
3381 reflags |= re.I
3383 try:
3382 try:
3384 regexp = util.re.compile(pattern, reflags)
3383 regexp = util.re.compile(pattern, reflags)
3385 except re.error as inst:
3384 except re.error as inst:
3386 ui.warn(
3385 ui.warn(
3387 _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
3386 _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
3388 )
3387 )
3389 return 1
3388 return 1
3390 sep, eol = b':', b'\n'
3389 sep, eol = b':', b'\n'
3391 if opts.get(b'print0'):
3390 if opts.get(b'print0'):
3392 sep = eol = b'\0'
3391 sep = eol = b'\0'
3393
3392
3394 getfile = util.lrucachefunc(repo.file)
3393 getfile = util.lrucachefunc(repo.file)
3395
3394
3396 def matchlines(body):
3395 def matchlines(body):
3397 begin = 0
3396 begin = 0
3398 linenum = 0
3397 linenum = 0
3399 while begin < len(body):
3398 while begin < len(body):
3400 match = regexp.search(body, begin)
3399 match = regexp.search(body, begin)
3401 if not match:
3400 if not match:
3402 break
3401 break
3403 mstart, mend = match.span()
3402 mstart, mend = match.span()
3404 linenum += body.count(b'\n', begin, mstart) + 1
3403 linenum += body.count(b'\n', begin, mstart) + 1
3405 lstart = body.rfind(b'\n', begin, mstart) + 1 or begin
3404 lstart = body.rfind(b'\n', begin, mstart) + 1 or begin
3406 begin = body.find(b'\n', mend) + 1 or len(body) + 1
3405 begin = body.find(b'\n', mend) + 1 or len(body) + 1
3407 lend = begin - 1
3406 lend = begin - 1
3408 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3407 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3409
3408
3410 class linestate(object):
3409 class linestate(object):
3411 def __init__(self, line, linenum, colstart, colend):
3410 def __init__(self, line, linenum, colstart, colend):
3412 self.line = line
3411 self.line = line
3413 self.linenum = linenum
3412 self.linenum = linenum
3414 self.colstart = colstart
3413 self.colstart = colstart
3415 self.colend = colend
3414 self.colend = colend
3416
3415
3417 def __hash__(self):
3416 def __hash__(self):
3418 return hash((self.linenum, self.line))
3417 return hash((self.linenum, self.line))
3419
3418
3420 def __eq__(self, other):
3419 def __eq__(self, other):
3421 return self.line == other.line
3420 return self.line == other.line
3422
3421
3423 def findpos(self):
3422 def findpos(self):
3424 """Iterate all (start, end) indices of matches"""
3423 """Iterate all (start, end) indices of matches"""
3425 yield self.colstart, self.colend
3424 yield self.colstart, self.colend
3426 p = self.colend
3425 p = self.colend
3427 while p < len(self.line):
3426 while p < len(self.line):
3428 m = regexp.search(self.line, p)
3427 m = regexp.search(self.line, p)
3429 if not m:
3428 if not m:
3430 break
3429 break
3431 yield m.span()
3430 yield m.span()
3432 p = m.end()
3431 p = m.end()
3433
3432
3434 matches = {}
3433 matches = {}
3435 copies = {}
3434 copies = {}
3436
3435
3437 def grepbody(fn, rev, body):
3436 def grepbody(fn, rev, body):
3438 matches[rev].setdefault(fn, [])
3437 matches[rev].setdefault(fn, [])
3439 m = matches[rev][fn]
3438 m = matches[rev][fn]
3440 if body is None:
3439 if body is None:
3441 return
3440 return
3442
3441
3443 for lnum, cstart, cend, line in matchlines(body):
3442 for lnum, cstart, cend, line in matchlines(body):
3444 s = linestate(line, lnum, cstart, cend)
3443 s = linestate(line, lnum, cstart, cend)
3445 m.append(s)
3444 m.append(s)
3446
3445
3447 def difflinestates(a, b):
3446 def difflinestates(a, b):
3448 sm = difflib.SequenceMatcher(None, a, b)
3447 sm = difflib.SequenceMatcher(None, a, b)
3449 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3448 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3450 if tag == 'insert':
3449 if tag == 'insert':
3451 for i in pycompat.xrange(blo, bhi):
3450 for i in pycompat.xrange(blo, bhi):
3452 yield (b'+', b[i])
3451 yield (b'+', b[i])
3453 elif tag == 'delete':
3452 elif tag == 'delete':
3454 for i in pycompat.xrange(alo, ahi):
3453 for i in pycompat.xrange(alo, ahi):
3455 yield (b'-', a[i])
3454 yield (b'-', a[i])
3456 elif tag == 'replace':
3455 elif tag == 'replace':
3457 for i in pycompat.xrange(alo, ahi):
3456 for i in pycompat.xrange(alo, ahi):
3458 yield (b'-', a[i])
3457 yield (b'-', a[i])
3459 for i in pycompat.xrange(blo, bhi):
3458 for i in pycompat.xrange(blo, bhi):
3460 yield (b'+', b[i])
3459 yield (b'+', b[i])
3461
3460
3462 uipathfn = scmutil.getuipathfn(repo)
3461 uipathfn = scmutil.getuipathfn(repo)
3463
3462
3464 def display(fm, fn, ctx, pstates, states):
3463 def display(fm, fn, ctx, pstates, states):
3465 rev = scmutil.intrev(ctx)
3464 rev = scmutil.intrev(ctx)
3466 if fm.isplain():
3465 if fm.isplain():
3467 formatuser = ui.shortuser
3466 formatuser = ui.shortuser
3468 else:
3467 else:
3469 formatuser = pycompat.bytestr
3468 formatuser = pycompat.bytestr
3470 if ui.quiet:
3469 if ui.quiet:
3471 datefmt = b'%Y-%m-%d'
3470 datefmt = b'%Y-%m-%d'
3472 else:
3471 else:
3473 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3472 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3474 found = False
3473 found = False
3475
3474
3476 @util.cachefunc
3475 @util.cachefunc
3477 def binary():
3476 def binary():
3478 flog = getfile(fn)
3477 flog = getfile(fn)
3479 try:
3478 try:
3480 return stringutil.binary(flog.read(ctx.filenode(fn)))
3479 return stringutil.binary(flog.read(ctx.filenode(fn)))
3481 except error.WdirUnsupported:
3480 except error.WdirUnsupported:
3482 return ctx[fn].isbinary()
3481 return ctx[fn].isbinary()
3483
3482
3484 fieldnamemap = {b'linenumber': b'lineno'}
3483 fieldnamemap = {b'linenumber': b'lineno'}
3485 if diff:
3484 if diff:
3486 iter = difflinestates(pstates, states)
3485 iter = difflinestates(pstates, states)
3487 else:
3486 else:
3488 iter = [(b'', l) for l in states]
3487 iter = [(b'', l) for l in states]
3489 for change, l in iter:
3488 for change, l in iter:
3490 fm.startitem()
3489 fm.startitem()
3491 fm.context(ctx=ctx)
3490 fm.context(ctx=ctx)
3492 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3491 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3493 fm.plain(uipathfn(fn), label=b'grep.filename')
3492 fm.plain(uipathfn(fn), label=b'grep.filename')
3494
3493
3495 cols = [
3494 cols = [
3496 (b'rev', b'%d', rev, not plaingrep, b''),
3495 (b'rev', b'%d', rev, not plaingrep, b''),
3497 (
3496 (
3498 b'linenumber',
3497 b'linenumber',
3499 b'%d',
3498 b'%d',
3500 l.linenum,
3499 l.linenum,
3501 opts.get(b'line_number'),
3500 opts.get(b'line_number'),
3502 b'',
3501 b'',
3503 ),
3502 ),
3504 ]
3503 ]
3505 if diff:
3504 if diff:
3506 cols.append(
3505 cols.append(
3507 (
3506 (
3508 b'change',
3507 b'change',
3509 b'%s',
3508 b'%s',
3510 change,
3509 change,
3511 True,
3510 True,
3512 b'grep.inserted '
3511 b'grep.inserted '
3513 if change == b'+'
3512 if change == b'+'
3514 else b'grep.deleted ',
3513 else b'grep.deleted ',
3515 )
3514 )
3516 )
3515 )
3517 cols.extend(
3516 cols.extend(
3518 [
3517 [
3519 (
3518 (
3520 b'user',
3519 b'user',
3521 b'%s',
3520 b'%s',
3522 formatuser(ctx.user()),
3521 formatuser(ctx.user()),
3523 opts.get(b'user'),
3522 opts.get(b'user'),
3524 b'',
3523 b'',
3525 ),
3524 ),
3526 (
3525 (
3527 b'date',
3526 b'date',
3528 b'%s',
3527 b'%s',
3529 fm.formatdate(ctx.date(), datefmt),
3528 fm.formatdate(ctx.date(), datefmt),
3530 opts.get(b'date'),
3529 opts.get(b'date'),
3531 b'',
3530 b'',
3532 ),
3531 ),
3533 ]
3532 ]
3534 )
3533 )
3535 for name, fmt, data, cond, extra_label in cols:
3534 for name, fmt, data, cond, extra_label in cols:
3536 if cond:
3535 if cond:
3537 fm.plain(sep, label=b'grep.sep')
3536 fm.plain(sep, label=b'grep.sep')
3538 field = fieldnamemap.get(name, name)
3537 field = fieldnamemap.get(name, name)
3539 label = extra_label + (b'grep.%s' % name)
3538 label = extra_label + (b'grep.%s' % name)
3540 fm.condwrite(cond, field, fmt, data, label=label)
3539 fm.condwrite(cond, field, fmt, data, label=label)
3541 if not opts.get(b'files_with_matches'):
3540 if not opts.get(b'files_with_matches'):
3542 fm.plain(sep, label=b'grep.sep')
3541 fm.plain(sep, label=b'grep.sep')
3543 if not opts.get(b'text') and binary():
3542 if not opts.get(b'text') and binary():
3544 fm.plain(_(b" Binary file matches"))
3543 fm.plain(_(b" Binary file matches"))
3545 else:
3544 else:
3546 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3545 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3547 fm.plain(eol)
3546 fm.plain(eol)
3548 found = True
3547 found = True
3549 if opts.get(b'files_with_matches'):
3548 if opts.get(b'files_with_matches'):
3550 break
3549 break
3551 return found
3550 return found
3552
3551
3553 def displaymatches(fm, l):
3552 def displaymatches(fm, l):
3554 p = 0
3553 p = 0
3555 for s, e in l.findpos():
3554 for s, e in l.findpos():
3556 if p < s:
3555 if p < s:
3557 fm.startitem()
3556 fm.startitem()
3558 fm.write(b'text', b'%s', l.line[p:s])
3557 fm.write(b'text', b'%s', l.line[p:s])
3559 fm.data(matched=False)
3558 fm.data(matched=False)
3560 fm.startitem()
3559 fm.startitem()
3561 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3560 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3562 fm.data(matched=True)
3561 fm.data(matched=True)
3563 p = e
3562 p = e
3564 if p < len(l.line):
3563 if p < len(l.line):
3565 fm.startitem()
3564 fm.startitem()
3566 fm.write(b'text', b'%s', l.line[p:])
3565 fm.write(b'text', b'%s', l.line[p:])
3567 fm.data(matched=False)
3566 fm.data(matched=False)
3568 fm.end()
3567 fm.end()
3569
3568
3570 skip = set()
3569 skip = set()
3571 revfiles = {}
3570 revfiles = {}
3572 match = scmutil.match(repo[None], pats, opts)
3571 match = scmutil.match(repo[None], pats, opts)
3573 found = False
3572 found = False
3574 follow = opts.get(b'follow')
3573 follow = opts.get(b'follow')
3575
3574
3576 getrenamed = scmutil.getrenamedfn(repo)
3575 getrenamed = scmutil.getrenamedfn(repo)
3577
3576
3578 def get_file_content(filename, filelog, filenode, context, revision):
3577 def get_file_content(filename, filelog, filenode, context, revision):
3579 try:
3578 try:
3580 content = filelog.read(filenode)
3579 content = filelog.read(filenode)
3581 except error.WdirUnsupported:
3580 except error.WdirUnsupported:
3582 content = context[filename].data()
3581 content = context[filename].data()
3583 except error.CensoredNodeError:
3582 except error.CensoredNodeError:
3584 content = None
3583 content = None
3585 ui.warn(
3584 ui.warn(
3586 _(b'cannot search in censored file: %(filename)s:%(revnum)s\n')
3585 _(b'cannot search in censored file: %(filename)s:%(revnum)s\n')
3587 % {b'filename': filename, b'revnum': pycompat.bytestr(revision)}
3586 % {b'filename': filename, b'revnum': pycompat.bytestr(revision)}
3588 )
3587 )
3589 return content
3588 return content
3590
3589
3591 def prep(ctx, fns):
3590 def prep(ctx, fns):
3592 rev = ctx.rev()
3591 rev = ctx.rev()
3593 pctx = ctx.p1()
3592 pctx = ctx.p1()
3594 parent = pctx.rev()
3593 parent = pctx.rev()
3595 matches.setdefault(rev, {})
3594 matches.setdefault(rev, {})
3596 matches.setdefault(parent, {})
3595 matches.setdefault(parent, {})
3597 files = revfiles.setdefault(rev, [])
3596 files = revfiles.setdefault(rev, [])
3598 for fn in fns:
3597 for fn in fns:
3599 flog = getfile(fn)
3598 flog = getfile(fn)
3600 try:
3599 try:
3601 fnode = ctx.filenode(fn)
3600 fnode = ctx.filenode(fn)
3602 except error.LookupError:
3601 except error.LookupError:
3603 continue
3602 continue
3604
3603
3605 copy = None
3604 copy = None
3606 if follow:
3605 if follow:
3607 copy = getrenamed(fn, rev)
3606 copy = getrenamed(fn, rev)
3608 if copy:
3607 if copy:
3609 copies.setdefault(rev, {})[fn] = copy
3608 copies.setdefault(rev, {})[fn] = copy
3610 if fn in skip:
3609 if fn in skip:
3611 skip.add(copy)
3610 skip.add(copy)
3612 if fn in skip:
3611 if fn in skip:
3613 continue
3612 continue
3614 files.append(fn)
3613 files.append(fn)
3615
3614
3616 if fn not in matches[rev]:
3615 if fn not in matches[rev]:
3617 content = get_file_content(fn, flog, fnode, ctx, rev)
3616 content = get_file_content(fn, flog, fnode, ctx, rev)
3618 grepbody(fn, rev, content)
3617 grepbody(fn, rev, content)
3619
3618
3620 pfn = copy or fn
3619 pfn = copy or fn
3621 if pfn not in matches[parent]:
3620 if pfn not in matches[parent]:
3622 try:
3621 try:
3623 pfnode = pctx.filenode(pfn)
3622 pfnode = pctx.filenode(pfn)
3624 pcontent = get_file_content(pfn, flog, pfnode, pctx, parent)
3623 pcontent = get_file_content(pfn, flog, pfnode, pctx, parent)
3625 grepbody(pfn, parent, pcontent)
3624 grepbody(pfn, parent, pcontent)
3626 except error.LookupError:
3625 except error.LookupError:
3627 pass
3626 pass
3628
3627
3629 ui.pager(b'grep')
3628 ui.pager(b'grep')
3630 fm = ui.formatter(b'grep', opts)
3629 fm = ui.formatter(b'grep', opts)
3631 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
3630 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
3632 rev = ctx.rev()
3631 rev = ctx.rev()
3633 parent = ctx.p1().rev()
3632 parent = ctx.p1().rev()
3634 for fn in sorted(revfiles.get(rev, [])):
3633 for fn in sorted(revfiles.get(rev, [])):
3635 states = matches[rev][fn]
3634 states = matches[rev][fn]
3636 copy = copies.get(rev, {}).get(fn)
3635 copy = copies.get(rev, {}).get(fn)
3637 if fn in skip:
3636 if fn in skip:
3638 if copy:
3637 if copy:
3639 skip.add(copy)
3638 skip.add(copy)
3640 continue
3639 continue
3641 pstates = matches.get(parent, {}).get(copy or fn, [])
3640 pstates = matches.get(parent, {}).get(copy or fn, [])
3642 if pstates or states:
3641 if pstates or states:
3643 r = display(fm, fn, ctx, pstates, states)
3642 r = display(fm, fn, ctx, pstates, states)
3644 found = found or r
3643 found = found or r
3645 if r and not diff and not all_files:
3644 if r and not diff and not all_files:
3646 skip.add(fn)
3645 skip.add(fn)
3647 if copy:
3646 if copy:
3648 skip.add(copy)
3647 skip.add(copy)
3649 del revfiles[rev]
3648 del revfiles[rev]
3650 # We will keep the matches dict for the duration of the window
3649 # We will keep the matches dict for the duration of the window
3651 # clear the matches dict once the window is over
3650 # clear the matches dict once the window is over
3652 if not revfiles:
3651 if not revfiles:
3653 matches.clear()
3652 matches.clear()
3654 fm.end()
3653 fm.end()
3655
3654
3656 return not found
3655 return not found
3657
3656
3658
3657
3659 @command(
3658 @command(
3660 b'heads',
3659 b'heads',
3661 [
3660 [
3662 (
3661 (
3663 b'r',
3662 b'r',
3664 b'rev',
3663 b'rev',
3665 b'',
3664 b'',
3666 _(b'show only heads which are descendants of STARTREV'),
3665 _(b'show only heads which are descendants of STARTREV'),
3667 _(b'STARTREV'),
3666 _(b'STARTREV'),
3668 ),
3667 ),
3669 (b't', b'topo', False, _(b'show topological heads only')),
3668 (b't', b'topo', False, _(b'show topological heads only')),
3670 (
3669 (
3671 b'a',
3670 b'a',
3672 b'active',
3671 b'active',
3673 False,
3672 False,
3674 _(b'show active branchheads only (DEPRECATED)'),
3673 _(b'show active branchheads only (DEPRECATED)'),
3675 ),
3674 ),
3676 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3675 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3677 ]
3676 ]
3678 + templateopts,
3677 + templateopts,
3679 _(b'[-ct] [-r STARTREV] [REV]...'),
3678 _(b'[-ct] [-r STARTREV] [REV]...'),
3680 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3679 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3681 intents={INTENT_READONLY},
3680 intents={INTENT_READONLY},
3682 )
3681 )
3683 def heads(ui, repo, *branchrevs, **opts):
3682 def heads(ui, repo, *branchrevs, **opts):
3684 """show branch heads
3683 """show branch heads
3685
3684
3686 With no arguments, show all open branch heads in the repository.
3685 With no arguments, show all open branch heads in the repository.
3687 Branch heads are changesets that have no descendants on the
3686 Branch heads are changesets that have no descendants on the
3688 same branch. They are where development generally takes place and
3687 same branch. They are where development generally takes place and
3689 are the usual targets for update and merge operations.
3688 are the usual targets for update and merge operations.
3690
3689
3691 If one or more REVs are given, only open branch heads on the
3690 If one or more REVs are given, only open branch heads on the
3692 branches associated with the specified changesets are shown. This
3691 branches associated with the specified changesets are shown. This
3693 means that you can use :hg:`heads .` to see the heads on the
3692 means that you can use :hg:`heads .` to see the heads on the
3694 currently checked-out branch.
3693 currently checked-out branch.
3695
3694
3696 If -c/--closed is specified, also show branch heads marked closed
3695 If -c/--closed is specified, also show branch heads marked closed
3697 (see :hg:`commit --close-branch`).
3696 (see :hg:`commit --close-branch`).
3698
3697
3699 If STARTREV is specified, only those heads that are descendants of
3698 If STARTREV is specified, only those heads that are descendants of
3700 STARTREV will be displayed.
3699 STARTREV will be displayed.
3701
3700
3702 If -t/--topo is specified, named branch mechanics will be ignored and only
3701 If -t/--topo is specified, named branch mechanics will be ignored and only
3703 topological heads (changesets with no children) will be shown.
3702 topological heads (changesets with no children) will be shown.
3704
3703
3705 Returns 0 if matching heads are found, 1 if not.
3704 Returns 0 if matching heads are found, 1 if not.
3706 """
3705 """
3707
3706
3708 opts = pycompat.byteskwargs(opts)
3707 opts = pycompat.byteskwargs(opts)
3709 start = None
3708 start = None
3710 rev = opts.get(b'rev')
3709 rev = opts.get(b'rev')
3711 if rev:
3710 if rev:
3712 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3711 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3713 start = scmutil.revsingle(repo, rev, None).node()
3712 start = scmutil.revsingle(repo, rev, None).node()
3714
3713
3715 if opts.get(b'topo'):
3714 if opts.get(b'topo'):
3716 heads = [repo[h] for h in repo.heads(start)]
3715 heads = [repo[h] for h in repo.heads(start)]
3717 else:
3716 else:
3718 heads = []
3717 heads = []
3719 for branch in repo.branchmap():
3718 for branch in repo.branchmap():
3720 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3719 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3721 heads = [repo[h] for h in heads]
3720 heads = [repo[h] for h in heads]
3722
3721
3723 if branchrevs:
3722 if branchrevs:
3724 branches = {
3723 branches = {
3725 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3724 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3726 }
3725 }
3727 heads = [h for h in heads if h.branch() in branches]
3726 heads = [h for h in heads if h.branch() in branches]
3728
3727
3729 if opts.get(b'active') and branchrevs:
3728 if opts.get(b'active') and branchrevs:
3730 dagheads = repo.heads(start)
3729 dagheads = repo.heads(start)
3731 heads = [h for h in heads if h.node() in dagheads]
3730 heads = [h for h in heads if h.node() in dagheads]
3732
3731
3733 if branchrevs:
3732 if branchrevs:
3734 haveheads = {h.branch() for h in heads}
3733 haveheads = {h.branch() for h in heads}
3735 if branches - haveheads:
3734 if branches - haveheads:
3736 headless = b', '.join(b for b in branches - haveheads)
3735 headless = b', '.join(b for b in branches - haveheads)
3737 msg = _(b'no open branch heads found on branches %s')
3736 msg = _(b'no open branch heads found on branches %s')
3738 if opts.get(b'rev'):
3737 if opts.get(b'rev'):
3739 msg += _(b' (started at %s)') % opts[b'rev']
3738 msg += _(b' (started at %s)') % opts[b'rev']
3740 ui.warn((msg + b'\n') % headless)
3739 ui.warn((msg + b'\n') % headless)
3741
3740
3742 if not heads:
3741 if not heads:
3743 return 1
3742 return 1
3744
3743
3745 ui.pager(b'heads')
3744 ui.pager(b'heads')
3746 heads = sorted(heads, key=lambda x: -(x.rev()))
3745 heads = sorted(heads, key=lambda x: -(x.rev()))
3747 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3746 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3748 for ctx in heads:
3747 for ctx in heads:
3749 displayer.show(ctx)
3748 displayer.show(ctx)
3750 displayer.close()
3749 displayer.close()
3751
3750
3752
3751
3753 @command(
3752 @command(
3754 b'help',
3753 b'help',
3755 [
3754 [
3756 (b'e', b'extension', None, _(b'show only help for extensions')),
3755 (b'e', b'extension', None, _(b'show only help for extensions')),
3757 (b'c', b'command', None, _(b'show only help for commands')),
3756 (b'c', b'command', None, _(b'show only help for commands')),
3758 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3757 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3759 (
3758 (
3760 b's',
3759 b's',
3761 b'system',
3760 b'system',
3762 [],
3761 [],
3763 _(b'show help for specific platform(s)'),
3762 _(b'show help for specific platform(s)'),
3764 _(b'PLATFORM'),
3763 _(b'PLATFORM'),
3765 ),
3764 ),
3766 ],
3765 ],
3767 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3766 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3768 helpcategory=command.CATEGORY_HELP,
3767 helpcategory=command.CATEGORY_HELP,
3769 norepo=True,
3768 norepo=True,
3770 intents={INTENT_READONLY},
3769 intents={INTENT_READONLY},
3771 )
3770 )
3772 def help_(ui, name=None, **opts):
3771 def help_(ui, name=None, **opts):
3773 """show help for a given topic or a help overview
3772 """show help for a given topic or a help overview
3774
3773
3775 With no arguments, print a list of commands with short help messages.
3774 With no arguments, print a list of commands with short help messages.
3776
3775
3777 Given a topic, extension, or command name, print help for that
3776 Given a topic, extension, or command name, print help for that
3778 topic.
3777 topic.
3779
3778
3780 Returns 0 if successful.
3779 Returns 0 if successful.
3781 """
3780 """
3782
3781
3783 keep = opts.get('system') or []
3782 keep = opts.get('system') or []
3784 if len(keep) == 0:
3783 if len(keep) == 0:
3785 if pycompat.sysplatform.startswith(b'win'):
3784 if pycompat.sysplatform.startswith(b'win'):
3786 keep.append(b'windows')
3785 keep.append(b'windows')
3787 elif pycompat.sysplatform == b'OpenVMS':
3786 elif pycompat.sysplatform == b'OpenVMS':
3788 keep.append(b'vms')
3787 keep.append(b'vms')
3789 elif pycompat.sysplatform == b'plan9':
3788 elif pycompat.sysplatform == b'plan9':
3790 keep.append(b'plan9')
3789 keep.append(b'plan9')
3791 else:
3790 else:
3792 keep.append(b'unix')
3791 keep.append(b'unix')
3793 keep.append(pycompat.sysplatform.lower())
3792 keep.append(pycompat.sysplatform.lower())
3794 if ui.verbose:
3793 if ui.verbose:
3795 keep.append(b'verbose')
3794 keep.append(b'verbose')
3796
3795
3797 commands = sys.modules[__name__]
3796 commands = sys.modules[__name__]
3798 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3797 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3799 ui.pager(b'help')
3798 ui.pager(b'help')
3800 ui.write(formatted)
3799 ui.write(formatted)
3801
3800
3802
3801
3803 @command(
3802 @command(
3804 b'identify|id',
3803 b'identify|id',
3805 [
3804 [
3806 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3805 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3807 (b'n', b'num', None, _(b'show local revision number')),
3806 (b'n', b'num', None, _(b'show local revision number')),
3808 (b'i', b'id', None, _(b'show global revision id')),
3807 (b'i', b'id', None, _(b'show global revision id')),
3809 (b'b', b'branch', None, _(b'show branch')),
3808 (b'b', b'branch', None, _(b'show branch')),
3810 (b't', b'tags', None, _(b'show tags')),
3809 (b't', b'tags', None, _(b'show tags')),
3811 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3810 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3812 ]
3811 ]
3813 + remoteopts
3812 + remoteopts
3814 + formatteropts,
3813 + formatteropts,
3815 _(b'[-nibtB] [-r REV] [SOURCE]'),
3814 _(b'[-nibtB] [-r REV] [SOURCE]'),
3816 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3815 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3817 optionalrepo=True,
3816 optionalrepo=True,
3818 intents={INTENT_READONLY},
3817 intents={INTENT_READONLY},
3819 )
3818 )
3820 def identify(
3819 def identify(
3821 ui,
3820 ui,
3822 repo,
3821 repo,
3823 source=None,
3822 source=None,
3824 rev=None,
3823 rev=None,
3825 num=None,
3824 num=None,
3826 id=None,
3825 id=None,
3827 branch=None,
3826 branch=None,
3828 tags=None,
3827 tags=None,
3829 bookmarks=None,
3828 bookmarks=None,
3830 **opts
3829 **opts
3831 ):
3830 ):
3832 """identify the working directory or specified revision
3831 """identify the working directory or specified revision
3833
3832
3834 Print a summary identifying the repository state at REV using one or
3833 Print a summary identifying the repository state at REV using one or
3835 two parent hash identifiers, followed by a "+" if the working
3834 two parent hash identifiers, followed by a "+" if the working
3836 directory has uncommitted changes, the branch name (if not default),
3835 directory has uncommitted changes, the branch name (if not default),
3837 a list of tags, and a list of bookmarks.
3836 a list of tags, and a list of bookmarks.
3838
3837
3839 When REV is not given, print a summary of the current state of the
3838 When REV is not given, print a summary of the current state of the
3840 repository including the working directory. Specify -r. to get information
3839 repository including the working directory. Specify -r. to get information
3841 of the working directory parent without scanning uncommitted changes.
3840 of the working directory parent without scanning uncommitted changes.
3842
3841
3843 Specifying a path to a repository root or Mercurial bundle will
3842 Specifying a path to a repository root or Mercurial bundle will
3844 cause lookup to operate on that repository/bundle.
3843 cause lookup to operate on that repository/bundle.
3845
3844
3846 .. container:: verbose
3845 .. container:: verbose
3847
3846
3848 Template:
3847 Template:
3849
3848
3850 The following keywords are supported in addition to the common template
3849 The following keywords are supported in addition to the common template
3851 keywords and functions. See also :hg:`help templates`.
3850 keywords and functions. See also :hg:`help templates`.
3852
3851
3853 :dirty: String. Character ``+`` denoting if the working directory has
3852 :dirty: String. Character ``+`` denoting if the working directory has
3854 uncommitted changes.
3853 uncommitted changes.
3855 :id: String. One or two nodes, optionally followed by ``+``.
3854 :id: String. One or two nodes, optionally followed by ``+``.
3856 :parents: List of strings. Parent nodes of the changeset.
3855 :parents: List of strings. Parent nodes of the changeset.
3857
3856
3858 Examples:
3857 Examples:
3859
3858
3860 - generate a build identifier for the working directory::
3859 - generate a build identifier for the working directory::
3861
3860
3862 hg id --id > build-id.dat
3861 hg id --id > build-id.dat
3863
3862
3864 - find the revision corresponding to a tag::
3863 - find the revision corresponding to a tag::
3865
3864
3866 hg id -n -r 1.3
3865 hg id -n -r 1.3
3867
3866
3868 - check the most recent revision of a remote repository::
3867 - check the most recent revision of a remote repository::
3869
3868
3870 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3869 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3871
3870
3872 See :hg:`log` for generating more information about specific revisions,
3871 See :hg:`log` for generating more information about specific revisions,
3873 including full hash identifiers.
3872 including full hash identifiers.
3874
3873
3875 Returns 0 if successful.
3874 Returns 0 if successful.
3876 """
3875 """
3877
3876
3878 opts = pycompat.byteskwargs(opts)
3877 opts = pycompat.byteskwargs(opts)
3879 if not repo and not source:
3878 if not repo and not source:
3880 raise error.Abort(
3879 raise error.Abort(
3881 _(b"there is no Mercurial repository here (.hg not found)")
3880 _(b"there is no Mercurial repository here (.hg not found)")
3882 )
3881 )
3883
3882
3884 default = not (num or id or branch or tags or bookmarks)
3883 default = not (num or id or branch or tags or bookmarks)
3885 output = []
3884 output = []
3886 revs = []
3885 revs = []
3887
3886
3888 if source:
3887 if source:
3889 source, branches = hg.parseurl(ui.expandpath(source))
3888 source, branches = hg.parseurl(ui.expandpath(source))
3890 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3889 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3891 repo = peer.local()
3890 repo = peer.local()
3892 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3891 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3893
3892
3894 fm = ui.formatter(b'identify', opts)
3893 fm = ui.formatter(b'identify', opts)
3895 fm.startitem()
3894 fm.startitem()
3896
3895
3897 if not repo:
3896 if not repo:
3898 if num or branch or tags:
3897 if num or branch or tags:
3899 raise error.Abort(
3898 raise error.Abort(
3900 _(b"can't query remote revision number, branch, or tags")
3899 _(b"can't query remote revision number, branch, or tags")
3901 )
3900 )
3902 if not rev and revs:
3901 if not rev and revs:
3903 rev = revs[0]
3902 rev = revs[0]
3904 if not rev:
3903 if not rev:
3905 rev = b"tip"
3904 rev = b"tip"
3906
3905
3907 remoterev = peer.lookup(rev)
3906 remoterev = peer.lookup(rev)
3908 hexrev = fm.hexfunc(remoterev)
3907 hexrev = fm.hexfunc(remoterev)
3909 if default or id:
3908 if default or id:
3910 output = [hexrev]
3909 output = [hexrev]
3911 fm.data(id=hexrev)
3910 fm.data(id=hexrev)
3912
3911
3913 @util.cachefunc
3912 @util.cachefunc
3914 def getbms():
3913 def getbms():
3915 bms = []
3914 bms = []
3916
3915
3917 if b'bookmarks' in peer.listkeys(b'namespaces'):
3916 if b'bookmarks' in peer.listkeys(b'namespaces'):
3918 hexremoterev = hex(remoterev)
3917 hexremoterev = hex(remoterev)
3919 bms = [
3918 bms = [
3920 bm
3919 bm
3921 for bm, bmr in pycompat.iteritems(
3920 for bm, bmr in pycompat.iteritems(
3922 peer.listkeys(b'bookmarks')
3921 peer.listkeys(b'bookmarks')
3923 )
3922 )
3924 if bmr == hexremoterev
3923 if bmr == hexremoterev
3925 ]
3924 ]
3926
3925
3927 return sorted(bms)
3926 return sorted(bms)
3928
3927
3929 if fm.isplain():
3928 if fm.isplain():
3930 if bookmarks:
3929 if bookmarks:
3931 output.extend(getbms())
3930 output.extend(getbms())
3932 elif default and not ui.quiet:
3931 elif default and not ui.quiet:
3933 # multiple bookmarks for a single parent separated by '/'
3932 # multiple bookmarks for a single parent separated by '/'
3934 bm = b'/'.join(getbms())
3933 bm = b'/'.join(getbms())
3935 if bm:
3934 if bm:
3936 output.append(bm)
3935 output.append(bm)
3937 else:
3936 else:
3938 fm.data(node=hex(remoterev))
3937 fm.data(node=hex(remoterev))
3939 if bookmarks or b'bookmarks' in fm.datahint():
3938 if bookmarks or b'bookmarks' in fm.datahint():
3940 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3939 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3941 else:
3940 else:
3942 if rev:
3941 if rev:
3943 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3942 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3944 ctx = scmutil.revsingle(repo, rev, None)
3943 ctx = scmutil.revsingle(repo, rev, None)
3945
3944
3946 if ctx.rev() is None:
3945 if ctx.rev() is None:
3947 ctx = repo[None]
3946 ctx = repo[None]
3948 parents = ctx.parents()
3947 parents = ctx.parents()
3949 taglist = []
3948 taglist = []
3950 for p in parents:
3949 for p in parents:
3951 taglist.extend(p.tags())
3950 taglist.extend(p.tags())
3952
3951
3953 dirty = b""
3952 dirty = b""
3954 if ctx.dirty(missing=True, merge=False, branch=False):
3953 if ctx.dirty(missing=True, merge=False, branch=False):
3955 dirty = b'+'
3954 dirty = b'+'
3956 fm.data(dirty=dirty)
3955 fm.data(dirty=dirty)
3957
3956
3958 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3957 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3959 if default or id:
3958 if default or id:
3960 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3959 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3961 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3960 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3962
3961
3963 if num:
3962 if num:
3964 numoutput = [b"%d" % p.rev() for p in parents]
3963 numoutput = [b"%d" % p.rev() for p in parents]
3965 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3964 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3966
3965
3967 fm.data(
3966 fm.data(
3968 parents=fm.formatlist(
3967 parents=fm.formatlist(
3969 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3968 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3970 )
3969 )
3971 )
3970 )
3972 else:
3971 else:
3973 hexoutput = fm.hexfunc(ctx.node())
3972 hexoutput = fm.hexfunc(ctx.node())
3974 if default or id:
3973 if default or id:
3975 output = [hexoutput]
3974 output = [hexoutput]
3976 fm.data(id=hexoutput)
3975 fm.data(id=hexoutput)
3977
3976
3978 if num:
3977 if num:
3979 output.append(pycompat.bytestr(ctx.rev()))
3978 output.append(pycompat.bytestr(ctx.rev()))
3980 taglist = ctx.tags()
3979 taglist = ctx.tags()
3981
3980
3982 if default and not ui.quiet:
3981 if default and not ui.quiet:
3983 b = ctx.branch()
3982 b = ctx.branch()
3984 if b != b'default':
3983 if b != b'default':
3985 output.append(b"(%s)" % b)
3984 output.append(b"(%s)" % b)
3986
3985
3987 # multiple tags for a single parent separated by '/'
3986 # multiple tags for a single parent separated by '/'
3988 t = b'/'.join(taglist)
3987 t = b'/'.join(taglist)
3989 if t:
3988 if t:
3990 output.append(t)
3989 output.append(t)
3991
3990
3992 # multiple bookmarks for a single parent separated by '/'
3991 # multiple bookmarks for a single parent separated by '/'
3993 bm = b'/'.join(ctx.bookmarks())
3992 bm = b'/'.join(ctx.bookmarks())
3994 if bm:
3993 if bm:
3995 output.append(bm)
3994 output.append(bm)
3996 else:
3995 else:
3997 if branch:
3996 if branch:
3998 output.append(ctx.branch())
3997 output.append(ctx.branch())
3999
3998
4000 if tags:
3999 if tags:
4001 output.extend(taglist)
4000 output.extend(taglist)
4002
4001
4003 if bookmarks:
4002 if bookmarks:
4004 output.extend(ctx.bookmarks())
4003 output.extend(ctx.bookmarks())
4005
4004
4006 fm.data(node=ctx.hex())
4005 fm.data(node=ctx.hex())
4007 fm.data(branch=ctx.branch())
4006 fm.data(branch=ctx.branch())
4008 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4007 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4009 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4008 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4010 fm.context(ctx=ctx)
4009 fm.context(ctx=ctx)
4011
4010
4012 fm.plain(b"%s\n" % b' '.join(output))
4011 fm.plain(b"%s\n" % b' '.join(output))
4013 fm.end()
4012 fm.end()
4014
4013
4015
4014
4016 @command(
4015 @command(
4017 b'import|patch',
4016 b'import|patch',
4018 [
4017 [
4019 (
4018 (
4020 b'p',
4019 b'p',
4021 b'strip',
4020 b'strip',
4022 1,
4021 1,
4023 _(
4022 _(
4024 b'directory strip option for patch. This has the same '
4023 b'directory strip option for patch. This has the same '
4025 b'meaning as the corresponding patch option'
4024 b'meaning as the corresponding patch option'
4026 ),
4025 ),
4027 _(b'NUM'),
4026 _(b'NUM'),
4028 ),
4027 ),
4029 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4028 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4030 (b'', b'secret', None, _(b'use the secret phase for committing')),
4029 (b'', b'secret', None, _(b'use the secret phase for committing')),
4031 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4030 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4032 (
4031 (
4033 b'f',
4032 b'f',
4034 b'force',
4033 b'force',
4035 None,
4034 None,
4036 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4035 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4037 ),
4036 ),
4038 (
4037 (
4039 b'',
4038 b'',
4040 b'no-commit',
4039 b'no-commit',
4041 None,
4040 None,
4042 _(b"don't commit, just update the working directory"),
4041 _(b"don't commit, just update the working directory"),
4043 ),
4042 ),
4044 (
4043 (
4045 b'',
4044 b'',
4046 b'bypass',
4045 b'bypass',
4047 None,
4046 None,
4048 _(b"apply patch without touching the working directory"),
4047 _(b"apply patch without touching the working directory"),
4049 ),
4048 ),
4050 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4049 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4051 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4050 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4052 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4051 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4053 (
4052 (
4054 b'',
4053 b'',
4055 b'import-branch',
4054 b'import-branch',
4056 None,
4055 None,
4057 _(b'use any branch information in patch (implied by --exact)'),
4056 _(b'use any branch information in patch (implied by --exact)'),
4058 ),
4057 ),
4059 ]
4058 ]
4060 + commitopts
4059 + commitopts
4061 + commitopts2
4060 + commitopts2
4062 + similarityopts,
4061 + similarityopts,
4063 _(b'[OPTION]... PATCH...'),
4062 _(b'[OPTION]... PATCH...'),
4064 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4063 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4065 )
4064 )
4066 def import_(ui, repo, patch1=None, *patches, **opts):
4065 def import_(ui, repo, patch1=None, *patches, **opts):
4067 """import an ordered set of patches
4066 """import an ordered set of patches
4068
4067
4069 Import a list of patches and commit them individually (unless
4068 Import a list of patches and commit them individually (unless
4070 --no-commit is specified).
4069 --no-commit is specified).
4071
4070
4072 To read a patch from standard input (stdin), use "-" as the patch
4071 To read a patch from standard input (stdin), use "-" as the patch
4073 name. If a URL is specified, the patch will be downloaded from
4072 name. If a URL is specified, the patch will be downloaded from
4074 there.
4073 there.
4075
4074
4076 Import first applies changes to the working directory (unless
4075 Import first applies changes to the working directory (unless
4077 --bypass is specified), import will abort if there are outstanding
4076 --bypass is specified), import will abort if there are outstanding
4078 changes.
4077 changes.
4079
4078
4080 Use --bypass to apply and commit patches directly to the
4079 Use --bypass to apply and commit patches directly to the
4081 repository, without affecting the working directory. Without
4080 repository, without affecting the working directory. Without
4082 --exact, patches will be applied on top of the working directory
4081 --exact, patches will be applied on top of the working directory
4083 parent revision.
4082 parent revision.
4084
4083
4085 You can import a patch straight from a mail message. Even patches
4084 You can import a patch straight from a mail message. Even patches
4086 as attachments work (to use the body part, it must have type
4085 as attachments work (to use the body part, it must have type
4087 text/plain or text/x-patch). From and Subject headers of email
4086 text/plain or text/x-patch). From and Subject headers of email
4088 message are used as default committer and commit message. All
4087 message are used as default committer and commit message. All
4089 text/plain body parts before first diff are added to the commit
4088 text/plain body parts before first diff are added to the commit
4090 message.
4089 message.
4091
4090
4092 If the imported patch was generated by :hg:`export`, user and
4091 If the imported patch was generated by :hg:`export`, user and
4093 description from patch override values from message headers and
4092 description from patch override values from message headers and
4094 body. Values given on command line with -m/--message and -u/--user
4093 body. Values given on command line with -m/--message and -u/--user
4095 override these.
4094 override these.
4096
4095
4097 If --exact is specified, import will set the working directory to
4096 If --exact is specified, import will set the working directory to
4098 the parent of each patch before applying it, and will abort if the
4097 the parent of each patch before applying it, and will abort if the
4099 resulting changeset has a different ID than the one recorded in
4098 resulting changeset has a different ID than the one recorded in
4100 the patch. This will guard against various ways that portable
4099 the patch. This will guard against various ways that portable
4101 patch formats and mail systems might fail to transfer Mercurial
4100 patch formats and mail systems might fail to transfer Mercurial
4102 data or metadata. See :hg:`bundle` for lossless transmission.
4101 data or metadata. See :hg:`bundle` for lossless transmission.
4103
4102
4104 Use --partial to ensure a changeset will be created from the patch
4103 Use --partial to ensure a changeset will be created from the patch
4105 even if some hunks fail to apply. Hunks that fail to apply will be
4104 even if some hunks fail to apply. Hunks that fail to apply will be
4106 written to a <target-file>.rej file. Conflicts can then be resolved
4105 written to a <target-file>.rej file. Conflicts can then be resolved
4107 by hand before :hg:`commit --amend` is run to update the created
4106 by hand before :hg:`commit --amend` is run to update the created
4108 changeset. This flag exists to let people import patches that
4107 changeset. This flag exists to let people import patches that
4109 partially apply without losing the associated metadata (author,
4108 partially apply without losing the associated metadata (author,
4110 date, description, ...).
4109 date, description, ...).
4111
4110
4112 .. note::
4111 .. note::
4113
4112
4114 When no hunks apply cleanly, :hg:`import --partial` will create
4113 When no hunks apply cleanly, :hg:`import --partial` will create
4115 an empty changeset, importing only the patch metadata.
4114 an empty changeset, importing only the patch metadata.
4116
4115
4117 With -s/--similarity, hg will attempt to discover renames and
4116 With -s/--similarity, hg will attempt to discover renames and
4118 copies in the patch in the same way as :hg:`addremove`.
4117 copies in the patch in the same way as :hg:`addremove`.
4119
4118
4120 It is possible to use external patch programs to perform the patch
4119 It is possible to use external patch programs to perform the patch
4121 by setting the ``ui.patch`` configuration option. For the default
4120 by setting the ``ui.patch`` configuration option. For the default
4122 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4121 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4123 See :hg:`help config` for more information about configuration
4122 See :hg:`help config` for more information about configuration
4124 files and how to use these options.
4123 files and how to use these options.
4125
4124
4126 See :hg:`help dates` for a list of formats valid for -d/--date.
4125 See :hg:`help dates` for a list of formats valid for -d/--date.
4127
4126
4128 .. container:: verbose
4127 .. container:: verbose
4129
4128
4130 Examples:
4129 Examples:
4131
4130
4132 - import a traditional patch from a website and detect renames::
4131 - import a traditional patch from a website and detect renames::
4133
4132
4134 hg import -s 80 http://example.com/bugfix.patch
4133 hg import -s 80 http://example.com/bugfix.patch
4135
4134
4136 - import a changeset from an hgweb server::
4135 - import a changeset from an hgweb server::
4137
4136
4138 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4137 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4139
4138
4140 - import all the patches in an Unix-style mbox::
4139 - import all the patches in an Unix-style mbox::
4141
4140
4142 hg import incoming-patches.mbox
4141 hg import incoming-patches.mbox
4143
4142
4144 - import patches from stdin::
4143 - import patches from stdin::
4145
4144
4146 hg import -
4145 hg import -
4147
4146
4148 - attempt to exactly restore an exported changeset (not always
4147 - attempt to exactly restore an exported changeset (not always
4149 possible)::
4148 possible)::
4150
4149
4151 hg import --exact proposed-fix.patch
4150 hg import --exact proposed-fix.patch
4152
4151
4153 - use an external tool to apply a patch which is too fuzzy for
4152 - use an external tool to apply a patch which is too fuzzy for
4154 the default internal tool.
4153 the default internal tool.
4155
4154
4156 hg import --config ui.patch="patch --merge" fuzzy.patch
4155 hg import --config ui.patch="patch --merge" fuzzy.patch
4157
4156
4158 - change the default fuzzing from 2 to a less strict 7
4157 - change the default fuzzing from 2 to a less strict 7
4159
4158
4160 hg import --config ui.fuzz=7 fuzz.patch
4159 hg import --config ui.fuzz=7 fuzz.patch
4161
4160
4162 Returns 0 on success, 1 on partial success (see --partial).
4161 Returns 0 on success, 1 on partial success (see --partial).
4163 """
4162 """
4164
4163
4165 opts = pycompat.byteskwargs(opts)
4164 opts = pycompat.byteskwargs(opts)
4166 if not patch1:
4165 if not patch1:
4167 raise error.Abort(_(b'need at least one patch to import'))
4166 raise error.Abort(_(b'need at least one patch to import'))
4168
4167
4169 patches = (patch1,) + patches
4168 patches = (patch1,) + patches
4170
4169
4171 date = opts.get(b'date')
4170 date = opts.get(b'date')
4172 if date:
4171 if date:
4173 opts[b'date'] = dateutil.parsedate(date)
4172 opts[b'date'] = dateutil.parsedate(date)
4174
4173
4175 exact = opts.get(b'exact')
4174 exact = opts.get(b'exact')
4176 update = not opts.get(b'bypass')
4175 update = not opts.get(b'bypass')
4177 if not update and opts.get(b'no_commit'):
4176 if not update and opts.get(b'no_commit'):
4178 raise error.Abort(_(b'cannot use --no-commit with --bypass'))
4177 raise error.Abort(_(b'cannot use --no-commit with --bypass'))
4179 if opts.get(b'secret') and opts.get(b'no_commit'):
4178 if opts.get(b'secret') and opts.get(b'no_commit'):
4180 raise error.Abort(_(b'cannot use --no-commit with --secret'))
4179 raise error.Abort(_(b'cannot use --no-commit with --secret'))
4181 try:
4180 try:
4182 sim = float(opts.get(b'similarity') or 0)
4181 sim = float(opts.get(b'similarity') or 0)
4183 except ValueError:
4182 except ValueError:
4184 raise error.Abort(_(b'similarity must be a number'))
4183 raise error.Abort(_(b'similarity must be a number'))
4185 if sim < 0 or sim > 100:
4184 if sim < 0 or sim > 100:
4186 raise error.Abort(_(b'similarity must be between 0 and 100'))
4185 raise error.Abort(_(b'similarity must be between 0 and 100'))
4187 if sim and not update:
4186 if sim and not update:
4188 raise error.Abort(_(b'cannot use --similarity with --bypass'))
4187 raise error.Abort(_(b'cannot use --similarity with --bypass'))
4189 if exact:
4188 if exact:
4190 if opts.get(b'edit'):
4189 if opts.get(b'edit'):
4191 raise error.Abort(_(b'cannot use --exact with --edit'))
4190 raise error.Abort(_(b'cannot use --exact with --edit'))
4192 if opts.get(b'prefix'):
4191 if opts.get(b'prefix'):
4193 raise error.Abort(_(b'cannot use --exact with --prefix'))
4192 raise error.Abort(_(b'cannot use --exact with --prefix'))
4194
4193
4195 base = opts[b"base"]
4194 base = opts[b"base"]
4196 msgs = []
4195 msgs = []
4197 ret = 0
4196 ret = 0
4198
4197
4199 with repo.wlock():
4198 with repo.wlock():
4200 if update:
4199 if update:
4201 cmdutil.checkunfinished(repo)
4200 cmdutil.checkunfinished(repo)
4202 if exact or not opts.get(b'force'):
4201 if exact or not opts.get(b'force'):
4203 cmdutil.bailifchanged(repo)
4202 cmdutil.bailifchanged(repo)
4204
4203
4205 if not opts.get(b'no_commit'):
4204 if not opts.get(b'no_commit'):
4206 lock = repo.lock
4205 lock = repo.lock
4207 tr = lambda: repo.transaction(b'import')
4206 tr = lambda: repo.transaction(b'import')
4208 dsguard = util.nullcontextmanager
4207 dsguard = util.nullcontextmanager
4209 else:
4208 else:
4210 lock = util.nullcontextmanager
4209 lock = util.nullcontextmanager
4211 tr = util.nullcontextmanager
4210 tr = util.nullcontextmanager
4212 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4211 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4213 with lock(), tr(), dsguard():
4212 with lock(), tr(), dsguard():
4214 parents = repo[None].parents()
4213 parents = repo[None].parents()
4215 for patchurl in patches:
4214 for patchurl in patches:
4216 if patchurl == b'-':
4215 if patchurl == b'-':
4217 ui.status(_(b'applying patch from stdin\n'))
4216 ui.status(_(b'applying patch from stdin\n'))
4218 patchfile = ui.fin
4217 patchfile = ui.fin
4219 patchurl = b'stdin' # for error message
4218 patchurl = b'stdin' # for error message
4220 else:
4219 else:
4221 patchurl = os.path.join(base, patchurl)
4220 patchurl = os.path.join(base, patchurl)
4222 ui.status(_(b'applying %s\n') % patchurl)
4221 ui.status(_(b'applying %s\n') % patchurl)
4223 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4222 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4224
4223
4225 haspatch = False
4224 haspatch = False
4226 for hunk in patch.split(patchfile):
4225 for hunk in patch.split(patchfile):
4227 with patch.extract(ui, hunk) as patchdata:
4226 with patch.extract(ui, hunk) as patchdata:
4228 msg, node, rej = cmdutil.tryimportone(
4227 msg, node, rej = cmdutil.tryimportone(
4229 ui, repo, patchdata, parents, opts, msgs, hg.clean
4228 ui, repo, patchdata, parents, opts, msgs, hg.clean
4230 )
4229 )
4231 if msg:
4230 if msg:
4232 haspatch = True
4231 haspatch = True
4233 ui.note(msg + b'\n')
4232 ui.note(msg + b'\n')
4234 if update or exact:
4233 if update or exact:
4235 parents = repo[None].parents()
4234 parents = repo[None].parents()
4236 else:
4235 else:
4237 parents = [repo[node]]
4236 parents = [repo[node]]
4238 if rej:
4237 if rej:
4239 ui.write_err(_(b"patch applied partially\n"))
4238 ui.write_err(_(b"patch applied partially\n"))
4240 ui.write_err(
4239 ui.write_err(
4241 _(
4240 _(
4242 b"(fix the .rej files and run "
4241 b"(fix the .rej files and run "
4243 b"`hg commit --amend`)\n"
4242 b"`hg commit --amend`)\n"
4244 )
4243 )
4245 )
4244 )
4246 ret = 1
4245 ret = 1
4247 break
4246 break
4248
4247
4249 if not haspatch:
4248 if not haspatch:
4250 raise error.Abort(_(b'%s: no diffs found') % patchurl)
4249 raise error.Abort(_(b'%s: no diffs found') % patchurl)
4251
4250
4252 if msgs:
4251 if msgs:
4253 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4252 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4254 return ret
4253 return ret
4255
4254
4256
4255
4257 @command(
4256 @command(
4258 b'incoming|in',
4257 b'incoming|in',
4259 [
4258 [
4260 (
4259 (
4261 b'f',
4260 b'f',
4262 b'force',
4261 b'force',
4263 None,
4262 None,
4264 _(b'run even if remote repository is unrelated'),
4263 _(b'run even if remote repository is unrelated'),
4265 ),
4264 ),
4266 (b'n', b'newest-first', None, _(b'show newest record first')),
4265 (b'n', b'newest-first', None, _(b'show newest record first')),
4267 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4266 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4268 (
4267 (
4269 b'r',
4268 b'r',
4270 b'rev',
4269 b'rev',
4271 [],
4270 [],
4272 _(b'a remote changeset intended to be added'),
4271 _(b'a remote changeset intended to be added'),
4273 _(b'REV'),
4272 _(b'REV'),
4274 ),
4273 ),
4275 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4274 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4276 (
4275 (
4277 b'b',
4276 b'b',
4278 b'branch',
4277 b'branch',
4279 [],
4278 [],
4280 _(b'a specific branch you would like to pull'),
4279 _(b'a specific branch you would like to pull'),
4281 _(b'BRANCH'),
4280 _(b'BRANCH'),
4282 ),
4281 ),
4283 ]
4282 ]
4284 + logopts
4283 + logopts
4285 + remoteopts
4284 + remoteopts
4286 + subrepoopts,
4285 + subrepoopts,
4287 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4286 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4288 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4287 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4289 )
4288 )
4290 def incoming(ui, repo, source=b"default", **opts):
4289 def incoming(ui, repo, source=b"default", **opts):
4291 """show new changesets found in source
4290 """show new changesets found in source
4292
4291
4293 Show new changesets found in the specified path/URL or the default
4292 Show new changesets found in the specified path/URL or the default
4294 pull location. These are the changesets that would have been pulled
4293 pull location. These are the changesets that would have been pulled
4295 by :hg:`pull` at the time you issued this command.
4294 by :hg:`pull` at the time you issued this command.
4296
4295
4297 See pull for valid source format details.
4296 See pull for valid source format details.
4298
4297
4299 .. container:: verbose
4298 .. container:: verbose
4300
4299
4301 With -B/--bookmarks, the result of bookmark comparison between
4300 With -B/--bookmarks, the result of bookmark comparison between
4302 local and remote repositories is displayed. With -v/--verbose,
4301 local and remote repositories is displayed. With -v/--verbose,
4303 status is also displayed for each bookmark like below::
4302 status is also displayed for each bookmark like below::
4304
4303
4305 BM1 01234567890a added
4304 BM1 01234567890a added
4306 BM2 1234567890ab advanced
4305 BM2 1234567890ab advanced
4307 BM3 234567890abc diverged
4306 BM3 234567890abc diverged
4308 BM4 34567890abcd changed
4307 BM4 34567890abcd changed
4309
4308
4310 The action taken locally when pulling depends on the
4309 The action taken locally when pulling depends on the
4311 status of each bookmark:
4310 status of each bookmark:
4312
4311
4313 :``added``: pull will create it
4312 :``added``: pull will create it
4314 :``advanced``: pull will update it
4313 :``advanced``: pull will update it
4315 :``diverged``: pull will create a divergent bookmark
4314 :``diverged``: pull will create a divergent bookmark
4316 :``changed``: result depends on remote changesets
4315 :``changed``: result depends on remote changesets
4317
4316
4318 From the point of view of pulling behavior, bookmark
4317 From the point of view of pulling behavior, bookmark
4319 existing only in the remote repository are treated as ``added``,
4318 existing only in the remote repository are treated as ``added``,
4320 even if it is in fact locally deleted.
4319 even if it is in fact locally deleted.
4321
4320
4322 .. container:: verbose
4321 .. container:: verbose
4323
4322
4324 For remote repository, using --bundle avoids downloading the
4323 For remote repository, using --bundle avoids downloading the
4325 changesets twice if the incoming is followed by a pull.
4324 changesets twice if the incoming is followed by a pull.
4326
4325
4327 Examples:
4326 Examples:
4328
4327
4329 - show incoming changes with patches and full description::
4328 - show incoming changes with patches and full description::
4330
4329
4331 hg incoming -vp
4330 hg incoming -vp
4332
4331
4333 - show incoming changes excluding merges, store a bundle::
4332 - show incoming changes excluding merges, store a bundle::
4334
4333
4335 hg in -vpM --bundle incoming.hg
4334 hg in -vpM --bundle incoming.hg
4336 hg pull incoming.hg
4335 hg pull incoming.hg
4337
4336
4338 - briefly list changes inside a bundle::
4337 - briefly list changes inside a bundle::
4339
4338
4340 hg in changes.hg -T "{desc|firstline}\\n"
4339 hg in changes.hg -T "{desc|firstline}\\n"
4341
4340
4342 Returns 0 if there are incoming changes, 1 otherwise.
4341 Returns 0 if there are incoming changes, 1 otherwise.
4343 """
4342 """
4344 opts = pycompat.byteskwargs(opts)
4343 opts = pycompat.byteskwargs(opts)
4345 if opts.get(b'graph'):
4344 if opts.get(b'graph'):
4346 logcmdutil.checkunsupportedgraphflags([], opts)
4345 logcmdutil.checkunsupportedgraphflags([], opts)
4347
4346
4348 def display(other, chlist, displayer):
4347 def display(other, chlist, displayer):
4349 revdag = logcmdutil.graphrevs(other, chlist, opts)
4348 revdag = logcmdutil.graphrevs(other, chlist, opts)
4350 logcmdutil.displaygraph(
4349 logcmdutil.displaygraph(
4351 ui, repo, revdag, displayer, graphmod.asciiedges
4350 ui, repo, revdag, displayer, graphmod.asciiedges
4352 )
4351 )
4353
4352
4354 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4353 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4355 return 0
4354 return 0
4356
4355
4357 if opts.get(b'bundle') and opts.get(b'subrepos'):
4356 if opts.get(b'bundle') and opts.get(b'subrepos'):
4358 raise error.Abort(_(b'cannot combine --bundle and --subrepos'))
4357 raise error.Abort(_(b'cannot combine --bundle and --subrepos'))
4359
4358
4360 if opts.get(b'bookmarks'):
4359 if opts.get(b'bookmarks'):
4361 source, branches = hg.parseurl(
4360 source, branches = hg.parseurl(
4362 ui.expandpath(source), opts.get(b'branch')
4361 ui.expandpath(source), opts.get(b'branch')
4363 )
4362 )
4364 other = hg.peer(repo, opts, source)
4363 other = hg.peer(repo, opts, source)
4365 if b'bookmarks' not in other.listkeys(b'namespaces'):
4364 if b'bookmarks' not in other.listkeys(b'namespaces'):
4366 ui.warn(_(b"remote doesn't support bookmarks\n"))
4365 ui.warn(_(b"remote doesn't support bookmarks\n"))
4367 return 0
4366 return 0
4368 ui.pager(b'incoming')
4367 ui.pager(b'incoming')
4369 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4368 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4370 return bookmarks.incoming(ui, repo, other)
4369 return bookmarks.incoming(ui, repo, other)
4371
4370
4372 repo._subtoppath = ui.expandpath(source)
4371 repo._subtoppath = ui.expandpath(source)
4373 try:
4372 try:
4374 return hg.incoming(ui, repo, source, opts)
4373 return hg.incoming(ui, repo, source, opts)
4375 finally:
4374 finally:
4376 del repo._subtoppath
4375 del repo._subtoppath
4377
4376
4378
4377
4379 @command(
4378 @command(
4380 b'init',
4379 b'init',
4381 remoteopts,
4380 remoteopts,
4382 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4381 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4383 helpcategory=command.CATEGORY_REPO_CREATION,
4382 helpcategory=command.CATEGORY_REPO_CREATION,
4384 helpbasic=True,
4383 helpbasic=True,
4385 norepo=True,
4384 norepo=True,
4386 )
4385 )
4387 def init(ui, dest=b".", **opts):
4386 def init(ui, dest=b".", **opts):
4388 """create a new repository in the given directory
4387 """create a new repository in the given directory
4389
4388
4390 Initialize a new repository in the given directory. If the given
4389 Initialize a new repository in the given directory. If the given
4391 directory does not exist, it will be created.
4390 directory does not exist, it will be created.
4392
4391
4393 If no directory is given, the current directory is used.
4392 If no directory is given, the current directory is used.
4394
4393
4395 It is possible to specify an ``ssh://`` URL as the destination.
4394 It is possible to specify an ``ssh://`` URL as the destination.
4396 See :hg:`help urls` for more information.
4395 See :hg:`help urls` for more information.
4397
4396
4398 Returns 0 on success.
4397 Returns 0 on success.
4399 """
4398 """
4400 opts = pycompat.byteskwargs(opts)
4399 opts = pycompat.byteskwargs(opts)
4401 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4400 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4402
4401
4403
4402
4404 @command(
4403 @command(
4405 b'locate',
4404 b'locate',
4406 [
4405 [
4407 (
4406 (
4408 b'r',
4407 b'r',
4409 b'rev',
4408 b'rev',
4410 b'',
4409 b'',
4411 _(b'search the repository as it is in REV'),
4410 _(b'search the repository as it is in REV'),
4412 _(b'REV'),
4411 _(b'REV'),
4413 ),
4412 ),
4414 (
4413 (
4415 b'0',
4414 b'0',
4416 b'print0',
4415 b'print0',
4417 None,
4416 None,
4418 _(b'end filenames with NUL, for use with xargs'),
4417 _(b'end filenames with NUL, for use with xargs'),
4419 ),
4418 ),
4420 (
4419 (
4421 b'f',
4420 b'f',
4422 b'fullpath',
4421 b'fullpath',
4423 None,
4422 None,
4424 _(b'print complete paths from the filesystem root'),
4423 _(b'print complete paths from the filesystem root'),
4425 ),
4424 ),
4426 ]
4425 ]
4427 + walkopts,
4426 + walkopts,
4428 _(b'[OPTION]... [PATTERN]...'),
4427 _(b'[OPTION]... [PATTERN]...'),
4429 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4428 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4430 )
4429 )
4431 def locate(ui, repo, *pats, **opts):
4430 def locate(ui, repo, *pats, **opts):
4432 """locate files matching specific patterns (DEPRECATED)
4431 """locate files matching specific patterns (DEPRECATED)
4433
4432
4434 Print files under Mercurial control in the working directory whose
4433 Print files under Mercurial control in the working directory whose
4435 names match the given patterns.
4434 names match the given patterns.
4436
4435
4437 By default, this command searches all directories in the working
4436 By default, this command searches all directories in the working
4438 directory. To search just the current directory and its
4437 directory. To search just the current directory and its
4439 subdirectories, use "--include .".
4438 subdirectories, use "--include .".
4440
4439
4441 If no patterns are given to match, this command prints the names
4440 If no patterns are given to match, this command prints the names
4442 of all files under Mercurial control in the working directory.
4441 of all files under Mercurial control in the working directory.
4443
4442
4444 If you want to feed the output of this command into the "xargs"
4443 If you want to feed the output of this command into the "xargs"
4445 command, use the -0 option to both this command and "xargs". This
4444 command, use the -0 option to both this command and "xargs". This
4446 will avoid the problem of "xargs" treating single filenames that
4445 will avoid the problem of "xargs" treating single filenames that
4447 contain whitespace as multiple filenames.
4446 contain whitespace as multiple filenames.
4448
4447
4449 See :hg:`help files` for a more versatile command.
4448 See :hg:`help files` for a more versatile command.
4450
4449
4451 Returns 0 if a match is found, 1 otherwise.
4450 Returns 0 if a match is found, 1 otherwise.
4452 """
4451 """
4453 opts = pycompat.byteskwargs(opts)
4452 opts = pycompat.byteskwargs(opts)
4454 if opts.get(b'print0'):
4453 if opts.get(b'print0'):
4455 end = b'\0'
4454 end = b'\0'
4456 else:
4455 else:
4457 end = b'\n'
4456 end = b'\n'
4458 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4457 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4459
4458
4460 ret = 1
4459 ret = 1
4461 m = scmutil.match(
4460 m = scmutil.match(
4462 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4461 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4463 )
4462 )
4464
4463
4465 ui.pager(b'locate')
4464 ui.pager(b'locate')
4466 if ctx.rev() is None:
4465 if ctx.rev() is None:
4467 # When run on the working copy, "locate" includes removed files, so
4466 # When run on the working copy, "locate" includes removed files, so
4468 # we get the list of files from the dirstate.
4467 # we get the list of files from the dirstate.
4469 filesgen = sorted(repo.dirstate.matches(m))
4468 filesgen = sorted(repo.dirstate.matches(m))
4470 else:
4469 else:
4471 filesgen = ctx.matches(m)
4470 filesgen = ctx.matches(m)
4472 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4471 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4473 for abs in filesgen:
4472 for abs in filesgen:
4474 if opts.get(b'fullpath'):
4473 if opts.get(b'fullpath'):
4475 ui.write(repo.wjoin(abs), end)
4474 ui.write(repo.wjoin(abs), end)
4476 else:
4475 else:
4477 ui.write(uipathfn(abs), end)
4476 ui.write(uipathfn(abs), end)
4478 ret = 0
4477 ret = 0
4479
4478
4480 return ret
4479 return ret
4481
4480
4482
4481
4483 @command(
4482 @command(
4484 b'log|history',
4483 b'log|history',
4485 [
4484 [
4486 (
4485 (
4487 b'f',
4486 b'f',
4488 b'follow',
4487 b'follow',
4489 None,
4488 None,
4490 _(
4489 _(
4491 b'follow changeset history, or file history across copies and renames'
4490 b'follow changeset history, or file history across copies and renames'
4492 ),
4491 ),
4493 ),
4492 ),
4494 (
4493 (
4495 b'',
4494 b'',
4496 b'follow-first',
4495 b'follow-first',
4497 None,
4496 None,
4498 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4497 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4499 ),
4498 ),
4500 (
4499 (
4501 b'd',
4500 b'd',
4502 b'date',
4501 b'date',
4503 b'',
4502 b'',
4504 _(b'show revisions matching date spec'),
4503 _(b'show revisions matching date spec'),
4505 _(b'DATE'),
4504 _(b'DATE'),
4506 ),
4505 ),
4507 (b'C', b'copies', None, _(b'show copied files')),
4506 (b'C', b'copies', None, _(b'show copied files')),
4508 (
4507 (
4509 b'k',
4508 b'k',
4510 b'keyword',
4509 b'keyword',
4511 [],
4510 [],
4512 _(b'do case-insensitive search for a given text'),
4511 _(b'do case-insensitive search for a given text'),
4513 _(b'TEXT'),
4512 _(b'TEXT'),
4514 ),
4513 ),
4515 (
4514 (
4516 b'r',
4515 b'r',
4517 b'rev',
4516 b'rev',
4518 [],
4517 [],
4519 _(b'show the specified revision or revset'),
4518 _(b'show the specified revision or revset'),
4520 _(b'REV'),
4519 _(b'REV'),
4521 ),
4520 ),
4522 (
4521 (
4523 b'L',
4522 b'L',
4524 b'line-range',
4523 b'line-range',
4525 [],
4524 [],
4526 _(b'follow line range of specified file (EXPERIMENTAL)'),
4525 _(b'follow line range of specified file (EXPERIMENTAL)'),
4527 _(b'FILE,RANGE'),
4526 _(b'FILE,RANGE'),
4528 ),
4527 ),
4529 (
4528 (
4530 b'',
4529 b'',
4531 b'removed',
4530 b'removed',
4532 None,
4531 None,
4533 _(b'include revisions where files were removed'),
4532 _(b'include revisions where files were removed'),
4534 ),
4533 ),
4535 (
4534 (
4536 b'm',
4535 b'm',
4537 b'only-merges',
4536 b'only-merges',
4538 None,
4537 None,
4539 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4538 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4540 ),
4539 ),
4541 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4540 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4542 (
4541 (
4543 b'',
4542 b'',
4544 b'only-branch',
4543 b'only-branch',
4545 [],
4544 [],
4546 _(
4545 _(
4547 b'show only changesets within the given named branch (DEPRECATED)'
4546 b'show only changesets within the given named branch (DEPRECATED)'
4548 ),
4547 ),
4549 _(b'BRANCH'),
4548 _(b'BRANCH'),
4550 ),
4549 ),
4551 (
4550 (
4552 b'b',
4551 b'b',
4553 b'branch',
4552 b'branch',
4554 [],
4553 [],
4555 _(b'show changesets within the given named branch'),
4554 _(b'show changesets within the given named branch'),
4556 _(b'BRANCH'),
4555 _(b'BRANCH'),
4557 ),
4556 ),
4558 (
4557 (
4559 b'P',
4558 b'P',
4560 b'prune',
4559 b'prune',
4561 [],
4560 [],
4562 _(b'do not display revision or any of its ancestors'),
4561 _(b'do not display revision or any of its ancestors'),
4563 _(b'REV'),
4562 _(b'REV'),
4564 ),
4563 ),
4565 ]
4564 ]
4566 + logopts
4565 + logopts
4567 + walkopts,
4566 + walkopts,
4568 _(b'[OPTION]... [FILE]'),
4567 _(b'[OPTION]... [FILE]'),
4569 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4568 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4570 helpbasic=True,
4569 helpbasic=True,
4571 inferrepo=True,
4570 inferrepo=True,
4572 intents={INTENT_READONLY},
4571 intents={INTENT_READONLY},
4573 )
4572 )
4574 def log(ui, repo, *pats, **opts):
4573 def log(ui, repo, *pats, **opts):
4575 """show revision history of entire repository or files
4574 """show revision history of entire repository or files
4576
4575
4577 Print the revision history of the specified files or the entire
4576 Print the revision history of the specified files or the entire
4578 project.
4577 project.
4579
4578
4580 If no revision range is specified, the default is ``tip:0`` unless
4579 If no revision range is specified, the default is ``tip:0`` unless
4581 --follow is set, in which case the working directory parent is
4580 --follow is set, in which case the working directory parent is
4582 used as the starting revision.
4581 used as the starting revision.
4583
4582
4584 File history is shown without following rename or copy history of
4583 File history is shown without following rename or copy history of
4585 files. Use -f/--follow with a filename to follow history across
4584 files. Use -f/--follow with a filename to follow history across
4586 renames and copies. --follow without a filename will only show
4585 renames and copies. --follow without a filename will only show
4587 ancestors of the starting revision.
4586 ancestors of the starting revision.
4588
4587
4589 By default this command prints revision number and changeset id,
4588 By default this command prints revision number and changeset id,
4590 tags, non-trivial parents, user, date and time, and a summary for
4589 tags, non-trivial parents, user, date and time, and a summary for
4591 each commit. When the -v/--verbose switch is used, the list of
4590 each commit. When the -v/--verbose switch is used, the list of
4592 changed files and full commit message are shown.
4591 changed files and full commit message are shown.
4593
4592
4594 With --graph the revisions are shown as an ASCII art DAG with the most
4593 With --graph the revisions are shown as an ASCII art DAG with the most
4595 recent changeset at the top.
4594 recent changeset at the top.
4596 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
4595 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
4597 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4596 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4598 changeset from the lines below is a parent of the 'o' merge on the same
4597 changeset from the lines below is a parent of the 'o' merge on the same
4599 line.
4598 line.
4600 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4599 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4601 of a '|' indicates one or more revisions in a path are omitted.
4600 of a '|' indicates one or more revisions in a path are omitted.
4602
4601
4603 .. container:: verbose
4602 .. container:: verbose
4604
4603
4605 Use -L/--line-range FILE,M:N options to follow the history of lines
4604 Use -L/--line-range FILE,M:N options to follow the history of lines
4606 from M to N in FILE. With -p/--patch only diff hunks affecting
4605 from M to N in FILE. With -p/--patch only diff hunks affecting
4607 specified line range will be shown. This option requires --follow;
4606 specified line range will be shown. This option requires --follow;
4608 it can be specified multiple times. Currently, this option is not
4607 it can be specified multiple times. Currently, this option is not
4609 compatible with --graph. This option is experimental.
4608 compatible with --graph. This option is experimental.
4610
4609
4611 .. note::
4610 .. note::
4612
4611
4613 :hg:`log --patch` may generate unexpected diff output for merge
4612 :hg:`log --patch` may generate unexpected diff output for merge
4614 changesets, as it will only compare the merge changeset against
4613 changesets, as it will only compare the merge changeset against
4615 its first parent. Also, only files different from BOTH parents
4614 its first parent. Also, only files different from BOTH parents
4616 will appear in files:.
4615 will appear in files:.
4617
4616
4618 .. note::
4617 .. note::
4619
4618
4620 For performance reasons, :hg:`log FILE` may omit duplicate changes
4619 For performance reasons, :hg:`log FILE` may omit duplicate changes
4621 made on branches and will not show removals or mode changes. To
4620 made on branches and will not show removals or mode changes. To
4622 see all such changes, use the --removed switch.
4621 see all such changes, use the --removed switch.
4623
4622
4624 .. container:: verbose
4623 .. container:: verbose
4625
4624
4626 .. note::
4625 .. note::
4627
4626
4628 The history resulting from -L/--line-range options depends on diff
4627 The history resulting from -L/--line-range options depends on diff
4629 options; for instance if white-spaces are ignored, respective changes
4628 options; for instance if white-spaces are ignored, respective changes
4630 with only white-spaces in specified line range will not be listed.
4629 with only white-spaces in specified line range will not be listed.
4631
4630
4632 .. container:: verbose
4631 .. container:: verbose
4633
4632
4634 Some examples:
4633 Some examples:
4635
4634
4636 - changesets with full descriptions and file lists::
4635 - changesets with full descriptions and file lists::
4637
4636
4638 hg log -v
4637 hg log -v
4639
4638
4640 - changesets ancestral to the working directory::
4639 - changesets ancestral to the working directory::
4641
4640
4642 hg log -f
4641 hg log -f
4643
4642
4644 - last 10 commits on the current branch::
4643 - last 10 commits on the current branch::
4645
4644
4646 hg log -l 10 -b .
4645 hg log -l 10 -b .
4647
4646
4648 - changesets showing all modifications of a file, including removals::
4647 - changesets showing all modifications of a file, including removals::
4649
4648
4650 hg log --removed file.c
4649 hg log --removed file.c
4651
4650
4652 - all changesets that touch a directory, with diffs, excluding merges::
4651 - all changesets that touch a directory, with diffs, excluding merges::
4653
4652
4654 hg log -Mp lib/
4653 hg log -Mp lib/
4655
4654
4656 - all revision numbers that match a keyword::
4655 - all revision numbers that match a keyword::
4657
4656
4658 hg log -k bug --template "{rev}\\n"
4657 hg log -k bug --template "{rev}\\n"
4659
4658
4660 - the full hash identifier of the working directory parent::
4659 - the full hash identifier of the working directory parent::
4661
4660
4662 hg log -r . --template "{node}\\n"
4661 hg log -r . --template "{node}\\n"
4663
4662
4664 - list available log templates::
4663 - list available log templates::
4665
4664
4666 hg log -T list
4665 hg log -T list
4667
4666
4668 - check if a given changeset is included in a tagged release::
4667 - check if a given changeset is included in a tagged release::
4669
4668
4670 hg log -r "a21ccf and ancestor(1.9)"
4669 hg log -r "a21ccf and ancestor(1.9)"
4671
4670
4672 - find all changesets by some user in a date range::
4671 - find all changesets by some user in a date range::
4673
4672
4674 hg log -k alice -d "may 2008 to jul 2008"
4673 hg log -k alice -d "may 2008 to jul 2008"
4675
4674
4676 - summary of all changesets after the last tag::
4675 - summary of all changesets after the last tag::
4677
4676
4678 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4677 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4679
4678
4680 - changesets touching lines 13 to 23 for file.c::
4679 - changesets touching lines 13 to 23 for file.c::
4681
4680
4682 hg log -L file.c,13:23
4681 hg log -L file.c,13:23
4683
4682
4684 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4683 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4685 main.c with patch::
4684 main.c with patch::
4686
4685
4687 hg log -L file.c,13:23 -L main.c,2:6 -p
4686 hg log -L file.c,13:23 -L main.c,2:6 -p
4688
4687
4689 See :hg:`help dates` for a list of formats valid for -d/--date.
4688 See :hg:`help dates` for a list of formats valid for -d/--date.
4690
4689
4691 See :hg:`help revisions` for more about specifying and ordering
4690 See :hg:`help revisions` for more about specifying and ordering
4692 revisions.
4691 revisions.
4693
4692
4694 See :hg:`help templates` for more about pre-packaged styles and
4693 See :hg:`help templates` for more about pre-packaged styles and
4695 specifying custom templates. The default template used by the log
4694 specifying custom templates. The default template used by the log
4696 command can be customized via the ``ui.logtemplate`` configuration
4695 command can be customized via the ``ui.logtemplate`` configuration
4697 setting.
4696 setting.
4698
4697
4699 Returns 0 on success.
4698 Returns 0 on success.
4700
4699
4701 """
4700 """
4702 opts = pycompat.byteskwargs(opts)
4701 opts = pycompat.byteskwargs(opts)
4703 linerange = opts.get(b'line_range')
4702 linerange = opts.get(b'line_range')
4704
4703
4705 if linerange and not opts.get(b'follow'):
4704 if linerange and not opts.get(b'follow'):
4706 raise error.Abort(_(b'--line-range requires --follow'))
4705 raise error.Abort(_(b'--line-range requires --follow'))
4707
4706
4708 if linerange and pats:
4707 if linerange and pats:
4709 # TODO: take pats as patterns with no line-range filter
4708 # TODO: take pats as patterns with no line-range filter
4710 raise error.Abort(
4709 raise error.Abort(
4711 _(b'FILE arguments are not compatible with --line-range option')
4710 _(b'FILE arguments are not compatible with --line-range option')
4712 )
4711 )
4713
4712
4714 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4713 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4715 revs, differ = logcmdutil.getrevs(repo, pats, opts)
4714 revs, differ = logcmdutil.getrevs(repo, pats, opts)
4716 if linerange:
4715 if linerange:
4717 # TODO: should follow file history from logcmdutil._initialrevs(),
4716 # TODO: should follow file history from logcmdutil._initialrevs(),
4718 # then filter the result by logcmdutil._makerevset() and --limit
4717 # then filter the result by logcmdutil._makerevset() and --limit
4719 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4718 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4720
4719
4721 getcopies = None
4720 getcopies = None
4722 if opts.get(b'copies'):
4721 if opts.get(b'copies'):
4723 endrev = None
4722 endrev = None
4724 if revs:
4723 if revs:
4725 endrev = revs.max() + 1
4724 endrev = revs.max() + 1
4726 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4725 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4727
4726
4728 ui.pager(b'log')
4727 ui.pager(b'log')
4729 displayer = logcmdutil.changesetdisplayer(
4728 displayer = logcmdutil.changesetdisplayer(
4730 ui, repo, opts, differ, buffered=True
4729 ui, repo, opts, differ, buffered=True
4731 )
4730 )
4732 if opts.get(b'graph'):
4731 if opts.get(b'graph'):
4733 displayfn = logcmdutil.displaygraphrevs
4732 displayfn = logcmdutil.displaygraphrevs
4734 else:
4733 else:
4735 displayfn = logcmdutil.displayrevs
4734 displayfn = logcmdutil.displayrevs
4736 displayfn(ui, repo, revs, displayer, getcopies)
4735 displayfn(ui, repo, revs, displayer, getcopies)
4737
4736
4738
4737
4739 @command(
4738 @command(
4740 b'manifest',
4739 b'manifest',
4741 [
4740 [
4742 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4741 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4743 (b'', b'all', False, _(b"list files from all revisions")),
4742 (b'', b'all', False, _(b"list files from all revisions")),
4744 ]
4743 ]
4745 + formatteropts,
4744 + formatteropts,
4746 _(b'[-r REV]'),
4745 _(b'[-r REV]'),
4747 helpcategory=command.CATEGORY_MAINTENANCE,
4746 helpcategory=command.CATEGORY_MAINTENANCE,
4748 intents={INTENT_READONLY},
4747 intents={INTENT_READONLY},
4749 )
4748 )
4750 def manifest(ui, repo, node=None, rev=None, **opts):
4749 def manifest(ui, repo, node=None, rev=None, **opts):
4751 """output the current or given revision of the project manifest
4750 """output the current or given revision of the project manifest
4752
4751
4753 Print a list of version controlled files for the given revision.
4752 Print a list of version controlled files for the given revision.
4754 If no revision is given, the first parent of the working directory
4753 If no revision is given, the first parent of the working directory
4755 is used, or the null revision if no revision is checked out.
4754 is used, or the null revision if no revision is checked out.
4756
4755
4757 With -v, print file permissions, symlink and executable bits.
4756 With -v, print file permissions, symlink and executable bits.
4758 With --debug, print file revision hashes.
4757 With --debug, print file revision hashes.
4759
4758
4760 If option --all is specified, the list of all files from all revisions
4759 If option --all is specified, the list of all files from all revisions
4761 is printed. This includes deleted and renamed files.
4760 is printed. This includes deleted and renamed files.
4762
4761
4763 Returns 0 on success.
4762 Returns 0 on success.
4764 """
4763 """
4765 opts = pycompat.byteskwargs(opts)
4764 opts = pycompat.byteskwargs(opts)
4766 fm = ui.formatter(b'manifest', opts)
4765 fm = ui.formatter(b'manifest', opts)
4767
4766
4768 if opts.get(b'all'):
4767 if opts.get(b'all'):
4769 if rev or node:
4768 if rev or node:
4770 raise error.Abort(_(b"can't specify a revision with --all"))
4769 raise error.Abort(_(b"can't specify a revision with --all"))
4771
4770
4772 res = set()
4771 res = set()
4773 for rev in repo:
4772 for rev in repo:
4774 ctx = repo[rev]
4773 ctx = repo[rev]
4775 res |= set(ctx.files())
4774 res |= set(ctx.files())
4776
4775
4777 ui.pager(b'manifest')
4776 ui.pager(b'manifest')
4778 for f in sorted(res):
4777 for f in sorted(res):
4779 fm.startitem()
4778 fm.startitem()
4780 fm.write(b"path", b'%s\n', f)
4779 fm.write(b"path", b'%s\n', f)
4781 fm.end()
4780 fm.end()
4782 return
4781 return
4783
4782
4784 if rev and node:
4783 if rev and node:
4785 raise error.Abort(_(b"please specify just one revision"))
4784 raise error.Abort(_(b"please specify just one revision"))
4786
4785
4787 if not node:
4786 if not node:
4788 node = rev
4787 node = rev
4789
4788
4790 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4789 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4791 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4790 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4792 if node:
4791 if node:
4793 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4792 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4794 ctx = scmutil.revsingle(repo, node)
4793 ctx = scmutil.revsingle(repo, node)
4795 mf = ctx.manifest()
4794 mf = ctx.manifest()
4796 ui.pager(b'manifest')
4795 ui.pager(b'manifest')
4797 for f in ctx:
4796 for f in ctx:
4798 fm.startitem()
4797 fm.startitem()
4799 fm.context(ctx=ctx)
4798 fm.context(ctx=ctx)
4800 fl = ctx[f].flags()
4799 fl = ctx[f].flags()
4801 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4800 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4802 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4801 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4803 fm.write(b'path', b'%s\n', f)
4802 fm.write(b'path', b'%s\n', f)
4804 fm.end()
4803 fm.end()
4805
4804
4806
4805
4807 @command(
4806 @command(
4808 b'merge',
4807 b'merge',
4809 [
4808 [
4810 (
4809 (
4811 b'f',
4810 b'f',
4812 b'force',
4811 b'force',
4813 None,
4812 None,
4814 _(b'force a merge including outstanding changes (DEPRECATED)'),
4813 _(b'force a merge including outstanding changes (DEPRECATED)'),
4815 ),
4814 ),
4816 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4815 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4817 (
4816 (
4818 b'P',
4817 b'P',
4819 b'preview',
4818 b'preview',
4820 None,
4819 None,
4821 _(b'review revisions to merge (no merge is performed)'),
4820 _(b'review revisions to merge (no merge is performed)'),
4822 ),
4821 ),
4823 (b'', b'abort', None, _(b'abort the ongoing merge')),
4822 (b'', b'abort', None, _(b'abort the ongoing merge')),
4824 ]
4823 ]
4825 + mergetoolopts,
4824 + mergetoolopts,
4826 _(b'[-P] [[-r] REV]'),
4825 _(b'[-P] [[-r] REV]'),
4827 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4826 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4828 helpbasic=True,
4827 helpbasic=True,
4829 )
4828 )
4830 def merge(ui, repo, node=None, **opts):
4829 def merge(ui, repo, node=None, **opts):
4831 """merge another revision into working directory
4830 """merge another revision into working directory
4832
4831
4833 The current working directory is updated with all changes made in
4832 The current working directory is updated with all changes made in
4834 the requested revision since the last common predecessor revision.
4833 the requested revision since the last common predecessor revision.
4835
4834
4836 Files that changed between either parent are marked as changed for
4835 Files that changed between either parent are marked as changed for
4837 the next commit and a commit must be performed before any further
4836 the next commit and a commit must be performed before any further
4838 updates to the repository are allowed. The next commit will have
4837 updates to the repository are allowed. The next commit will have
4839 two parents.
4838 two parents.
4840
4839
4841 ``--tool`` can be used to specify the merge tool used for file
4840 ``--tool`` can be used to specify the merge tool used for file
4842 merges. It overrides the HGMERGE environment variable and your
4841 merges. It overrides the HGMERGE environment variable and your
4843 configuration files. See :hg:`help merge-tools` for options.
4842 configuration files. See :hg:`help merge-tools` for options.
4844
4843
4845 If no revision is specified, the working directory's parent is a
4844 If no revision is specified, the working directory's parent is a
4846 head revision, and the current branch contains exactly one other
4845 head revision, and the current branch contains exactly one other
4847 head, the other head is merged with by default. Otherwise, an
4846 head, the other head is merged with by default. Otherwise, an
4848 explicit revision with which to merge must be provided.
4847 explicit revision with which to merge must be provided.
4849
4848
4850 See :hg:`help resolve` for information on handling file conflicts.
4849 See :hg:`help resolve` for information on handling file conflicts.
4851
4850
4852 To undo an uncommitted merge, use :hg:`merge --abort` which
4851 To undo an uncommitted merge, use :hg:`merge --abort` which
4853 will check out a clean copy of the original merge parent, losing
4852 will check out a clean copy of the original merge parent, losing
4854 all changes.
4853 all changes.
4855
4854
4856 Returns 0 on success, 1 if there are unresolved files.
4855 Returns 0 on success, 1 if there are unresolved files.
4857 """
4856 """
4858
4857
4859 opts = pycompat.byteskwargs(opts)
4858 opts = pycompat.byteskwargs(opts)
4860 abort = opts.get(b'abort')
4859 abort = opts.get(b'abort')
4861 if abort and repo.dirstate.p2() == nullid:
4860 if abort and repo.dirstate.p2() == nullid:
4862 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4861 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4863 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4862 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4864 if abort:
4863 if abort:
4865 state = cmdutil.getunfinishedstate(repo)
4864 state = cmdutil.getunfinishedstate(repo)
4866 if state and state._opname != b'merge':
4865 if state and state._opname != b'merge':
4867 raise error.Abort(
4866 raise error.Abort(
4868 _(b'cannot abort merge with %s in progress') % (state._opname),
4867 _(b'cannot abort merge with %s in progress') % (state._opname),
4869 hint=state.hint(),
4868 hint=state.hint(),
4870 )
4869 )
4871 if node:
4870 if node:
4872 raise error.Abort(_(b"cannot specify a node with --abort"))
4871 raise error.Abort(_(b"cannot specify a node with --abort"))
4873 return hg.abortmerge(repo.ui, repo)
4872 return hg.abortmerge(repo.ui, repo)
4874
4873
4875 if opts.get(b'rev') and node:
4874 if opts.get(b'rev') and node:
4876 raise error.Abort(_(b"please specify just one revision"))
4875 raise error.Abort(_(b"please specify just one revision"))
4877 if not node:
4876 if not node:
4878 node = opts.get(b'rev')
4877 node = opts.get(b'rev')
4879
4878
4880 if node:
4879 if node:
4881 ctx = scmutil.revsingle(repo, node)
4880 ctx = scmutil.revsingle(repo, node)
4882 else:
4881 else:
4883 if ui.configbool(b'commands', b'merge.require-rev'):
4882 if ui.configbool(b'commands', b'merge.require-rev'):
4884 raise error.Abort(
4883 raise error.Abort(
4885 _(
4884 _(
4886 b'configuration requires specifying revision to merge '
4885 b'configuration requires specifying revision to merge '
4887 b'with'
4886 b'with'
4888 )
4887 )
4889 )
4888 )
4890 ctx = repo[destutil.destmerge(repo)]
4889 ctx = repo[destutil.destmerge(repo)]
4891
4890
4892 if ctx.node() is None:
4891 if ctx.node() is None:
4893 raise error.Abort(_(b'merging with the working copy has no effect'))
4892 raise error.Abort(_(b'merging with the working copy has no effect'))
4894
4893
4895 if opts.get(b'preview'):
4894 if opts.get(b'preview'):
4896 # find nodes that are ancestors of p2 but not of p1
4895 # find nodes that are ancestors of p2 but not of p1
4897 p1 = repo[b'.'].node()
4896 p1 = repo[b'.'].node()
4898 p2 = ctx.node()
4897 p2 = ctx.node()
4899 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4898 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4900
4899
4901 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4900 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4902 for node in nodes:
4901 for node in nodes:
4903 displayer.show(repo[node])
4902 displayer.show(repo[node])
4904 displayer.close()
4903 displayer.close()
4905 return 0
4904 return 0
4906
4905
4907 # ui.forcemerge is an internal variable, do not document
4906 # ui.forcemerge is an internal variable, do not document
4908 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4907 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4909 with ui.configoverride(overrides, b'merge'):
4908 with ui.configoverride(overrides, b'merge'):
4910 force = opts.get(b'force')
4909 force = opts.get(b'force')
4911 labels = [b'working copy', b'merge rev']
4910 labels = [b'working copy', b'merge rev']
4912 return hg.merge(ctx, force=force, labels=labels)
4911 return hg.merge(ctx, force=force, labels=labels)
4913
4912
4914
4913
4915 statemod.addunfinished(
4914 statemod.addunfinished(
4916 b'merge',
4915 b'merge',
4917 fname=None,
4916 fname=None,
4918 clearable=True,
4917 clearable=True,
4919 allowcommit=True,
4918 allowcommit=True,
4920 cmdmsg=_(b'outstanding uncommitted merge'),
4919 cmdmsg=_(b'outstanding uncommitted merge'),
4921 abortfunc=hg.abortmerge,
4920 abortfunc=hg.abortmerge,
4922 statushint=_(
4921 statushint=_(
4923 b'To continue: hg commit\nTo abort: hg merge --abort'
4922 b'To continue: hg commit\nTo abort: hg merge --abort'
4924 ),
4923 ),
4925 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4924 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4926 )
4925 )
4927
4926
4928
4927
4929 @command(
4928 @command(
4930 b'outgoing|out',
4929 b'outgoing|out',
4931 [
4930 [
4932 (
4931 (
4933 b'f',
4932 b'f',
4934 b'force',
4933 b'force',
4935 None,
4934 None,
4936 _(b'run even when the destination is unrelated'),
4935 _(b'run even when the destination is unrelated'),
4937 ),
4936 ),
4938 (
4937 (
4939 b'r',
4938 b'r',
4940 b'rev',
4939 b'rev',
4941 [],
4940 [],
4942 _(b'a changeset intended to be included in the destination'),
4941 _(b'a changeset intended to be included in the destination'),
4943 _(b'REV'),
4942 _(b'REV'),
4944 ),
4943 ),
4945 (b'n', b'newest-first', None, _(b'show newest record first')),
4944 (b'n', b'newest-first', None, _(b'show newest record first')),
4946 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4945 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4947 (
4946 (
4948 b'b',
4947 b'b',
4949 b'branch',
4948 b'branch',
4950 [],
4949 [],
4951 _(b'a specific branch you would like to push'),
4950 _(b'a specific branch you would like to push'),
4952 _(b'BRANCH'),
4951 _(b'BRANCH'),
4953 ),
4952 ),
4954 ]
4953 ]
4955 + logopts
4954 + logopts
4956 + remoteopts
4955 + remoteopts
4957 + subrepoopts,
4956 + subrepoopts,
4958 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4957 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4959 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4958 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4960 )
4959 )
4961 def outgoing(ui, repo, dest=None, **opts):
4960 def outgoing(ui, repo, dest=None, **opts):
4962 """show changesets not found in the destination
4961 """show changesets not found in the destination
4963
4962
4964 Show changesets not found in the specified destination repository
4963 Show changesets not found in the specified destination repository
4965 or the default push location. These are the changesets that would
4964 or the default push location. These are the changesets that would
4966 be pushed if a push was requested.
4965 be pushed if a push was requested.
4967
4966
4968 See pull for details of valid destination formats.
4967 See pull for details of valid destination formats.
4969
4968
4970 .. container:: verbose
4969 .. container:: verbose
4971
4970
4972 With -B/--bookmarks, the result of bookmark comparison between
4971 With -B/--bookmarks, the result of bookmark comparison between
4973 local and remote repositories is displayed. With -v/--verbose,
4972 local and remote repositories is displayed. With -v/--verbose,
4974 status is also displayed for each bookmark like below::
4973 status is also displayed for each bookmark like below::
4975
4974
4976 BM1 01234567890a added
4975 BM1 01234567890a added
4977 BM2 deleted
4976 BM2 deleted
4978 BM3 234567890abc advanced
4977 BM3 234567890abc advanced
4979 BM4 34567890abcd diverged
4978 BM4 34567890abcd diverged
4980 BM5 4567890abcde changed
4979 BM5 4567890abcde changed
4981
4980
4982 The action taken when pushing depends on the
4981 The action taken when pushing depends on the
4983 status of each bookmark:
4982 status of each bookmark:
4984
4983
4985 :``added``: push with ``-B`` will create it
4984 :``added``: push with ``-B`` will create it
4986 :``deleted``: push with ``-B`` will delete it
4985 :``deleted``: push with ``-B`` will delete it
4987 :``advanced``: push will update it
4986 :``advanced``: push will update it
4988 :``diverged``: push with ``-B`` will update it
4987 :``diverged``: push with ``-B`` will update it
4989 :``changed``: push with ``-B`` will update it
4988 :``changed``: push with ``-B`` will update it
4990
4989
4991 From the point of view of pushing behavior, bookmarks
4990 From the point of view of pushing behavior, bookmarks
4992 existing only in the remote repository are treated as
4991 existing only in the remote repository are treated as
4993 ``deleted``, even if it is in fact added remotely.
4992 ``deleted``, even if it is in fact added remotely.
4994
4993
4995 Returns 0 if there are outgoing changes, 1 otherwise.
4994 Returns 0 if there are outgoing changes, 1 otherwise.
4996 """
4995 """
4997 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4996 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4998 # style URLs, so don't overwrite dest.
4997 # style URLs, so don't overwrite dest.
4999 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
4998 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5000 if not path:
4999 if not path:
5001 raise error.Abort(
5000 raise error.Abort(
5002 _(b'default repository not configured!'),
5001 _(b'default repository not configured!'),
5003 hint=_(b"see 'hg help config.paths'"),
5002 hint=_(b"see 'hg help config.paths'"),
5004 )
5003 )
5005
5004
5006 opts = pycompat.byteskwargs(opts)
5005 opts = pycompat.byteskwargs(opts)
5007 if opts.get(b'graph'):
5006 if opts.get(b'graph'):
5008 logcmdutil.checkunsupportedgraphflags([], opts)
5007 logcmdutil.checkunsupportedgraphflags([], opts)
5009 o, other = hg._outgoing(ui, repo, dest, opts)
5008 o, other = hg._outgoing(ui, repo, dest, opts)
5010 if not o:
5009 if not o:
5011 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5010 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5012 return
5011 return
5013
5012
5014 revdag = logcmdutil.graphrevs(repo, o, opts)
5013 revdag = logcmdutil.graphrevs(repo, o, opts)
5015 ui.pager(b'outgoing')
5014 ui.pager(b'outgoing')
5016 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
5015 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
5017 logcmdutil.displaygraph(
5016 logcmdutil.displaygraph(
5018 ui, repo, revdag, displayer, graphmod.asciiedges
5017 ui, repo, revdag, displayer, graphmod.asciiedges
5019 )
5018 )
5020 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5019 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5021 return 0
5020 return 0
5022
5021
5023 if opts.get(b'bookmarks'):
5022 if opts.get(b'bookmarks'):
5024 dest = path.pushloc or path.loc
5023 dest = path.pushloc or path.loc
5025 other = hg.peer(repo, opts, dest)
5024 other = hg.peer(repo, opts, dest)
5026 if b'bookmarks' not in other.listkeys(b'namespaces'):
5025 if b'bookmarks' not in other.listkeys(b'namespaces'):
5027 ui.warn(_(b"remote doesn't support bookmarks\n"))
5026 ui.warn(_(b"remote doesn't support bookmarks\n"))
5028 return 0
5027 return 0
5029 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
5028 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
5030 ui.pager(b'outgoing')
5029 ui.pager(b'outgoing')
5031 return bookmarks.outgoing(ui, repo, other)
5030 return bookmarks.outgoing(ui, repo, other)
5032
5031
5033 repo._subtoppath = path.pushloc or path.loc
5032 repo._subtoppath = path.pushloc or path.loc
5034 try:
5033 try:
5035 return hg.outgoing(ui, repo, dest, opts)
5034 return hg.outgoing(ui, repo, dest, opts)
5036 finally:
5035 finally:
5037 del repo._subtoppath
5036 del repo._subtoppath
5038
5037
5039
5038
5040 @command(
5039 @command(
5041 b'parents',
5040 b'parents',
5042 [
5041 [
5043 (
5042 (
5044 b'r',
5043 b'r',
5045 b'rev',
5044 b'rev',
5046 b'',
5045 b'',
5047 _(b'show parents of the specified revision'),
5046 _(b'show parents of the specified revision'),
5048 _(b'REV'),
5047 _(b'REV'),
5049 ),
5048 ),
5050 ]
5049 ]
5051 + templateopts,
5050 + templateopts,
5052 _(b'[-r REV] [FILE]'),
5051 _(b'[-r REV] [FILE]'),
5053 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5052 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5054 inferrepo=True,
5053 inferrepo=True,
5055 )
5054 )
5056 def parents(ui, repo, file_=None, **opts):
5055 def parents(ui, repo, file_=None, **opts):
5057 """show the parents of the working directory or revision (DEPRECATED)
5056 """show the parents of the working directory or revision (DEPRECATED)
5058
5057
5059 Print the working directory's parent revisions. If a revision is
5058 Print the working directory's parent revisions. If a revision is
5060 given via -r/--rev, the parent of that revision will be printed.
5059 given via -r/--rev, the parent of that revision will be printed.
5061 If a file argument is given, the revision in which the file was
5060 If a file argument is given, the revision in which the file was
5062 last changed (before the working directory revision or the
5061 last changed (before the working directory revision or the
5063 argument to --rev if given) is printed.
5062 argument to --rev if given) is printed.
5064
5063
5065 This command is equivalent to::
5064 This command is equivalent to::
5066
5065
5067 hg log -r "p1()+p2()" or
5066 hg log -r "p1()+p2()" or
5068 hg log -r "p1(REV)+p2(REV)" or
5067 hg log -r "p1(REV)+p2(REV)" or
5069 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5068 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5070 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5069 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5071
5070
5072 See :hg:`summary` and :hg:`help revsets` for related information.
5071 See :hg:`summary` and :hg:`help revsets` for related information.
5073
5072
5074 Returns 0 on success.
5073 Returns 0 on success.
5075 """
5074 """
5076
5075
5077 opts = pycompat.byteskwargs(opts)
5076 opts = pycompat.byteskwargs(opts)
5078 rev = opts.get(b'rev')
5077 rev = opts.get(b'rev')
5079 if rev:
5078 if rev:
5080 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5079 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5081 ctx = scmutil.revsingle(repo, rev, None)
5080 ctx = scmutil.revsingle(repo, rev, None)
5082
5081
5083 if file_:
5082 if file_:
5084 m = scmutil.match(ctx, (file_,), opts)
5083 m = scmutil.match(ctx, (file_,), opts)
5085 if m.anypats() or len(m.files()) != 1:
5084 if m.anypats() or len(m.files()) != 1:
5086 raise error.Abort(_(b'can only specify an explicit filename'))
5085 raise error.Abort(_(b'can only specify an explicit filename'))
5087 file_ = m.files()[0]
5086 file_ = m.files()[0]
5088 filenodes = []
5087 filenodes = []
5089 for cp in ctx.parents():
5088 for cp in ctx.parents():
5090 if not cp:
5089 if not cp:
5091 continue
5090 continue
5092 try:
5091 try:
5093 filenodes.append(cp.filenode(file_))
5092 filenodes.append(cp.filenode(file_))
5094 except error.LookupError:
5093 except error.LookupError:
5095 pass
5094 pass
5096 if not filenodes:
5095 if not filenodes:
5097 raise error.Abort(_(b"'%s' not found in manifest!") % file_)
5096 raise error.Abort(_(b"'%s' not found in manifest!") % file_)
5098 p = []
5097 p = []
5099 for fn in filenodes:
5098 for fn in filenodes:
5100 fctx = repo.filectx(file_, fileid=fn)
5099 fctx = repo.filectx(file_, fileid=fn)
5101 p.append(fctx.node())
5100 p.append(fctx.node())
5102 else:
5101 else:
5103 p = [cp.node() for cp in ctx.parents()]
5102 p = [cp.node() for cp in ctx.parents()]
5104
5103
5105 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5104 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5106 for n in p:
5105 for n in p:
5107 if n != nullid:
5106 if n != nullid:
5108 displayer.show(repo[n])
5107 displayer.show(repo[n])
5109 displayer.close()
5108 displayer.close()
5110
5109
5111
5110
5112 @command(
5111 @command(
5113 b'paths',
5112 b'paths',
5114 formatteropts,
5113 formatteropts,
5115 _(b'[NAME]'),
5114 _(b'[NAME]'),
5116 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5115 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5117 optionalrepo=True,
5116 optionalrepo=True,
5118 intents={INTENT_READONLY},
5117 intents={INTENT_READONLY},
5119 )
5118 )
5120 def paths(ui, repo, search=None, **opts):
5119 def paths(ui, repo, search=None, **opts):
5121 """show aliases for remote repositories
5120 """show aliases for remote repositories
5122
5121
5123 Show definition of symbolic path name NAME. If no name is given,
5122 Show definition of symbolic path name NAME. If no name is given,
5124 show definition of all available names.
5123 show definition of all available names.
5125
5124
5126 Option -q/--quiet suppresses all output when searching for NAME
5125 Option -q/--quiet suppresses all output when searching for NAME
5127 and shows only the path names when listing all definitions.
5126 and shows only the path names when listing all definitions.
5128
5127
5129 Path names are defined in the [paths] section of your
5128 Path names are defined in the [paths] section of your
5130 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5129 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5131 repository, ``.hg/hgrc`` is used, too.
5130 repository, ``.hg/hgrc`` is used, too.
5132
5131
5133 The path names ``default`` and ``default-push`` have a special
5132 The path names ``default`` and ``default-push`` have a special
5134 meaning. When performing a push or pull operation, they are used
5133 meaning. When performing a push or pull operation, they are used
5135 as fallbacks if no location is specified on the command-line.
5134 as fallbacks if no location is specified on the command-line.
5136 When ``default-push`` is set, it will be used for push and
5135 When ``default-push`` is set, it will be used for push and
5137 ``default`` will be used for pull; otherwise ``default`` is used
5136 ``default`` will be used for pull; otherwise ``default`` is used
5138 as the fallback for both. When cloning a repository, the clone
5137 as the fallback for both. When cloning a repository, the clone
5139 source is written as ``default`` in ``.hg/hgrc``.
5138 source is written as ``default`` in ``.hg/hgrc``.
5140
5139
5141 .. note::
5140 .. note::
5142
5141
5143 ``default`` and ``default-push`` apply to all inbound (e.g.
5142 ``default`` and ``default-push`` apply to all inbound (e.g.
5144 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5143 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5145 and :hg:`bundle`) operations.
5144 and :hg:`bundle`) operations.
5146
5145
5147 See :hg:`help urls` for more information.
5146 See :hg:`help urls` for more information.
5148
5147
5149 .. container:: verbose
5148 .. container:: verbose
5150
5149
5151 Template:
5150 Template:
5152
5151
5153 The following keywords are supported. See also :hg:`help templates`.
5152 The following keywords are supported. See also :hg:`help templates`.
5154
5153
5155 :name: String. Symbolic name of the path alias.
5154 :name: String. Symbolic name of the path alias.
5156 :pushurl: String. URL for push operations.
5155 :pushurl: String. URL for push operations.
5157 :url: String. URL or directory path for the other operations.
5156 :url: String. URL or directory path for the other operations.
5158
5157
5159 Returns 0 on success.
5158 Returns 0 on success.
5160 """
5159 """
5161
5160
5162 opts = pycompat.byteskwargs(opts)
5161 opts = pycompat.byteskwargs(opts)
5163 ui.pager(b'paths')
5162 ui.pager(b'paths')
5164 if search:
5163 if search:
5165 pathitems = [
5164 pathitems = [
5166 (name, path)
5165 (name, path)
5167 for name, path in pycompat.iteritems(ui.paths)
5166 for name, path in pycompat.iteritems(ui.paths)
5168 if name == search
5167 if name == search
5169 ]
5168 ]
5170 else:
5169 else:
5171 pathitems = sorted(pycompat.iteritems(ui.paths))
5170 pathitems = sorted(pycompat.iteritems(ui.paths))
5172
5171
5173 fm = ui.formatter(b'paths', opts)
5172 fm = ui.formatter(b'paths', opts)
5174 if fm.isplain():
5173 if fm.isplain():
5175 hidepassword = util.hidepassword
5174 hidepassword = util.hidepassword
5176 else:
5175 else:
5177 hidepassword = bytes
5176 hidepassword = bytes
5178 if ui.quiet:
5177 if ui.quiet:
5179 namefmt = b'%s\n'
5178 namefmt = b'%s\n'
5180 else:
5179 else:
5181 namefmt = b'%s = '
5180 namefmt = b'%s = '
5182 showsubopts = not search and not ui.quiet
5181 showsubopts = not search and not ui.quiet
5183
5182
5184 for name, path in pathitems:
5183 for name, path in pathitems:
5185 fm.startitem()
5184 fm.startitem()
5186 fm.condwrite(not search, b'name', namefmt, name)
5185 fm.condwrite(not search, b'name', namefmt, name)
5187 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5186 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5188 for subopt, value in sorted(path.suboptions.items()):
5187 for subopt, value in sorted(path.suboptions.items()):
5189 assert subopt not in (b'name', b'url')
5188 assert subopt not in (b'name', b'url')
5190 if showsubopts:
5189 if showsubopts:
5191 fm.plain(b'%s:%s = ' % (name, subopt))
5190 fm.plain(b'%s:%s = ' % (name, subopt))
5192 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5191 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5193
5192
5194 fm.end()
5193 fm.end()
5195
5194
5196 if search and not pathitems:
5195 if search and not pathitems:
5197 if not ui.quiet:
5196 if not ui.quiet:
5198 ui.warn(_(b"not found!\n"))
5197 ui.warn(_(b"not found!\n"))
5199 return 1
5198 return 1
5200 else:
5199 else:
5201 return 0
5200 return 0
5202
5201
5203
5202
5204 @command(
5203 @command(
5205 b'phase',
5204 b'phase',
5206 [
5205 [
5207 (b'p', b'public', False, _(b'set changeset phase to public')),
5206 (b'p', b'public', False, _(b'set changeset phase to public')),
5208 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5207 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5209 (b's', b'secret', False, _(b'set changeset phase to secret')),
5208 (b's', b'secret', False, _(b'set changeset phase to secret')),
5210 (b'f', b'force', False, _(b'allow to move boundary backward')),
5209 (b'f', b'force', False, _(b'allow to move boundary backward')),
5211 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5210 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5212 ],
5211 ],
5213 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5212 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5214 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5213 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5215 )
5214 )
5216 def phase(ui, repo, *revs, **opts):
5215 def phase(ui, repo, *revs, **opts):
5217 """set or show the current phase name
5216 """set or show the current phase name
5218
5217
5219 With no argument, show the phase name of the current revision(s).
5218 With no argument, show the phase name of the current revision(s).
5220
5219
5221 With one of -p/--public, -d/--draft or -s/--secret, change the
5220 With one of -p/--public, -d/--draft or -s/--secret, change the
5222 phase value of the specified revisions.
5221 phase value of the specified revisions.
5223
5222
5224 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5223 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5225 lower phase to a higher phase. Phases are ordered as follows::
5224 lower phase to a higher phase. Phases are ordered as follows::
5226
5225
5227 public < draft < secret
5226 public < draft < secret
5228
5227
5229 Returns 0 on success, 1 if some phases could not be changed.
5228 Returns 0 on success, 1 if some phases could not be changed.
5230
5229
5231 (For more information about the phases concept, see :hg:`help phases`.)
5230 (For more information about the phases concept, see :hg:`help phases`.)
5232 """
5231 """
5233 opts = pycompat.byteskwargs(opts)
5232 opts = pycompat.byteskwargs(opts)
5234 # search for a unique phase argument
5233 # search for a unique phase argument
5235 targetphase = None
5234 targetphase = None
5236 for idx, name in enumerate(phases.cmdphasenames):
5235 for idx, name in enumerate(phases.cmdphasenames):
5237 if opts[name]:
5236 if opts[name]:
5238 if targetphase is not None:
5237 if targetphase is not None:
5239 raise error.Abort(_(b'only one phase can be specified'))
5238 raise error.Abort(_(b'only one phase can be specified'))
5240 targetphase = idx
5239 targetphase = idx
5241
5240
5242 # look for specified revision
5241 # look for specified revision
5243 revs = list(revs)
5242 revs = list(revs)
5244 revs.extend(opts[b'rev'])
5243 revs.extend(opts[b'rev'])
5245 if not revs:
5244 if not revs:
5246 # display both parents as the second parent phase can influence
5245 # display both parents as the second parent phase can influence
5247 # the phase of a merge commit
5246 # the phase of a merge commit
5248 revs = [c.rev() for c in repo[None].parents()]
5247 revs = [c.rev() for c in repo[None].parents()]
5249
5248
5250 revs = scmutil.revrange(repo, revs)
5249 revs = scmutil.revrange(repo, revs)
5251
5250
5252 ret = 0
5251 ret = 0
5253 if targetphase is None:
5252 if targetphase is None:
5254 # display
5253 # display
5255 for r in revs:
5254 for r in revs:
5256 ctx = repo[r]
5255 ctx = repo[r]
5257 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5256 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5258 else:
5257 else:
5259 with repo.lock(), repo.transaction(b"phase") as tr:
5258 with repo.lock(), repo.transaction(b"phase") as tr:
5260 # set phase
5259 # set phase
5261 if not revs:
5260 if not revs:
5262 raise error.Abort(_(b'empty revision set'))
5261 raise error.Abort(_(b'empty revision set'))
5263 nodes = [repo[r].node() for r in revs]
5262 nodes = [repo[r].node() for r in revs]
5264 # moving revision from public to draft may hide them
5263 # moving revision from public to draft may hide them
5265 # We have to check result on an unfiltered repository
5264 # We have to check result on an unfiltered repository
5266 unfi = repo.unfiltered()
5265 unfi = repo.unfiltered()
5267 getphase = unfi._phasecache.phase
5266 getphase = unfi._phasecache.phase
5268 olddata = [getphase(unfi, r) for r in unfi]
5267 olddata = [getphase(unfi, r) for r in unfi]
5269 phases.advanceboundary(repo, tr, targetphase, nodes)
5268 phases.advanceboundary(repo, tr, targetphase, nodes)
5270 if opts[b'force']:
5269 if opts[b'force']:
5271 phases.retractboundary(repo, tr, targetphase, nodes)
5270 phases.retractboundary(repo, tr, targetphase, nodes)
5272 getphase = unfi._phasecache.phase
5271 getphase = unfi._phasecache.phase
5273 newdata = [getphase(unfi, r) for r in unfi]
5272 newdata = [getphase(unfi, r) for r in unfi]
5274 changes = sum(newdata[r] != olddata[r] for r in unfi)
5273 changes = sum(newdata[r] != olddata[r] for r in unfi)
5275 cl = unfi.changelog
5274 cl = unfi.changelog
5276 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5275 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5277 if rejected:
5276 if rejected:
5278 ui.warn(
5277 ui.warn(
5279 _(
5278 _(
5280 b'cannot move %i changesets to a higher '
5279 b'cannot move %i changesets to a higher '
5281 b'phase, use --force\n'
5280 b'phase, use --force\n'
5282 )
5281 )
5283 % len(rejected)
5282 % len(rejected)
5284 )
5283 )
5285 ret = 1
5284 ret = 1
5286 if changes:
5285 if changes:
5287 msg = _(b'phase changed for %i changesets\n') % changes
5286 msg = _(b'phase changed for %i changesets\n') % changes
5288 if ret:
5287 if ret:
5289 ui.status(msg)
5288 ui.status(msg)
5290 else:
5289 else:
5291 ui.note(msg)
5290 ui.note(msg)
5292 else:
5291 else:
5293 ui.warn(_(b'no phases changed\n'))
5292 ui.warn(_(b'no phases changed\n'))
5294 return ret
5293 return ret
5295
5294
5296
5295
5297 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5296 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5298 """Run after a changegroup has been added via pull/unbundle
5297 """Run after a changegroup has been added via pull/unbundle
5299
5298
5300 This takes arguments below:
5299 This takes arguments below:
5301
5300
5302 :modheads: change of heads by pull/unbundle
5301 :modheads: change of heads by pull/unbundle
5303 :optupdate: updating working directory is needed or not
5302 :optupdate: updating working directory is needed or not
5304 :checkout: update destination revision (or None to default destination)
5303 :checkout: update destination revision (or None to default destination)
5305 :brev: a name, which might be a bookmark to be activated after updating
5304 :brev: a name, which might be a bookmark to be activated after updating
5306 """
5305 """
5307 if modheads == 0:
5306 if modheads == 0:
5308 return
5307 return
5309 if optupdate:
5308 if optupdate:
5310 try:
5309 try:
5311 return hg.updatetotally(ui, repo, checkout, brev)
5310 return hg.updatetotally(ui, repo, checkout, brev)
5312 except error.UpdateAbort as inst:
5311 except error.UpdateAbort as inst:
5313 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5312 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5314 hint = inst.hint
5313 hint = inst.hint
5315 raise error.UpdateAbort(msg, hint=hint)
5314 raise error.UpdateAbort(msg, hint=hint)
5316 if modheads is not None and modheads > 1:
5315 if modheads is not None and modheads > 1:
5317 currentbranchheads = len(repo.branchheads())
5316 currentbranchheads = len(repo.branchheads())
5318 if currentbranchheads == modheads:
5317 if currentbranchheads == modheads:
5319 ui.status(
5318 ui.status(
5320 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5319 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5321 )
5320 )
5322 elif currentbranchheads > 1:
5321 elif currentbranchheads > 1:
5323 ui.status(
5322 ui.status(
5324 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5323 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5325 )
5324 )
5326 else:
5325 else:
5327 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5326 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5328 elif not ui.configbool(b'commands', b'update.requiredest'):
5327 elif not ui.configbool(b'commands', b'update.requiredest'):
5329 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5328 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5330
5329
5331
5330
5332 @command(
5331 @command(
5333 b'pull',
5332 b'pull',
5334 [
5333 [
5335 (
5334 (
5336 b'u',
5335 b'u',
5337 b'update',
5336 b'update',
5338 None,
5337 None,
5339 _(b'update to new branch head if new descendants were pulled'),
5338 _(b'update to new branch head if new descendants were pulled'),
5340 ),
5339 ),
5341 (
5340 (
5342 b'f',
5341 b'f',
5343 b'force',
5342 b'force',
5344 None,
5343 None,
5345 _(b'run even when remote repository is unrelated'),
5344 _(b'run even when remote repository is unrelated'),
5346 ),
5345 ),
5347 (b'', b'confirm', None, _(b'confirm pull before applying changes'),),
5346 (b'', b'confirm', None, _(b'confirm pull before applying changes'),),
5348 (
5347 (
5349 b'r',
5348 b'r',
5350 b'rev',
5349 b'rev',
5351 [],
5350 [],
5352 _(b'a remote changeset intended to be added'),
5351 _(b'a remote changeset intended to be added'),
5353 _(b'REV'),
5352 _(b'REV'),
5354 ),
5353 ),
5355 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5354 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5356 (
5355 (
5357 b'b',
5356 b'b',
5358 b'branch',
5357 b'branch',
5359 [],
5358 [],
5360 _(b'a specific branch you would like to pull'),
5359 _(b'a specific branch you would like to pull'),
5361 _(b'BRANCH'),
5360 _(b'BRANCH'),
5362 ),
5361 ),
5363 ]
5362 ]
5364 + remoteopts,
5363 + remoteopts,
5365 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
5364 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
5366 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5365 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5367 helpbasic=True,
5366 helpbasic=True,
5368 )
5367 )
5369 def pull(ui, repo, source=b"default", **opts):
5368 def pull(ui, repo, source=b"default", **opts):
5370 """pull changes from the specified source
5369 """pull changes from the specified source
5371
5370
5372 Pull changes from a remote repository to a local one.
5371 Pull changes from a remote repository to a local one.
5373
5372
5374 This finds all changes from the repository at the specified path
5373 This finds all changes from the repository at the specified path
5375 or URL and adds them to a local repository (the current one unless
5374 or URL and adds them to a local repository (the current one unless
5376 -R is specified). By default, this does not update the copy of the
5375 -R is specified). By default, this does not update the copy of the
5377 project in the working directory.
5376 project in the working directory.
5378
5377
5379 When cloning from servers that support it, Mercurial may fetch
5378 When cloning from servers that support it, Mercurial may fetch
5380 pre-generated data. When this is done, hooks operating on incoming
5379 pre-generated data. When this is done, hooks operating on incoming
5381 changesets and changegroups may fire more than once, once for each
5380 changesets and changegroups may fire more than once, once for each
5382 pre-generated bundle and as well as for any additional remaining
5381 pre-generated bundle and as well as for any additional remaining
5383 data. See :hg:`help -e clonebundles` for more.
5382 data. See :hg:`help -e clonebundles` for more.
5384
5383
5385 Use :hg:`incoming` if you want to see what would have been added
5384 Use :hg:`incoming` if you want to see what would have been added
5386 by a pull at the time you issued this command. If you then decide
5385 by a pull at the time you issued this command. If you then decide
5387 to add those changes to the repository, you should use :hg:`pull
5386 to add those changes to the repository, you should use :hg:`pull
5388 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5387 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5389
5388
5390 If SOURCE is omitted, the 'default' path will be used.
5389 If SOURCE is omitted, the 'default' path will be used.
5391 See :hg:`help urls` for more information.
5390 See :hg:`help urls` for more information.
5392
5391
5393 Specifying bookmark as ``.`` is equivalent to specifying the active
5392 Specifying bookmark as ``.`` is equivalent to specifying the active
5394 bookmark's name.
5393 bookmark's name.
5395
5394
5396 Returns 0 on success, 1 if an update had unresolved files.
5395 Returns 0 on success, 1 if an update had unresolved files.
5397 """
5396 """
5398
5397
5399 opts = pycompat.byteskwargs(opts)
5398 opts = pycompat.byteskwargs(opts)
5400 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5399 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5401 b'update'
5400 b'update'
5402 ):
5401 ):
5403 msg = _(b'update destination required by configuration')
5402 msg = _(b'update destination required by configuration')
5404 hint = _(b'use hg pull followed by hg update DEST')
5403 hint = _(b'use hg pull followed by hg update DEST')
5405 raise error.Abort(msg, hint=hint)
5404 raise error.Abort(msg, hint=hint)
5406
5405
5407 source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
5406 source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
5408 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5407 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5409 other = hg.peer(repo, opts, source)
5408 other = hg.peer(repo, opts, source)
5410 try:
5409 try:
5411 revs, checkout = hg.addbranchrevs(
5410 revs, checkout = hg.addbranchrevs(
5412 repo, other, branches, opts.get(b'rev')
5411 repo, other, branches, opts.get(b'rev')
5413 )
5412 )
5414
5413
5415 pullopargs = {}
5414 pullopargs = {}
5416
5415
5417 nodes = None
5416 nodes = None
5418 if opts.get(b'bookmark') or revs:
5417 if opts.get(b'bookmark') or revs:
5419 # The list of bookmark used here is the same used to actually update
5418 # The list of bookmark used here is the same used to actually update
5420 # the bookmark names, to avoid the race from issue 4689 and we do
5419 # the bookmark names, to avoid the race from issue 4689 and we do
5421 # all lookup and bookmark queries in one go so they see the same
5420 # all lookup and bookmark queries in one go so they see the same
5422 # version of the server state (issue 4700).
5421 # version of the server state (issue 4700).
5423 nodes = []
5422 nodes = []
5424 fnodes = []
5423 fnodes = []
5425 revs = revs or []
5424 revs = revs or []
5426 if revs and not other.capable(b'lookup'):
5425 if revs and not other.capable(b'lookup'):
5427 err = _(
5426 err = _(
5428 b"other repository doesn't support revision lookup, "
5427 b"other repository doesn't support revision lookup, "
5429 b"so a rev cannot be specified."
5428 b"so a rev cannot be specified."
5430 )
5429 )
5431 raise error.Abort(err)
5430 raise error.Abort(err)
5432 with other.commandexecutor() as e:
5431 with other.commandexecutor() as e:
5433 fremotebookmarks = e.callcommand(
5432 fremotebookmarks = e.callcommand(
5434 b'listkeys', {b'namespace': b'bookmarks'}
5433 b'listkeys', {b'namespace': b'bookmarks'}
5435 )
5434 )
5436 for r in revs:
5435 for r in revs:
5437 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5436 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5438 remotebookmarks = fremotebookmarks.result()
5437 remotebookmarks = fremotebookmarks.result()
5439 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5438 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5440 pullopargs[b'remotebookmarks'] = remotebookmarks
5439 pullopargs[b'remotebookmarks'] = remotebookmarks
5441 for b in opts.get(b'bookmark', []):
5440 for b in opts.get(b'bookmark', []):
5442 b = repo._bookmarks.expandname(b)
5441 b = repo._bookmarks.expandname(b)
5443 if b not in remotebookmarks:
5442 if b not in remotebookmarks:
5444 raise error.Abort(_(b'remote bookmark %s not found!') % b)
5443 raise error.Abort(_(b'remote bookmark %s not found!') % b)
5445 nodes.append(remotebookmarks[b])
5444 nodes.append(remotebookmarks[b])
5446 for i, rev in enumerate(revs):
5445 for i, rev in enumerate(revs):
5447 node = fnodes[i].result()
5446 node = fnodes[i].result()
5448 nodes.append(node)
5447 nodes.append(node)
5449 if rev == checkout:
5448 if rev == checkout:
5450 checkout = node
5449 checkout = node
5451
5450
5452 wlock = util.nullcontextmanager()
5451 wlock = util.nullcontextmanager()
5453 if opts.get(b'update'):
5452 if opts.get(b'update'):
5454 wlock = repo.wlock()
5453 wlock = repo.wlock()
5455 with wlock:
5454 with wlock:
5456 pullopargs.update(opts.get(b'opargs', {}))
5455 pullopargs.update(opts.get(b'opargs', {}))
5457 modheads = exchange.pull(
5456 modheads = exchange.pull(
5458 repo,
5457 repo,
5459 other,
5458 other,
5460 heads=nodes,
5459 heads=nodes,
5461 force=opts.get(b'force'),
5460 force=opts.get(b'force'),
5462 bookmarks=opts.get(b'bookmark', ()),
5461 bookmarks=opts.get(b'bookmark', ()),
5463 opargs=pullopargs,
5462 opargs=pullopargs,
5464 confirm=opts.get(b'confirm'),
5463 confirm=opts.get(b'confirm'),
5465 ).cgresult
5464 ).cgresult
5466
5465
5467 # brev is a name, which might be a bookmark to be activated at
5466 # brev is a name, which might be a bookmark to be activated at
5468 # the end of the update. In other words, it is an explicit
5467 # the end of the update. In other words, it is an explicit
5469 # destination of the update
5468 # destination of the update
5470 brev = None
5469 brev = None
5471
5470
5472 if checkout:
5471 if checkout:
5473 checkout = repo.unfiltered().changelog.rev(checkout)
5472 checkout = repo.unfiltered().changelog.rev(checkout)
5474
5473
5475 # order below depends on implementation of
5474 # order below depends on implementation of
5476 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5475 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5477 # because 'checkout' is determined without it.
5476 # because 'checkout' is determined without it.
5478 if opts.get(b'rev'):
5477 if opts.get(b'rev'):
5479 brev = opts[b'rev'][0]
5478 brev = opts[b'rev'][0]
5480 elif opts.get(b'branch'):
5479 elif opts.get(b'branch'):
5481 brev = opts[b'branch'][0]
5480 brev = opts[b'branch'][0]
5482 else:
5481 else:
5483 brev = branches[0]
5482 brev = branches[0]
5484 repo._subtoppath = source
5483 repo._subtoppath = source
5485 try:
5484 try:
5486 ret = postincoming(
5485 ret = postincoming(
5487 ui, repo, modheads, opts.get(b'update'), checkout, brev
5486 ui, repo, modheads, opts.get(b'update'), checkout, brev
5488 )
5487 )
5489 except error.FilteredRepoLookupError as exc:
5488 except error.FilteredRepoLookupError as exc:
5490 msg = _(b'cannot update to target: %s') % exc.args[0]
5489 msg = _(b'cannot update to target: %s') % exc.args[0]
5491 exc.args = (msg,) + exc.args[1:]
5490 exc.args = (msg,) + exc.args[1:]
5492 raise
5491 raise
5493 finally:
5492 finally:
5494 del repo._subtoppath
5493 del repo._subtoppath
5495
5494
5496 finally:
5495 finally:
5497 other.close()
5496 other.close()
5498 return ret
5497 return ret
5499
5498
5500
5499
5501 @command(
5500 @command(
5502 b'push',
5501 b'push',
5503 [
5502 [
5504 (b'f', b'force', None, _(b'force push')),
5503 (b'f', b'force', None, _(b'force push')),
5505 (
5504 (
5506 b'r',
5505 b'r',
5507 b'rev',
5506 b'rev',
5508 [],
5507 [],
5509 _(b'a changeset intended to be included in the destination'),
5508 _(b'a changeset intended to be included in the destination'),
5510 _(b'REV'),
5509 _(b'REV'),
5511 ),
5510 ),
5512 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5511 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5513 (
5512 (
5514 b'b',
5513 b'b',
5515 b'branch',
5514 b'branch',
5516 [],
5515 [],
5517 _(b'a specific branch you would like to push'),
5516 _(b'a specific branch you would like to push'),
5518 _(b'BRANCH'),
5517 _(b'BRANCH'),
5519 ),
5518 ),
5520 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5519 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5521 (
5520 (
5522 b'',
5521 b'',
5523 b'pushvars',
5522 b'pushvars',
5524 [],
5523 [],
5525 _(b'variables that can be sent to server (ADVANCED)'),
5524 _(b'variables that can be sent to server (ADVANCED)'),
5526 ),
5525 ),
5527 (
5526 (
5528 b'',
5527 b'',
5529 b'publish',
5528 b'publish',
5530 False,
5529 False,
5531 _(b'push the changeset as public (EXPERIMENTAL)'),
5530 _(b'push the changeset as public (EXPERIMENTAL)'),
5532 ),
5531 ),
5533 ]
5532 ]
5534 + remoteopts,
5533 + remoteopts,
5535 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
5534 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
5536 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5535 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5537 helpbasic=True,
5536 helpbasic=True,
5538 )
5537 )
5539 def push(ui, repo, dest=None, **opts):
5538 def push(ui, repo, dest=None, **opts):
5540 """push changes to the specified destination
5539 """push changes to the specified destination
5541
5540
5542 Push changesets from the local repository to the specified
5541 Push changesets from the local repository to the specified
5543 destination.
5542 destination.
5544
5543
5545 This operation is symmetrical to pull: it is identical to a pull
5544 This operation is symmetrical to pull: it is identical to a pull
5546 in the destination repository from the current one.
5545 in the destination repository from the current one.
5547
5546
5548 By default, push will not allow creation of new heads at the
5547 By default, push will not allow creation of new heads at the
5549 destination, since multiple heads would make it unclear which head
5548 destination, since multiple heads would make it unclear which head
5550 to use. In this situation, it is recommended to pull and merge
5549 to use. In this situation, it is recommended to pull and merge
5551 before pushing.
5550 before pushing.
5552
5551
5553 Use --new-branch if you want to allow push to create a new named
5552 Use --new-branch if you want to allow push to create a new named
5554 branch that is not present at the destination. This allows you to
5553 branch that is not present at the destination. This allows you to
5555 only create a new branch without forcing other changes.
5554 only create a new branch without forcing other changes.
5556
5555
5557 .. note::
5556 .. note::
5558
5557
5559 Extra care should be taken with the -f/--force option,
5558 Extra care should be taken with the -f/--force option,
5560 which will push all new heads on all branches, an action which will
5559 which will push all new heads on all branches, an action which will
5561 almost always cause confusion for collaborators.
5560 almost always cause confusion for collaborators.
5562
5561
5563 If -r/--rev is used, the specified revision and all its ancestors
5562 If -r/--rev is used, the specified revision and all its ancestors
5564 will be pushed to the remote repository.
5563 will be pushed to the remote repository.
5565
5564
5566 If -B/--bookmark is used, the specified bookmarked revision, its
5565 If -B/--bookmark is used, the specified bookmarked revision, its
5567 ancestors, and the bookmark will be pushed to the remote
5566 ancestors, and the bookmark will be pushed to the remote
5568 repository. Specifying ``.`` is equivalent to specifying the active
5567 repository. Specifying ``.`` is equivalent to specifying the active
5569 bookmark's name.
5568 bookmark's name.
5570
5569
5571 Please see :hg:`help urls` for important details about ``ssh://``
5570 Please see :hg:`help urls` for important details about ``ssh://``
5572 URLs. If DESTINATION is omitted, a default path will be used.
5571 URLs. If DESTINATION is omitted, a default path will be used.
5573
5572
5574 .. container:: verbose
5573 .. container:: verbose
5575
5574
5576 The --pushvars option sends strings to the server that become
5575 The --pushvars option sends strings to the server that become
5577 environment variables prepended with ``HG_USERVAR_``. For example,
5576 environment variables prepended with ``HG_USERVAR_``. For example,
5578 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5577 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5579 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5578 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5580
5579
5581 pushvars can provide for user-overridable hooks as well as set debug
5580 pushvars can provide for user-overridable hooks as well as set debug
5582 levels. One example is having a hook that blocks commits containing
5581 levels. One example is having a hook that blocks commits containing
5583 conflict markers, but enables the user to override the hook if the file
5582 conflict markers, but enables the user to override the hook if the file
5584 is using conflict markers for testing purposes or the file format has
5583 is using conflict markers for testing purposes or the file format has
5585 strings that look like conflict markers.
5584 strings that look like conflict markers.
5586
5585
5587 By default, servers will ignore `--pushvars`. To enable it add the
5586 By default, servers will ignore `--pushvars`. To enable it add the
5588 following to your configuration file::
5587 following to your configuration file::
5589
5588
5590 [push]
5589 [push]
5591 pushvars.server = true
5590 pushvars.server = true
5592
5591
5593 Returns 0 if push was successful, 1 if nothing to push.
5592 Returns 0 if push was successful, 1 if nothing to push.
5594 """
5593 """
5595
5594
5596 opts = pycompat.byteskwargs(opts)
5595 opts = pycompat.byteskwargs(opts)
5597 if opts.get(b'bookmark'):
5596 if opts.get(b'bookmark'):
5598 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5597 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5599 for b in opts[b'bookmark']:
5598 for b in opts[b'bookmark']:
5600 # translate -B options to -r so changesets get pushed
5599 # translate -B options to -r so changesets get pushed
5601 b = repo._bookmarks.expandname(b)
5600 b = repo._bookmarks.expandname(b)
5602 if b in repo._bookmarks:
5601 if b in repo._bookmarks:
5603 opts.setdefault(b'rev', []).append(b)
5602 opts.setdefault(b'rev', []).append(b)
5604 else:
5603 else:
5605 # if we try to push a deleted bookmark, translate it to null
5604 # if we try to push a deleted bookmark, translate it to null
5606 # this lets simultaneous -r, -b options continue working
5605 # this lets simultaneous -r, -b options continue working
5607 opts.setdefault(b'rev', []).append(b"null")
5606 opts.setdefault(b'rev', []).append(b"null")
5608
5607
5609 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5608 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5610 if not path:
5609 if not path:
5611 raise error.Abort(
5610 raise error.Abort(
5612 _(b'default repository not configured!'),
5611 _(b'default repository not configured!'),
5613 hint=_(b"see 'hg help config.paths'"),
5612 hint=_(b"see 'hg help config.paths'"),
5614 )
5613 )
5615 dest = path.pushloc or path.loc
5614 dest = path.pushloc or path.loc
5616 branches = (path.branch, opts.get(b'branch') or [])
5615 branches = (path.branch, opts.get(b'branch') or [])
5617 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5616 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5618 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
5617 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
5619 other = hg.peer(repo, opts, dest)
5618 other = hg.peer(repo, opts, dest)
5620
5619
5621 if revs:
5620 if revs:
5622 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5621 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5623 if not revs:
5622 if not revs:
5624 raise error.Abort(
5623 raise error.Abort(
5625 _(b"specified revisions evaluate to an empty set"),
5624 _(b"specified revisions evaluate to an empty set"),
5626 hint=_(b"use different revision arguments"),
5625 hint=_(b"use different revision arguments"),
5627 )
5626 )
5628 elif path.pushrev:
5627 elif path.pushrev:
5629 # It doesn't make any sense to specify ancestor revisions. So limit
5628 # It doesn't make any sense to specify ancestor revisions. So limit
5630 # to DAG heads to make discovery simpler.
5629 # to DAG heads to make discovery simpler.
5631 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5630 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5632 revs = scmutil.revrange(repo, [expr])
5631 revs = scmutil.revrange(repo, [expr])
5633 revs = [repo[rev].node() for rev in revs]
5632 revs = [repo[rev].node() for rev in revs]
5634 if not revs:
5633 if not revs:
5635 raise error.Abort(
5634 raise error.Abort(
5636 _(b'default push revset for path evaluates to an empty set')
5635 _(b'default push revset for path evaluates to an empty set')
5637 )
5636 )
5638 elif ui.configbool(b'commands', b'push.require-revs'):
5637 elif ui.configbool(b'commands', b'push.require-revs'):
5639 raise error.Abort(
5638 raise error.Abort(
5640 _(b'no revisions specified to push'),
5639 _(b'no revisions specified to push'),
5641 hint=_(b'did you mean "hg push -r ."?'),
5640 hint=_(b'did you mean "hg push -r ."?'),
5642 )
5641 )
5643
5642
5644 repo._subtoppath = dest
5643 repo._subtoppath = dest
5645 try:
5644 try:
5646 # push subrepos depth-first for coherent ordering
5645 # push subrepos depth-first for coherent ordering
5647 c = repo[b'.']
5646 c = repo[b'.']
5648 subs = c.substate # only repos that are committed
5647 subs = c.substate # only repos that are committed
5649 for s in sorted(subs):
5648 for s in sorted(subs):
5650 result = c.sub(s).push(opts)
5649 result = c.sub(s).push(opts)
5651 if result == 0:
5650 if result == 0:
5652 return not result
5651 return not result
5653 finally:
5652 finally:
5654 del repo._subtoppath
5653 del repo._subtoppath
5655
5654
5656 opargs = dict(opts.get(b'opargs', {})) # copy opargs since we may mutate it
5655 opargs = dict(opts.get(b'opargs', {})) # copy opargs since we may mutate it
5657 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5656 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5658
5657
5659 pushop = exchange.push(
5658 pushop = exchange.push(
5660 repo,
5659 repo,
5661 other,
5660 other,
5662 opts.get(b'force'),
5661 opts.get(b'force'),
5663 revs=revs,
5662 revs=revs,
5664 newbranch=opts.get(b'new_branch'),
5663 newbranch=opts.get(b'new_branch'),
5665 bookmarks=opts.get(b'bookmark', ()),
5664 bookmarks=opts.get(b'bookmark', ()),
5666 publish=opts.get(b'publish'),
5665 publish=opts.get(b'publish'),
5667 opargs=opargs,
5666 opargs=opargs,
5668 )
5667 )
5669
5668
5670 result = not pushop.cgresult
5669 result = not pushop.cgresult
5671
5670
5672 if pushop.bkresult is not None:
5671 if pushop.bkresult is not None:
5673 if pushop.bkresult == 2:
5672 if pushop.bkresult == 2:
5674 result = 2
5673 result = 2
5675 elif not result and pushop.bkresult:
5674 elif not result and pushop.bkresult:
5676 result = 2
5675 result = 2
5677
5676
5678 return result
5677 return result
5679
5678
5680
5679
5681 @command(
5680 @command(
5682 b'recover',
5681 b'recover',
5683 [(b'', b'verify', False, b"run `hg verify` after successful recover"),],
5682 [(b'', b'verify', False, b"run `hg verify` after successful recover"),],
5684 helpcategory=command.CATEGORY_MAINTENANCE,
5683 helpcategory=command.CATEGORY_MAINTENANCE,
5685 )
5684 )
5686 def recover(ui, repo, **opts):
5685 def recover(ui, repo, **opts):
5687 """roll back an interrupted transaction
5686 """roll back an interrupted transaction
5688
5687
5689 Recover from an interrupted commit or pull.
5688 Recover from an interrupted commit or pull.
5690
5689
5691 This command tries to fix the repository status after an
5690 This command tries to fix the repository status after an
5692 interrupted operation. It should only be necessary when Mercurial
5691 interrupted operation. It should only be necessary when Mercurial
5693 suggests it.
5692 suggests it.
5694
5693
5695 Returns 0 if successful, 1 if nothing to recover or verify fails.
5694 Returns 0 if successful, 1 if nothing to recover or verify fails.
5696 """
5695 """
5697 ret = repo.recover()
5696 ret = repo.recover()
5698 if ret:
5697 if ret:
5699 if opts['verify']:
5698 if opts['verify']:
5700 return hg.verify(repo)
5699 return hg.verify(repo)
5701 else:
5700 else:
5702 msg = _(
5701 msg = _(
5703 b"(verify step skipped, run `hg verify` to check your "
5702 b"(verify step skipped, run `hg verify` to check your "
5704 b"repository content)\n"
5703 b"repository content)\n"
5705 )
5704 )
5706 ui.warn(msg)
5705 ui.warn(msg)
5707 return 0
5706 return 0
5708 return 1
5707 return 1
5709
5708
5710
5709
5711 @command(
5710 @command(
5712 b'remove|rm',
5711 b'remove|rm',
5713 [
5712 [
5714 (b'A', b'after', None, _(b'record delete for missing files')),
5713 (b'A', b'after', None, _(b'record delete for missing files')),
5715 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5714 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5716 ]
5715 ]
5717 + subrepoopts
5716 + subrepoopts
5718 + walkopts
5717 + walkopts
5719 + dryrunopts,
5718 + dryrunopts,
5720 _(b'[OPTION]... FILE...'),
5719 _(b'[OPTION]... FILE...'),
5721 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5720 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5722 helpbasic=True,
5721 helpbasic=True,
5723 inferrepo=True,
5722 inferrepo=True,
5724 )
5723 )
5725 def remove(ui, repo, *pats, **opts):
5724 def remove(ui, repo, *pats, **opts):
5726 """remove the specified files on the next commit
5725 """remove the specified files on the next commit
5727
5726
5728 Schedule the indicated files for removal from the current branch.
5727 Schedule the indicated files for removal from the current branch.
5729
5728
5730 This command schedules the files to be removed at the next commit.
5729 This command schedules the files to be removed at the next commit.
5731 To undo a remove before that, see :hg:`revert`. To undo added
5730 To undo a remove before that, see :hg:`revert`. To undo added
5732 files, see :hg:`forget`.
5731 files, see :hg:`forget`.
5733
5732
5734 .. container:: verbose
5733 .. container:: verbose
5735
5734
5736 -A/--after can be used to remove only files that have already
5735 -A/--after can be used to remove only files that have already
5737 been deleted, -f/--force can be used to force deletion, and -Af
5736 been deleted, -f/--force can be used to force deletion, and -Af
5738 can be used to remove files from the next revision without
5737 can be used to remove files from the next revision without
5739 deleting them from the working directory.
5738 deleting them from the working directory.
5740
5739
5741 The following table details the behavior of remove for different
5740 The following table details the behavior of remove for different
5742 file states (columns) and option combinations (rows). The file
5741 file states (columns) and option combinations (rows). The file
5743 states are Added [A], Clean [C], Modified [M] and Missing [!]
5742 states are Added [A], Clean [C], Modified [M] and Missing [!]
5744 (as reported by :hg:`status`). The actions are Warn, Remove
5743 (as reported by :hg:`status`). The actions are Warn, Remove
5745 (from branch) and Delete (from disk):
5744 (from branch) and Delete (from disk):
5746
5745
5747 ========= == == == ==
5746 ========= == == == ==
5748 opt/state A C M !
5747 opt/state A C M !
5749 ========= == == == ==
5748 ========= == == == ==
5750 none W RD W R
5749 none W RD W R
5751 -f R RD RD R
5750 -f R RD RD R
5752 -A W W W R
5751 -A W W W R
5753 -Af R R R R
5752 -Af R R R R
5754 ========= == == == ==
5753 ========= == == == ==
5755
5754
5756 .. note::
5755 .. note::
5757
5756
5758 :hg:`remove` never deletes files in Added [A] state from the
5757 :hg:`remove` never deletes files in Added [A] state from the
5759 working directory, not even if ``--force`` is specified.
5758 working directory, not even if ``--force`` is specified.
5760
5759
5761 Returns 0 on success, 1 if any warnings encountered.
5760 Returns 0 on success, 1 if any warnings encountered.
5762 """
5761 """
5763
5762
5764 opts = pycompat.byteskwargs(opts)
5763 opts = pycompat.byteskwargs(opts)
5765 after, force = opts.get(b'after'), opts.get(b'force')
5764 after, force = opts.get(b'after'), opts.get(b'force')
5766 dryrun = opts.get(b'dry_run')
5765 dryrun = opts.get(b'dry_run')
5767 if not pats and not after:
5766 if not pats and not after:
5768 raise error.Abort(_(b'no files specified'))
5767 raise error.Abort(_(b'no files specified'))
5769
5768
5770 m = scmutil.match(repo[None], pats, opts)
5769 m = scmutil.match(repo[None], pats, opts)
5771 subrepos = opts.get(b'subrepos')
5770 subrepos = opts.get(b'subrepos')
5772 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5771 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5773 return cmdutil.remove(
5772 return cmdutil.remove(
5774 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5773 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5775 )
5774 )
5776
5775
5777
5776
5778 @command(
5777 @command(
5779 b'rename|move|mv',
5778 b'rename|move|mv',
5780 [
5779 [
5781 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5780 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5782 (
5781 (
5783 b'f',
5782 b'f',
5784 b'force',
5783 b'force',
5785 None,
5784 None,
5786 _(b'forcibly move over an existing managed file'),
5785 _(b'forcibly move over an existing managed file'),
5787 ),
5786 ),
5788 ]
5787 ]
5789 + walkopts
5788 + walkopts
5790 + dryrunopts,
5789 + dryrunopts,
5791 _(b'[OPTION]... SOURCE... DEST'),
5790 _(b'[OPTION]... SOURCE... DEST'),
5792 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5791 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5793 )
5792 )
5794 def rename(ui, repo, *pats, **opts):
5793 def rename(ui, repo, *pats, **opts):
5795 """rename files; equivalent of copy + remove
5794 """rename files; equivalent of copy + remove
5796
5795
5797 Mark dest as copies of sources; mark sources for deletion. If dest
5796 Mark dest as copies of sources; mark sources for deletion. If dest
5798 is a directory, copies are put in that directory. If dest is a
5797 is a directory, copies are put in that directory. If dest is a
5799 file, there can only be one source.
5798 file, there can only be one source.
5800
5799
5801 By default, this command copies the contents of files as they
5800 By default, this command copies the contents of files as they
5802 exist in the working directory. If invoked with -A/--after, the
5801 exist in the working directory. If invoked with -A/--after, the
5803 operation is recorded, but no copying is performed.
5802 operation is recorded, but no copying is performed.
5804
5803
5805 This command takes effect at the next commit. To undo a rename
5804 This command takes effect at the next commit. To undo a rename
5806 before that, see :hg:`revert`.
5805 before that, see :hg:`revert`.
5807
5806
5808 Returns 0 on success, 1 if errors are encountered.
5807 Returns 0 on success, 1 if errors are encountered.
5809 """
5808 """
5810 opts = pycompat.byteskwargs(opts)
5809 opts = pycompat.byteskwargs(opts)
5811 with repo.wlock(False):
5810 with repo.wlock(False):
5812 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5811 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5813
5812
5814
5813
5815 @command(
5814 @command(
5816 b'resolve',
5815 b'resolve',
5817 [
5816 [
5818 (b'a', b'all', None, _(b'select all unresolved files')),
5817 (b'a', b'all', None, _(b'select all unresolved files')),
5819 (b'l', b'list', None, _(b'list state of files needing merge')),
5818 (b'l', b'list', None, _(b'list state of files needing merge')),
5820 (b'm', b'mark', None, _(b'mark files as resolved')),
5819 (b'm', b'mark', None, _(b'mark files as resolved')),
5821 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5820 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5822 (b'n', b'no-status', None, _(b'hide status prefix')),
5821 (b'n', b'no-status', None, _(b'hide status prefix')),
5823 (b'', b're-merge', None, _(b're-merge files')),
5822 (b'', b're-merge', None, _(b're-merge files')),
5824 ]
5823 ]
5825 + mergetoolopts
5824 + mergetoolopts
5826 + walkopts
5825 + walkopts
5827 + formatteropts,
5826 + formatteropts,
5828 _(b'[OPTION]... [FILE]...'),
5827 _(b'[OPTION]... [FILE]...'),
5829 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5828 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5830 inferrepo=True,
5829 inferrepo=True,
5831 )
5830 )
5832 def resolve(ui, repo, *pats, **opts):
5831 def resolve(ui, repo, *pats, **opts):
5833 """redo merges or set/view the merge status of files
5832 """redo merges or set/view the merge status of files
5834
5833
5835 Merges with unresolved conflicts are often the result of
5834 Merges with unresolved conflicts are often the result of
5836 non-interactive merging using the ``internal:merge`` configuration
5835 non-interactive merging using the ``internal:merge`` configuration
5837 setting, or a command-line merge tool like ``diff3``. The resolve
5836 setting, or a command-line merge tool like ``diff3``. The resolve
5838 command is used to manage the files involved in a merge, after
5837 command is used to manage the files involved in a merge, after
5839 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5838 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5840 working directory must have two parents). See :hg:`help
5839 working directory must have two parents). See :hg:`help
5841 merge-tools` for information on configuring merge tools.
5840 merge-tools` for information on configuring merge tools.
5842
5841
5843 The resolve command can be used in the following ways:
5842 The resolve command can be used in the following ways:
5844
5843
5845 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5844 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5846 the specified files, discarding any previous merge attempts. Re-merging
5845 the specified files, discarding any previous merge attempts. Re-merging
5847 is not performed for files already marked as resolved. Use ``--all/-a``
5846 is not performed for files already marked as resolved. Use ``--all/-a``
5848 to select all unresolved files. ``--tool`` can be used to specify
5847 to select all unresolved files. ``--tool`` can be used to specify
5849 the merge tool used for the given files. It overrides the HGMERGE
5848 the merge tool used for the given files. It overrides the HGMERGE
5850 environment variable and your configuration files. Previous file
5849 environment variable and your configuration files. Previous file
5851 contents are saved with a ``.orig`` suffix.
5850 contents are saved with a ``.orig`` suffix.
5852
5851
5853 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5852 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5854 (e.g. after having manually fixed-up the files). The default is
5853 (e.g. after having manually fixed-up the files). The default is
5855 to mark all unresolved files.
5854 to mark all unresolved files.
5856
5855
5857 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5856 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5858 default is to mark all resolved files.
5857 default is to mark all resolved files.
5859
5858
5860 - :hg:`resolve -l`: list files which had or still have conflicts.
5859 - :hg:`resolve -l`: list files which had or still have conflicts.
5861 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5860 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5862 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5861 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5863 the list. See :hg:`help filesets` for details.
5862 the list. See :hg:`help filesets` for details.
5864
5863
5865 .. note::
5864 .. note::
5866
5865
5867 Mercurial will not let you commit files with unresolved merge
5866 Mercurial will not let you commit files with unresolved merge
5868 conflicts. You must use :hg:`resolve -m ...` before you can
5867 conflicts. You must use :hg:`resolve -m ...` before you can
5869 commit after a conflicting merge.
5868 commit after a conflicting merge.
5870
5869
5871 .. container:: verbose
5870 .. container:: verbose
5872
5871
5873 Template:
5872 Template:
5874
5873
5875 The following keywords are supported in addition to the common template
5874 The following keywords are supported in addition to the common template
5876 keywords and functions. See also :hg:`help templates`.
5875 keywords and functions. See also :hg:`help templates`.
5877
5876
5878 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
5877 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
5879 :path: String. Repository-absolute path of the file.
5878 :path: String. Repository-absolute path of the file.
5880
5879
5881 Returns 0 on success, 1 if any files fail a resolve attempt.
5880 Returns 0 on success, 1 if any files fail a resolve attempt.
5882 """
5881 """
5883
5882
5884 opts = pycompat.byteskwargs(opts)
5883 opts = pycompat.byteskwargs(opts)
5885 confirm = ui.configbool(b'commands', b'resolve.confirm')
5884 confirm = ui.configbool(b'commands', b'resolve.confirm')
5886 flaglist = b'all mark unmark list no_status re_merge'.split()
5885 flaglist = b'all mark unmark list no_status re_merge'.split()
5887 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
5886 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
5888
5887
5889 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
5888 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
5890 if actioncount > 1:
5889 if actioncount > 1:
5891 raise error.Abort(_(b"too many actions specified"))
5890 raise error.Abort(_(b"too many actions specified"))
5892 elif actioncount == 0 and ui.configbool(
5891 elif actioncount == 0 and ui.configbool(
5893 b'commands', b'resolve.explicit-re-merge'
5892 b'commands', b'resolve.explicit-re-merge'
5894 ):
5893 ):
5895 hint = _(b'use --mark, --unmark, --list or --re-merge')
5894 hint = _(b'use --mark, --unmark, --list or --re-merge')
5896 raise error.Abort(_(b'no action specified'), hint=hint)
5895 raise error.Abort(_(b'no action specified'), hint=hint)
5897 if pats and all:
5896 if pats and all:
5898 raise error.Abort(_(b"can't specify --all and patterns"))
5897 raise error.Abort(_(b"can't specify --all and patterns"))
5899 if not (all or pats or show or mark or unmark):
5898 if not (all or pats or show or mark or unmark):
5900 raise error.Abort(
5899 raise error.Abort(
5901 _(b'no files or directories specified'),
5900 _(b'no files or directories specified'),
5902 hint=b'use --all to re-merge all unresolved files',
5901 hint=b'use --all to re-merge all unresolved files',
5903 )
5902 )
5904
5903
5905 if confirm:
5904 if confirm:
5906 if all:
5905 if all:
5907 if ui.promptchoice(
5906 if ui.promptchoice(
5908 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
5907 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
5909 ):
5908 ):
5910 raise error.Abort(_(b'user quit'))
5909 raise error.Abort(_(b'user quit'))
5911 if mark and not pats:
5910 if mark and not pats:
5912 if ui.promptchoice(
5911 if ui.promptchoice(
5913 _(
5912 _(
5914 b'mark all unresolved files as resolved (yn)?'
5913 b'mark all unresolved files as resolved (yn)?'
5915 b'$$ &Yes $$ &No'
5914 b'$$ &Yes $$ &No'
5916 )
5915 )
5917 ):
5916 ):
5918 raise error.Abort(_(b'user quit'))
5917 raise error.Abort(_(b'user quit'))
5919 if unmark and not pats:
5918 if unmark and not pats:
5920 if ui.promptchoice(
5919 if ui.promptchoice(
5921 _(
5920 _(
5922 b'mark all resolved files as unresolved (yn)?'
5921 b'mark all resolved files as unresolved (yn)?'
5923 b'$$ &Yes $$ &No'
5922 b'$$ &Yes $$ &No'
5924 )
5923 )
5925 ):
5924 ):
5926 raise error.Abort(_(b'user quit'))
5925 raise error.Abort(_(b'user quit'))
5927
5926
5928 uipathfn = scmutil.getuipathfn(repo)
5927 uipathfn = scmutil.getuipathfn(repo)
5929
5928
5930 if show:
5929 if show:
5931 ui.pager(b'resolve')
5930 ui.pager(b'resolve')
5932 fm = ui.formatter(b'resolve', opts)
5931 fm = ui.formatter(b'resolve', opts)
5933 ms = mergemod.mergestate.read(repo)
5932 ms = mergemod.mergestate.read(repo)
5934 wctx = repo[None]
5933 wctx = repo[None]
5935 m = scmutil.match(wctx, pats, opts)
5934 m = scmutil.match(wctx, pats, opts)
5936
5935
5937 # Labels and keys based on merge state. Unresolved path conflicts show
5936 # Labels and keys based on merge state. Unresolved path conflicts show
5938 # as 'P'. Resolved path conflicts show as 'R', the same as normal
5937 # as 'P'. Resolved path conflicts show as 'R', the same as normal
5939 # resolved conflicts.
5938 # resolved conflicts.
5940 mergestateinfo = {
5939 mergestateinfo = {
5941 mergemod.MERGE_RECORD_UNRESOLVED: (b'resolve.unresolved', b'U'),
5940 mergemod.MERGE_RECORD_UNRESOLVED: (b'resolve.unresolved', b'U'),
5942 mergemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
5941 mergemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
5943 mergemod.MERGE_RECORD_UNRESOLVED_PATH: (
5942 mergemod.MERGE_RECORD_UNRESOLVED_PATH: (
5944 b'resolve.unresolved',
5943 b'resolve.unresolved',
5945 b'P',
5944 b'P',
5946 ),
5945 ),
5947 mergemod.MERGE_RECORD_RESOLVED_PATH: (b'resolve.resolved', b'R'),
5946 mergemod.MERGE_RECORD_RESOLVED_PATH: (b'resolve.resolved', b'R'),
5948 mergemod.MERGE_RECORD_DRIVER_RESOLVED: (
5947 mergemod.MERGE_RECORD_DRIVER_RESOLVED: (
5949 b'resolve.driverresolved',
5948 b'resolve.driverresolved',
5950 b'D',
5949 b'D',
5951 ),
5950 ),
5952 }
5951 }
5953
5952
5954 for f in ms:
5953 for f in ms:
5955 if not m(f):
5954 if not m(f):
5956 continue
5955 continue
5957
5956
5958 if ms[f] == mergemod.MERGE_RECORD_MERGED_OTHER:
5957 if ms[f] == mergemod.MERGE_RECORD_MERGED_OTHER:
5959 continue
5958 continue
5960 label, key = mergestateinfo[ms[f]]
5959 label, key = mergestateinfo[ms[f]]
5961 fm.startitem()
5960 fm.startitem()
5962 fm.context(ctx=wctx)
5961 fm.context(ctx=wctx)
5963 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
5962 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
5964 fm.data(path=f)
5963 fm.data(path=f)
5965 fm.plain(b'%s\n' % uipathfn(f), label=label)
5964 fm.plain(b'%s\n' % uipathfn(f), label=label)
5966 fm.end()
5965 fm.end()
5967 return 0
5966 return 0
5968
5967
5969 with repo.wlock():
5968 with repo.wlock():
5970 ms = mergemod.mergestate.read(repo)
5969 ms = mergemod.mergestate.read(repo)
5971
5970
5972 if not (ms.active() or repo.dirstate.p2() != nullid):
5971 if not (ms.active() or repo.dirstate.p2() != nullid):
5973 raise error.Abort(
5972 raise error.Abort(
5974 _(b'resolve command not applicable when not merging')
5973 _(b'resolve command not applicable when not merging')
5975 )
5974 )
5976
5975
5977 wctx = repo[None]
5976 wctx = repo[None]
5978
5977
5979 if (
5978 if (
5980 ms.mergedriver
5979 ms.mergedriver
5981 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED
5980 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED
5982 ):
5981 ):
5983 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5982 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5984 ms.commit()
5983 ms.commit()
5985 # allow mark and unmark to go through
5984 # allow mark and unmark to go through
5986 if not mark and not unmark and not proceed:
5985 if not mark and not unmark and not proceed:
5987 return 1
5986 return 1
5988
5987
5989 m = scmutil.match(wctx, pats, opts)
5988 m = scmutil.match(wctx, pats, opts)
5990 ret = 0
5989 ret = 0
5991 didwork = False
5990 didwork = False
5992 runconclude = False
5991 runconclude = False
5993
5992
5994 tocomplete = []
5993 tocomplete = []
5995 hasconflictmarkers = []
5994 hasconflictmarkers = []
5996 if mark:
5995 if mark:
5997 markcheck = ui.config(b'commands', b'resolve.mark-check')
5996 markcheck = ui.config(b'commands', b'resolve.mark-check')
5998 if markcheck not in [b'warn', b'abort']:
5997 if markcheck not in [b'warn', b'abort']:
5999 # Treat all invalid / unrecognized values as 'none'.
5998 # Treat all invalid / unrecognized values as 'none'.
6000 markcheck = False
5999 markcheck = False
6001 for f in ms:
6000 for f in ms:
6002 if not m(f):
6001 if not m(f):
6003 continue
6002 continue
6004
6003
6005 didwork = True
6004 didwork = True
6006
6005
6007 if ms[f] == mergemod.MERGE_RECORD_MERGED_OTHER:
6006 if ms[f] == mergemod.MERGE_RECORD_MERGED_OTHER:
6008 continue
6007 continue
6009
6008
6010 # don't let driver-resolved files be marked, and run the conclude
6009 # don't let driver-resolved files be marked, and run the conclude
6011 # step if asked to resolve
6010 # step if asked to resolve
6012 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
6011 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
6013 exact = m.exact(f)
6012 exact = m.exact(f)
6014 if mark:
6013 if mark:
6015 if exact:
6014 if exact:
6016 ui.warn(
6015 ui.warn(
6017 _(b'not marking %s as it is driver-resolved\n')
6016 _(b'not marking %s as it is driver-resolved\n')
6018 % uipathfn(f)
6017 % uipathfn(f)
6019 )
6018 )
6020 elif unmark:
6019 elif unmark:
6021 if exact:
6020 if exact:
6022 ui.warn(
6021 ui.warn(
6023 _(b'not unmarking %s as it is driver-resolved\n')
6022 _(b'not unmarking %s as it is driver-resolved\n')
6024 % uipathfn(f)
6023 % uipathfn(f)
6025 )
6024 )
6026 else:
6025 else:
6027 runconclude = True
6026 runconclude = True
6028 continue
6027 continue
6029
6028
6030 # path conflicts must be resolved manually
6029 # path conflicts must be resolved manually
6031 if ms[f] in (
6030 if ms[f] in (
6032 mergemod.MERGE_RECORD_UNRESOLVED_PATH,
6031 mergemod.MERGE_RECORD_UNRESOLVED_PATH,
6033 mergemod.MERGE_RECORD_RESOLVED_PATH,
6032 mergemod.MERGE_RECORD_RESOLVED_PATH,
6034 ):
6033 ):
6035 if mark:
6034 if mark:
6036 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
6035 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
6037 elif unmark:
6036 elif unmark:
6038 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
6037 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
6039 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
6038 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
6040 ui.warn(
6039 ui.warn(
6041 _(b'%s: path conflict must be resolved manually\n')
6040 _(b'%s: path conflict must be resolved manually\n')
6042 % uipathfn(f)
6041 % uipathfn(f)
6043 )
6042 )
6044 continue
6043 continue
6045
6044
6046 if mark:
6045 if mark:
6047 if markcheck:
6046 if markcheck:
6048 fdata = repo.wvfs.tryread(f)
6047 fdata = repo.wvfs.tryread(f)
6049 if (
6048 if (
6050 filemerge.hasconflictmarkers(fdata)
6049 filemerge.hasconflictmarkers(fdata)
6051 and ms[f] != mergemod.MERGE_RECORD_RESOLVED
6050 and ms[f] != mergemod.MERGE_RECORD_RESOLVED
6052 ):
6051 ):
6053 hasconflictmarkers.append(f)
6052 hasconflictmarkers.append(f)
6054 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
6053 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
6055 elif unmark:
6054 elif unmark:
6056 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
6055 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
6057 else:
6056 else:
6058 # backup pre-resolve (merge uses .orig for its own purposes)
6057 # backup pre-resolve (merge uses .orig for its own purposes)
6059 a = repo.wjoin(f)
6058 a = repo.wjoin(f)
6060 try:
6059 try:
6061 util.copyfile(a, a + b".resolve")
6060 util.copyfile(a, a + b".resolve")
6062 except (IOError, OSError) as inst:
6061 except (IOError, OSError) as inst:
6063 if inst.errno != errno.ENOENT:
6062 if inst.errno != errno.ENOENT:
6064 raise
6063 raise
6065
6064
6066 try:
6065 try:
6067 # preresolve file
6066 # preresolve file
6068 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6067 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6069 with ui.configoverride(overrides, b'resolve'):
6068 with ui.configoverride(overrides, b'resolve'):
6070 complete, r = ms.preresolve(f, wctx)
6069 complete, r = ms.preresolve(f, wctx)
6071 if not complete:
6070 if not complete:
6072 tocomplete.append(f)
6071 tocomplete.append(f)
6073 elif r:
6072 elif r:
6074 ret = 1
6073 ret = 1
6075 finally:
6074 finally:
6076 ms.commit()
6075 ms.commit()
6077
6076
6078 # replace filemerge's .orig file with our resolve file, but only
6077 # replace filemerge's .orig file with our resolve file, but only
6079 # for merges that are complete
6078 # for merges that are complete
6080 if complete:
6079 if complete:
6081 try:
6080 try:
6082 util.rename(
6081 util.rename(
6083 a + b".resolve", scmutil.backuppath(ui, repo, f)
6082 a + b".resolve", scmutil.backuppath(ui, repo, f)
6084 )
6083 )
6085 except OSError as inst:
6084 except OSError as inst:
6086 if inst.errno != errno.ENOENT:
6085 if inst.errno != errno.ENOENT:
6087 raise
6086 raise
6088
6087
6089 if hasconflictmarkers:
6088 if hasconflictmarkers:
6090 ui.warn(
6089 ui.warn(
6091 _(
6090 _(
6092 b'warning: the following files still have conflict '
6091 b'warning: the following files still have conflict '
6093 b'markers:\n'
6092 b'markers:\n'
6094 )
6093 )
6095 + b''.join(
6094 + b''.join(
6096 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6095 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6097 )
6096 )
6098 )
6097 )
6099 if markcheck == b'abort' and not all and not pats:
6098 if markcheck == b'abort' and not all and not pats:
6100 raise error.Abort(
6099 raise error.Abort(
6101 _(b'conflict markers detected'),
6100 _(b'conflict markers detected'),
6102 hint=_(b'use --all to mark anyway'),
6101 hint=_(b'use --all to mark anyway'),
6103 )
6102 )
6104
6103
6105 for f in tocomplete:
6104 for f in tocomplete:
6106 try:
6105 try:
6107 # resolve file
6106 # resolve file
6108 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6107 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6109 with ui.configoverride(overrides, b'resolve'):
6108 with ui.configoverride(overrides, b'resolve'):
6110 r = ms.resolve(f, wctx)
6109 r = ms.resolve(f, wctx)
6111 if r:
6110 if r:
6112 ret = 1
6111 ret = 1
6113 finally:
6112 finally:
6114 ms.commit()
6113 ms.commit()
6115
6114
6116 # replace filemerge's .orig file with our resolve file
6115 # replace filemerge's .orig file with our resolve file
6117 a = repo.wjoin(f)
6116 a = repo.wjoin(f)
6118 try:
6117 try:
6119 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
6118 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
6120 except OSError as inst:
6119 except OSError as inst:
6121 if inst.errno != errno.ENOENT:
6120 if inst.errno != errno.ENOENT:
6122 raise
6121 raise
6123
6122
6124 ms.commit()
6123 ms.commit()
6125 ms.recordactions()
6124 ms.recordactions()
6126
6125
6127 if not didwork and pats:
6126 if not didwork and pats:
6128 hint = None
6127 hint = None
6129 if not any([p for p in pats if p.find(b':') >= 0]):
6128 if not any([p for p in pats if p.find(b':') >= 0]):
6130 pats = [b'path:%s' % p for p in pats]
6129 pats = [b'path:%s' % p for p in pats]
6131 m = scmutil.match(wctx, pats, opts)
6130 m = scmutil.match(wctx, pats, opts)
6132 for f in ms:
6131 for f in ms:
6133 if not m(f):
6132 if not m(f):
6134 continue
6133 continue
6135
6134
6136 def flag(o):
6135 def flag(o):
6137 if o == b're_merge':
6136 if o == b're_merge':
6138 return b'--re-merge '
6137 return b'--re-merge '
6139 return b'-%s ' % o[0:1]
6138 return b'-%s ' % o[0:1]
6140
6139
6141 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6140 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6142 hint = _(b"(try: hg resolve %s%s)\n") % (
6141 hint = _(b"(try: hg resolve %s%s)\n") % (
6143 flags,
6142 flags,
6144 b' '.join(pats),
6143 b' '.join(pats),
6145 )
6144 )
6146 break
6145 break
6147 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6146 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6148 if hint:
6147 if hint:
6149 ui.warn(hint)
6148 ui.warn(hint)
6150 elif ms.mergedriver and ms.mdstate() != b's':
6149 elif ms.mergedriver and ms.mdstate() != b's':
6151 # run conclude step when either a driver-resolved file is requested
6150 # run conclude step when either a driver-resolved file is requested
6152 # or there are no driver-resolved files
6151 # or there are no driver-resolved files
6153 # we can't use 'ret' to determine whether any files are unresolved
6152 # we can't use 'ret' to determine whether any files are unresolved
6154 # because we might not have tried to resolve some
6153 # because we might not have tried to resolve some
6155 if (runconclude or not list(ms.driverresolved())) and not list(
6154 if (runconclude or not list(ms.driverresolved())) and not list(
6156 ms.unresolved()
6155 ms.unresolved()
6157 ):
6156 ):
6158 proceed = mergemod.driverconclude(repo, ms, wctx)
6157 proceed = mergemod.driverconclude(repo, ms, wctx)
6159 ms.commit()
6158 ms.commit()
6160 if not proceed:
6159 if not proceed:
6161 return 1
6160 return 1
6162
6161
6163 # Nudge users into finishing an unfinished operation
6162 # Nudge users into finishing an unfinished operation
6164 unresolvedf = list(ms.unresolved())
6163 unresolvedf = list(ms.unresolved())
6165 driverresolvedf = list(ms.driverresolved())
6164 driverresolvedf = list(ms.driverresolved())
6166 if not unresolvedf and not driverresolvedf:
6165 if not unresolvedf and not driverresolvedf:
6167 ui.status(_(b'(no more unresolved files)\n'))
6166 ui.status(_(b'(no more unresolved files)\n'))
6168 cmdutil.checkafterresolved(repo)
6167 cmdutil.checkafterresolved(repo)
6169 elif not unresolvedf:
6168 elif not unresolvedf:
6170 ui.status(
6169 ui.status(
6171 _(
6170 _(
6172 b'(no more unresolved files -- '
6171 b'(no more unresolved files -- '
6173 b'run "hg resolve --all" to conclude)\n'
6172 b'run "hg resolve --all" to conclude)\n'
6174 )
6173 )
6175 )
6174 )
6176
6175
6177 return ret
6176 return ret
6178
6177
6179
6178
6180 @command(
6179 @command(
6181 b'revert',
6180 b'revert',
6182 [
6181 [
6183 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6182 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6184 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6183 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6185 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6184 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6186 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6185 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6187 (b'i', b'interactive', None, _(b'interactively select the changes')),
6186 (b'i', b'interactive', None, _(b'interactively select the changes')),
6188 ]
6187 ]
6189 + walkopts
6188 + walkopts
6190 + dryrunopts,
6189 + dryrunopts,
6191 _(b'[OPTION]... [-r REV] [NAME]...'),
6190 _(b'[OPTION]... [-r REV] [NAME]...'),
6192 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6191 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6193 )
6192 )
6194 def revert(ui, repo, *pats, **opts):
6193 def revert(ui, repo, *pats, **opts):
6195 """restore files to their checkout state
6194 """restore files to their checkout state
6196
6195
6197 .. note::
6196 .. note::
6198
6197
6199 To check out earlier revisions, you should use :hg:`update REV`.
6198 To check out earlier revisions, you should use :hg:`update REV`.
6200 To cancel an uncommitted merge (and lose your changes),
6199 To cancel an uncommitted merge (and lose your changes),
6201 use :hg:`merge --abort`.
6200 use :hg:`merge --abort`.
6202
6201
6203 With no revision specified, revert the specified files or directories
6202 With no revision specified, revert the specified files or directories
6204 to the contents they had in the parent of the working directory.
6203 to the contents they had in the parent of the working directory.
6205 This restores the contents of files to an unmodified
6204 This restores the contents of files to an unmodified
6206 state and unschedules adds, removes, copies, and renames. If the
6205 state and unschedules adds, removes, copies, and renames. If the
6207 working directory has two parents, you must explicitly specify a
6206 working directory has two parents, you must explicitly specify a
6208 revision.
6207 revision.
6209
6208
6210 Using the -r/--rev or -d/--date options, revert the given files or
6209 Using the -r/--rev or -d/--date options, revert the given files or
6211 directories to their states as of a specific revision. Because
6210 directories to their states as of a specific revision. Because
6212 revert does not change the working directory parents, this will
6211 revert does not change the working directory parents, this will
6213 cause these files to appear modified. This can be helpful to "back
6212 cause these files to appear modified. This can be helpful to "back
6214 out" some or all of an earlier change. See :hg:`backout` for a
6213 out" some or all of an earlier change. See :hg:`backout` for a
6215 related method.
6214 related method.
6216
6215
6217 Modified files are saved with a .orig suffix before reverting.
6216 Modified files are saved with a .orig suffix before reverting.
6218 To disable these backups, use --no-backup. It is possible to store
6217 To disable these backups, use --no-backup. It is possible to store
6219 the backup files in a custom directory relative to the root of the
6218 the backup files in a custom directory relative to the root of the
6220 repository by setting the ``ui.origbackuppath`` configuration
6219 repository by setting the ``ui.origbackuppath`` configuration
6221 option.
6220 option.
6222
6221
6223 See :hg:`help dates` for a list of formats valid for -d/--date.
6222 See :hg:`help dates` for a list of formats valid for -d/--date.
6224
6223
6225 See :hg:`help backout` for a way to reverse the effect of an
6224 See :hg:`help backout` for a way to reverse the effect of an
6226 earlier changeset.
6225 earlier changeset.
6227
6226
6228 Returns 0 on success.
6227 Returns 0 on success.
6229 """
6228 """
6230
6229
6231 opts = pycompat.byteskwargs(opts)
6230 opts = pycompat.byteskwargs(opts)
6232 if opts.get(b"date"):
6231 if opts.get(b"date"):
6233 if opts.get(b"rev"):
6232 if opts.get(b"rev"):
6234 raise error.Abort(_(b"you can't specify a revision and a date"))
6233 raise error.Abort(_(b"you can't specify a revision and a date"))
6235 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6234 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6236
6235
6237 parent, p2 = repo.dirstate.parents()
6236 parent, p2 = repo.dirstate.parents()
6238 if not opts.get(b'rev') and p2 != nullid:
6237 if not opts.get(b'rev') and p2 != nullid:
6239 # revert after merge is a trap for new users (issue2915)
6238 # revert after merge is a trap for new users (issue2915)
6240 raise error.Abort(
6239 raise error.Abort(
6241 _(b'uncommitted merge with no revision specified'),
6240 _(b'uncommitted merge with no revision specified'),
6242 hint=_(b"use 'hg update' or see 'hg help revert'"),
6241 hint=_(b"use 'hg update' or see 'hg help revert'"),
6243 )
6242 )
6244
6243
6245 rev = opts.get(b'rev')
6244 rev = opts.get(b'rev')
6246 if rev:
6245 if rev:
6247 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6246 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6248 ctx = scmutil.revsingle(repo, rev)
6247 ctx = scmutil.revsingle(repo, rev)
6249
6248
6250 if not (
6249 if not (
6251 pats
6250 pats
6252 or opts.get(b'include')
6251 or opts.get(b'include')
6253 or opts.get(b'exclude')
6252 or opts.get(b'exclude')
6254 or opts.get(b'all')
6253 or opts.get(b'all')
6255 or opts.get(b'interactive')
6254 or opts.get(b'interactive')
6256 ):
6255 ):
6257 msg = _(b"no files or directories specified")
6256 msg = _(b"no files or directories specified")
6258 if p2 != nullid:
6257 if p2 != nullid:
6259 hint = _(
6258 hint = _(
6260 b"uncommitted merge, use --all to discard all changes,"
6259 b"uncommitted merge, use --all to discard all changes,"
6261 b" or 'hg update -C .' to abort the merge"
6260 b" or 'hg update -C .' to abort the merge"
6262 )
6261 )
6263 raise error.Abort(msg, hint=hint)
6262 raise error.Abort(msg, hint=hint)
6264 dirty = any(repo.status())
6263 dirty = any(repo.status())
6265 node = ctx.node()
6264 node = ctx.node()
6266 if node != parent:
6265 if node != parent:
6267 if dirty:
6266 if dirty:
6268 hint = (
6267 hint = (
6269 _(
6268 _(
6270 b"uncommitted changes, use --all to discard all"
6269 b"uncommitted changes, use --all to discard all"
6271 b" changes, or 'hg update %d' to update"
6270 b" changes, or 'hg update %d' to update"
6272 )
6271 )
6273 % ctx.rev()
6272 % ctx.rev()
6274 )
6273 )
6275 else:
6274 else:
6276 hint = (
6275 hint = (
6277 _(
6276 _(
6278 b"use --all to revert all files,"
6277 b"use --all to revert all files,"
6279 b" or 'hg update %d' to update"
6278 b" or 'hg update %d' to update"
6280 )
6279 )
6281 % ctx.rev()
6280 % ctx.rev()
6282 )
6281 )
6283 elif dirty:
6282 elif dirty:
6284 hint = _(b"uncommitted changes, use --all to discard all changes")
6283 hint = _(b"uncommitted changes, use --all to discard all changes")
6285 else:
6284 else:
6286 hint = _(b"use --all to revert all files")
6285 hint = _(b"use --all to revert all files")
6287 raise error.Abort(msg, hint=hint)
6286 raise error.Abort(msg, hint=hint)
6288
6287
6289 return cmdutil.revert(
6288 return cmdutil.revert(
6290 ui, repo, ctx, (parent, p2), *pats, **pycompat.strkwargs(opts)
6289 ui, repo, ctx, (parent, p2), *pats, **pycompat.strkwargs(opts)
6291 )
6290 )
6292
6291
6293
6292
6294 @command(
6293 @command(
6295 b'rollback',
6294 b'rollback',
6296 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6295 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6297 helpcategory=command.CATEGORY_MAINTENANCE,
6296 helpcategory=command.CATEGORY_MAINTENANCE,
6298 )
6297 )
6299 def rollback(ui, repo, **opts):
6298 def rollback(ui, repo, **opts):
6300 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6299 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6301
6300
6302 Please use :hg:`commit --amend` instead of rollback to correct
6301 Please use :hg:`commit --amend` instead of rollback to correct
6303 mistakes in the last commit.
6302 mistakes in the last commit.
6304
6303
6305 This command should be used with care. There is only one level of
6304 This command should be used with care. There is only one level of
6306 rollback, and there is no way to undo a rollback. It will also
6305 rollback, and there is no way to undo a rollback. It will also
6307 restore the dirstate at the time of the last transaction, losing
6306 restore the dirstate at the time of the last transaction, losing
6308 any dirstate changes since that time. This command does not alter
6307 any dirstate changes since that time. This command does not alter
6309 the working directory.
6308 the working directory.
6310
6309
6311 Transactions are used to encapsulate the effects of all commands
6310 Transactions are used to encapsulate the effects of all commands
6312 that create new changesets or propagate existing changesets into a
6311 that create new changesets or propagate existing changesets into a
6313 repository.
6312 repository.
6314
6313
6315 .. container:: verbose
6314 .. container:: verbose
6316
6315
6317 For example, the following commands are transactional, and their
6316 For example, the following commands are transactional, and their
6318 effects can be rolled back:
6317 effects can be rolled back:
6319
6318
6320 - commit
6319 - commit
6321 - import
6320 - import
6322 - pull
6321 - pull
6323 - push (with this repository as the destination)
6322 - push (with this repository as the destination)
6324 - unbundle
6323 - unbundle
6325
6324
6326 To avoid permanent data loss, rollback will refuse to rollback a
6325 To avoid permanent data loss, rollback will refuse to rollback a
6327 commit transaction if it isn't checked out. Use --force to
6326 commit transaction if it isn't checked out. Use --force to
6328 override this protection.
6327 override this protection.
6329
6328
6330 The rollback command can be entirely disabled by setting the
6329 The rollback command can be entirely disabled by setting the
6331 ``ui.rollback`` configuration setting to false. If you're here
6330 ``ui.rollback`` configuration setting to false. If you're here
6332 because you want to use rollback and it's disabled, you can
6331 because you want to use rollback and it's disabled, you can
6333 re-enable the command by setting ``ui.rollback`` to true.
6332 re-enable the command by setting ``ui.rollback`` to true.
6334
6333
6335 This command is not intended for use on public repositories. Once
6334 This command is not intended for use on public repositories. Once
6336 changes are visible for pull by other users, rolling a transaction
6335 changes are visible for pull by other users, rolling a transaction
6337 back locally is ineffective (someone else may already have pulled
6336 back locally is ineffective (someone else may already have pulled
6338 the changes). Furthermore, a race is possible with readers of the
6337 the changes). Furthermore, a race is possible with readers of the
6339 repository; for example an in-progress pull from the repository
6338 repository; for example an in-progress pull from the repository
6340 may fail if a rollback is performed.
6339 may fail if a rollback is performed.
6341
6340
6342 Returns 0 on success, 1 if no rollback data is available.
6341 Returns 0 on success, 1 if no rollback data is available.
6343 """
6342 """
6344 if not ui.configbool(b'ui', b'rollback'):
6343 if not ui.configbool(b'ui', b'rollback'):
6345 raise error.Abort(
6344 raise error.Abort(
6346 _(b'rollback is disabled because it is unsafe'),
6345 _(b'rollback is disabled because it is unsafe'),
6347 hint=b'see `hg help -v rollback` for information',
6346 hint=b'see `hg help -v rollback` for information',
6348 )
6347 )
6349 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6348 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6350
6349
6351
6350
6352 @command(
6351 @command(
6353 b'root',
6352 b'root',
6354 [] + formatteropts,
6353 [] + formatteropts,
6355 intents={INTENT_READONLY},
6354 intents={INTENT_READONLY},
6356 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6355 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6357 )
6356 )
6358 def root(ui, repo, **opts):
6357 def root(ui, repo, **opts):
6359 """print the root (top) of the current working directory
6358 """print the root (top) of the current working directory
6360
6359
6361 Print the root directory of the current repository.
6360 Print the root directory of the current repository.
6362
6361
6363 .. container:: verbose
6362 .. container:: verbose
6364
6363
6365 Template:
6364 Template:
6366
6365
6367 The following keywords are supported in addition to the common template
6366 The following keywords are supported in addition to the common template
6368 keywords and functions. See also :hg:`help templates`.
6367 keywords and functions. See also :hg:`help templates`.
6369
6368
6370 :hgpath: String. Path to the .hg directory.
6369 :hgpath: String. Path to the .hg directory.
6371 :storepath: String. Path to the directory holding versioned data.
6370 :storepath: String. Path to the directory holding versioned data.
6372
6371
6373 Returns 0 on success.
6372 Returns 0 on success.
6374 """
6373 """
6375 opts = pycompat.byteskwargs(opts)
6374 opts = pycompat.byteskwargs(opts)
6376 with ui.formatter(b'root', opts) as fm:
6375 with ui.formatter(b'root', opts) as fm:
6377 fm.startitem()
6376 fm.startitem()
6378 fm.write(b'reporoot', b'%s\n', repo.root)
6377 fm.write(b'reporoot', b'%s\n', repo.root)
6379 fm.data(hgpath=repo.path, storepath=repo.spath)
6378 fm.data(hgpath=repo.path, storepath=repo.spath)
6380
6379
6381
6380
6382 @command(
6381 @command(
6383 b'serve',
6382 b'serve',
6384 [
6383 [
6385 (
6384 (
6386 b'A',
6385 b'A',
6387 b'accesslog',
6386 b'accesslog',
6388 b'',
6387 b'',
6389 _(b'name of access log file to write to'),
6388 _(b'name of access log file to write to'),
6390 _(b'FILE'),
6389 _(b'FILE'),
6391 ),
6390 ),
6392 (b'd', b'daemon', None, _(b'run server in background')),
6391 (b'd', b'daemon', None, _(b'run server in background')),
6393 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6392 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6394 (
6393 (
6395 b'E',
6394 b'E',
6396 b'errorlog',
6395 b'errorlog',
6397 b'',
6396 b'',
6398 _(b'name of error log file to write to'),
6397 _(b'name of error log file to write to'),
6399 _(b'FILE'),
6398 _(b'FILE'),
6400 ),
6399 ),
6401 # use string type, then we can check if something was passed
6400 # use string type, then we can check if something was passed
6402 (
6401 (
6403 b'p',
6402 b'p',
6404 b'port',
6403 b'port',
6405 b'',
6404 b'',
6406 _(b'port to listen on (default: 8000)'),
6405 _(b'port to listen on (default: 8000)'),
6407 _(b'PORT'),
6406 _(b'PORT'),
6408 ),
6407 ),
6409 (
6408 (
6410 b'a',
6409 b'a',
6411 b'address',
6410 b'address',
6412 b'',
6411 b'',
6413 _(b'address to listen on (default: all interfaces)'),
6412 _(b'address to listen on (default: all interfaces)'),
6414 _(b'ADDR'),
6413 _(b'ADDR'),
6415 ),
6414 ),
6416 (
6415 (
6417 b'',
6416 b'',
6418 b'prefix',
6417 b'prefix',
6419 b'',
6418 b'',
6420 _(b'prefix path to serve from (default: server root)'),
6419 _(b'prefix path to serve from (default: server root)'),
6421 _(b'PREFIX'),
6420 _(b'PREFIX'),
6422 ),
6421 ),
6423 (
6422 (
6424 b'n',
6423 b'n',
6425 b'name',
6424 b'name',
6426 b'',
6425 b'',
6427 _(b'name to show in web pages (default: working directory)'),
6426 _(b'name to show in web pages (default: working directory)'),
6428 _(b'NAME'),
6427 _(b'NAME'),
6429 ),
6428 ),
6430 (
6429 (
6431 b'',
6430 b'',
6432 b'web-conf',
6431 b'web-conf',
6433 b'',
6432 b'',
6434 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6433 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6435 _(b'FILE'),
6434 _(b'FILE'),
6436 ),
6435 ),
6437 (
6436 (
6438 b'',
6437 b'',
6439 b'webdir-conf',
6438 b'webdir-conf',
6440 b'',
6439 b'',
6441 _(b'name of the hgweb config file (DEPRECATED)'),
6440 _(b'name of the hgweb config file (DEPRECATED)'),
6442 _(b'FILE'),
6441 _(b'FILE'),
6443 ),
6442 ),
6444 (
6443 (
6445 b'',
6444 b'',
6446 b'pid-file',
6445 b'pid-file',
6447 b'',
6446 b'',
6448 _(b'name of file to write process ID to'),
6447 _(b'name of file to write process ID to'),
6449 _(b'FILE'),
6448 _(b'FILE'),
6450 ),
6449 ),
6451 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6450 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6452 (
6451 (
6453 b'',
6452 b'',
6454 b'cmdserver',
6453 b'cmdserver',
6455 b'',
6454 b'',
6456 _(b'for remote clients (ADVANCED)'),
6455 _(b'for remote clients (ADVANCED)'),
6457 _(b'MODE'),
6456 _(b'MODE'),
6458 ),
6457 ),
6459 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6458 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6460 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6459 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6461 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6460 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6462 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6461 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6463 (b'', b'print-url', None, _(b'start and print only the URL')),
6462 (b'', b'print-url', None, _(b'start and print only the URL')),
6464 ]
6463 ]
6465 + subrepoopts,
6464 + subrepoopts,
6466 _(b'[OPTION]...'),
6465 _(b'[OPTION]...'),
6467 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6466 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6468 helpbasic=True,
6467 helpbasic=True,
6469 optionalrepo=True,
6468 optionalrepo=True,
6470 )
6469 )
6471 def serve(ui, repo, **opts):
6470 def serve(ui, repo, **opts):
6472 """start stand-alone webserver
6471 """start stand-alone webserver
6473
6472
6474 Start a local HTTP repository browser and pull server. You can use
6473 Start a local HTTP repository browser and pull server. You can use
6475 this for ad-hoc sharing and browsing of repositories. It is
6474 this for ad-hoc sharing and browsing of repositories. It is
6476 recommended to use a real web server to serve a repository for
6475 recommended to use a real web server to serve a repository for
6477 longer periods of time.
6476 longer periods of time.
6478
6477
6479 Please note that the server does not implement access control.
6478 Please note that the server does not implement access control.
6480 This means that, by default, anybody can read from the server and
6479 This means that, by default, anybody can read from the server and
6481 nobody can write to it by default. Set the ``web.allow-push``
6480 nobody can write to it by default. Set the ``web.allow-push``
6482 option to ``*`` to allow everybody to push to the server. You
6481 option to ``*`` to allow everybody to push to the server. You
6483 should use a real web server if you need to authenticate users.
6482 should use a real web server if you need to authenticate users.
6484
6483
6485 By default, the server logs accesses to stdout and errors to
6484 By default, the server logs accesses to stdout and errors to
6486 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6485 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6487 files.
6486 files.
6488
6487
6489 To have the server choose a free port number to listen on, specify
6488 To have the server choose a free port number to listen on, specify
6490 a port number of 0; in this case, the server will print the port
6489 a port number of 0; in this case, the server will print the port
6491 number it uses.
6490 number it uses.
6492
6491
6493 Returns 0 on success.
6492 Returns 0 on success.
6494 """
6493 """
6495
6494
6496 opts = pycompat.byteskwargs(opts)
6495 opts = pycompat.byteskwargs(opts)
6497 if opts[b"stdio"] and opts[b"cmdserver"]:
6496 if opts[b"stdio"] and opts[b"cmdserver"]:
6498 raise error.Abort(_(b"cannot use --stdio with --cmdserver"))
6497 raise error.Abort(_(b"cannot use --stdio with --cmdserver"))
6499 if opts[b"print_url"] and ui.verbose:
6498 if opts[b"print_url"] and ui.verbose:
6500 raise error.Abort(_(b"cannot use --print-url with --verbose"))
6499 raise error.Abort(_(b"cannot use --print-url with --verbose"))
6501
6500
6502 if opts[b"stdio"]:
6501 if opts[b"stdio"]:
6503 if repo is None:
6502 if repo is None:
6504 raise error.RepoError(
6503 raise error.RepoError(
6505 _(b"there is no Mercurial repository here (.hg not found)")
6504 _(b"there is no Mercurial repository here (.hg not found)")
6506 )
6505 )
6507 s = wireprotoserver.sshserver(ui, repo)
6506 s = wireprotoserver.sshserver(ui, repo)
6508 s.serve_forever()
6507 s.serve_forever()
6509
6508
6510 service = server.createservice(ui, repo, opts)
6509 service = server.createservice(ui, repo, opts)
6511 return server.runservice(opts, initfn=service.init, runfn=service.run)
6510 return server.runservice(opts, initfn=service.init, runfn=service.run)
6512
6511
6513
6512
6514 @command(
6513 @command(
6515 b'shelve',
6514 b'shelve',
6516 [
6515 [
6517 (
6516 (
6518 b'A',
6517 b'A',
6519 b'addremove',
6518 b'addremove',
6520 None,
6519 None,
6521 _(b'mark new/missing files as added/removed before shelving'),
6520 _(b'mark new/missing files as added/removed before shelving'),
6522 ),
6521 ),
6523 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6522 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6524 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6523 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6525 (
6524 (
6526 b'',
6525 b'',
6527 b'date',
6526 b'date',
6528 b'',
6527 b'',
6529 _(b'shelve with the specified commit date'),
6528 _(b'shelve with the specified commit date'),
6530 _(b'DATE'),
6529 _(b'DATE'),
6531 ),
6530 ),
6532 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6531 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6533 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6532 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6534 (
6533 (
6535 b'k',
6534 b'k',
6536 b'keep',
6535 b'keep',
6537 False,
6536 False,
6538 _(b'shelve, but keep changes in the working directory'),
6537 _(b'shelve, but keep changes in the working directory'),
6539 ),
6538 ),
6540 (b'l', b'list', None, _(b'list current shelves')),
6539 (b'l', b'list', None, _(b'list current shelves')),
6541 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6540 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6542 (
6541 (
6543 b'n',
6542 b'n',
6544 b'name',
6543 b'name',
6545 b'',
6544 b'',
6546 _(b'use the given name for the shelved commit'),
6545 _(b'use the given name for the shelved commit'),
6547 _(b'NAME'),
6546 _(b'NAME'),
6548 ),
6547 ),
6549 (
6548 (
6550 b'p',
6549 b'p',
6551 b'patch',
6550 b'patch',
6552 None,
6551 None,
6553 _(
6552 _(
6554 b'output patches for changes (provide the names of the shelved '
6553 b'output patches for changes (provide the names of the shelved '
6555 b'changes as positional arguments)'
6554 b'changes as positional arguments)'
6556 ),
6555 ),
6557 ),
6556 ),
6558 (b'i', b'interactive', None, _(b'interactive mode')),
6557 (b'i', b'interactive', None, _(b'interactive mode')),
6559 (
6558 (
6560 b'',
6559 b'',
6561 b'stat',
6560 b'stat',
6562 None,
6561 None,
6563 _(
6562 _(
6564 b'output diffstat-style summary of changes (provide the names of '
6563 b'output diffstat-style summary of changes (provide the names of '
6565 b'the shelved changes as positional arguments)'
6564 b'the shelved changes as positional arguments)'
6566 ),
6565 ),
6567 ),
6566 ),
6568 ]
6567 ]
6569 + cmdutil.walkopts,
6568 + cmdutil.walkopts,
6570 _(b'hg shelve [OPTION]... [FILE]...'),
6569 _(b'hg shelve [OPTION]... [FILE]...'),
6571 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6570 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6572 )
6571 )
6573 def shelve(ui, repo, *pats, **opts):
6572 def shelve(ui, repo, *pats, **opts):
6574 '''save and set aside changes from the working directory
6573 '''save and set aside changes from the working directory
6575
6574
6576 Shelving takes files that "hg status" reports as not clean, saves
6575 Shelving takes files that "hg status" reports as not clean, saves
6577 the modifications to a bundle (a shelved change), and reverts the
6576 the modifications to a bundle (a shelved change), and reverts the
6578 files so that their state in the working directory becomes clean.
6577 files so that their state in the working directory becomes clean.
6579
6578
6580 To restore these changes to the working directory, using "hg
6579 To restore these changes to the working directory, using "hg
6581 unshelve"; this will work even if you switch to a different
6580 unshelve"; this will work even if you switch to a different
6582 commit.
6581 commit.
6583
6582
6584 When no files are specified, "hg shelve" saves all not-clean
6583 When no files are specified, "hg shelve" saves all not-clean
6585 files. If specific files or directories are named, only changes to
6584 files. If specific files or directories are named, only changes to
6586 those files are shelved.
6585 those files are shelved.
6587
6586
6588 In bare shelve (when no files are specified, without interactive,
6587 In bare shelve (when no files are specified, without interactive,
6589 include and exclude option), shelving remembers information if the
6588 include and exclude option), shelving remembers information if the
6590 working directory was on newly created branch, in other words working
6589 working directory was on newly created branch, in other words working
6591 directory was on different branch than its first parent. In this
6590 directory was on different branch than its first parent. In this
6592 situation unshelving restores branch information to the working directory.
6591 situation unshelving restores branch information to the working directory.
6593
6592
6594 Each shelved change has a name that makes it easier to find later.
6593 Each shelved change has a name that makes it easier to find later.
6595 The name of a shelved change defaults to being based on the active
6594 The name of a shelved change defaults to being based on the active
6596 bookmark, or if there is no active bookmark, the current named
6595 bookmark, or if there is no active bookmark, the current named
6597 branch. To specify a different name, use ``--name``.
6596 branch. To specify a different name, use ``--name``.
6598
6597
6599 To see a list of existing shelved changes, use the ``--list``
6598 To see a list of existing shelved changes, use the ``--list``
6600 option. For each shelved change, this will print its name, age,
6599 option. For each shelved change, this will print its name, age,
6601 and description; use ``--patch`` or ``--stat`` for more details.
6600 and description; use ``--patch`` or ``--stat`` for more details.
6602
6601
6603 To delete specific shelved changes, use ``--delete``. To delete
6602 To delete specific shelved changes, use ``--delete``. To delete
6604 all shelved changes, use ``--cleanup``.
6603 all shelved changes, use ``--cleanup``.
6605 '''
6604 '''
6606 opts = pycompat.byteskwargs(opts)
6605 opts = pycompat.byteskwargs(opts)
6607 allowables = [
6606 allowables = [
6608 (b'addremove', {b'create'}), # 'create' is pseudo action
6607 (b'addremove', {b'create'}), # 'create' is pseudo action
6609 (b'unknown', {b'create'}),
6608 (b'unknown', {b'create'}),
6610 (b'cleanup', {b'cleanup'}),
6609 (b'cleanup', {b'cleanup'}),
6611 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6610 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6612 (b'delete', {b'delete'}),
6611 (b'delete', {b'delete'}),
6613 (b'edit', {b'create'}),
6612 (b'edit', {b'create'}),
6614 (b'keep', {b'create'}),
6613 (b'keep', {b'create'}),
6615 (b'list', {b'list'}),
6614 (b'list', {b'list'}),
6616 (b'message', {b'create'}),
6615 (b'message', {b'create'}),
6617 (b'name', {b'create'}),
6616 (b'name', {b'create'}),
6618 (b'patch', {b'patch', b'list'}),
6617 (b'patch', {b'patch', b'list'}),
6619 (b'stat', {b'stat', b'list'}),
6618 (b'stat', {b'stat', b'list'}),
6620 ]
6619 ]
6621
6620
6622 def checkopt(opt):
6621 def checkopt(opt):
6623 if opts.get(opt):
6622 if opts.get(opt):
6624 for i, allowable in allowables:
6623 for i, allowable in allowables:
6625 if opts[i] and opt not in allowable:
6624 if opts[i] and opt not in allowable:
6626 raise error.Abort(
6625 raise error.Abort(
6627 _(
6626 _(
6628 b"options '--%s' and '--%s' may not be "
6627 b"options '--%s' and '--%s' may not be "
6629 b"used together"
6628 b"used together"
6630 )
6629 )
6631 % (opt, i)
6630 % (opt, i)
6632 )
6631 )
6633 return True
6632 return True
6634
6633
6635 if checkopt(b'cleanup'):
6634 if checkopt(b'cleanup'):
6636 if pats:
6635 if pats:
6637 raise error.Abort(_(b"cannot specify names when using '--cleanup'"))
6636 raise error.Abort(_(b"cannot specify names when using '--cleanup'"))
6638 return shelvemod.cleanupcmd(ui, repo)
6637 return shelvemod.cleanupcmd(ui, repo)
6639 elif checkopt(b'delete'):
6638 elif checkopt(b'delete'):
6640 return shelvemod.deletecmd(ui, repo, pats)
6639 return shelvemod.deletecmd(ui, repo, pats)
6641 elif checkopt(b'list'):
6640 elif checkopt(b'list'):
6642 return shelvemod.listcmd(ui, repo, pats, opts)
6641 return shelvemod.listcmd(ui, repo, pats, opts)
6643 elif checkopt(b'patch') or checkopt(b'stat'):
6642 elif checkopt(b'patch') or checkopt(b'stat'):
6644 return shelvemod.patchcmds(ui, repo, pats, opts)
6643 return shelvemod.patchcmds(ui, repo, pats, opts)
6645 else:
6644 else:
6646 return shelvemod.createcmd(ui, repo, pats, opts)
6645 return shelvemod.createcmd(ui, repo, pats, opts)
6647
6646
6648
6647
6649 _NOTTERSE = b'nothing'
6648 _NOTTERSE = b'nothing'
6650
6649
6651
6650
6652 @command(
6651 @command(
6653 b'status|st',
6652 b'status|st',
6654 [
6653 [
6655 (b'A', b'all', None, _(b'show status of all files')),
6654 (b'A', b'all', None, _(b'show status of all files')),
6656 (b'm', b'modified', None, _(b'show only modified files')),
6655 (b'm', b'modified', None, _(b'show only modified files')),
6657 (b'a', b'added', None, _(b'show only added files')),
6656 (b'a', b'added', None, _(b'show only added files')),
6658 (b'r', b'removed', None, _(b'show only removed files')),
6657 (b'r', b'removed', None, _(b'show only removed files')),
6659 (b'd', b'deleted', None, _(b'show only deleted (but tracked) files')),
6658 (b'd', b'deleted', None, _(b'show only deleted (but tracked) files')),
6660 (b'c', b'clean', None, _(b'show only files without changes')),
6659 (b'c', b'clean', None, _(b'show only files without changes')),
6661 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6660 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6662 (b'i', b'ignored', None, _(b'show only ignored files')),
6661 (b'i', b'ignored', None, _(b'show only ignored files')),
6663 (b'n', b'no-status', None, _(b'hide status prefix')),
6662 (b'n', b'no-status', None, _(b'hide status prefix')),
6664 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6663 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6665 (
6664 (
6666 b'C',
6665 b'C',
6667 b'copies',
6666 b'copies',
6668 None,
6667 None,
6669 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6668 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6670 ),
6669 ),
6671 (
6670 (
6672 b'0',
6671 b'0',
6673 b'print0',
6672 b'print0',
6674 None,
6673 None,
6675 _(b'end filenames with NUL, for use with xargs'),
6674 _(b'end filenames with NUL, for use with xargs'),
6676 ),
6675 ),
6677 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6676 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6678 (
6677 (
6679 b'',
6678 b'',
6680 b'change',
6679 b'change',
6681 b'',
6680 b'',
6682 _(b'list the changed files of a revision'),
6681 _(b'list the changed files of a revision'),
6683 _(b'REV'),
6682 _(b'REV'),
6684 ),
6683 ),
6685 ]
6684 ]
6686 + walkopts
6685 + walkopts
6687 + subrepoopts
6686 + subrepoopts
6688 + formatteropts,
6687 + formatteropts,
6689 _(b'[OPTION]... [FILE]...'),
6688 _(b'[OPTION]... [FILE]...'),
6690 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6689 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6691 helpbasic=True,
6690 helpbasic=True,
6692 inferrepo=True,
6691 inferrepo=True,
6693 intents={INTENT_READONLY},
6692 intents={INTENT_READONLY},
6694 )
6693 )
6695 def status(ui, repo, *pats, **opts):
6694 def status(ui, repo, *pats, **opts):
6696 """show changed files in the working directory
6695 """show changed files in the working directory
6697
6696
6698 Show status of files in the repository. If names are given, only
6697 Show status of files in the repository. If names are given, only
6699 files that match are shown. Files that are clean or ignored or
6698 files that match are shown. Files that are clean or ignored or
6700 the source of a copy/move operation, are not listed unless
6699 the source of a copy/move operation, are not listed unless
6701 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6700 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6702 Unless options described with "show only ..." are given, the
6701 Unless options described with "show only ..." are given, the
6703 options -mardu are used.
6702 options -mardu are used.
6704
6703
6705 Option -q/--quiet hides untracked (unknown and ignored) files
6704 Option -q/--quiet hides untracked (unknown and ignored) files
6706 unless explicitly requested with -u/--unknown or -i/--ignored.
6705 unless explicitly requested with -u/--unknown or -i/--ignored.
6707
6706
6708 .. note::
6707 .. note::
6709
6708
6710 :hg:`status` may appear to disagree with diff if permissions have
6709 :hg:`status` may appear to disagree with diff if permissions have
6711 changed or a merge has occurred. The standard diff format does
6710 changed or a merge has occurred. The standard diff format does
6712 not report permission changes and diff only reports changes
6711 not report permission changes and diff only reports changes
6713 relative to one merge parent.
6712 relative to one merge parent.
6714
6713
6715 If one revision is given, it is used as the base revision.
6714 If one revision is given, it is used as the base revision.
6716 If two revisions are given, the differences between them are
6715 If two revisions are given, the differences between them are
6717 shown. The --change option can also be used as a shortcut to list
6716 shown. The --change option can also be used as a shortcut to list
6718 the changed files of a revision from its first parent.
6717 the changed files of a revision from its first parent.
6719
6718
6720 The codes used to show the status of files are::
6719 The codes used to show the status of files are::
6721
6720
6722 M = modified
6721 M = modified
6723 A = added
6722 A = added
6724 R = removed
6723 R = removed
6725 C = clean
6724 C = clean
6726 ! = missing (deleted by non-hg command, but still tracked)
6725 ! = missing (deleted by non-hg command, but still tracked)
6727 ? = not tracked
6726 ? = not tracked
6728 I = ignored
6727 I = ignored
6729 = origin of the previous file (with --copies)
6728 = origin of the previous file (with --copies)
6730
6729
6731 .. container:: verbose
6730 .. container:: verbose
6732
6731
6733 The -t/--terse option abbreviates the output by showing only the directory
6732 The -t/--terse option abbreviates the output by showing only the directory
6734 name if all the files in it share the same status. The option takes an
6733 name if all the files in it share the same status. The option takes an
6735 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6734 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6736 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6735 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6737 for 'ignored' and 'c' for clean.
6736 for 'ignored' and 'c' for clean.
6738
6737
6739 It abbreviates only those statuses which are passed. Note that clean and
6738 It abbreviates only those statuses which are passed. Note that clean and
6740 ignored files are not displayed with '--terse ic' unless the -c/--clean
6739 ignored files are not displayed with '--terse ic' unless the -c/--clean
6741 and -i/--ignored options are also used.
6740 and -i/--ignored options are also used.
6742
6741
6743 The -v/--verbose option shows information when the repository is in an
6742 The -v/--verbose option shows information when the repository is in an
6744 unfinished merge, shelve, rebase state etc. You can have this behavior
6743 unfinished merge, shelve, rebase state etc. You can have this behavior
6745 turned on by default by enabling the ``commands.status.verbose`` option.
6744 turned on by default by enabling the ``commands.status.verbose`` option.
6746
6745
6747 You can skip displaying some of these states by setting
6746 You can skip displaying some of these states by setting
6748 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6747 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6749 'histedit', 'merge', 'rebase', or 'unshelve'.
6748 'histedit', 'merge', 'rebase', or 'unshelve'.
6750
6749
6751 Template:
6750 Template:
6752
6751
6753 The following keywords are supported in addition to the common template
6752 The following keywords are supported in addition to the common template
6754 keywords and functions. See also :hg:`help templates`.
6753 keywords and functions. See also :hg:`help templates`.
6755
6754
6756 :path: String. Repository-absolute path of the file.
6755 :path: String. Repository-absolute path of the file.
6757 :source: String. Repository-absolute path of the file originated from.
6756 :source: String. Repository-absolute path of the file originated from.
6758 Available if ``--copies`` is specified.
6757 Available if ``--copies`` is specified.
6759 :status: String. Character denoting file's status.
6758 :status: String. Character denoting file's status.
6760
6759
6761 Examples:
6760 Examples:
6762
6761
6763 - show changes in the working directory relative to a
6762 - show changes in the working directory relative to a
6764 changeset::
6763 changeset::
6765
6764
6766 hg status --rev 9353
6765 hg status --rev 9353
6767
6766
6768 - show changes in the working directory relative to the
6767 - show changes in the working directory relative to the
6769 current directory (see :hg:`help patterns` for more information)::
6768 current directory (see :hg:`help patterns` for more information)::
6770
6769
6771 hg status re:
6770 hg status re:
6772
6771
6773 - show all changes including copies in an existing changeset::
6772 - show all changes including copies in an existing changeset::
6774
6773
6775 hg status --copies --change 9353
6774 hg status --copies --change 9353
6776
6775
6777 - get a NUL separated list of added files, suitable for xargs::
6776 - get a NUL separated list of added files, suitable for xargs::
6778
6777
6779 hg status -an0
6778 hg status -an0
6780
6779
6781 - show more information about the repository status, abbreviating
6780 - show more information about the repository status, abbreviating
6782 added, removed, modified, deleted, and untracked paths::
6781 added, removed, modified, deleted, and untracked paths::
6783
6782
6784 hg status -v -t mardu
6783 hg status -v -t mardu
6785
6784
6786 Returns 0 on success.
6785 Returns 0 on success.
6787
6786
6788 """
6787 """
6789
6788
6790 opts = pycompat.byteskwargs(opts)
6789 opts = pycompat.byteskwargs(opts)
6791 revs = opts.get(b'rev')
6790 revs = opts.get(b'rev')
6792 change = opts.get(b'change')
6791 change = opts.get(b'change')
6793 terse = opts.get(b'terse')
6792 terse = opts.get(b'terse')
6794 if terse is _NOTTERSE:
6793 if terse is _NOTTERSE:
6795 if revs:
6794 if revs:
6796 terse = b''
6795 terse = b''
6797 else:
6796 else:
6798 terse = ui.config(b'commands', b'status.terse')
6797 terse = ui.config(b'commands', b'status.terse')
6799
6798
6800 if revs and change:
6799 if revs and change:
6801 msg = _(b'cannot specify --rev and --change at the same time')
6800 msg = _(b'cannot specify --rev and --change at the same time')
6802 raise error.Abort(msg)
6801 raise error.Abort(msg)
6803 elif revs and terse:
6802 elif revs and terse:
6804 msg = _(b'cannot use --terse with --rev')
6803 msg = _(b'cannot use --terse with --rev')
6805 raise error.Abort(msg)
6804 raise error.Abort(msg)
6806 elif change:
6805 elif change:
6807 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6806 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6808 ctx2 = scmutil.revsingle(repo, change, None)
6807 ctx2 = scmutil.revsingle(repo, change, None)
6809 ctx1 = ctx2.p1()
6808 ctx1 = ctx2.p1()
6810 else:
6809 else:
6811 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6810 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6812 ctx1, ctx2 = scmutil.revpair(repo, revs)
6811 ctx1, ctx2 = scmutil.revpair(repo, revs)
6813
6812
6814 forcerelativevalue = None
6813 forcerelativevalue = None
6815 if ui.hasconfig(b'commands', b'status.relative'):
6814 if ui.hasconfig(b'commands', b'status.relative'):
6816 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6815 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6817 uipathfn = scmutil.getuipathfn(
6816 uipathfn = scmutil.getuipathfn(
6818 repo,
6817 repo,
6819 legacyrelativevalue=bool(pats),
6818 legacyrelativevalue=bool(pats),
6820 forcerelativevalue=forcerelativevalue,
6819 forcerelativevalue=forcerelativevalue,
6821 )
6820 )
6822
6821
6823 if opts.get(b'print0'):
6822 if opts.get(b'print0'):
6824 end = b'\0'
6823 end = b'\0'
6825 else:
6824 else:
6826 end = b'\n'
6825 end = b'\n'
6827 states = b'modified added removed deleted unknown ignored clean'.split()
6826 states = b'modified added removed deleted unknown ignored clean'.split()
6828 show = [k for k in states if opts.get(k)]
6827 show = [k for k in states if opts.get(k)]
6829 if opts.get(b'all'):
6828 if opts.get(b'all'):
6830 show += ui.quiet and (states[:4] + [b'clean']) or states
6829 show += ui.quiet and (states[:4] + [b'clean']) or states
6831
6830
6832 if not show:
6831 if not show:
6833 if ui.quiet:
6832 if ui.quiet:
6834 show = states[:4]
6833 show = states[:4]
6835 else:
6834 else:
6836 show = states[:5]
6835 show = states[:5]
6837
6836
6838 m = scmutil.match(ctx2, pats, opts)
6837 m = scmutil.match(ctx2, pats, opts)
6839 if terse:
6838 if terse:
6840 # we need to compute clean and unknown to terse
6839 # we need to compute clean and unknown to terse
6841 stat = repo.status(
6840 stat = repo.status(
6842 ctx1.node(),
6841 ctx1.node(),
6843 ctx2.node(),
6842 ctx2.node(),
6844 m,
6843 m,
6845 b'ignored' in show or b'i' in terse,
6844 b'ignored' in show or b'i' in terse,
6846 clean=True,
6845 clean=True,
6847 unknown=True,
6846 unknown=True,
6848 listsubrepos=opts.get(b'subrepos'),
6847 listsubrepos=opts.get(b'subrepos'),
6849 )
6848 )
6850
6849
6851 stat = cmdutil.tersedir(stat, terse)
6850 stat = cmdutil.tersedir(stat, terse)
6852 else:
6851 else:
6853 stat = repo.status(
6852 stat = repo.status(
6854 ctx1.node(),
6853 ctx1.node(),
6855 ctx2.node(),
6854 ctx2.node(),
6856 m,
6855 m,
6857 b'ignored' in show,
6856 b'ignored' in show,
6858 b'clean' in show,
6857 b'clean' in show,
6859 b'unknown' in show,
6858 b'unknown' in show,
6860 opts.get(b'subrepos'),
6859 opts.get(b'subrepos'),
6861 )
6860 )
6862
6861
6863 changestates = zip(
6862 changestates = zip(
6864 states,
6863 states,
6865 pycompat.iterbytestr(b'MAR!?IC'),
6864 pycompat.iterbytestr(b'MAR!?IC'),
6866 [getattr(stat, s.decode('utf8')) for s in states],
6865 [getattr(stat, s.decode('utf8')) for s in states],
6867 )
6866 )
6868
6867
6869 copy = {}
6868 copy = {}
6870 if (
6869 if (
6871 opts.get(b'all')
6870 opts.get(b'all')
6872 or opts.get(b'copies')
6871 or opts.get(b'copies')
6873 or ui.configbool(b'ui', b'statuscopies')
6872 or ui.configbool(b'ui', b'statuscopies')
6874 ) and not opts.get(b'no_status'):
6873 ) and not opts.get(b'no_status'):
6875 copy = copies.pathcopies(ctx1, ctx2, m)
6874 copy = copies.pathcopies(ctx1, ctx2, m)
6876
6875
6877 morestatus = None
6876 morestatus = None
6878 if (
6877 if (
6879 ui.verbose or ui.configbool(b'commands', b'status.verbose')
6878 ui.verbose or ui.configbool(b'commands', b'status.verbose')
6880 ) and not ui.plain():
6879 ) and not ui.plain():
6881 morestatus = cmdutil.readmorestatus(repo)
6880 morestatus = cmdutil.readmorestatus(repo)
6882
6881
6883 ui.pager(b'status')
6882 ui.pager(b'status')
6884 fm = ui.formatter(b'status', opts)
6883 fm = ui.formatter(b'status', opts)
6885 fmt = b'%s' + end
6884 fmt = b'%s' + end
6886 showchar = not opts.get(b'no_status')
6885 showchar = not opts.get(b'no_status')
6887
6886
6888 for state, char, files in changestates:
6887 for state, char, files in changestates:
6889 if state in show:
6888 if state in show:
6890 label = b'status.' + state
6889 label = b'status.' + state
6891 for f in files:
6890 for f in files:
6892 fm.startitem()
6891 fm.startitem()
6893 fm.context(ctx=ctx2)
6892 fm.context(ctx=ctx2)
6894 fm.data(itemtype=b'file', path=f)
6893 fm.data(itemtype=b'file', path=f)
6895 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6894 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6896 fm.plain(fmt % uipathfn(f), label=label)
6895 fm.plain(fmt % uipathfn(f), label=label)
6897 if f in copy:
6896 if f in copy:
6898 fm.data(source=copy[f])
6897 fm.data(source=copy[f])
6899 fm.plain(
6898 fm.plain(
6900 (b' %s' + end) % uipathfn(copy[f]),
6899 (b' %s' + end) % uipathfn(copy[f]),
6901 label=b'status.copied',
6900 label=b'status.copied',
6902 )
6901 )
6903 if morestatus:
6902 if morestatus:
6904 morestatus.formatfile(f, fm)
6903 morestatus.formatfile(f, fm)
6905
6904
6906 if morestatus:
6905 if morestatus:
6907 morestatus.formatfooter(fm)
6906 morestatus.formatfooter(fm)
6908 fm.end()
6907 fm.end()
6909
6908
6910
6909
6911 @command(
6910 @command(
6912 b'summary|sum',
6911 b'summary|sum',
6913 [(b'', b'remote', None, _(b'check for push and pull'))],
6912 [(b'', b'remote', None, _(b'check for push and pull'))],
6914 b'[--remote]',
6913 b'[--remote]',
6915 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6914 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6916 helpbasic=True,
6915 helpbasic=True,
6917 intents={INTENT_READONLY},
6916 intents={INTENT_READONLY},
6918 )
6917 )
6919 def summary(ui, repo, **opts):
6918 def summary(ui, repo, **opts):
6920 """summarize working directory state
6919 """summarize working directory state
6921
6920
6922 This generates a brief summary of the working directory state,
6921 This generates a brief summary of the working directory state,
6923 including parents, branch, commit status, phase and available updates.
6922 including parents, branch, commit status, phase and available updates.
6924
6923
6925 With the --remote option, this will check the default paths for
6924 With the --remote option, this will check the default paths for
6926 incoming and outgoing changes. This can be time-consuming.
6925 incoming and outgoing changes. This can be time-consuming.
6927
6926
6928 Returns 0 on success.
6927 Returns 0 on success.
6929 """
6928 """
6930
6929
6931 opts = pycompat.byteskwargs(opts)
6930 opts = pycompat.byteskwargs(opts)
6932 ui.pager(b'summary')
6931 ui.pager(b'summary')
6933 ctx = repo[None]
6932 ctx = repo[None]
6934 parents = ctx.parents()
6933 parents = ctx.parents()
6935 pnode = parents[0].node()
6934 pnode = parents[0].node()
6936 marks = []
6935 marks = []
6937
6936
6938 try:
6937 try:
6939 ms = mergemod.mergestate.read(repo)
6938 ms = mergemod.mergestate.read(repo)
6940 except error.UnsupportedMergeRecords as e:
6939 except error.UnsupportedMergeRecords as e:
6941 s = b' '.join(e.recordtypes)
6940 s = b' '.join(e.recordtypes)
6942 ui.warn(
6941 ui.warn(
6943 _(b'warning: merge state has unsupported record types: %s\n') % s
6942 _(b'warning: merge state has unsupported record types: %s\n') % s
6944 )
6943 )
6945 unresolved = []
6944 unresolved = []
6946 else:
6945 else:
6947 unresolved = list(ms.unresolved())
6946 unresolved = list(ms.unresolved())
6948
6947
6949 for p in parents:
6948 for p in parents:
6950 # label with log.changeset (instead of log.parent) since this
6949 # label with log.changeset (instead of log.parent) since this
6951 # shows a working directory parent *changeset*:
6950 # shows a working directory parent *changeset*:
6952 # i18n: column positioning for "hg summary"
6951 # i18n: column positioning for "hg summary"
6953 ui.write(
6952 ui.write(
6954 _(b'parent: %d:%s ') % (p.rev(), p),
6953 _(b'parent: %d:%s ') % (p.rev(), p),
6955 label=logcmdutil.changesetlabels(p),
6954 label=logcmdutil.changesetlabels(p),
6956 )
6955 )
6957 ui.write(b' '.join(p.tags()), label=b'log.tag')
6956 ui.write(b' '.join(p.tags()), label=b'log.tag')
6958 if p.bookmarks():
6957 if p.bookmarks():
6959 marks.extend(p.bookmarks())
6958 marks.extend(p.bookmarks())
6960 if p.rev() == -1:
6959 if p.rev() == -1:
6961 if not len(repo):
6960 if not len(repo):
6962 ui.write(_(b' (empty repository)'))
6961 ui.write(_(b' (empty repository)'))
6963 else:
6962 else:
6964 ui.write(_(b' (no revision checked out)'))
6963 ui.write(_(b' (no revision checked out)'))
6965 if p.obsolete():
6964 if p.obsolete():
6966 ui.write(_(b' (obsolete)'))
6965 ui.write(_(b' (obsolete)'))
6967 if p.isunstable():
6966 if p.isunstable():
6968 instabilities = (
6967 instabilities = (
6969 ui.label(instability, b'trouble.%s' % instability)
6968 ui.label(instability, b'trouble.%s' % instability)
6970 for instability in p.instabilities()
6969 for instability in p.instabilities()
6971 )
6970 )
6972 ui.write(b' (' + b', '.join(instabilities) + b')')
6971 ui.write(b' (' + b', '.join(instabilities) + b')')
6973 ui.write(b'\n')
6972 ui.write(b'\n')
6974 if p.description():
6973 if p.description():
6975 ui.status(
6974 ui.status(
6976 b' ' + p.description().splitlines()[0].strip() + b'\n',
6975 b' ' + p.description().splitlines()[0].strip() + b'\n',
6977 label=b'log.summary',
6976 label=b'log.summary',
6978 )
6977 )
6979
6978
6980 branch = ctx.branch()
6979 branch = ctx.branch()
6981 bheads = repo.branchheads(branch)
6980 bheads = repo.branchheads(branch)
6982 # i18n: column positioning for "hg summary"
6981 # i18n: column positioning for "hg summary"
6983 m = _(b'branch: %s\n') % branch
6982 m = _(b'branch: %s\n') % branch
6984 if branch != b'default':
6983 if branch != b'default':
6985 ui.write(m, label=b'log.branch')
6984 ui.write(m, label=b'log.branch')
6986 else:
6985 else:
6987 ui.status(m, label=b'log.branch')
6986 ui.status(m, label=b'log.branch')
6988
6987
6989 if marks:
6988 if marks:
6990 active = repo._activebookmark
6989 active = repo._activebookmark
6991 # i18n: column positioning for "hg summary"
6990 # i18n: column positioning for "hg summary"
6992 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
6991 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
6993 if active is not None:
6992 if active is not None:
6994 if active in marks:
6993 if active in marks:
6995 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
6994 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
6996 marks.remove(active)
6995 marks.remove(active)
6997 else:
6996 else:
6998 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
6997 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
6999 for m in marks:
6998 for m in marks:
7000 ui.write(b' ' + m, label=b'log.bookmark')
6999 ui.write(b' ' + m, label=b'log.bookmark')
7001 ui.write(b'\n', label=b'log.bookmark')
7000 ui.write(b'\n', label=b'log.bookmark')
7002
7001
7003 status = repo.status(unknown=True)
7002 status = repo.status(unknown=True)
7004
7003
7005 c = repo.dirstate.copies()
7004 c = repo.dirstate.copies()
7006 copied, renamed = [], []
7005 copied, renamed = [], []
7007 for d, s in pycompat.iteritems(c):
7006 for d, s in pycompat.iteritems(c):
7008 if s in status.removed:
7007 if s in status.removed:
7009 status.removed.remove(s)
7008 status.removed.remove(s)
7010 renamed.append(d)
7009 renamed.append(d)
7011 else:
7010 else:
7012 copied.append(d)
7011 copied.append(d)
7013 if d in status.added:
7012 if d in status.added:
7014 status.added.remove(d)
7013 status.added.remove(d)
7015
7014
7016 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7015 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7017
7016
7018 labels = [
7017 labels = [
7019 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7018 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7020 (ui.label(_(b'%d added'), b'status.added'), status.added),
7019 (ui.label(_(b'%d added'), b'status.added'), status.added),
7021 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7020 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7022 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7021 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7023 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7022 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7024 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7023 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7025 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7024 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7026 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7025 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7027 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7026 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7028 ]
7027 ]
7029 t = []
7028 t = []
7030 for l, s in labels:
7029 for l, s in labels:
7031 if s:
7030 if s:
7032 t.append(l % len(s))
7031 t.append(l % len(s))
7033
7032
7034 t = b', '.join(t)
7033 t = b', '.join(t)
7035 cleanworkdir = False
7034 cleanworkdir = False
7036
7035
7037 if repo.vfs.exists(b'graftstate'):
7036 if repo.vfs.exists(b'graftstate'):
7038 t += _(b' (graft in progress)')
7037 t += _(b' (graft in progress)')
7039 if repo.vfs.exists(b'updatestate'):
7038 if repo.vfs.exists(b'updatestate'):
7040 t += _(b' (interrupted update)')
7039 t += _(b' (interrupted update)')
7041 elif len(parents) > 1:
7040 elif len(parents) > 1:
7042 t += _(b' (merge)')
7041 t += _(b' (merge)')
7043 elif branch != parents[0].branch():
7042 elif branch != parents[0].branch():
7044 t += _(b' (new branch)')
7043 t += _(b' (new branch)')
7045 elif parents[0].closesbranch() and pnode in repo.branchheads(
7044 elif parents[0].closesbranch() and pnode in repo.branchheads(
7046 branch, closed=True
7045 branch, closed=True
7047 ):
7046 ):
7048 t += _(b' (head closed)')
7047 t += _(b' (head closed)')
7049 elif not (
7048 elif not (
7050 status.modified
7049 status.modified
7051 or status.added
7050 or status.added
7052 or status.removed
7051 or status.removed
7053 or renamed
7052 or renamed
7054 or copied
7053 or copied
7055 or subs
7054 or subs
7056 ):
7055 ):
7057 t += _(b' (clean)')
7056 t += _(b' (clean)')
7058 cleanworkdir = True
7057 cleanworkdir = True
7059 elif pnode not in bheads:
7058 elif pnode not in bheads:
7060 t += _(b' (new branch head)')
7059 t += _(b' (new branch head)')
7061
7060
7062 if parents:
7061 if parents:
7063 pendingphase = max(p.phase() for p in parents)
7062 pendingphase = max(p.phase() for p in parents)
7064 else:
7063 else:
7065 pendingphase = phases.public
7064 pendingphase = phases.public
7066
7065
7067 if pendingphase > phases.newcommitphase(ui):
7066 if pendingphase > phases.newcommitphase(ui):
7068 t += b' (%s)' % phases.phasenames[pendingphase]
7067 t += b' (%s)' % phases.phasenames[pendingphase]
7069
7068
7070 if cleanworkdir:
7069 if cleanworkdir:
7071 # i18n: column positioning for "hg summary"
7070 # i18n: column positioning for "hg summary"
7072 ui.status(_(b'commit: %s\n') % t.strip())
7071 ui.status(_(b'commit: %s\n') % t.strip())
7073 else:
7072 else:
7074 # i18n: column positioning for "hg summary"
7073 # i18n: column positioning for "hg summary"
7075 ui.write(_(b'commit: %s\n') % t.strip())
7074 ui.write(_(b'commit: %s\n') % t.strip())
7076
7075
7077 # all ancestors of branch heads - all ancestors of parent = new csets
7076 # all ancestors of branch heads - all ancestors of parent = new csets
7078 new = len(
7077 new = len(
7079 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7078 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7080 )
7079 )
7081
7080
7082 if new == 0:
7081 if new == 0:
7083 # i18n: column positioning for "hg summary"
7082 # i18n: column positioning for "hg summary"
7084 ui.status(_(b'update: (current)\n'))
7083 ui.status(_(b'update: (current)\n'))
7085 elif pnode not in bheads:
7084 elif pnode not in bheads:
7086 # i18n: column positioning for "hg summary"
7085 # i18n: column positioning for "hg summary"
7087 ui.write(_(b'update: %d new changesets (update)\n') % new)
7086 ui.write(_(b'update: %d new changesets (update)\n') % new)
7088 else:
7087 else:
7089 # i18n: column positioning for "hg summary"
7088 # i18n: column positioning for "hg summary"
7090 ui.write(
7089 ui.write(
7091 _(b'update: %d new changesets, %d branch heads (merge)\n')
7090 _(b'update: %d new changesets, %d branch heads (merge)\n')
7092 % (new, len(bheads))
7091 % (new, len(bheads))
7093 )
7092 )
7094
7093
7095 t = []
7094 t = []
7096 draft = len(repo.revs(b'draft()'))
7095 draft = len(repo.revs(b'draft()'))
7097 if draft:
7096 if draft:
7098 t.append(_(b'%d draft') % draft)
7097 t.append(_(b'%d draft') % draft)
7099 secret = len(repo.revs(b'secret()'))
7098 secret = len(repo.revs(b'secret()'))
7100 if secret:
7099 if secret:
7101 t.append(_(b'%d secret') % secret)
7100 t.append(_(b'%d secret') % secret)
7102
7101
7103 if draft or secret:
7102 if draft or secret:
7104 ui.status(_(b'phases: %s\n') % b', '.join(t))
7103 ui.status(_(b'phases: %s\n') % b', '.join(t))
7105
7104
7106 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7105 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7107 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7106 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7108 numtrouble = len(repo.revs(trouble + b"()"))
7107 numtrouble = len(repo.revs(trouble + b"()"))
7109 # We write all the possibilities to ease translation
7108 # We write all the possibilities to ease translation
7110 troublemsg = {
7109 troublemsg = {
7111 b"orphan": _(b"orphan: %d changesets"),
7110 b"orphan": _(b"orphan: %d changesets"),
7112 b"contentdivergent": _(b"content-divergent: %d changesets"),
7111 b"contentdivergent": _(b"content-divergent: %d changesets"),
7113 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7112 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7114 }
7113 }
7115 if numtrouble > 0:
7114 if numtrouble > 0:
7116 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7115 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7117
7116
7118 cmdutil.summaryhooks(ui, repo)
7117 cmdutil.summaryhooks(ui, repo)
7119
7118
7120 if opts.get(b'remote'):
7119 if opts.get(b'remote'):
7121 needsincoming, needsoutgoing = True, True
7120 needsincoming, needsoutgoing = True, True
7122 else:
7121 else:
7123 needsincoming, needsoutgoing = False, False
7122 needsincoming, needsoutgoing = False, False
7124 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7123 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7125 if i:
7124 if i:
7126 needsincoming = True
7125 needsincoming = True
7127 if o:
7126 if o:
7128 needsoutgoing = True
7127 needsoutgoing = True
7129 if not needsincoming and not needsoutgoing:
7128 if not needsincoming and not needsoutgoing:
7130 return
7129 return
7131
7130
7132 def getincoming():
7131 def getincoming():
7133 source, branches = hg.parseurl(ui.expandpath(b'default'))
7132 source, branches = hg.parseurl(ui.expandpath(b'default'))
7134 sbranch = branches[0]
7133 sbranch = branches[0]
7135 try:
7134 try:
7136 other = hg.peer(repo, {}, source)
7135 other = hg.peer(repo, {}, source)
7137 except error.RepoError:
7136 except error.RepoError:
7138 if opts.get(b'remote'):
7137 if opts.get(b'remote'):
7139 raise
7138 raise
7140 return source, sbranch, None, None, None
7139 return source, sbranch, None, None, None
7141 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7140 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7142 if revs:
7141 if revs:
7143 revs = [other.lookup(rev) for rev in revs]
7142 revs = [other.lookup(rev) for rev in revs]
7144 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
7143 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
7145 repo.ui.pushbuffer()
7144 repo.ui.pushbuffer()
7146 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7145 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7147 repo.ui.popbuffer()
7146 repo.ui.popbuffer()
7148 return source, sbranch, other, commoninc, commoninc[1]
7147 return source, sbranch, other, commoninc, commoninc[1]
7149
7148
7150 if needsincoming:
7149 if needsincoming:
7151 source, sbranch, sother, commoninc, incoming = getincoming()
7150 source, sbranch, sother, commoninc, incoming = getincoming()
7152 else:
7151 else:
7153 source = sbranch = sother = commoninc = incoming = None
7152 source = sbranch = sother = commoninc = incoming = None
7154
7153
7155 def getoutgoing():
7154 def getoutgoing():
7156 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
7155 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
7157 dbranch = branches[0]
7156 dbranch = branches[0]
7158 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
7157 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
7159 if source != dest:
7158 if source != dest:
7160 try:
7159 try:
7161 dother = hg.peer(repo, {}, dest)
7160 dother = hg.peer(repo, {}, dest)
7162 except error.RepoError:
7161 except error.RepoError:
7163 if opts.get(b'remote'):
7162 if opts.get(b'remote'):
7164 raise
7163 raise
7165 return dest, dbranch, None, None
7164 return dest, dbranch, None, None
7166 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7165 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7167 elif sother is None:
7166 elif sother is None:
7168 # there is no explicit destination peer, but source one is invalid
7167 # there is no explicit destination peer, but source one is invalid
7169 return dest, dbranch, None, None
7168 return dest, dbranch, None, None
7170 else:
7169 else:
7171 dother = sother
7170 dother = sother
7172 if source != dest or (sbranch is not None and sbranch != dbranch):
7171 if source != dest or (sbranch is not None and sbranch != dbranch):
7173 common = None
7172 common = None
7174 else:
7173 else:
7175 common = commoninc
7174 common = commoninc
7176 if revs:
7175 if revs:
7177 revs = [repo.lookup(rev) for rev in revs]
7176 revs = [repo.lookup(rev) for rev in revs]
7178 repo.ui.pushbuffer()
7177 repo.ui.pushbuffer()
7179 outgoing = discovery.findcommonoutgoing(
7178 outgoing = discovery.findcommonoutgoing(
7180 repo, dother, onlyheads=revs, commoninc=common
7179 repo, dother, onlyheads=revs, commoninc=common
7181 )
7180 )
7182 repo.ui.popbuffer()
7181 repo.ui.popbuffer()
7183 return dest, dbranch, dother, outgoing
7182 return dest, dbranch, dother, outgoing
7184
7183
7185 if needsoutgoing:
7184 if needsoutgoing:
7186 dest, dbranch, dother, outgoing = getoutgoing()
7185 dest, dbranch, dother, outgoing = getoutgoing()
7187 else:
7186 else:
7188 dest = dbranch = dother = outgoing = None
7187 dest = dbranch = dother = outgoing = None
7189
7188
7190 if opts.get(b'remote'):
7189 if opts.get(b'remote'):
7191 t = []
7190 t = []
7192 if incoming:
7191 if incoming:
7193 t.append(_(b'1 or more incoming'))
7192 t.append(_(b'1 or more incoming'))
7194 o = outgoing.missing
7193 o = outgoing.missing
7195 if o:
7194 if o:
7196 t.append(_(b'%d outgoing') % len(o))
7195 t.append(_(b'%d outgoing') % len(o))
7197 other = dother or sother
7196 other = dother or sother
7198 if b'bookmarks' in other.listkeys(b'namespaces'):
7197 if b'bookmarks' in other.listkeys(b'namespaces'):
7199 counts = bookmarks.summary(repo, other)
7198 counts = bookmarks.summary(repo, other)
7200 if counts[0] > 0:
7199 if counts[0] > 0:
7201 t.append(_(b'%d incoming bookmarks') % counts[0])
7200 t.append(_(b'%d incoming bookmarks') % counts[0])
7202 if counts[1] > 0:
7201 if counts[1] > 0:
7203 t.append(_(b'%d outgoing bookmarks') % counts[1])
7202 t.append(_(b'%d outgoing bookmarks') % counts[1])
7204
7203
7205 if t:
7204 if t:
7206 # i18n: column positioning for "hg summary"
7205 # i18n: column positioning for "hg summary"
7207 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7206 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7208 else:
7207 else:
7209 # i18n: column positioning for "hg summary"
7208 # i18n: column positioning for "hg summary"
7210 ui.status(_(b'remote: (synced)\n'))
7209 ui.status(_(b'remote: (synced)\n'))
7211
7210
7212 cmdutil.summaryremotehooks(
7211 cmdutil.summaryremotehooks(
7213 ui,
7212 ui,
7214 repo,
7213 repo,
7215 opts,
7214 opts,
7216 (
7215 (
7217 (source, sbranch, sother, commoninc),
7216 (source, sbranch, sother, commoninc),
7218 (dest, dbranch, dother, outgoing),
7217 (dest, dbranch, dother, outgoing),
7219 ),
7218 ),
7220 )
7219 )
7221
7220
7222
7221
7223 @command(
7222 @command(
7224 b'tag',
7223 b'tag',
7225 [
7224 [
7226 (b'f', b'force', None, _(b'force tag')),
7225 (b'f', b'force', None, _(b'force tag')),
7227 (b'l', b'local', None, _(b'make the tag local')),
7226 (b'l', b'local', None, _(b'make the tag local')),
7228 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7227 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7229 (b'', b'remove', None, _(b'remove a tag')),
7228 (b'', b'remove', None, _(b'remove a tag')),
7230 # -l/--local is already there, commitopts cannot be used
7229 # -l/--local is already there, commitopts cannot be used
7231 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7230 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7232 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7231 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7233 ]
7232 ]
7234 + commitopts2,
7233 + commitopts2,
7235 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7234 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7236 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7235 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7237 )
7236 )
7238 def tag(ui, repo, name1, *names, **opts):
7237 def tag(ui, repo, name1, *names, **opts):
7239 """add one or more tags for the current or given revision
7238 """add one or more tags for the current or given revision
7240
7239
7241 Name a particular revision using <name>.
7240 Name a particular revision using <name>.
7242
7241
7243 Tags are used to name particular revisions of the repository and are
7242 Tags are used to name particular revisions of the repository and are
7244 very useful to compare different revisions, to go back to significant
7243 very useful to compare different revisions, to go back to significant
7245 earlier versions or to mark branch points as releases, etc. Changing
7244 earlier versions or to mark branch points as releases, etc. Changing
7246 an existing tag is normally disallowed; use -f/--force to override.
7245 an existing tag is normally disallowed; use -f/--force to override.
7247
7246
7248 If no revision is given, the parent of the working directory is
7247 If no revision is given, the parent of the working directory is
7249 used.
7248 used.
7250
7249
7251 To facilitate version control, distribution, and merging of tags,
7250 To facilitate version control, distribution, and merging of tags,
7252 they are stored as a file named ".hgtags" which is managed similarly
7251 they are stored as a file named ".hgtags" which is managed similarly
7253 to other project files and can be hand-edited if necessary. This
7252 to other project files and can be hand-edited if necessary. This
7254 also means that tagging creates a new commit. The file
7253 also means that tagging creates a new commit. The file
7255 ".hg/localtags" is used for local tags (not shared among
7254 ".hg/localtags" is used for local tags (not shared among
7256 repositories).
7255 repositories).
7257
7256
7258 Tag commits are usually made at the head of a branch. If the parent
7257 Tag commits are usually made at the head of a branch. If the parent
7259 of the working directory is not a branch head, :hg:`tag` aborts; use
7258 of the working directory is not a branch head, :hg:`tag` aborts; use
7260 -f/--force to force the tag commit to be based on a non-head
7259 -f/--force to force the tag commit to be based on a non-head
7261 changeset.
7260 changeset.
7262
7261
7263 See :hg:`help dates` for a list of formats valid for -d/--date.
7262 See :hg:`help dates` for a list of formats valid for -d/--date.
7264
7263
7265 Since tag names have priority over branch names during revision
7264 Since tag names have priority over branch names during revision
7266 lookup, using an existing branch name as a tag name is discouraged.
7265 lookup, using an existing branch name as a tag name is discouraged.
7267
7266
7268 Returns 0 on success.
7267 Returns 0 on success.
7269 """
7268 """
7270 opts = pycompat.byteskwargs(opts)
7269 opts = pycompat.byteskwargs(opts)
7271 with repo.wlock(), repo.lock():
7270 with repo.wlock(), repo.lock():
7272 rev_ = b"."
7271 rev_ = b"."
7273 names = [t.strip() for t in (name1,) + names]
7272 names = [t.strip() for t in (name1,) + names]
7274 if len(names) != len(set(names)):
7273 if len(names) != len(set(names)):
7275 raise error.Abort(_(b'tag names must be unique'))
7274 raise error.Abort(_(b'tag names must be unique'))
7276 for n in names:
7275 for n in names:
7277 scmutil.checknewlabel(repo, n, b'tag')
7276 scmutil.checknewlabel(repo, n, b'tag')
7278 if not n:
7277 if not n:
7279 raise error.Abort(
7278 raise error.Abort(
7280 _(b'tag names cannot consist entirely of whitespace')
7279 _(b'tag names cannot consist entirely of whitespace')
7281 )
7280 )
7282 if opts.get(b'rev') and opts.get(b'remove'):
7281 if opts.get(b'rev') and opts.get(b'remove'):
7283 raise error.Abort(_(b"--rev and --remove are incompatible"))
7282 raise error.Abort(_(b"--rev and --remove are incompatible"))
7284 if opts.get(b'rev'):
7283 if opts.get(b'rev'):
7285 rev_ = opts[b'rev']
7284 rev_ = opts[b'rev']
7286 message = opts.get(b'message')
7285 message = opts.get(b'message')
7287 if opts.get(b'remove'):
7286 if opts.get(b'remove'):
7288 if opts.get(b'local'):
7287 if opts.get(b'local'):
7289 expectedtype = b'local'
7288 expectedtype = b'local'
7290 else:
7289 else:
7291 expectedtype = b'global'
7290 expectedtype = b'global'
7292
7291
7293 for n in names:
7292 for n in names:
7294 if repo.tagtype(n) == b'global':
7293 if repo.tagtype(n) == b'global':
7295 alltags = tagsmod.findglobaltags(ui, repo)
7294 alltags = tagsmod.findglobaltags(ui, repo)
7296 if alltags[n][0] == nullid:
7295 if alltags[n][0] == nullid:
7297 raise error.Abort(_(b"tag '%s' is already removed") % n)
7296 raise error.Abort(_(b"tag '%s' is already removed") % n)
7298 if not repo.tagtype(n):
7297 if not repo.tagtype(n):
7299 raise error.Abort(_(b"tag '%s' does not exist") % n)
7298 raise error.Abort(_(b"tag '%s' does not exist") % n)
7300 if repo.tagtype(n) != expectedtype:
7299 if repo.tagtype(n) != expectedtype:
7301 if expectedtype == b'global':
7300 if expectedtype == b'global':
7302 raise error.Abort(
7301 raise error.Abort(
7303 _(b"tag '%s' is not a global tag") % n
7302 _(b"tag '%s' is not a global tag") % n
7304 )
7303 )
7305 else:
7304 else:
7306 raise error.Abort(_(b"tag '%s' is not a local tag") % n)
7305 raise error.Abort(_(b"tag '%s' is not a local tag") % n)
7307 rev_ = b'null'
7306 rev_ = b'null'
7308 if not message:
7307 if not message:
7309 # we don't translate commit messages
7308 # we don't translate commit messages
7310 message = b'Removed tag %s' % b', '.join(names)
7309 message = b'Removed tag %s' % b', '.join(names)
7311 elif not opts.get(b'force'):
7310 elif not opts.get(b'force'):
7312 for n in names:
7311 for n in names:
7313 if n in repo.tags():
7312 if n in repo.tags():
7314 raise error.Abort(
7313 raise error.Abort(
7315 _(b"tag '%s' already exists (use -f to force)") % n
7314 _(b"tag '%s' already exists (use -f to force)") % n
7316 )
7315 )
7317 if not opts.get(b'local'):
7316 if not opts.get(b'local'):
7318 p1, p2 = repo.dirstate.parents()
7317 p1, p2 = repo.dirstate.parents()
7319 if p2 != nullid:
7318 if p2 != nullid:
7320 raise error.Abort(_(b'uncommitted merge'))
7319 raise error.Abort(_(b'uncommitted merge'))
7321 bheads = repo.branchheads()
7320 bheads = repo.branchheads()
7322 if not opts.get(b'force') and bheads and p1 not in bheads:
7321 if not opts.get(b'force') and bheads and p1 not in bheads:
7323 raise error.Abort(
7322 raise error.Abort(
7324 _(
7323 _(
7325 b'working directory is not at a branch head '
7324 b'working directory is not at a branch head '
7326 b'(use -f to force)'
7325 b'(use -f to force)'
7327 )
7326 )
7328 )
7327 )
7329 node = scmutil.revsingle(repo, rev_).node()
7328 node = scmutil.revsingle(repo, rev_).node()
7330
7329
7331 if not message:
7330 if not message:
7332 # we don't translate commit messages
7331 # we don't translate commit messages
7333 message = b'Added tag %s for changeset %s' % (
7332 message = b'Added tag %s for changeset %s' % (
7334 b', '.join(names),
7333 b', '.join(names),
7335 short(node),
7334 short(node),
7336 )
7335 )
7337
7336
7338 date = opts.get(b'date')
7337 date = opts.get(b'date')
7339 if date:
7338 if date:
7340 date = dateutil.parsedate(date)
7339 date = dateutil.parsedate(date)
7341
7340
7342 if opts.get(b'remove'):
7341 if opts.get(b'remove'):
7343 editform = b'tag.remove'
7342 editform = b'tag.remove'
7344 else:
7343 else:
7345 editform = b'tag.add'
7344 editform = b'tag.add'
7346 editor = cmdutil.getcommiteditor(
7345 editor = cmdutil.getcommiteditor(
7347 editform=editform, **pycompat.strkwargs(opts)
7346 editform=editform, **pycompat.strkwargs(opts)
7348 )
7347 )
7349
7348
7350 # don't allow tagging the null rev
7349 # don't allow tagging the null rev
7351 if (
7350 if (
7352 not opts.get(b'remove')
7351 not opts.get(b'remove')
7353 and scmutil.revsingle(repo, rev_).rev() == nullrev
7352 and scmutil.revsingle(repo, rev_).rev() == nullrev
7354 ):
7353 ):
7355 raise error.Abort(_(b"cannot tag null revision"))
7354 raise error.Abort(_(b"cannot tag null revision"))
7356
7355
7357 tagsmod.tag(
7356 tagsmod.tag(
7358 repo,
7357 repo,
7359 names,
7358 names,
7360 node,
7359 node,
7361 message,
7360 message,
7362 opts.get(b'local'),
7361 opts.get(b'local'),
7363 opts.get(b'user'),
7362 opts.get(b'user'),
7364 date,
7363 date,
7365 editor=editor,
7364 editor=editor,
7366 )
7365 )
7367
7366
7368
7367
7369 @command(
7368 @command(
7370 b'tags',
7369 b'tags',
7371 formatteropts,
7370 formatteropts,
7372 b'',
7371 b'',
7373 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7372 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7374 intents={INTENT_READONLY},
7373 intents={INTENT_READONLY},
7375 )
7374 )
7376 def tags(ui, repo, **opts):
7375 def tags(ui, repo, **opts):
7377 """list repository tags
7376 """list repository tags
7378
7377
7379 This lists both regular and local tags. When the -v/--verbose
7378 This lists both regular and local tags. When the -v/--verbose
7380 switch is used, a third column "local" is printed for local tags.
7379 switch is used, a third column "local" is printed for local tags.
7381 When the -q/--quiet switch is used, only the tag name is printed.
7380 When the -q/--quiet switch is used, only the tag name is printed.
7382
7381
7383 .. container:: verbose
7382 .. container:: verbose
7384
7383
7385 Template:
7384 Template:
7386
7385
7387 The following keywords are supported in addition to the common template
7386 The following keywords are supported in addition to the common template
7388 keywords and functions such as ``{tag}``. See also
7387 keywords and functions such as ``{tag}``. See also
7389 :hg:`help templates`.
7388 :hg:`help templates`.
7390
7389
7391 :type: String. ``local`` for local tags.
7390 :type: String. ``local`` for local tags.
7392
7391
7393 Returns 0 on success.
7392 Returns 0 on success.
7394 """
7393 """
7395
7394
7396 opts = pycompat.byteskwargs(opts)
7395 opts = pycompat.byteskwargs(opts)
7397 ui.pager(b'tags')
7396 ui.pager(b'tags')
7398 fm = ui.formatter(b'tags', opts)
7397 fm = ui.formatter(b'tags', opts)
7399 hexfunc = fm.hexfunc
7398 hexfunc = fm.hexfunc
7400
7399
7401 for t, n in reversed(repo.tagslist()):
7400 for t, n in reversed(repo.tagslist()):
7402 hn = hexfunc(n)
7401 hn = hexfunc(n)
7403 label = b'tags.normal'
7402 label = b'tags.normal'
7404 tagtype = b''
7403 tagtype = b''
7405 if repo.tagtype(t) == b'local':
7404 if repo.tagtype(t) == b'local':
7406 label = b'tags.local'
7405 label = b'tags.local'
7407 tagtype = b'local'
7406 tagtype = b'local'
7408
7407
7409 fm.startitem()
7408 fm.startitem()
7410 fm.context(repo=repo)
7409 fm.context(repo=repo)
7411 fm.write(b'tag', b'%s', t, label=label)
7410 fm.write(b'tag', b'%s', t, label=label)
7412 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7411 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7413 fm.condwrite(
7412 fm.condwrite(
7414 not ui.quiet,
7413 not ui.quiet,
7415 b'rev node',
7414 b'rev node',
7416 fmt,
7415 fmt,
7417 repo.changelog.rev(n),
7416 repo.changelog.rev(n),
7418 hn,
7417 hn,
7419 label=label,
7418 label=label,
7420 )
7419 )
7421 fm.condwrite(
7420 fm.condwrite(
7422 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7421 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7423 )
7422 )
7424 fm.plain(b'\n')
7423 fm.plain(b'\n')
7425 fm.end()
7424 fm.end()
7426
7425
7427
7426
7428 @command(
7427 @command(
7429 b'tip',
7428 b'tip',
7430 [
7429 [
7431 (b'p', b'patch', None, _(b'show patch')),
7430 (b'p', b'patch', None, _(b'show patch')),
7432 (b'g', b'git', None, _(b'use git extended diff format')),
7431 (b'g', b'git', None, _(b'use git extended diff format')),
7433 ]
7432 ]
7434 + templateopts,
7433 + templateopts,
7435 _(b'[-p] [-g]'),
7434 _(b'[-p] [-g]'),
7436 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7435 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7437 )
7436 )
7438 def tip(ui, repo, **opts):
7437 def tip(ui, repo, **opts):
7439 """show the tip revision (DEPRECATED)
7438 """show the tip revision (DEPRECATED)
7440
7439
7441 The tip revision (usually just called the tip) is the changeset
7440 The tip revision (usually just called the tip) is the changeset
7442 most recently added to the repository (and therefore the most
7441 most recently added to the repository (and therefore the most
7443 recently changed head).
7442 recently changed head).
7444
7443
7445 If you have just made a commit, that commit will be the tip. If
7444 If you have just made a commit, that commit will be the tip. If
7446 you have just pulled changes from another repository, the tip of
7445 you have just pulled changes from another repository, the tip of
7447 that repository becomes the current tip. The "tip" tag is special
7446 that repository becomes the current tip. The "tip" tag is special
7448 and cannot be renamed or assigned to a different changeset.
7447 and cannot be renamed or assigned to a different changeset.
7449
7448
7450 This command is deprecated, please use :hg:`heads` instead.
7449 This command is deprecated, please use :hg:`heads` instead.
7451
7450
7452 Returns 0 on success.
7451 Returns 0 on success.
7453 """
7452 """
7454 opts = pycompat.byteskwargs(opts)
7453 opts = pycompat.byteskwargs(opts)
7455 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7454 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7456 displayer.show(repo[b'tip'])
7455 displayer.show(repo[b'tip'])
7457 displayer.close()
7456 displayer.close()
7458
7457
7459
7458
7460 @command(
7459 @command(
7461 b'unbundle',
7460 b'unbundle',
7462 [
7461 [
7463 (
7462 (
7464 b'u',
7463 b'u',
7465 b'update',
7464 b'update',
7466 None,
7465 None,
7467 _(b'update to new branch head if changesets were unbundled'),
7466 _(b'update to new branch head if changesets were unbundled'),
7468 )
7467 )
7469 ],
7468 ],
7470 _(b'[-u] FILE...'),
7469 _(b'[-u] FILE...'),
7471 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7470 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7472 )
7471 )
7473 def unbundle(ui, repo, fname1, *fnames, **opts):
7472 def unbundle(ui, repo, fname1, *fnames, **opts):
7474 """apply one or more bundle files
7473 """apply one or more bundle files
7475
7474
7476 Apply one or more bundle files generated by :hg:`bundle`.
7475 Apply one or more bundle files generated by :hg:`bundle`.
7477
7476
7478 Returns 0 on success, 1 if an update has unresolved files.
7477 Returns 0 on success, 1 if an update has unresolved files.
7479 """
7478 """
7480 fnames = (fname1,) + fnames
7479 fnames = (fname1,) + fnames
7481
7480
7482 with repo.lock():
7481 with repo.lock():
7483 for fname in fnames:
7482 for fname in fnames:
7484 f = hg.openpath(ui, fname)
7483 f = hg.openpath(ui, fname)
7485 gen = exchange.readbundle(ui, f, fname)
7484 gen = exchange.readbundle(ui, f, fname)
7486 if isinstance(gen, streamclone.streamcloneapplier):
7485 if isinstance(gen, streamclone.streamcloneapplier):
7487 raise error.Abort(
7486 raise error.Abort(
7488 _(
7487 _(
7489 b'packed bundles cannot be applied with '
7488 b'packed bundles cannot be applied with '
7490 b'"hg unbundle"'
7489 b'"hg unbundle"'
7491 ),
7490 ),
7492 hint=_(b'use "hg debugapplystreamclonebundle"'),
7491 hint=_(b'use "hg debugapplystreamclonebundle"'),
7493 )
7492 )
7494 url = b'bundle:' + fname
7493 url = b'bundle:' + fname
7495 try:
7494 try:
7496 txnname = b'unbundle'
7495 txnname = b'unbundle'
7497 if not isinstance(gen, bundle2.unbundle20):
7496 if not isinstance(gen, bundle2.unbundle20):
7498 txnname = b'unbundle\n%s' % util.hidepassword(url)
7497 txnname = b'unbundle\n%s' % util.hidepassword(url)
7499 with repo.transaction(txnname) as tr:
7498 with repo.transaction(txnname) as tr:
7500 op = bundle2.applybundle(
7499 op = bundle2.applybundle(
7501 repo, gen, tr, source=b'unbundle', url=url
7500 repo, gen, tr, source=b'unbundle', url=url
7502 )
7501 )
7503 except error.BundleUnknownFeatureError as exc:
7502 except error.BundleUnknownFeatureError as exc:
7504 raise error.Abort(
7503 raise error.Abort(
7505 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7504 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7506 hint=_(
7505 hint=_(
7507 b"see https://mercurial-scm.org/"
7506 b"see https://mercurial-scm.org/"
7508 b"wiki/BundleFeature for more "
7507 b"wiki/BundleFeature for more "
7509 b"information"
7508 b"information"
7510 ),
7509 ),
7511 )
7510 )
7512 modheads = bundle2.combinechangegroupresults(op)
7511 modheads = bundle2.combinechangegroupresults(op)
7513
7512
7514 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7513 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7515
7514
7516
7515
7517 @command(
7516 @command(
7518 b'unshelve',
7517 b'unshelve',
7519 [
7518 [
7520 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7519 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7521 (
7520 (
7522 b'c',
7521 b'c',
7523 b'continue',
7522 b'continue',
7524 None,
7523 None,
7525 _(b'continue an incomplete unshelve operation'),
7524 _(b'continue an incomplete unshelve operation'),
7526 ),
7525 ),
7527 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7526 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7528 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7527 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7529 (
7528 (
7530 b'n',
7529 b'n',
7531 b'name',
7530 b'name',
7532 b'',
7531 b'',
7533 _(b'restore shelved change with given name'),
7532 _(b'restore shelved change with given name'),
7534 _(b'NAME'),
7533 _(b'NAME'),
7535 ),
7534 ),
7536 (b't', b'tool', b'', _(b'specify merge tool')),
7535 (b't', b'tool', b'', _(b'specify merge tool')),
7537 (
7536 (
7538 b'',
7537 b'',
7539 b'date',
7538 b'date',
7540 b'',
7539 b'',
7541 _(b'set date for temporary commits (DEPRECATED)'),
7540 _(b'set date for temporary commits (DEPRECATED)'),
7542 _(b'DATE'),
7541 _(b'DATE'),
7543 ),
7542 ),
7544 ],
7543 ],
7545 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7544 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7546 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7545 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7547 )
7546 )
7548 def unshelve(ui, repo, *shelved, **opts):
7547 def unshelve(ui, repo, *shelved, **opts):
7549 """restore a shelved change to the working directory
7548 """restore a shelved change to the working directory
7550
7549
7551 This command accepts an optional name of a shelved change to
7550 This command accepts an optional name of a shelved change to
7552 restore. If none is given, the most recent shelved change is used.
7551 restore. If none is given, the most recent shelved change is used.
7553
7552
7554 If a shelved change is applied successfully, the bundle that
7553 If a shelved change is applied successfully, the bundle that
7555 contains the shelved changes is moved to a backup location
7554 contains the shelved changes is moved to a backup location
7556 (.hg/shelve-backup).
7555 (.hg/shelve-backup).
7557
7556
7558 Since you can restore a shelved change on top of an arbitrary
7557 Since you can restore a shelved change on top of an arbitrary
7559 commit, it is possible that unshelving will result in a conflict
7558 commit, it is possible that unshelving will result in a conflict
7560 between your changes and the commits you are unshelving onto. If
7559 between your changes and the commits you are unshelving onto. If
7561 this occurs, you must resolve the conflict, then use
7560 this occurs, you must resolve the conflict, then use
7562 ``--continue`` to complete the unshelve operation. (The bundle
7561 ``--continue`` to complete the unshelve operation. (The bundle
7563 will not be moved until you successfully complete the unshelve.)
7562 will not be moved until you successfully complete the unshelve.)
7564
7563
7565 (Alternatively, you can use ``--abort`` to abandon an unshelve
7564 (Alternatively, you can use ``--abort`` to abandon an unshelve
7566 that causes a conflict. This reverts the unshelved changes, and
7565 that causes a conflict. This reverts the unshelved changes, and
7567 leaves the bundle in place.)
7566 leaves the bundle in place.)
7568
7567
7569 If bare shelved change (without interactive, include and exclude
7568 If bare shelved change (without interactive, include and exclude
7570 option) was done on newly created branch it would restore branch
7569 option) was done on newly created branch it would restore branch
7571 information to the working directory.
7570 information to the working directory.
7572
7571
7573 After a successful unshelve, the shelved changes are stored in a
7572 After a successful unshelve, the shelved changes are stored in a
7574 backup directory. Only the N most recent backups are kept. N
7573 backup directory. Only the N most recent backups are kept. N
7575 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7574 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7576 configuration option.
7575 configuration option.
7577
7576
7578 .. container:: verbose
7577 .. container:: verbose
7579
7578
7580 Timestamp in seconds is used to decide order of backups. More
7579 Timestamp in seconds is used to decide order of backups. More
7581 than ``maxbackups`` backups are kept, if same timestamp
7580 than ``maxbackups`` backups are kept, if same timestamp
7582 prevents from deciding exact order of them, for safety.
7581 prevents from deciding exact order of them, for safety.
7583
7582
7584 Selected changes can be unshelved with ``--interactive`` flag.
7583 Selected changes can be unshelved with ``--interactive`` flag.
7585 The working directory is updated with the selected changes, and
7584 The working directory is updated with the selected changes, and
7586 only the unselected changes remain shelved.
7585 only the unselected changes remain shelved.
7587 Note: The whole shelve is applied to working directory first before
7586 Note: The whole shelve is applied to working directory first before
7588 running interactively. So, this will bring up all the conflicts between
7587 running interactively. So, this will bring up all the conflicts between
7589 working directory and the shelve, irrespective of which changes will be
7588 working directory and the shelve, irrespective of which changes will be
7590 unshelved.
7589 unshelved.
7591 """
7590 """
7592 with repo.wlock():
7591 with repo.wlock():
7593 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7592 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7594
7593
7595
7594
7596 statemod.addunfinished(
7595 statemod.addunfinished(
7597 b'unshelve',
7596 b'unshelve',
7598 fname=b'shelvedstate',
7597 fname=b'shelvedstate',
7599 continueflag=True,
7598 continueflag=True,
7600 abortfunc=shelvemod.hgabortunshelve,
7599 abortfunc=shelvemod.hgabortunshelve,
7601 continuefunc=shelvemod.hgcontinueunshelve,
7600 continuefunc=shelvemod.hgcontinueunshelve,
7602 cmdmsg=_(b'unshelve already in progress'),
7601 cmdmsg=_(b'unshelve already in progress'),
7603 )
7602 )
7604
7603
7605
7604
7606 @command(
7605 @command(
7607 b'update|up|checkout|co',
7606 b'update|up|checkout|co',
7608 [
7607 [
7609 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7608 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7610 (b'c', b'check', None, _(b'require clean working directory')),
7609 (b'c', b'check', None, _(b'require clean working directory')),
7611 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7610 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7612 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7611 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7613 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7612 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7614 ]
7613 ]
7615 + mergetoolopts,
7614 + mergetoolopts,
7616 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7615 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7617 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7616 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7618 helpbasic=True,
7617 helpbasic=True,
7619 )
7618 )
7620 def update(ui, repo, node=None, **opts):
7619 def update(ui, repo, node=None, **opts):
7621 """update working directory (or switch revisions)
7620 """update working directory (or switch revisions)
7622
7621
7623 Update the repository's working directory to the specified
7622 Update the repository's working directory to the specified
7624 changeset. If no changeset is specified, update to the tip of the
7623 changeset. If no changeset is specified, update to the tip of the
7625 current named branch and move the active bookmark (see :hg:`help
7624 current named branch and move the active bookmark (see :hg:`help
7626 bookmarks`).
7625 bookmarks`).
7627
7626
7628 Update sets the working directory's parent revision to the specified
7627 Update sets the working directory's parent revision to the specified
7629 changeset (see :hg:`help parents`).
7628 changeset (see :hg:`help parents`).
7630
7629
7631 If the changeset is not a descendant or ancestor of the working
7630 If the changeset is not a descendant or ancestor of the working
7632 directory's parent and there are uncommitted changes, the update is
7631 directory's parent and there are uncommitted changes, the update is
7633 aborted. With the -c/--check option, the working directory is checked
7632 aborted. With the -c/--check option, the working directory is checked
7634 for uncommitted changes; if none are found, the working directory is
7633 for uncommitted changes; if none are found, the working directory is
7635 updated to the specified changeset.
7634 updated to the specified changeset.
7636
7635
7637 .. container:: verbose
7636 .. container:: verbose
7638
7637
7639 The -C/--clean, -c/--check, and -m/--merge options control what
7638 The -C/--clean, -c/--check, and -m/--merge options control what
7640 happens if the working directory contains uncommitted changes.
7639 happens if the working directory contains uncommitted changes.
7641 At most of one of them can be specified.
7640 At most of one of them can be specified.
7642
7641
7643 1. If no option is specified, and if
7642 1. If no option is specified, and if
7644 the requested changeset is an ancestor or descendant of
7643 the requested changeset is an ancestor or descendant of
7645 the working directory's parent, the uncommitted changes
7644 the working directory's parent, the uncommitted changes
7646 are merged into the requested changeset and the merged
7645 are merged into the requested changeset and the merged
7647 result is left uncommitted. If the requested changeset is
7646 result is left uncommitted. If the requested changeset is
7648 not an ancestor or descendant (that is, it is on another
7647 not an ancestor or descendant (that is, it is on another
7649 branch), the update is aborted and the uncommitted changes
7648 branch), the update is aborted and the uncommitted changes
7650 are preserved.
7649 are preserved.
7651
7650
7652 2. With the -m/--merge option, the update is allowed even if the
7651 2. With the -m/--merge option, the update is allowed even if the
7653 requested changeset is not an ancestor or descendant of
7652 requested changeset is not an ancestor or descendant of
7654 the working directory's parent.
7653 the working directory's parent.
7655
7654
7656 3. With the -c/--check option, the update is aborted and the
7655 3. With the -c/--check option, the update is aborted and the
7657 uncommitted changes are preserved.
7656 uncommitted changes are preserved.
7658
7657
7659 4. With the -C/--clean option, uncommitted changes are discarded and
7658 4. With the -C/--clean option, uncommitted changes are discarded and
7660 the working directory is updated to the requested changeset.
7659 the working directory is updated to the requested changeset.
7661
7660
7662 To cancel an uncommitted merge (and lose your changes), use
7661 To cancel an uncommitted merge (and lose your changes), use
7663 :hg:`merge --abort`.
7662 :hg:`merge --abort`.
7664
7663
7665 Use null as the changeset to remove the working directory (like
7664 Use null as the changeset to remove the working directory (like
7666 :hg:`clone -U`).
7665 :hg:`clone -U`).
7667
7666
7668 If you want to revert just one file to an older revision, use
7667 If you want to revert just one file to an older revision, use
7669 :hg:`revert [-r REV] NAME`.
7668 :hg:`revert [-r REV] NAME`.
7670
7669
7671 See :hg:`help dates` for a list of formats valid for -d/--date.
7670 See :hg:`help dates` for a list of formats valid for -d/--date.
7672
7671
7673 Returns 0 on success, 1 if there are unresolved files.
7672 Returns 0 on success, 1 if there are unresolved files.
7674 """
7673 """
7675 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7674 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7676 rev = opts.get('rev')
7675 rev = opts.get('rev')
7677 date = opts.get('date')
7676 date = opts.get('date')
7678 clean = opts.get('clean')
7677 clean = opts.get('clean')
7679 check = opts.get('check')
7678 check = opts.get('check')
7680 merge = opts.get('merge')
7679 merge = opts.get('merge')
7681 if rev and node:
7680 if rev and node:
7682 raise error.Abort(_(b"please specify just one revision"))
7681 raise error.Abort(_(b"please specify just one revision"))
7683
7682
7684 if ui.configbool(b'commands', b'update.requiredest'):
7683 if ui.configbool(b'commands', b'update.requiredest'):
7685 if not node and not rev and not date:
7684 if not node and not rev and not date:
7686 raise error.Abort(
7685 raise error.Abort(
7687 _(b'you must specify a destination'),
7686 _(b'you must specify a destination'),
7688 hint=_(b'for example: hg update ".::"'),
7687 hint=_(b'for example: hg update ".::"'),
7689 )
7688 )
7690
7689
7691 if rev is None or rev == b'':
7690 if rev is None or rev == b'':
7692 rev = node
7691 rev = node
7693
7692
7694 if date and rev is not None:
7693 if date and rev is not None:
7695 raise error.Abort(_(b"you can't specify a revision and a date"))
7694 raise error.Abort(_(b"you can't specify a revision and a date"))
7696
7695
7697 updatecheck = None
7696 updatecheck = None
7698 if check:
7697 if check:
7699 updatecheck = b'abort'
7698 updatecheck = b'abort'
7700 elif merge:
7699 elif merge:
7701 updatecheck = b'none'
7700 updatecheck = b'none'
7702
7701
7703 with repo.wlock():
7702 with repo.wlock():
7704 cmdutil.clearunfinished(repo)
7703 cmdutil.clearunfinished(repo)
7705 if date:
7704 if date:
7706 rev = cmdutil.finddate(ui, repo, date)
7705 rev = cmdutil.finddate(ui, repo, date)
7707
7706
7708 # if we defined a bookmark, we have to remember the original name
7707 # if we defined a bookmark, we have to remember the original name
7709 brev = rev
7708 brev = rev
7710 if rev:
7709 if rev:
7711 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7710 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7712 ctx = scmutil.revsingle(repo, rev, default=None)
7711 ctx = scmutil.revsingle(repo, rev, default=None)
7713 rev = ctx.rev()
7712 rev = ctx.rev()
7714 hidden = ctx.hidden()
7713 hidden = ctx.hidden()
7715 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7714 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7716 with ui.configoverride(overrides, b'update'):
7715 with ui.configoverride(overrides, b'update'):
7717 ret = hg.updatetotally(
7716 ret = hg.updatetotally(
7718 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7717 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7719 )
7718 )
7720 if hidden:
7719 if hidden:
7721 ctxstr = ctx.hex()[:12]
7720 ctxstr = ctx.hex()[:12]
7722 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7721 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7723
7722
7724 if ctx.obsolete():
7723 if ctx.obsolete():
7725 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7724 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7726 ui.warn(b"(%s)\n" % obsfatemsg)
7725 ui.warn(b"(%s)\n" % obsfatemsg)
7727 return ret
7726 return ret
7728
7727
7729
7728
7730 @command(
7729 @command(
7731 b'verify',
7730 b'verify',
7732 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7731 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7733 helpcategory=command.CATEGORY_MAINTENANCE,
7732 helpcategory=command.CATEGORY_MAINTENANCE,
7734 )
7733 )
7735 def verify(ui, repo, **opts):
7734 def verify(ui, repo, **opts):
7736 """verify the integrity of the repository
7735 """verify the integrity of the repository
7737
7736
7738 Verify the integrity of the current repository.
7737 Verify the integrity of the current repository.
7739
7738
7740 This will perform an extensive check of the repository's
7739 This will perform an extensive check of the repository's
7741 integrity, validating the hashes and checksums of each entry in
7740 integrity, validating the hashes and checksums of each entry in
7742 the changelog, manifest, and tracked files, as well as the
7741 the changelog, manifest, and tracked files, as well as the
7743 integrity of their crosslinks and indices.
7742 integrity of their crosslinks and indices.
7744
7743
7745 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7744 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7746 for more information about recovery from corruption of the
7745 for more information about recovery from corruption of the
7747 repository.
7746 repository.
7748
7747
7749 Returns 0 on success, 1 if errors are encountered.
7748 Returns 0 on success, 1 if errors are encountered.
7750 """
7749 """
7751 opts = pycompat.byteskwargs(opts)
7750 opts = pycompat.byteskwargs(opts)
7752
7751
7753 level = None
7752 level = None
7754 if opts[b'full']:
7753 if opts[b'full']:
7755 level = verifymod.VERIFY_FULL
7754 level = verifymod.VERIFY_FULL
7756 return hg.verify(repo, level)
7755 return hg.verify(repo, level)
7757
7756
7758
7757
7759 @command(
7758 @command(
7760 b'version',
7759 b'version',
7761 [] + formatteropts,
7760 [] + formatteropts,
7762 helpcategory=command.CATEGORY_HELP,
7761 helpcategory=command.CATEGORY_HELP,
7763 norepo=True,
7762 norepo=True,
7764 intents={INTENT_READONLY},
7763 intents={INTENT_READONLY},
7765 )
7764 )
7766 def version_(ui, **opts):
7765 def version_(ui, **opts):
7767 """output version and copyright information
7766 """output version and copyright information
7768
7767
7769 .. container:: verbose
7768 .. container:: verbose
7770
7769
7771 Template:
7770 Template:
7772
7771
7773 The following keywords are supported. See also :hg:`help templates`.
7772 The following keywords are supported. See also :hg:`help templates`.
7774
7773
7775 :extensions: List of extensions.
7774 :extensions: List of extensions.
7776 :ver: String. Version number.
7775 :ver: String. Version number.
7777
7776
7778 And each entry of ``{extensions}`` provides the following sub-keywords
7777 And each entry of ``{extensions}`` provides the following sub-keywords
7779 in addition to ``{ver}``.
7778 in addition to ``{ver}``.
7780
7779
7781 :bundled: Boolean. True if included in the release.
7780 :bundled: Boolean. True if included in the release.
7782 :name: String. Extension name.
7781 :name: String. Extension name.
7783 """
7782 """
7784 opts = pycompat.byteskwargs(opts)
7783 opts = pycompat.byteskwargs(opts)
7785 if ui.verbose:
7784 if ui.verbose:
7786 ui.pager(b'version')
7785 ui.pager(b'version')
7787 fm = ui.formatter(b"version", opts)
7786 fm = ui.formatter(b"version", opts)
7788 fm.startitem()
7787 fm.startitem()
7789 fm.write(
7788 fm.write(
7790 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7789 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7791 )
7790 )
7792 license = _(
7791 license = _(
7793 b"(see https://mercurial-scm.org for more information)\n"
7792 b"(see https://mercurial-scm.org for more information)\n"
7794 b"\nCopyright (C) 2005-2020 Matt Mackall and others\n"
7793 b"\nCopyright (C) 2005-2020 Matt Mackall and others\n"
7795 b"This is free software; see the source for copying conditions. "
7794 b"This is free software; see the source for copying conditions. "
7796 b"There is NO\nwarranty; "
7795 b"There is NO\nwarranty; "
7797 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7796 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7798 )
7797 )
7799 if not ui.quiet:
7798 if not ui.quiet:
7800 fm.plain(license)
7799 fm.plain(license)
7801
7800
7802 if ui.verbose:
7801 if ui.verbose:
7803 fm.plain(_(b"\nEnabled extensions:\n\n"))
7802 fm.plain(_(b"\nEnabled extensions:\n\n"))
7804 # format names and versions into columns
7803 # format names and versions into columns
7805 names = []
7804 names = []
7806 vers = []
7805 vers = []
7807 isinternals = []
7806 isinternals = []
7808 for name, module in extensions.extensions():
7807 for name, module in extensions.extensions():
7809 names.append(name)
7808 names.append(name)
7810 vers.append(extensions.moduleversion(module) or None)
7809 vers.append(extensions.moduleversion(module) or None)
7811 isinternals.append(extensions.ismoduleinternal(module))
7810 isinternals.append(extensions.ismoduleinternal(module))
7812 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7811 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7813 if names:
7812 if names:
7814 namefmt = b" %%-%ds " % max(len(n) for n in names)
7813 namefmt = b" %%-%ds " % max(len(n) for n in names)
7815 places = [_(b"external"), _(b"internal")]
7814 places = [_(b"external"), _(b"internal")]
7816 for n, v, p in zip(names, vers, isinternals):
7815 for n, v, p in zip(names, vers, isinternals):
7817 fn.startitem()
7816 fn.startitem()
7818 fn.condwrite(ui.verbose, b"name", namefmt, n)
7817 fn.condwrite(ui.verbose, b"name", namefmt, n)
7819 if ui.verbose:
7818 if ui.verbose:
7820 fn.plain(b"%s " % places[p])
7819 fn.plain(b"%s " % places[p])
7821 fn.data(bundled=p)
7820 fn.data(bundled=p)
7822 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7821 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7823 if ui.verbose:
7822 if ui.verbose:
7824 fn.plain(b"\n")
7823 fn.plain(b"\n")
7825 fn.end()
7824 fn.end()
7826 fm.end()
7825 fm.end()
7827
7826
7828
7827
7829 def loadcmdtable(ui, name, cmdtable):
7828 def loadcmdtable(ui, name, cmdtable):
7830 """Load command functions from specified cmdtable
7829 """Load command functions from specified cmdtable
7831 """
7830 """
7832 overrides = [cmd for cmd in cmdtable if cmd in table]
7831 overrides = [cmd for cmd in cmdtable if cmd in table]
7833 if overrides:
7832 if overrides:
7834 ui.warn(
7833 ui.warn(
7835 _(b"extension '%s' overrides commands: %s\n")
7834 _(b"extension '%s' overrides commands: %s\n")
7836 % (name, b" ".join(overrides))
7835 % (name, b" ".join(overrides))
7837 )
7836 )
7838 table.update(cmdtable)
7837 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
17 $ hg log
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 changeset: 30:ed2d2f24b11c
24 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 changeset: 29:b5bd63375ab9
29 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 changeset: 28:8e0c2264c8af
34 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 changeset: 27:288867a866e9
39 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 changeset: 26:3efc6fd51aeb
44 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 changeset: 25:02a84173a97a
49 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 changeset: 24:10e0acd3809e
54 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 changeset: 23:5ec79163bff4
59 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 changeset: 22:06c7993750ce
64 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 changeset: 21:e5db6aa3fe2a
69 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 changeset: 20:7128fb4fdbc9
74 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 changeset: 19:52798545b482
79 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 changeset: 18:86977a90077e
84 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 changeset: 17:03515f4a9080
89 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 changeset: 16:a2e6ea4973e9
94 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 changeset: 15:e7fa0811edb0
99 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 changeset: 14:ce8f0998e922
104 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 changeset: 13:9d7d07bc967c
109 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 changeset: 12:1941b52820a5
114 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 changeset: 11:7b4cd9578619
119 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 changeset: 10:7c5eff49a6b6
124 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 changeset: 9:eb44510ef29a
129 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 changeset: 8:453eb4dba229
134 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 changeset: 7:03750880c6b5
139 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 changeset: 6:a3d5c6fdf0d3
144 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 changeset: 5:7874a09ea728
149 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 changeset: 4:9b2ba8336a65
154 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 changeset: 3:b53bea5e2fcb
159 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 changeset: 2:db07c04beaca
164 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 changeset: 1:5cd978ea5149
169 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 changeset: 0:b99c7b9c8e11
174 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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 [255]
367 [255]
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 (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 (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 (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 (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 (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: good
477 abort: cannot bisect (no known bad revisions)
477 abort: cannot bisect (no known bad revisions)
478 [255]
478 [255]
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: bad
482 changeset 15:e7fa0811edb0: good
482 changeset 15:e7fa0811edb0: good
483 changeset 7:03750880c6b5: good
483 changeset 7:03750880c6b5: good
484 changeset 3:b53bea5e2fcb: bad
484 changeset 3:b53bea5e2fcb: bad
485 changeset 5:7874a09ea728: bad
485 changeset 5:7874a09ea728: bad
486 changeset 6:a3d5c6fdf0d3: good
486 changeset 6:a3d5c6fdf0d3: 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 (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: good
516 changeset 7:03750880c6b5: good
516 changeset 7:03750880c6b5: good
517 changeset 3:b53bea5e2fcb: bad
517 changeset 3:b53bea5e2fcb: bad
518 changeset 5:7874a09ea728: bad
518 changeset 5:7874a09ea728: bad
519 changeset 6:a3d5c6fdf0d3: good
519 changeset 6:a3d5c6fdf0d3: 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: good
547 abort: cannot bisect (no known bad revisions)
547 abort: cannot bisect (no known bad revisions)
548 [255]
548 [255]
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: bad
552 changeset 15:e7fa0811edb0: good
552 changeset 15:e7fa0811edb0: good
553 changeset 7:03750880c6b5: good
553 changeset 7:03750880c6b5: good
554 changeset 3:b53bea5e2fcb: bad
554 changeset 3:b53bea5e2fcb: bad
555 changeset 5:7874a09ea728: bad
555 changeset 5:7874a09ea728: bad
556 changeset 6:a3d5c6fdf0d3: good
556 changeset 6:a3d5c6fdf0d3: 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 [255]
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 (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: good
593 changeset 26:3efc6fd51aeb: good
593 changeset 26:3efc6fd51aeb: good
594 changeset 28:8e0c2264c8af: good
594 changeset 28:8e0c2264c8af: good
595 changeset 29:b5bd63375ab9: good
595 changeset 29:b5bd63375ab9: 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 (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: good
742 changeset 26:3efc6fd51aeb: good
742 changeset 26:3efc6fd51aeb: 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 [255]
754 [255]
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 [255]
757 [255]
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 [255]
760 [255]
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 [255]
763 [255]
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 [255]
766 [255]
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 [255]
769 [255]
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 [255]
772 [255]
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 [255]
775 [255]
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 [255]
778 [255]
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 [255]
781 [255]
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 [255]
784 [255]
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 [255]
787 [255]
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 [255]
790 [255]
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 [255]
793 [255]
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 [255]
796 [255]
@@ -1,456 +1,456 b''
1 #testcases filelog compatibility changeset sidedata
1 #testcases filelog compatibility changeset sidedata
2
2
3 $ cat >> $HGRCPATH << EOF
3 $ cat >> $HGRCPATH << EOF
4 > [extensions]
4 > [extensions]
5 > rebase=
5 > rebase=
6 > [alias]
6 > [alias]
7 > l = log -G -T '{rev} {desc}\n{files}\n'
7 > l = log -G -T '{rev} {desc}\n{files}\n'
8 > EOF
8 > EOF
9
9
10 #if compatibility
10 #if compatibility
11 $ cat >> $HGRCPATH << EOF
11 $ cat >> $HGRCPATH << EOF
12 > [experimental]
12 > [experimental]
13 > copies.read-from = compatibility
13 > copies.read-from = compatibility
14 > EOF
14 > EOF
15 #endif
15 #endif
16
16
17 #if changeset
17 #if changeset
18 $ cat >> $HGRCPATH << EOF
18 $ cat >> $HGRCPATH << EOF
19 > [experimental]
19 > [experimental]
20 > copies.read-from = changeset-only
20 > copies.read-from = changeset-only
21 > copies.write-to = changeset-only
21 > copies.write-to = changeset-only
22 > EOF
22 > EOF
23 #endif
23 #endif
24
24
25 #if sidedata
25 #if sidedata
26 $ cat >> $HGRCPATH << EOF
26 $ cat >> $HGRCPATH << EOF
27 > [format]
27 > [format]
28 > exp-use-copies-side-data-changeset = yes
28 > exp-use-copies-side-data-changeset = yes
29 > EOF
29 > EOF
30 #endif
30 #endif
31
31
32 $ REPONUM=0
32 $ REPONUM=0
33 $ newrepo() {
33 $ newrepo() {
34 > cd $TESTTMP
34 > cd $TESTTMP
35 > REPONUM=`expr $REPONUM + 1`
35 > REPONUM=`expr $REPONUM + 1`
36 > hg init repo-$REPONUM
36 > hg init repo-$REPONUM
37 > cd repo-$REPONUM
37 > cd repo-$REPONUM
38 > }
38 > }
39
39
40 Copy a file, then delete destination, then copy again. This does not create a new filelog entry.
40 Copy a file, then delete destination, then copy again. This does not create a new filelog entry.
41 $ newrepo
41 $ newrepo
42 $ echo x > x
42 $ echo x > x
43 $ hg ci -Aqm 'add x'
43 $ hg ci -Aqm 'add x'
44 $ echo x2 > x
44 $ echo x2 > x
45 $ hg ci -m 'modify x'
45 $ hg ci -m 'modify x'
46 $ hg co -q 0
46 $ hg co -q 0
47 $ hg cp x y
47 $ hg cp x y
48 $ hg ci -qm 'copy x to y'
48 $ hg ci -qm 'copy x to y'
49 $ hg rm y
49 $ hg rm y
50 $ hg ci -m 'remove y'
50 $ hg ci -m 'remove y'
51 $ hg cp -f x y
51 $ hg cp -f x y
52 $ hg ci -m 'copy x onto y (again)'
52 $ hg ci -m 'copy x onto y (again)'
53 $ hg l
53 $ hg l
54 @ 4 copy x onto y (again)
54 @ 4 copy x onto y (again)
55 | y
55 | y
56 o 3 remove y
56 o 3 remove y
57 | y
57 | y
58 o 2 copy x to y
58 o 2 copy x to y
59 | y
59 | y
60 | o 1 modify x
60 | o 1 modify x
61 |/ x
61 |/ x
62 o 0 add x
62 o 0 add x
63 x
63 x
64 $ hg debugp1copies -r 4
64 $ hg debugp1copies -r 4
65 x -> y
65 x -> y
66 $ hg debugpathcopies 0 4
66 $ hg debugpathcopies 0 4
67 x -> y
67 x -> y
68 $ hg graft -r 1
68 $ hg graft -r 1
69 grafting 1:* "modify x" (glob)
69 grafting 1:* "modify x" (glob)
70 merging y and x to y
70 merging y and x to y
71 $ hg co -qC 1
71 $ hg co -qC 1
72 $ hg graft -r 4
72 $ hg graft -r 4
73 grafting 4:* "copy x onto y (again)" (glob)
73 grafting 4:* "copy x onto y (again)" (glob)
74 merging x and y to y
74 merging x and y to y
75
75
76 Copy x to y, then remove y, then add back y. With copy metadata in the
76 Copy x to y, then remove y, then add back y. With copy metadata in the
77 changeset, this could easily end up reporting y as copied from x (if we don't
77 changeset, this could easily end up reporting y as copied from x (if we don't
78 unmark it as a copy when it's removed). Despite x and y not being related, we
78 unmark it as a copy when it's removed). Despite x and y not being related, we
79 want grafts to propagate across the rename.
79 want grafts to propagate across the rename.
80 $ newrepo
80 $ newrepo
81 $ echo x > x
81 $ echo x > x
82 $ hg ci -Aqm 'add x'
82 $ hg ci -Aqm 'add x'
83 $ echo x2 > x
83 $ echo x2 > x
84 $ hg ci -m 'modify x'
84 $ hg ci -m 'modify x'
85 $ hg co -q 0
85 $ hg co -q 0
86 $ hg mv x y
86 $ hg mv x y
87 $ hg ci -qm 'rename x to y'
87 $ hg ci -qm 'rename x to y'
88 $ hg rm y
88 $ hg rm y
89 $ hg ci -qm 'remove y'
89 $ hg ci -qm 'remove y'
90 $ echo x > y
90 $ echo x > y
91 $ hg ci -Aqm 'add back y'
91 $ hg ci -Aqm 'add back y'
92 $ hg l
92 $ hg l
93 @ 4 add back y
93 @ 4 add back y
94 | y
94 | y
95 o 3 remove y
95 o 3 remove y
96 | y
96 | y
97 o 2 rename x to y
97 o 2 rename x to y
98 | x y
98 | x y
99 | o 1 modify x
99 | o 1 modify x
100 |/ x
100 |/ x
101 o 0 add x
101 o 0 add x
102 x
102 x
103 $ hg debugpathcopies 0 4
103 $ hg debugpathcopies 0 4
104 BROKEN: This should succeed and merge the changes from x into y
104 BROKEN: This should succeed and merge the changes from x into y
105 $ hg graft -r 1
105 $ hg graft -r 1
106 grafting 1:* "modify x" (glob)
106 grafting 1:* "modify x" (glob)
107 file 'x' was deleted in local [local] but was modified in other [graft].
107 file 'x' was deleted in local [local] but was modified in other [graft].
108 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
108 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
109 What do you want to do? u
109 What do you want to do? u
110 abort: unresolved conflicts, can't continue
110 abort: unresolved conflicts, can't continue
111 (use 'hg resolve' and 'hg graft --continue')
111 (use 'hg resolve' and 'hg graft --continue')
112 [255]
112 [1]
113
113
114 Add x, remove it, then add it back, then rename x to y. Similar to the case
114 Add x, remove it, then add it back, then rename x to y. Similar to the case
115 above, but here the break in history is before the rename.
115 above, but here the break in history is before the rename.
116 $ newrepo
116 $ newrepo
117 $ echo x > x
117 $ echo x > x
118 $ hg ci -Aqm 'add x'
118 $ hg ci -Aqm 'add x'
119 $ echo x2 > x
119 $ echo x2 > x
120 $ hg ci -m 'modify x'
120 $ hg ci -m 'modify x'
121 $ hg co -q 0
121 $ hg co -q 0
122 $ hg rm x
122 $ hg rm x
123 $ hg ci -qm 'remove x'
123 $ hg ci -qm 'remove x'
124 $ echo x > x
124 $ echo x > x
125 $ hg ci -Aqm 'add x again'
125 $ hg ci -Aqm 'add x again'
126 $ hg mv x y
126 $ hg mv x y
127 $ hg ci -m 'rename x to y'
127 $ hg ci -m 'rename x to y'
128 $ hg l
128 $ hg l
129 @ 4 rename x to y
129 @ 4 rename x to y
130 | x y
130 | x y
131 o 3 add x again
131 o 3 add x again
132 | x
132 | x
133 o 2 remove x
133 o 2 remove x
134 | x
134 | x
135 | o 1 modify x
135 | o 1 modify x
136 |/ x
136 |/ x
137 o 0 add x
137 o 0 add x
138 x
138 x
139 $ hg debugpathcopies 0 4
139 $ hg debugpathcopies 0 4
140 x -> y
140 x -> y
141 $ hg graft -r 1
141 $ hg graft -r 1
142 grafting 1:* "modify x" (glob)
142 grafting 1:* "modify x" (glob)
143 merging y and x to y
143 merging y and x to y
144 $ hg co -qC 1
144 $ hg co -qC 1
145 $ hg graft -r 4
145 $ hg graft -r 4
146 grafting 4:* "rename x to y" (glob)
146 grafting 4:* "rename x to y" (glob)
147 merging x and y to y
147 merging x and y to y
148
148
149 Add x, modify it, remove it, then add it back, then rename x to y. Similar to
149 Add x, modify it, remove it, then add it back, then rename x to y. Similar to
150 the case above, but here the re-added file's nodeid is different from before
150 the case above, but here the re-added file's nodeid is different from before
151 the break.
151 the break.
152
152
153 $ newrepo
153 $ newrepo
154 $ echo x > x
154 $ echo x > x
155 $ hg ci -Aqm 'add x'
155 $ hg ci -Aqm 'add x'
156 $ echo x2 > x
156 $ echo x2 > x
157 $ hg ci -m 'modify x'
157 $ hg ci -m 'modify x'
158 $ echo x3 > x
158 $ echo x3 > x
159 $ hg ci -qm 'modify x again'
159 $ hg ci -qm 'modify x again'
160 $ hg co -q 1
160 $ hg co -q 1
161 $ hg rm x
161 $ hg rm x
162 $ hg ci -qm 'remove x'
162 $ hg ci -qm 'remove x'
163 # Same content to avoid conflicts
163 # Same content to avoid conflicts
164 $ hg revert -r 1 x
164 $ hg revert -r 1 x
165 $ hg ci -Aqm 'add x again'
165 $ hg ci -Aqm 'add x again'
166 $ hg mv x y
166 $ hg mv x y
167 $ hg ci -m 'rename x to y'
167 $ hg ci -m 'rename x to y'
168 $ hg l
168 $ hg l
169 @ 5 rename x to y
169 @ 5 rename x to y
170 | x y
170 | x y
171 o 4 add x again
171 o 4 add x again
172 | x
172 | x
173 o 3 remove x
173 o 3 remove x
174 | x
174 | x
175 | o 2 modify x again
175 | o 2 modify x again
176 |/ x
176 |/ x
177 o 1 modify x
177 o 1 modify x
178 | x
178 | x
179 o 0 add x
179 o 0 add x
180 x
180 x
181 $ hg debugpathcopies 0 5
181 $ hg debugpathcopies 0 5
182 x -> y (no-filelog !)
182 x -> y (no-filelog !)
183 #if no-filelog
183 #if no-filelog
184 $ hg graft -r 2
184 $ hg graft -r 2
185 grafting 2:* "modify x again" (glob)
185 grafting 2:* "modify x again" (glob)
186 merging y and x to y
186 merging y and x to y
187 #else
187 #else
188 BROKEN: This should succeed and merge the changes from x into y
188 BROKEN: This should succeed and merge the changes from x into y
189 $ hg graft -r 2
189 $ hg graft -r 2
190 grafting 2:* "modify x again" (glob)
190 grafting 2:* "modify x again" (glob)
191 file 'x' was deleted in local [local] but was modified in other [graft].
191 file 'x' was deleted in local [local] but was modified in other [graft].
192 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
192 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
193 What do you want to do? u
193 What do you want to do? u
194 abort: unresolved conflicts, can't continue
194 abort: unresolved conflicts, can't continue
195 (use 'hg resolve' and 'hg graft --continue')
195 (use 'hg resolve' and 'hg graft --continue')
196 [255]
196 [1]
197 #endif
197 #endif
198 $ hg co -qC 2
198 $ hg co -qC 2
199 BROKEN: This should succeed and merge the changes from x into y
199 BROKEN: This should succeed and merge the changes from x into y
200 $ hg graft -r 5
200 $ hg graft -r 5
201 grafting 5:* "rename x to y"* (glob)
201 grafting 5:* "rename x to y"* (glob)
202 file 'x' was deleted in other [graft] but was modified in local [local].
202 file 'x' was deleted in other [graft] but was modified in local [local].
203 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
203 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
204 What do you want to do? u
204 What do you want to do? u
205 abort: unresolved conflicts, can't continue
205 abort: unresolved conflicts, can't continue
206 (use 'hg resolve' and 'hg graft --continue')
206 (use 'hg resolve' and 'hg graft --continue')
207 [255]
207 [1]
208
208
209 Add x, remove it, then add it back, rename x to y from the first commit.
209 Add x, remove it, then add it back, rename x to y from the first commit.
210 Similar to the case above, but here the break in history is parallel to the
210 Similar to the case above, but here the break in history is parallel to the
211 rename.
211 rename.
212 $ newrepo
212 $ newrepo
213 $ echo x > x
213 $ echo x > x
214 $ hg ci -Aqm 'add x'
214 $ hg ci -Aqm 'add x'
215 $ hg rm x
215 $ hg rm x
216 $ hg ci -qm 'remove x'
216 $ hg ci -qm 'remove x'
217 $ echo x > x
217 $ echo x > x
218 $ hg ci -Aqm 'add x again'
218 $ hg ci -Aqm 'add x again'
219 $ echo x2 > x
219 $ echo x2 > x
220 $ hg ci -m 'modify x'
220 $ hg ci -m 'modify x'
221 $ hg co -q 0
221 $ hg co -q 0
222 $ hg mv x y
222 $ hg mv x y
223 $ hg ci -qm 'rename x to y'
223 $ hg ci -qm 'rename x to y'
224 $ hg l
224 $ hg l
225 @ 4 rename x to y
225 @ 4 rename x to y
226 | x y
226 | x y
227 | o 3 modify x
227 | o 3 modify x
228 | | x
228 | | x
229 | o 2 add x again
229 | o 2 add x again
230 | | x
230 | | x
231 | o 1 remove x
231 | o 1 remove x
232 |/ x
232 |/ x
233 o 0 add x
233 o 0 add x
234 x
234 x
235 $ hg debugpathcopies 2 4
235 $ hg debugpathcopies 2 4
236 x -> y
236 x -> y
237 $ hg graft -r 3
237 $ hg graft -r 3
238 grafting 3:* "modify x" (glob)
238 grafting 3:* "modify x" (glob)
239 merging y and x to y
239 merging y and x to y
240 $ hg co -qC 3
240 $ hg co -qC 3
241 $ hg graft -r 4
241 $ hg graft -r 4
242 grafting 4:* "rename x to y" (glob)
242 grafting 4:* "rename x to y" (glob)
243 merging x and y to y
243 merging x and y to y
244
244
245 Add x, remove it, then add it back, rename x to y from the first commit.
245 Add x, remove it, then add it back, rename x to y from the first commit.
246 Similar to the case above, but here the re-added file's nodeid is different
246 Similar to the case above, but here the re-added file's nodeid is different
247 from the base.
247 from the base.
248 $ newrepo
248 $ newrepo
249 $ echo x > x
249 $ echo x > x
250 $ hg ci -Aqm 'add x'
250 $ hg ci -Aqm 'add x'
251 $ hg rm x
251 $ hg rm x
252 $ hg ci -qm 'remove x'
252 $ hg ci -qm 'remove x'
253 $ echo x2 > x
253 $ echo x2 > x
254 $ hg ci -Aqm 'add x again with different content'
254 $ hg ci -Aqm 'add x again with different content'
255 $ hg co -q 0
255 $ hg co -q 0
256 $ hg mv x y
256 $ hg mv x y
257 $ hg ci -qm 'rename x to y'
257 $ hg ci -qm 'rename x to y'
258 $ hg l
258 $ hg l
259 @ 3 rename x to y
259 @ 3 rename x to y
260 | x y
260 | x y
261 | o 2 add x again with different content
261 | o 2 add x again with different content
262 | | x
262 | | x
263 | o 1 remove x
263 | o 1 remove x
264 |/ x
264 |/ x
265 o 0 add x
265 o 0 add x
266 x
266 x
267 $ hg debugpathcopies 2 3
267 $ hg debugpathcopies 2 3
268 x -> y
268 x -> y
269 BROKEN: This should merge the changes from x into y
269 BROKEN: This should merge the changes from x into y
270 $ hg graft -r 2
270 $ hg graft -r 2
271 grafting 2:* "add x again with different content" (glob)
271 grafting 2:* "add x again with different content" (glob)
272 $ hg co -qC 2
272 $ hg co -qC 2
273 BROKEN: This should succeed and merge the changes from x into y
273 BROKEN: This should succeed and merge the changes from x into y
274 $ hg graft -r 3
274 $ hg graft -r 3
275 grafting 3:* "rename x to y" (glob)
275 grafting 3:* "rename x to y" (glob)
276 file 'x' was deleted in other [graft] but was modified in local [local].
276 file 'x' was deleted in other [graft] but was modified in local [local].
277 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
277 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
278 What do you want to do? u
278 What do you want to do? u
279 abort: unresolved conflicts, can't continue
279 abort: unresolved conflicts, can't continue
280 (use 'hg resolve' and 'hg graft --continue')
280 (use 'hg resolve' and 'hg graft --continue')
281 [255]
281 [1]
282
282
283 Add x on two branches, then rename x to y on one side. Similar to the case
283 Add x on two branches, then rename x to y on one side. Similar to the case
284 above, but here the break in history is via the base commit.
284 above, but here the break in history is via the base commit.
285 $ newrepo
285 $ newrepo
286 $ echo a > a
286 $ echo a > a
287 $ hg ci -Aqm 'base'
287 $ hg ci -Aqm 'base'
288 $ echo x > x
288 $ echo x > x
289 $ hg ci -Aqm 'add x'
289 $ hg ci -Aqm 'add x'
290 $ echo x2 > x
290 $ echo x2 > x
291 $ hg ci -m 'modify x'
291 $ hg ci -m 'modify x'
292 $ hg co -q 0
292 $ hg co -q 0
293 $ echo x > x
293 $ echo x > x
294 $ hg ci -Aqm 'add x again'
294 $ hg ci -Aqm 'add x again'
295 $ hg mv x y
295 $ hg mv x y
296 $ hg ci -qm 'rename x to y'
296 $ hg ci -qm 'rename x to y'
297 $ hg l
297 $ hg l
298 @ 4 rename x to y
298 @ 4 rename x to y
299 | x y
299 | x y
300 o 3 add x again
300 o 3 add x again
301 | x
301 | x
302 | o 2 modify x
302 | o 2 modify x
303 | | x
303 | | x
304 | o 1 add x
304 | o 1 add x
305 |/ x
305 |/ x
306 o 0 base
306 o 0 base
307 a
307 a
308 $ hg debugpathcopies 1 4
308 $ hg debugpathcopies 1 4
309 x -> y
309 x -> y
310 $ hg graft -r 2
310 $ hg graft -r 2
311 grafting 2:* "modify x" (glob)
311 grafting 2:* "modify x" (glob)
312 merging y and x to y
312 merging y and x to y
313 $ hg co -qC 2
313 $ hg co -qC 2
314 $ hg graft -r 4
314 $ hg graft -r 4
315 grafting 4:* "rename x to y"* (glob)
315 grafting 4:* "rename x to y"* (glob)
316 merging x and y to y
316 merging x and y to y
317
317
318 Add x on two branches, with same content but different history, then rename x
318 Add x on two branches, with same content but different history, then rename x
319 to y on one side. Similar to the case above, here the file's nodeid is
319 to y on one side. Similar to the case above, here the file's nodeid is
320 different between the branches.
320 different between the branches.
321 $ newrepo
321 $ newrepo
322 $ echo a > a
322 $ echo a > a
323 $ hg ci -Aqm 'base'
323 $ hg ci -Aqm 'base'
324 $ echo x > x
324 $ echo x > x
325 $ hg ci -Aqm 'add x'
325 $ hg ci -Aqm 'add x'
326 $ echo x2 > x
326 $ echo x2 > x
327 $ hg ci -m 'modify x'
327 $ hg ci -m 'modify x'
328 $ hg co -q 0
328 $ hg co -q 0
329 $ touch x
329 $ touch x
330 $ hg ci -Aqm 'add empty x'
330 $ hg ci -Aqm 'add empty x'
331 # Same content to avoid conflicts
331 # Same content to avoid conflicts
332 $ hg revert -r 1 x
332 $ hg revert -r 1 x
333 $ hg ci -m 'modify x to match commit 1'
333 $ hg ci -m 'modify x to match commit 1'
334 $ hg mv x y
334 $ hg mv x y
335 $ hg ci -qm 'rename x to y'
335 $ hg ci -qm 'rename x to y'
336 $ hg l
336 $ hg l
337 @ 5 rename x to y
337 @ 5 rename x to y
338 | x y
338 | x y
339 o 4 modify x to match commit 1
339 o 4 modify x to match commit 1
340 | x
340 | x
341 o 3 add empty x
341 o 3 add empty x
342 | x
342 | x
343 | o 2 modify x
343 | o 2 modify x
344 | | x
344 | | x
345 | o 1 add x
345 | o 1 add x
346 |/ x
346 |/ x
347 o 0 base
347 o 0 base
348 a
348 a
349 $ hg debugpathcopies 1 5
349 $ hg debugpathcopies 1 5
350 x -> y (no-filelog !)
350 x -> y (no-filelog !)
351 #if no-filelog
351 #if no-filelog
352 $ hg graft -r 2
352 $ hg graft -r 2
353 grafting 2:* "modify x" (glob)
353 grafting 2:* "modify x" (glob)
354 merging y and x to y
354 merging y and x to y
355 #else
355 #else
356 BROKEN: This should succeed and merge the changes from x into y
356 BROKEN: This should succeed and merge the changes from x into y
357 $ hg graft -r 2
357 $ hg graft -r 2
358 grafting 2:* "modify x" (glob)
358 grafting 2:* "modify x" (glob)
359 file 'x' was deleted in local [local] but was modified in other [graft].
359 file 'x' was deleted in local [local] but was modified in other [graft].
360 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
360 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
361 What do you want to do? u
361 What do you want to do? u
362 abort: unresolved conflicts, can't continue
362 abort: unresolved conflicts, can't continue
363 (use 'hg resolve' and 'hg graft --continue')
363 (use 'hg resolve' and 'hg graft --continue')
364 [255]
364 [1]
365 #endif
365 #endif
366 $ hg co -qC 2
366 $ hg co -qC 2
367 BROKEN: This should succeed and merge the changes from x into y
367 BROKEN: This should succeed and merge the changes from x into y
368 $ hg graft -r 5
368 $ hg graft -r 5
369 grafting 5:* "rename x to y"* (glob)
369 grafting 5:* "rename x to y"* (glob)
370 file 'x' was deleted in other [graft] but was modified in local [local].
370 file 'x' was deleted in other [graft] but was modified in local [local].
371 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
371 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
372 What do you want to do? u
372 What do you want to do? u
373 abort: unresolved conflicts, can't continue
373 abort: unresolved conflicts, can't continue
374 (use 'hg resolve' and 'hg graft --continue')
374 (use 'hg resolve' and 'hg graft --continue')
375 [255]
375 [1]
376
376
377 Copies via null revision (there shouldn't be any)
377 Copies via null revision (there shouldn't be any)
378 $ newrepo
378 $ newrepo
379 $ echo x > x
379 $ echo x > x
380 $ hg ci -Aqm 'add x'
380 $ hg ci -Aqm 'add x'
381 $ hg cp x y
381 $ hg cp x y
382 $ hg ci -m 'copy x to y'
382 $ hg ci -m 'copy x to y'
383 $ hg co -q null
383 $ hg co -q null
384 $ echo x > x
384 $ echo x > x
385 $ hg ci -Aqm 'add x (again)'
385 $ hg ci -Aqm 'add x (again)'
386 $ hg l
386 $ hg l
387 @ 2 add x (again)
387 @ 2 add x (again)
388 x
388 x
389 o 1 copy x to y
389 o 1 copy x to y
390 | y
390 | y
391 o 0 add x
391 o 0 add x
392 x
392 x
393 $ hg debugpathcopies 1 2
393 $ hg debugpathcopies 1 2
394 $ hg debugpathcopies 2 1
394 $ hg debugpathcopies 2 1
395 $ hg graft -r 1
395 $ hg graft -r 1
396 grafting 1:* "copy x to y" (glob)
396 grafting 1:* "copy x to y" (glob)
397
397
398 Copies involving a merge of multiple roots.
398 Copies involving a merge of multiple roots.
399
399
400 $ newrepo
400 $ newrepo
401 $ echo a > a
401 $ echo a > a
402 $ hg ci -Aqm 'add a'
402 $ hg ci -Aqm 'add a'
403 $ echo a >> a
403 $ echo a >> a
404 $ hg ci -Aqm 'update a'
404 $ hg ci -Aqm 'update a'
405 $ echo a >> a
405 $ echo a >> a
406 $ hg ci -Aqm 'update a'
406 $ hg ci -Aqm 'update a'
407
407
408 $ hg up null
408 $ hg up null
409 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
409 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
410 $ echo b > a
410 $ echo b > a
411 $ hg ci -Aqm 'add a'
411 $ hg ci -Aqm 'add a'
412 $ hg mv a b
412 $ hg mv a b
413 $ hg ci -Aqm 'move a to b'
413 $ hg ci -Aqm 'move a to b'
414 $ echo b >> b
414 $ echo b >> b
415 $ hg ci -Aqm 'update b'
415 $ hg ci -Aqm 'update b'
416 $ hg merge 0
416 $ hg merge 0
417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
418 (branch merge, don't forget to commit)
418 (branch merge, don't forget to commit)
419 $ hg ci -m "merge with other branch"
419 $ hg ci -m "merge with other branch"
420 $ echo a >> a
420 $ echo a >> a
421 $ echo a >> a
421 $ echo a >> a
422 $ echo b >> b
422 $ echo b >> b
423 $ hg ci -Aqm 'update a and b'
423 $ hg ci -Aqm 'update a and b'
424 $ hg l
424 $ hg l
425 @ 7 update a and b
425 @ 7 update a and b
426 | a b
426 | a b
427 o 6 merge with other branch
427 o 6 merge with other branch
428 |\
428 |\
429 | o 5 update b
429 | o 5 update b
430 | | b
430 | | b
431 | o 4 move a to b
431 | o 4 move a to b
432 | | a b
432 | | a b
433 | o 3 add a
433 | o 3 add a
434 | a
434 | a
435 | o 2 update a
435 | o 2 update a
436 | | a
436 | | a
437 | o 1 update a
437 | o 1 update a
438 |/ a
438 |/ a
439 o 0 add a
439 o 0 add a
440 a
440 a
441 $ hg cat a -r 7
441 $ hg cat a -r 7
442 a
442 a
443 a
443 a
444 a
444 a
445 $ hg cat a -r 2
445 $ hg cat a -r 2
446 a
446 a
447 a
447 a
448 a
448 a
449 $ hg cat a -r 0
449 $ hg cat a -r 0
450 a
450 a
451 $ hg debugpathcopies 7 2
451 $ hg debugpathcopies 7 2
452 $ hg debugpathcopies 2 7
452 $ hg debugpathcopies 2 7
453 $ hg merge 2
453 $ hg merge 2
454 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
454 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
455 (branch merge, don't forget to commit)
455 (branch merge, don't forget to commit)
456
456
@@ -1,771 +1,771 b''
1 #testcases abortcommand abortflag
1 #testcases abortcommand abortflag
2
2
3 #if abortflag
3 #if abortflag
4 $ cat >> $HGRCPATH <<EOF
4 $ cat >> $HGRCPATH <<EOF
5 > [alias]
5 > [alias]
6 > abort = graft --abort
6 > abort = graft --abort
7 > EOF
7 > EOF
8 #endif
8 #endif
9
9
10
10
11 Testing the reading of old format graftstate file with newer mercurial
11 Testing the reading of old format graftstate file with newer mercurial
12
12
13 $ hg init oldgraft
13 $ hg init oldgraft
14 $ cd oldgraft
14 $ cd oldgraft
15 $ for ch in a b c; do echo foo > $ch; hg add $ch; hg ci -Aqm "added "$ch; done;
15 $ for ch in a b c; do echo foo > $ch; hg add $ch; hg ci -Aqm "added "$ch; done;
16 $ hg log -GT "{rev}:{node|short} {desc}\n"
16 $ hg log -GT "{rev}:{node|short} {desc}\n"
17 @ 2:8be98ac1a569 added c
17 @ 2:8be98ac1a569 added c
18 |
18 |
19 o 1:80e6d2c47cfe added b
19 o 1:80e6d2c47cfe added b
20 |
20 |
21 o 0:f7ad41964313 added a
21 o 0:f7ad41964313 added a
22
22
23 $ hg up 0
23 $ hg up 0
24 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
24 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
25 $ echo bar > b
25 $ echo bar > b
26 $ hg add b
26 $ hg add b
27 $ hg ci -m "bar to b"
27 $ hg ci -m "bar to b"
28 created new head
28 created new head
29 $ hg graft -r 1 -r 2
29 $ hg graft -r 1 -r 2
30 grafting 1:80e6d2c47cfe "added b"
30 grafting 1:80e6d2c47cfe "added b"
31 merging b
31 merging b
32 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
32 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
33 abort: unresolved conflicts, can't continue
33 abort: unresolved conflicts, can't continue
34 (use 'hg resolve' and 'hg graft --continue')
34 (use 'hg resolve' and 'hg graft --continue')
35 [255]
35 [1]
36
36
37 Writing the nodes in old format to graftstate
37 Writing the nodes in old format to graftstate
38
38
39 $ hg log -r 1 -r 2 -T '{node}\n' > .hg/graftstate
39 $ hg log -r 1 -r 2 -T '{node}\n' > .hg/graftstate
40 $ echo foo > b
40 $ echo foo > b
41 $ hg resolve -m
41 $ hg resolve -m
42 (no more unresolved files)
42 (no more unresolved files)
43 continue: hg graft --continue
43 continue: hg graft --continue
44 $ hg graft --continue
44 $ hg graft --continue
45 grafting 1:80e6d2c47cfe "added b"
45 grafting 1:80e6d2c47cfe "added b"
46 grafting 2:8be98ac1a569 "added c"
46 grafting 2:8be98ac1a569 "added c"
47
47
48 Testing that --user is preserved during conflicts and value is reused while
48 Testing that --user is preserved during conflicts and value is reused while
49 running `hg graft --continue`
49 running `hg graft --continue`
50
50
51 $ hg log -G
51 $ hg log -G
52 @ changeset: 5:711e9fa999f1
52 @ changeset: 5:711e9fa999f1
53 | tag: tip
53 | tag: tip
54 | user: test
54 | user: test
55 | date: Thu Jan 01 00:00:00 1970 +0000
55 | date: Thu Jan 01 00:00:00 1970 +0000
56 | summary: added c
56 | summary: added c
57 |
57 |
58 o changeset: 4:e5ad7353b408
58 o changeset: 4:e5ad7353b408
59 | user: test
59 | user: test
60 | date: Thu Jan 01 00:00:00 1970 +0000
60 | date: Thu Jan 01 00:00:00 1970 +0000
61 | summary: added b
61 | summary: added b
62 |
62 |
63 o changeset: 3:9e887f7a939c
63 o changeset: 3:9e887f7a939c
64 | parent: 0:f7ad41964313
64 | parent: 0:f7ad41964313
65 | user: test
65 | user: test
66 | date: Thu Jan 01 00:00:00 1970 +0000
66 | date: Thu Jan 01 00:00:00 1970 +0000
67 | summary: bar to b
67 | summary: bar to b
68 |
68 |
69 | o changeset: 2:8be98ac1a569
69 | o changeset: 2:8be98ac1a569
70 | | user: test
70 | | user: test
71 | | date: Thu Jan 01 00:00:00 1970 +0000
71 | | date: Thu Jan 01 00:00:00 1970 +0000
72 | | summary: added c
72 | | summary: added c
73 | |
73 | |
74 | o changeset: 1:80e6d2c47cfe
74 | o changeset: 1:80e6d2c47cfe
75 |/ user: test
75 |/ user: test
76 | date: Thu Jan 01 00:00:00 1970 +0000
76 | date: Thu Jan 01 00:00:00 1970 +0000
77 | summary: added b
77 | summary: added b
78 |
78 |
79 o changeset: 0:f7ad41964313
79 o changeset: 0:f7ad41964313
80 user: test
80 user: test
81 date: Thu Jan 01 00:00:00 1970 +0000
81 date: Thu Jan 01 00:00:00 1970 +0000
82 summary: added a
82 summary: added a
83
83
84
84
85 $ hg up '.^^'
85 $ hg up '.^^'
86 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
86 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
87
87
88 $ hg graft -r 1 -r 2 --user batman
88 $ hg graft -r 1 -r 2 --user batman
89 grafting 1:80e6d2c47cfe "added b"
89 grafting 1:80e6d2c47cfe "added b"
90 merging b
90 merging b
91 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
91 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
92 abort: unresolved conflicts, can't continue
92 abort: unresolved conflicts, can't continue
93 (use 'hg resolve' and 'hg graft --continue')
93 (use 'hg resolve' and 'hg graft --continue')
94 [255]
94 [1]
95
95
96 $ echo wat > b
96 $ echo wat > b
97 $ hg resolve -m
97 $ hg resolve -m
98 (no more unresolved files)
98 (no more unresolved files)
99 continue: hg graft --continue
99 continue: hg graft --continue
100
100
101 $ hg graft --continue
101 $ hg graft --continue
102 grafting 1:80e6d2c47cfe "added b"
102 grafting 1:80e6d2c47cfe "added b"
103 grafting 2:8be98ac1a569 "added c"
103 grafting 2:8be98ac1a569 "added c"
104
104
105 $ hg log -Gr 3::
105 $ hg log -Gr 3::
106 @ changeset: 7:11a36ffaacf2
106 @ changeset: 7:11a36ffaacf2
107 | tag: tip
107 | tag: tip
108 | user: batman
108 | user: batman
109 | date: Thu Jan 01 00:00:00 1970 +0000
109 | date: Thu Jan 01 00:00:00 1970 +0000
110 | summary: added c
110 | summary: added c
111 |
111 |
112 o changeset: 6:76803afc6511
112 o changeset: 6:76803afc6511
113 | parent: 3:9e887f7a939c
113 | parent: 3:9e887f7a939c
114 | user: batman
114 | user: batman
115 | date: Thu Jan 01 00:00:00 1970 +0000
115 | date: Thu Jan 01 00:00:00 1970 +0000
116 | summary: added b
116 | summary: added b
117 |
117 |
118 | o changeset: 5:711e9fa999f1
118 | o changeset: 5:711e9fa999f1
119 | | user: test
119 | | user: test
120 | | date: Thu Jan 01 00:00:00 1970 +0000
120 | | date: Thu Jan 01 00:00:00 1970 +0000
121 | | summary: added c
121 | | summary: added c
122 | |
122 | |
123 | o changeset: 4:e5ad7353b408
123 | o changeset: 4:e5ad7353b408
124 |/ user: test
124 |/ user: test
125 | date: Thu Jan 01 00:00:00 1970 +0000
125 | date: Thu Jan 01 00:00:00 1970 +0000
126 | summary: added b
126 | summary: added b
127 |
127 |
128 o changeset: 3:9e887f7a939c
128 o changeset: 3:9e887f7a939c
129 | parent: 0:f7ad41964313
129 | parent: 0:f7ad41964313
130 ~ user: test
130 ~ user: test
131 date: Thu Jan 01 00:00:00 1970 +0000
131 date: Thu Jan 01 00:00:00 1970 +0000
132 summary: bar to b
132 summary: bar to b
133
133
134 Test that --date is preserved and reused in `hg graft --continue`
134 Test that --date is preserved and reused in `hg graft --continue`
135
135
136 $ hg up '.^^'
136 $ hg up '.^^'
137 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
137 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
138 $ hg graft -r 1 -r 2 --date '1234560000 120'
138 $ hg graft -r 1 -r 2 --date '1234560000 120'
139 grafting 1:80e6d2c47cfe "added b"
139 grafting 1:80e6d2c47cfe "added b"
140 merging b
140 merging b
141 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
141 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
142 abort: unresolved conflicts, can't continue
142 abort: unresolved conflicts, can't continue
143 (use 'hg resolve' and 'hg graft --continue')
143 (use 'hg resolve' and 'hg graft --continue')
144 [255]
144 [1]
145
145
146 $ echo foobar > b
146 $ echo foobar > b
147 $ hg resolve -m
147 $ hg resolve -m
148 (no more unresolved files)
148 (no more unresolved files)
149 continue: hg graft --continue
149 continue: hg graft --continue
150 $ hg graft --continue
150 $ hg graft --continue
151 grafting 1:80e6d2c47cfe "added b"
151 grafting 1:80e6d2c47cfe "added b"
152 grafting 2:8be98ac1a569 "added c"
152 grafting 2:8be98ac1a569 "added c"
153
153
154 $ hg log -Gr '.^^::.'
154 $ hg log -Gr '.^^::.'
155 @ changeset: 9:1896b76e007a
155 @ changeset: 9:1896b76e007a
156 | tag: tip
156 | tag: tip
157 | user: test
157 | user: test
158 | date: Fri Feb 13 21:18:00 2009 -0002
158 | date: Fri Feb 13 21:18:00 2009 -0002
159 | summary: added c
159 | summary: added c
160 |
160 |
161 o changeset: 8:ce2b4f1632af
161 o changeset: 8:ce2b4f1632af
162 | parent: 3:9e887f7a939c
162 | parent: 3:9e887f7a939c
163 | user: test
163 | user: test
164 | date: Fri Feb 13 21:18:00 2009 -0002
164 | date: Fri Feb 13 21:18:00 2009 -0002
165 | summary: added b
165 | summary: added b
166 |
166 |
167 o changeset: 3:9e887f7a939c
167 o changeset: 3:9e887f7a939c
168 | parent: 0:f7ad41964313
168 | parent: 0:f7ad41964313
169 ~ user: test
169 ~ user: test
170 date: Thu Jan 01 00:00:00 1970 +0000
170 date: Thu Jan 01 00:00:00 1970 +0000
171 summary: bar to b
171 summary: bar to b
172
172
173 Test that --log is preserved and reused in `hg graft --continue`
173 Test that --log is preserved and reused in `hg graft --continue`
174
174
175 $ hg up '.^^'
175 $ hg up '.^^'
176 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
176 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
177 $ hg graft -r 1 -r 2 --log
177 $ hg graft -r 1 -r 2 --log
178 grafting 1:80e6d2c47cfe "added b"
178 grafting 1:80e6d2c47cfe "added b"
179 merging b
179 merging b
180 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
180 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
181 abort: unresolved conflicts, can't continue
181 abort: unresolved conflicts, can't continue
182 (use 'hg resolve' and 'hg graft --continue')
182 (use 'hg resolve' and 'hg graft --continue')
183 [255]
183 [1]
184
184
185 $ echo foobar > b
185 $ echo foobar > b
186 $ hg resolve -m
186 $ hg resolve -m
187 (no more unresolved files)
187 (no more unresolved files)
188 continue: hg graft --continue
188 continue: hg graft --continue
189
189
190 $ hg graft --continue
190 $ hg graft --continue
191 grafting 1:80e6d2c47cfe "added b"
191 grafting 1:80e6d2c47cfe "added b"
192 grafting 2:8be98ac1a569 "added c"
192 grafting 2:8be98ac1a569 "added c"
193
193
194 $ hg log -GT "{rev}:{node|short} {desc}" -r '.^^::.'
194 $ hg log -GT "{rev}:{node|short} {desc}" -r '.^^::.'
195 @ 11:30c1050a58b2 added c
195 @ 11:30c1050a58b2 added c
196 | (grafted from 8be98ac1a56990c2d9ca6861041b8390af7bd6f3)
196 | (grafted from 8be98ac1a56990c2d9ca6861041b8390af7bd6f3)
197 o 10:ec7eda2313e2 added b
197 o 10:ec7eda2313e2 added b
198 | (grafted from 80e6d2c47cfe5b3185519568327a17a061c7efb6)
198 | (grafted from 80e6d2c47cfe5b3185519568327a17a061c7efb6)
199 o 3:9e887f7a939c bar to b
199 o 3:9e887f7a939c bar to b
200 |
200 |
201 ~
201 ~
202
202
203 $ cd ..
203 $ cd ..
204
204
205 Testing the --stop flag of `hg graft` which stops the interrupted graft
205 Testing the --stop flag of `hg graft` which stops the interrupted graft
206
206
207 $ hg init stopgraft
207 $ hg init stopgraft
208 $ cd stopgraft
208 $ cd stopgraft
209 $ for ch in a b c d; do echo $ch > $ch; hg add $ch; hg ci -Aqm "added "$ch; done;
209 $ for ch in a b c d; do echo $ch > $ch; hg add $ch; hg ci -Aqm "added "$ch; done;
210
210
211 $ hg log -G
211 $ hg log -G
212 @ changeset: 3:9150fe93bec6
212 @ changeset: 3:9150fe93bec6
213 | tag: tip
213 | tag: tip
214 | user: test
214 | user: test
215 | date: Thu Jan 01 00:00:00 1970 +0000
215 | date: Thu Jan 01 00:00:00 1970 +0000
216 | summary: added d
216 | summary: added d
217 |
217 |
218 o changeset: 2:155349b645be
218 o changeset: 2:155349b645be
219 | user: test
219 | user: test
220 | date: Thu Jan 01 00:00:00 1970 +0000
220 | date: Thu Jan 01 00:00:00 1970 +0000
221 | summary: added c
221 | summary: added c
222 |
222 |
223 o changeset: 1:5f6d8a4bf34a
223 o changeset: 1:5f6d8a4bf34a
224 | user: test
224 | user: test
225 | date: Thu Jan 01 00:00:00 1970 +0000
225 | date: Thu Jan 01 00:00:00 1970 +0000
226 | summary: added b
226 | summary: added b
227 |
227 |
228 o changeset: 0:9092f1db7931
228 o changeset: 0:9092f1db7931
229 user: test
229 user: test
230 date: Thu Jan 01 00:00:00 1970 +0000
230 date: Thu Jan 01 00:00:00 1970 +0000
231 summary: added a
231 summary: added a
232
232
233 $ hg up '.^^'
233 $ hg up '.^^'
234 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
234 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
235
235
236 $ echo foo > d
236 $ echo foo > d
237 $ hg ci -Aqm "added foo to d"
237 $ hg ci -Aqm "added foo to d"
238
238
239 $ hg graft --stop
239 $ hg graft --stop
240 abort: no interrupted graft found
240 abort: no interrupted graft found
241 [255]
241 [255]
242
242
243 $ hg graft -r 3
243 $ hg graft -r 3
244 grafting 3:9150fe93bec6 "added d"
244 grafting 3:9150fe93bec6 "added d"
245 merging d
245 merging d
246 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
246 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
247 abort: unresolved conflicts, can't continue
247 abort: unresolved conflicts, can't continue
248 (use 'hg resolve' and 'hg graft --continue')
248 (use 'hg resolve' and 'hg graft --continue')
249 [255]
249 [1]
250
250
251 $ hg graft --stop --continue
251 $ hg graft --stop --continue
252 abort: cannot use '--continue' and '--stop' together
252 abort: cannot use '--continue' and '--stop' together
253 [255]
253 [255]
254
254
255 $ hg graft --stop -U
255 $ hg graft --stop -U
256 abort: cannot specify any other flag with '--stop'
256 abort: cannot specify any other flag with '--stop'
257 [255]
257 [255]
258 $ hg graft --stop --rev 4
258 $ hg graft --stop --rev 4
259 abort: cannot specify any other flag with '--stop'
259 abort: cannot specify any other flag with '--stop'
260 [255]
260 [255]
261 $ hg graft --stop --log
261 $ hg graft --stop --log
262 abort: cannot specify any other flag with '--stop'
262 abort: cannot specify any other flag with '--stop'
263 [255]
263 [255]
264
264
265 $ hg graft --stop
265 $ hg graft --stop
266 stopped the interrupted graft
266 stopped the interrupted graft
267 working directory is now at a0deacecd59d
267 working directory is now at a0deacecd59d
268
268
269 $ hg diff
269 $ hg diff
270
270
271 $ hg log -Gr '.'
271 $ hg log -Gr '.'
272 @ changeset: 4:a0deacecd59d
272 @ changeset: 4:a0deacecd59d
273 | tag: tip
273 | tag: tip
274 ~ parent: 1:5f6d8a4bf34a
274 ~ parent: 1:5f6d8a4bf34a
275 user: test
275 user: test
276 date: Thu Jan 01 00:00:00 1970 +0000
276 date: Thu Jan 01 00:00:00 1970 +0000
277 summary: added foo to d
277 summary: added foo to d
278
278
279 $ hg graft -r 2 -r 3
279 $ hg graft -r 2 -r 3
280 grafting 2:155349b645be "added c"
280 grafting 2:155349b645be "added c"
281 grafting 3:9150fe93bec6 "added d"
281 grafting 3:9150fe93bec6 "added d"
282 merging d
282 merging d
283 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
283 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
284 abort: unresolved conflicts, can't continue
284 abort: unresolved conflicts, can't continue
285 (use 'hg resolve' and 'hg graft --continue')
285 (use 'hg resolve' and 'hg graft --continue')
286 [255]
286 [1]
287
287
288 $ hg graft --stop
288 $ hg graft --stop
289 stopped the interrupted graft
289 stopped the interrupted graft
290 working directory is now at 75b447541a9e
290 working directory is now at 75b447541a9e
291
291
292 $ hg diff
292 $ hg diff
293
293
294 $ hg log -G -T "{rev}:{node|short} {desc}"
294 $ hg log -G -T "{rev}:{node|short} {desc}"
295 @ 5:75b447541a9e added c
295 @ 5:75b447541a9e added c
296 |
296 |
297 o 4:a0deacecd59d added foo to d
297 o 4:a0deacecd59d added foo to d
298 |
298 |
299 | o 3:9150fe93bec6 added d
299 | o 3:9150fe93bec6 added d
300 | |
300 | |
301 | o 2:155349b645be added c
301 | o 2:155349b645be added c
302 |/
302 |/
303 o 1:5f6d8a4bf34a added b
303 o 1:5f6d8a4bf34a added b
304 |
304 |
305 o 0:9092f1db7931 added a
305 o 0:9092f1db7931 added a
306
306
307 $ cd ..
307 $ cd ..
308
308
309 Testing the --abort flag for `hg graft` which aborts and rollback to state
309 Testing the --abort flag for `hg graft` which aborts and rollback to state
310 before the graft
310 before the graft
311
311
312 $ hg init abortgraft
312 $ hg init abortgraft
313 $ cd abortgraft
313 $ cd abortgraft
314 $ for ch in a b c d; do echo $ch > $ch; hg add $ch; hg ci -Aqm "added "$ch; done;
314 $ for ch in a b c d; do echo $ch > $ch; hg add $ch; hg ci -Aqm "added "$ch; done;
315
315
316 $ hg up '.^^'
316 $ hg up '.^^'
317 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
317 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
318
318
319 $ echo x > x
319 $ echo x > x
320 $ hg ci -Aqm "added x"
320 $ hg ci -Aqm "added x"
321 $ hg up '.^'
321 $ hg up '.^'
322 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
322 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
323 $ echo foo > c
323 $ echo foo > c
324 $ hg ci -Aqm "added foo to c"
324 $ hg ci -Aqm "added foo to c"
325
325
326 $ hg log -GT "{rev}:{node|short} {desc}"
326 $ hg log -GT "{rev}:{node|short} {desc}"
327 @ 5:36b793615f78 added foo to c
327 @ 5:36b793615f78 added foo to c
328 |
328 |
329 | o 4:863a25e1a9ea added x
329 | o 4:863a25e1a9ea added x
330 |/
330 |/
331 | o 3:9150fe93bec6 added d
331 | o 3:9150fe93bec6 added d
332 | |
332 | |
333 | o 2:155349b645be added c
333 | o 2:155349b645be added c
334 |/
334 |/
335 o 1:5f6d8a4bf34a added b
335 o 1:5f6d8a4bf34a added b
336 |
336 |
337 o 0:9092f1db7931 added a
337 o 0:9092f1db7931 added a
338
338
339 $ hg up 9150fe93bec6
339 $ hg up 9150fe93bec6
340 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
340 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
341
341
342 $ hg abort
342 $ hg abort
343 abort: no interrupted graft to abort (abortflag !)
343 abort: no interrupted graft to abort (abortflag !)
344 abort: no operation in progress (abortcommand !)
344 abort: no operation in progress (abortcommand !)
345 [255]
345 [255]
346
346
347 when stripping is required
347 when stripping is required
348 $ hg graft -r 4 -r 5
348 $ hg graft -r 4 -r 5
349 grafting 4:863a25e1a9ea "added x"
349 grafting 4:863a25e1a9ea "added x"
350 grafting 5:36b793615f78 "added foo to c" (tip)
350 grafting 5:36b793615f78 "added foo to c" (tip)
351 merging c
351 merging c
352 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
352 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
353 abort: unresolved conflicts, can't continue
353 abort: unresolved conflicts, can't continue
354 (use 'hg resolve' and 'hg graft --continue')
354 (use 'hg resolve' and 'hg graft --continue')
355 [255]
355 [1]
356
356
357 $ hg graft --continue --abort
357 $ hg graft --continue --abort
358 abort: cannot use '--continue' and '--abort' together
358 abort: cannot use '--continue' and '--abort' together
359 [255]
359 [255]
360
360
361 $ hg graft --abort --stop
361 $ hg graft --abort --stop
362 abort: cannot use '--abort' and '--stop' together
362 abort: cannot use '--abort' and '--stop' together
363 [255]
363 [255]
364
364
365 $ hg graft --abort --currentuser
365 $ hg graft --abort --currentuser
366 abort: cannot specify any other flag with '--abort'
366 abort: cannot specify any other flag with '--abort'
367 [255]
367 [255]
368
368
369 $ hg graft --abort --edit
369 $ hg graft --abort --edit
370 abort: cannot specify any other flag with '--abort'
370 abort: cannot specify any other flag with '--abort'
371 [255]
371 [255]
372
372
373 #if abortcommand
373 #if abortcommand
374 when in dry-run mode
374 when in dry-run mode
375 $ hg abort --dry-run
375 $ hg abort --dry-run
376 graft in progress, will be aborted
376 graft in progress, will be aborted
377 #endif
377 #endif
378
378
379 $ hg abort
379 $ hg abort
380 graft aborted
380 graft aborted
381 working directory is now at 9150fe93bec6
381 working directory is now at 9150fe93bec6
382 $ hg log -GT "{rev}:{node|short} {desc}"
382 $ hg log -GT "{rev}:{node|short} {desc}"
383 o 5:36b793615f78 added foo to c
383 o 5:36b793615f78 added foo to c
384 |
384 |
385 | o 4:863a25e1a9ea added x
385 | o 4:863a25e1a9ea added x
386 |/
386 |/
387 | @ 3:9150fe93bec6 added d
387 | @ 3:9150fe93bec6 added d
388 | |
388 | |
389 | o 2:155349b645be added c
389 | o 2:155349b645be added c
390 |/
390 |/
391 o 1:5f6d8a4bf34a added b
391 o 1:5f6d8a4bf34a added b
392 |
392 |
393 o 0:9092f1db7931 added a
393 o 0:9092f1db7931 added a
394
394
395 when stripping is not required
395 when stripping is not required
396 $ hg graft -r 5
396 $ hg graft -r 5
397 grafting 5:36b793615f78 "added foo to c" (tip)
397 grafting 5:36b793615f78 "added foo to c" (tip)
398 merging c
398 merging c
399 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
399 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
400 abort: unresolved conflicts, can't continue
400 abort: unresolved conflicts, can't continue
401 (use 'hg resolve' and 'hg graft --continue')
401 (use 'hg resolve' and 'hg graft --continue')
402 [255]
402 [1]
403
403
404 $ hg abort
404 $ hg abort
405 graft aborted
405 graft aborted
406 working directory is now at 9150fe93bec6
406 working directory is now at 9150fe93bec6
407 $ hg log -GT "{rev}:{node|short} {desc}"
407 $ hg log -GT "{rev}:{node|short} {desc}"
408 o 5:36b793615f78 added foo to c
408 o 5:36b793615f78 added foo to c
409 |
409 |
410 | o 4:863a25e1a9ea added x
410 | o 4:863a25e1a9ea added x
411 |/
411 |/
412 | @ 3:9150fe93bec6 added d
412 | @ 3:9150fe93bec6 added d
413 | |
413 | |
414 | o 2:155349b645be added c
414 | o 2:155349b645be added c
415 |/
415 |/
416 o 1:5f6d8a4bf34a added b
416 o 1:5f6d8a4bf34a added b
417 |
417 |
418 o 0:9092f1db7931 added a
418 o 0:9092f1db7931 added a
419
419
420 when some of the changesets became public
420 when some of the changesets became public
421
421
422 $ hg graft -r 4 -r 5
422 $ hg graft -r 4 -r 5
423 grafting 4:863a25e1a9ea "added x"
423 grafting 4:863a25e1a9ea "added x"
424 grafting 5:36b793615f78 "added foo to c" (tip)
424 grafting 5:36b793615f78 "added foo to c" (tip)
425 merging c
425 merging c
426 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
426 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
427 abort: unresolved conflicts, can't continue
427 abort: unresolved conflicts, can't continue
428 (use 'hg resolve' and 'hg graft --continue')
428 (use 'hg resolve' and 'hg graft --continue')
429 [255]
429 [1]
430
430
431 $ hg log -GT "{rev}:{node|short} {desc}"
431 $ hg log -GT "{rev}:{node|short} {desc}"
432 @ 6:6ec71c037d94 added x
432 @ 6:6ec71c037d94 added x
433 |
433 |
434 | % 5:36b793615f78 added foo to c
434 | % 5:36b793615f78 added foo to c
435 | |
435 | |
436 | | o 4:863a25e1a9ea added x
436 | | o 4:863a25e1a9ea added x
437 | |/
437 | |/
438 o | 3:9150fe93bec6 added d
438 o | 3:9150fe93bec6 added d
439 | |
439 | |
440 o | 2:155349b645be added c
440 o | 2:155349b645be added c
441 |/
441 |/
442 o 1:5f6d8a4bf34a added b
442 o 1:5f6d8a4bf34a added b
443 |
443 |
444 o 0:9092f1db7931 added a
444 o 0:9092f1db7931 added a
445
445
446 $ hg phase -r 6 --public
446 $ hg phase -r 6 --public
447
447
448 $ hg abort
448 $ hg abort
449 cannot clean up public changesets 6ec71c037d94
449 cannot clean up public changesets 6ec71c037d94
450 graft aborted
450 graft aborted
451 working directory is now at 6ec71c037d94
451 working directory is now at 6ec71c037d94
452
452
453 when we created new changesets on top of existing one
453 when we created new changesets on top of existing one
454
454
455 $ hg up '.^^'
455 $ hg up '.^^'
456 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
456 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
457 $ echo y > y
457 $ echo y > y
458 $ hg ci -Aqm "added y"
458 $ hg ci -Aqm "added y"
459 $ echo z > z
459 $ echo z > z
460 $ hg ci -Aqm "added z"
460 $ hg ci -Aqm "added z"
461
461
462 $ hg up 3
462 $ hg up 3
463 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
463 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
464 $ hg log -GT "{rev}:{node|short} {desc}"
464 $ hg log -GT "{rev}:{node|short} {desc}"
465 o 8:637f9e9bbfd4 added z
465 o 8:637f9e9bbfd4 added z
466 |
466 |
467 o 7:123221671fd4 added y
467 o 7:123221671fd4 added y
468 |
468 |
469 | o 6:6ec71c037d94 added x
469 | o 6:6ec71c037d94 added x
470 | |
470 | |
471 | | o 5:36b793615f78 added foo to c
471 | | o 5:36b793615f78 added foo to c
472 | | |
472 | | |
473 | | | o 4:863a25e1a9ea added x
473 | | | o 4:863a25e1a9ea added x
474 | | |/
474 | | |/
475 | @ | 3:9150fe93bec6 added d
475 | @ | 3:9150fe93bec6 added d
476 |/ /
476 |/ /
477 o / 2:155349b645be added c
477 o / 2:155349b645be added c
478 |/
478 |/
479 o 1:5f6d8a4bf34a added b
479 o 1:5f6d8a4bf34a added b
480 |
480 |
481 o 0:9092f1db7931 added a
481 o 0:9092f1db7931 added a
482
482
483 $ hg graft -r 8 -r 7 -r 5
483 $ hg graft -r 8 -r 7 -r 5
484 grafting 8:637f9e9bbfd4 "added z" (tip)
484 grafting 8:637f9e9bbfd4 "added z" (tip)
485 grafting 7:123221671fd4 "added y"
485 grafting 7:123221671fd4 "added y"
486 grafting 5:36b793615f78 "added foo to c"
486 grafting 5:36b793615f78 "added foo to c"
487 merging c
487 merging c
488 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
488 warning: conflicts while merging c! (edit, then use 'hg resolve --mark')
489 abort: unresolved conflicts, can't continue
489 abort: unresolved conflicts, can't continue
490 (use 'hg resolve' and 'hg graft --continue')
490 (use 'hg resolve' and 'hg graft --continue')
491 [255]
491 [1]
492
492
493 $ cd ..
493 $ cd ..
494 $ hg init pullrepo
494 $ hg init pullrepo
495 $ cd pullrepo
495 $ cd pullrepo
496 $ cat >> .hg/hgrc <<EOF
496 $ cat >> .hg/hgrc <<EOF
497 > [phases]
497 > [phases]
498 > publish=False
498 > publish=False
499 > EOF
499 > EOF
500 $ hg pull ../abortgraft --config phases.publish=False
500 $ hg pull ../abortgraft --config phases.publish=False
501 pulling from ../abortgraft
501 pulling from ../abortgraft
502 requesting all changes
502 requesting all changes
503 adding changesets
503 adding changesets
504 adding manifests
504 adding manifests
505 adding file changes
505 adding file changes
506 added 11 changesets with 9 changes to 8 files (+4 heads)
506 added 11 changesets with 9 changes to 8 files (+4 heads)
507 new changesets 9092f1db7931:6b98ff0062dd (6 drafts)
507 new changesets 9092f1db7931:6b98ff0062dd (6 drafts)
508 (run 'hg heads' to see heads, 'hg merge' to merge)
508 (run 'hg heads' to see heads, 'hg merge' to merge)
509 $ hg up 9
509 $ hg up 9
510 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
510 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
511 $ echo w > w
511 $ echo w > w
512 $ hg ci -Aqm "added w" --config phases.publish=False
512 $ hg ci -Aqm "added w" --config phases.publish=False
513
513
514 $ cd ../abortgraft
514 $ cd ../abortgraft
515 $ hg pull ../pullrepo
515 $ hg pull ../pullrepo
516 pulling from ../pullrepo
516 pulling from ../pullrepo
517 searching for changes
517 searching for changes
518 adding changesets
518 adding changesets
519 adding manifests
519 adding manifests
520 adding file changes
520 adding file changes
521 added 1 changesets with 1 changes to 1 files (+1 heads)
521 added 1 changesets with 1 changes to 1 files (+1 heads)
522 new changesets 311dfc6cf3bf (1 drafts)
522 new changesets 311dfc6cf3bf (1 drafts)
523 (run 'hg heads .' to see heads, 'hg merge' to merge)
523 (run 'hg heads .' to see heads, 'hg merge' to merge)
524
524
525 $ hg abort
525 $ hg abort
526 new changesets detected on destination branch, can't strip
526 new changesets detected on destination branch, can't strip
527 graft aborted
527 graft aborted
528 working directory is now at 6b98ff0062dd
528 working directory is now at 6b98ff0062dd
529
529
530 $ cd ..
530 $ cd ..
531
531
532 ============================
532 ============================
533 Testing --no-commit option:|
533 Testing --no-commit option:|
534 ============================
534 ============================
535
535
536 $ hg init nocommit
536 $ hg init nocommit
537 $ cd nocommit
537 $ cd nocommit
538 $ echo a > a
538 $ echo a > a
539 $ hg ci -qAma
539 $ hg ci -qAma
540 $ echo b > b
540 $ echo b > b
541 $ hg ci -qAmb
541 $ hg ci -qAmb
542 $ hg up -q 0
542 $ hg up -q 0
543 $ echo c > c
543 $ echo c > c
544 $ hg ci -qAmc
544 $ hg ci -qAmc
545 $ hg log -GT "{rev}:{node|short} {desc}\n"
545 $ hg log -GT "{rev}:{node|short} {desc}\n"
546 @ 2:d36c0562f908 c
546 @ 2:d36c0562f908 c
547 |
547 |
548 | o 1:d2ae7f538514 b
548 | o 1:d2ae7f538514 b
549 |/
549 |/
550 o 0:cb9a9f314b8b a
550 o 0:cb9a9f314b8b a
551
551
552
552
553 Check reporting when --no-commit used with non-applicable options:
553 Check reporting when --no-commit used with non-applicable options:
554
554
555 $ hg graft 1 --no-commit -e
555 $ hg graft 1 --no-commit -e
556 abort: cannot specify --no-commit and --edit together
556 abort: cannot specify --no-commit and --edit together
557 [255]
557 [255]
558
558
559 $ hg graft 1 --no-commit --log
559 $ hg graft 1 --no-commit --log
560 abort: cannot specify --no-commit and --log together
560 abort: cannot specify --no-commit and --log together
561 [255]
561 [255]
562
562
563 $ hg graft 1 --no-commit -D
563 $ hg graft 1 --no-commit -D
564 abort: cannot specify --no-commit and --currentdate together
564 abort: cannot specify --no-commit and --currentdate together
565 [255]
565 [255]
566
566
567 Test --no-commit is working:
567 Test --no-commit is working:
568 $ hg graft 1 --no-commit
568 $ hg graft 1 --no-commit
569 grafting 1:d2ae7f538514 "b"
569 grafting 1:d2ae7f538514 "b"
570
570
571 $ hg log -GT "{rev}:{node|short} {desc}\n"
571 $ hg log -GT "{rev}:{node|short} {desc}\n"
572 @ 2:d36c0562f908 c
572 @ 2:d36c0562f908 c
573 |
573 |
574 | o 1:d2ae7f538514 b
574 | o 1:d2ae7f538514 b
575 |/
575 |/
576 o 0:cb9a9f314b8b a
576 o 0:cb9a9f314b8b a
577
577
578
578
579 $ hg diff
579 $ hg diff
580 diff -r d36c0562f908 b
580 diff -r d36c0562f908 b
581 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
581 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
582 +++ b/b Thu Jan 01 00:00:00 1970 +0000
582 +++ b/b Thu Jan 01 00:00:00 1970 +0000
583 @@ -0,0 +1,1 @@
583 @@ -0,0 +1,1 @@
584 +b
584 +b
585
585
586 Prepare wrdir to check --no-commit is resepected after --continue:
586 Prepare wrdir to check --no-commit is resepected after --continue:
587
587
588 $ hg up -qC
588 $ hg up -qC
589 $ echo A>a
589 $ echo A>a
590 $ hg ci -qm "A in file a"
590 $ hg ci -qm "A in file a"
591 $ hg up -q 1
591 $ hg up -q 1
592 $ echo B>a
592 $ echo B>a
593 $ hg ci -qm "B in file a"
593 $ hg ci -qm "B in file a"
594 $ hg log -GT "{rev}:{node|short} {desc}\n"
594 $ hg log -GT "{rev}:{node|short} {desc}\n"
595 @ 4:2aa9ad1006ff B in file a
595 @ 4:2aa9ad1006ff B in file a
596 |
596 |
597 | o 3:09e253b87e17 A in file a
597 | o 3:09e253b87e17 A in file a
598 | |
598 | |
599 | o 2:d36c0562f908 c
599 | o 2:d36c0562f908 c
600 | |
600 | |
601 o | 1:d2ae7f538514 b
601 o | 1:d2ae7f538514 b
602 |/
602 |/
603 o 0:cb9a9f314b8b a
603 o 0:cb9a9f314b8b a
604
604
605
605
606 $ hg graft 3 --no-commit
606 $ hg graft 3 --no-commit
607 grafting 3:09e253b87e17 "A in file a"
607 grafting 3:09e253b87e17 "A in file a"
608 merging a
608 merging a
609 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
609 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
610 abort: unresolved conflicts, can't continue
610 abort: unresolved conflicts, can't continue
611 (use 'hg resolve' and 'hg graft --continue')
611 (use 'hg resolve' and 'hg graft --continue')
612 [255]
612 [1]
613
613
614 Resolve conflict:
614 Resolve conflict:
615 $ echo A>a
615 $ echo A>a
616 $ hg resolve --mark
616 $ hg resolve --mark
617 (no more unresolved files)
617 (no more unresolved files)
618 continue: hg graft --continue
618 continue: hg graft --continue
619
619
620 $ hg graft --continue
620 $ hg graft --continue
621 grafting 3:09e253b87e17 "A in file a"
621 grafting 3:09e253b87e17 "A in file a"
622 $ hg log -GT "{rev}:{node|short} {desc}\n"
622 $ hg log -GT "{rev}:{node|short} {desc}\n"
623 @ 4:2aa9ad1006ff B in file a
623 @ 4:2aa9ad1006ff B in file a
624 |
624 |
625 | % 3:09e253b87e17 A in file a
625 | % 3:09e253b87e17 A in file a
626 | |
626 | |
627 | o 2:d36c0562f908 c
627 | o 2:d36c0562f908 c
628 | |
628 | |
629 o | 1:d2ae7f538514 b
629 o | 1:d2ae7f538514 b
630 |/
630 |/
631 o 0:cb9a9f314b8b a
631 o 0:cb9a9f314b8b a
632
632
633 $ hg diff
633 $ hg diff
634 diff -r 2aa9ad1006ff a
634 diff -r 2aa9ad1006ff a
635 --- a/a Thu Jan 01 00:00:00 1970 +0000
635 --- a/a Thu Jan 01 00:00:00 1970 +0000
636 +++ b/a Thu Jan 01 00:00:00 1970 +0000
636 +++ b/a Thu Jan 01 00:00:00 1970 +0000
637 @@ -1,1 +1,1 @@
637 @@ -1,1 +1,1 @@
638 -B
638 -B
639 +A
639 +A
640
640
641 $ hg up -qC
641 $ hg up -qC
642
642
643 Check --no-commit is resepected when passed with --continue:
643 Check --no-commit is resepected when passed with --continue:
644
644
645 $ hg graft 3
645 $ hg graft 3
646 grafting 3:09e253b87e17 "A in file a"
646 grafting 3:09e253b87e17 "A in file a"
647 merging a
647 merging a
648 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
648 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
649 abort: unresolved conflicts, can't continue
649 abort: unresolved conflicts, can't continue
650 (use 'hg resolve' and 'hg graft --continue')
650 (use 'hg resolve' and 'hg graft --continue')
651 [255]
651 [1]
652
652
653 Resolve conflict:
653 Resolve conflict:
654 $ echo A>a
654 $ echo A>a
655 $ hg resolve --mark
655 $ hg resolve --mark
656 (no more unresolved files)
656 (no more unresolved files)
657 continue: hg graft --continue
657 continue: hg graft --continue
658
658
659 $ hg graft --continue --no-commit
659 $ hg graft --continue --no-commit
660 grafting 3:09e253b87e17 "A in file a"
660 grafting 3:09e253b87e17 "A in file a"
661 $ hg diff
661 $ hg diff
662 diff -r 2aa9ad1006ff a
662 diff -r 2aa9ad1006ff a
663 --- a/a Thu Jan 01 00:00:00 1970 +0000
663 --- a/a Thu Jan 01 00:00:00 1970 +0000
664 +++ b/a Thu Jan 01 00:00:00 1970 +0000
664 +++ b/a Thu Jan 01 00:00:00 1970 +0000
665 @@ -1,1 +1,1 @@
665 @@ -1,1 +1,1 @@
666 -B
666 -B
667 +A
667 +A
668
668
669 $ hg log -GT "{rev}:{node|short} {desc}\n"
669 $ hg log -GT "{rev}:{node|short} {desc}\n"
670 @ 4:2aa9ad1006ff B in file a
670 @ 4:2aa9ad1006ff B in file a
671 |
671 |
672 | % 3:09e253b87e17 A in file a
672 | % 3:09e253b87e17 A in file a
673 | |
673 | |
674 | o 2:d36c0562f908 c
674 | o 2:d36c0562f908 c
675 | |
675 | |
676 o | 1:d2ae7f538514 b
676 o | 1:d2ae7f538514 b
677 |/
677 |/
678 o 0:cb9a9f314b8b a
678 o 0:cb9a9f314b8b a
679
679
680 $ hg up -qC
680 $ hg up -qC
681
681
682 Test --no-commit when graft multiple revisions:
682 Test --no-commit when graft multiple revisions:
683 When there is conflict:
683 When there is conflict:
684 $ hg graft -r "2::3" --no-commit
684 $ hg graft -r "2::3" --no-commit
685 grafting 2:d36c0562f908 "c"
685 grafting 2:d36c0562f908 "c"
686 grafting 3:09e253b87e17 "A in file a"
686 grafting 3:09e253b87e17 "A in file a"
687 merging a
687 merging a
688 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
688 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
689 abort: unresolved conflicts, can't continue
689 abort: unresolved conflicts, can't continue
690 (use 'hg resolve' and 'hg graft --continue')
690 (use 'hg resolve' and 'hg graft --continue')
691 [255]
691 [1]
692
692
693 $ echo A>a
693 $ echo A>a
694 $ hg resolve --mark
694 $ hg resolve --mark
695 (no more unresolved files)
695 (no more unresolved files)
696 continue: hg graft --continue
696 continue: hg graft --continue
697 $ hg graft --continue
697 $ hg graft --continue
698 grafting 3:09e253b87e17 "A in file a"
698 grafting 3:09e253b87e17 "A in file a"
699 $ hg diff
699 $ hg diff
700 diff -r 2aa9ad1006ff a
700 diff -r 2aa9ad1006ff a
701 --- a/a Thu Jan 01 00:00:00 1970 +0000
701 --- a/a Thu Jan 01 00:00:00 1970 +0000
702 +++ b/a Thu Jan 01 00:00:00 1970 +0000
702 +++ b/a Thu Jan 01 00:00:00 1970 +0000
703 @@ -1,1 +1,1 @@
703 @@ -1,1 +1,1 @@
704 -B
704 -B
705 +A
705 +A
706 diff -r 2aa9ad1006ff c
706 diff -r 2aa9ad1006ff c
707 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
707 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
708 +++ b/c Thu Jan 01 00:00:00 1970 +0000
708 +++ b/c Thu Jan 01 00:00:00 1970 +0000
709 @@ -0,0 +1,1 @@
709 @@ -0,0 +1,1 @@
710 +c
710 +c
711
711
712 $ hg log -GT "{rev}:{node|short} {desc}\n"
712 $ hg log -GT "{rev}:{node|short} {desc}\n"
713 @ 4:2aa9ad1006ff B in file a
713 @ 4:2aa9ad1006ff B in file a
714 |
714 |
715 | % 3:09e253b87e17 A in file a
715 | % 3:09e253b87e17 A in file a
716 | |
716 | |
717 | o 2:d36c0562f908 c
717 | o 2:d36c0562f908 c
718 | |
718 | |
719 o | 1:d2ae7f538514 b
719 o | 1:d2ae7f538514 b
720 |/
720 |/
721 o 0:cb9a9f314b8b a
721 o 0:cb9a9f314b8b a
722
722
723 $ hg up -qC
723 $ hg up -qC
724
724
725 When there is no conflict:
725 When there is no conflict:
726 $ echo d>d
726 $ echo d>d
727 $ hg add d -q
727 $ hg add d -q
728 $ hg ci -qmd
728 $ hg ci -qmd
729 $ hg up 3 -q
729 $ hg up 3 -q
730 $ hg log -GT "{rev}:{node|short} {desc}\n"
730 $ hg log -GT "{rev}:{node|short} {desc}\n"
731 o 5:baefa8927fc0 d
731 o 5:baefa8927fc0 d
732 |
732 |
733 o 4:2aa9ad1006ff B in file a
733 o 4:2aa9ad1006ff B in file a
734 |
734 |
735 | @ 3:09e253b87e17 A in file a
735 | @ 3:09e253b87e17 A in file a
736 | |
736 | |
737 | o 2:d36c0562f908 c
737 | o 2:d36c0562f908 c
738 | |
738 | |
739 o | 1:d2ae7f538514 b
739 o | 1:d2ae7f538514 b
740 |/
740 |/
741 o 0:cb9a9f314b8b a
741 o 0:cb9a9f314b8b a
742
742
743
743
744 $ hg graft -r 1 -r 5 --no-commit
744 $ hg graft -r 1 -r 5 --no-commit
745 grafting 1:d2ae7f538514 "b"
745 grafting 1:d2ae7f538514 "b"
746 grafting 5:baefa8927fc0 "d" (tip)
746 grafting 5:baefa8927fc0 "d" (tip)
747 $ hg diff
747 $ hg diff
748 diff -r 09e253b87e17 b
748 diff -r 09e253b87e17 b
749 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
749 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
750 +++ b/b Thu Jan 01 00:00:00 1970 +0000
750 +++ b/b Thu Jan 01 00:00:00 1970 +0000
751 @@ -0,0 +1,1 @@
751 @@ -0,0 +1,1 @@
752 +b
752 +b
753 diff -r 09e253b87e17 d
753 diff -r 09e253b87e17 d
754 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
754 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
755 +++ b/d Thu Jan 01 00:00:00 1970 +0000
755 +++ b/d Thu Jan 01 00:00:00 1970 +0000
756 @@ -0,0 +1,1 @@
756 @@ -0,0 +1,1 @@
757 +d
757 +d
758 $ hg log -GT "{rev}:{node|short} {desc}\n"
758 $ hg log -GT "{rev}:{node|short} {desc}\n"
759 o 5:baefa8927fc0 d
759 o 5:baefa8927fc0 d
760 |
760 |
761 o 4:2aa9ad1006ff B in file a
761 o 4:2aa9ad1006ff B in file a
762 |
762 |
763 | @ 3:09e253b87e17 A in file a
763 | @ 3:09e253b87e17 A in file a
764 | |
764 | |
765 | o 2:d36c0562f908 c
765 | o 2:d36c0562f908 c
766 | |
766 | |
767 o | 1:d2ae7f538514 b
767 o | 1:d2ae7f538514 b
768 |/
768 |/
769 o 0:cb9a9f314b8b a
769 o 0:cb9a9f314b8b a
770
770
771 $ cd ..
771 $ cd ..
@@ -1,914 +1,914 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extdiff]
2 > [extdiff]
3 > # for portability:
3 > # for portability:
4 > pdiff = sh "$RUNTESTDIR/pdiff"
4 > pdiff = sh "$RUNTESTDIR/pdiff"
5 > EOF
5 > EOF
6
6
7 Create a repo with some stuff in it:
7 Create a repo with some stuff in it:
8
8
9 $ hg init a
9 $ hg init a
10 $ cd a
10 $ cd a
11 $ echo a > a
11 $ echo a > a
12 $ echo a > d
12 $ echo a > d
13 $ echo a > e
13 $ echo a > e
14 $ hg ci -qAm0
14 $ hg ci -qAm0
15 $ echo b > a
15 $ echo b > a
16 $ hg ci -m1 -u bar
16 $ hg ci -m1 -u bar
17 $ hg mv a b
17 $ hg mv a b
18 $ hg ci -m2
18 $ hg ci -m2
19 $ hg cp b c
19 $ hg cp b c
20 $ hg ci -m3 -u baz
20 $ hg ci -m3 -u baz
21 $ echo b > d
21 $ echo b > d
22 $ echo f > e
22 $ echo f > e
23 $ hg ci -m4
23 $ hg ci -m4
24 $ hg up -q 3
24 $ hg up -q 3
25 $ echo b > e
25 $ echo b > e
26 $ hg branch -q stable
26 $ hg branch -q stable
27 $ hg ci -m5
27 $ hg ci -m5
28 $ hg merge -q default --tool internal:local # for conflicts in e, choose 5 and ignore 4
28 $ hg merge -q default --tool internal:local # for conflicts in e, choose 5 and ignore 4
29 $ hg branch -q default
29 $ hg branch -q default
30 $ hg ci -m6
30 $ hg ci -m6
31 $ hg phase --public 3
31 $ hg phase --public 3
32 $ hg phase --force --secret 6
32 $ hg phase --force --secret 6
33
33
34 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
34 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
35 @ test@6.secret: 6
35 @ test@6.secret: 6
36 |\
36 |\
37 | o test@5.draft: 5
37 | o test@5.draft: 5
38 | |
38 | |
39 o | test@4.draft: 4
39 o | test@4.draft: 4
40 |/
40 |/
41 o baz@3.public: 3
41 o baz@3.public: 3
42 |
42 |
43 o test@2.public: 2
43 o test@2.public: 2
44 |
44 |
45 o bar@1.public: 1
45 o bar@1.public: 1
46 |
46 |
47 o test@0.public: 0
47 o test@0.public: 0
48
48
49 Test --base for grafting the merge of 4 from the perspective of 5, thus only getting the change to d
49 Test --base for grafting the merge of 4 from the perspective of 5, thus only getting the change to d
50
50
51 $ hg up -cqr 3
51 $ hg up -cqr 3
52 $ hg graft -r 6 --base 5
52 $ hg graft -r 6 --base 5
53 grafting 6:25a2b029d3ae "6" (tip)
53 grafting 6:25a2b029d3ae "6" (tip)
54 merging e
54 merging e
55 $ hg st --change .
55 $ hg st --change .
56 M d
56 M d
57
57
58 $ hg -q strip . --config extensions.strip=
58 $ hg -q strip . --config extensions.strip=
59
59
60 Test --base for collapsing changesets 2 and 3, thus getting both b and c
60 Test --base for collapsing changesets 2 and 3, thus getting both b and c
61
61
62 $ hg up -cqr 0
62 $ hg up -cqr 0
63 $ hg graft -r 3 --base 1
63 $ hg graft -r 3 --base 1
64 grafting 3:4c60f11aa304 "3"
64 grafting 3:4c60f11aa304 "3"
65 merging a and b to b
65 merging a and b to b
66 merging a and c to c
66 merging a and c to c
67 $ hg st --change .
67 $ hg st --change .
68 A b
68 A b
69 A c
69 A c
70 R a
70 R a
71
71
72 $ hg -q strip . --config extensions.strip=
72 $ hg -q strip . --config extensions.strip=
73
73
74 Specifying child as --base revision fails safely (perhaps slightly confusing, but consistent)
74 Specifying child as --base revision fails safely (perhaps slightly confusing, but consistent)
75
75
76 $ hg graft -r 2 --base 3
76 $ hg graft -r 2 --base 3
77 grafting 2:5c095ad7e90f "2"
77 grafting 2:5c095ad7e90f "2"
78 note: possible conflict - c was deleted and renamed to:
78 note: possible conflict - c was deleted and renamed to:
79 a
79 a
80 note: graft of 2:5c095ad7e90f created no changes to commit
80 note: graft of 2:5c095ad7e90f created no changes to commit
81
81
82 Can't continue without starting:
82 Can't continue without starting:
83
83
84 $ hg -q up -cr tip
84 $ hg -q up -cr tip
85 $ hg rm -q e
85 $ hg rm -q e
86 $ hg graft --continue
86 $ hg graft --continue
87 abort: no graft in progress
87 abort: no graft in progress
88 [255]
88 [255]
89 $ hg revert -r . -q e
89 $ hg revert -r . -q e
90
90
91 Need to specify a rev:
91 Need to specify a rev:
92
92
93 $ hg graft
93 $ hg graft
94 abort: no revisions specified
94 abort: no revisions specified
95 [255]
95 [255]
96
96
97 Can't graft ancestor:
97 Can't graft ancestor:
98
98
99 $ hg graft 1 2
99 $ hg graft 1 2
100 skipping ancestor revision 1:5d205f8b35b6
100 skipping ancestor revision 1:5d205f8b35b6
101 skipping ancestor revision 2:5c095ad7e90f
101 skipping ancestor revision 2:5c095ad7e90f
102 [255]
102 [255]
103
103
104 Specify revisions with -r:
104 Specify revisions with -r:
105
105
106 $ hg graft -r 1 -r 2
106 $ hg graft -r 1 -r 2
107 skipping ancestor revision 1:5d205f8b35b6
107 skipping ancestor revision 1:5d205f8b35b6
108 skipping ancestor revision 2:5c095ad7e90f
108 skipping ancestor revision 2:5c095ad7e90f
109 [255]
109 [255]
110
110
111 $ hg graft -r 1 2
111 $ hg graft -r 1 2
112 warning: inconsistent use of --rev might give unexpected revision ordering!
112 warning: inconsistent use of --rev might give unexpected revision ordering!
113 skipping ancestor revision 2:5c095ad7e90f
113 skipping ancestor revision 2:5c095ad7e90f
114 skipping ancestor revision 1:5d205f8b35b6
114 skipping ancestor revision 1:5d205f8b35b6
115 [255]
115 [255]
116
116
117 Conflicting date/user options:
117 Conflicting date/user options:
118
118
119 $ hg up -q 0
119 $ hg up -q 0
120 $ hg graft -U --user foo 2
120 $ hg graft -U --user foo 2
121 abort: cannot specify both --user and --currentuser
121 abort: cannot specify both --user and --currentuser
122 [255]
122 [255]
123 $ hg graft -D --date '0 0' 2
123 $ hg graft -D --date '0 0' 2
124 abort: cannot specify both --date and --currentdate
124 abort: cannot specify both --date and --currentdate
125 [255]
125 [255]
126
126
127 Can't graft with dirty wd:
127 Can't graft with dirty wd:
128
128
129 $ hg up -q 0
129 $ hg up -q 0
130 $ echo foo > a
130 $ echo foo > a
131 $ hg graft 1
131 $ hg graft 1
132 abort: uncommitted changes
132 abort: uncommitted changes
133 [255]
133 [255]
134 $ hg revert a
134 $ hg revert a
135
135
136 Graft a rename:
136 Graft a rename:
137 (this also tests that editor is invoked if '--edit' is specified)
137 (this also tests that editor is invoked if '--edit' is specified)
138
138
139 $ hg status --rev "2^1" --rev 2
139 $ hg status --rev "2^1" --rev 2
140 A b
140 A b
141 R a
141 R a
142 $ HGEDITOR=cat hg graft 2 -u foo --edit
142 $ HGEDITOR=cat hg graft 2 -u foo --edit
143 grafting 2:5c095ad7e90f "2"
143 grafting 2:5c095ad7e90f "2"
144 merging a and b to b
144 merging a and b to b
145 2
145 2
146
146
147
147
148 HG: Enter commit message. Lines beginning with 'HG:' are removed.
148 HG: Enter commit message. Lines beginning with 'HG:' are removed.
149 HG: Leave message empty to abort commit.
149 HG: Leave message empty to abort commit.
150 HG: --
150 HG: --
151 HG: user: foo
151 HG: user: foo
152 HG: branch 'default'
152 HG: branch 'default'
153 HG: added b
153 HG: added b
154 HG: removed a
154 HG: removed a
155 $ hg export tip --git
155 $ hg export tip --git
156 # HG changeset patch
156 # HG changeset patch
157 # User foo
157 # User foo
158 # Date 0 0
158 # Date 0 0
159 # Thu Jan 01 00:00:00 1970 +0000
159 # Thu Jan 01 00:00:00 1970 +0000
160 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
160 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
161 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
161 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
162 2
162 2
163
163
164 diff --git a/a b/b
164 diff --git a/a b/b
165 rename from a
165 rename from a
166 rename to b
166 rename to b
167
167
168 Look for extra:source
168 Look for extra:source
169
169
170 $ hg log --debug -r tip
170 $ hg log --debug -r tip
171 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
171 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
172 tag: tip
172 tag: tip
173 phase: draft
173 phase: draft
174 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
174 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
175 parent: -1:0000000000000000000000000000000000000000
175 parent: -1:0000000000000000000000000000000000000000
176 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
176 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
177 user: foo
177 user: foo
178 date: Thu Jan 01 00:00:00 1970 +0000
178 date: Thu Jan 01 00:00:00 1970 +0000
179 files+: b
179 files+: b
180 files-: a
180 files-: a
181 extra: branch=default
181 extra: branch=default
182 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
182 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
183 description:
183 description:
184 2
184 2
185
185
186
186
187
187
188 Graft out of order, skipping a merge and a duplicate
188 Graft out of order, skipping a merge and a duplicate
189 (this also tests that editor is not invoked if '--edit' is not specified)
189 (this also tests that editor is not invoked if '--edit' is not specified)
190
190
191 $ hg graft 1 5 4 3 'merge()' 2 -n
191 $ hg graft 1 5 4 3 'merge()' 2 -n
192 skipping ungraftable merge revision 6
192 skipping ungraftable merge revision 6
193 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
193 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
194 grafting 1:5d205f8b35b6 "1"
194 grafting 1:5d205f8b35b6 "1"
195 grafting 5:97f8bfe72746 "5"
195 grafting 5:97f8bfe72746 "5"
196 grafting 4:9c233e8e184d "4"
196 grafting 4:9c233e8e184d "4"
197 grafting 3:4c60f11aa304 "3"
197 grafting 3:4c60f11aa304 "3"
198
198
199 $ HGEDITOR=cat hg graft 1 5 'merge()' 2 --debug
199 $ HGEDITOR=cat hg graft 1 5 'merge()' 2 --debug
200 skipping ungraftable merge revision 6
200 skipping ungraftable merge revision 6
201 scanning for duplicate grafts
201 scanning for duplicate grafts
202 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
202 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
203 grafting 1:5d205f8b35b6 "1"
203 grafting 1:5d205f8b35b6 "1"
204 unmatched files in local:
204 unmatched files in local:
205 b
205 b
206 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
206 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
207 on local side:
207 on local side:
208 src: 'a' -> dst: 'b' *
208 src: 'a' -> dst: 'b' *
209 checking for directory renames
209 checking for directory renames
210 resolving manifests
210 resolving manifests
211 branchmerge: True, force: True, partial: False
211 branchmerge: True, force: True, partial: False
212 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
212 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
213 preserving b for resolve of b
213 preserving b for resolve of b
214 starting 4 threads for background file closing (?)
214 starting 4 threads for background file closing (?)
215 b: local copied/moved from a -> m (premerge)
215 b: local copied/moved from a -> m (premerge)
216 picked tool ':merge' for b (binary False symlink False changedelete False)
216 picked tool ':merge' for b (binary False symlink False changedelete False)
217 merging b and a to b
217 merging b and a to b
218 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
218 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
219 premerge successful
219 premerge successful
220 committing files:
220 committing files:
221 b
221 b
222 committing manifest
222 committing manifest
223 committing changelog
223 committing changelog
224 updating the branch cache
224 updating the branch cache
225 grafting 5:97f8bfe72746 "5"
225 grafting 5:97f8bfe72746 "5"
226 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
226 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
227 on local side:
227 on local side:
228 src: 'c' -> dst: 'b'
228 src: 'c' -> dst: 'b'
229 checking for directory renames
229 checking for directory renames
230 resolving manifests
230 resolving manifests
231 branchmerge: True, force: True, partial: False
231 branchmerge: True, force: True, partial: False
232 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
232 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
233 e: remote is newer -> g
233 e: remote is newer -> g
234 getting e
234 getting e
235 committing files:
235 committing files:
236 e
236 e
237 committing manifest
237 committing manifest
238 committing changelog
238 committing changelog
239 updating the branch cache
239 updating the branch cache
240 $ HGEDITOR=cat hg graft 4 3 --log --debug
240 $ HGEDITOR=cat hg graft 4 3 --log --debug
241 scanning for duplicate grafts
241 scanning for duplicate grafts
242 grafting 4:9c233e8e184d "4"
242 grafting 4:9c233e8e184d "4"
243 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
243 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
244 on local side:
244 on local side:
245 src: 'c' -> dst: 'b'
245 src: 'c' -> dst: 'b'
246 checking for directory renames
246 checking for directory renames
247 resolving manifests
247 resolving manifests
248 branchmerge: True, force: True, partial: False
248 branchmerge: True, force: True, partial: False
249 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
249 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
250 preserving e for resolve of e
250 preserving e for resolve of e
251 d: remote is newer -> g
251 d: remote is newer -> g
252 getting d
252 getting d
253 e: versions differ -> m (premerge)
253 e: versions differ -> m (premerge)
254 picked tool ':merge' for e (binary False symlink False changedelete False)
254 picked tool ':merge' for e (binary False symlink False changedelete False)
255 merging e
255 merging e
256 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
256 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
257 e: versions differ -> m (merge)
257 e: versions differ -> m (merge)
258 picked tool ':merge' for e (binary False symlink False changedelete False)
258 picked tool ':merge' for e (binary False symlink False changedelete False)
259 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
259 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
260 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
260 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
261 abort: unresolved conflicts, can't continue
261 abort: unresolved conflicts, can't continue
262 (use 'hg resolve' and 'hg graft --continue')
262 (use 'hg resolve' and 'hg graft --continue')
263 [255]
263 [1]
264
264
265 Summary should mention graft:
265 Summary should mention graft:
266
266
267 $ hg summary |grep graft
267 $ hg summary |grep graft
268 commit: 2 modified, 2 unknown, 1 unresolved (graft in progress)
268 commit: 2 modified, 2 unknown, 1 unresolved (graft in progress)
269
269
270 Using status to get more context
270 Using status to get more context
271
271
272 $ hg status --verbose
272 $ hg status --verbose
273 M d
273 M d
274 M e
274 M e
275 ? a.orig
275 ? a.orig
276 ? e.orig
276 ? e.orig
277 # The repository is in an unfinished *graft* state.
277 # The repository is in an unfinished *graft* state.
278
278
279 # Unresolved merge conflicts:
279 # Unresolved merge conflicts:
280 #
280 #
281 # e
281 # e
282 #
282 #
283 # To mark files as resolved: hg resolve --mark FILE
283 # To mark files as resolved: hg resolve --mark FILE
284
284
285 # To continue: hg graft --continue
285 # To continue: hg graft --continue
286 # To abort: hg graft --abort
286 # To abort: hg graft --abort
287 # To stop: hg graft --stop
287 # To stop: hg graft --stop
288
288
289
289
290 Commit while interrupted should fail:
290 Commit while interrupted should fail:
291
291
292 $ hg ci -m 'commit interrupted graft'
292 $ hg ci -m 'commit interrupted graft'
293 abort: graft in progress
293 abort: graft in progress
294 (use 'hg graft --continue' or 'hg graft --stop' to stop)
294 (use 'hg graft --continue' or 'hg graft --stop' to stop)
295 [255]
295 [255]
296
296
297 Abort the graft and try committing:
297 Abort the graft and try committing:
298
298
299 $ hg up -C .
299 $ hg up -C .
300 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
300 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
301 $ echo c >> e
301 $ echo c >> e
302 $ hg ci -mtest
302 $ hg ci -mtest
303
303
304 $ hg strip . --config extensions.strip=
304 $ hg strip . --config extensions.strip=
305 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
305 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
306 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
306 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
307
307
308 Graft again:
308 Graft again:
309
309
310 $ hg graft 1 5 4 3 'merge()' 2
310 $ hg graft 1 5 4 3 'merge()' 2
311 skipping ungraftable merge revision 6
311 skipping ungraftable merge revision 6
312 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
312 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
313 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
313 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
314 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
314 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
315 grafting 4:9c233e8e184d "4"
315 grafting 4:9c233e8e184d "4"
316 merging e
316 merging e
317 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
317 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
318 abort: unresolved conflicts, can't continue
318 abort: unresolved conflicts, can't continue
319 (use 'hg resolve' and 'hg graft --continue')
319 (use 'hg resolve' and 'hg graft --continue')
320 [255]
320 [1]
321
321
322 Continue without resolve should fail:
322 Continue without resolve should fail:
323
323
324 $ hg graft -c
324 $ hg graft -c
325 grafting 4:9c233e8e184d "4"
325 grafting 4:9c233e8e184d "4"
326 abort: unresolved merge conflicts (see 'hg help resolve')
326 abort: unresolved merge conflicts (see 'hg help resolve')
327 [255]
327 [255]
328
328
329 Fix up:
329 Fix up:
330
330
331 $ echo b > e
331 $ echo b > e
332 $ hg resolve -m e
332 $ hg resolve -m e
333 (no more unresolved files)
333 (no more unresolved files)
334 continue: hg graft --continue
334 continue: hg graft --continue
335
335
336 Continue with a revision should fail:
336 Continue with a revision should fail:
337
337
338 $ hg graft -c 6
338 $ hg graft -c 6
339 abort: can't specify --continue and revisions
339 abort: can't specify --continue and revisions
340 [255]
340 [255]
341
341
342 $ hg graft -c -r 6
342 $ hg graft -c -r 6
343 abort: can't specify --continue and revisions
343 abort: can't specify --continue and revisions
344 [255]
344 [255]
345
345
346 Continue for real, clobber usernames
346 Continue for real, clobber usernames
347
347
348 $ hg graft -c -U
348 $ hg graft -c -U
349 grafting 4:9c233e8e184d "4"
349 grafting 4:9c233e8e184d "4"
350 grafting 3:4c60f11aa304 "3"
350 grafting 3:4c60f11aa304 "3"
351
351
352 Compare with original:
352 Compare with original:
353
353
354 $ hg diff -r 6
354 $ hg diff -r 6
355 $ hg status --rev 0:. -C
355 $ hg status --rev 0:. -C
356 M d
356 M d
357 M e
357 M e
358 A b
358 A b
359 a
359 a
360 A c
360 A c
361 a
361 a
362 R a
362 R a
363
363
364 View graph:
364 View graph:
365
365
366 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
366 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
367 @ test@11.draft: 3
367 @ test@11.draft: 3
368 |
368 |
369 o test@10.draft: 4
369 o test@10.draft: 4
370 |
370 |
371 o test@9.draft: 5
371 o test@9.draft: 5
372 |
372 |
373 o bar@8.draft: 1
373 o bar@8.draft: 1
374 |
374 |
375 o foo@7.draft: 2
375 o foo@7.draft: 2
376 |
376 |
377 | o test@6.secret: 6
377 | o test@6.secret: 6
378 | |\
378 | |\
379 | | o test@5.draft: 5
379 | | o test@5.draft: 5
380 | | |
380 | | |
381 | o | test@4.draft: 4
381 | o | test@4.draft: 4
382 | |/
382 | |/
383 | o baz@3.public: 3
383 | o baz@3.public: 3
384 | |
384 | |
385 | o test@2.public: 2
385 | o test@2.public: 2
386 | |
386 | |
387 | o bar@1.public: 1
387 | o bar@1.public: 1
388 |/
388 |/
389 o test@0.public: 0
389 o test@0.public: 0
390
390
391 Graft again onto another branch should preserve the original source
391 Graft again onto another branch should preserve the original source
392 $ hg up -q 0
392 $ hg up -q 0
393 $ echo 'g'>g
393 $ echo 'g'>g
394 $ hg add g
394 $ hg add g
395 $ hg ci -m 7
395 $ hg ci -m 7
396 created new head
396 created new head
397 $ hg graft 7
397 $ hg graft 7
398 grafting 7:ef0ef43d49e7 "2"
398 grafting 7:ef0ef43d49e7 "2"
399
399
400 $ hg log -r 7 --template '{rev}:{node}\n'
400 $ hg log -r 7 --template '{rev}:{node}\n'
401 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
401 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
402 $ hg log -r 2 --template '{rev}:{node}\n'
402 $ hg log -r 2 --template '{rev}:{node}\n'
403 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
403 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
404
404
405 $ hg log --debug -r tip
405 $ hg log --debug -r tip
406 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
406 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
407 tag: tip
407 tag: tip
408 phase: draft
408 phase: draft
409 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
409 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
410 parent: -1:0000000000000000000000000000000000000000
410 parent: -1:0000000000000000000000000000000000000000
411 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
411 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
412 user: foo
412 user: foo
413 date: Thu Jan 01 00:00:00 1970 +0000
413 date: Thu Jan 01 00:00:00 1970 +0000
414 files+: b
414 files+: b
415 files-: a
415 files-: a
416 extra: branch=default
416 extra: branch=default
417 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
417 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
418 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
418 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
419 description:
419 description:
420 2
420 2
421
421
422
422
423 Disallow grafting an already grafted cset onto its original branch
423 Disallow grafting an already grafted cset onto its original branch
424 $ hg up -q 6
424 $ hg up -q 6
425 $ hg graft 7
425 $ hg graft 7
426 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
426 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
427 [255]
427 [255]
428
428
429 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13
429 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13
430 --- */hg-5c095ad7e90f.patch * (glob)
430 --- */hg-5c095ad7e90f.patch * (glob)
431 +++ */hg-7a4785234d87.patch * (glob)
431 +++ */hg-7a4785234d87.patch * (glob)
432 @@ -1,18 +1,18 @@
432 @@ -1,18 +1,18 @@
433 # HG changeset patch
433 # HG changeset patch
434 -# User test
434 -# User test
435 +# User foo
435 +# User foo
436 # Date 0 0
436 # Date 0 0
437 # Thu Jan 01 00:00:00 1970 +0000
437 # Thu Jan 01 00:00:00 1970 +0000
438 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
438 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
439 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
439 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
440 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
440 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
441 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
441 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
442 2
442 2
443
443
444 -diff -r 5d205f8b35b6 -r 5c095ad7e90f a
444 -diff -r 5d205f8b35b6 -r 5c095ad7e90f a
445 +diff -r b592ea63bb0c -r 7a4785234d87 a
445 +diff -r b592ea63bb0c -r 7a4785234d87 a
446 --- a/a Thu Jan 01 00:00:00 1970 +0000
446 --- a/a Thu Jan 01 00:00:00 1970 +0000
447 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
447 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
448 @@ -1,1 +0,0 @@
448 @@ -1,1 +0,0 @@
449 --b
449 --b
450 -diff -r 5d205f8b35b6 -r 5c095ad7e90f b
450 -diff -r 5d205f8b35b6 -r 5c095ad7e90f b
451 +-a
451 +-a
452 +diff -r b592ea63bb0c -r 7a4785234d87 b
452 +diff -r b592ea63bb0c -r 7a4785234d87 b
453 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
453 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
454 +++ b/b Thu Jan 01 00:00:00 1970 +0000
454 +++ b/b Thu Jan 01 00:00:00 1970 +0000
455 @@ -0,0 +1,1 @@
455 @@ -0,0 +1,1 @@
456 -+b
456 -+b
457 ++a
457 ++a
458 [1]
458 [1]
459
459
460 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13 -X .
460 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13 -X .
461 --- */hg-5c095ad7e90f.patch * (glob)
461 --- */hg-5c095ad7e90f.patch * (glob)
462 +++ */hg-7a4785234d87.patch * (glob)
462 +++ */hg-7a4785234d87.patch * (glob)
463 @@ -1,8 +1,8 @@
463 @@ -1,8 +1,8 @@
464 # HG changeset patch
464 # HG changeset patch
465 -# User test
465 -# User test
466 +# User foo
466 +# User foo
467 # Date 0 0
467 # Date 0 0
468 # Thu Jan 01 00:00:00 1970 +0000
468 # Thu Jan 01 00:00:00 1970 +0000
469 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
469 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
470 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
470 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
471 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
471 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
472 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
472 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
473 2
473 2
474
474
475 [1]
475 [1]
476
476
477 Disallow grafting already grafted csets with the same origin onto each other
477 Disallow grafting already grafted csets with the same origin onto each other
478 $ hg up -q 13
478 $ hg up -q 13
479 $ hg graft 2
479 $ hg graft 2
480 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
480 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
481 [255]
481 [255]
482 $ hg graft 7
482 $ hg graft 7
483 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
483 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
484 [255]
484 [255]
485
485
486 $ hg up -q 7
486 $ hg up -q 7
487 $ hg graft 2
487 $ hg graft 2
488 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
488 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
489 [255]
489 [255]
490 $ hg graft tip
490 $ hg graft tip
491 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
491 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
492 [255]
492 [255]
493
493
494 Graft with --log
494 Graft with --log
495
495
496 $ hg up -Cq 1
496 $ hg up -Cq 1
497 $ hg graft 3 --log -u foo
497 $ hg graft 3 --log -u foo
498 grafting 3:4c60f11aa304 "3"
498 grafting 3:4c60f11aa304 "3"
499 $ hg log --template '{rev}:{node|short} {parents} {desc}\n' -r tip
499 $ hg log --template '{rev}:{node|short} {parents} {desc}\n' -r tip
500 14:0c921c65ef1e 1:5d205f8b35b6 3
500 14:0c921c65ef1e 1:5d205f8b35b6 3
501 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
501 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
502
502
503 Resolve conflicted graft
503 Resolve conflicted graft
504 $ hg up -q 0
504 $ hg up -q 0
505 $ echo b > a
505 $ echo b > a
506 $ hg ci -m 8
506 $ hg ci -m 8
507 created new head
507 created new head
508 $ echo c > a
508 $ echo c > a
509 $ hg ci -m 9
509 $ hg ci -m 9
510 $ hg graft 1 --tool internal:fail
510 $ hg graft 1 --tool internal:fail
511 grafting 1:5d205f8b35b6 "1"
511 grafting 1:5d205f8b35b6 "1"
512 abort: unresolved conflicts, can't continue
512 abort: unresolved conflicts, can't continue
513 (use 'hg resolve' and 'hg graft --continue')
513 (use 'hg resolve' and 'hg graft --continue')
514 [255]
514 [1]
515 $ hg resolve --all
515 $ hg resolve --all
516 merging a
516 merging a
517 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
517 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
518 [1]
518 [1]
519 $ cat a
519 $ cat a
520 <<<<<<< local: aaa4406d4f0a - test: 9
520 <<<<<<< local: aaa4406d4f0a - test: 9
521 c
521 c
522 =======
522 =======
523 b
523 b
524 >>>>>>> graft: 5d205f8b35b6 - bar: 1
524 >>>>>>> graft: 5d205f8b35b6 - bar: 1
525 $ echo b > a
525 $ echo b > a
526 $ hg resolve -m a
526 $ hg resolve -m a
527 (no more unresolved files)
527 (no more unresolved files)
528 continue: hg graft --continue
528 continue: hg graft --continue
529 $ hg graft -c
529 $ hg graft -c
530 grafting 1:5d205f8b35b6 "1"
530 grafting 1:5d205f8b35b6 "1"
531 $ hg export tip --git
531 $ hg export tip --git
532 # HG changeset patch
532 # HG changeset patch
533 # User bar
533 # User bar
534 # Date 0 0
534 # Date 0 0
535 # Thu Jan 01 00:00:00 1970 +0000
535 # Thu Jan 01 00:00:00 1970 +0000
536 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
536 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
537 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
537 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
538 1
538 1
539
539
540 diff --git a/a b/a
540 diff --git a/a b/a
541 --- a/a
541 --- a/a
542 +++ b/a
542 +++ b/a
543 @@ -1,1 +1,1 @@
543 @@ -1,1 +1,1 @@
544 -c
544 -c
545 +b
545 +b
546
546
547 Resolve conflicted graft with rename
547 Resolve conflicted graft with rename
548 $ echo c > a
548 $ echo c > a
549 $ hg ci -m 10
549 $ hg ci -m 10
550 $ hg graft 2 --tool internal:fail
550 $ hg graft 2 --tool internal:fail
551 grafting 2:5c095ad7e90f "2"
551 grafting 2:5c095ad7e90f "2"
552 abort: unresolved conflicts, can't continue
552 abort: unresolved conflicts, can't continue
553 (use 'hg resolve' and 'hg graft --continue')
553 (use 'hg resolve' and 'hg graft --continue')
554 [255]
554 [1]
555 $ hg resolve --all
555 $ hg resolve --all
556 merging a and b to b
556 merging a and b to b
557 (no more unresolved files)
557 (no more unresolved files)
558 continue: hg graft --continue
558 continue: hg graft --continue
559 $ hg graft -c
559 $ hg graft -c
560 grafting 2:5c095ad7e90f "2"
560 grafting 2:5c095ad7e90f "2"
561 $ hg export tip --git
561 $ hg export tip --git
562 # HG changeset patch
562 # HG changeset patch
563 # User test
563 # User test
564 # Date 0 0
564 # Date 0 0
565 # Thu Jan 01 00:00:00 1970 +0000
565 # Thu Jan 01 00:00:00 1970 +0000
566 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
566 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
567 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
567 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
568 2
568 2
569
569
570 diff --git a/a b/b
570 diff --git a/a b/b
571 rename from a
571 rename from a
572 rename to b
572 rename to b
573
573
574 Test simple origin(), with and without args
574 Test simple origin(), with and without args
575 $ hg log -r 'origin()'
575 $ hg log -r 'origin()'
576 changeset: 1:5d205f8b35b6
576 changeset: 1:5d205f8b35b6
577 user: bar
577 user: bar
578 date: Thu Jan 01 00:00:00 1970 +0000
578 date: Thu Jan 01 00:00:00 1970 +0000
579 summary: 1
579 summary: 1
580
580
581 changeset: 2:5c095ad7e90f
581 changeset: 2:5c095ad7e90f
582 user: test
582 user: test
583 date: Thu Jan 01 00:00:00 1970 +0000
583 date: Thu Jan 01 00:00:00 1970 +0000
584 summary: 2
584 summary: 2
585
585
586 changeset: 3:4c60f11aa304
586 changeset: 3:4c60f11aa304
587 user: baz
587 user: baz
588 date: Thu Jan 01 00:00:00 1970 +0000
588 date: Thu Jan 01 00:00:00 1970 +0000
589 summary: 3
589 summary: 3
590
590
591 changeset: 4:9c233e8e184d
591 changeset: 4:9c233e8e184d
592 user: test
592 user: test
593 date: Thu Jan 01 00:00:00 1970 +0000
593 date: Thu Jan 01 00:00:00 1970 +0000
594 summary: 4
594 summary: 4
595
595
596 changeset: 5:97f8bfe72746
596 changeset: 5:97f8bfe72746
597 branch: stable
597 branch: stable
598 parent: 3:4c60f11aa304
598 parent: 3:4c60f11aa304
599 user: test
599 user: test
600 date: Thu Jan 01 00:00:00 1970 +0000
600 date: Thu Jan 01 00:00:00 1970 +0000
601 summary: 5
601 summary: 5
602
602
603 $ hg log -r 'origin(7)'
603 $ hg log -r 'origin(7)'
604 changeset: 2:5c095ad7e90f
604 changeset: 2:5c095ad7e90f
605 user: test
605 user: test
606 date: Thu Jan 01 00:00:00 1970 +0000
606 date: Thu Jan 01 00:00:00 1970 +0000
607 summary: 2
607 summary: 2
608
608
609 Now transplant a graft to test following through copies
609 Now transplant a graft to test following through copies
610 $ hg up -q 0
610 $ hg up -q 0
611 $ hg branch -q dev
611 $ hg branch -q dev
612 $ hg ci -qm "dev branch"
612 $ hg ci -qm "dev branch"
613 $ hg --config extensions.transplant= transplant -q 7
613 $ hg --config extensions.transplant= transplant -q 7
614 $ hg log -r 'origin(.)'
614 $ hg log -r 'origin(.)'
615 changeset: 2:5c095ad7e90f
615 changeset: 2:5c095ad7e90f
616 user: test
616 user: test
617 date: Thu Jan 01 00:00:00 1970 +0000
617 date: Thu Jan 01 00:00:00 1970 +0000
618 summary: 2
618 summary: 2
619
619
620 Test that the graft and transplant markers in extra are converted, allowing
620 Test that the graft and transplant markers in extra are converted, allowing
621 origin() to still work. Note that these recheck the immediately preceeding two
621 origin() to still work. Note that these recheck the immediately preceeding two
622 tests.
622 tests.
623 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
623 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
624
624
625 The graft case
625 The graft case
626 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
626 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
627 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
627 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
628 branch=default
628 branch=default
629 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
629 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
630 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
630 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
631 $ hg -R ../converted log -r 'origin(7)'
631 $ hg -R ../converted log -r 'origin(7)'
632 changeset: 2:e0213322b2c1
632 changeset: 2:e0213322b2c1
633 user: test
633 user: test
634 date: Thu Jan 01 00:00:00 1970 +0000
634 date: Thu Jan 01 00:00:00 1970 +0000
635 summary: 2
635 summary: 2
636
636
637 Test that template correctly expands more than one 'extra' (issue4362), and that
637 Test that template correctly expands more than one 'extra' (issue4362), and that
638 'intermediate-source' is converted.
638 'intermediate-source' is converted.
639 $ hg -R ../converted log -r 13 --template "{extras % ' Extra: {extra}\n'}"
639 $ hg -R ../converted log -r 13 --template "{extras % ' Extra: {extra}\n'}"
640 Extra: branch=default
640 Extra: branch=default
641 Extra: convert_revision=7a4785234d87ec1aa420ed6b11afe40fa73e12a9
641 Extra: convert_revision=7a4785234d87ec1aa420ed6b11afe40fa73e12a9
642 Extra: intermediate-source=7ae846e9111fc8f57745634250c7b9ac0a60689b
642 Extra: intermediate-source=7ae846e9111fc8f57745634250c7b9ac0a60689b
643 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
643 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
644
644
645 The transplant case
645 The transplant case
646 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
646 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
647 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
647 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
648 branch=dev
648 branch=dev
649 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
649 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
650 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac\n`h\x9b
650 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac\n`h\x9b
651 $ hg -R ../converted log -r 'origin(tip)'
651 $ hg -R ../converted log -r 'origin(tip)'
652 changeset: 2:e0213322b2c1
652 changeset: 2:e0213322b2c1
653 user: test
653 user: test
654 date: Thu Jan 01 00:00:00 1970 +0000
654 date: Thu Jan 01 00:00:00 1970 +0000
655 summary: 2
655 summary: 2
656
656
657
657
658 Test simple destination
658 Test simple destination
659 $ hg log -r 'destination()'
659 $ hg log -r 'destination()'
660 changeset: 7:ef0ef43d49e7
660 changeset: 7:ef0ef43d49e7
661 parent: 0:68795b066622
661 parent: 0:68795b066622
662 user: foo
662 user: foo
663 date: Thu Jan 01 00:00:00 1970 +0000
663 date: Thu Jan 01 00:00:00 1970 +0000
664 summary: 2
664 summary: 2
665
665
666 changeset: 8:6b9e5368ca4e
666 changeset: 8:6b9e5368ca4e
667 user: bar
667 user: bar
668 date: Thu Jan 01 00:00:00 1970 +0000
668 date: Thu Jan 01 00:00:00 1970 +0000
669 summary: 1
669 summary: 1
670
670
671 changeset: 9:1905859650ec
671 changeset: 9:1905859650ec
672 user: test
672 user: test
673 date: Thu Jan 01 00:00:00 1970 +0000
673 date: Thu Jan 01 00:00:00 1970 +0000
674 summary: 5
674 summary: 5
675
675
676 changeset: 10:52dc0b4c6907
676 changeset: 10:52dc0b4c6907
677 user: test
677 user: test
678 date: Thu Jan 01 00:00:00 1970 +0000
678 date: Thu Jan 01 00:00:00 1970 +0000
679 summary: 4
679 summary: 4
680
680
681 changeset: 11:882b35362a6b
681 changeset: 11:882b35362a6b
682 user: test
682 user: test
683 date: Thu Jan 01 00:00:00 1970 +0000
683 date: Thu Jan 01 00:00:00 1970 +0000
684 summary: 3
684 summary: 3
685
685
686 changeset: 13:7a4785234d87
686 changeset: 13:7a4785234d87
687 user: foo
687 user: foo
688 date: Thu Jan 01 00:00:00 1970 +0000
688 date: Thu Jan 01 00:00:00 1970 +0000
689 summary: 2
689 summary: 2
690
690
691 changeset: 14:0c921c65ef1e
691 changeset: 14:0c921c65ef1e
692 parent: 1:5d205f8b35b6
692 parent: 1:5d205f8b35b6
693 user: foo
693 user: foo
694 date: Thu Jan 01 00:00:00 1970 +0000
694 date: Thu Jan 01 00:00:00 1970 +0000
695 summary: 3
695 summary: 3
696
696
697 changeset: 17:f67661df0c48
697 changeset: 17:f67661df0c48
698 user: bar
698 user: bar
699 date: Thu Jan 01 00:00:00 1970 +0000
699 date: Thu Jan 01 00:00:00 1970 +0000
700 summary: 1
700 summary: 1
701
701
702 changeset: 19:9627f653b421
702 changeset: 19:9627f653b421
703 user: test
703 user: test
704 date: Thu Jan 01 00:00:00 1970 +0000
704 date: Thu Jan 01 00:00:00 1970 +0000
705 summary: 2
705 summary: 2
706
706
707 changeset: 21:7e61b508e709
707 changeset: 21:7e61b508e709
708 branch: dev
708 branch: dev
709 tag: tip
709 tag: tip
710 user: foo
710 user: foo
711 date: Thu Jan 01 00:00:00 1970 +0000
711 date: Thu Jan 01 00:00:00 1970 +0000
712 summary: 2
712 summary: 2
713
713
714 $ hg log -r 'destination(2)'
714 $ hg log -r 'destination(2)'
715 changeset: 7:ef0ef43d49e7
715 changeset: 7:ef0ef43d49e7
716 parent: 0:68795b066622
716 parent: 0:68795b066622
717 user: foo
717 user: foo
718 date: Thu Jan 01 00:00:00 1970 +0000
718 date: Thu Jan 01 00:00:00 1970 +0000
719 summary: 2
719 summary: 2
720
720
721 changeset: 13:7a4785234d87
721 changeset: 13:7a4785234d87
722 user: foo
722 user: foo
723 date: Thu Jan 01 00:00:00 1970 +0000
723 date: Thu Jan 01 00:00:00 1970 +0000
724 summary: 2
724 summary: 2
725
725
726 changeset: 19:9627f653b421
726 changeset: 19:9627f653b421
727 user: test
727 user: test
728 date: Thu Jan 01 00:00:00 1970 +0000
728 date: Thu Jan 01 00:00:00 1970 +0000
729 summary: 2
729 summary: 2
730
730
731 changeset: 21:7e61b508e709
731 changeset: 21:7e61b508e709
732 branch: dev
732 branch: dev
733 tag: tip
733 tag: tip
734 user: foo
734 user: foo
735 date: Thu Jan 01 00:00:00 1970 +0000
735 date: Thu Jan 01 00:00:00 1970 +0000
736 summary: 2
736 summary: 2
737
737
738 Transplants of grafts can find a destination...
738 Transplants of grafts can find a destination...
739 $ hg log -r 'destination(7)'
739 $ hg log -r 'destination(7)'
740 changeset: 21:7e61b508e709
740 changeset: 21:7e61b508e709
741 branch: dev
741 branch: dev
742 tag: tip
742 tag: tip
743 user: foo
743 user: foo
744 date: Thu Jan 01 00:00:00 1970 +0000
744 date: Thu Jan 01 00:00:00 1970 +0000
745 summary: 2
745 summary: 2
746
746
747 ... grafts of grafts unfortunately can't
747 ... grafts of grafts unfortunately can't
748 $ hg graft -q 13 --debug
748 $ hg graft -q 13 --debug
749 scanning for duplicate grafts
749 scanning for duplicate grafts
750 grafting 13:7a4785234d87 "2"
750 grafting 13:7a4785234d87 "2"
751 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
751 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
752 on local side:
752 on local side:
753 src: 'a' -> dst: 'b' *
753 src: 'a' -> dst: 'b' *
754 on remote side:
754 on remote side:
755 src: 'a' -> dst: 'b' *
755 src: 'a' -> dst: 'b' *
756 checking for directory renames
756 checking for directory renames
757 resolving manifests
757 resolving manifests
758 branchmerge: True, force: True, partial: False
758 branchmerge: True, force: True, partial: False
759 ancestor: b592ea63bb0c, local: 7e61b508e709+, remote: 7a4785234d87
759 ancestor: b592ea63bb0c, local: 7e61b508e709+, remote: 7a4785234d87
760 starting 4 threads for background file closing (?)
760 starting 4 threads for background file closing (?)
761 nothing to commit, clearing merge state
761 nothing to commit, clearing merge state
762 note: graft of 13:7a4785234d87 created no changes to commit
762 note: graft of 13:7a4785234d87 created no changes to commit
763 $ hg log -r 'destination(13)'
763 $ hg log -r 'destination(13)'
764 All copies of a cset
764 All copies of a cset
765 $ hg log -r 'origin(13) or destination(origin(13))'
765 $ hg log -r 'origin(13) or destination(origin(13))'
766 changeset: 2:5c095ad7e90f
766 changeset: 2:5c095ad7e90f
767 user: test
767 user: test
768 date: Thu Jan 01 00:00:00 1970 +0000
768 date: Thu Jan 01 00:00:00 1970 +0000
769 summary: 2
769 summary: 2
770
770
771 changeset: 7:ef0ef43d49e7
771 changeset: 7:ef0ef43d49e7
772 parent: 0:68795b066622
772 parent: 0:68795b066622
773 user: foo
773 user: foo
774 date: Thu Jan 01 00:00:00 1970 +0000
774 date: Thu Jan 01 00:00:00 1970 +0000
775 summary: 2
775 summary: 2
776
776
777 changeset: 13:7a4785234d87
777 changeset: 13:7a4785234d87
778 user: foo
778 user: foo
779 date: Thu Jan 01 00:00:00 1970 +0000
779 date: Thu Jan 01 00:00:00 1970 +0000
780 summary: 2
780 summary: 2
781
781
782 changeset: 19:9627f653b421
782 changeset: 19:9627f653b421
783 user: test
783 user: test
784 date: Thu Jan 01 00:00:00 1970 +0000
784 date: Thu Jan 01 00:00:00 1970 +0000
785 summary: 2
785 summary: 2
786
786
787 changeset: 21:7e61b508e709
787 changeset: 21:7e61b508e709
788 branch: dev
788 branch: dev
789 tag: tip
789 tag: tip
790 user: foo
790 user: foo
791 date: Thu Jan 01 00:00:00 1970 +0000
791 date: Thu Jan 01 00:00:00 1970 +0000
792 summary: 2
792 summary: 2
793
793
794
794
795 graft skips ancestors
795 graft skips ancestors
796
796
797 $ hg graft 21 3
797 $ hg graft 21 3
798 skipping ancestor revision 21:7e61b508e709
798 skipping ancestor revision 21:7e61b508e709
799 grafting 3:4c60f11aa304 "3"
799 grafting 3:4c60f11aa304 "3"
800 merging b and c to c
800 merging b and c to c
801
801
802 graft with --force (still doesn't graft merges)
802 graft with --force (still doesn't graft merges)
803
803
804 $ hg graft 19 0 6
804 $ hg graft 19 0 6
805 skipping ungraftable merge revision 6
805 skipping ungraftable merge revision 6
806 skipping ancestor revision 0:68795b066622
806 skipping ancestor revision 0:68795b066622
807 grafting 19:9627f653b421 "2"
807 grafting 19:9627f653b421 "2"
808 merging b
808 merging b
809 note: graft of 19:9627f653b421 created no changes to commit
809 note: graft of 19:9627f653b421 created no changes to commit
810 $ hg graft 19 0 6 --force
810 $ hg graft 19 0 6 --force
811 skipping ungraftable merge revision 6
811 skipping ungraftable merge revision 6
812 grafting 19:9627f653b421 "2"
812 grafting 19:9627f653b421 "2"
813 merging b
813 merging b
814 note: graft of 19:9627f653b421 created no changes to commit
814 note: graft of 19:9627f653b421 created no changes to commit
815 grafting 0:68795b066622 "0"
815 grafting 0:68795b066622 "0"
816
816
817 graft --force after backout. Do the backout with graft too, to make
817 graft --force after backout. Do the backout with graft too, to make
818 sure we support issue6248.
818 sure we support issue6248.
819
819
820 $ echo abc > a
820 $ echo abc > a
821 $ hg ci -m 24
821 $ hg ci -m 24
822 $ hg graft --base . -r ".^" --no-commit
822 $ hg graft --base . -r ".^" --no-commit
823 grafting 23:b1cac6de36a9 "0"
823 grafting 23:b1cac6de36a9 "0"
824 $ hg commit -m 'Backed out changeset 2e7ea477be26'
824 $ hg commit -m 'Backed out changeset 2e7ea477be26'
825 $ hg graft 24
825 $ hg graft 24
826 skipping ancestor revision 24:2e7ea477be26
826 skipping ancestor revision 24:2e7ea477be26
827 [255]
827 [255]
828 $ hg graft 24 --force
828 $ hg graft 24 --force
829 grafting 24:2e7ea477be26 "24"
829 grafting 24:2e7ea477be26 "24"
830 merging a
830 merging a
831 $ cat a
831 $ cat a
832 abc
832 abc
833
833
834 graft --continue after --force
834 graft --continue after --force
835
835
836 $ echo def > a
836 $ echo def > a
837 $ hg ci -m 27
837 $ hg ci -m 27
838 $ hg graft 24 --force --tool internal:fail
838 $ hg graft 24 --force --tool internal:fail
839 grafting 24:2e7ea477be26 "24"
839 grafting 24:2e7ea477be26 "24"
840 abort: unresolved conflicts, can't continue
840 abort: unresolved conflicts, can't continue
841 (use 'hg resolve' and 'hg graft --continue')
841 (use 'hg resolve' and 'hg graft --continue')
842 [255]
842 [1]
843 $ hg resolve --all
843 $ hg resolve --all
844 merging a
844 merging a
845 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
845 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
846 [1]
846 [1]
847 $ echo abc > a
847 $ echo abc > a
848 $ hg resolve -m a
848 $ hg resolve -m a
849 (no more unresolved files)
849 (no more unresolved files)
850 continue: hg graft --continue
850 continue: hg graft --continue
851 $ hg graft -c
851 $ hg graft -c
852 grafting 24:2e7ea477be26 "24"
852 grafting 24:2e7ea477be26 "24"
853 $ cat a
853 $ cat a
854 abc
854 abc
855
855
856 Continue testing same origin policy, using revision numbers from test above
856 Continue testing same origin policy, using revision numbers from test above
857 but do some destructive editing of the repo:
857 but do some destructive editing of the repo:
858
858
859 $ hg up -qC 7
859 $ hg up -qC 7
860 $ hg tag -l -r 13 tmp
860 $ hg tag -l -r 13 tmp
861 $ hg --config extensions.strip= strip 2
861 $ hg --config extensions.strip= strip 2
862 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg
862 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg
863 $ hg graft tmp
863 $ hg graft tmp
864 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
864 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
865 [255]
865 [255]
866
866
867 Empty graft
867 Empty graft
868
868
869 $ hg up -qr 22
869 $ hg up -qr 22
870 $ hg tag -f something
870 $ hg tag -f something
871 $ hg graft -qr 23
871 $ hg graft -qr 23
872 $ hg graft -f 23
872 $ hg graft -f 23
873 grafting 23:72d9c7c75bcc "24"
873 grafting 23:72d9c7c75bcc "24"
874 note: graft of 23:72d9c7c75bcc created no changes to commit
874 note: graft of 23:72d9c7c75bcc created no changes to commit
875
875
876 $ cd ..
876 $ cd ..
877
877
878 Graft to duplicate a commit
878 Graft to duplicate a commit
879
879
880 $ hg init graftsibling
880 $ hg init graftsibling
881 $ cd graftsibling
881 $ cd graftsibling
882 $ touch a
882 $ touch a
883 $ hg commit -qAm a
883 $ hg commit -qAm a
884 $ touch b
884 $ touch b
885 $ hg commit -qAm b
885 $ hg commit -qAm b
886 $ hg log -G -T '{rev}\n'
886 $ hg log -G -T '{rev}\n'
887 @ 1
887 @ 1
888 |
888 |
889 o 0
889 o 0
890
890
891 $ hg up -q 0
891 $ hg up -q 0
892 $ hg graft -r 1
892 $ hg graft -r 1
893 grafting 1:0e067c57feba "b" (tip)
893 grafting 1:0e067c57feba "b" (tip)
894 $ hg log -G -T '{rev}\n'
894 $ hg log -G -T '{rev}\n'
895 @ 2
895 @ 2
896 |
896 |
897 | o 1
897 | o 1
898 |/
898 |/
899 o 0
899 o 0
900
900
901 Graft to duplicate a commit twice
901 Graft to duplicate a commit twice
902
902
903 $ hg up -q 0
903 $ hg up -q 0
904 $ hg graft -r 2
904 $ hg graft -r 2
905 grafting 2:044ec77f6389 "b" (tip)
905 grafting 2:044ec77f6389 "b" (tip)
906 $ hg log -G -T '{rev}\n'
906 $ hg log -G -T '{rev}\n'
907 @ 3
907 @ 3
908 |
908 |
909 | o 2
909 | o 2
910 |/
910 |/
911 | o 1
911 | o 1
912 |/
912 |/
913 o 0
913 o 0
914
914
@@ -1,96 +1,96 b''
1 https://bz.mercurial-scm.org/1175
1 https://bz.mercurial-scm.org/1175
2
2
3 $ hg init
3 $ hg init
4 $ touch a
4 $ touch a
5 $ hg ci -Am0
5 $ hg ci -Am0
6 adding a
6 adding a
7
7
8 $ hg mv a a1
8 $ hg mv a a1
9 $ hg ci -m1
9 $ hg ci -m1
10
10
11 $ hg co 0
11 $ hg co 0
12 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
12 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
13
13
14 $ hg mv a a2
14 $ hg mv a a2
15 $ hg up
15 $ hg up
16 note: possible conflict - a was renamed multiple times to:
16 note: possible conflict - a was renamed multiple times to:
17 a1
17 a1
18 a2
18 a2
19 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
19 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20
20
21 $ hg ci -m2
21 $ hg ci -m2
22
22
23 $ touch a
23 $ touch a
24 $ hg ci -Am3
24 $ hg ci -Am3
25 adding a
25 adding a
26
26
27 $ hg mv a b
27 $ hg mv a b
28 $ hg ci -Am4 a
28 $ hg ci -Am4 a
29
29
30 $ hg ci --debug --traceback -Am5 b
30 $ hg ci --debug --traceback -Am5 b
31 committing files:
31 committing files:
32 b
32 b
33 warning: can't find ancestor for 'b' copied from 'a'!
33 warning: can't find ancestor for 'b' copied from 'a'!
34 committing manifest
34 committing manifest
35 committing changelog
35 committing changelog
36 updating the branch cache
36 updating the branch cache
37 committed changeset 5:83a687e8a97c80992ba385bbfd766be181bfb1d1
37 committed changeset 5:83a687e8a97c80992ba385bbfd766be181bfb1d1
38
38
39 $ hg verify
39 $ hg verify
40 checking changesets
40 checking changesets
41 checking manifests
41 checking manifests
42 crosschecking files in changesets and manifests
42 crosschecking files in changesets and manifests
43 checking files
43 checking files
44 checked 6 changesets with 4 changes to 4 files
44 checked 6 changesets with 4 changes to 4 files
45
45
46 $ hg export --git tip
46 $ hg export --git tip
47 # HG changeset patch
47 # HG changeset patch
48 # User test
48 # User test
49 # Date 0 0
49 # Date 0 0
50 # Thu Jan 01 00:00:00 1970 +0000
50 # Thu Jan 01 00:00:00 1970 +0000
51 # Node ID 83a687e8a97c80992ba385bbfd766be181bfb1d1
51 # Node ID 83a687e8a97c80992ba385bbfd766be181bfb1d1
52 # Parent 1d1625283f71954f21d14c3d44d0ad3c019c597f
52 # Parent 1d1625283f71954f21d14c3d44d0ad3c019c597f
53 5
53 5
54
54
55 diff --git a/b b/b
55 diff --git a/b b/b
56 new file mode 100644
56 new file mode 100644
57
57
58 https://bz.mercurial-scm.org/show_bug.cgi?id=4476
58 https://bz.mercurial-scm.org/show_bug.cgi?id=4476
59
59
60 $ hg init foo
60 $ hg init foo
61 $ cd foo
61 $ cd foo
62 $ touch a && hg ci -Aqm a
62 $ touch a && hg ci -Aqm a
63 $ hg mv a b
63 $ hg mv a b
64 $ echo b1 >> b
64 $ echo b1 >> b
65 $ hg ci -Aqm b1
65 $ hg ci -Aqm b1
66 $ hg up 0
66 $ hg up 0
67 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
67 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
68 $ hg mv a b
68 $ hg mv a b
69 $ echo b2 >> b
69 $ echo b2 >> b
70 $ hg ci -Aqm b2
70 $ hg ci -Aqm b2
71 $ hg graft 1
71 $ hg graft 1
72 grafting 1:5974126fad84 "b1"
72 grafting 1:5974126fad84 "b1"
73 merging b
73 merging b
74 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
74 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
75 abort: unresolved conflicts, can't continue
75 abort: unresolved conflicts, can't continue
76 (use 'hg resolve' and 'hg graft --continue')
76 (use 'hg resolve' and 'hg graft --continue')
77 [255]
77 [1]
78 $ echo a > b
78 $ echo a > b
79 $ echo b3 >> b
79 $ echo b3 >> b
80 $ hg resolve --mark b
80 $ hg resolve --mark b
81 (no more unresolved files)
81 (no more unresolved files)
82 continue: hg graft --continue
82 continue: hg graft --continue
83 $ hg graft --continue
83 $ hg graft --continue
84 grafting 1:5974126fad84 "b1"
84 grafting 1:5974126fad84 "b1"
85 $ hg log -f b -T 'changeset: {rev}:{node|short}\nsummary: {desc}\n\n'
85 $ hg log -f b -T 'changeset: {rev}:{node|short}\nsummary: {desc}\n\n'
86 changeset: 3:376d30ccffc0
86 changeset: 3:376d30ccffc0
87 summary: b1
87 summary: b1
88
88
89 changeset: 2:416baaa2e5e4
89 changeset: 2:416baaa2e5e4
90 summary: b2
90 summary: b2
91
91
92 changeset: 0:3903775176ed
92 changeset: 0:3903775176ed
93 summary: a
93 summary: a
94
94
95
95
96
96
General Comments 0
You need to be logged in to leave comments. Login now