##// END OF EJS Templates
push: add --all-bookmarks option...
Dan Villiom Podlaski Christiansen -
r46407:49535e56 default
parent child Browse files
Show More
@@ -1,7664 +1,7673 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import os
11 import os
12 import re
12 import re
13 import sys
13 import sys
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 hex,
17 hex,
18 nullid,
18 nullid,
19 nullrev,
19 nullrev,
20 short,
20 short,
21 wdirhex,
21 wdirhex,
22 wdirrev,
22 wdirrev,
23 )
23 )
24 from .pycompat import open
24 from .pycompat import open
25 from . import (
25 from . import (
26 archival,
26 archival,
27 bookmarks,
27 bookmarks,
28 bundle2,
28 bundle2,
29 bundlecaches,
29 bundlecaches,
30 changegroup,
30 changegroup,
31 cmdutil,
31 cmdutil,
32 copies,
32 copies,
33 debugcommands as debugcommandsmod,
33 debugcommands as debugcommandsmod,
34 destutil,
34 destutil,
35 dirstateguard,
35 dirstateguard,
36 discovery,
36 discovery,
37 encoding,
37 encoding,
38 error,
38 error,
39 exchange,
39 exchange,
40 extensions,
40 extensions,
41 filemerge,
41 filemerge,
42 formatter,
42 formatter,
43 graphmod,
43 graphmod,
44 grep as grepmod,
44 grep as grepmod,
45 hbisect,
45 hbisect,
46 help,
46 help,
47 hg,
47 hg,
48 logcmdutil,
48 logcmdutil,
49 merge as mergemod,
49 merge as mergemod,
50 mergestate as mergestatemod,
50 mergestate as mergestatemod,
51 narrowspec,
51 narrowspec,
52 obsolete,
52 obsolete,
53 obsutil,
53 obsutil,
54 patch,
54 patch,
55 phases,
55 phases,
56 pycompat,
56 pycompat,
57 rcutil,
57 rcutil,
58 registrar,
58 registrar,
59 requirements,
59 requirements,
60 revsetlang,
60 revsetlang,
61 rewriteutil,
61 rewriteutil,
62 scmutil,
62 scmutil,
63 server,
63 server,
64 shelve as shelvemod,
64 shelve as shelvemod,
65 state as statemod,
65 state as statemod,
66 streamclone,
66 streamclone,
67 tags as tagsmod,
67 tags as tagsmod,
68 ui as uimod,
68 ui as uimod,
69 util,
69 util,
70 verify as verifymod,
70 verify as verifymod,
71 vfs as vfsmod,
71 vfs as vfsmod,
72 wireprotoserver,
72 wireprotoserver,
73 )
73 )
74 from .utils import (
74 from .utils import (
75 dateutil,
75 dateutil,
76 stringutil,
76 stringutil,
77 )
77 )
78
78
79 table = {}
79 table = {}
80 table.update(debugcommandsmod.command._table)
80 table.update(debugcommandsmod.command._table)
81
81
82 command = registrar.command(table)
82 command = registrar.command(table)
83 INTENT_READONLY = registrar.INTENT_READONLY
83 INTENT_READONLY = registrar.INTENT_READONLY
84
84
85 # common command options
85 # common command options
86
86
87 globalopts = [
87 globalopts = [
88 (
88 (
89 b'R',
89 b'R',
90 b'repository',
90 b'repository',
91 b'',
91 b'',
92 _(b'repository root directory or name of overlay bundle file'),
92 _(b'repository root directory or name of overlay bundle file'),
93 _(b'REPO'),
93 _(b'REPO'),
94 ),
94 ),
95 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
95 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
96 (
96 (
97 b'y',
97 b'y',
98 b'noninteractive',
98 b'noninteractive',
99 None,
99 None,
100 _(
100 _(
101 b'do not prompt, automatically pick the first choice for all prompts'
101 b'do not prompt, automatically pick the first choice for all prompts'
102 ),
102 ),
103 ),
103 ),
104 (b'q', b'quiet', None, _(b'suppress output')),
104 (b'q', b'quiet', None, _(b'suppress output')),
105 (b'v', b'verbose', None, _(b'enable additional output')),
105 (b'v', b'verbose', None, _(b'enable additional output')),
106 (
106 (
107 b'',
107 b'',
108 b'color',
108 b'color',
109 b'',
109 b'',
110 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
110 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
111 # and should not be translated
111 # and should not be translated
112 _(b"when to colorize (boolean, always, auto, never, or debug)"),
112 _(b"when to colorize (boolean, always, auto, never, or debug)"),
113 _(b'TYPE'),
113 _(b'TYPE'),
114 ),
114 ),
115 (
115 (
116 b'',
116 b'',
117 b'config',
117 b'config',
118 [],
118 [],
119 _(b'set/override config option (use \'section.name=value\')'),
119 _(b'set/override config option (use \'section.name=value\')'),
120 _(b'CONFIG'),
120 _(b'CONFIG'),
121 ),
121 ),
122 (b'', b'debug', None, _(b'enable debugging output')),
122 (b'', b'debug', None, _(b'enable debugging output')),
123 (b'', b'debugger', None, _(b'start debugger')),
123 (b'', b'debugger', None, _(b'start debugger')),
124 (
124 (
125 b'',
125 b'',
126 b'encoding',
126 b'encoding',
127 encoding.encoding,
127 encoding.encoding,
128 _(b'set the charset encoding'),
128 _(b'set the charset encoding'),
129 _(b'ENCODE'),
129 _(b'ENCODE'),
130 ),
130 ),
131 (
131 (
132 b'',
132 b'',
133 b'encodingmode',
133 b'encodingmode',
134 encoding.encodingmode,
134 encoding.encodingmode,
135 _(b'set the charset encoding mode'),
135 _(b'set the charset encoding mode'),
136 _(b'MODE'),
136 _(b'MODE'),
137 ),
137 ),
138 (b'', b'traceback', None, _(b'always print a traceback on exception')),
138 (b'', b'traceback', None, _(b'always print a traceback on exception')),
139 (b'', b'time', None, _(b'time how long the command takes')),
139 (b'', b'time', None, _(b'time how long the command takes')),
140 (b'', b'profile', None, _(b'print command execution profile')),
140 (b'', b'profile', None, _(b'print command execution profile')),
141 (b'', b'version', None, _(b'output version information and exit')),
141 (b'', b'version', None, _(b'output version information and exit')),
142 (b'h', b'help', None, _(b'display help and exit')),
142 (b'h', b'help', None, _(b'display help and exit')),
143 (b'', b'hidden', False, _(b'consider hidden changesets')),
143 (b'', b'hidden', False, _(b'consider hidden changesets')),
144 (
144 (
145 b'',
145 b'',
146 b'pager',
146 b'pager',
147 b'auto',
147 b'auto',
148 _(b"when to paginate (boolean, always, auto, or never)"),
148 _(b"when to paginate (boolean, always, auto, or never)"),
149 _(b'TYPE'),
149 _(b'TYPE'),
150 ),
150 ),
151 ]
151 ]
152
152
153 dryrunopts = cmdutil.dryrunopts
153 dryrunopts = cmdutil.dryrunopts
154 remoteopts = cmdutil.remoteopts
154 remoteopts = cmdutil.remoteopts
155 walkopts = cmdutil.walkopts
155 walkopts = cmdutil.walkopts
156 commitopts = cmdutil.commitopts
156 commitopts = cmdutil.commitopts
157 commitopts2 = cmdutil.commitopts2
157 commitopts2 = cmdutil.commitopts2
158 commitopts3 = cmdutil.commitopts3
158 commitopts3 = cmdutil.commitopts3
159 formatteropts = cmdutil.formatteropts
159 formatteropts = cmdutil.formatteropts
160 templateopts = cmdutil.templateopts
160 templateopts = cmdutil.templateopts
161 logopts = cmdutil.logopts
161 logopts = cmdutil.logopts
162 diffopts = cmdutil.diffopts
162 diffopts = cmdutil.diffopts
163 diffwsopts = cmdutil.diffwsopts
163 diffwsopts = cmdutil.diffwsopts
164 diffopts2 = cmdutil.diffopts2
164 diffopts2 = cmdutil.diffopts2
165 mergetoolopts = cmdutil.mergetoolopts
165 mergetoolopts = cmdutil.mergetoolopts
166 similarityopts = cmdutil.similarityopts
166 similarityopts = cmdutil.similarityopts
167 subrepoopts = cmdutil.subrepoopts
167 subrepoopts = cmdutil.subrepoopts
168 debugrevlogopts = cmdutil.debugrevlogopts
168 debugrevlogopts = cmdutil.debugrevlogopts
169
169
170 # Commands start here, listed alphabetically
170 # Commands start here, listed alphabetically
171
171
172
172
173 @command(
173 @command(
174 b'abort',
174 b'abort',
175 dryrunopts,
175 dryrunopts,
176 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
176 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
177 helpbasic=True,
177 helpbasic=True,
178 )
178 )
179 def abort(ui, repo, **opts):
179 def abort(ui, repo, **opts):
180 """abort an unfinished operation (EXPERIMENTAL)
180 """abort an unfinished operation (EXPERIMENTAL)
181
181
182 Aborts a multistep operation like graft, histedit, rebase, merge,
182 Aborts a multistep operation like graft, histedit, rebase, merge,
183 and unshelve if they are in an unfinished state.
183 and unshelve if they are in an unfinished state.
184
184
185 use --dry-run/-n to dry run the command.
185 use --dry-run/-n to dry run the command.
186 """
186 """
187 dryrun = opts.get('dry_run')
187 dryrun = opts.get('dry_run')
188 abortstate = cmdutil.getunfinishedstate(repo)
188 abortstate = cmdutil.getunfinishedstate(repo)
189 if not abortstate:
189 if not abortstate:
190 raise error.Abort(_(b'no operation in progress'))
190 raise error.Abort(_(b'no operation in progress'))
191 if not abortstate.abortfunc:
191 if not abortstate.abortfunc:
192 raise error.Abort(
192 raise error.Abort(
193 (
193 (
194 _(b"%s in progress but does not support 'hg abort'")
194 _(b"%s in progress but does not support 'hg abort'")
195 % (abortstate._opname)
195 % (abortstate._opname)
196 ),
196 ),
197 hint=abortstate.hint(),
197 hint=abortstate.hint(),
198 )
198 )
199 if dryrun:
199 if dryrun:
200 ui.status(
200 ui.status(
201 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
201 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
202 )
202 )
203 return
203 return
204 return abortstate.abortfunc(ui, repo)
204 return abortstate.abortfunc(ui, repo)
205
205
206
206
207 @command(
207 @command(
208 b'add',
208 b'add',
209 walkopts + subrepoopts + dryrunopts,
209 walkopts + subrepoopts + dryrunopts,
210 _(b'[OPTION]... [FILE]...'),
210 _(b'[OPTION]... [FILE]...'),
211 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
211 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
212 helpbasic=True,
212 helpbasic=True,
213 inferrepo=True,
213 inferrepo=True,
214 )
214 )
215 def add(ui, repo, *pats, **opts):
215 def add(ui, repo, *pats, **opts):
216 """add the specified files on the next commit
216 """add the specified files on the next commit
217
217
218 Schedule files to be version controlled and added to the
218 Schedule files to be version controlled and added to the
219 repository.
219 repository.
220
220
221 The files will be added to the repository at the next commit. To
221 The files will be added to the repository at the next commit. To
222 undo an add before that, see :hg:`forget`.
222 undo an add before that, see :hg:`forget`.
223
223
224 If no names are given, add all files to the repository (except
224 If no names are given, add all files to the repository (except
225 files matching ``.hgignore``).
225 files matching ``.hgignore``).
226
226
227 .. container:: verbose
227 .. container:: verbose
228
228
229 Examples:
229 Examples:
230
230
231 - New (unknown) files are added
231 - New (unknown) files are added
232 automatically by :hg:`add`::
232 automatically by :hg:`add`::
233
233
234 $ ls
234 $ ls
235 foo.c
235 foo.c
236 $ hg status
236 $ hg status
237 ? foo.c
237 ? foo.c
238 $ hg add
238 $ hg add
239 adding foo.c
239 adding foo.c
240 $ hg status
240 $ hg status
241 A foo.c
241 A foo.c
242
242
243 - Specific files to be added can be specified::
243 - Specific files to be added can be specified::
244
244
245 $ ls
245 $ ls
246 bar.c foo.c
246 bar.c foo.c
247 $ hg status
247 $ hg status
248 ? bar.c
248 ? bar.c
249 ? foo.c
249 ? foo.c
250 $ hg add bar.c
250 $ hg add bar.c
251 $ hg status
251 $ hg status
252 A bar.c
252 A bar.c
253 ? foo.c
253 ? foo.c
254
254
255 Returns 0 if all files are successfully added.
255 Returns 0 if all files are successfully added.
256 """
256 """
257
257
258 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
258 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
259 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
259 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
260 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
260 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
261 return rejected and 1 or 0
261 return rejected and 1 or 0
262
262
263
263
264 @command(
264 @command(
265 b'addremove',
265 b'addremove',
266 similarityopts + subrepoopts + walkopts + dryrunopts,
266 similarityopts + subrepoopts + walkopts + dryrunopts,
267 _(b'[OPTION]... [FILE]...'),
267 _(b'[OPTION]... [FILE]...'),
268 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
268 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
269 inferrepo=True,
269 inferrepo=True,
270 )
270 )
271 def addremove(ui, repo, *pats, **opts):
271 def addremove(ui, repo, *pats, **opts):
272 """add all new files, delete all missing files
272 """add all new files, delete all missing files
273
273
274 Add all new files and remove all missing files from the
274 Add all new files and remove all missing files from the
275 repository.
275 repository.
276
276
277 Unless names are given, new files are ignored if they match any of
277 Unless names are given, new files are ignored if they match any of
278 the patterns in ``.hgignore``. As with add, these changes take
278 the patterns in ``.hgignore``. As with add, these changes take
279 effect at the next commit.
279 effect at the next commit.
280
280
281 Use the -s/--similarity option to detect renamed files. This
281 Use the -s/--similarity option to detect renamed files. This
282 option takes a percentage between 0 (disabled) and 100 (files must
282 option takes a percentage between 0 (disabled) and 100 (files must
283 be identical) as its parameter. With a parameter greater than 0,
283 be identical) as its parameter. With a parameter greater than 0,
284 this compares every removed file with every added file and records
284 this compares every removed file with every added file and records
285 those similar enough as renames. Detecting renamed files this way
285 those similar enough as renames. Detecting renamed files this way
286 can be expensive. After using this option, :hg:`status -C` can be
286 can be expensive. After using this option, :hg:`status -C` can be
287 used to check which files were identified as moved or renamed. If
287 used to check which files were identified as moved or renamed. If
288 not specified, -s/--similarity defaults to 100 and only renames of
288 not specified, -s/--similarity defaults to 100 and only renames of
289 identical files are detected.
289 identical files are detected.
290
290
291 .. container:: verbose
291 .. container:: verbose
292
292
293 Examples:
293 Examples:
294
294
295 - A number of files (bar.c and foo.c) are new,
295 - A number of files (bar.c and foo.c) are new,
296 while foobar.c has been removed (without using :hg:`remove`)
296 while foobar.c has been removed (without using :hg:`remove`)
297 from the repository::
297 from the repository::
298
298
299 $ ls
299 $ ls
300 bar.c foo.c
300 bar.c foo.c
301 $ hg status
301 $ hg status
302 ! foobar.c
302 ! foobar.c
303 ? bar.c
303 ? bar.c
304 ? foo.c
304 ? foo.c
305 $ hg addremove
305 $ hg addremove
306 adding bar.c
306 adding bar.c
307 adding foo.c
307 adding foo.c
308 removing foobar.c
308 removing foobar.c
309 $ hg status
309 $ hg status
310 A bar.c
310 A bar.c
311 A foo.c
311 A foo.c
312 R foobar.c
312 R foobar.c
313
313
314 - A file foobar.c was moved to foo.c without using :hg:`rename`.
314 - A file foobar.c was moved to foo.c without using :hg:`rename`.
315 Afterwards, it was edited slightly::
315 Afterwards, it was edited slightly::
316
316
317 $ ls
317 $ ls
318 foo.c
318 foo.c
319 $ hg status
319 $ hg status
320 ! foobar.c
320 ! foobar.c
321 ? foo.c
321 ? foo.c
322 $ hg addremove --similarity 90
322 $ hg addremove --similarity 90
323 removing foobar.c
323 removing foobar.c
324 adding foo.c
324 adding foo.c
325 recording removal of foobar.c as rename to foo.c (94% similar)
325 recording removal of foobar.c as rename to foo.c (94% similar)
326 $ hg status -C
326 $ hg status -C
327 A foo.c
327 A foo.c
328 foobar.c
328 foobar.c
329 R foobar.c
329 R foobar.c
330
330
331 Returns 0 if all files are successfully added.
331 Returns 0 if all files are successfully added.
332 """
332 """
333 opts = pycompat.byteskwargs(opts)
333 opts = pycompat.byteskwargs(opts)
334 if not opts.get(b'similarity'):
334 if not opts.get(b'similarity'):
335 opts[b'similarity'] = b'100'
335 opts[b'similarity'] = b'100'
336 matcher = scmutil.match(repo[None], pats, opts)
336 matcher = scmutil.match(repo[None], pats, opts)
337 relative = scmutil.anypats(pats, opts)
337 relative = scmutil.anypats(pats, opts)
338 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
338 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
339 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
339 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
340
340
341
341
342 @command(
342 @command(
343 b'annotate|blame',
343 b'annotate|blame',
344 [
344 [
345 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
345 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
346 (
346 (
347 b'',
347 b'',
348 b'follow',
348 b'follow',
349 None,
349 None,
350 _(b'follow copies/renames and list the filename (DEPRECATED)'),
350 _(b'follow copies/renames and list the filename (DEPRECATED)'),
351 ),
351 ),
352 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
352 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
353 (b'a', b'text', None, _(b'treat all files as text')),
353 (b'a', b'text', None, _(b'treat all files as text')),
354 (b'u', b'user', None, _(b'list the author (long with -v)')),
354 (b'u', b'user', None, _(b'list the author (long with -v)')),
355 (b'f', b'file', None, _(b'list the filename')),
355 (b'f', b'file', None, _(b'list the filename')),
356 (b'd', b'date', None, _(b'list the date (short with -q)')),
356 (b'd', b'date', None, _(b'list the date (short with -q)')),
357 (b'n', b'number', None, _(b'list the revision number (default)')),
357 (b'n', b'number', None, _(b'list the revision number (default)')),
358 (b'c', b'changeset', None, _(b'list the changeset')),
358 (b'c', b'changeset', None, _(b'list the changeset')),
359 (
359 (
360 b'l',
360 b'l',
361 b'line-number',
361 b'line-number',
362 None,
362 None,
363 _(b'show line number at the first appearance'),
363 _(b'show line number at the first appearance'),
364 ),
364 ),
365 (
365 (
366 b'',
366 b'',
367 b'skip',
367 b'skip',
368 [],
368 [],
369 _(b'revset to not display (EXPERIMENTAL)'),
369 _(b'revset to not display (EXPERIMENTAL)'),
370 _(b'REV'),
370 _(b'REV'),
371 ),
371 ),
372 ]
372 ]
373 + diffwsopts
373 + diffwsopts
374 + walkopts
374 + walkopts
375 + formatteropts,
375 + formatteropts,
376 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
376 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
377 helpcategory=command.CATEGORY_FILE_CONTENTS,
377 helpcategory=command.CATEGORY_FILE_CONTENTS,
378 helpbasic=True,
378 helpbasic=True,
379 inferrepo=True,
379 inferrepo=True,
380 )
380 )
381 def annotate(ui, repo, *pats, **opts):
381 def annotate(ui, repo, *pats, **opts):
382 """show changeset information by line for each file
382 """show changeset information by line for each file
383
383
384 List changes in files, showing the revision id responsible for
384 List changes in files, showing the revision id responsible for
385 each line.
385 each line.
386
386
387 This command is useful for discovering when a change was made and
387 This command is useful for discovering when a change was made and
388 by whom.
388 by whom.
389
389
390 If you include --file, --user, or --date, the revision number is
390 If you include --file, --user, or --date, the revision number is
391 suppressed unless you also include --number.
391 suppressed unless you also include --number.
392
392
393 Without the -a/--text option, annotate will avoid processing files
393 Without the -a/--text option, annotate will avoid processing files
394 it detects as binary. With -a, annotate will annotate the file
394 it detects as binary. With -a, annotate will annotate the file
395 anyway, although the results will probably be neither useful
395 anyway, although the results will probably be neither useful
396 nor desirable.
396 nor desirable.
397
397
398 .. container:: verbose
398 .. container:: verbose
399
399
400 Template:
400 Template:
401
401
402 The following keywords are supported in addition to the common template
402 The following keywords are supported in addition to the common template
403 keywords and functions. See also :hg:`help templates`.
403 keywords and functions. See also :hg:`help templates`.
404
404
405 :lines: List of lines with annotation data.
405 :lines: List of lines with annotation data.
406 :path: String. Repository-absolute path of the specified file.
406 :path: String. Repository-absolute path of the specified file.
407
407
408 And each entry of ``{lines}`` provides the following sub-keywords in
408 And each entry of ``{lines}`` provides the following sub-keywords in
409 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
409 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
410
410
411 :line: String. Line content.
411 :line: String. Line content.
412 :lineno: Integer. Line number at that revision.
412 :lineno: Integer. Line number at that revision.
413 :path: String. Repository-absolute path of the file at that revision.
413 :path: String. Repository-absolute path of the file at that revision.
414
414
415 See :hg:`help templates.operators` for the list expansion syntax.
415 See :hg:`help templates.operators` for the list expansion syntax.
416
416
417 Returns 0 on success.
417 Returns 0 on success.
418 """
418 """
419 opts = pycompat.byteskwargs(opts)
419 opts = pycompat.byteskwargs(opts)
420 if not pats:
420 if not pats:
421 raise error.Abort(_(b'at least one filename or pattern is required'))
421 raise error.Abort(_(b'at least one filename or pattern is required'))
422
422
423 if opts.get(b'follow'):
423 if opts.get(b'follow'):
424 # --follow is deprecated and now just an alias for -f/--file
424 # --follow is deprecated and now just an alias for -f/--file
425 # to mimic the behavior of Mercurial before version 1.5
425 # to mimic the behavior of Mercurial before version 1.5
426 opts[b'file'] = True
426 opts[b'file'] = True
427
427
428 if (
428 if (
429 not opts.get(b'user')
429 not opts.get(b'user')
430 and not opts.get(b'changeset')
430 and not opts.get(b'changeset')
431 and not opts.get(b'date')
431 and not opts.get(b'date')
432 and not opts.get(b'file')
432 and not opts.get(b'file')
433 ):
433 ):
434 opts[b'number'] = True
434 opts[b'number'] = True
435
435
436 linenumber = opts.get(b'line_number') is not None
436 linenumber = opts.get(b'line_number') is not None
437 if (
437 if (
438 linenumber
438 linenumber
439 and (not opts.get(b'changeset'))
439 and (not opts.get(b'changeset'))
440 and (not opts.get(b'number'))
440 and (not opts.get(b'number'))
441 ):
441 ):
442 raise error.Abort(_(b'at least one of -n/-c is required for -l'))
442 raise error.Abort(_(b'at least one of -n/-c is required for -l'))
443
443
444 rev = opts.get(b'rev')
444 rev = opts.get(b'rev')
445 if rev:
445 if rev:
446 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
446 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
447 ctx = scmutil.revsingle(repo, rev)
447 ctx = scmutil.revsingle(repo, rev)
448
448
449 ui.pager(b'annotate')
449 ui.pager(b'annotate')
450 rootfm = ui.formatter(b'annotate', opts)
450 rootfm = ui.formatter(b'annotate', opts)
451 if ui.debugflag:
451 if ui.debugflag:
452 shorthex = pycompat.identity
452 shorthex = pycompat.identity
453 else:
453 else:
454
454
455 def shorthex(h):
455 def shorthex(h):
456 return h[:12]
456 return h[:12]
457
457
458 if ui.quiet:
458 if ui.quiet:
459 datefunc = dateutil.shortdate
459 datefunc = dateutil.shortdate
460 else:
460 else:
461 datefunc = dateutil.datestr
461 datefunc = dateutil.datestr
462 if ctx.rev() is None:
462 if ctx.rev() is None:
463 if opts.get(b'changeset'):
463 if opts.get(b'changeset'):
464 # omit "+" suffix which is appended to node hex
464 # omit "+" suffix which is appended to node hex
465 def formatrev(rev):
465 def formatrev(rev):
466 if rev == wdirrev:
466 if rev == wdirrev:
467 return b'%d' % ctx.p1().rev()
467 return b'%d' % ctx.p1().rev()
468 else:
468 else:
469 return b'%d' % rev
469 return b'%d' % rev
470
470
471 else:
471 else:
472
472
473 def formatrev(rev):
473 def formatrev(rev):
474 if rev == wdirrev:
474 if rev == wdirrev:
475 return b'%d+' % ctx.p1().rev()
475 return b'%d+' % ctx.p1().rev()
476 else:
476 else:
477 return b'%d ' % rev
477 return b'%d ' % rev
478
478
479 def formathex(h):
479 def formathex(h):
480 if h == wdirhex:
480 if h == wdirhex:
481 return b'%s+' % shorthex(hex(ctx.p1().node()))
481 return b'%s+' % shorthex(hex(ctx.p1().node()))
482 else:
482 else:
483 return b'%s ' % shorthex(h)
483 return b'%s ' % shorthex(h)
484
484
485 else:
485 else:
486 formatrev = b'%d'.__mod__
486 formatrev = b'%d'.__mod__
487 formathex = shorthex
487 formathex = shorthex
488
488
489 opmap = [
489 opmap = [
490 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
490 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
491 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
491 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
492 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
492 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
493 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
493 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
494 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
494 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
495 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
495 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
496 ]
496 ]
497 opnamemap = {
497 opnamemap = {
498 b'rev': b'number',
498 b'rev': b'number',
499 b'node': b'changeset',
499 b'node': b'changeset',
500 b'path': b'file',
500 b'path': b'file',
501 b'lineno': b'line_number',
501 b'lineno': b'line_number',
502 }
502 }
503
503
504 if rootfm.isplain():
504 if rootfm.isplain():
505
505
506 def makefunc(get, fmt):
506 def makefunc(get, fmt):
507 return lambda x: fmt(get(x))
507 return lambda x: fmt(get(x))
508
508
509 else:
509 else:
510
510
511 def makefunc(get, fmt):
511 def makefunc(get, fmt):
512 return get
512 return get
513
513
514 datahint = rootfm.datahint()
514 datahint = rootfm.datahint()
515 funcmap = [
515 funcmap = [
516 (makefunc(get, fmt), sep)
516 (makefunc(get, fmt), sep)
517 for fn, sep, get, fmt in opmap
517 for fn, sep, get, fmt in opmap
518 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
518 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
519 ]
519 ]
520 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
520 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
521 fields = b' '.join(
521 fields = b' '.join(
522 fn
522 fn
523 for fn, sep, get, fmt in opmap
523 for fn, sep, get, fmt in opmap
524 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
524 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
525 )
525 )
526
526
527 def bad(x, y):
527 def bad(x, y):
528 raise error.Abort(b"%s: %s" % (x, y))
528 raise error.Abort(b"%s: %s" % (x, y))
529
529
530 m = scmutil.match(ctx, pats, opts, badfn=bad)
530 m = scmutil.match(ctx, pats, opts, badfn=bad)
531
531
532 follow = not opts.get(b'no_follow')
532 follow = not opts.get(b'no_follow')
533 diffopts = patch.difffeatureopts(
533 diffopts = patch.difffeatureopts(
534 ui, opts, section=b'annotate', whitespace=True
534 ui, opts, section=b'annotate', whitespace=True
535 )
535 )
536 skiprevs = opts.get(b'skip')
536 skiprevs = opts.get(b'skip')
537 if skiprevs:
537 if skiprevs:
538 skiprevs = scmutil.revrange(repo, skiprevs)
538 skiprevs = scmutil.revrange(repo, skiprevs)
539
539
540 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
540 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
541 for abs in ctx.walk(m):
541 for abs in ctx.walk(m):
542 fctx = ctx[abs]
542 fctx = ctx[abs]
543 rootfm.startitem()
543 rootfm.startitem()
544 rootfm.data(path=abs)
544 rootfm.data(path=abs)
545 if not opts.get(b'text') and fctx.isbinary():
545 if not opts.get(b'text') and fctx.isbinary():
546 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
546 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
547 continue
547 continue
548
548
549 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
549 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
550 lines = fctx.annotate(
550 lines = fctx.annotate(
551 follow=follow, skiprevs=skiprevs, diffopts=diffopts
551 follow=follow, skiprevs=skiprevs, diffopts=diffopts
552 )
552 )
553 if not lines:
553 if not lines:
554 fm.end()
554 fm.end()
555 continue
555 continue
556 formats = []
556 formats = []
557 pieces = []
557 pieces = []
558
558
559 for f, sep in funcmap:
559 for f, sep in funcmap:
560 l = [f(n) for n in lines]
560 l = [f(n) for n in lines]
561 if fm.isplain():
561 if fm.isplain():
562 sizes = [encoding.colwidth(x) for x in l]
562 sizes = [encoding.colwidth(x) for x in l]
563 ml = max(sizes)
563 ml = max(sizes)
564 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
564 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
565 else:
565 else:
566 formats.append([b'%s'] * len(l))
566 formats.append([b'%s'] * len(l))
567 pieces.append(l)
567 pieces.append(l)
568
568
569 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
569 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
570 fm.startitem()
570 fm.startitem()
571 fm.context(fctx=n.fctx)
571 fm.context(fctx=n.fctx)
572 fm.write(fields, b"".join(f), *p)
572 fm.write(fields, b"".join(f), *p)
573 if n.skip:
573 if n.skip:
574 fmt = b"* %s"
574 fmt = b"* %s"
575 else:
575 else:
576 fmt = b": %s"
576 fmt = b": %s"
577 fm.write(b'line', fmt, n.text)
577 fm.write(b'line', fmt, n.text)
578
578
579 if not lines[-1].text.endswith(b'\n'):
579 if not lines[-1].text.endswith(b'\n'):
580 fm.plain(b'\n')
580 fm.plain(b'\n')
581 fm.end()
581 fm.end()
582
582
583 rootfm.end()
583 rootfm.end()
584
584
585
585
586 @command(
586 @command(
587 b'archive',
587 b'archive',
588 [
588 [
589 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
589 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
590 (
590 (
591 b'p',
591 b'p',
592 b'prefix',
592 b'prefix',
593 b'',
593 b'',
594 _(b'directory prefix for files in archive'),
594 _(b'directory prefix for files in archive'),
595 _(b'PREFIX'),
595 _(b'PREFIX'),
596 ),
596 ),
597 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
597 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
598 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
598 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
599 ]
599 ]
600 + subrepoopts
600 + subrepoopts
601 + walkopts,
601 + walkopts,
602 _(b'[OPTION]... DEST'),
602 _(b'[OPTION]... DEST'),
603 helpcategory=command.CATEGORY_IMPORT_EXPORT,
603 helpcategory=command.CATEGORY_IMPORT_EXPORT,
604 )
604 )
605 def archive(ui, repo, dest, **opts):
605 def archive(ui, repo, dest, **opts):
606 '''create an unversioned archive of a repository revision
606 '''create an unversioned archive of a repository revision
607
607
608 By default, the revision used is the parent of the working
608 By default, the revision used is the parent of the working
609 directory; use -r/--rev to specify a different revision.
609 directory; use -r/--rev to specify a different revision.
610
610
611 The archive type is automatically detected based on file
611 The archive type is automatically detected based on file
612 extension (to override, use -t/--type).
612 extension (to override, use -t/--type).
613
613
614 .. container:: verbose
614 .. container:: verbose
615
615
616 Examples:
616 Examples:
617
617
618 - create a zip file containing the 1.0 release::
618 - create a zip file containing the 1.0 release::
619
619
620 hg archive -r 1.0 project-1.0.zip
620 hg archive -r 1.0 project-1.0.zip
621
621
622 - create a tarball excluding .hg files::
622 - create a tarball excluding .hg files::
623
623
624 hg archive project.tar.gz -X ".hg*"
624 hg archive project.tar.gz -X ".hg*"
625
625
626 Valid types are:
626 Valid types are:
627
627
628 :``files``: a directory full of files (default)
628 :``files``: a directory full of files (default)
629 :``tar``: tar archive, uncompressed
629 :``tar``: tar archive, uncompressed
630 :``tbz2``: tar archive, compressed using bzip2
630 :``tbz2``: tar archive, compressed using bzip2
631 :``tgz``: tar archive, compressed using gzip
631 :``tgz``: tar archive, compressed using gzip
632 :``txz``: tar archive, compressed using lzma (only in Python 3)
632 :``txz``: tar archive, compressed using lzma (only in Python 3)
633 :``uzip``: zip archive, uncompressed
633 :``uzip``: zip archive, uncompressed
634 :``zip``: zip archive, compressed using deflate
634 :``zip``: zip archive, compressed using deflate
635
635
636 The exact name of the destination archive or directory is given
636 The exact name of the destination archive or directory is given
637 using a format string; see :hg:`help export` for details.
637 using a format string; see :hg:`help export` for details.
638
638
639 Each member added to an archive file has a directory prefix
639 Each member added to an archive file has a directory prefix
640 prepended. Use -p/--prefix to specify a format string for the
640 prepended. Use -p/--prefix to specify a format string for the
641 prefix. The default is the basename of the archive, with suffixes
641 prefix. The default is the basename of the archive, with suffixes
642 removed.
642 removed.
643
643
644 Returns 0 on success.
644 Returns 0 on success.
645 '''
645 '''
646
646
647 opts = pycompat.byteskwargs(opts)
647 opts = pycompat.byteskwargs(opts)
648 rev = opts.get(b'rev')
648 rev = opts.get(b'rev')
649 if rev:
649 if rev:
650 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
650 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
651 ctx = scmutil.revsingle(repo, rev)
651 ctx = scmutil.revsingle(repo, rev)
652 if not ctx:
652 if not ctx:
653 raise error.Abort(_(b'no working directory: please specify a revision'))
653 raise error.Abort(_(b'no working directory: please specify a revision'))
654 node = ctx.node()
654 node = ctx.node()
655 dest = cmdutil.makefilename(ctx, dest)
655 dest = cmdutil.makefilename(ctx, dest)
656 if os.path.realpath(dest) == repo.root:
656 if os.path.realpath(dest) == repo.root:
657 raise error.Abort(_(b'repository root cannot be destination'))
657 raise error.Abort(_(b'repository root cannot be destination'))
658
658
659 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
659 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
660 prefix = opts.get(b'prefix')
660 prefix = opts.get(b'prefix')
661
661
662 if dest == b'-':
662 if dest == b'-':
663 if kind == b'files':
663 if kind == b'files':
664 raise error.Abort(_(b'cannot archive plain files to stdout'))
664 raise error.Abort(_(b'cannot archive plain files to stdout'))
665 dest = cmdutil.makefileobj(ctx, dest)
665 dest = cmdutil.makefileobj(ctx, dest)
666 if not prefix:
666 if not prefix:
667 prefix = os.path.basename(repo.root) + b'-%h'
667 prefix = os.path.basename(repo.root) + b'-%h'
668
668
669 prefix = cmdutil.makefilename(ctx, prefix)
669 prefix = cmdutil.makefilename(ctx, prefix)
670 match = scmutil.match(ctx, [], opts)
670 match = scmutil.match(ctx, [], opts)
671 archival.archive(
671 archival.archive(
672 repo,
672 repo,
673 dest,
673 dest,
674 node,
674 node,
675 kind,
675 kind,
676 not opts.get(b'no_decode'),
676 not opts.get(b'no_decode'),
677 match,
677 match,
678 prefix,
678 prefix,
679 subrepos=opts.get(b'subrepos'),
679 subrepos=opts.get(b'subrepos'),
680 )
680 )
681
681
682
682
683 @command(
683 @command(
684 b'backout',
684 b'backout',
685 [
685 [
686 (
686 (
687 b'',
687 b'',
688 b'merge',
688 b'merge',
689 None,
689 None,
690 _(b'merge with old dirstate parent after backout'),
690 _(b'merge with old dirstate parent after backout'),
691 ),
691 ),
692 (
692 (
693 b'',
693 b'',
694 b'commit',
694 b'commit',
695 None,
695 None,
696 _(b'commit if no conflicts were encountered (DEPRECATED)'),
696 _(b'commit if no conflicts were encountered (DEPRECATED)'),
697 ),
697 ),
698 (b'', b'no-commit', None, _(b'do not commit')),
698 (b'', b'no-commit', None, _(b'do not commit')),
699 (
699 (
700 b'',
700 b'',
701 b'parent',
701 b'parent',
702 b'',
702 b'',
703 _(b'parent to choose when backing out merge (DEPRECATED)'),
703 _(b'parent to choose when backing out merge (DEPRECATED)'),
704 _(b'REV'),
704 _(b'REV'),
705 ),
705 ),
706 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
706 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
707 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
707 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
708 ]
708 ]
709 + mergetoolopts
709 + mergetoolopts
710 + walkopts
710 + walkopts
711 + commitopts
711 + commitopts
712 + commitopts2,
712 + commitopts2,
713 _(b'[OPTION]... [-r] REV'),
713 _(b'[OPTION]... [-r] REV'),
714 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
714 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
715 )
715 )
716 def backout(ui, repo, node=None, rev=None, **opts):
716 def backout(ui, repo, node=None, rev=None, **opts):
717 '''reverse effect of earlier changeset
717 '''reverse effect of earlier changeset
718
718
719 Prepare a new changeset with the effect of REV undone in the
719 Prepare a new changeset with the effect of REV undone in the
720 current working directory. If no conflicts were encountered,
720 current working directory. If no conflicts were encountered,
721 it will be committed immediately.
721 it will be committed immediately.
722
722
723 If REV is the parent of the working directory, then this new changeset
723 If REV is the parent of the working directory, then this new changeset
724 is committed automatically (unless --no-commit is specified).
724 is committed automatically (unless --no-commit is specified).
725
725
726 .. note::
726 .. note::
727
727
728 :hg:`backout` cannot be used to fix either an unwanted or
728 :hg:`backout` cannot be used to fix either an unwanted or
729 incorrect merge.
729 incorrect merge.
730
730
731 .. container:: verbose
731 .. container:: verbose
732
732
733 Examples:
733 Examples:
734
734
735 - Reverse the effect of the parent of the working directory.
735 - Reverse the effect of the parent of the working directory.
736 This backout will be committed immediately::
736 This backout will be committed immediately::
737
737
738 hg backout -r .
738 hg backout -r .
739
739
740 - Reverse the effect of previous bad revision 23::
740 - Reverse the effect of previous bad revision 23::
741
741
742 hg backout -r 23
742 hg backout -r 23
743
743
744 - Reverse the effect of previous bad revision 23 and
744 - Reverse the effect of previous bad revision 23 and
745 leave changes uncommitted::
745 leave changes uncommitted::
746
746
747 hg backout -r 23 --no-commit
747 hg backout -r 23 --no-commit
748 hg commit -m "Backout revision 23"
748 hg commit -m "Backout revision 23"
749
749
750 By default, the pending changeset will have one parent,
750 By default, the pending changeset will have one parent,
751 maintaining a linear history. With --merge, the pending
751 maintaining a linear history. With --merge, the pending
752 changeset will instead have two parents: the old parent of the
752 changeset will instead have two parents: the old parent of the
753 working directory and a new child of REV that simply undoes REV.
753 working directory and a new child of REV that simply undoes REV.
754
754
755 Before version 1.7, the behavior without --merge was equivalent
755 Before version 1.7, the behavior without --merge was equivalent
756 to specifying --merge followed by :hg:`update --clean .` to
756 to specifying --merge followed by :hg:`update --clean .` to
757 cancel the merge and leave the child of REV as a head to be
757 cancel the merge and leave the child of REV as a head to be
758 merged separately.
758 merged separately.
759
759
760 See :hg:`help dates` for a list of formats valid for -d/--date.
760 See :hg:`help dates` for a list of formats valid for -d/--date.
761
761
762 See :hg:`help revert` for a way to restore files to the state
762 See :hg:`help revert` for a way to restore files to the state
763 of another revision.
763 of another revision.
764
764
765 Returns 0 on success, 1 if nothing to backout or there are unresolved
765 Returns 0 on success, 1 if nothing to backout or there are unresolved
766 files.
766 files.
767 '''
767 '''
768 with repo.wlock(), repo.lock():
768 with repo.wlock(), repo.lock():
769 return _dobackout(ui, repo, node, rev, **opts)
769 return _dobackout(ui, repo, node, rev, **opts)
770
770
771
771
772 def _dobackout(ui, repo, node=None, rev=None, **opts):
772 def _dobackout(ui, repo, node=None, rev=None, **opts):
773 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
773 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
774 opts = pycompat.byteskwargs(opts)
774 opts = pycompat.byteskwargs(opts)
775
775
776 if rev and node:
776 if rev and node:
777 raise error.Abort(_(b"please specify just one revision"))
777 raise error.Abort(_(b"please specify just one revision"))
778
778
779 if not rev:
779 if not rev:
780 rev = node
780 rev = node
781
781
782 if not rev:
782 if not rev:
783 raise error.Abort(_(b"please specify a revision to backout"))
783 raise error.Abort(_(b"please specify a revision to backout"))
784
784
785 date = opts.get(b'date')
785 date = opts.get(b'date')
786 if date:
786 if date:
787 opts[b'date'] = dateutil.parsedate(date)
787 opts[b'date'] = dateutil.parsedate(date)
788
788
789 cmdutil.checkunfinished(repo)
789 cmdutil.checkunfinished(repo)
790 cmdutil.bailifchanged(repo)
790 cmdutil.bailifchanged(repo)
791 ctx = scmutil.revsingle(repo, rev)
791 ctx = scmutil.revsingle(repo, rev)
792 node = ctx.node()
792 node = ctx.node()
793
793
794 op1, op2 = repo.dirstate.parents()
794 op1, op2 = repo.dirstate.parents()
795 if not repo.changelog.isancestor(node, op1):
795 if not repo.changelog.isancestor(node, op1):
796 raise error.Abort(_(b'cannot backout change that is not an ancestor'))
796 raise error.Abort(_(b'cannot backout change that is not an ancestor'))
797
797
798 p1, p2 = repo.changelog.parents(node)
798 p1, p2 = repo.changelog.parents(node)
799 if p1 == nullid:
799 if p1 == nullid:
800 raise error.Abort(_(b'cannot backout a change with no parents'))
800 raise error.Abort(_(b'cannot backout a change with no parents'))
801 if p2 != nullid:
801 if p2 != nullid:
802 if not opts.get(b'parent'):
802 if not opts.get(b'parent'):
803 raise error.Abort(_(b'cannot backout a merge changeset'))
803 raise error.Abort(_(b'cannot backout a merge changeset'))
804 p = repo.lookup(opts[b'parent'])
804 p = repo.lookup(opts[b'parent'])
805 if p not in (p1, p2):
805 if p not in (p1, p2):
806 raise error.Abort(
806 raise error.Abort(
807 _(b'%s is not a parent of %s') % (short(p), short(node))
807 _(b'%s is not a parent of %s') % (short(p), short(node))
808 )
808 )
809 parent = p
809 parent = p
810 else:
810 else:
811 if opts.get(b'parent'):
811 if opts.get(b'parent'):
812 raise error.Abort(_(b'cannot use --parent on non-merge changeset'))
812 raise error.Abort(_(b'cannot use --parent on non-merge changeset'))
813 parent = p1
813 parent = p1
814
814
815 # the backout should appear on the same branch
815 # the backout should appear on the same branch
816 branch = repo.dirstate.branch()
816 branch = repo.dirstate.branch()
817 bheads = repo.branchheads(branch)
817 bheads = repo.branchheads(branch)
818 rctx = scmutil.revsingle(repo, hex(parent))
818 rctx = scmutil.revsingle(repo, hex(parent))
819 if not opts.get(b'merge') and op1 != node:
819 if not opts.get(b'merge') and op1 != node:
820 with dirstateguard.dirstateguard(repo, b'backout'):
820 with dirstateguard.dirstateguard(repo, b'backout'):
821 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
821 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
822 with ui.configoverride(overrides, b'backout'):
822 with ui.configoverride(overrides, b'backout'):
823 stats = mergemod.back_out(ctx, parent=repo[parent])
823 stats = mergemod.back_out(ctx, parent=repo[parent])
824 repo.setparents(op1, op2)
824 repo.setparents(op1, op2)
825 hg._showstats(repo, stats)
825 hg._showstats(repo, stats)
826 if stats.unresolvedcount:
826 if stats.unresolvedcount:
827 repo.ui.status(
827 repo.ui.status(
828 _(b"use 'hg resolve' to retry unresolved file merges\n")
828 _(b"use 'hg resolve' to retry unresolved file merges\n")
829 )
829 )
830 return 1
830 return 1
831 else:
831 else:
832 hg.clean(repo, node, show_stats=False)
832 hg.clean(repo, node, show_stats=False)
833 repo.dirstate.setbranch(branch)
833 repo.dirstate.setbranch(branch)
834 cmdutil.revert(ui, repo, rctx)
834 cmdutil.revert(ui, repo, rctx)
835
835
836 if opts.get(b'no_commit'):
836 if opts.get(b'no_commit'):
837 msg = _(b"changeset %s backed out, don't forget to commit.\n")
837 msg = _(b"changeset %s backed out, don't forget to commit.\n")
838 ui.status(msg % short(node))
838 ui.status(msg % short(node))
839 return 0
839 return 0
840
840
841 def commitfunc(ui, repo, message, match, opts):
841 def commitfunc(ui, repo, message, match, opts):
842 editform = b'backout'
842 editform = b'backout'
843 e = cmdutil.getcommiteditor(
843 e = cmdutil.getcommiteditor(
844 editform=editform, **pycompat.strkwargs(opts)
844 editform=editform, **pycompat.strkwargs(opts)
845 )
845 )
846 if not message:
846 if not message:
847 # we don't translate commit messages
847 # we don't translate commit messages
848 message = b"Backed out changeset %s" % short(node)
848 message = b"Backed out changeset %s" % short(node)
849 e = cmdutil.getcommiteditor(edit=True, editform=editform)
849 e = cmdutil.getcommiteditor(edit=True, editform=editform)
850 return repo.commit(
850 return repo.commit(
851 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
851 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
852 )
852 )
853
853
854 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
854 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
855 if not newnode:
855 if not newnode:
856 ui.status(_(b"nothing changed\n"))
856 ui.status(_(b"nothing changed\n"))
857 return 1
857 return 1
858 cmdutil.commitstatus(repo, newnode, branch, bheads)
858 cmdutil.commitstatus(repo, newnode, branch, bheads)
859
859
860 def nice(node):
860 def nice(node):
861 return b'%d:%s' % (repo.changelog.rev(node), short(node))
861 return b'%d:%s' % (repo.changelog.rev(node), short(node))
862
862
863 ui.status(
863 ui.status(
864 _(b'changeset %s backs out changeset %s\n')
864 _(b'changeset %s backs out changeset %s\n')
865 % (nice(newnode), nice(node))
865 % (nice(newnode), nice(node))
866 )
866 )
867 if opts.get(b'merge') and op1 != node:
867 if opts.get(b'merge') and op1 != node:
868 hg.clean(repo, op1, show_stats=False)
868 hg.clean(repo, op1, show_stats=False)
869 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
869 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
870 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
870 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
871 with ui.configoverride(overrides, b'backout'):
871 with ui.configoverride(overrides, b'backout'):
872 return hg.merge(repo[b'tip'])
872 return hg.merge(repo[b'tip'])
873 return 0
873 return 0
874
874
875
875
876 @command(
876 @command(
877 b'bisect',
877 b'bisect',
878 [
878 [
879 (b'r', b'reset', False, _(b'reset bisect state')),
879 (b'r', b'reset', False, _(b'reset bisect state')),
880 (b'g', b'good', False, _(b'mark changeset good')),
880 (b'g', b'good', False, _(b'mark changeset good')),
881 (b'b', b'bad', False, _(b'mark changeset bad')),
881 (b'b', b'bad', False, _(b'mark changeset bad')),
882 (b's', b'skip', False, _(b'skip testing changeset')),
882 (b's', b'skip', False, _(b'skip testing changeset')),
883 (b'e', b'extend', False, _(b'extend the bisect range')),
883 (b'e', b'extend', False, _(b'extend the bisect range')),
884 (
884 (
885 b'c',
885 b'c',
886 b'command',
886 b'command',
887 b'',
887 b'',
888 _(b'use command to check changeset state'),
888 _(b'use command to check changeset state'),
889 _(b'CMD'),
889 _(b'CMD'),
890 ),
890 ),
891 (b'U', b'noupdate', False, _(b'do not update to target')),
891 (b'U', b'noupdate', False, _(b'do not update to target')),
892 ],
892 ],
893 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
893 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
894 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
894 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
895 )
895 )
896 def bisect(
896 def bisect(
897 ui,
897 ui,
898 repo,
898 repo,
899 rev=None,
899 rev=None,
900 extra=None,
900 extra=None,
901 command=None,
901 command=None,
902 reset=None,
902 reset=None,
903 good=None,
903 good=None,
904 bad=None,
904 bad=None,
905 skip=None,
905 skip=None,
906 extend=None,
906 extend=None,
907 noupdate=None,
907 noupdate=None,
908 ):
908 ):
909 """subdivision search of changesets
909 """subdivision search of changesets
910
910
911 This command helps to find changesets which introduce problems. To
911 This command helps to find changesets which introduce problems. To
912 use, mark the earliest changeset you know exhibits the problem as
912 use, mark the earliest changeset you know exhibits the problem as
913 bad, then mark the latest changeset which is free from the problem
913 bad, then mark the latest changeset which is free from the problem
914 as good. Bisect will update your working directory to a revision
914 as good. Bisect will update your working directory to a revision
915 for testing (unless the -U/--noupdate option is specified). Once
915 for testing (unless the -U/--noupdate option is specified). Once
916 you have performed tests, mark the working directory as good or
916 you have performed tests, mark the working directory as good or
917 bad, and bisect will either update to another candidate changeset
917 bad, and bisect will either update to another candidate changeset
918 or announce that it has found the bad revision.
918 or announce that it has found the bad revision.
919
919
920 As a shortcut, you can also use the revision argument to mark a
920 As a shortcut, you can also use the revision argument to mark a
921 revision as good or bad without checking it out first.
921 revision as good or bad without checking it out first.
922
922
923 If you supply a command, it will be used for automatic bisection.
923 If you supply a command, it will be used for automatic bisection.
924 The environment variable HG_NODE will contain the ID of the
924 The environment variable HG_NODE will contain the ID of the
925 changeset being tested. The exit status of the command will be
925 changeset being tested. The exit status of the command will be
926 used to mark revisions as good or bad: status 0 means good, 125
926 used to mark revisions as good or bad: status 0 means good, 125
927 means to skip the revision, 127 (command not found) will abort the
927 means to skip the revision, 127 (command not found) will abort the
928 bisection, and any other non-zero exit status means the revision
928 bisection, and any other non-zero exit status means the revision
929 is bad.
929 is bad.
930
930
931 .. container:: verbose
931 .. container:: verbose
932
932
933 Some examples:
933 Some examples:
934
934
935 - start a bisection with known bad revision 34, and good revision 12::
935 - start a bisection with known bad revision 34, and good revision 12::
936
936
937 hg bisect --bad 34
937 hg bisect --bad 34
938 hg bisect --good 12
938 hg bisect --good 12
939
939
940 - advance the current bisection by marking current revision as good or
940 - advance the current bisection by marking current revision as good or
941 bad::
941 bad::
942
942
943 hg bisect --good
943 hg bisect --good
944 hg bisect --bad
944 hg bisect --bad
945
945
946 - mark the current revision, or a known revision, to be skipped (e.g. if
946 - mark the current revision, or a known revision, to be skipped (e.g. if
947 that revision is not usable because of another issue)::
947 that revision is not usable because of another issue)::
948
948
949 hg bisect --skip
949 hg bisect --skip
950 hg bisect --skip 23
950 hg bisect --skip 23
951
951
952 - skip all revisions that do not touch directories ``foo`` or ``bar``::
952 - skip all revisions that do not touch directories ``foo`` or ``bar``::
953
953
954 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
954 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
955
955
956 - forget the current bisection::
956 - forget the current bisection::
957
957
958 hg bisect --reset
958 hg bisect --reset
959
959
960 - use 'make && make tests' to automatically find the first broken
960 - use 'make && make tests' to automatically find the first broken
961 revision::
961 revision::
962
962
963 hg bisect --reset
963 hg bisect --reset
964 hg bisect --bad 34
964 hg bisect --bad 34
965 hg bisect --good 12
965 hg bisect --good 12
966 hg bisect --command "make && make tests"
966 hg bisect --command "make && make tests"
967
967
968 - see all changesets whose states are already known in the current
968 - see all changesets whose states are already known in the current
969 bisection::
969 bisection::
970
970
971 hg log -r "bisect(pruned)"
971 hg log -r "bisect(pruned)"
972
972
973 - see the changeset currently being bisected (especially useful
973 - see the changeset currently being bisected (especially useful
974 if running with -U/--noupdate)::
974 if running with -U/--noupdate)::
975
975
976 hg log -r "bisect(current)"
976 hg log -r "bisect(current)"
977
977
978 - see all changesets that took part in the current bisection::
978 - see all changesets that took part in the current bisection::
979
979
980 hg log -r "bisect(range)"
980 hg log -r "bisect(range)"
981
981
982 - you can even get a nice graph::
982 - you can even get a nice graph::
983
983
984 hg log --graph -r "bisect(range)"
984 hg log --graph -r "bisect(range)"
985
985
986 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
986 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
987
987
988 Returns 0 on success.
988 Returns 0 on success.
989 """
989 """
990 # backward compatibility
990 # backward compatibility
991 if rev in b"good bad reset init".split():
991 if rev in b"good bad reset init".split():
992 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
992 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
993 cmd, rev, extra = rev, extra, None
993 cmd, rev, extra = rev, extra, None
994 if cmd == b"good":
994 if cmd == b"good":
995 good = True
995 good = True
996 elif cmd == b"bad":
996 elif cmd == b"bad":
997 bad = True
997 bad = True
998 else:
998 else:
999 reset = True
999 reset = True
1000 elif extra:
1000 elif extra:
1001 raise error.Abort(_(b'incompatible arguments'))
1001 raise error.Abort(_(b'incompatible arguments'))
1002
1002
1003 incompatibles = {
1003 incompatibles = {
1004 b'--bad': bad,
1004 b'--bad': bad,
1005 b'--command': bool(command),
1005 b'--command': bool(command),
1006 b'--extend': extend,
1006 b'--extend': extend,
1007 b'--good': good,
1007 b'--good': good,
1008 b'--reset': reset,
1008 b'--reset': reset,
1009 b'--skip': skip,
1009 b'--skip': skip,
1010 }
1010 }
1011
1011
1012 enabled = [x for x in incompatibles if incompatibles[x]]
1012 enabled = [x for x in incompatibles if incompatibles[x]]
1013
1013
1014 if len(enabled) > 1:
1014 if len(enabled) > 1:
1015 raise error.Abort(
1015 raise error.Abort(
1016 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1016 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1017 )
1017 )
1018
1018
1019 if reset:
1019 if reset:
1020 hbisect.resetstate(repo)
1020 hbisect.resetstate(repo)
1021 return
1021 return
1022
1022
1023 state = hbisect.load_state(repo)
1023 state = hbisect.load_state(repo)
1024
1024
1025 # update state
1025 # update state
1026 if good or bad or skip:
1026 if good or bad or skip:
1027 if rev:
1027 if rev:
1028 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
1028 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
1029 else:
1029 else:
1030 nodes = [repo.lookup(b'.')]
1030 nodes = [repo.lookup(b'.')]
1031 if good:
1031 if good:
1032 state[b'good'] += nodes
1032 state[b'good'] += nodes
1033 elif bad:
1033 elif bad:
1034 state[b'bad'] += nodes
1034 state[b'bad'] += nodes
1035 elif skip:
1035 elif skip:
1036 state[b'skip'] += nodes
1036 state[b'skip'] += nodes
1037 hbisect.save_state(repo, state)
1037 hbisect.save_state(repo, state)
1038 if not (state[b'good'] and state[b'bad']):
1038 if not (state[b'good'] and state[b'bad']):
1039 return
1039 return
1040
1040
1041 def mayupdate(repo, node, show_stats=True):
1041 def mayupdate(repo, node, show_stats=True):
1042 """common used update sequence"""
1042 """common used update sequence"""
1043 if noupdate:
1043 if noupdate:
1044 return
1044 return
1045 cmdutil.checkunfinished(repo)
1045 cmdutil.checkunfinished(repo)
1046 cmdutil.bailifchanged(repo)
1046 cmdutil.bailifchanged(repo)
1047 return hg.clean(repo, node, show_stats=show_stats)
1047 return hg.clean(repo, node, show_stats=show_stats)
1048
1048
1049 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1049 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1050
1050
1051 if command:
1051 if command:
1052 changesets = 1
1052 changesets = 1
1053 if noupdate:
1053 if noupdate:
1054 try:
1054 try:
1055 node = state[b'current'][0]
1055 node = state[b'current'][0]
1056 except LookupError:
1056 except LookupError:
1057 raise error.Abort(
1057 raise error.Abort(
1058 _(
1058 _(
1059 b'current bisect revision is unknown - '
1059 b'current bisect revision is unknown - '
1060 b'start a new bisect to fix'
1060 b'start a new bisect to fix'
1061 )
1061 )
1062 )
1062 )
1063 else:
1063 else:
1064 node, p2 = repo.dirstate.parents()
1064 node, p2 = repo.dirstate.parents()
1065 if p2 != nullid:
1065 if p2 != nullid:
1066 raise error.Abort(_(b'current bisect revision is a merge'))
1066 raise error.Abort(_(b'current bisect revision is a merge'))
1067 if rev:
1067 if rev:
1068 node = repo[scmutil.revsingle(repo, rev, node)].node()
1068 node = repo[scmutil.revsingle(repo, rev, node)].node()
1069 with hbisect.restore_state(repo, state, node):
1069 with hbisect.restore_state(repo, state, node):
1070 while changesets:
1070 while changesets:
1071 # update state
1071 # update state
1072 state[b'current'] = [node]
1072 state[b'current'] = [node]
1073 hbisect.save_state(repo, state)
1073 hbisect.save_state(repo, state)
1074 status = ui.system(
1074 status = ui.system(
1075 command,
1075 command,
1076 environ={b'HG_NODE': hex(node)},
1076 environ={b'HG_NODE': hex(node)},
1077 blockedtag=b'bisect_check',
1077 blockedtag=b'bisect_check',
1078 )
1078 )
1079 if status == 125:
1079 if status == 125:
1080 transition = b"skip"
1080 transition = b"skip"
1081 elif status == 0:
1081 elif status == 0:
1082 transition = b"good"
1082 transition = b"good"
1083 # status < 0 means process was killed
1083 # status < 0 means process was killed
1084 elif status == 127:
1084 elif status == 127:
1085 raise error.Abort(_(b"failed to execute %s") % command)
1085 raise error.Abort(_(b"failed to execute %s") % command)
1086 elif status < 0:
1086 elif status < 0:
1087 raise error.Abort(_(b"%s killed") % command)
1087 raise error.Abort(_(b"%s killed") % command)
1088 else:
1088 else:
1089 transition = b"bad"
1089 transition = b"bad"
1090 state[transition].append(node)
1090 state[transition].append(node)
1091 ctx = repo[node]
1091 ctx = repo[node]
1092 ui.status(
1092 ui.status(
1093 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1093 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1094 )
1094 )
1095 hbisect.checkstate(state)
1095 hbisect.checkstate(state)
1096 # bisect
1096 # bisect
1097 nodes, changesets, bgood = hbisect.bisect(repo, state)
1097 nodes, changesets, bgood = hbisect.bisect(repo, state)
1098 # update to next check
1098 # update to next check
1099 node = nodes[0]
1099 node = nodes[0]
1100 mayupdate(repo, node, show_stats=False)
1100 mayupdate(repo, node, show_stats=False)
1101 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1101 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1102 return
1102 return
1103
1103
1104 hbisect.checkstate(state)
1104 hbisect.checkstate(state)
1105
1105
1106 # actually bisect
1106 # actually bisect
1107 nodes, changesets, good = hbisect.bisect(repo, state)
1107 nodes, changesets, good = hbisect.bisect(repo, state)
1108 if extend:
1108 if extend:
1109 if not changesets:
1109 if not changesets:
1110 extendnode = hbisect.extendrange(repo, state, nodes, good)
1110 extendnode = hbisect.extendrange(repo, state, nodes, good)
1111 if extendnode is not None:
1111 if extendnode is not None:
1112 ui.write(
1112 ui.write(
1113 _(b"Extending search to changeset %d:%s\n")
1113 _(b"Extending search to changeset %d:%s\n")
1114 % (extendnode.rev(), extendnode)
1114 % (extendnode.rev(), extendnode)
1115 )
1115 )
1116 state[b'current'] = [extendnode.node()]
1116 state[b'current'] = [extendnode.node()]
1117 hbisect.save_state(repo, state)
1117 hbisect.save_state(repo, state)
1118 return mayupdate(repo, extendnode.node())
1118 return mayupdate(repo, extendnode.node())
1119 raise error.Abort(_(b"nothing to extend"))
1119 raise error.Abort(_(b"nothing to extend"))
1120
1120
1121 if changesets == 0:
1121 if changesets == 0:
1122 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1122 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1123 else:
1123 else:
1124 assert len(nodes) == 1 # only a single node can be tested next
1124 assert len(nodes) == 1 # only a single node can be tested next
1125 node = nodes[0]
1125 node = nodes[0]
1126 # compute the approximate number of remaining tests
1126 # compute the approximate number of remaining tests
1127 tests, size = 0, 2
1127 tests, size = 0, 2
1128 while size <= changesets:
1128 while size <= changesets:
1129 tests, size = tests + 1, size * 2
1129 tests, size = tests + 1, size * 2
1130 rev = repo.changelog.rev(node)
1130 rev = repo.changelog.rev(node)
1131 ui.write(
1131 ui.write(
1132 _(
1132 _(
1133 b"Testing changeset %d:%s "
1133 b"Testing changeset %d:%s "
1134 b"(%d changesets remaining, ~%d tests)\n"
1134 b"(%d changesets remaining, ~%d tests)\n"
1135 )
1135 )
1136 % (rev, short(node), changesets, tests)
1136 % (rev, short(node), changesets, tests)
1137 )
1137 )
1138 state[b'current'] = [node]
1138 state[b'current'] = [node]
1139 hbisect.save_state(repo, state)
1139 hbisect.save_state(repo, state)
1140 return mayupdate(repo, node)
1140 return mayupdate(repo, node)
1141
1141
1142
1142
1143 @command(
1143 @command(
1144 b'bookmarks|bookmark',
1144 b'bookmarks|bookmark',
1145 [
1145 [
1146 (b'f', b'force', False, _(b'force')),
1146 (b'f', b'force', False, _(b'force')),
1147 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1147 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1148 (b'd', b'delete', False, _(b'delete a given bookmark')),
1148 (b'd', b'delete', False, _(b'delete a given bookmark')),
1149 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1149 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1150 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1150 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1151 (b'l', b'list', False, _(b'list existing bookmarks')),
1151 (b'l', b'list', False, _(b'list existing bookmarks')),
1152 ]
1152 ]
1153 + formatteropts,
1153 + formatteropts,
1154 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1154 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1155 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1155 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1156 )
1156 )
1157 def bookmark(ui, repo, *names, **opts):
1157 def bookmark(ui, repo, *names, **opts):
1158 '''create a new bookmark or list existing bookmarks
1158 '''create a new bookmark or list existing bookmarks
1159
1159
1160 Bookmarks are labels on changesets to help track lines of development.
1160 Bookmarks are labels on changesets to help track lines of development.
1161 Bookmarks are unversioned and can be moved, renamed and deleted.
1161 Bookmarks are unversioned and can be moved, renamed and deleted.
1162 Deleting or moving a bookmark has no effect on the associated changesets.
1162 Deleting or moving a bookmark has no effect on the associated changesets.
1163
1163
1164 Creating or updating to a bookmark causes it to be marked as 'active'.
1164 Creating or updating to a bookmark causes it to be marked as 'active'.
1165 The active bookmark is indicated with a '*'.
1165 The active bookmark is indicated with a '*'.
1166 When a commit is made, the active bookmark will advance to the new commit.
1166 When a commit is made, the active bookmark will advance to the new commit.
1167 A plain :hg:`update` will also advance an active bookmark, if possible.
1167 A plain :hg:`update` will also advance an active bookmark, if possible.
1168 Updating away from a bookmark will cause it to be deactivated.
1168 Updating away from a bookmark will cause it to be deactivated.
1169
1169
1170 Bookmarks can be pushed and pulled between repositories (see
1170 Bookmarks can be pushed and pulled between repositories (see
1171 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1171 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1172 diverged, a new 'divergent bookmark' of the form 'name@path' will
1172 diverged, a new 'divergent bookmark' of the form 'name@path' will
1173 be created. Using :hg:`merge` will resolve the divergence.
1173 be created. Using :hg:`merge` will resolve the divergence.
1174
1174
1175 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1175 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1176 the active bookmark's name.
1176 the active bookmark's name.
1177
1177
1178 A bookmark named '@' has the special property that :hg:`clone` will
1178 A bookmark named '@' has the special property that :hg:`clone` will
1179 check it out by default if it exists.
1179 check it out by default if it exists.
1180
1180
1181 .. container:: verbose
1181 .. container:: verbose
1182
1182
1183 Template:
1183 Template:
1184
1184
1185 The following keywords are supported in addition to the common template
1185 The following keywords are supported in addition to the common template
1186 keywords and functions such as ``{bookmark}``. See also
1186 keywords and functions such as ``{bookmark}``. See also
1187 :hg:`help templates`.
1187 :hg:`help templates`.
1188
1188
1189 :active: Boolean. True if the bookmark is active.
1189 :active: Boolean. True if the bookmark is active.
1190
1190
1191 Examples:
1191 Examples:
1192
1192
1193 - create an active bookmark for a new line of development::
1193 - create an active bookmark for a new line of development::
1194
1194
1195 hg book new-feature
1195 hg book new-feature
1196
1196
1197 - create an inactive bookmark as a place marker::
1197 - create an inactive bookmark as a place marker::
1198
1198
1199 hg book -i reviewed
1199 hg book -i reviewed
1200
1200
1201 - create an inactive bookmark on another changeset::
1201 - create an inactive bookmark on another changeset::
1202
1202
1203 hg book -r .^ tested
1203 hg book -r .^ tested
1204
1204
1205 - rename bookmark turkey to dinner::
1205 - rename bookmark turkey to dinner::
1206
1206
1207 hg book -m turkey dinner
1207 hg book -m turkey dinner
1208
1208
1209 - move the '@' bookmark from another branch::
1209 - move the '@' bookmark from another branch::
1210
1210
1211 hg book -f @
1211 hg book -f @
1212
1212
1213 - print only the active bookmark name::
1213 - print only the active bookmark name::
1214
1214
1215 hg book -ql .
1215 hg book -ql .
1216 '''
1216 '''
1217 opts = pycompat.byteskwargs(opts)
1217 opts = pycompat.byteskwargs(opts)
1218 force = opts.get(b'force')
1218 force = opts.get(b'force')
1219 rev = opts.get(b'rev')
1219 rev = opts.get(b'rev')
1220 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1220 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1221
1221
1222 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1222 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1223 if action:
1223 if action:
1224 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1224 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1225 elif names or rev:
1225 elif names or rev:
1226 action = b'add'
1226 action = b'add'
1227 elif inactive:
1227 elif inactive:
1228 action = b'inactive' # meaning deactivate
1228 action = b'inactive' # meaning deactivate
1229 else:
1229 else:
1230 action = b'list'
1230 action = b'list'
1231
1231
1232 cmdutil.check_incompatible_arguments(
1232 cmdutil.check_incompatible_arguments(
1233 opts, b'inactive', [b'delete', b'list']
1233 opts, b'inactive', [b'delete', b'list']
1234 )
1234 )
1235 if not names and action in {b'add', b'delete'}:
1235 if not names and action in {b'add', b'delete'}:
1236 raise error.Abort(_(b"bookmark name required"))
1236 raise error.Abort(_(b"bookmark name required"))
1237
1237
1238 if action in {b'add', b'delete', b'rename', b'inactive'}:
1238 if action in {b'add', b'delete', b'rename', b'inactive'}:
1239 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1239 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1240 if action == b'delete':
1240 if action == b'delete':
1241 names = pycompat.maplist(repo._bookmarks.expandname, names)
1241 names = pycompat.maplist(repo._bookmarks.expandname, names)
1242 bookmarks.delete(repo, tr, names)
1242 bookmarks.delete(repo, tr, names)
1243 elif action == b'rename':
1243 elif action == b'rename':
1244 if not names:
1244 if not names:
1245 raise error.Abort(_(b"new bookmark name required"))
1245 raise error.Abort(_(b"new bookmark name required"))
1246 elif len(names) > 1:
1246 elif len(names) > 1:
1247 raise error.Abort(_(b"only one new bookmark name allowed"))
1247 raise error.Abort(_(b"only one new bookmark name allowed"))
1248 oldname = repo._bookmarks.expandname(opts[b'rename'])
1248 oldname = repo._bookmarks.expandname(opts[b'rename'])
1249 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1249 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1250 elif action == b'add':
1250 elif action == b'add':
1251 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1251 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1252 elif action == b'inactive':
1252 elif action == b'inactive':
1253 if len(repo._bookmarks) == 0:
1253 if len(repo._bookmarks) == 0:
1254 ui.status(_(b"no bookmarks set\n"))
1254 ui.status(_(b"no bookmarks set\n"))
1255 elif not repo._activebookmark:
1255 elif not repo._activebookmark:
1256 ui.status(_(b"no active bookmark\n"))
1256 ui.status(_(b"no active bookmark\n"))
1257 else:
1257 else:
1258 bookmarks.deactivate(repo)
1258 bookmarks.deactivate(repo)
1259 elif action == b'list':
1259 elif action == b'list':
1260 names = pycompat.maplist(repo._bookmarks.expandname, names)
1260 names = pycompat.maplist(repo._bookmarks.expandname, names)
1261 with ui.formatter(b'bookmarks', opts) as fm:
1261 with ui.formatter(b'bookmarks', opts) as fm:
1262 bookmarks.printbookmarks(ui, repo, fm, names)
1262 bookmarks.printbookmarks(ui, repo, fm, names)
1263 else:
1263 else:
1264 raise error.ProgrammingError(b'invalid action: %s' % action)
1264 raise error.ProgrammingError(b'invalid action: %s' % action)
1265
1265
1266
1266
1267 @command(
1267 @command(
1268 b'branch',
1268 b'branch',
1269 [
1269 [
1270 (
1270 (
1271 b'f',
1271 b'f',
1272 b'force',
1272 b'force',
1273 None,
1273 None,
1274 _(b'set branch name even if it shadows an existing branch'),
1274 _(b'set branch name even if it shadows an existing branch'),
1275 ),
1275 ),
1276 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1276 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1277 (
1277 (
1278 b'r',
1278 b'r',
1279 b'rev',
1279 b'rev',
1280 [],
1280 [],
1281 _(b'change branches of the given revs (EXPERIMENTAL)'),
1281 _(b'change branches of the given revs (EXPERIMENTAL)'),
1282 ),
1282 ),
1283 ],
1283 ],
1284 _(b'[-fC] [NAME]'),
1284 _(b'[-fC] [NAME]'),
1285 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1285 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1286 )
1286 )
1287 def branch(ui, repo, label=None, **opts):
1287 def branch(ui, repo, label=None, **opts):
1288 """set or show the current branch name
1288 """set or show the current branch name
1289
1289
1290 .. note::
1290 .. note::
1291
1291
1292 Branch names are permanent and global. Use :hg:`bookmark` to create a
1292 Branch names are permanent and global. Use :hg:`bookmark` to create a
1293 light-weight bookmark instead. See :hg:`help glossary` for more
1293 light-weight bookmark instead. See :hg:`help glossary` for more
1294 information about named branches and bookmarks.
1294 information about named branches and bookmarks.
1295
1295
1296 With no argument, show the current branch name. With one argument,
1296 With no argument, show the current branch name. With one argument,
1297 set the working directory branch name (the branch will not exist
1297 set the working directory branch name (the branch will not exist
1298 in the repository until the next commit). Standard practice
1298 in the repository until the next commit). Standard practice
1299 recommends that primary development take place on the 'default'
1299 recommends that primary development take place on the 'default'
1300 branch.
1300 branch.
1301
1301
1302 Unless -f/--force is specified, branch will not let you set a
1302 Unless -f/--force is specified, branch will not let you set a
1303 branch name that already exists.
1303 branch name that already exists.
1304
1304
1305 Use -C/--clean to reset the working directory branch to that of
1305 Use -C/--clean to reset the working directory branch to that of
1306 the parent of the working directory, negating a previous branch
1306 the parent of the working directory, negating a previous branch
1307 change.
1307 change.
1308
1308
1309 Use the command :hg:`update` to switch to an existing branch. Use
1309 Use the command :hg:`update` to switch to an existing branch. Use
1310 :hg:`commit --close-branch` to mark this branch head as closed.
1310 :hg:`commit --close-branch` to mark this branch head as closed.
1311 When all heads of a branch are closed, the branch will be
1311 When all heads of a branch are closed, the branch will be
1312 considered closed.
1312 considered closed.
1313
1313
1314 Returns 0 on success.
1314 Returns 0 on success.
1315 """
1315 """
1316 opts = pycompat.byteskwargs(opts)
1316 opts = pycompat.byteskwargs(opts)
1317 revs = opts.get(b'rev')
1317 revs = opts.get(b'rev')
1318 if label:
1318 if label:
1319 label = label.strip()
1319 label = label.strip()
1320
1320
1321 if not opts.get(b'clean') and not label:
1321 if not opts.get(b'clean') and not label:
1322 if revs:
1322 if revs:
1323 raise error.Abort(_(b"no branch name specified for the revisions"))
1323 raise error.Abort(_(b"no branch name specified for the revisions"))
1324 ui.write(b"%s\n" % repo.dirstate.branch())
1324 ui.write(b"%s\n" % repo.dirstate.branch())
1325 return
1325 return
1326
1326
1327 with repo.wlock():
1327 with repo.wlock():
1328 if opts.get(b'clean'):
1328 if opts.get(b'clean'):
1329 label = repo[b'.'].branch()
1329 label = repo[b'.'].branch()
1330 repo.dirstate.setbranch(label)
1330 repo.dirstate.setbranch(label)
1331 ui.status(_(b'reset working directory to branch %s\n') % label)
1331 ui.status(_(b'reset working directory to branch %s\n') % label)
1332 elif label:
1332 elif label:
1333
1333
1334 scmutil.checknewlabel(repo, label, b'branch')
1334 scmutil.checknewlabel(repo, label, b'branch')
1335 if revs:
1335 if revs:
1336 return cmdutil.changebranch(ui, repo, revs, label, opts)
1336 return cmdutil.changebranch(ui, repo, revs, label, opts)
1337
1337
1338 if not opts.get(b'force') and label in repo.branchmap():
1338 if not opts.get(b'force') and label in repo.branchmap():
1339 if label not in [p.branch() for p in repo[None].parents()]:
1339 if label not in [p.branch() for p in repo[None].parents()]:
1340 raise error.Abort(
1340 raise error.Abort(
1341 _(b'a branch of the same name already exists'),
1341 _(b'a branch of the same name already exists'),
1342 # i18n: "it" refers to an existing branch
1342 # i18n: "it" refers to an existing branch
1343 hint=_(b"use 'hg update' to switch to it"),
1343 hint=_(b"use 'hg update' to switch to it"),
1344 )
1344 )
1345
1345
1346 repo.dirstate.setbranch(label)
1346 repo.dirstate.setbranch(label)
1347 ui.status(_(b'marked working directory as branch %s\n') % label)
1347 ui.status(_(b'marked working directory as branch %s\n') % label)
1348
1348
1349 # find any open named branches aside from default
1349 # find any open named branches aside from default
1350 for n, h, t, c in repo.branchmap().iterbranches():
1350 for n, h, t, c in repo.branchmap().iterbranches():
1351 if n != b"default" and not c:
1351 if n != b"default" and not c:
1352 return 0
1352 return 0
1353 ui.status(
1353 ui.status(
1354 _(
1354 _(
1355 b'(branches are permanent and global, '
1355 b'(branches are permanent and global, '
1356 b'did you want a bookmark?)\n'
1356 b'did you want a bookmark?)\n'
1357 )
1357 )
1358 )
1358 )
1359
1359
1360
1360
1361 @command(
1361 @command(
1362 b'branches',
1362 b'branches',
1363 [
1363 [
1364 (
1364 (
1365 b'a',
1365 b'a',
1366 b'active',
1366 b'active',
1367 False,
1367 False,
1368 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1368 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1369 ),
1369 ),
1370 (b'c', b'closed', False, _(b'show normal and closed branches')),
1370 (b'c', b'closed', False, _(b'show normal and closed branches')),
1371 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1371 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1372 ]
1372 ]
1373 + formatteropts,
1373 + formatteropts,
1374 _(b'[-c]'),
1374 _(b'[-c]'),
1375 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1375 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1376 intents={INTENT_READONLY},
1376 intents={INTENT_READONLY},
1377 )
1377 )
1378 def branches(ui, repo, active=False, closed=False, **opts):
1378 def branches(ui, repo, active=False, closed=False, **opts):
1379 """list repository named branches
1379 """list repository named branches
1380
1380
1381 List the repository's named branches, indicating which ones are
1381 List the repository's named branches, indicating which ones are
1382 inactive. If -c/--closed is specified, also list branches which have
1382 inactive. If -c/--closed is specified, also list branches which have
1383 been marked closed (see :hg:`commit --close-branch`).
1383 been marked closed (see :hg:`commit --close-branch`).
1384
1384
1385 Use the command :hg:`update` to switch to an existing branch.
1385 Use the command :hg:`update` to switch to an existing branch.
1386
1386
1387 .. container:: verbose
1387 .. container:: verbose
1388
1388
1389 Template:
1389 Template:
1390
1390
1391 The following keywords are supported in addition to the common template
1391 The following keywords are supported in addition to the common template
1392 keywords and functions such as ``{branch}``. See also
1392 keywords and functions such as ``{branch}``. See also
1393 :hg:`help templates`.
1393 :hg:`help templates`.
1394
1394
1395 :active: Boolean. True if the branch is active.
1395 :active: Boolean. True if the branch is active.
1396 :closed: Boolean. True if the branch is closed.
1396 :closed: Boolean. True if the branch is closed.
1397 :current: Boolean. True if it is the current branch.
1397 :current: Boolean. True if it is the current branch.
1398
1398
1399 Returns 0.
1399 Returns 0.
1400 """
1400 """
1401
1401
1402 opts = pycompat.byteskwargs(opts)
1402 opts = pycompat.byteskwargs(opts)
1403 revs = opts.get(b'rev')
1403 revs = opts.get(b'rev')
1404 selectedbranches = None
1404 selectedbranches = None
1405 if revs:
1405 if revs:
1406 revs = scmutil.revrange(repo, revs)
1406 revs = scmutil.revrange(repo, revs)
1407 getbi = repo.revbranchcache().branchinfo
1407 getbi = repo.revbranchcache().branchinfo
1408 selectedbranches = {getbi(r)[0] for r in revs}
1408 selectedbranches = {getbi(r)[0] for r in revs}
1409
1409
1410 ui.pager(b'branches')
1410 ui.pager(b'branches')
1411 fm = ui.formatter(b'branches', opts)
1411 fm = ui.formatter(b'branches', opts)
1412 hexfunc = fm.hexfunc
1412 hexfunc = fm.hexfunc
1413
1413
1414 allheads = set(repo.heads())
1414 allheads = set(repo.heads())
1415 branches = []
1415 branches = []
1416 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1416 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1417 if selectedbranches is not None and tag not in selectedbranches:
1417 if selectedbranches is not None and tag not in selectedbranches:
1418 continue
1418 continue
1419 isactive = False
1419 isactive = False
1420 if not isclosed:
1420 if not isclosed:
1421 openheads = set(repo.branchmap().iteropen(heads))
1421 openheads = set(repo.branchmap().iteropen(heads))
1422 isactive = bool(openheads & allheads)
1422 isactive = bool(openheads & allheads)
1423 branches.append((tag, repo[tip], isactive, not isclosed))
1423 branches.append((tag, repo[tip], isactive, not isclosed))
1424 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1424 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1425
1425
1426 for tag, ctx, isactive, isopen in branches:
1426 for tag, ctx, isactive, isopen in branches:
1427 if active and not isactive:
1427 if active and not isactive:
1428 continue
1428 continue
1429 if isactive:
1429 if isactive:
1430 label = b'branches.active'
1430 label = b'branches.active'
1431 notice = b''
1431 notice = b''
1432 elif not isopen:
1432 elif not isopen:
1433 if not closed:
1433 if not closed:
1434 continue
1434 continue
1435 label = b'branches.closed'
1435 label = b'branches.closed'
1436 notice = _(b' (closed)')
1436 notice = _(b' (closed)')
1437 else:
1437 else:
1438 label = b'branches.inactive'
1438 label = b'branches.inactive'
1439 notice = _(b' (inactive)')
1439 notice = _(b' (inactive)')
1440 current = tag == repo.dirstate.branch()
1440 current = tag == repo.dirstate.branch()
1441 if current:
1441 if current:
1442 label = b'branches.current'
1442 label = b'branches.current'
1443
1443
1444 fm.startitem()
1444 fm.startitem()
1445 fm.write(b'branch', b'%s', tag, label=label)
1445 fm.write(b'branch', b'%s', tag, label=label)
1446 rev = ctx.rev()
1446 rev = ctx.rev()
1447 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1447 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1448 fmt = b' ' * padsize + b' %d:%s'
1448 fmt = b' ' * padsize + b' %d:%s'
1449 fm.condwrite(
1449 fm.condwrite(
1450 not ui.quiet,
1450 not ui.quiet,
1451 b'rev node',
1451 b'rev node',
1452 fmt,
1452 fmt,
1453 rev,
1453 rev,
1454 hexfunc(ctx.node()),
1454 hexfunc(ctx.node()),
1455 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1455 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1456 )
1456 )
1457 fm.context(ctx=ctx)
1457 fm.context(ctx=ctx)
1458 fm.data(active=isactive, closed=not isopen, current=current)
1458 fm.data(active=isactive, closed=not isopen, current=current)
1459 if not ui.quiet:
1459 if not ui.quiet:
1460 fm.plain(notice)
1460 fm.plain(notice)
1461 fm.plain(b'\n')
1461 fm.plain(b'\n')
1462 fm.end()
1462 fm.end()
1463
1463
1464
1464
1465 @command(
1465 @command(
1466 b'bundle',
1466 b'bundle',
1467 [
1467 [
1468 (
1468 (
1469 b'f',
1469 b'f',
1470 b'force',
1470 b'force',
1471 None,
1471 None,
1472 _(b'run even when the destination is unrelated'),
1472 _(b'run even when the destination is unrelated'),
1473 ),
1473 ),
1474 (
1474 (
1475 b'r',
1475 b'r',
1476 b'rev',
1476 b'rev',
1477 [],
1477 [],
1478 _(b'a changeset intended to be added to the destination'),
1478 _(b'a changeset intended to be added to the destination'),
1479 _(b'REV'),
1479 _(b'REV'),
1480 ),
1480 ),
1481 (
1481 (
1482 b'b',
1482 b'b',
1483 b'branch',
1483 b'branch',
1484 [],
1484 [],
1485 _(b'a specific branch you would like to bundle'),
1485 _(b'a specific branch you would like to bundle'),
1486 _(b'BRANCH'),
1486 _(b'BRANCH'),
1487 ),
1487 ),
1488 (
1488 (
1489 b'',
1489 b'',
1490 b'base',
1490 b'base',
1491 [],
1491 [],
1492 _(b'a base changeset assumed to be available at the destination'),
1492 _(b'a base changeset assumed to be available at the destination'),
1493 _(b'REV'),
1493 _(b'REV'),
1494 ),
1494 ),
1495 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1495 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1496 (
1496 (
1497 b't',
1497 b't',
1498 b'type',
1498 b'type',
1499 b'bzip2',
1499 b'bzip2',
1500 _(b'bundle compression type to use'),
1500 _(b'bundle compression type to use'),
1501 _(b'TYPE'),
1501 _(b'TYPE'),
1502 ),
1502 ),
1503 ]
1503 ]
1504 + remoteopts,
1504 + remoteopts,
1505 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1505 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1506 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1506 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1507 )
1507 )
1508 def bundle(ui, repo, fname, dest=None, **opts):
1508 def bundle(ui, repo, fname, dest=None, **opts):
1509 """create a bundle file
1509 """create a bundle file
1510
1510
1511 Generate a bundle file containing data to be transferred to another
1511 Generate a bundle file containing data to be transferred to another
1512 repository.
1512 repository.
1513
1513
1514 To create a bundle containing all changesets, use -a/--all
1514 To create a bundle containing all changesets, use -a/--all
1515 (or --base null). Otherwise, hg assumes the destination will have
1515 (or --base null). Otherwise, hg assumes the destination will have
1516 all the nodes you specify with --base parameters. Otherwise, hg
1516 all the nodes you specify with --base parameters. Otherwise, hg
1517 will assume the repository has all the nodes in destination, or
1517 will assume the repository has all the nodes in destination, or
1518 default-push/default if no destination is specified, where destination
1518 default-push/default if no destination is specified, where destination
1519 is the repository you provide through DEST option.
1519 is the repository you provide through DEST option.
1520
1520
1521 You can change bundle format with the -t/--type option. See
1521 You can change bundle format with the -t/--type option. See
1522 :hg:`help bundlespec` for documentation on this format. By default,
1522 :hg:`help bundlespec` for documentation on this format. By default,
1523 the most appropriate format is used and compression defaults to
1523 the most appropriate format is used and compression defaults to
1524 bzip2.
1524 bzip2.
1525
1525
1526 The bundle file can then be transferred using conventional means
1526 The bundle file can then be transferred using conventional means
1527 and applied to another repository with the unbundle or pull
1527 and applied to another repository with the unbundle or pull
1528 command. This is useful when direct push and pull are not
1528 command. This is useful when direct push and pull are not
1529 available or when exporting an entire repository is undesirable.
1529 available or when exporting an entire repository is undesirable.
1530
1530
1531 Applying bundles preserves all changeset contents including
1531 Applying bundles preserves all changeset contents including
1532 permissions, copy/rename information, and revision history.
1532 permissions, copy/rename information, and revision history.
1533
1533
1534 Returns 0 on success, 1 if no changes found.
1534 Returns 0 on success, 1 if no changes found.
1535 """
1535 """
1536 opts = pycompat.byteskwargs(opts)
1536 opts = pycompat.byteskwargs(opts)
1537 revs = None
1537 revs = None
1538 if b'rev' in opts:
1538 if b'rev' in opts:
1539 revstrings = opts[b'rev']
1539 revstrings = opts[b'rev']
1540 revs = scmutil.revrange(repo, revstrings)
1540 revs = scmutil.revrange(repo, revstrings)
1541 if revstrings and not revs:
1541 if revstrings and not revs:
1542 raise error.Abort(_(b'no commits to bundle'))
1542 raise error.Abort(_(b'no commits to bundle'))
1543
1543
1544 bundletype = opts.get(b'type', b'bzip2').lower()
1544 bundletype = opts.get(b'type', b'bzip2').lower()
1545 try:
1545 try:
1546 bundlespec = bundlecaches.parsebundlespec(
1546 bundlespec = bundlecaches.parsebundlespec(
1547 repo, bundletype, strict=False
1547 repo, bundletype, strict=False
1548 )
1548 )
1549 except error.UnsupportedBundleSpecification as e:
1549 except error.UnsupportedBundleSpecification as e:
1550 raise error.Abort(
1550 raise error.Abort(
1551 pycompat.bytestr(e),
1551 pycompat.bytestr(e),
1552 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1552 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1553 )
1553 )
1554 cgversion = bundlespec.contentopts[b"cg.version"]
1554 cgversion = bundlespec.contentopts[b"cg.version"]
1555
1555
1556 # Packed bundles are a pseudo bundle format for now.
1556 # Packed bundles are a pseudo bundle format for now.
1557 if cgversion == b's1':
1557 if cgversion == b's1':
1558 raise error.Abort(
1558 raise error.Abort(
1559 _(b'packed bundles cannot be produced by "hg bundle"'),
1559 _(b'packed bundles cannot be produced by "hg bundle"'),
1560 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1560 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1561 )
1561 )
1562
1562
1563 if opts.get(b'all'):
1563 if opts.get(b'all'):
1564 if dest:
1564 if dest:
1565 raise error.Abort(
1565 raise error.Abort(
1566 _(b"--all is incompatible with specifying a destination")
1566 _(b"--all is incompatible with specifying a destination")
1567 )
1567 )
1568 if opts.get(b'base'):
1568 if opts.get(b'base'):
1569 ui.warn(_(b"ignoring --base because --all was specified\n"))
1569 ui.warn(_(b"ignoring --base because --all was specified\n"))
1570 base = [nullrev]
1570 base = [nullrev]
1571 else:
1571 else:
1572 base = scmutil.revrange(repo, opts.get(b'base'))
1572 base = scmutil.revrange(repo, opts.get(b'base'))
1573 if cgversion not in changegroup.supportedoutgoingversions(repo):
1573 if cgversion not in changegroup.supportedoutgoingversions(repo):
1574 raise error.Abort(
1574 raise error.Abort(
1575 _(b"repository does not support bundle version %s") % cgversion
1575 _(b"repository does not support bundle version %s") % cgversion
1576 )
1576 )
1577
1577
1578 if base:
1578 if base:
1579 if dest:
1579 if dest:
1580 raise error.Abort(
1580 raise error.Abort(
1581 _(b"--base is incompatible with specifying a destination")
1581 _(b"--base is incompatible with specifying a destination")
1582 )
1582 )
1583 common = [repo[rev].node() for rev in base]
1583 common = [repo[rev].node() for rev in base]
1584 heads = [repo[r].node() for r in revs] if revs else None
1584 heads = [repo[r].node() for r in revs] if revs else None
1585 outgoing = discovery.outgoing(repo, common, heads)
1585 outgoing = discovery.outgoing(repo, common, heads)
1586 else:
1586 else:
1587 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1587 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1588 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1588 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1589 other = hg.peer(repo, opts, dest)
1589 other = hg.peer(repo, opts, dest)
1590 revs = [repo[r].hex() for r in revs]
1590 revs = [repo[r].hex() for r in revs]
1591 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1591 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1592 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1592 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1593 outgoing = discovery.findcommonoutgoing(
1593 outgoing = discovery.findcommonoutgoing(
1594 repo,
1594 repo,
1595 other,
1595 other,
1596 onlyheads=heads,
1596 onlyheads=heads,
1597 force=opts.get(b'force'),
1597 force=opts.get(b'force'),
1598 portable=True,
1598 portable=True,
1599 )
1599 )
1600
1600
1601 if not outgoing.missing:
1601 if not outgoing.missing:
1602 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1602 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1603 return 1
1603 return 1
1604
1604
1605 if cgversion == b'01': # bundle1
1605 if cgversion == b'01': # bundle1
1606 bversion = b'HG10' + bundlespec.wirecompression
1606 bversion = b'HG10' + bundlespec.wirecompression
1607 bcompression = None
1607 bcompression = None
1608 elif cgversion in (b'02', b'03'):
1608 elif cgversion in (b'02', b'03'):
1609 bversion = b'HG20'
1609 bversion = b'HG20'
1610 bcompression = bundlespec.wirecompression
1610 bcompression = bundlespec.wirecompression
1611 else:
1611 else:
1612 raise error.ProgrammingError(
1612 raise error.ProgrammingError(
1613 b'bundle: unexpected changegroup version %s' % cgversion
1613 b'bundle: unexpected changegroup version %s' % cgversion
1614 )
1614 )
1615
1615
1616 # TODO compression options should be derived from bundlespec parsing.
1616 # TODO compression options should be derived from bundlespec parsing.
1617 # This is a temporary hack to allow adjusting bundle compression
1617 # This is a temporary hack to allow adjusting bundle compression
1618 # level without a) formalizing the bundlespec changes to declare it
1618 # level without a) formalizing the bundlespec changes to declare it
1619 # b) introducing a command flag.
1619 # b) introducing a command flag.
1620 compopts = {}
1620 compopts = {}
1621 complevel = ui.configint(
1621 complevel = ui.configint(
1622 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1622 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1623 )
1623 )
1624 if complevel is None:
1624 if complevel is None:
1625 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1625 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1626 if complevel is not None:
1626 if complevel is not None:
1627 compopts[b'level'] = complevel
1627 compopts[b'level'] = complevel
1628
1628
1629 # Allow overriding the bundling of obsmarker in phases through
1629 # Allow overriding the bundling of obsmarker in phases through
1630 # configuration while we don't have a bundle version that include them
1630 # configuration while we don't have a bundle version that include them
1631 if repo.ui.configbool(b'experimental', b'evolution.bundle-obsmarker'):
1631 if repo.ui.configbool(b'experimental', b'evolution.bundle-obsmarker'):
1632 bundlespec.contentopts[b'obsolescence'] = True
1632 bundlespec.contentopts[b'obsolescence'] = True
1633 if repo.ui.configbool(b'experimental', b'bundle-phases'):
1633 if repo.ui.configbool(b'experimental', b'bundle-phases'):
1634 bundlespec.contentopts[b'phases'] = True
1634 bundlespec.contentopts[b'phases'] = True
1635
1635
1636 bundle2.writenewbundle(
1636 bundle2.writenewbundle(
1637 ui,
1637 ui,
1638 repo,
1638 repo,
1639 b'bundle',
1639 b'bundle',
1640 fname,
1640 fname,
1641 bversion,
1641 bversion,
1642 outgoing,
1642 outgoing,
1643 bundlespec.contentopts,
1643 bundlespec.contentopts,
1644 compression=bcompression,
1644 compression=bcompression,
1645 compopts=compopts,
1645 compopts=compopts,
1646 )
1646 )
1647
1647
1648
1648
1649 @command(
1649 @command(
1650 b'cat',
1650 b'cat',
1651 [
1651 [
1652 (
1652 (
1653 b'o',
1653 b'o',
1654 b'output',
1654 b'output',
1655 b'',
1655 b'',
1656 _(b'print output to file with formatted name'),
1656 _(b'print output to file with formatted name'),
1657 _(b'FORMAT'),
1657 _(b'FORMAT'),
1658 ),
1658 ),
1659 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1659 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1660 (b'', b'decode', None, _(b'apply any matching decode filter')),
1660 (b'', b'decode', None, _(b'apply any matching decode filter')),
1661 ]
1661 ]
1662 + walkopts
1662 + walkopts
1663 + formatteropts,
1663 + formatteropts,
1664 _(b'[OPTION]... FILE...'),
1664 _(b'[OPTION]... FILE...'),
1665 helpcategory=command.CATEGORY_FILE_CONTENTS,
1665 helpcategory=command.CATEGORY_FILE_CONTENTS,
1666 inferrepo=True,
1666 inferrepo=True,
1667 intents={INTENT_READONLY},
1667 intents={INTENT_READONLY},
1668 )
1668 )
1669 def cat(ui, repo, file1, *pats, **opts):
1669 def cat(ui, repo, file1, *pats, **opts):
1670 """output the current or given revision of files
1670 """output the current or given revision of files
1671
1671
1672 Print the specified files as they were at the given revision. If
1672 Print the specified files as they were at the given revision. If
1673 no revision is given, the parent of the working directory is used.
1673 no revision is given, the parent of the working directory is used.
1674
1674
1675 Output may be to a file, in which case the name of the file is
1675 Output may be to a file, in which case the name of the file is
1676 given using a template string. See :hg:`help templates`. In addition
1676 given using a template string. See :hg:`help templates`. In addition
1677 to the common template keywords, the following formatting rules are
1677 to the common template keywords, the following formatting rules are
1678 supported:
1678 supported:
1679
1679
1680 :``%%``: literal "%" character
1680 :``%%``: literal "%" character
1681 :``%s``: basename of file being printed
1681 :``%s``: basename of file being printed
1682 :``%d``: dirname of file being printed, or '.' if in repository root
1682 :``%d``: dirname of file being printed, or '.' if in repository root
1683 :``%p``: root-relative path name of file being printed
1683 :``%p``: root-relative path name of file being printed
1684 :``%H``: changeset hash (40 hexadecimal digits)
1684 :``%H``: changeset hash (40 hexadecimal digits)
1685 :``%R``: changeset revision number
1685 :``%R``: changeset revision number
1686 :``%h``: short-form changeset hash (12 hexadecimal digits)
1686 :``%h``: short-form changeset hash (12 hexadecimal digits)
1687 :``%r``: zero-padded changeset revision number
1687 :``%r``: zero-padded changeset revision number
1688 :``%b``: basename of the exporting repository
1688 :``%b``: basename of the exporting repository
1689 :``\\``: literal "\\" character
1689 :``\\``: literal "\\" character
1690
1690
1691 .. container:: verbose
1691 .. container:: verbose
1692
1692
1693 Template:
1693 Template:
1694
1694
1695 The following keywords are supported in addition to the common template
1695 The following keywords are supported in addition to the common template
1696 keywords and functions. See also :hg:`help templates`.
1696 keywords and functions. See also :hg:`help templates`.
1697
1697
1698 :data: String. File content.
1698 :data: String. File content.
1699 :path: String. Repository-absolute path of the file.
1699 :path: String. Repository-absolute path of the file.
1700
1700
1701 Returns 0 on success.
1701 Returns 0 on success.
1702 """
1702 """
1703 opts = pycompat.byteskwargs(opts)
1703 opts = pycompat.byteskwargs(opts)
1704 rev = opts.get(b'rev')
1704 rev = opts.get(b'rev')
1705 if rev:
1705 if rev:
1706 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1706 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1707 ctx = scmutil.revsingle(repo, rev)
1707 ctx = scmutil.revsingle(repo, rev)
1708 m = scmutil.match(ctx, (file1,) + pats, opts)
1708 m = scmutil.match(ctx, (file1,) + pats, opts)
1709 fntemplate = opts.pop(b'output', b'')
1709 fntemplate = opts.pop(b'output', b'')
1710 if cmdutil.isstdiofilename(fntemplate):
1710 if cmdutil.isstdiofilename(fntemplate):
1711 fntemplate = b''
1711 fntemplate = b''
1712
1712
1713 if fntemplate:
1713 if fntemplate:
1714 fm = formatter.nullformatter(ui, b'cat', opts)
1714 fm = formatter.nullformatter(ui, b'cat', opts)
1715 else:
1715 else:
1716 ui.pager(b'cat')
1716 ui.pager(b'cat')
1717 fm = ui.formatter(b'cat', opts)
1717 fm = ui.formatter(b'cat', opts)
1718 with fm:
1718 with fm:
1719 return cmdutil.cat(
1719 return cmdutil.cat(
1720 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1720 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1721 )
1721 )
1722
1722
1723
1723
1724 @command(
1724 @command(
1725 b'clone',
1725 b'clone',
1726 [
1726 [
1727 (
1727 (
1728 b'U',
1728 b'U',
1729 b'noupdate',
1729 b'noupdate',
1730 None,
1730 None,
1731 _(
1731 _(
1732 b'the clone will include an empty working '
1732 b'the clone will include an empty working '
1733 b'directory (only a repository)'
1733 b'directory (only a repository)'
1734 ),
1734 ),
1735 ),
1735 ),
1736 (
1736 (
1737 b'u',
1737 b'u',
1738 b'updaterev',
1738 b'updaterev',
1739 b'',
1739 b'',
1740 _(b'revision, tag, or branch to check out'),
1740 _(b'revision, tag, or branch to check out'),
1741 _(b'REV'),
1741 _(b'REV'),
1742 ),
1742 ),
1743 (
1743 (
1744 b'r',
1744 b'r',
1745 b'rev',
1745 b'rev',
1746 [],
1746 [],
1747 _(
1747 _(
1748 b'do not clone everything, but include this changeset'
1748 b'do not clone everything, but include this changeset'
1749 b' and its ancestors'
1749 b' and its ancestors'
1750 ),
1750 ),
1751 _(b'REV'),
1751 _(b'REV'),
1752 ),
1752 ),
1753 (
1753 (
1754 b'b',
1754 b'b',
1755 b'branch',
1755 b'branch',
1756 [],
1756 [],
1757 _(
1757 _(
1758 b'do not clone everything, but include this branch\'s'
1758 b'do not clone everything, but include this branch\'s'
1759 b' changesets and their ancestors'
1759 b' changesets and their ancestors'
1760 ),
1760 ),
1761 _(b'BRANCH'),
1761 _(b'BRANCH'),
1762 ),
1762 ),
1763 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1763 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1764 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1764 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1765 (b'', b'stream', None, _(b'clone with minimal data processing')),
1765 (b'', b'stream', None, _(b'clone with minimal data processing')),
1766 ]
1766 ]
1767 + remoteopts,
1767 + remoteopts,
1768 _(b'[OPTION]... SOURCE [DEST]'),
1768 _(b'[OPTION]... SOURCE [DEST]'),
1769 helpcategory=command.CATEGORY_REPO_CREATION,
1769 helpcategory=command.CATEGORY_REPO_CREATION,
1770 helpbasic=True,
1770 helpbasic=True,
1771 norepo=True,
1771 norepo=True,
1772 )
1772 )
1773 def clone(ui, source, dest=None, **opts):
1773 def clone(ui, source, dest=None, **opts):
1774 """make a copy of an existing repository
1774 """make a copy of an existing repository
1775
1775
1776 Create a copy of an existing repository in a new directory.
1776 Create a copy of an existing repository in a new directory.
1777
1777
1778 If no destination directory name is specified, it defaults to the
1778 If no destination directory name is specified, it defaults to the
1779 basename of the source.
1779 basename of the source.
1780
1780
1781 The location of the source is added to the new repository's
1781 The location of the source is added to the new repository's
1782 ``.hg/hgrc`` file, as the default to be used for future pulls.
1782 ``.hg/hgrc`` file, as the default to be used for future pulls.
1783
1783
1784 Only local paths and ``ssh://`` URLs are supported as
1784 Only local paths and ``ssh://`` URLs are supported as
1785 destinations. For ``ssh://`` destinations, no working directory or
1785 destinations. For ``ssh://`` destinations, no working directory or
1786 ``.hg/hgrc`` will be created on the remote side.
1786 ``.hg/hgrc`` will be created on the remote side.
1787
1787
1788 If the source repository has a bookmark called '@' set, that
1788 If the source repository has a bookmark called '@' set, that
1789 revision will be checked out in the new repository by default.
1789 revision will be checked out in the new repository by default.
1790
1790
1791 To check out a particular version, use -u/--update, or
1791 To check out a particular version, use -u/--update, or
1792 -U/--noupdate to create a clone with no working directory.
1792 -U/--noupdate to create a clone with no working directory.
1793
1793
1794 To pull only a subset of changesets, specify one or more revisions
1794 To pull only a subset of changesets, specify one or more revisions
1795 identifiers with -r/--rev or branches with -b/--branch. The
1795 identifiers with -r/--rev or branches with -b/--branch. The
1796 resulting clone will contain only the specified changesets and
1796 resulting clone will contain only the specified changesets and
1797 their ancestors. These options (or 'clone src#rev dest') imply
1797 their ancestors. These options (or 'clone src#rev dest') imply
1798 --pull, even for local source repositories.
1798 --pull, even for local source repositories.
1799
1799
1800 In normal clone mode, the remote normalizes repository data into a common
1800 In normal clone mode, the remote normalizes repository data into a common
1801 exchange format and the receiving end translates this data into its local
1801 exchange format and the receiving end translates this data into its local
1802 storage format. --stream activates a different clone mode that essentially
1802 storage format. --stream activates a different clone mode that essentially
1803 copies repository files from the remote with minimal data processing. This
1803 copies repository files from the remote with minimal data processing. This
1804 significantly reduces the CPU cost of a clone both remotely and locally.
1804 significantly reduces the CPU cost of a clone both remotely and locally.
1805 However, it often increases the transferred data size by 30-40%. This can
1805 However, it often increases the transferred data size by 30-40%. This can
1806 result in substantially faster clones where I/O throughput is plentiful,
1806 result in substantially faster clones where I/O throughput is plentiful,
1807 especially for larger repositories. A side-effect of --stream clones is
1807 especially for larger repositories. A side-effect of --stream clones is
1808 that storage settings and requirements on the remote are applied locally:
1808 that storage settings and requirements on the remote are applied locally:
1809 a modern client may inherit legacy or inefficient storage used by the
1809 a modern client may inherit legacy or inefficient storage used by the
1810 remote or a legacy Mercurial client may not be able to clone from a
1810 remote or a legacy Mercurial client may not be able to clone from a
1811 modern Mercurial remote.
1811 modern Mercurial remote.
1812
1812
1813 .. note::
1813 .. note::
1814
1814
1815 Specifying a tag will include the tagged changeset but not the
1815 Specifying a tag will include the tagged changeset but not the
1816 changeset containing the tag.
1816 changeset containing the tag.
1817
1817
1818 .. container:: verbose
1818 .. container:: verbose
1819
1819
1820 For efficiency, hardlinks are used for cloning whenever the
1820 For efficiency, hardlinks are used for cloning whenever the
1821 source and destination are on the same filesystem (note this
1821 source and destination are on the same filesystem (note this
1822 applies only to the repository data, not to the working
1822 applies only to the repository data, not to the working
1823 directory). Some filesystems, such as AFS, implement hardlinking
1823 directory). Some filesystems, such as AFS, implement hardlinking
1824 incorrectly, but do not report errors. In these cases, use the
1824 incorrectly, but do not report errors. In these cases, use the
1825 --pull option to avoid hardlinking.
1825 --pull option to avoid hardlinking.
1826
1826
1827 Mercurial will update the working directory to the first applicable
1827 Mercurial will update the working directory to the first applicable
1828 revision from this list:
1828 revision from this list:
1829
1829
1830 a) null if -U or the source repository has no changesets
1830 a) null if -U or the source repository has no changesets
1831 b) if -u . and the source repository is local, the first parent of
1831 b) if -u . and the source repository is local, the first parent of
1832 the source repository's working directory
1832 the source repository's working directory
1833 c) the changeset specified with -u (if a branch name, this means the
1833 c) the changeset specified with -u (if a branch name, this means the
1834 latest head of that branch)
1834 latest head of that branch)
1835 d) the changeset specified with -r
1835 d) the changeset specified with -r
1836 e) the tipmost head specified with -b
1836 e) the tipmost head specified with -b
1837 f) the tipmost head specified with the url#branch source syntax
1837 f) the tipmost head specified with the url#branch source syntax
1838 g) the revision marked with the '@' bookmark, if present
1838 g) the revision marked with the '@' bookmark, if present
1839 h) the tipmost head of the default branch
1839 h) the tipmost head of the default branch
1840 i) tip
1840 i) tip
1841
1841
1842 When cloning from servers that support it, Mercurial may fetch
1842 When cloning from servers that support it, Mercurial may fetch
1843 pre-generated data from a server-advertised URL or inline from the
1843 pre-generated data from a server-advertised URL or inline from the
1844 same stream. When this is done, hooks operating on incoming changesets
1844 same stream. When this is done, hooks operating on incoming changesets
1845 and changegroups may fire more than once, once for each pre-generated
1845 and changegroups may fire more than once, once for each pre-generated
1846 bundle and as well as for any additional remaining data. In addition,
1846 bundle and as well as for any additional remaining data. In addition,
1847 if an error occurs, the repository may be rolled back to a partial
1847 if an error occurs, the repository may be rolled back to a partial
1848 clone. This behavior may change in future releases.
1848 clone. This behavior may change in future releases.
1849 See :hg:`help -e clonebundles` for more.
1849 See :hg:`help -e clonebundles` for more.
1850
1850
1851 Examples:
1851 Examples:
1852
1852
1853 - clone a remote repository to a new directory named hg/::
1853 - clone a remote repository to a new directory named hg/::
1854
1854
1855 hg clone https://www.mercurial-scm.org/repo/hg/
1855 hg clone https://www.mercurial-scm.org/repo/hg/
1856
1856
1857 - create a lightweight local clone::
1857 - create a lightweight local clone::
1858
1858
1859 hg clone project/ project-feature/
1859 hg clone project/ project-feature/
1860
1860
1861 - clone from an absolute path on an ssh server (note double-slash)::
1861 - clone from an absolute path on an ssh server (note double-slash)::
1862
1862
1863 hg clone ssh://user@server//home/projects/alpha/
1863 hg clone ssh://user@server//home/projects/alpha/
1864
1864
1865 - do a streaming clone while checking out a specified version::
1865 - do a streaming clone while checking out a specified version::
1866
1866
1867 hg clone --stream http://server/repo -u 1.5
1867 hg clone --stream http://server/repo -u 1.5
1868
1868
1869 - create a repository without changesets after a particular revision::
1869 - create a repository without changesets after a particular revision::
1870
1870
1871 hg clone -r 04e544 experimental/ good/
1871 hg clone -r 04e544 experimental/ good/
1872
1872
1873 - clone (and track) a particular named branch::
1873 - clone (and track) a particular named branch::
1874
1874
1875 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1875 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1876
1876
1877 See :hg:`help urls` for details on specifying URLs.
1877 See :hg:`help urls` for details on specifying URLs.
1878
1878
1879 Returns 0 on success.
1879 Returns 0 on success.
1880 """
1880 """
1881 opts = pycompat.byteskwargs(opts)
1881 opts = pycompat.byteskwargs(opts)
1882 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1882 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1883
1883
1884 # --include/--exclude can come from narrow or sparse.
1884 # --include/--exclude can come from narrow or sparse.
1885 includepats, excludepats = None, None
1885 includepats, excludepats = None, None
1886
1886
1887 # hg.clone() differentiates between None and an empty set. So make sure
1887 # hg.clone() differentiates between None and an empty set. So make sure
1888 # patterns are sets if narrow is requested without patterns.
1888 # patterns are sets if narrow is requested without patterns.
1889 if opts.get(b'narrow'):
1889 if opts.get(b'narrow'):
1890 includepats = set()
1890 includepats = set()
1891 excludepats = set()
1891 excludepats = set()
1892
1892
1893 if opts.get(b'include'):
1893 if opts.get(b'include'):
1894 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1894 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1895 if opts.get(b'exclude'):
1895 if opts.get(b'exclude'):
1896 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1896 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1897
1897
1898 r = hg.clone(
1898 r = hg.clone(
1899 ui,
1899 ui,
1900 opts,
1900 opts,
1901 source,
1901 source,
1902 dest,
1902 dest,
1903 pull=opts.get(b'pull'),
1903 pull=opts.get(b'pull'),
1904 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1904 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1905 revs=opts.get(b'rev'),
1905 revs=opts.get(b'rev'),
1906 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1906 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1907 branch=opts.get(b'branch'),
1907 branch=opts.get(b'branch'),
1908 shareopts=opts.get(b'shareopts'),
1908 shareopts=opts.get(b'shareopts'),
1909 storeincludepats=includepats,
1909 storeincludepats=includepats,
1910 storeexcludepats=excludepats,
1910 storeexcludepats=excludepats,
1911 depth=opts.get(b'depth') or None,
1911 depth=opts.get(b'depth') or None,
1912 )
1912 )
1913
1913
1914 return r is None
1914 return r is None
1915
1915
1916
1916
1917 @command(
1917 @command(
1918 b'commit|ci',
1918 b'commit|ci',
1919 [
1919 [
1920 (
1920 (
1921 b'A',
1921 b'A',
1922 b'addremove',
1922 b'addremove',
1923 None,
1923 None,
1924 _(b'mark new/missing files as added/removed before committing'),
1924 _(b'mark new/missing files as added/removed before committing'),
1925 ),
1925 ),
1926 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1926 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1927 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1927 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1928 (b's', b'secret', None, _(b'use the secret phase for committing')),
1928 (b's', b'secret', None, _(b'use the secret phase for committing')),
1929 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1929 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1930 (
1930 (
1931 b'',
1931 b'',
1932 b'force-close-branch',
1932 b'force-close-branch',
1933 None,
1933 None,
1934 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1934 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1935 ),
1935 ),
1936 (b'i', b'interactive', None, _(b'use interactive mode')),
1936 (b'i', b'interactive', None, _(b'use interactive mode')),
1937 ]
1937 ]
1938 + walkopts
1938 + walkopts
1939 + commitopts
1939 + commitopts
1940 + commitopts2
1940 + commitopts2
1941 + subrepoopts,
1941 + subrepoopts,
1942 _(b'[OPTION]... [FILE]...'),
1942 _(b'[OPTION]... [FILE]...'),
1943 helpcategory=command.CATEGORY_COMMITTING,
1943 helpcategory=command.CATEGORY_COMMITTING,
1944 helpbasic=True,
1944 helpbasic=True,
1945 inferrepo=True,
1945 inferrepo=True,
1946 )
1946 )
1947 def commit(ui, repo, *pats, **opts):
1947 def commit(ui, repo, *pats, **opts):
1948 """commit the specified files or all outstanding changes
1948 """commit the specified files or all outstanding changes
1949
1949
1950 Commit changes to the given files into the repository. Unlike a
1950 Commit changes to the given files into the repository. Unlike a
1951 centralized SCM, this operation is a local operation. See
1951 centralized SCM, this operation is a local operation. See
1952 :hg:`push` for a way to actively distribute your changes.
1952 :hg:`push` for a way to actively distribute your changes.
1953
1953
1954 If a list of files is omitted, all changes reported by :hg:`status`
1954 If a list of files is omitted, all changes reported by :hg:`status`
1955 will be committed.
1955 will be committed.
1956
1956
1957 If you are committing the result of a merge, do not provide any
1957 If you are committing the result of a merge, do not provide any
1958 filenames or -I/-X filters.
1958 filenames or -I/-X filters.
1959
1959
1960 If no commit message is specified, Mercurial starts your
1960 If no commit message is specified, Mercurial starts your
1961 configured editor where you can enter a message. In case your
1961 configured editor where you can enter a message. In case your
1962 commit fails, you will find a backup of your message in
1962 commit fails, you will find a backup of your message in
1963 ``.hg/last-message.txt``.
1963 ``.hg/last-message.txt``.
1964
1964
1965 The --close-branch flag can be used to mark the current branch
1965 The --close-branch flag can be used to mark the current branch
1966 head closed. When all heads of a branch are closed, the branch
1966 head closed. When all heads of a branch are closed, the branch
1967 will be considered closed and no longer listed.
1967 will be considered closed and no longer listed.
1968
1968
1969 The --amend flag can be used to amend the parent of the
1969 The --amend flag can be used to amend the parent of the
1970 working directory with a new commit that contains the changes
1970 working directory with a new commit that contains the changes
1971 in the parent in addition to those currently reported by :hg:`status`,
1971 in the parent in addition to those currently reported by :hg:`status`,
1972 if there are any. The old commit is stored in a backup bundle in
1972 if there are any. The old commit is stored in a backup bundle in
1973 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1973 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1974 on how to restore it).
1974 on how to restore it).
1975
1975
1976 Message, user and date are taken from the amended commit unless
1976 Message, user and date are taken from the amended commit unless
1977 specified. When a message isn't specified on the command line,
1977 specified. When a message isn't specified on the command line,
1978 the editor will open with the message of the amended commit.
1978 the editor will open with the message of the amended commit.
1979
1979
1980 It is not possible to amend public changesets (see :hg:`help phases`)
1980 It is not possible to amend public changesets (see :hg:`help phases`)
1981 or changesets that have children.
1981 or changesets that have children.
1982
1982
1983 See :hg:`help dates` for a list of formats valid for -d/--date.
1983 See :hg:`help dates` for a list of formats valid for -d/--date.
1984
1984
1985 Returns 0 on success, 1 if nothing changed.
1985 Returns 0 on success, 1 if nothing changed.
1986
1986
1987 .. container:: verbose
1987 .. container:: verbose
1988
1988
1989 Examples:
1989 Examples:
1990
1990
1991 - commit all files ending in .py::
1991 - commit all files ending in .py::
1992
1992
1993 hg commit --include "set:**.py"
1993 hg commit --include "set:**.py"
1994
1994
1995 - commit all non-binary files::
1995 - commit all non-binary files::
1996
1996
1997 hg commit --exclude "set:binary()"
1997 hg commit --exclude "set:binary()"
1998
1998
1999 - amend the current commit and set the date to now::
1999 - amend the current commit and set the date to now::
2000
2000
2001 hg commit --amend --date now
2001 hg commit --amend --date now
2002 """
2002 """
2003 with repo.wlock(), repo.lock():
2003 with repo.wlock(), repo.lock():
2004 return _docommit(ui, repo, *pats, **opts)
2004 return _docommit(ui, repo, *pats, **opts)
2005
2005
2006
2006
2007 def _docommit(ui, repo, *pats, **opts):
2007 def _docommit(ui, repo, *pats, **opts):
2008 if opts.get('interactive'):
2008 if opts.get('interactive'):
2009 opts.pop('interactive')
2009 opts.pop('interactive')
2010 ret = cmdutil.dorecord(
2010 ret = cmdutil.dorecord(
2011 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2011 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2012 )
2012 )
2013 # ret can be 0 (no changes to record) or the value returned by
2013 # ret can be 0 (no changes to record) or the value returned by
2014 # commit(), 1 if nothing changed or None on success.
2014 # commit(), 1 if nothing changed or None on success.
2015 return 1 if ret == 0 else ret
2015 return 1 if ret == 0 else ret
2016
2016
2017 opts = pycompat.byteskwargs(opts)
2017 opts = pycompat.byteskwargs(opts)
2018 if opts.get(b'subrepos'):
2018 if opts.get(b'subrepos'):
2019 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'amend'])
2019 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'amend'])
2020 # Let --subrepos on the command line override config setting.
2020 # Let --subrepos on the command line override config setting.
2021 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2021 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2022
2022
2023 cmdutil.checkunfinished(repo, commit=True)
2023 cmdutil.checkunfinished(repo, commit=True)
2024
2024
2025 branch = repo[None].branch()
2025 branch = repo[None].branch()
2026 bheads = repo.branchheads(branch)
2026 bheads = repo.branchheads(branch)
2027
2027
2028 extra = {}
2028 extra = {}
2029 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2029 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2030 extra[b'close'] = b'1'
2030 extra[b'close'] = b'1'
2031
2031
2032 if repo[b'.'].closesbranch():
2032 if repo[b'.'].closesbranch():
2033 raise error.Abort(
2033 raise error.Abort(
2034 _(b'current revision is already a branch closing head')
2034 _(b'current revision is already a branch closing head')
2035 )
2035 )
2036 elif not bheads:
2036 elif not bheads:
2037 raise error.Abort(_(b'branch "%s" has no heads to close') % branch)
2037 raise error.Abort(_(b'branch "%s" has no heads to close') % branch)
2038 elif (
2038 elif (
2039 branch == repo[b'.'].branch()
2039 branch == repo[b'.'].branch()
2040 and repo[b'.'].node() not in bheads
2040 and repo[b'.'].node() not in bheads
2041 and not opts.get(b'force_close_branch')
2041 and not opts.get(b'force_close_branch')
2042 ):
2042 ):
2043 hint = _(
2043 hint = _(
2044 b'use --force-close-branch to close branch from a non-head'
2044 b'use --force-close-branch to close branch from a non-head'
2045 b' changeset'
2045 b' changeset'
2046 )
2046 )
2047 raise error.Abort(_(b'can only close branch heads'), hint=hint)
2047 raise error.Abort(_(b'can only close branch heads'), hint=hint)
2048 elif opts.get(b'amend'):
2048 elif opts.get(b'amend'):
2049 if (
2049 if (
2050 repo[b'.'].p1().branch() != branch
2050 repo[b'.'].p1().branch() != branch
2051 and repo[b'.'].p2().branch() != branch
2051 and repo[b'.'].p2().branch() != branch
2052 ):
2052 ):
2053 raise error.Abort(_(b'can only close branch heads'))
2053 raise error.Abort(_(b'can only close branch heads'))
2054
2054
2055 if opts.get(b'amend'):
2055 if opts.get(b'amend'):
2056 if ui.configbool(b'ui', b'commitsubrepos'):
2056 if ui.configbool(b'ui', b'commitsubrepos'):
2057 raise error.Abort(_(b'cannot amend with ui.commitsubrepos enabled'))
2057 raise error.Abort(_(b'cannot amend with ui.commitsubrepos enabled'))
2058
2058
2059 old = repo[b'.']
2059 old = repo[b'.']
2060 rewriteutil.precheck(repo, [old.rev()], b'amend')
2060 rewriteutil.precheck(repo, [old.rev()], b'amend')
2061
2061
2062 # Currently histedit gets confused if an amend happens while histedit
2062 # Currently histedit gets confused if an amend happens while histedit
2063 # is in progress. Since we have a checkunfinished command, we are
2063 # is in progress. Since we have a checkunfinished command, we are
2064 # temporarily honoring it.
2064 # temporarily honoring it.
2065 #
2065 #
2066 # Note: eventually this guard will be removed. Please do not expect
2066 # Note: eventually this guard will be removed. Please do not expect
2067 # this behavior to remain.
2067 # this behavior to remain.
2068 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2068 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2069 cmdutil.checkunfinished(repo)
2069 cmdutil.checkunfinished(repo)
2070
2070
2071 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2071 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2072 if node == old.node():
2072 if node == old.node():
2073 ui.status(_(b"nothing changed\n"))
2073 ui.status(_(b"nothing changed\n"))
2074 return 1
2074 return 1
2075 else:
2075 else:
2076
2076
2077 def commitfunc(ui, repo, message, match, opts):
2077 def commitfunc(ui, repo, message, match, opts):
2078 overrides = {}
2078 overrides = {}
2079 if opts.get(b'secret'):
2079 if opts.get(b'secret'):
2080 overrides[(b'phases', b'new-commit')] = b'secret'
2080 overrides[(b'phases', b'new-commit')] = b'secret'
2081
2081
2082 baseui = repo.baseui
2082 baseui = repo.baseui
2083 with baseui.configoverride(overrides, b'commit'):
2083 with baseui.configoverride(overrides, b'commit'):
2084 with ui.configoverride(overrides, b'commit'):
2084 with ui.configoverride(overrides, b'commit'):
2085 editform = cmdutil.mergeeditform(
2085 editform = cmdutil.mergeeditform(
2086 repo[None], b'commit.normal'
2086 repo[None], b'commit.normal'
2087 )
2087 )
2088 editor = cmdutil.getcommiteditor(
2088 editor = cmdutil.getcommiteditor(
2089 editform=editform, **pycompat.strkwargs(opts)
2089 editform=editform, **pycompat.strkwargs(opts)
2090 )
2090 )
2091 return repo.commit(
2091 return repo.commit(
2092 message,
2092 message,
2093 opts.get(b'user'),
2093 opts.get(b'user'),
2094 opts.get(b'date'),
2094 opts.get(b'date'),
2095 match,
2095 match,
2096 editor=editor,
2096 editor=editor,
2097 extra=extra,
2097 extra=extra,
2098 )
2098 )
2099
2099
2100 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2100 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2101
2101
2102 if not node:
2102 if not node:
2103 stat = cmdutil.postcommitstatus(repo, pats, opts)
2103 stat = cmdutil.postcommitstatus(repo, pats, opts)
2104 if stat.deleted:
2104 if stat.deleted:
2105 ui.status(
2105 ui.status(
2106 _(
2106 _(
2107 b"nothing changed (%d missing files, see "
2107 b"nothing changed (%d missing files, see "
2108 b"'hg status')\n"
2108 b"'hg status')\n"
2109 )
2109 )
2110 % len(stat.deleted)
2110 % len(stat.deleted)
2111 )
2111 )
2112 else:
2112 else:
2113 ui.status(_(b"nothing changed\n"))
2113 ui.status(_(b"nothing changed\n"))
2114 return 1
2114 return 1
2115
2115
2116 cmdutil.commitstatus(repo, node, branch, bheads, opts)
2116 cmdutil.commitstatus(repo, node, branch, bheads, opts)
2117
2117
2118 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2118 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2119 status(
2119 status(
2120 ui,
2120 ui,
2121 repo,
2121 repo,
2122 modified=True,
2122 modified=True,
2123 added=True,
2123 added=True,
2124 removed=True,
2124 removed=True,
2125 deleted=True,
2125 deleted=True,
2126 unknown=True,
2126 unknown=True,
2127 subrepos=opts.get(b'subrepos'),
2127 subrepos=opts.get(b'subrepos'),
2128 )
2128 )
2129
2129
2130
2130
2131 @command(
2131 @command(
2132 b'config|showconfig|debugconfig',
2132 b'config|showconfig|debugconfig',
2133 [
2133 [
2134 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2134 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2135 (b'e', b'edit', None, _(b'edit user config')),
2135 (b'e', b'edit', None, _(b'edit user config')),
2136 (b'l', b'local', None, _(b'edit repository config')),
2136 (b'l', b'local', None, _(b'edit repository config')),
2137 (
2137 (
2138 b'',
2138 b'',
2139 b'shared',
2139 b'shared',
2140 None,
2140 None,
2141 _(b'edit shared source repository config (EXPERIMENTAL)'),
2141 _(b'edit shared source repository config (EXPERIMENTAL)'),
2142 ),
2142 ),
2143 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2143 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2144 (b'g', b'global', None, _(b'edit global config')),
2144 (b'g', b'global', None, _(b'edit global config')),
2145 ]
2145 ]
2146 + formatteropts,
2146 + formatteropts,
2147 _(b'[-u] [NAME]...'),
2147 _(b'[-u] [NAME]...'),
2148 helpcategory=command.CATEGORY_HELP,
2148 helpcategory=command.CATEGORY_HELP,
2149 optionalrepo=True,
2149 optionalrepo=True,
2150 intents={INTENT_READONLY},
2150 intents={INTENT_READONLY},
2151 )
2151 )
2152 def config(ui, repo, *values, **opts):
2152 def config(ui, repo, *values, **opts):
2153 """show combined config settings from all hgrc files
2153 """show combined config settings from all hgrc files
2154
2154
2155 With no arguments, print names and values of all config items.
2155 With no arguments, print names and values of all config items.
2156
2156
2157 With one argument of the form section.name, print just the value
2157 With one argument of the form section.name, print just the value
2158 of that config item.
2158 of that config item.
2159
2159
2160 With multiple arguments, print names and values of all config
2160 With multiple arguments, print names and values of all config
2161 items with matching section names or section.names.
2161 items with matching section names or section.names.
2162
2162
2163 With --edit, start an editor on the user-level config file. With
2163 With --edit, start an editor on the user-level config file. With
2164 --global, edit the system-wide config file. With --local, edit the
2164 --global, edit the system-wide config file. With --local, edit the
2165 repository-level config file.
2165 repository-level config file.
2166
2166
2167 With --debug, the source (filename and line number) is printed
2167 With --debug, the source (filename and line number) is printed
2168 for each config item.
2168 for each config item.
2169
2169
2170 See :hg:`help config` for more information about config files.
2170 See :hg:`help config` for more information about config files.
2171
2171
2172 .. container:: verbose
2172 .. container:: verbose
2173
2173
2174 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2174 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2175 This file is not shared across shares when in share-safe mode.
2175 This file is not shared across shares when in share-safe mode.
2176
2176
2177 Template:
2177 Template:
2178
2178
2179 The following keywords are supported. See also :hg:`help templates`.
2179 The following keywords are supported. See also :hg:`help templates`.
2180
2180
2181 :name: String. Config name.
2181 :name: String. Config name.
2182 :source: String. Filename and line number where the item is defined.
2182 :source: String. Filename and line number where the item is defined.
2183 :value: String. Config value.
2183 :value: String. Config value.
2184
2184
2185 The --shared flag can be used to edit the config file of shared source
2185 The --shared flag can be used to edit the config file of shared source
2186 repository. It only works when you have shared using the experimental
2186 repository. It only works when you have shared using the experimental
2187 share safe feature.
2187 share safe feature.
2188
2188
2189 Returns 0 on success, 1 if NAME does not exist.
2189 Returns 0 on success, 1 if NAME does not exist.
2190
2190
2191 """
2191 """
2192
2192
2193 opts = pycompat.byteskwargs(opts)
2193 opts = pycompat.byteskwargs(opts)
2194 editopts = (b'edit', b'local', b'global', b'shared', b'non_shared')
2194 editopts = (b'edit', b'local', b'global', b'shared', b'non_shared')
2195 if any(opts.get(o) for o in editopts):
2195 if any(opts.get(o) for o in editopts):
2196 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2196 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2197 if opts.get(b'local'):
2197 if opts.get(b'local'):
2198 if not repo:
2198 if not repo:
2199 raise error.Abort(_(b"can't use --local outside a repository"))
2199 raise error.Abort(_(b"can't use --local outside a repository"))
2200 paths = [repo.vfs.join(b'hgrc')]
2200 paths = [repo.vfs.join(b'hgrc')]
2201 elif opts.get(b'global'):
2201 elif opts.get(b'global'):
2202 paths = rcutil.systemrcpath()
2202 paths = rcutil.systemrcpath()
2203 elif opts.get(b'shared'):
2203 elif opts.get(b'shared'):
2204 if not repo.shared():
2204 if not repo.shared():
2205 raise error.Abort(
2205 raise error.Abort(
2206 _(b"repository is not shared; can't use --shared")
2206 _(b"repository is not shared; can't use --shared")
2207 )
2207 )
2208 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2208 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2209 raise error.Abort(
2209 raise error.Abort(
2210 _(
2210 _(
2211 b"share safe feature not unabled; "
2211 b"share safe feature not unabled; "
2212 b"unable to edit shared source repository config"
2212 b"unable to edit shared source repository config"
2213 )
2213 )
2214 )
2214 )
2215 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2215 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2216 elif opts.get(b'non_shared'):
2216 elif opts.get(b'non_shared'):
2217 paths = [repo.vfs.join(b'hgrc-not-shared')]
2217 paths = [repo.vfs.join(b'hgrc-not-shared')]
2218 else:
2218 else:
2219 paths = rcutil.userrcpath()
2219 paths = rcutil.userrcpath()
2220
2220
2221 for f in paths:
2221 for f in paths:
2222 if os.path.exists(f):
2222 if os.path.exists(f):
2223 break
2223 break
2224 else:
2224 else:
2225 if opts.get(b'global'):
2225 if opts.get(b'global'):
2226 samplehgrc = uimod.samplehgrcs[b'global']
2226 samplehgrc = uimod.samplehgrcs[b'global']
2227 elif opts.get(b'local'):
2227 elif opts.get(b'local'):
2228 samplehgrc = uimod.samplehgrcs[b'local']
2228 samplehgrc = uimod.samplehgrcs[b'local']
2229 else:
2229 else:
2230 samplehgrc = uimod.samplehgrcs[b'user']
2230 samplehgrc = uimod.samplehgrcs[b'user']
2231
2231
2232 f = paths[0]
2232 f = paths[0]
2233 fp = open(f, b"wb")
2233 fp = open(f, b"wb")
2234 fp.write(util.tonativeeol(samplehgrc))
2234 fp.write(util.tonativeeol(samplehgrc))
2235 fp.close()
2235 fp.close()
2236
2236
2237 editor = ui.geteditor()
2237 editor = ui.geteditor()
2238 ui.system(
2238 ui.system(
2239 b"%s \"%s\"" % (editor, f),
2239 b"%s \"%s\"" % (editor, f),
2240 onerr=error.Abort,
2240 onerr=error.Abort,
2241 errprefix=_(b"edit failed"),
2241 errprefix=_(b"edit failed"),
2242 blockedtag=b'config_edit',
2242 blockedtag=b'config_edit',
2243 )
2243 )
2244 return
2244 return
2245 ui.pager(b'config')
2245 ui.pager(b'config')
2246 fm = ui.formatter(b'config', opts)
2246 fm = ui.formatter(b'config', opts)
2247 for t, f in rcutil.rccomponents():
2247 for t, f in rcutil.rccomponents():
2248 if t == b'path':
2248 if t == b'path':
2249 ui.debug(b'read config from: %s\n' % f)
2249 ui.debug(b'read config from: %s\n' % f)
2250 elif t == b'resource':
2250 elif t == b'resource':
2251 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2251 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2252 elif t == b'items':
2252 elif t == b'items':
2253 # Don't print anything for 'items'.
2253 # Don't print anything for 'items'.
2254 pass
2254 pass
2255 else:
2255 else:
2256 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2256 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2257 untrusted = bool(opts.get(b'untrusted'))
2257 untrusted = bool(opts.get(b'untrusted'))
2258
2258
2259 selsections = selentries = []
2259 selsections = selentries = []
2260 if values:
2260 if values:
2261 selsections = [v for v in values if b'.' not in v]
2261 selsections = [v for v in values if b'.' not in v]
2262 selentries = [v for v in values if b'.' in v]
2262 selentries = [v for v in values if b'.' in v]
2263 uniquesel = len(selentries) == 1 and not selsections
2263 uniquesel = len(selentries) == 1 and not selsections
2264 selsections = set(selsections)
2264 selsections = set(selsections)
2265 selentries = set(selentries)
2265 selentries = set(selentries)
2266
2266
2267 matched = False
2267 matched = False
2268 for section, name, value in ui.walkconfig(untrusted=untrusted):
2268 for section, name, value in ui.walkconfig(untrusted=untrusted):
2269 source = ui.configsource(section, name, untrusted)
2269 source = ui.configsource(section, name, untrusted)
2270 value = pycompat.bytestr(value)
2270 value = pycompat.bytestr(value)
2271 defaultvalue = ui.configdefault(section, name)
2271 defaultvalue = ui.configdefault(section, name)
2272 if fm.isplain():
2272 if fm.isplain():
2273 source = source or b'none'
2273 source = source or b'none'
2274 value = value.replace(b'\n', b'\\n')
2274 value = value.replace(b'\n', b'\\n')
2275 entryname = section + b'.' + name
2275 entryname = section + b'.' + name
2276 if values and not (section in selsections or entryname in selentries):
2276 if values and not (section in selsections or entryname in selentries):
2277 continue
2277 continue
2278 fm.startitem()
2278 fm.startitem()
2279 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2279 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2280 if uniquesel:
2280 if uniquesel:
2281 fm.data(name=entryname)
2281 fm.data(name=entryname)
2282 fm.write(b'value', b'%s\n', value)
2282 fm.write(b'value', b'%s\n', value)
2283 else:
2283 else:
2284 fm.write(b'name value', b'%s=%s\n', entryname, value)
2284 fm.write(b'name value', b'%s=%s\n', entryname, value)
2285 if formatter.isprintable(defaultvalue):
2285 if formatter.isprintable(defaultvalue):
2286 fm.data(defaultvalue=defaultvalue)
2286 fm.data(defaultvalue=defaultvalue)
2287 elif isinstance(defaultvalue, list) and all(
2287 elif isinstance(defaultvalue, list) and all(
2288 formatter.isprintable(e) for e in defaultvalue
2288 formatter.isprintable(e) for e in defaultvalue
2289 ):
2289 ):
2290 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2290 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2291 # TODO: no idea how to process unsupported defaultvalue types
2291 # TODO: no idea how to process unsupported defaultvalue types
2292 matched = True
2292 matched = True
2293 fm.end()
2293 fm.end()
2294 if matched:
2294 if matched:
2295 return 0
2295 return 0
2296 return 1
2296 return 1
2297
2297
2298
2298
2299 @command(
2299 @command(
2300 b'continue',
2300 b'continue',
2301 dryrunopts,
2301 dryrunopts,
2302 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2302 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2303 helpbasic=True,
2303 helpbasic=True,
2304 )
2304 )
2305 def continuecmd(ui, repo, **opts):
2305 def continuecmd(ui, repo, **opts):
2306 """resumes an interrupted operation (EXPERIMENTAL)
2306 """resumes an interrupted operation (EXPERIMENTAL)
2307
2307
2308 Finishes a multistep operation like graft, histedit, rebase, merge,
2308 Finishes a multistep operation like graft, histedit, rebase, merge,
2309 and unshelve if they are in an interrupted state.
2309 and unshelve if they are in an interrupted state.
2310
2310
2311 use --dry-run/-n to dry run the command.
2311 use --dry-run/-n to dry run the command.
2312 """
2312 """
2313 dryrun = opts.get('dry_run')
2313 dryrun = opts.get('dry_run')
2314 contstate = cmdutil.getunfinishedstate(repo)
2314 contstate = cmdutil.getunfinishedstate(repo)
2315 if not contstate:
2315 if not contstate:
2316 raise error.Abort(_(b'no operation in progress'))
2316 raise error.Abort(_(b'no operation in progress'))
2317 if not contstate.continuefunc:
2317 if not contstate.continuefunc:
2318 raise error.Abort(
2318 raise error.Abort(
2319 (
2319 (
2320 _(b"%s in progress but does not support 'hg continue'")
2320 _(b"%s in progress but does not support 'hg continue'")
2321 % (contstate._opname)
2321 % (contstate._opname)
2322 ),
2322 ),
2323 hint=contstate.continuemsg(),
2323 hint=contstate.continuemsg(),
2324 )
2324 )
2325 if dryrun:
2325 if dryrun:
2326 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2326 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2327 return
2327 return
2328 return contstate.continuefunc(ui, repo)
2328 return contstate.continuefunc(ui, repo)
2329
2329
2330
2330
2331 @command(
2331 @command(
2332 b'copy|cp',
2332 b'copy|cp',
2333 [
2333 [
2334 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2334 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2335 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2335 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2336 (
2336 (
2337 b'',
2337 b'',
2338 b'at-rev',
2338 b'at-rev',
2339 b'',
2339 b'',
2340 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2340 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2341 _(b'REV'),
2341 _(b'REV'),
2342 ),
2342 ),
2343 (
2343 (
2344 b'f',
2344 b'f',
2345 b'force',
2345 b'force',
2346 None,
2346 None,
2347 _(b'forcibly copy over an existing managed file'),
2347 _(b'forcibly copy over an existing managed file'),
2348 ),
2348 ),
2349 ]
2349 ]
2350 + walkopts
2350 + walkopts
2351 + dryrunopts,
2351 + dryrunopts,
2352 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2352 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2353 helpcategory=command.CATEGORY_FILE_CONTENTS,
2353 helpcategory=command.CATEGORY_FILE_CONTENTS,
2354 )
2354 )
2355 def copy(ui, repo, *pats, **opts):
2355 def copy(ui, repo, *pats, **opts):
2356 """mark files as copied for the next commit
2356 """mark files as copied for the next commit
2357
2357
2358 Mark dest as having copies of source files. If dest is a
2358 Mark dest as having copies of source files. If dest is a
2359 directory, copies are put in that directory. If dest is a file,
2359 directory, copies are put in that directory. If dest is a file,
2360 the source must be a single file.
2360 the source must be a single file.
2361
2361
2362 By default, this command copies the contents of files as they
2362 By default, this command copies the contents of files as they
2363 exist in the working directory. If invoked with -A/--after, the
2363 exist in the working directory. If invoked with -A/--after, the
2364 operation is recorded, but no copying is performed.
2364 operation is recorded, but no copying is performed.
2365
2365
2366 To undo marking a destination file as copied, use --forget. With that
2366 To undo marking a destination file as copied, use --forget. With that
2367 option, all given (positional) arguments are unmarked as copies. The
2367 option, all given (positional) arguments are unmarked as copies. The
2368 destination file(s) will be left in place (still tracked).
2368 destination file(s) will be left in place (still tracked).
2369
2369
2370 This command takes effect with the next commit by default.
2370 This command takes effect with the next commit by default.
2371
2371
2372 Returns 0 on success, 1 if errors are encountered.
2372 Returns 0 on success, 1 if errors are encountered.
2373 """
2373 """
2374 opts = pycompat.byteskwargs(opts)
2374 opts = pycompat.byteskwargs(opts)
2375 with repo.wlock():
2375 with repo.wlock():
2376 return cmdutil.copy(ui, repo, pats, opts)
2376 return cmdutil.copy(ui, repo, pats, opts)
2377
2377
2378
2378
2379 @command(
2379 @command(
2380 b'debugcommands',
2380 b'debugcommands',
2381 [],
2381 [],
2382 _(b'[COMMAND]'),
2382 _(b'[COMMAND]'),
2383 helpcategory=command.CATEGORY_HELP,
2383 helpcategory=command.CATEGORY_HELP,
2384 norepo=True,
2384 norepo=True,
2385 )
2385 )
2386 def debugcommands(ui, cmd=b'', *args):
2386 def debugcommands(ui, cmd=b'', *args):
2387 """list all available commands and options"""
2387 """list all available commands and options"""
2388 for cmd, vals in sorted(pycompat.iteritems(table)):
2388 for cmd, vals in sorted(pycompat.iteritems(table)):
2389 cmd = cmd.split(b'|')[0]
2389 cmd = cmd.split(b'|')[0]
2390 opts = b', '.join([i[1] for i in vals[1]])
2390 opts = b', '.join([i[1] for i in vals[1]])
2391 ui.write(b'%s: %s\n' % (cmd, opts))
2391 ui.write(b'%s: %s\n' % (cmd, opts))
2392
2392
2393
2393
2394 @command(
2394 @command(
2395 b'debugcomplete',
2395 b'debugcomplete',
2396 [(b'o', b'options', None, _(b'show the command options'))],
2396 [(b'o', b'options', None, _(b'show the command options'))],
2397 _(b'[-o] CMD'),
2397 _(b'[-o] CMD'),
2398 helpcategory=command.CATEGORY_HELP,
2398 helpcategory=command.CATEGORY_HELP,
2399 norepo=True,
2399 norepo=True,
2400 )
2400 )
2401 def debugcomplete(ui, cmd=b'', **opts):
2401 def debugcomplete(ui, cmd=b'', **opts):
2402 """returns the completion list associated with the given command"""
2402 """returns the completion list associated with the given command"""
2403
2403
2404 if opts.get('options'):
2404 if opts.get('options'):
2405 options = []
2405 options = []
2406 otables = [globalopts]
2406 otables = [globalopts]
2407 if cmd:
2407 if cmd:
2408 aliases, entry = cmdutil.findcmd(cmd, table, False)
2408 aliases, entry = cmdutil.findcmd(cmd, table, False)
2409 otables.append(entry[1])
2409 otables.append(entry[1])
2410 for t in otables:
2410 for t in otables:
2411 for o in t:
2411 for o in t:
2412 if b"(DEPRECATED)" in o[3]:
2412 if b"(DEPRECATED)" in o[3]:
2413 continue
2413 continue
2414 if o[0]:
2414 if o[0]:
2415 options.append(b'-%s' % o[0])
2415 options.append(b'-%s' % o[0])
2416 options.append(b'--%s' % o[1])
2416 options.append(b'--%s' % o[1])
2417 ui.write(b"%s\n" % b"\n".join(options))
2417 ui.write(b"%s\n" % b"\n".join(options))
2418 return
2418 return
2419
2419
2420 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2420 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2421 if ui.verbose:
2421 if ui.verbose:
2422 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2422 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2423 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2423 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2424
2424
2425
2425
2426 @command(
2426 @command(
2427 b'diff',
2427 b'diff',
2428 [
2428 [
2429 (b'r', b'rev', [], _(b'revision'), _(b'REV')),
2429 (b'r', b'rev', [], _(b'revision'), _(b'REV')),
2430 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2430 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2431 ]
2431 ]
2432 + diffopts
2432 + diffopts
2433 + diffopts2
2433 + diffopts2
2434 + walkopts
2434 + walkopts
2435 + subrepoopts,
2435 + subrepoopts,
2436 _(b'[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2436 _(b'[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2437 helpcategory=command.CATEGORY_FILE_CONTENTS,
2437 helpcategory=command.CATEGORY_FILE_CONTENTS,
2438 helpbasic=True,
2438 helpbasic=True,
2439 inferrepo=True,
2439 inferrepo=True,
2440 intents={INTENT_READONLY},
2440 intents={INTENT_READONLY},
2441 )
2441 )
2442 def diff(ui, repo, *pats, **opts):
2442 def diff(ui, repo, *pats, **opts):
2443 """diff repository (or selected files)
2443 """diff repository (or selected files)
2444
2444
2445 Show differences between revisions for the specified files.
2445 Show differences between revisions for the specified files.
2446
2446
2447 Differences between files are shown using the unified diff format.
2447 Differences between files are shown using the unified diff format.
2448
2448
2449 .. note::
2449 .. note::
2450
2450
2451 :hg:`diff` may generate unexpected results for merges, as it will
2451 :hg:`diff` may generate unexpected results for merges, as it will
2452 default to comparing against the working directory's first
2452 default to comparing against the working directory's first
2453 parent changeset if no revisions are specified.
2453 parent changeset if no revisions are specified.
2454
2454
2455 When two revision arguments are given, then changes are shown
2455 When two revision arguments are given, then changes are shown
2456 between those revisions. If only one revision is specified then
2456 between those revisions. If only one revision is specified then
2457 that revision is compared to the working directory, and, when no
2457 that revision is compared to the working directory, and, when no
2458 revisions are specified, the working directory files are compared
2458 revisions are specified, the working directory files are compared
2459 to its first parent.
2459 to its first parent.
2460
2460
2461 Alternatively you can specify -c/--change with a revision to see
2461 Alternatively you can specify -c/--change with a revision to see
2462 the changes in that changeset relative to its first parent.
2462 the changes in that changeset relative to its first parent.
2463
2463
2464 Without the -a/--text option, diff will avoid generating diffs of
2464 Without the -a/--text option, diff will avoid generating diffs of
2465 files it detects as binary. With -a, diff will generate a diff
2465 files it detects as binary. With -a, diff will generate a diff
2466 anyway, probably with undesirable results.
2466 anyway, probably with undesirable results.
2467
2467
2468 Use the -g/--git option to generate diffs in the git extended diff
2468 Use the -g/--git option to generate diffs in the git extended diff
2469 format. For more information, read :hg:`help diffs`.
2469 format. For more information, read :hg:`help diffs`.
2470
2470
2471 .. container:: verbose
2471 .. container:: verbose
2472
2472
2473 Examples:
2473 Examples:
2474
2474
2475 - compare a file in the current working directory to its parent::
2475 - compare a file in the current working directory to its parent::
2476
2476
2477 hg diff foo.c
2477 hg diff foo.c
2478
2478
2479 - compare two historical versions of a directory, with rename info::
2479 - compare two historical versions of a directory, with rename info::
2480
2480
2481 hg diff --git -r 1.0:1.2 lib/
2481 hg diff --git -r 1.0:1.2 lib/
2482
2482
2483 - get change stats relative to the last change on some date::
2483 - get change stats relative to the last change on some date::
2484
2484
2485 hg diff --stat -r "date('may 2')"
2485 hg diff --stat -r "date('may 2')"
2486
2486
2487 - diff all newly-added files that contain a keyword::
2487 - diff all newly-added files that contain a keyword::
2488
2488
2489 hg diff "set:added() and grep(GNU)"
2489 hg diff "set:added() and grep(GNU)"
2490
2490
2491 - compare a revision and its parents::
2491 - compare a revision and its parents::
2492
2492
2493 hg diff -c 9353 # compare against first parent
2493 hg diff -c 9353 # compare against first parent
2494 hg diff -r 9353^:9353 # same using revset syntax
2494 hg diff -r 9353^:9353 # same using revset syntax
2495 hg diff -r 9353^2:9353 # compare against the second parent
2495 hg diff -r 9353^2:9353 # compare against the second parent
2496
2496
2497 Returns 0 on success.
2497 Returns 0 on success.
2498 """
2498 """
2499
2499
2500 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2500 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2501 opts = pycompat.byteskwargs(opts)
2501 opts = pycompat.byteskwargs(opts)
2502 revs = opts.get(b'rev')
2502 revs = opts.get(b'rev')
2503 change = opts.get(b'change')
2503 change = opts.get(b'change')
2504 stat = opts.get(b'stat')
2504 stat = opts.get(b'stat')
2505 reverse = opts.get(b'reverse')
2505 reverse = opts.get(b'reverse')
2506
2506
2507 if change:
2507 if change:
2508 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2508 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2509 ctx2 = scmutil.revsingle(repo, change, None)
2509 ctx2 = scmutil.revsingle(repo, change, None)
2510 ctx1 = ctx2.p1()
2510 ctx1 = ctx2.p1()
2511 else:
2511 else:
2512 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2512 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2513 ctx1, ctx2 = scmutil.revpair(repo, revs)
2513 ctx1, ctx2 = scmutil.revpair(repo, revs)
2514
2514
2515 if reverse:
2515 if reverse:
2516 ctxleft = ctx2
2516 ctxleft = ctx2
2517 ctxright = ctx1
2517 ctxright = ctx1
2518 else:
2518 else:
2519 ctxleft = ctx1
2519 ctxleft = ctx1
2520 ctxright = ctx2
2520 ctxright = ctx2
2521
2521
2522 diffopts = patch.diffallopts(ui, opts)
2522 diffopts = patch.diffallopts(ui, opts)
2523 m = scmutil.match(ctx2, pats, opts)
2523 m = scmutil.match(ctx2, pats, opts)
2524 m = repo.narrowmatch(m)
2524 m = repo.narrowmatch(m)
2525 ui.pager(b'diff')
2525 ui.pager(b'diff')
2526 logcmdutil.diffordiffstat(
2526 logcmdutil.diffordiffstat(
2527 ui,
2527 ui,
2528 repo,
2528 repo,
2529 diffopts,
2529 diffopts,
2530 ctxleft,
2530 ctxleft,
2531 ctxright,
2531 ctxright,
2532 m,
2532 m,
2533 stat=stat,
2533 stat=stat,
2534 listsubrepos=opts.get(b'subrepos'),
2534 listsubrepos=opts.get(b'subrepos'),
2535 root=opts.get(b'root'),
2535 root=opts.get(b'root'),
2536 )
2536 )
2537
2537
2538
2538
2539 @command(
2539 @command(
2540 b'export',
2540 b'export',
2541 [
2541 [
2542 (
2542 (
2543 b'B',
2543 b'B',
2544 b'bookmark',
2544 b'bookmark',
2545 b'',
2545 b'',
2546 _(b'export changes only reachable by given bookmark'),
2546 _(b'export changes only reachable by given bookmark'),
2547 _(b'BOOKMARK'),
2547 _(b'BOOKMARK'),
2548 ),
2548 ),
2549 (
2549 (
2550 b'o',
2550 b'o',
2551 b'output',
2551 b'output',
2552 b'',
2552 b'',
2553 _(b'print output to file with formatted name'),
2553 _(b'print output to file with formatted name'),
2554 _(b'FORMAT'),
2554 _(b'FORMAT'),
2555 ),
2555 ),
2556 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2556 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2557 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2557 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2558 ]
2558 ]
2559 + diffopts
2559 + diffopts
2560 + formatteropts,
2560 + formatteropts,
2561 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2561 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2562 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2562 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2563 helpbasic=True,
2563 helpbasic=True,
2564 intents={INTENT_READONLY},
2564 intents={INTENT_READONLY},
2565 )
2565 )
2566 def export(ui, repo, *changesets, **opts):
2566 def export(ui, repo, *changesets, **opts):
2567 """dump the header and diffs for one or more changesets
2567 """dump the header and diffs for one or more changesets
2568
2568
2569 Print the changeset header and diffs for one or more revisions.
2569 Print the changeset header and diffs for one or more revisions.
2570 If no revision is given, the parent of the working directory is used.
2570 If no revision is given, the parent of the working directory is used.
2571
2571
2572 The information shown in the changeset header is: author, date,
2572 The information shown in the changeset header is: author, date,
2573 branch name (if non-default), changeset hash, parent(s) and commit
2573 branch name (if non-default), changeset hash, parent(s) and commit
2574 comment.
2574 comment.
2575
2575
2576 .. note::
2576 .. note::
2577
2577
2578 :hg:`export` may generate unexpected diff output for merge
2578 :hg:`export` may generate unexpected diff output for merge
2579 changesets, as it will compare the merge changeset against its
2579 changesets, as it will compare the merge changeset against its
2580 first parent only.
2580 first parent only.
2581
2581
2582 Output may be to a file, in which case the name of the file is
2582 Output may be to a file, in which case the name of the file is
2583 given using a template string. See :hg:`help templates`. In addition
2583 given using a template string. See :hg:`help templates`. In addition
2584 to the common template keywords, the following formatting rules are
2584 to the common template keywords, the following formatting rules are
2585 supported:
2585 supported:
2586
2586
2587 :``%%``: literal "%" character
2587 :``%%``: literal "%" character
2588 :``%H``: changeset hash (40 hexadecimal digits)
2588 :``%H``: changeset hash (40 hexadecimal digits)
2589 :``%N``: number of patches being generated
2589 :``%N``: number of patches being generated
2590 :``%R``: changeset revision number
2590 :``%R``: changeset revision number
2591 :``%b``: basename of the exporting repository
2591 :``%b``: basename of the exporting repository
2592 :``%h``: short-form changeset hash (12 hexadecimal digits)
2592 :``%h``: short-form changeset hash (12 hexadecimal digits)
2593 :``%m``: first line of the commit message (only alphanumeric characters)
2593 :``%m``: first line of the commit message (only alphanumeric characters)
2594 :``%n``: zero-padded sequence number, starting at 1
2594 :``%n``: zero-padded sequence number, starting at 1
2595 :``%r``: zero-padded changeset revision number
2595 :``%r``: zero-padded changeset revision number
2596 :``\\``: literal "\\" character
2596 :``\\``: literal "\\" character
2597
2597
2598 Without the -a/--text option, export will avoid generating diffs
2598 Without the -a/--text option, export will avoid generating diffs
2599 of files it detects as binary. With -a, export will generate a
2599 of files it detects as binary. With -a, export will generate a
2600 diff anyway, probably with undesirable results.
2600 diff anyway, probably with undesirable results.
2601
2601
2602 With -B/--bookmark changesets reachable by the given bookmark are
2602 With -B/--bookmark changesets reachable by the given bookmark are
2603 selected.
2603 selected.
2604
2604
2605 Use the -g/--git option to generate diffs in the git extended diff
2605 Use the -g/--git option to generate diffs in the git extended diff
2606 format. See :hg:`help diffs` for more information.
2606 format. See :hg:`help diffs` for more information.
2607
2607
2608 With the --switch-parent option, the diff will be against the
2608 With the --switch-parent option, the diff will be against the
2609 second parent. It can be useful to review a merge.
2609 second parent. It can be useful to review a merge.
2610
2610
2611 .. container:: verbose
2611 .. container:: verbose
2612
2612
2613 Template:
2613 Template:
2614
2614
2615 The following keywords are supported in addition to the common template
2615 The following keywords are supported in addition to the common template
2616 keywords and functions. See also :hg:`help templates`.
2616 keywords and functions. See also :hg:`help templates`.
2617
2617
2618 :diff: String. Diff content.
2618 :diff: String. Diff content.
2619 :parents: List of strings. Parent nodes of the changeset.
2619 :parents: List of strings. Parent nodes of the changeset.
2620
2620
2621 Examples:
2621 Examples:
2622
2622
2623 - use export and import to transplant a bugfix to the current
2623 - use export and import to transplant a bugfix to the current
2624 branch::
2624 branch::
2625
2625
2626 hg export -r 9353 | hg import -
2626 hg export -r 9353 | hg import -
2627
2627
2628 - export all the changesets between two revisions to a file with
2628 - export all the changesets between two revisions to a file with
2629 rename information::
2629 rename information::
2630
2630
2631 hg export --git -r 123:150 > changes.txt
2631 hg export --git -r 123:150 > changes.txt
2632
2632
2633 - split outgoing changes into a series of patches with
2633 - split outgoing changes into a series of patches with
2634 descriptive names::
2634 descriptive names::
2635
2635
2636 hg export -r "outgoing()" -o "%n-%m.patch"
2636 hg export -r "outgoing()" -o "%n-%m.patch"
2637
2637
2638 Returns 0 on success.
2638 Returns 0 on success.
2639 """
2639 """
2640 opts = pycompat.byteskwargs(opts)
2640 opts = pycompat.byteskwargs(opts)
2641 bookmark = opts.get(b'bookmark')
2641 bookmark = opts.get(b'bookmark')
2642 changesets += tuple(opts.get(b'rev', []))
2642 changesets += tuple(opts.get(b'rev', []))
2643
2643
2644 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2644 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2645
2645
2646 if bookmark:
2646 if bookmark:
2647 if bookmark not in repo._bookmarks:
2647 if bookmark not in repo._bookmarks:
2648 raise error.Abort(_(b"bookmark '%s' not found") % bookmark)
2648 raise error.Abort(_(b"bookmark '%s' not found") % bookmark)
2649
2649
2650 revs = scmutil.bookmarkrevs(repo, bookmark)
2650 revs = scmutil.bookmarkrevs(repo, bookmark)
2651 else:
2651 else:
2652 if not changesets:
2652 if not changesets:
2653 changesets = [b'.']
2653 changesets = [b'.']
2654
2654
2655 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2655 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2656 revs = scmutil.revrange(repo, changesets)
2656 revs = scmutil.revrange(repo, changesets)
2657
2657
2658 if not revs:
2658 if not revs:
2659 raise error.Abort(_(b"export requires at least one changeset"))
2659 raise error.Abort(_(b"export requires at least one changeset"))
2660 if len(revs) > 1:
2660 if len(revs) > 1:
2661 ui.note(_(b'exporting patches:\n'))
2661 ui.note(_(b'exporting patches:\n'))
2662 else:
2662 else:
2663 ui.note(_(b'exporting patch:\n'))
2663 ui.note(_(b'exporting patch:\n'))
2664
2664
2665 fntemplate = opts.get(b'output')
2665 fntemplate = opts.get(b'output')
2666 if cmdutil.isstdiofilename(fntemplate):
2666 if cmdutil.isstdiofilename(fntemplate):
2667 fntemplate = b''
2667 fntemplate = b''
2668
2668
2669 if fntemplate:
2669 if fntemplate:
2670 fm = formatter.nullformatter(ui, b'export', opts)
2670 fm = formatter.nullformatter(ui, b'export', opts)
2671 else:
2671 else:
2672 ui.pager(b'export')
2672 ui.pager(b'export')
2673 fm = ui.formatter(b'export', opts)
2673 fm = ui.formatter(b'export', opts)
2674 with fm:
2674 with fm:
2675 cmdutil.export(
2675 cmdutil.export(
2676 repo,
2676 repo,
2677 revs,
2677 revs,
2678 fm,
2678 fm,
2679 fntemplate=fntemplate,
2679 fntemplate=fntemplate,
2680 switch_parent=opts.get(b'switch_parent'),
2680 switch_parent=opts.get(b'switch_parent'),
2681 opts=patch.diffallopts(ui, opts),
2681 opts=patch.diffallopts(ui, opts),
2682 )
2682 )
2683
2683
2684
2684
2685 @command(
2685 @command(
2686 b'files',
2686 b'files',
2687 [
2687 [
2688 (
2688 (
2689 b'r',
2689 b'r',
2690 b'rev',
2690 b'rev',
2691 b'',
2691 b'',
2692 _(b'search the repository as it is in REV'),
2692 _(b'search the repository as it is in REV'),
2693 _(b'REV'),
2693 _(b'REV'),
2694 ),
2694 ),
2695 (
2695 (
2696 b'0',
2696 b'0',
2697 b'print0',
2697 b'print0',
2698 None,
2698 None,
2699 _(b'end filenames with NUL, for use with xargs'),
2699 _(b'end filenames with NUL, for use with xargs'),
2700 ),
2700 ),
2701 ]
2701 ]
2702 + walkopts
2702 + walkopts
2703 + formatteropts
2703 + formatteropts
2704 + subrepoopts,
2704 + subrepoopts,
2705 _(b'[OPTION]... [FILE]...'),
2705 _(b'[OPTION]... [FILE]...'),
2706 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2706 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2707 intents={INTENT_READONLY},
2707 intents={INTENT_READONLY},
2708 )
2708 )
2709 def files(ui, repo, *pats, **opts):
2709 def files(ui, repo, *pats, **opts):
2710 """list tracked files
2710 """list tracked files
2711
2711
2712 Print files under Mercurial control in the working directory or
2712 Print files under Mercurial control in the working directory or
2713 specified revision for given files (excluding removed files).
2713 specified revision for given files (excluding removed files).
2714 Files can be specified as filenames or filesets.
2714 Files can be specified as filenames or filesets.
2715
2715
2716 If no files are given to match, this command prints the names
2716 If no files are given to match, this command prints the names
2717 of all files under Mercurial control.
2717 of all files under Mercurial control.
2718
2718
2719 .. container:: verbose
2719 .. container:: verbose
2720
2720
2721 Template:
2721 Template:
2722
2722
2723 The following keywords are supported in addition to the common template
2723 The following keywords are supported in addition to the common template
2724 keywords and functions. See also :hg:`help templates`.
2724 keywords and functions. See also :hg:`help templates`.
2725
2725
2726 :flags: String. Character denoting file's symlink and executable bits.
2726 :flags: String. Character denoting file's symlink and executable bits.
2727 :path: String. Repository-absolute path of the file.
2727 :path: String. Repository-absolute path of the file.
2728 :size: Integer. Size of the file in bytes.
2728 :size: Integer. Size of the file in bytes.
2729
2729
2730 Examples:
2730 Examples:
2731
2731
2732 - list all files under the current directory::
2732 - list all files under the current directory::
2733
2733
2734 hg files .
2734 hg files .
2735
2735
2736 - shows sizes and flags for current revision::
2736 - shows sizes and flags for current revision::
2737
2737
2738 hg files -vr .
2738 hg files -vr .
2739
2739
2740 - list all files named README::
2740 - list all files named README::
2741
2741
2742 hg files -I "**/README"
2742 hg files -I "**/README"
2743
2743
2744 - list all binary files::
2744 - list all binary files::
2745
2745
2746 hg files "set:binary()"
2746 hg files "set:binary()"
2747
2747
2748 - find files containing a regular expression::
2748 - find files containing a regular expression::
2749
2749
2750 hg files "set:grep('bob')"
2750 hg files "set:grep('bob')"
2751
2751
2752 - search tracked file contents with xargs and grep::
2752 - search tracked file contents with xargs and grep::
2753
2753
2754 hg files -0 | xargs -0 grep foo
2754 hg files -0 | xargs -0 grep foo
2755
2755
2756 See :hg:`help patterns` and :hg:`help filesets` for more information
2756 See :hg:`help patterns` and :hg:`help filesets` for more information
2757 on specifying file patterns.
2757 on specifying file patterns.
2758
2758
2759 Returns 0 if a match is found, 1 otherwise.
2759 Returns 0 if a match is found, 1 otherwise.
2760
2760
2761 """
2761 """
2762
2762
2763 opts = pycompat.byteskwargs(opts)
2763 opts = pycompat.byteskwargs(opts)
2764 rev = opts.get(b'rev')
2764 rev = opts.get(b'rev')
2765 if rev:
2765 if rev:
2766 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2766 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2767 ctx = scmutil.revsingle(repo, rev, None)
2767 ctx = scmutil.revsingle(repo, rev, None)
2768
2768
2769 end = b'\n'
2769 end = b'\n'
2770 if opts.get(b'print0'):
2770 if opts.get(b'print0'):
2771 end = b'\0'
2771 end = b'\0'
2772 fmt = b'%s' + end
2772 fmt = b'%s' + end
2773
2773
2774 m = scmutil.match(ctx, pats, opts)
2774 m = scmutil.match(ctx, pats, opts)
2775 ui.pager(b'files')
2775 ui.pager(b'files')
2776 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2776 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2777 with ui.formatter(b'files', opts) as fm:
2777 with ui.formatter(b'files', opts) as fm:
2778 return cmdutil.files(
2778 return cmdutil.files(
2779 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2779 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2780 )
2780 )
2781
2781
2782
2782
2783 @command(
2783 @command(
2784 b'forget',
2784 b'forget',
2785 [(b'i', b'interactive', None, _(b'use interactive mode')),]
2785 [(b'i', b'interactive', None, _(b'use interactive mode')),]
2786 + walkopts
2786 + walkopts
2787 + dryrunopts,
2787 + dryrunopts,
2788 _(b'[OPTION]... FILE...'),
2788 _(b'[OPTION]... FILE...'),
2789 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2789 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2790 helpbasic=True,
2790 helpbasic=True,
2791 inferrepo=True,
2791 inferrepo=True,
2792 )
2792 )
2793 def forget(ui, repo, *pats, **opts):
2793 def forget(ui, repo, *pats, **opts):
2794 """forget the specified files on the next commit
2794 """forget the specified files on the next commit
2795
2795
2796 Mark the specified files so they will no longer be tracked
2796 Mark the specified files so they will no longer be tracked
2797 after the next commit.
2797 after the next commit.
2798
2798
2799 This only removes files from the current branch, not from the
2799 This only removes files from the current branch, not from the
2800 entire project history, and it does not delete them from the
2800 entire project history, and it does not delete them from the
2801 working directory.
2801 working directory.
2802
2802
2803 To delete the file from the working directory, see :hg:`remove`.
2803 To delete the file from the working directory, see :hg:`remove`.
2804
2804
2805 To undo a forget before the next commit, see :hg:`add`.
2805 To undo a forget before the next commit, see :hg:`add`.
2806
2806
2807 .. container:: verbose
2807 .. container:: verbose
2808
2808
2809 Examples:
2809 Examples:
2810
2810
2811 - forget newly-added binary files::
2811 - forget newly-added binary files::
2812
2812
2813 hg forget "set:added() and binary()"
2813 hg forget "set:added() and binary()"
2814
2814
2815 - forget files that would be excluded by .hgignore::
2815 - forget files that would be excluded by .hgignore::
2816
2816
2817 hg forget "set:hgignore()"
2817 hg forget "set:hgignore()"
2818
2818
2819 Returns 0 on success.
2819 Returns 0 on success.
2820 """
2820 """
2821
2821
2822 opts = pycompat.byteskwargs(opts)
2822 opts = pycompat.byteskwargs(opts)
2823 if not pats:
2823 if not pats:
2824 raise error.Abort(_(b'no files specified'))
2824 raise error.Abort(_(b'no files specified'))
2825
2825
2826 m = scmutil.match(repo[None], pats, opts)
2826 m = scmutil.match(repo[None], pats, opts)
2827 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2827 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2828 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2828 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2829 rejected = cmdutil.forget(
2829 rejected = cmdutil.forget(
2830 ui,
2830 ui,
2831 repo,
2831 repo,
2832 m,
2832 m,
2833 prefix=b"",
2833 prefix=b"",
2834 uipathfn=uipathfn,
2834 uipathfn=uipathfn,
2835 explicitonly=False,
2835 explicitonly=False,
2836 dryrun=dryrun,
2836 dryrun=dryrun,
2837 interactive=interactive,
2837 interactive=interactive,
2838 )[0]
2838 )[0]
2839 return rejected and 1 or 0
2839 return rejected and 1 or 0
2840
2840
2841
2841
2842 @command(
2842 @command(
2843 b'graft',
2843 b'graft',
2844 [
2844 [
2845 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2845 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2846 (
2846 (
2847 b'',
2847 b'',
2848 b'base',
2848 b'base',
2849 b'',
2849 b'',
2850 _(b'base revision when doing the graft merge (ADVANCED)'),
2850 _(b'base revision when doing the graft merge (ADVANCED)'),
2851 _(b'REV'),
2851 _(b'REV'),
2852 ),
2852 ),
2853 (b'c', b'continue', False, _(b'resume interrupted graft')),
2853 (b'c', b'continue', False, _(b'resume interrupted graft')),
2854 (b'', b'stop', False, _(b'stop interrupted graft')),
2854 (b'', b'stop', False, _(b'stop interrupted graft')),
2855 (b'', b'abort', False, _(b'abort interrupted graft')),
2855 (b'', b'abort', False, _(b'abort interrupted graft')),
2856 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2856 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2857 (b'', b'log', None, _(b'append graft info to log message')),
2857 (b'', b'log', None, _(b'append graft info to log message')),
2858 (
2858 (
2859 b'',
2859 b'',
2860 b'no-commit',
2860 b'no-commit',
2861 None,
2861 None,
2862 _(b"don't commit, just apply the changes in working directory"),
2862 _(b"don't commit, just apply the changes in working directory"),
2863 ),
2863 ),
2864 (b'f', b'force', False, _(b'force graft')),
2864 (b'f', b'force', False, _(b'force graft')),
2865 (
2865 (
2866 b'D',
2866 b'D',
2867 b'currentdate',
2867 b'currentdate',
2868 False,
2868 False,
2869 _(b'record the current date as commit date'),
2869 _(b'record the current date as commit date'),
2870 ),
2870 ),
2871 (
2871 (
2872 b'U',
2872 b'U',
2873 b'currentuser',
2873 b'currentuser',
2874 False,
2874 False,
2875 _(b'record the current user as committer'),
2875 _(b'record the current user as committer'),
2876 ),
2876 ),
2877 ]
2877 ]
2878 + commitopts2
2878 + commitopts2
2879 + mergetoolopts
2879 + mergetoolopts
2880 + dryrunopts,
2880 + dryrunopts,
2881 _(b'[OPTION]... [-r REV]... REV...'),
2881 _(b'[OPTION]... [-r REV]... REV...'),
2882 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2882 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2883 )
2883 )
2884 def graft(ui, repo, *revs, **opts):
2884 def graft(ui, repo, *revs, **opts):
2885 '''copy changes from other branches onto the current branch
2885 '''copy changes from other branches onto the current branch
2886
2886
2887 This command uses Mercurial's merge logic to copy individual
2887 This command uses Mercurial's merge logic to copy individual
2888 changes from other branches without merging branches in the
2888 changes from other branches without merging branches in the
2889 history graph. This is sometimes known as 'backporting' or
2889 history graph. This is sometimes known as 'backporting' or
2890 'cherry-picking'. By default, graft will copy user, date, and
2890 'cherry-picking'. By default, graft will copy user, date, and
2891 description from the source changesets.
2891 description from the source changesets.
2892
2892
2893 Changesets that are ancestors of the current revision, that have
2893 Changesets that are ancestors of the current revision, that have
2894 already been grafted, or that are merges will be skipped.
2894 already been grafted, or that are merges will be skipped.
2895
2895
2896 If --log is specified, log messages will have a comment appended
2896 If --log is specified, log messages will have a comment appended
2897 of the form::
2897 of the form::
2898
2898
2899 (grafted from CHANGESETHASH)
2899 (grafted from CHANGESETHASH)
2900
2900
2901 If --force is specified, revisions will be grafted even if they
2901 If --force is specified, revisions will be grafted even if they
2902 are already ancestors of, or have been grafted to, the destination.
2902 are already ancestors of, or have been grafted to, the destination.
2903 This is useful when the revisions have since been backed out.
2903 This is useful when the revisions have since been backed out.
2904
2904
2905 If a graft merge results in conflicts, the graft process is
2905 If a graft merge results in conflicts, the graft process is
2906 interrupted so that the current merge can be manually resolved.
2906 interrupted so that the current merge can be manually resolved.
2907 Once all conflicts are addressed, the graft process can be
2907 Once all conflicts are addressed, the graft process can be
2908 continued with the -c/--continue option.
2908 continued with the -c/--continue option.
2909
2909
2910 The -c/--continue option reapplies all the earlier options.
2910 The -c/--continue option reapplies all the earlier options.
2911
2911
2912 .. container:: verbose
2912 .. container:: verbose
2913
2913
2914 The --base option exposes more of how graft internally uses merge with a
2914 The --base option exposes more of how graft internally uses merge with a
2915 custom base revision. --base can be used to specify another ancestor than
2915 custom base revision. --base can be used to specify another ancestor than
2916 the first and only parent.
2916 the first and only parent.
2917
2917
2918 The command::
2918 The command::
2919
2919
2920 hg graft -r 345 --base 234
2920 hg graft -r 345 --base 234
2921
2921
2922 is thus pretty much the same as::
2922 is thus pretty much the same as::
2923
2923
2924 hg diff -r 234 -r 345 | hg import
2924 hg diff -r 234 -r 345 | hg import
2925
2925
2926 but using merge to resolve conflicts and track moved files.
2926 but using merge to resolve conflicts and track moved files.
2927
2927
2928 The result of a merge can thus be backported as a single commit by
2928 The result of a merge can thus be backported as a single commit by
2929 specifying one of the merge parents as base, and thus effectively
2929 specifying one of the merge parents as base, and thus effectively
2930 grafting the changes from the other side.
2930 grafting the changes from the other side.
2931
2931
2932 It is also possible to collapse multiple changesets and clean up history
2932 It is also possible to collapse multiple changesets and clean up history
2933 by specifying another ancestor as base, much like rebase --collapse
2933 by specifying another ancestor as base, much like rebase --collapse
2934 --keep.
2934 --keep.
2935
2935
2936 The commit message can be tweaked after the fact using commit --amend .
2936 The commit message can be tweaked after the fact using commit --amend .
2937
2937
2938 For using non-ancestors as the base to backout changes, see the backout
2938 For using non-ancestors as the base to backout changes, see the backout
2939 command and the hidden --parent option.
2939 command and the hidden --parent option.
2940
2940
2941 .. container:: verbose
2941 .. container:: verbose
2942
2942
2943 Examples:
2943 Examples:
2944
2944
2945 - copy a single change to the stable branch and edit its description::
2945 - copy a single change to the stable branch and edit its description::
2946
2946
2947 hg update stable
2947 hg update stable
2948 hg graft --edit 9393
2948 hg graft --edit 9393
2949
2949
2950 - graft a range of changesets with one exception, updating dates::
2950 - graft a range of changesets with one exception, updating dates::
2951
2951
2952 hg graft -D "2085::2093 and not 2091"
2952 hg graft -D "2085::2093 and not 2091"
2953
2953
2954 - continue a graft after resolving conflicts::
2954 - continue a graft after resolving conflicts::
2955
2955
2956 hg graft -c
2956 hg graft -c
2957
2957
2958 - show the source of a grafted changeset::
2958 - show the source of a grafted changeset::
2959
2959
2960 hg log --debug -r .
2960 hg log --debug -r .
2961
2961
2962 - show revisions sorted by date::
2962 - show revisions sorted by date::
2963
2963
2964 hg log -r "sort(all(), date)"
2964 hg log -r "sort(all(), date)"
2965
2965
2966 - backport the result of a merge as a single commit::
2966 - backport the result of a merge as a single commit::
2967
2967
2968 hg graft -r 123 --base 123^
2968 hg graft -r 123 --base 123^
2969
2969
2970 - land a feature branch as one changeset::
2970 - land a feature branch as one changeset::
2971
2971
2972 hg up -cr default
2972 hg up -cr default
2973 hg graft -r featureX --base "ancestor('featureX', 'default')"
2973 hg graft -r featureX --base "ancestor('featureX', 'default')"
2974
2974
2975 See :hg:`help revisions` for more about specifying revisions.
2975 See :hg:`help revisions` for more about specifying revisions.
2976
2976
2977 Returns 0 on successful completion, 1 if there are unresolved files.
2977 Returns 0 on successful completion, 1 if there are unresolved files.
2978 '''
2978 '''
2979 with repo.wlock():
2979 with repo.wlock():
2980 return _dograft(ui, repo, *revs, **opts)
2980 return _dograft(ui, repo, *revs, **opts)
2981
2981
2982
2982
2983 def _dograft(ui, repo, *revs, **opts):
2983 def _dograft(ui, repo, *revs, **opts):
2984 opts = pycompat.byteskwargs(opts)
2984 opts = pycompat.byteskwargs(opts)
2985 if revs and opts.get(b'rev'):
2985 if revs and opts.get(b'rev'):
2986 ui.warn(
2986 ui.warn(
2987 _(
2987 _(
2988 b'warning: inconsistent use of --rev might give unexpected '
2988 b'warning: inconsistent use of --rev might give unexpected '
2989 b'revision ordering!\n'
2989 b'revision ordering!\n'
2990 )
2990 )
2991 )
2991 )
2992
2992
2993 revs = list(revs)
2993 revs = list(revs)
2994 revs.extend(opts.get(b'rev'))
2994 revs.extend(opts.get(b'rev'))
2995 # a dict of data to be stored in state file
2995 # a dict of data to be stored in state file
2996 statedata = {}
2996 statedata = {}
2997 # list of new nodes created by ongoing graft
2997 # list of new nodes created by ongoing graft
2998 statedata[b'newnodes'] = []
2998 statedata[b'newnodes'] = []
2999
2999
3000 cmdutil.resolvecommitoptions(ui, opts)
3000 cmdutil.resolvecommitoptions(ui, opts)
3001
3001
3002 editor = cmdutil.getcommiteditor(
3002 editor = cmdutil.getcommiteditor(
3003 editform=b'graft', **pycompat.strkwargs(opts)
3003 editform=b'graft', **pycompat.strkwargs(opts)
3004 )
3004 )
3005
3005
3006 cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
3006 cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
3007
3007
3008 cont = False
3008 cont = False
3009 if opts.get(b'no_commit'):
3009 if opts.get(b'no_commit'):
3010 cmdutil.check_incompatible_arguments(
3010 cmdutil.check_incompatible_arguments(
3011 opts,
3011 opts,
3012 b'no_commit',
3012 b'no_commit',
3013 [b'edit', b'currentuser', b'currentdate', b'log'],
3013 [b'edit', b'currentuser', b'currentdate', b'log'],
3014 )
3014 )
3015
3015
3016 graftstate = statemod.cmdstate(repo, b'graftstate')
3016 graftstate = statemod.cmdstate(repo, b'graftstate')
3017
3017
3018 if opts.get(b'stop'):
3018 if opts.get(b'stop'):
3019 cmdutil.check_incompatible_arguments(
3019 cmdutil.check_incompatible_arguments(
3020 opts,
3020 opts,
3021 b'stop',
3021 b'stop',
3022 [
3022 [
3023 b'edit',
3023 b'edit',
3024 b'log',
3024 b'log',
3025 b'user',
3025 b'user',
3026 b'date',
3026 b'date',
3027 b'currentdate',
3027 b'currentdate',
3028 b'currentuser',
3028 b'currentuser',
3029 b'rev',
3029 b'rev',
3030 ],
3030 ],
3031 )
3031 )
3032 return _stopgraft(ui, repo, graftstate)
3032 return _stopgraft(ui, repo, graftstate)
3033 elif opts.get(b'abort'):
3033 elif opts.get(b'abort'):
3034 cmdutil.check_incompatible_arguments(
3034 cmdutil.check_incompatible_arguments(
3035 opts,
3035 opts,
3036 b'abort',
3036 b'abort',
3037 [
3037 [
3038 b'edit',
3038 b'edit',
3039 b'log',
3039 b'log',
3040 b'user',
3040 b'user',
3041 b'date',
3041 b'date',
3042 b'currentdate',
3042 b'currentdate',
3043 b'currentuser',
3043 b'currentuser',
3044 b'rev',
3044 b'rev',
3045 ],
3045 ],
3046 )
3046 )
3047 return cmdutil.abortgraft(ui, repo, graftstate)
3047 return cmdutil.abortgraft(ui, repo, graftstate)
3048 elif opts.get(b'continue'):
3048 elif opts.get(b'continue'):
3049 cont = True
3049 cont = True
3050 if revs:
3050 if revs:
3051 raise error.Abort(_(b"can't specify --continue and revisions"))
3051 raise error.Abort(_(b"can't specify --continue and revisions"))
3052 # read in unfinished revisions
3052 # read in unfinished revisions
3053 if graftstate.exists():
3053 if graftstate.exists():
3054 statedata = cmdutil.readgraftstate(repo, graftstate)
3054 statedata = cmdutil.readgraftstate(repo, graftstate)
3055 if statedata.get(b'date'):
3055 if statedata.get(b'date'):
3056 opts[b'date'] = statedata[b'date']
3056 opts[b'date'] = statedata[b'date']
3057 if statedata.get(b'user'):
3057 if statedata.get(b'user'):
3058 opts[b'user'] = statedata[b'user']
3058 opts[b'user'] = statedata[b'user']
3059 if statedata.get(b'log'):
3059 if statedata.get(b'log'):
3060 opts[b'log'] = True
3060 opts[b'log'] = True
3061 if statedata.get(b'no_commit'):
3061 if statedata.get(b'no_commit'):
3062 opts[b'no_commit'] = statedata.get(b'no_commit')
3062 opts[b'no_commit'] = statedata.get(b'no_commit')
3063 if statedata.get(b'base'):
3063 if statedata.get(b'base'):
3064 opts[b'base'] = statedata.get(b'base')
3064 opts[b'base'] = statedata.get(b'base')
3065 nodes = statedata[b'nodes']
3065 nodes = statedata[b'nodes']
3066 revs = [repo[node].rev() for node in nodes]
3066 revs = [repo[node].rev() for node in nodes]
3067 else:
3067 else:
3068 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3068 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3069 else:
3069 else:
3070 if not revs:
3070 if not revs:
3071 raise error.Abort(_(b'no revisions specified'))
3071 raise error.Abort(_(b'no revisions specified'))
3072 cmdutil.checkunfinished(repo)
3072 cmdutil.checkunfinished(repo)
3073 cmdutil.bailifchanged(repo)
3073 cmdutil.bailifchanged(repo)
3074 revs = scmutil.revrange(repo, revs)
3074 revs = scmutil.revrange(repo, revs)
3075
3075
3076 skipped = set()
3076 skipped = set()
3077 basectx = None
3077 basectx = None
3078 if opts.get(b'base'):
3078 if opts.get(b'base'):
3079 basectx = scmutil.revsingle(repo, opts[b'base'], None)
3079 basectx = scmutil.revsingle(repo, opts[b'base'], None)
3080 if basectx is None:
3080 if basectx is None:
3081 # check for merges
3081 # check for merges
3082 for rev in repo.revs(b'%ld and merge()', revs):
3082 for rev in repo.revs(b'%ld and merge()', revs):
3083 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3083 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3084 skipped.add(rev)
3084 skipped.add(rev)
3085 revs = [r for r in revs if r not in skipped]
3085 revs = [r for r in revs if r not in skipped]
3086 if not revs:
3086 if not revs:
3087 return -1
3087 return -1
3088 if basectx is not None and len(revs) != 1:
3088 if basectx is not None and len(revs) != 1:
3089 raise error.Abort(_(b'only one revision allowed with --base '))
3089 raise error.Abort(_(b'only one revision allowed with --base '))
3090
3090
3091 # Don't check in the --continue case, in effect retaining --force across
3091 # Don't check in the --continue case, in effect retaining --force across
3092 # --continues. That's because without --force, any revisions we decided to
3092 # --continues. That's because without --force, any revisions we decided to
3093 # skip would have been filtered out here, so they wouldn't have made their
3093 # skip would have been filtered out here, so they wouldn't have made their
3094 # way to the graftstate. With --force, any revisions we would have otherwise
3094 # way to the graftstate. With --force, any revisions we would have otherwise
3095 # skipped would not have been filtered out, and if they hadn't been applied
3095 # skipped would not have been filtered out, and if they hadn't been applied
3096 # already, they'd have been in the graftstate.
3096 # already, they'd have been in the graftstate.
3097 if not (cont or opts.get(b'force')) and basectx is None:
3097 if not (cont or opts.get(b'force')) and basectx is None:
3098 # check for ancestors of dest branch
3098 # check for ancestors of dest branch
3099 ancestors = repo.revs(b'%ld & (::.)', revs)
3099 ancestors = repo.revs(b'%ld & (::.)', revs)
3100 for rev in ancestors:
3100 for rev in ancestors:
3101 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3101 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3102
3102
3103 revs = [r for r in revs if r not in ancestors]
3103 revs = [r for r in revs if r not in ancestors]
3104
3104
3105 if not revs:
3105 if not revs:
3106 return -1
3106 return -1
3107
3107
3108 # analyze revs for earlier grafts
3108 # analyze revs for earlier grafts
3109 ids = {}
3109 ids = {}
3110 for ctx in repo.set(b"%ld", revs):
3110 for ctx in repo.set(b"%ld", revs):
3111 ids[ctx.hex()] = ctx.rev()
3111 ids[ctx.hex()] = ctx.rev()
3112 n = ctx.extra().get(b'source')
3112 n = ctx.extra().get(b'source')
3113 if n:
3113 if n:
3114 ids[n] = ctx.rev()
3114 ids[n] = ctx.rev()
3115
3115
3116 # check ancestors for earlier grafts
3116 # check ancestors for earlier grafts
3117 ui.debug(b'scanning for duplicate grafts\n')
3117 ui.debug(b'scanning for duplicate grafts\n')
3118
3118
3119 # The only changesets we can be sure doesn't contain grafts of any
3119 # The only changesets we can be sure doesn't contain grafts of any
3120 # revs, are the ones that are common ancestors of *all* revs:
3120 # revs, are the ones that are common ancestors of *all* revs:
3121 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3121 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3122 ctx = repo[rev]
3122 ctx = repo[rev]
3123 n = ctx.extra().get(b'source')
3123 n = ctx.extra().get(b'source')
3124 if n in ids:
3124 if n in ids:
3125 try:
3125 try:
3126 r = repo[n].rev()
3126 r = repo[n].rev()
3127 except error.RepoLookupError:
3127 except error.RepoLookupError:
3128 r = None
3128 r = None
3129 if r in revs:
3129 if r in revs:
3130 ui.warn(
3130 ui.warn(
3131 _(
3131 _(
3132 b'skipping revision %d:%s '
3132 b'skipping revision %d:%s '
3133 b'(already grafted to %d:%s)\n'
3133 b'(already grafted to %d:%s)\n'
3134 )
3134 )
3135 % (r, repo[r], rev, ctx)
3135 % (r, repo[r], rev, ctx)
3136 )
3136 )
3137 revs.remove(r)
3137 revs.remove(r)
3138 elif ids[n] in revs:
3138 elif ids[n] in revs:
3139 if r is None:
3139 if r is None:
3140 ui.warn(
3140 ui.warn(
3141 _(
3141 _(
3142 b'skipping already grafted revision %d:%s '
3142 b'skipping already grafted revision %d:%s '
3143 b'(%d:%s also has unknown origin %s)\n'
3143 b'(%d:%s also has unknown origin %s)\n'
3144 )
3144 )
3145 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3145 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3146 )
3146 )
3147 else:
3147 else:
3148 ui.warn(
3148 ui.warn(
3149 _(
3149 _(
3150 b'skipping already grafted revision %d:%s '
3150 b'skipping already grafted revision %d:%s '
3151 b'(%d:%s also has origin %d:%s)\n'
3151 b'(%d:%s also has origin %d:%s)\n'
3152 )
3152 )
3153 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3153 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3154 )
3154 )
3155 revs.remove(ids[n])
3155 revs.remove(ids[n])
3156 elif ctx.hex() in ids:
3156 elif ctx.hex() in ids:
3157 r = ids[ctx.hex()]
3157 r = ids[ctx.hex()]
3158 if r in revs:
3158 if r in revs:
3159 ui.warn(
3159 ui.warn(
3160 _(
3160 _(
3161 b'skipping already grafted revision %d:%s '
3161 b'skipping already grafted revision %d:%s '
3162 b'(was grafted from %d:%s)\n'
3162 b'(was grafted from %d:%s)\n'
3163 )
3163 )
3164 % (r, repo[r], rev, ctx)
3164 % (r, repo[r], rev, ctx)
3165 )
3165 )
3166 revs.remove(r)
3166 revs.remove(r)
3167 if not revs:
3167 if not revs:
3168 return -1
3168 return -1
3169
3169
3170 if opts.get(b'no_commit'):
3170 if opts.get(b'no_commit'):
3171 statedata[b'no_commit'] = True
3171 statedata[b'no_commit'] = True
3172 if opts.get(b'base'):
3172 if opts.get(b'base'):
3173 statedata[b'base'] = opts[b'base']
3173 statedata[b'base'] = opts[b'base']
3174 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3174 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3175 desc = b'%d:%s "%s"' % (
3175 desc = b'%d:%s "%s"' % (
3176 ctx.rev(),
3176 ctx.rev(),
3177 ctx,
3177 ctx,
3178 ctx.description().split(b'\n', 1)[0],
3178 ctx.description().split(b'\n', 1)[0],
3179 )
3179 )
3180 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3180 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3181 if names:
3181 if names:
3182 desc += b' (%s)' % b' '.join(names)
3182 desc += b' (%s)' % b' '.join(names)
3183 ui.status(_(b'grafting %s\n') % desc)
3183 ui.status(_(b'grafting %s\n') % desc)
3184 if opts.get(b'dry_run'):
3184 if opts.get(b'dry_run'):
3185 continue
3185 continue
3186
3186
3187 source = ctx.extra().get(b'source')
3187 source = ctx.extra().get(b'source')
3188 extra = {}
3188 extra = {}
3189 if source:
3189 if source:
3190 extra[b'source'] = source
3190 extra[b'source'] = source
3191 extra[b'intermediate-source'] = ctx.hex()
3191 extra[b'intermediate-source'] = ctx.hex()
3192 else:
3192 else:
3193 extra[b'source'] = ctx.hex()
3193 extra[b'source'] = ctx.hex()
3194 user = ctx.user()
3194 user = ctx.user()
3195 if opts.get(b'user'):
3195 if opts.get(b'user'):
3196 user = opts[b'user']
3196 user = opts[b'user']
3197 statedata[b'user'] = user
3197 statedata[b'user'] = user
3198 date = ctx.date()
3198 date = ctx.date()
3199 if opts.get(b'date'):
3199 if opts.get(b'date'):
3200 date = opts[b'date']
3200 date = opts[b'date']
3201 statedata[b'date'] = date
3201 statedata[b'date'] = date
3202 message = ctx.description()
3202 message = ctx.description()
3203 if opts.get(b'log'):
3203 if opts.get(b'log'):
3204 message += b'\n(grafted from %s)' % ctx.hex()
3204 message += b'\n(grafted from %s)' % ctx.hex()
3205 statedata[b'log'] = True
3205 statedata[b'log'] = True
3206
3206
3207 # we don't merge the first commit when continuing
3207 # we don't merge the first commit when continuing
3208 if not cont:
3208 if not cont:
3209 # perform the graft merge with p1(rev) as 'ancestor'
3209 # perform the graft merge with p1(rev) as 'ancestor'
3210 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3210 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3211 base = ctx.p1() if basectx is None else basectx
3211 base = ctx.p1() if basectx is None else basectx
3212 with ui.configoverride(overrides, b'graft'):
3212 with ui.configoverride(overrides, b'graft'):
3213 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3213 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3214 # report any conflicts
3214 # report any conflicts
3215 if stats.unresolvedcount > 0:
3215 if stats.unresolvedcount > 0:
3216 # write out state for --continue
3216 # write out state for --continue
3217 nodes = [repo[rev].hex() for rev in revs[pos:]]
3217 nodes = [repo[rev].hex() for rev in revs[pos:]]
3218 statedata[b'nodes'] = nodes
3218 statedata[b'nodes'] = nodes
3219 stateversion = 1
3219 stateversion = 1
3220 graftstate.save(stateversion, statedata)
3220 graftstate.save(stateversion, statedata)
3221 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3221 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3222 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3222 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3223 return 1
3223 return 1
3224 else:
3224 else:
3225 cont = False
3225 cont = False
3226
3226
3227 # commit if --no-commit is false
3227 # commit if --no-commit is false
3228 if not opts.get(b'no_commit'):
3228 if not opts.get(b'no_commit'):
3229 node = repo.commit(
3229 node = repo.commit(
3230 text=message, user=user, date=date, extra=extra, editor=editor
3230 text=message, user=user, date=date, extra=extra, editor=editor
3231 )
3231 )
3232 if node is None:
3232 if node is None:
3233 ui.warn(
3233 ui.warn(
3234 _(b'note: graft of %d:%s created no changes to commit\n')
3234 _(b'note: graft of %d:%s created no changes to commit\n')
3235 % (ctx.rev(), ctx)
3235 % (ctx.rev(), ctx)
3236 )
3236 )
3237 # checking that newnodes exist because old state files won't have it
3237 # checking that newnodes exist because old state files won't have it
3238 elif statedata.get(b'newnodes') is not None:
3238 elif statedata.get(b'newnodes') is not None:
3239 statedata[b'newnodes'].append(node)
3239 statedata[b'newnodes'].append(node)
3240
3240
3241 # remove state when we complete successfully
3241 # remove state when we complete successfully
3242 if not opts.get(b'dry_run'):
3242 if not opts.get(b'dry_run'):
3243 graftstate.delete()
3243 graftstate.delete()
3244
3244
3245 return 0
3245 return 0
3246
3246
3247
3247
3248 def _stopgraft(ui, repo, graftstate):
3248 def _stopgraft(ui, repo, graftstate):
3249 """stop the interrupted graft"""
3249 """stop the interrupted graft"""
3250 if not graftstate.exists():
3250 if not graftstate.exists():
3251 raise error.Abort(_(b"no interrupted graft found"))
3251 raise error.Abort(_(b"no interrupted graft found"))
3252 pctx = repo[b'.']
3252 pctx = repo[b'.']
3253 mergemod.clean_update(pctx)
3253 mergemod.clean_update(pctx)
3254 graftstate.delete()
3254 graftstate.delete()
3255 ui.status(_(b"stopped the interrupted graft\n"))
3255 ui.status(_(b"stopped the interrupted graft\n"))
3256 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3256 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3257 return 0
3257 return 0
3258
3258
3259
3259
3260 statemod.addunfinished(
3260 statemod.addunfinished(
3261 b'graft',
3261 b'graft',
3262 fname=b'graftstate',
3262 fname=b'graftstate',
3263 clearable=True,
3263 clearable=True,
3264 stopflag=True,
3264 stopflag=True,
3265 continueflag=True,
3265 continueflag=True,
3266 abortfunc=cmdutil.hgabortgraft,
3266 abortfunc=cmdutil.hgabortgraft,
3267 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3267 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3268 )
3268 )
3269
3269
3270
3270
3271 @command(
3271 @command(
3272 b'grep',
3272 b'grep',
3273 [
3273 [
3274 (b'0', b'print0', None, _(b'end fields with NUL')),
3274 (b'0', b'print0', None, _(b'end fields with NUL')),
3275 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3275 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3276 (
3276 (
3277 b'',
3277 b'',
3278 b'diff',
3278 b'diff',
3279 None,
3279 None,
3280 _(
3280 _(
3281 b'search revision differences for when the pattern was added '
3281 b'search revision differences for when the pattern was added '
3282 b'or removed'
3282 b'or removed'
3283 ),
3283 ),
3284 ),
3284 ),
3285 (b'a', b'text', None, _(b'treat all files as text')),
3285 (b'a', b'text', None, _(b'treat all files as text')),
3286 (
3286 (
3287 b'f',
3287 b'f',
3288 b'follow',
3288 b'follow',
3289 None,
3289 None,
3290 _(
3290 _(
3291 b'follow changeset history,'
3291 b'follow changeset history,'
3292 b' or file history across copies and renames'
3292 b' or file history across copies and renames'
3293 ),
3293 ),
3294 ),
3294 ),
3295 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3295 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3296 (
3296 (
3297 b'l',
3297 b'l',
3298 b'files-with-matches',
3298 b'files-with-matches',
3299 None,
3299 None,
3300 _(b'print only filenames and revisions that match'),
3300 _(b'print only filenames and revisions that match'),
3301 ),
3301 ),
3302 (b'n', b'line-number', None, _(b'print matching line numbers')),
3302 (b'n', b'line-number', None, _(b'print matching line numbers')),
3303 (
3303 (
3304 b'r',
3304 b'r',
3305 b'rev',
3305 b'rev',
3306 [],
3306 [],
3307 _(b'search files changed within revision range'),
3307 _(b'search files changed within revision range'),
3308 _(b'REV'),
3308 _(b'REV'),
3309 ),
3309 ),
3310 (
3310 (
3311 b'',
3311 b'',
3312 b'all-files',
3312 b'all-files',
3313 None,
3313 None,
3314 _(
3314 _(
3315 b'include all files in the changeset while grepping (DEPRECATED)'
3315 b'include all files in the changeset while grepping (DEPRECATED)'
3316 ),
3316 ),
3317 ),
3317 ),
3318 (b'u', b'user', None, _(b'list the author (long with -v)')),
3318 (b'u', b'user', None, _(b'list the author (long with -v)')),
3319 (b'd', b'date', None, _(b'list the date (short with -q)')),
3319 (b'd', b'date', None, _(b'list the date (short with -q)')),
3320 ]
3320 ]
3321 + formatteropts
3321 + formatteropts
3322 + walkopts,
3322 + walkopts,
3323 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3323 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3324 helpcategory=command.CATEGORY_FILE_CONTENTS,
3324 helpcategory=command.CATEGORY_FILE_CONTENTS,
3325 inferrepo=True,
3325 inferrepo=True,
3326 intents={INTENT_READONLY},
3326 intents={INTENT_READONLY},
3327 )
3327 )
3328 def grep(ui, repo, pattern, *pats, **opts):
3328 def grep(ui, repo, pattern, *pats, **opts):
3329 """search for a pattern in specified files
3329 """search for a pattern in specified files
3330
3330
3331 Search the working directory or revision history for a regular
3331 Search the working directory or revision history for a regular
3332 expression in the specified files for the entire repository.
3332 expression in the specified files for the entire repository.
3333
3333
3334 By default, grep searches the repository files in the working
3334 By default, grep searches the repository files in the working
3335 directory and prints the files where it finds a match. To specify
3335 directory and prints the files where it finds a match. To specify
3336 historical revisions instead of the working directory, use the
3336 historical revisions instead of the working directory, use the
3337 --rev flag.
3337 --rev flag.
3338
3338
3339 To search instead historical revision differences that contains a
3339 To search instead historical revision differences that contains a
3340 change in match status ("-" for a match that becomes a non-match,
3340 change in match status ("-" for a match that becomes a non-match,
3341 or "+" for a non-match that becomes a match), use the --diff flag.
3341 or "+" for a non-match that becomes a match), use the --diff flag.
3342
3342
3343 PATTERN can be any Python (roughly Perl-compatible) regular
3343 PATTERN can be any Python (roughly Perl-compatible) regular
3344 expression.
3344 expression.
3345
3345
3346 If no FILEs are specified and the --rev flag isn't supplied, all
3346 If no FILEs are specified and the --rev flag isn't supplied, all
3347 files in the working directory are searched. When using the --rev
3347 files in the working directory are searched. When using the --rev
3348 flag and specifying FILEs, use the --follow argument to also
3348 flag and specifying FILEs, use the --follow argument to also
3349 follow the specified FILEs across renames and copies.
3349 follow the specified FILEs across renames and copies.
3350
3350
3351 .. container:: verbose
3351 .. container:: verbose
3352
3352
3353 Template:
3353 Template:
3354
3354
3355 The following keywords are supported in addition to the common template
3355 The following keywords are supported in addition to the common template
3356 keywords and functions. See also :hg:`help templates`.
3356 keywords and functions. See also :hg:`help templates`.
3357
3357
3358 :change: String. Character denoting insertion ``+`` or removal ``-``.
3358 :change: String. Character denoting insertion ``+`` or removal ``-``.
3359 Available if ``--diff`` is specified.
3359 Available if ``--diff`` is specified.
3360 :lineno: Integer. Line number of the match.
3360 :lineno: Integer. Line number of the match.
3361 :path: String. Repository-absolute path of the file.
3361 :path: String. Repository-absolute path of the file.
3362 :texts: List of text chunks.
3362 :texts: List of text chunks.
3363
3363
3364 And each entry of ``{texts}`` provides the following sub-keywords.
3364 And each entry of ``{texts}`` provides the following sub-keywords.
3365
3365
3366 :matched: Boolean. True if the chunk matches the specified pattern.
3366 :matched: Boolean. True if the chunk matches the specified pattern.
3367 :text: String. Chunk content.
3367 :text: String. Chunk content.
3368
3368
3369 See :hg:`help templates.operators` for the list expansion syntax.
3369 See :hg:`help templates.operators` for the list expansion syntax.
3370
3370
3371 Returns 0 if a match is found, 1 otherwise.
3371 Returns 0 if a match is found, 1 otherwise.
3372
3372
3373 """
3373 """
3374 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3374 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3375 opts = pycompat.byteskwargs(opts)
3375 opts = pycompat.byteskwargs(opts)
3376 diff = opts.get(b'all') or opts.get(b'diff')
3376 diff = opts.get(b'all') or opts.get(b'diff')
3377 follow = opts.get(b'follow')
3377 follow = opts.get(b'follow')
3378 if opts.get(b'all_files') is None and not diff:
3378 if opts.get(b'all_files') is None and not diff:
3379 opts[b'all_files'] = True
3379 opts[b'all_files'] = True
3380 plaingrep = (
3380 plaingrep = (
3381 opts.get(b'all_files')
3381 opts.get(b'all_files')
3382 and not opts.get(b'rev')
3382 and not opts.get(b'rev')
3383 and not opts.get(b'follow')
3383 and not opts.get(b'follow')
3384 )
3384 )
3385 all_files = opts.get(b'all_files')
3385 all_files = opts.get(b'all_files')
3386 if plaingrep:
3386 if plaingrep:
3387 opts[b'rev'] = [b'wdir()']
3387 opts[b'rev'] = [b'wdir()']
3388
3388
3389 reflags = re.M
3389 reflags = re.M
3390 if opts.get(b'ignore_case'):
3390 if opts.get(b'ignore_case'):
3391 reflags |= re.I
3391 reflags |= re.I
3392 try:
3392 try:
3393 regexp = util.re.compile(pattern, reflags)
3393 regexp = util.re.compile(pattern, reflags)
3394 except re.error as inst:
3394 except re.error as inst:
3395 ui.warn(
3395 ui.warn(
3396 _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
3396 _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
3397 )
3397 )
3398 return 1
3398 return 1
3399 sep, eol = b':', b'\n'
3399 sep, eol = b':', b'\n'
3400 if opts.get(b'print0'):
3400 if opts.get(b'print0'):
3401 sep = eol = b'\0'
3401 sep = eol = b'\0'
3402
3402
3403 searcher = grepmod.grepsearcher(
3403 searcher = grepmod.grepsearcher(
3404 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3404 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3405 )
3405 )
3406
3406
3407 getfile = searcher._getfile
3407 getfile = searcher._getfile
3408
3408
3409 uipathfn = scmutil.getuipathfn(repo)
3409 uipathfn = scmutil.getuipathfn(repo)
3410
3410
3411 def display(fm, fn, ctx, pstates, states):
3411 def display(fm, fn, ctx, pstates, states):
3412 rev = scmutil.intrev(ctx)
3412 rev = scmutil.intrev(ctx)
3413 if fm.isplain():
3413 if fm.isplain():
3414 formatuser = ui.shortuser
3414 formatuser = ui.shortuser
3415 else:
3415 else:
3416 formatuser = pycompat.bytestr
3416 formatuser = pycompat.bytestr
3417 if ui.quiet:
3417 if ui.quiet:
3418 datefmt = b'%Y-%m-%d'
3418 datefmt = b'%Y-%m-%d'
3419 else:
3419 else:
3420 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3420 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3421 found = False
3421 found = False
3422
3422
3423 @util.cachefunc
3423 @util.cachefunc
3424 def binary():
3424 def binary():
3425 flog = getfile(fn)
3425 flog = getfile(fn)
3426 try:
3426 try:
3427 return stringutil.binary(flog.read(ctx.filenode(fn)))
3427 return stringutil.binary(flog.read(ctx.filenode(fn)))
3428 except error.WdirUnsupported:
3428 except error.WdirUnsupported:
3429 return ctx[fn].isbinary()
3429 return ctx[fn].isbinary()
3430
3430
3431 fieldnamemap = {b'linenumber': b'lineno'}
3431 fieldnamemap = {b'linenumber': b'lineno'}
3432 if diff:
3432 if diff:
3433 iter = grepmod.difflinestates(pstates, states)
3433 iter = grepmod.difflinestates(pstates, states)
3434 else:
3434 else:
3435 iter = [(b'', l) for l in states]
3435 iter = [(b'', l) for l in states]
3436 for change, l in iter:
3436 for change, l in iter:
3437 fm.startitem()
3437 fm.startitem()
3438 fm.context(ctx=ctx)
3438 fm.context(ctx=ctx)
3439 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3439 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3440 fm.plain(uipathfn(fn), label=b'grep.filename')
3440 fm.plain(uipathfn(fn), label=b'grep.filename')
3441
3441
3442 cols = [
3442 cols = [
3443 (b'rev', b'%d', rev, not plaingrep, b''),
3443 (b'rev', b'%d', rev, not plaingrep, b''),
3444 (
3444 (
3445 b'linenumber',
3445 b'linenumber',
3446 b'%d',
3446 b'%d',
3447 l.linenum,
3447 l.linenum,
3448 opts.get(b'line_number'),
3448 opts.get(b'line_number'),
3449 b'',
3449 b'',
3450 ),
3450 ),
3451 ]
3451 ]
3452 if diff:
3452 if diff:
3453 cols.append(
3453 cols.append(
3454 (
3454 (
3455 b'change',
3455 b'change',
3456 b'%s',
3456 b'%s',
3457 change,
3457 change,
3458 True,
3458 True,
3459 b'grep.inserted '
3459 b'grep.inserted '
3460 if change == b'+'
3460 if change == b'+'
3461 else b'grep.deleted ',
3461 else b'grep.deleted ',
3462 )
3462 )
3463 )
3463 )
3464 cols.extend(
3464 cols.extend(
3465 [
3465 [
3466 (
3466 (
3467 b'user',
3467 b'user',
3468 b'%s',
3468 b'%s',
3469 formatuser(ctx.user()),
3469 formatuser(ctx.user()),
3470 opts.get(b'user'),
3470 opts.get(b'user'),
3471 b'',
3471 b'',
3472 ),
3472 ),
3473 (
3473 (
3474 b'date',
3474 b'date',
3475 b'%s',
3475 b'%s',
3476 fm.formatdate(ctx.date(), datefmt),
3476 fm.formatdate(ctx.date(), datefmt),
3477 opts.get(b'date'),
3477 opts.get(b'date'),
3478 b'',
3478 b'',
3479 ),
3479 ),
3480 ]
3480 ]
3481 )
3481 )
3482 for name, fmt, data, cond, extra_label in cols:
3482 for name, fmt, data, cond, extra_label in cols:
3483 if cond:
3483 if cond:
3484 fm.plain(sep, label=b'grep.sep')
3484 fm.plain(sep, label=b'grep.sep')
3485 field = fieldnamemap.get(name, name)
3485 field = fieldnamemap.get(name, name)
3486 label = extra_label + (b'grep.%s' % name)
3486 label = extra_label + (b'grep.%s' % name)
3487 fm.condwrite(cond, field, fmt, data, label=label)
3487 fm.condwrite(cond, field, fmt, data, label=label)
3488 if not opts.get(b'files_with_matches'):
3488 if not opts.get(b'files_with_matches'):
3489 fm.plain(sep, label=b'grep.sep')
3489 fm.plain(sep, label=b'grep.sep')
3490 if not opts.get(b'text') and binary():
3490 if not opts.get(b'text') and binary():
3491 fm.plain(_(b" Binary file matches"))
3491 fm.plain(_(b" Binary file matches"))
3492 else:
3492 else:
3493 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3493 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3494 fm.plain(eol)
3494 fm.plain(eol)
3495 found = True
3495 found = True
3496 if opts.get(b'files_with_matches'):
3496 if opts.get(b'files_with_matches'):
3497 break
3497 break
3498 return found
3498 return found
3499
3499
3500 def displaymatches(fm, l):
3500 def displaymatches(fm, l):
3501 p = 0
3501 p = 0
3502 for s, e in l.findpos(regexp):
3502 for s, e in l.findpos(regexp):
3503 if p < s:
3503 if p < s:
3504 fm.startitem()
3504 fm.startitem()
3505 fm.write(b'text', b'%s', l.line[p:s])
3505 fm.write(b'text', b'%s', l.line[p:s])
3506 fm.data(matched=False)
3506 fm.data(matched=False)
3507 fm.startitem()
3507 fm.startitem()
3508 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3508 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3509 fm.data(matched=True)
3509 fm.data(matched=True)
3510 p = e
3510 p = e
3511 if p < len(l.line):
3511 if p < len(l.line):
3512 fm.startitem()
3512 fm.startitem()
3513 fm.write(b'text', b'%s', l.line[p:])
3513 fm.write(b'text', b'%s', l.line[p:])
3514 fm.data(matched=False)
3514 fm.data(matched=False)
3515 fm.end()
3515 fm.end()
3516
3516
3517 found = False
3517 found = False
3518
3518
3519 wopts = logcmdutil.walkopts(
3519 wopts = logcmdutil.walkopts(
3520 pats=pats,
3520 pats=pats,
3521 opts=opts,
3521 opts=opts,
3522 revspec=opts[b'rev'],
3522 revspec=opts[b'rev'],
3523 include_pats=opts[b'include'],
3523 include_pats=opts[b'include'],
3524 exclude_pats=opts[b'exclude'],
3524 exclude_pats=opts[b'exclude'],
3525 follow=follow,
3525 follow=follow,
3526 force_changelog_traversal=all_files,
3526 force_changelog_traversal=all_files,
3527 filter_revisions_by_pats=not all_files,
3527 filter_revisions_by_pats=not all_files,
3528 )
3528 )
3529 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3529 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3530
3530
3531 ui.pager(b'grep')
3531 ui.pager(b'grep')
3532 fm = ui.formatter(b'grep', opts)
3532 fm = ui.formatter(b'grep', opts)
3533 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3533 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3534 r = display(fm, fn, ctx, pstates, states)
3534 r = display(fm, fn, ctx, pstates, states)
3535 found = found or r
3535 found = found or r
3536 if r and not diff and not all_files:
3536 if r and not diff and not all_files:
3537 searcher.skipfile(fn, ctx.rev())
3537 searcher.skipfile(fn, ctx.rev())
3538 fm.end()
3538 fm.end()
3539
3539
3540 return not found
3540 return not found
3541
3541
3542
3542
3543 @command(
3543 @command(
3544 b'heads',
3544 b'heads',
3545 [
3545 [
3546 (
3546 (
3547 b'r',
3547 b'r',
3548 b'rev',
3548 b'rev',
3549 b'',
3549 b'',
3550 _(b'show only heads which are descendants of STARTREV'),
3550 _(b'show only heads which are descendants of STARTREV'),
3551 _(b'STARTREV'),
3551 _(b'STARTREV'),
3552 ),
3552 ),
3553 (b't', b'topo', False, _(b'show topological heads only')),
3553 (b't', b'topo', False, _(b'show topological heads only')),
3554 (
3554 (
3555 b'a',
3555 b'a',
3556 b'active',
3556 b'active',
3557 False,
3557 False,
3558 _(b'show active branchheads only (DEPRECATED)'),
3558 _(b'show active branchheads only (DEPRECATED)'),
3559 ),
3559 ),
3560 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3560 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3561 ]
3561 ]
3562 + templateopts,
3562 + templateopts,
3563 _(b'[-ct] [-r STARTREV] [REV]...'),
3563 _(b'[-ct] [-r STARTREV] [REV]...'),
3564 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3564 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3565 intents={INTENT_READONLY},
3565 intents={INTENT_READONLY},
3566 )
3566 )
3567 def heads(ui, repo, *branchrevs, **opts):
3567 def heads(ui, repo, *branchrevs, **opts):
3568 """show branch heads
3568 """show branch heads
3569
3569
3570 With no arguments, show all open branch heads in the repository.
3570 With no arguments, show all open branch heads in the repository.
3571 Branch heads are changesets that have no descendants on the
3571 Branch heads are changesets that have no descendants on the
3572 same branch. They are where development generally takes place and
3572 same branch. They are where development generally takes place and
3573 are the usual targets for update and merge operations.
3573 are the usual targets for update and merge operations.
3574
3574
3575 If one or more REVs are given, only open branch heads on the
3575 If one or more REVs are given, only open branch heads on the
3576 branches associated with the specified changesets are shown. This
3576 branches associated with the specified changesets are shown. This
3577 means that you can use :hg:`heads .` to see the heads on the
3577 means that you can use :hg:`heads .` to see the heads on the
3578 currently checked-out branch.
3578 currently checked-out branch.
3579
3579
3580 If -c/--closed is specified, also show branch heads marked closed
3580 If -c/--closed is specified, also show branch heads marked closed
3581 (see :hg:`commit --close-branch`).
3581 (see :hg:`commit --close-branch`).
3582
3582
3583 If STARTREV is specified, only those heads that are descendants of
3583 If STARTREV is specified, only those heads that are descendants of
3584 STARTREV will be displayed.
3584 STARTREV will be displayed.
3585
3585
3586 If -t/--topo is specified, named branch mechanics will be ignored and only
3586 If -t/--topo is specified, named branch mechanics will be ignored and only
3587 topological heads (changesets with no children) will be shown.
3587 topological heads (changesets with no children) will be shown.
3588
3588
3589 Returns 0 if matching heads are found, 1 if not.
3589 Returns 0 if matching heads are found, 1 if not.
3590 """
3590 """
3591
3591
3592 opts = pycompat.byteskwargs(opts)
3592 opts = pycompat.byteskwargs(opts)
3593 start = None
3593 start = None
3594 rev = opts.get(b'rev')
3594 rev = opts.get(b'rev')
3595 if rev:
3595 if rev:
3596 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3596 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3597 start = scmutil.revsingle(repo, rev, None).node()
3597 start = scmutil.revsingle(repo, rev, None).node()
3598
3598
3599 if opts.get(b'topo'):
3599 if opts.get(b'topo'):
3600 heads = [repo[h] for h in repo.heads(start)]
3600 heads = [repo[h] for h in repo.heads(start)]
3601 else:
3601 else:
3602 heads = []
3602 heads = []
3603 for branch in repo.branchmap():
3603 for branch in repo.branchmap():
3604 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3604 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3605 heads = [repo[h] for h in heads]
3605 heads = [repo[h] for h in heads]
3606
3606
3607 if branchrevs:
3607 if branchrevs:
3608 branches = {
3608 branches = {
3609 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3609 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3610 }
3610 }
3611 heads = [h for h in heads if h.branch() in branches]
3611 heads = [h for h in heads if h.branch() in branches]
3612
3612
3613 if opts.get(b'active') and branchrevs:
3613 if opts.get(b'active') and branchrevs:
3614 dagheads = repo.heads(start)
3614 dagheads = repo.heads(start)
3615 heads = [h for h in heads if h.node() in dagheads]
3615 heads = [h for h in heads if h.node() in dagheads]
3616
3616
3617 if branchrevs:
3617 if branchrevs:
3618 haveheads = {h.branch() for h in heads}
3618 haveheads = {h.branch() for h in heads}
3619 if branches - haveheads:
3619 if branches - haveheads:
3620 headless = b', '.join(b for b in branches - haveheads)
3620 headless = b', '.join(b for b in branches - haveheads)
3621 msg = _(b'no open branch heads found on branches %s')
3621 msg = _(b'no open branch heads found on branches %s')
3622 if opts.get(b'rev'):
3622 if opts.get(b'rev'):
3623 msg += _(b' (started at %s)') % opts[b'rev']
3623 msg += _(b' (started at %s)') % opts[b'rev']
3624 ui.warn((msg + b'\n') % headless)
3624 ui.warn((msg + b'\n') % headless)
3625
3625
3626 if not heads:
3626 if not heads:
3627 return 1
3627 return 1
3628
3628
3629 ui.pager(b'heads')
3629 ui.pager(b'heads')
3630 heads = sorted(heads, key=lambda x: -(x.rev()))
3630 heads = sorted(heads, key=lambda x: -(x.rev()))
3631 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3631 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3632 for ctx in heads:
3632 for ctx in heads:
3633 displayer.show(ctx)
3633 displayer.show(ctx)
3634 displayer.close()
3634 displayer.close()
3635
3635
3636
3636
3637 @command(
3637 @command(
3638 b'help',
3638 b'help',
3639 [
3639 [
3640 (b'e', b'extension', None, _(b'show only help for extensions')),
3640 (b'e', b'extension', None, _(b'show only help for extensions')),
3641 (b'c', b'command', None, _(b'show only help for commands')),
3641 (b'c', b'command', None, _(b'show only help for commands')),
3642 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3642 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3643 (
3643 (
3644 b's',
3644 b's',
3645 b'system',
3645 b'system',
3646 [],
3646 [],
3647 _(b'show help for specific platform(s)'),
3647 _(b'show help for specific platform(s)'),
3648 _(b'PLATFORM'),
3648 _(b'PLATFORM'),
3649 ),
3649 ),
3650 ],
3650 ],
3651 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3651 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3652 helpcategory=command.CATEGORY_HELP,
3652 helpcategory=command.CATEGORY_HELP,
3653 norepo=True,
3653 norepo=True,
3654 intents={INTENT_READONLY},
3654 intents={INTENT_READONLY},
3655 )
3655 )
3656 def help_(ui, name=None, **opts):
3656 def help_(ui, name=None, **opts):
3657 """show help for a given topic or a help overview
3657 """show help for a given topic or a help overview
3658
3658
3659 With no arguments, print a list of commands with short help messages.
3659 With no arguments, print a list of commands with short help messages.
3660
3660
3661 Given a topic, extension, or command name, print help for that
3661 Given a topic, extension, or command name, print help for that
3662 topic.
3662 topic.
3663
3663
3664 Returns 0 if successful.
3664 Returns 0 if successful.
3665 """
3665 """
3666
3666
3667 keep = opts.get('system') or []
3667 keep = opts.get('system') or []
3668 if len(keep) == 0:
3668 if len(keep) == 0:
3669 if pycompat.sysplatform.startswith(b'win'):
3669 if pycompat.sysplatform.startswith(b'win'):
3670 keep.append(b'windows')
3670 keep.append(b'windows')
3671 elif pycompat.sysplatform == b'OpenVMS':
3671 elif pycompat.sysplatform == b'OpenVMS':
3672 keep.append(b'vms')
3672 keep.append(b'vms')
3673 elif pycompat.sysplatform == b'plan9':
3673 elif pycompat.sysplatform == b'plan9':
3674 keep.append(b'plan9')
3674 keep.append(b'plan9')
3675 else:
3675 else:
3676 keep.append(b'unix')
3676 keep.append(b'unix')
3677 keep.append(pycompat.sysplatform.lower())
3677 keep.append(pycompat.sysplatform.lower())
3678 if ui.verbose:
3678 if ui.verbose:
3679 keep.append(b'verbose')
3679 keep.append(b'verbose')
3680
3680
3681 commands = sys.modules[__name__]
3681 commands = sys.modules[__name__]
3682 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3682 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3683 ui.pager(b'help')
3683 ui.pager(b'help')
3684 ui.write(formatted)
3684 ui.write(formatted)
3685
3685
3686
3686
3687 @command(
3687 @command(
3688 b'identify|id',
3688 b'identify|id',
3689 [
3689 [
3690 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3690 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3691 (b'n', b'num', None, _(b'show local revision number')),
3691 (b'n', b'num', None, _(b'show local revision number')),
3692 (b'i', b'id', None, _(b'show global revision id')),
3692 (b'i', b'id', None, _(b'show global revision id')),
3693 (b'b', b'branch', None, _(b'show branch')),
3693 (b'b', b'branch', None, _(b'show branch')),
3694 (b't', b'tags', None, _(b'show tags')),
3694 (b't', b'tags', None, _(b'show tags')),
3695 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3695 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3696 ]
3696 ]
3697 + remoteopts
3697 + remoteopts
3698 + formatteropts,
3698 + formatteropts,
3699 _(b'[-nibtB] [-r REV] [SOURCE]'),
3699 _(b'[-nibtB] [-r REV] [SOURCE]'),
3700 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3700 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3701 optionalrepo=True,
3701 optionalrepo=True,
3702 intents={INTENT_READONLY},
3702 intents={INTENT_READONLY},
3703 )
3703 )
3704 def identify(
3704 def identify(
3705 ui,
3705 ui,
3706 repo,
3706 repo,
3707 source=None,
3707 source=None,
3708 rev=None,
3708 rev=None,
3709 num=None,
3709 num=None,
3710 id=None,
3710 id=None,
3711 branch=None,
3711 branch=None,
3712 tags=None,
3712 tags=None,
3713 bookmarks=None,
3713 bookmarks=None,
3714 **opts
3714 **opts
3715 ):
3715 ):
3716 """identify the working directory or specified revision
3716 """identify the working directory or specified revision
3717
3717
3718 Print a summary identifying the repository state at REV using one or
3718 Print a summary identifying the repository state at REV using one or
3719 two parent hash identifiers, followed by a "+" if the working
3719 two parent hash identifiers, followed by a "+" if the working
3720 directory has uncommitted changes, the branch name (if not default),
3720 directory has uncommitted changes, the branch name (if not default),
3721 a list of tags, and a list of bookmarks.
3721 a list of tags, and a list of bookmarks.
3722
3722
3723 When REV is not given, print a summary of the current state of the
3723 When REV is not given, print a summary of the current state of the
3724 repository including the working directory. Specify -r. to get information
3724 repository including the working directory. Specify -r. to get information
3725 of the working directory parent without scanning uncommitted changes.
3725 of the working directory parent without scanning uncommitted changes.
3726
3726
3727 Specifying a path to a repository root or Mercurial bundle will
3727 Specifying a path to a repository root or Mercurial bundle will
3728 cause lookup to operate on that repository/bundle.
3728 cause lookup to operate on that repository/bundle.
3729
3729
3730 .. container:: verbose
3730 .. container:: verbose
3731
3731
3732 Template:
3732 Template:
3733
3733
3734 The following keywords are supported in addition to the common template
3734 The following keywords are supported in addition to the common template
3735 keywords and functions. See also :hg:`help templates`.
3735 keywords and functions. See also :hg:`help templates`.
3736
3736
3737 :dirty: String. Character ``+`` denoting if the working directory has
3737 :dirty: String. Character ``+`` denoting if the working directory has
3738 uncommitted changes.
3738 uncommitted changes.
3739 :id: String. One or two nodes, optionally followed by ``+``.
3739 :id: String. One or two nodes, optionally followed by ``+``.
3740 :parents: List of strings. Parent nodes of the changeset.
3740 :parents: List of strings. Parent nodes of the changeset.
3741
3741
3742 Examples:
3742 Examples:
3743
3743
3744 - generate a build identifier for the working directory::
3744 - generate a build identifier for the working directory::
3745
3745
3746 hg id --id > build-id.dat
3746 hg id --id > build-id.dat
3747
3747
3748 - find the revision corresponding to a tag::
3748 - find the revision corresponding to a tag::
3749
3749
3750 hg id -n -r 1.3
3750 hg id -n -r 1.3
3751
3751
3752 - check the most recent revision of a remote repository::
3752 - check the most recent revision of a remote repository::
3753
3753
3754 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3754 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3755
3755
3756 See :hg:`log` for generating more information about specific revisions,
3756 See :hg:`log` for generating more information about specific revisions,
3757 including full hash identifiers.
3757 including full hash identifiers.
3758
3758
3759 Returns 0 if successful.
3759 Returns 0 if successful.
3760 """
3760 """
3761
3761
3762 opts = pycompat.byteskwargs(opts)
3762 opts = pycompat.byteskwargs(opts)
3763 if not repo and not source:
3763 if not repo and not source:
3764 raise error.Abort(
3764 raise error.Abort(
3765 _(b"there is no Mercurial repository here (.hg not found)")
3765 _(b"there is no Mercurial repository here (.hg not found)")
3766 )
3766 )
3767
3767
3768 default = not (num or id or branch or tags or bookmarks)
3768 default = not (num or id or branch or tags or bookmarks)
3769 output = []
3769 output = []
3770 revs = []
3770 revs = []
3771
3771
3772 if source:
3772 if source:
3773 source, branches = hg.parseurl(ui.expandpath(source))
3773 source, branches = hg.parseurl(ui.expandpath(source))
3774 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3774 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3775 repo = peer.local()
3775 repo = peer.local()
3776 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3776 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3777
3777
3778 fm = ui.formatter(b'identify', opts)
3778 fm = ui.formatter(b'identify', opts)
3779 fm.startitem()
3779 fm.startitem()
3780
3780
3781 if not repo:
3781 if not repo:
3782 if num or branch or tags:
3782 if num or branch or tags:
3783 raise error.Abort(
3783 raise error.Abort(
3784 _(b"can't query remote revision number, branch, or tags")
3784 _(b"can't query remote revision number, branch, or tags")
3785 )
3785 )
3786 if not rev and revs:
3786 if not rev and revs:
3787 rev = revs[0]
3787 rev = revs[0]
3788 if not rev:
3788 if not rev:
3789 rev = b"tip"
3789 rev = b"tip"
3790
3790
3791 remoterev = peer.lookup(rev)
3791 remoterev = peer.lookup(rev)
3792 hexrev = fm.hexfunc(remoterev)
3792 hexrev = fm.hexfunc(remoterev)
3793 if default or id:
3793 if default or id:
3794 output = [hexrev]
3794 output = [hexrev]
3795 fm.data(id=hexrev)
3795 fm.data(id=hexrev)
3796
3796
3797 @util.cachefunc
3797 @util.cachefunc
3798 def getbms():
3798 def getbms():
3799 bms = []
3799 bms = []
3800
3800
3801 if b'bookmarks' in peer.listkeys(b'namespaces'):
3801 if b'bookmarks' in peer.listkeys(b'namespaces'):
3802 hexremoterev = hex(remoterev)
3802 hexremoterev = hex(remoterev)
3803 bms = [
3803 bms = [
3804 bm
3804 bm
3805 for bm, bmr in pycompat.iteritems(
3805 for bm, bmr in pycompat.iteritems(
3806 peer.listkeys(b'bookmarks')
3806 peer.listkeys(b'bookmarks')
3807 )
3807 )
3808 if bmr == hexremoterev
3808 if bmr == hexremoterev
3809 ]
3809 ]
3810
3810
3811 return sorted(bms)
3811 return sorted(bms)
3812
3812
3813 if fm.isplain():
3813 if fm.isplain():
3814 if bookmarks:
3814 if bookmarks:
3815 output.extend(getbms())
3815 output.extend(getbms())
3816 elif default and not ui.quiet:
3816 elif default and not ui.quiet:
3817 # multiple bookmarks for a single parent separated by '/'
3817 # multiple bookmarks for a single parent separated by '/'
3818 bm = b'/'.join(getbms())
3818 bm = b'/'.join(getbms())
3819 if bm:
3819 if bm:
3820 output.append(bm)
3820 output.append(bm)
3821 else:
3821 else:
3822 fm.data(node=hex(remoterev))
3822 fm.data(node=hex(remoterev))
3823 if bookmarks or b'bookmarks' in fm.datahint():
3823 if bookmarks or b'bookmarks' in fm.datahint():
3824 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3824 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3825 else:
3825 else:
3826 if rev:
3826 if rev:
3827 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3827 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3828 ctx = scmutil.revsingle(repo, rev, None)
3828 ctx = scmutil.revsingle(repo, rev, None)
3829
3829
3830 if ctx.rev() is None:
3830 if ctx.rev() is None:
3831 ctx = repo[None]
3831 ctx = repo[None]
3832 parents = ctx.parents()
3832 parents = ctx.parents()
3833 taglist = []
3833 taglist = []
3834 for p in parents:
3834 for p in parents:
3835 taglist.extend(p.tags())
3835 taglist.extend(p.tags())
3836
3836
3837 dirty = b""
3837 dirty = b""
3838 if ctx.dirty(missing=True, merge=False, branch=False):
3838 if ctx.dirty(missing=True, merge=False, branch=False):
3839 dirty = b'+'
3839 dirty = b'+'
3840 fm.data(dirty=dirty)
3840 fm.data(dirty=dirty)
3841
3841
3842 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3842 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3843 if default or id:
3843 if default or id:
3844 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3844 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3845 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3845 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3846
3846
3847 if num:
3847 if num:
3848 numoutput = [b"%d" % p.rev() for p in parents]
3848 numoutput = [b"%d" % p.rev() for p in parents]
3849 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3849 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3850
3850
3851 fm.data(
3851 fm.data(
3852 parents=fm.formatlist(
3852 parents=fm.formatlist(
3853 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3853 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3854 )
3854 )
3855 )
3855 )
3856 else:
3856 else:
3857 hexoutput = fm.hexfunc(ctx.node())
3857 hexoutput = fm.hexfunc(ctx.node())
3858 if default or id:
3858 if default or id:
3859 output = [hexoutput]
3859 output = [hexoutput]
3860 fm.data(id=hexoutput)
3860 fm.data(id=hexoutput)
3861
3861
3862 if num:
3862 if num:
3863 output.append(pycompat.bytestr(ctx.rev()))
3863 output.append(pycompat.bytestr(ctx.rev()))
3864 taglist = ctx.tags()
3864 taglist = ctx.tags()
3865
3865
3866 if default and not ui.quiet:
3866 if default and not ui.quiet:
3867 b = ctx.branch()
3867 b = ctx.branch()
3868 if b != b'default':
3868 if b != b'default':
3869 output.append(b"(%s)" % b)
3869 output.append(b"(%s)" % b)
3870
3870
3871 # multiple tags for a single parent separated by '/'
3871 # multiple tags for a single parent separated by '/'
3872 t = b'/'.join(taglist)
3872 t = b'/'.join(taglist)
3873 if t:
3873 if t:
3874 output.append(t)
3874 output.append(t)
3875
3875
3876 # multiple bookmarks for a single parent separated by '/'
3876 # multiple bookmarks for a single parent separated by '/'
3877 bm = b'/'.join(ctx.bookmarks())
3877 bm = b'/'.join(ctx.bookmarks())
3878 if bm:
3878 if bm:
3879 output.append(bm)
3879 output.append(bm)
3880 else:
3880 else:
3881 if branch:
3881 if branch:
3882 output.append(ctx.branch())
3882 output.append(ctx.branch())
3883
3883
3884 if tags:
3884 if tags:
3885 output.extend(taglist)
3885 output.extend(taglist)
3886
3886
3887 if bookmarks:
3887 if bookmarks:
3888 output.extend(ctx.bookmarks())
3888 output.extend(ctx.bookmarks())
3889
3889
3890 fm.data(node=ctx.hex())
3890 fm.data(node=ctx.hex())
3891 fm.data(branch=ctx.branch())
3891 fm.data(branch=ctx.branch())
3892 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
3892 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
3893 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
3893 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
3894 fm.context(ctx=ctx)
3894 fm.context(ctx=ctx)
3895
3895
3896 fm.plain(b"%s\n" % b' '.join(output))
3896 fm.plain(b"%s\n" % b' '.join(output))
3897 fm.end()
3897 fm.end()
3898
3898
3899
3899
3900 @command(
3900 @command(
3901 b'import|patch',
3901 b'import|patch',
3902 [
3902 [
3903 (
3903 (
3904 b'p',
3904 b'p',
3905 b'strip',
3905 b'strip',
3906 1,
3906 1,
3907 _(
3907 _(
3908 b'directory strip option for patch. This has the same '
3908 b'directory strip option for patch. This has the same '
3909 b'meaning as the corresponding patch option'
3909 b'meaning as the corresponding patch option'
3910 ),
3910 ),
3911 _(b'NUM'),
3911 _(b'NUM'),
3912 ),
3912 ),
3913 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
3913 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
3914 (b'', b'secret', None, _(b'use the secret phase for committing')),
3914 (b'', b'secret', None, _(b'use the secret phase for committing')),
3915 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3915 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3916 (
3916 (
3917 b'f',
3917 b'f',
3918 b'force',
3918 b'force',
3919 None,
3919 None,
3920 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
3920 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
3921 ),
3921 ),
3922 (
3922 (
3923 b'',
3923 b'',
3924 b'no-commit',
3924 b'no-commit',
3925 None,
3925 None,
3926 _(b"don't commit, just update the working directory"),
3926 _(b"don't commit, just update the working directory"),
3927 ),
3927 ),
3928 (
3928 (
3929 b'',
3929 b'',
3930 b'bypass',
3930 b'bypass',
3931 None,
3931 None,
3932 _(b"apply patch without touching the working directory"),
3932 _(b"apply patch without touching the working directory"),
3933 ),
3933 ),
3934 (b'', b'partial', None, _(b'commit even if some hunks fail')),
3934 (b'', b'partial', None, _(b'commit even if some hunks fail')),
3935 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
3935 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
3936 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
3936 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
3937 (
3937 (
3938 b'',
3938 b'',
3939 b'import-branch',
3939 b'import-branch',
3940 None,
3940 None,
3941 _(b'use any branch information in patch (implied by --exact)'),
3941 _(b'use any branch information in patch (implied by --exact)'),
3942 ),
3942 ),
3943 ]
3943 ]
3944 + commitopts
3944 + commitopts
3945 + commitopts2
3945 + commitopts2
3946 + similarityopts,
3946 + similarityopts,
3947 _(b'[OPTION]... PATCH...'),
3947 _(b'[OPTION]... PATCH...'),
3948 helpcategory=command.CATEGORY_IMPORT_EXPORT,
3948 helpcategory=command.CATEGORY_IMPORT_EXPORT,
3949 )
3949 )
3950 def import_(ui, repo, patch1=None, *patches, **opts):
3950 def import_(ui, repo, patch1=None, *patches, **opts):
3951 """import an ordered set of patches
3951 """import an ordered set of patches
3952
3952
3953 Import a list of patches and commit them individually (unless
3953 Import a list of patches and commit them individually (unless
3954 --no-commit is specified).
3954 --no-commit is specified).
3955
3955
3956 To read a patch from standard input (stdin), use "-" as the patch
3956 To read a patch from standard input (stdin), use "-" as the patch
3957 name. If a URL is specified, the patch will be downloaded from
3957 name. If a URL is specified, the patch will be downloaded from
3958 there.
3958 there.
3959
3959
3960 Import first applies changes to the working directory (unless
3960 Import first applies changes to the working directory (unless
3961 --bypass is specified), import will abort if there are outstanding
3961 --bypass is specified), import will abort if there are outstanding
3962 changes.
3962 changes.
3963
3963
3964 Use --bypass to apply and commit patches directly to the
3964 Use --bypass to apply and commit patches directly to the
3965 repository, without affecting the working directory. Without
3965 repository, without affecting the working directory. Without
3966 --exact, patches will be applied on top of the working directory
3966 --exact, patches will be applied on top of the working directory
3967 parent revision.
3967 parent revision.
3968
3968
3969 You can import a patch straight from a mail message. Even patches
3969 You can import a patch straight from a mail message. Even patches
3970 as attachments work (to use the body part, it must have type
3970 as attachments work (to use the body part, it must have type
3971 text/plain or text/x-patch). From and Subject headers of email
3971 text/plain or text/x-patch). From and Subject headers of email
3972 message are used as default committer and commit message. All
3972 message are used as default committer and commit message. All
3973 text/plain body parts before first diff are added to the commit
3973 text/plain body parts before first diff are added to the commit
3974 message.
3974 message.
3975
3975
3976 If the imported patch was generated by :hg:`export`, user and
3976 If the imported patch was generated by :hg:`export`, user and
3977 description from patch override values from message headers and
3977 description from patch override values from message headers and
3978 body. Values given on command line with -m/--message and -u/--user
3978 body. Values given on command line with -m/--message and -u/--user
3979 override these.
3979 override these.
3980
3980
3981 If --exact is specified, import will set the working directory to
3981 If --exact is specified, import will set the working directory to
3982 the parent of each patch before applying it, and will abort if the
3982 the parent of each patch before applying it, and will abort if the
3983 resulting changeset has a different ID than the one recorded in
3983 resulting changeset has a different ID than the one recorded in
3984 the patch. This will guard against various ways that portable
3984 the patch. This will guard against various ways that portable
3985 patch formats and mail systems might fail to transfer Mercurial
3985 patch formats and mail systems might fail to transfer Mercurial
3986 data or metadata. See :hg:`bundle` for lossless transmission.
3986 data or metadata. See :hg:`bundle` for lossless transmission.
3987
3987
3988 Use --partial to ensure a changeset will be created from the patch
3988 Use --partial to ensure a changeset will be created from the patch
3989 even if some hunks fail to apply. Hunks that fail to apply will be
3989 even if some hunks fail to apply. Hunks that fail to apply will be
3990 written to a <target-file>.rej file. Conflicts can then be resolved
3990 written to a <target-file>.rej file. Conflicts can then be resolved
3991 by hand before :hg:`commit --amend` is run to update the created
3991 by hand before :hg:`commit --amend` is run to update the created
3992 changeset. This flag exists to let people import patches that
3992 changeset. This flag exists to let people import patches that
3993 partially apply without losing the associated metadata (author,
3993 partially apply without losing the associated metadata (author,
3994 date, description, ...).
3994 date, description, ...).
3995
3995
3996 .. note::
3996 .. note::
3997
3997
3998 When no hunks apply cleanly, :hg:`import --partial` will create
3998 When no hunks apply cleanly, :hg:`import --partial` will create
3999 an empty changeset, importing only the patch metadata.
3999 an empty changeset, importing only the patch metadata.
4000
4000
4001 With -s/--similarity, hg will attempt to discover renames and
4001 With -s/--similarity, hg will attempt to discover renames and
4002 copies in the patch in the same way as :hg:`addremove`.
4002 copies in the patch in the same way as :hg:`addremove`.
4003
4003
4004 It is possible to use external patch programs to perform the patch
4004 It is possible to use external patch programs to perform the patch
4005 by setting the ``ui.patch`` configuration option. For the default
4005 by setting the ``ui.patch`` configuration option. For the default
4006 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4006 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4007 See :hg:`help config` for more information about configuration
4007 See :hg:`help config` for more information about configuration
4008 files and how to use these options.
4008 files and how to use these options.
4009
4009
4010 See :hg:`help dates` for a list of formats valid for -d/--date.
4010 See :hg:`help dates` for a list of formats valid for -d/--date.
4011
4011
4012 .. container:: verbose
4012 .. container:: verbose
4013
4013
4014 Examples:
4014 Examples:
4015
4015
4016 - import a traditional patch from a website and detect renames::
4016 - import a traditional patch from a website and detect renames::
4017
4017
4018 hg import -s 80 http://example.com/bugfix.patch
4018 hg import -s 80 http://example.com/bugfix.patch
4019
4019
4020 - import a changeset from an hgweb server::
4020 - import a changeset from an hgweb server::
4021
4021
4022 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4022 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4023
4023
4024 - import all the patches in an Unix-style mbox::
4024 - import all the patches in an Unix-style mbox::
4025
4025
4026 hg import incoming-patches.mbox
4026 hg import incoming-patches.mbox
4027
4027
4028 - import patches from stdin::
4028 - import patches from stdin::
4029
4029
4030 hg import -
4030 hg import -
4031
4031
4032 - attempt to exactly restore an exported changeset (not always
4032 - attempt to exactly restore an exported changeset (not always
4033 possible)::
4033 possible)::
4034
4034
4035 hg import --exact proposed-fix.patch
4035 hg import --exact proposed-fix.patch
4036
4036
4037 - use an external tool to apply a patch which is too fuzzy for
4037 - use an external tool to apply a patch which is too fuzzy for
4038 the default internal tool.
4038 the default internal tool.
4039
4039
4040 hg import --config ui.patch="patch --merge" fuzzy.patch
4040 hg import --config ui.patch="patch --merge" fuzzy.patch
4041
4041
4042 - change the default fuzzing from 2 to a less strict 7
4042 - change the default fuzzing from 2 to a less strict 7
4043
4043
4044 hg import --config ui.fuzz=7 fuzz.patch
4044 hg import --config ui.fuzz=7 fuzz.patch
4045
4045
4046 Returns 0 on success, 1 on partial success (see --partial).
4046 Returns 0 on success, 1 on partial success (see --partial).
4047 """
4047 """
4048
4048
4049 cmdutil.check_incompatible_arguments(
4049 cmdutil.check_incompatible_arguments(
4050 opts, 'no_commit', ['bypass', 'secret']
4050 opts, 'no_commit', ['bypass', 'secret']
4051 )
4051 )
4052 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4052 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4053 opts = pycompat.byteskwargs(opts)
4053 opts = pycompat.byteskwargs(opts)
4054 if not patch1:
4054 if not patch1:
4055 raise error.Abort(_(b'need at least one patch to import'))
4055 raise error.Abort(_(b'need at least one patch to import'))
4056
4056
4057 patches = (patch1,) + patches
4057 patches = (patch1,) + patches
4058
4058
4059 date = opts.get(b'date')
4059 date = opts.get(b'date')
4060 if date:
4060 if date:
4061 opts[b'date'] = dateutil.parsedate(date)
4061 opts[b'date'] = dateutil.parsedate(date)
4062
4062
4063 exact = opts.get(b'exact')
4063 exact = opts.get(b'exact')
4064 update = not opts.get(b'bypass')
4064 update = not opts.get(b'bypass')
4065 try:
4065 try:
4066 sim = float(opts.get(b'similarity') or 0)
4066 sim = float(opts.get(b'similarity') or 0)
4067 except ValueError:
4067 except ValueError:
4068 raise error.Abort(_(b'similarity must be a number'))
4068 raise error.Abort(_(b'similarity must be a number'))
4069 if sim < 0 or sim > 100:
4069 if sim < 0 or sim > 100:
4070 raise error.Abort(_(b'similarity must be between 0 and 100'))
4070 raise error.Abort(_(b'similarity must be between 0 and 100'))
4071 if sim and not update:
4071 if sim and not update:
4072 raise error.Abort(_(b'cannot use --similarity with --bypass'))
4072 raise error.Abort(_(b'cannot use --similarity with --bypass'))
4073
4073
4074 base = opts[b"base"]
4074 base = opts[b"base"]
4075 msgs = []
4075 msgs = []
4076 ret = 0
4076 ret = 0
4077
4077
4078 with repo.wlock():
4078 with repo.wlock():
4079 if update:
4079 if update:
4080 cmdutil.checkunfinished(repo)
4080 cmdutil.checkunfinished(repo)
4081 if exact or not opts.get(b'force'):
4081 if exact or not opts.get(b'force'):
4082 cmdutil.bailifchanged(repo)
4082 cmdutil.bailifchanged(repo)
4083
4083
4084 if not opts.get(b'no_commit'):
4084 if not opts.get(b'no_commit'):
4085 lock = repo.lock
4085 lock = repo.lock
4086 tr = lambda: repo.transaction(b'import')
4086 tr = lambda: repo.transaction(b'import')
4087 dsguard = util.nullcontextmanager
4087 dsguard = util.nullcontextmanager
4088 else:
4088 else:
4089 lock = util.nullcontextmanager
4089 lock = util.nullcontextmanager
4090 tr = util.nullcontextmanager
4090 tr = util.nullcontextmanager
4091 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4091 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4092 with lock(), tr(), dsguard():
4092 with lock(), tr(), dsguard():
4093 parents = repo[None].parents()
4093 parents = repo[None].parents()
4094 for patchurl in patches:
4094 for patchurl in patches:
4095 if patchurl == b'-':
4095 if patchurl == b'-':
4096 ui.status(_(b'applying patch from stdin\n'))
4096 ui.status(_(b'applying patch from stdin\n'))
4097 patchfile = ui.fin
4097 patchfile = ui.fin
4098 patchurl = b'stdin' # for error message
4098 patchurl = b'stdin' # for error message
4099 else:
4099 else:
4100 patchurl = os.path.join(base, patchurl)
4100 patchurl = os.path.join(base, patchurl)
4101 ui.status(_(b'applying %s\n') % patchurl)
4101 ui.status(_(b'applying %s\n') % patchurl)
4102 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4102 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4103
4103
4104 haspatch = False
4104 haspatch = False
4105 for hunk in patch.split(patchfile):
4105 for hunk in patch.split(patchfile):
4106 with patch.extract(ui, hunk) as patchdata:
4106 with patch.extract(ui, hunk) as patchdata:
4107 msg, node, rej = cmdutil.tryimportone(
4107 msg, node, rej = cmdutil.tryimportone(
4108 ui, repo, patchdata, parents, opts, msgs, hg.clean
4108 ui, repo, patchdata, parents, opts, msgs, hg.clean
4109 )
4109 )
4110 if msg:
4110 if msg:
4111 haspatch = True
4111 haspatch = True
4112 ui.note(msg + b'\n')
4112 ui.note(msg + b'\n')
4113 if update or exact:
4113 if update or exact:
4114 parents = repo[None].parents()
4114 parents = repo[None].parents()
4115 else:
4115 else:
4116 parents = [repo[node]]
4116 parents = [repo[node]]
4117 if rej:
4117 if rej:
4118 ui.write_err(_(b"patch applied partially\n"))
4118 ui.write_err(_(b"patch applied partially\n"))
4119 ui.write_err(
4119 ui.write_err(
4120 _(
4120 _(
4121 b"(fix the .rej files and run "
4121 b"(fix the .rej files and run "
4122 b"`hg commit --amend`)\n"
4122 b"`hg commit --amend`)\n"
4123 )
4123 )
4124 )
4124 )
4125 ret = 1
4125 ret = 1
4126 break
4126 break
4127
4127
4128 if not haspatch:
4128 if not haspatch:
4129 raise error.Abort(_(b'%s: no diffs found') % patchurl)
4129 raise error.Abort(_(b'%s: no diffs found') % patchurl)
4130
4130
4131 if msgs:
4131 if msgs:
4132 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4132 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4133 return ret
4133 return ret
4134
4134
4135
4135
4136 @command(
4136 @command(
4137 b'incoming|in',
4137 b'incoming|in',
4138 [
4138 [
4139 (
4139 (
4140 b'f',
4140 b'f',
4141 b'force',
4141 b'force',
4142 None,
4142 None,
4143 _(b'run even if remote repository is unrelated'),
4143 _(b'run even if remote repository is unrelated'),
4144 ),
4144 ),
4145 (b'n', b'newest-first', None, _(b'show newest record first')),
4145 (b'n', b'newest-first', None, _(b'show newest record first')),
4146 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4146 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4147 (
4147 (
4148 b'r',
4148 b'r',
4149 b'rev',
4149 b'rev',
4150 [],
4150 [],
4151 _(b'a remote changeset intended to be added'),
4151 _(b'a remote changeset intended to be added'),
4152 _(b'REV'),
4152 _(b'REV'),
4153 ),
4153 ),
4154 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4154 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4155 (
4155 (
4156 b'b',
4156 b'b',
4157 b'branch',
4157 b'branch',
4158 [],
4158 [],
4159 _(b'a specific branch you would like to pull'),
4159 _(b'a specific branch you would like to pull'),
4160 _(b'BRANCH'),
4160 _(b'BRANCH'),
4161 ),
4161 ),
4162 ]
4162 ]
4163 + logopts
4163 + logopts
4164 + remoteopts
4164 + remoteopts
4165 + subrepoopts,
4165 + subrepoopts,
4166 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4166 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4167 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4167 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4168 )
4168 )
4169 def incoming(ui, repo, source=b"default", **opts):
4169 def incoming(ui, repo, source=b"default", **opts):
4170 """show new changesets found in source
4170 """show new changesets found in source
4171
4171
4172 Show new changesets found in the specified path/URL or the default
4172 Show new changesets found in the specified path/URL or the default
4173 pull location. These are the changesets that would have been pulled
4173 pull location. These are the changesets that would have been pulled
4174 by :hg:`pull` at the time you issued this command.
4174 by :hg:`pull` at the time you issued this command.
4175
4175
4176 See pull for valid source format details.
4176 See pull for valid source format details.
4177
4177
4178 .. container:: verbose
4178 .. container:: verbose
4179
4179
4180 With -B/--bookmarks, the result of bookmark comparison between
4180 With -B/--bookmarks, the result of bookmark comparison between
4181 local and remote repositories is displayed. With -v/--verbose,
4181 local and remote repositories is displayed. With -v/--verbose,
4182 status is also displayed for each bookmark like below::
4182 status is also displayed for each bookmark like below::
4183
4183
4184 BM1 01234567890a added
4184 BM1 01234567890a added
4185 BM2 1234567890ab advanced
4185 BM2 1234567890ab advanced
4186 BM3 234567890abc diverged
4186 BM3 234567890abc diverged
4187 BM4 34567890abcd changed
4187 BM4 34567890abcd changed
4188
4188
4189 The action taken locally when pulling depends on the
4189 The action taken locally when pulling depends on the
4190 status of each bookmark:
4190 status of each bookmark:
4191
4191
4192 :``added``: pull will create it
4192 :``added``: pull will create it
4193 :``advanced``: pull will update it
4193 :``advanced``: pull will update it
4194 :``diverged``: pull will create a divergent bookmark
4194 :``diverged``: pull will create a divergent bookmark
4195 :``changed``: result depends on remote changesets
4195 :``changed``: result depends on remote changesets
4196
4196
4197 From the point of view of pulling behavior, bookmark
4197 From the point of view of pulling behavior, bookmark
4198 existing only in the remote repository are treated as ``added``,
4198 existing only in the remote repository are treated as ``added``,
4199 even if it is in fact locally deleted.
4199 even if it is in fact locally deleted.
4200
4200
4201 .. container:: verbose
4201 .. container:: verbose
4202
4202
4203 For remote repository, using --bundle avoids downloading the
4203 For remote repository, using --bundle avoids downloading the
4204 changesets twice if the incoming is followed by a pull.
4204 changesets twice if the incoming is followed by a pull.
4205
4205
4206 Examples:
4206 Examples:
4207
4207
4208 - show incoming changes with patches and full description::
4208 - show incoming changes with patches and full description::
4209
4209
4210 hg incoming -vp
4210 hg incoming -vp
4211
4211
4212 - show incoming changes excluding merges, store a bundle::
4212 - show incoming changes excluding merges, store a bundle::
4213
4213
4214 hg in -vpM --bundle incoming.hg
4214 hg in -vpM --bundle incoming.hg
4215 hg pull incoming.hg
4215 hg pull incoming.hg
4216
4216
4217 - briefly list changes inside a bundle::
4217 - briefly list changes inside a bundle::
4218
4218
4219 hg in changes.hg -T "{desc|firstline}\\n"
4219 hg in changes.hg -T "{desc|firstline}\\n"
4220
4220
4221 Returns 0 if there are incoming changes, 1 otherwise.
4221 Returns 0 if there are incoming changes, 1 otherwise.
4222 """
4222 """
4223 opts = pycompat.byteskwargs(opts)
4223 opts = pycompat.byteskwargs(opts)
4224 if opts.get(b'graph'):
4224 if opts.get(b'graph'):
4225 logcmdutil.checkunsupportedgraphflags([], opts)
4225 logcmdutil.checkunsupportedgraphflags([], opts)
4226
4226
4227 def display(other, chlist, displayer):
4227 def display(other, chlist, displayer):
4228 revdag = logcmdutil.graphrevs(other, chlist, opts)
4228 revdag = logcmdutil.graphrevs(other, chlist, opts)
4229 logcmdutil.displaygraph(
4229 logcmdutil.displaygraph(
4230 ui, repo, revdag, displayer, graphmod.asciiedges
4230 ui, repo, revdag, displayer, graphmod.asciiedges
4231 )
4231 )
4232
4232
4233 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4233 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4234 return 0
4234 return 0
4235
4235
4236 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4236 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4237
4237
4238 if opts.get(b'bookmarks'):
4238 if opts.get(b'bookmarks'):
4239 source, branches = hg.parseurl(
4239 source, branches = hg.parseurl(
4240 ui.expandpath(source), opts.get(b'branch')
4240 ui.expandpath(source), opts.get(b'branch')
4241 )
4241 )
4242 other = hg.peer(repo, opts, source)
4242 other = hg.peer(repo, opts, source)
4243 if b'bookmarks' not in other.listkeys(b'namespaces'):
4243 if b'bookmarks' not in other.listkeys(b'namespaces'):
4244 ui.warn(_(b"remote doesn't support bookmarks\n"))
4244 ui.warn(_(b"remote doesn't support bookmarks\n"))
4245 return 0
4245 return 0
4246 ui.pager(b'incoming')
4246 ui.pager(b'incoming')
4247 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4247 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4248 return bookmarks.incoming(ui, repo, other)
4248 return bookmarks.incoming(ui, repo, other)
4249
4249
4250 repo._subtoppath = ui.expandpath(source)
4250 repo._subtoppath = ui.expandpath(source)
4251 try:
4251 try:
4252 return hg.incoming(ui, repo, source, opts)
4252 return hg.incoming(ui, repo, source, opts)
4253 finally:
4253 finally:
4254 del repo._subtoppath
4254 del repo._subtoppath
4255
4255
4256
4256
4257 @command(
4257 @command(
4258 b'init',
4258 b'init',
4259 remoteopts,
4259 remoteopts,
4260 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4260 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4261 helpcategory=command.CATEGORY_REPO_CREATION,
4261 helpcategory=command.CATEGORY_REPO_CREATION,
4262 helpbasic=True,
4262 helpbasic=True,
4263 norepo=True,
4263 norepo=True,
4264 )
4264 )
4265 def init(ui, dest=b".", **opts):
4265 def init(ui, dest=b".", **opts):
4266 """create a new repository in the given directory
4266 """create a new repository in the given directory
4267
4267
4268 Initialize a new repository in the given directory. If the given
4268 Initialize a new repository in the given directory. If the given
4269 directory does not exist, it will be created.
4269 directory does not exist, it will be created.
4270
4270
4271 If no directory is given, the current directory is used.
4271 If no directory is given, the current directory is used.
4272
4272
4273 It is possible to specify an ``ssh://`` URL as the destination.
4273 It is possible to specify an ``ssh://`` URL as the destination.
4274 See :hg:`help urls` for more information.
4274 See :hg:`help urls` for more information.
4275
4275
4276 Returns 0 on success.
4276 Returns 0 on success.
4277 """
4277 """
4278 opts = pycompat.byteskwargs(opts)
4278 opts = pycompat.byteskwargs(opts)
4279 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4279 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4280
4280
4281
4281
4282 @command(
4282 @command(
4283 b'locate',
4283 b'locate',
4284 [
4284 [
4285 (
4285 (
4286 b'r',
4286 b'r',
4287 b'rev',
4287 b'rev',
4288 b'',
4288 b'',
4289 _(b'search the repository as it is in REV'),
4289 _(b'search the repository as it is in REV'),
4290 _(b'REV'),
4290 _(b'REV'),
4291 ),
4291 ),
4292 (
4292 (
4293 b'0',
4293 b'0',
4294 b'print0',
4294 b'print0',
4295 None,
4295 None,
4296 _(b'end filenames with NUL, for use with xargs'),
4296 _(b'end filenames with NUL, for use with xargs'),
4297 ),
4297 ),
4298 (
4298 (
4299 b'f',
4299 b'f',
4300 b'fullpath',
4300 b'fullpath',
4301 None,
4301 None,
4302 _(b'print complete paths from the filesystem root'),
4302 _(b'print complete paths from the filesystem root'),
4303 ),
4303 ),
4304 ]
4304 ]
4305 + walkopts,
4305 + walkopts,
4306 _(b'[OPTION]... [PATTERN]...'),
4306 _(b'[OPTION]... [PATTERN]...'),
4307 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4307 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4308 )
4308 )
4309 def locate(ui, repo, *pats, **opts):
4309 def locate(ui, repo, *pats, **opts):
4310 """locate files matching specific patterns (DEPRECATED)
4310 """locate files matching specific patterns (DEPRECATED)
4311
4311
4312 Print files under Mercurial control in the working directory whose
4312 Print files under Mercurial control in the working directory whose
4313 names match the given patterns.
4313 names match the given patterns.
4314
4314
4315 By default, this command searches all directories in the working
4315 By default, this command searches all directories in the working
4316 directory. To search just the current directory and its
4316 directory. To search just the current directory and its
4317 subdirectories, use "--include .".
4317 subdirectories, use "--include .".
4318
4318
4319 If no patterns are given to match, this command prints the names
4319 If no patterns are given to match, this command prints the names
4320 of all files under Mercurial control in the working directory.
4320 of all files under Mercurial control in the working directory.
4321
4321
4322 If you want to feed the output of this command into the "xargs"
4322 If you want to feed the output of this command into the "xargs"
4323 command, use the -0 option to both this command and "xargs". This
4323 command, use the -0 option to both this command and "xargs". This
4324 will avoid the problem of "xargs" treating single filenames that
4324 will avoid the problem of "xargs" treating single filenames that
4325 contain whitespace as multiple filenames.
4325 contain whitespace as multiple filenames.
4326
4326
4327 See :hg:`help files` for a more versatile command.
4327 See :hg:`help files` for a more versatile command.
4328
4328
4329 Returns 0 if a match is found, 1 otherwise.
4329 Returns 0 if a match is found, 1 otherwise.
4330 """
4330 """
4331 opts = pycompat.byteskwargs(opts)
4331 opts = pycompat.byteskwargs(opts)
4332 if opts.get(b'print0'):
4332 if opts.get(b'print0'):
4333 end = b'\0'
4333 end = b'\0'
4334 else:
4334 else:
4335 end = b'\n'
4335 end = b'\n'
4336 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4336 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4337
4337
4338 ret = 1
4338 ret = 1
4339 m = scmutil.match(
4339 m = scmutil.match(
4340 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4340 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4341 )
4341 )
4342
4342
4343 ui.pager(b'locate')
4343 ui.pager(b'locate')
4344 if ctx.rev() is None:
4344 if ctx.rev() is None:
4345 # When run on the working copy, "locate" includes removed files, so
4345 # When run on the working copy, "locate" includes removed files, so
4346 # we get the list of files from the dirstate.
4346 # we get the list of files from the dirstate.
4347 filesgen = sorted(repo.dirstate.matches(m))
4347 filesgen = sorted(repo.dirstate.matches(m))
4348 else:
4348 else:
4349 filesgen = ctx.matches(m)
4349 filesgen = ctx.matches(m)
4350 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4350 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4351 for abs in filesgen:
4351 for abs in filesgen:
4352 if opts.get(b'fullpath'):
4352 if opts.get(b'fullpath'):
4353 ui.write(repo.wjoin(abs), end)
4353 ui.write(repo.wjoin(abs), end)
4354 else:
4354 else:
4355 ui.write(uipathfn(abs), end)
4355 ui.write(uipathfn(abs), end)
4356 ret = 0
4356 ret = 0
4357
4357
4358 return ret
4358 return ret
4359
4359
4360
4360
4361 @command(
4361 @command(
4362 b'log|history',
4362 b'log|history',
4363 [
4363 [
4364 (
4364 (
4365 b'f',
4365 b'f',
4366 b'follow',
4366 b'follow',
4367 None,
4367 None,
4368 _(
4368 _(
4369 b'follow changeset history, or file history across copies and renames'
4369 b'follow changeset history, or file history across copies and renames'
4370 ),
4370 ),
4371 ),
4371 ),
4372 (
4372 (
4373 b'',
4373 b'',
4374 b'follow-first',
4374 b'follow-first',
4375 None,
4375 None,
4376 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4376 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4377 ),
4377 ),
4378 (
4378 (
4379 b'd',
4379 b'd',
4380 b'date',
4380 b'date',
4381 b'',
4381 b'',
4382 _(b'show revisions matching date spec'),
4382 _(b'show revisions matching date spec'),
4383 _(b'DATE'),
4383 _(b'DATE'),
4384 ),
4384 ),
4385 (b'C', b'copies', None, _(b'show copied files')),
4385 (b'C', b'copies', None, _(b'show copied files')),
4386 (
4386 (
4387 b'k',
4387 b'k',
4388 b'keyword',
4388 b'keyword',
4389 [],
4389 [],
4390 _(b'do case-insensitive search for a given text'),
4390 _(b'do case-insensitive search for a given text'),
4391 _(b'TEXT'),
4391 _(b'TEXT'),
4392 ),
4392 ),
4393 (
4393 (
4394 b'r',
4394 b'r',
4395 b'rev',
4395 b'rev',
4396 [],
4396 [],
4397 _(b'show the specified revision or revset'),
4397 _(b'show the specified revision or revset'),
4398 _(b'REV'),
4398 _(b'REV'),
4399 ),
4399 ),
4400 (
4400 (
4401 b'L',
4401 b'L',
4402 b'line-range',
4402 b'line-range',
4403 [],
4403 [],
4404 _(b'follow line range of specified file (EXPERIMENTAL)'),
4404 _(b'follow line range of specified file (EXPERIMENTAL)'),
4405 _(b'FILE,RANGE'),
4405 _(b'FILE,RANGE'),
4406 ),
4406 ),
4407 (
4407 (
4408 b'',
4408 b'',
4409 b'removed',
4409 b'removed',
4410 None,
4410 None,
4411 _(b'include revisions where files were removed'),
4411 _(b'include revisions where files were removed'),
4412 ),
4412 ),
4413 (
4413 (
4414 b'm',
4414 b'm',
4415 b'only-merges',
4415 b'only-merges',
4416 None,
4416 None,
4417 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4417 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4418 ),
4418 ),
4419 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4419 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4420 (
4420 (
4421 b'',
4421 b'',
4422 b'only-branch',
4422 b'only-branch',
4423 [],
4423 [],
4424 _(
4424 _(
4425 b'show only changesets within the given named branch (DEPRECATED)'
4425 b'show only changesets within the given named branch (DEPRECATED)'
4426 ),
4426 ),
4427 _(b'BRANCH'),
4427 _(b'BRANCH'),
4428 ),
4428 ),
4429 (
4429 (
4430 b'b',
4430 b'b',
4431 b'branch',
4431 b'branch',
4432 [],
4432 [],
4433 _(b'show changesets within the given named branch'),
4433 _(b'show changesets within the given named branch'),
4434 _(b'BRANCH'),
4434 _(b'BRANCH'),
4435 ),
4435 ),
4436 (
4436 (
4437 b'P',
4437 b'P',
4438 b'prune',
4438 b'prune',
4439 [],
4439 [],
4440 _(b'do not display revision or any of its ancestors'),
4440 _(b'do not display revision or any of its ancestors'),
4441 _(b'REV'),
4441 _(b'REV'),
4442 ),
4442 ),
4443 ]
4443 ]
4444 + logopts
4444 + logopts
4445 + walkopts,
4445 + walkopts,
4446 _(b'[OPTION]... [FILE]'),
4446 _(b'[OPTION]... [FILE]'),
4447 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4447 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4448 helpbasic=True,
4448 helpbasic=True,
4449 inferrepo=True,
4449 inferrepo=True,
4450 intents={INTENT_READONLY},
4450 intents={INTENT_READONLY},
4451 )
4451 )
4452 def log(ui, repo, *pats, **opts):
4452 def log(ui, repo, *pats, **opts):
4453 """show revision history of entire repository or files
4453 """show revision history of entire repository or files
4454
4454
4455 Print the revision history of the specified files or the entire
4455 Print the revision history of the specified files or the entire
4456 project.
4456 project.
4457
4457
4458 If no revision range is specified, the default is ``tip:0`` unless
4458 If no revision range is specified, the default is ``tip:0`` unless
4459 --follow is set, in which case the working directory parent is
4459 --follow is set, in which case the working directory parent is
4460 used as the starting revision.
4460 used as the starting revision.
4461
4461
4462 File history is shown without following rename or copy history of
4462 File history is shown without following rename or copy history of
4463 files. Use -f/--follow with a filename to follow history across
4463 files. Use -f/--follow with a filename to follow history across
4464 renames and copies. --follow without a filename will only show
4464 renames and copies. --follow without a filename will only show
4465 ancestors of the starting revision.
4465 ancestors of the starting revision.
4466
4466
4467 By default this command prints revision number and changeset id,
4467 By default this command prints revision number and changeset id,
4468 tags, non-trivial parents, user, date and time, and a summary for
4468 tags, non-trivial parents, user, date and time, and a summary for
4469 each commit. When the -v/--verbose switch is used, the list of
4469 each commit. When the -v/--verbose switch is used, the list of
4470 changed files and full commit message are shown.
4470 changed files and full commit message are shown.
4471
4471
4472 With --graph the revisions are shown as an ASCII art DAG with the most
4472 With --graph the revisions are shown as an ASCII art DAG with the most
4473 recent changeset at the top.
4473 recent changeset at the top.
4474 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4474 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4475 involved in an unresolved merge conflict, '_' closes a branch,
4475 involved in an unresolved merge conflict, '_' closes a branch,
4476 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4476 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4477 changeset from the lines below is a parent of the 'o' merge on the same
4477 changeset from the lines below is a parent of the 'o' merge on the same
4478 line.
4478 line.
4479 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4479 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4480 of a '|' indicates one or more revisions in a path are omitted.
4480 of a '|' indicates one or more revisions in a path are omitted.
4481
4481
4482 .. container:: verbose
4482 .. container:: verbose
4483
4483
4484 Use -L/--line-range FILE,M:N options to follow the history of lines
4484 Use -L/--line-range FILE,M:N options to follow the history of lines
4485 from M to N in FILE. With -p/--patch only diff hunks affecting
4485 from M to N in FILE. With -p/--patch only diff hunks affecting
4486 specified line range will be shown. This option requires --follow;
4486 specified line range will be shown. This option requires --follow;
4487 it can be specified multiple times. Currently, this option is not
4487 it can be specified multiple times. Currently, this option is not
4488 compatible with --graph. This option is experimental.
4488 compatible with --graph. This option is experimental.
4489
4489
4490 .. note::
4490 .. note::
4491
4491
4492 :hg:`log --patch` may generate unexpected diff output for merge
4492 :hg:`log --patch` may generate unexpected diff output for merge
4493 changesets, as it will only compare the merge changeset against
4493 changesets, as it will only compare the merge changeset against
4494 its first parent. Also, only files different from BOTH parents
4494 its first parent. Also, only files different from BOTH parents
4495 will appear in files:.
4495 will appear in files:.
4496
4496
4497 .. note::
4497 .. note::
4498
4498
4499 For performance reasons, :hg:`log FILE` may omit duplicate changes
4499 For performance reasons, :hg:`log FILE` may omit duplicate changes
4500 made on branches and will not show removals or mode changes. To
4500 made on branches and will not show removals or mode changes. To
4501 see all such changes, use the --removed switch.
4501 see all such changes, use the --removed switch.
4502
4502
4503 .. container:: verbose
4503 .. container:: verbose
4504
4504
4505 .. note::
4505 .. note::
4506
4506
4507 The history resulting from -L/--line-range options depends on diff
4507 The history resulting from -L/--line-range options depends on diff
4508 options; for instance if white-spaces are ignored, respective changes
4508 options; for instance if white-spaces are ignored, respective changes
4509 with only white-spaces in specified line range will not be listed.
4509 with only white-spaces in specified line range will not be listed.
4510
4510
4511 .. container:: verbose
4511 .. container:: verbose
4512
4512
4513 Some examples:
4513 Some examples:
4514
4514
4515 - changesets with full descriptions and file lists::
4515 - changesets with full descriptions and file lists::
4516
4516
4517 hg log -v
4517 hg log -v
4518
4518
4519 - changesets ancestral to the working directory::
4519 - changesets ancestral to the working directory::
4520
4520
4521 hg log -f
4521 hg log -f
4522
4522
4523 - last 10 commits on the current branch::
4523 - last 10 commits on the current branch::
4524
4524
4525 hg log -l 10 -b .
4525 hg log -l 10 -b .
4526
4526
4527 - changesets showing all modifications of a file, including removals::
4527 - changesets showing all modifications of a file, including removals::
4528
4528
4529 hg log --removed file.c
4529 hg log --removed file.c
4530
4530
4531 - all changesets that touch a directory, with diffs, excluding merges::
4531 - all changesets that touch a directory, with diffs, excluding merges::
4532
4532
4533 hg log -Mp lib/
4533 hg log -Mp lib/
4534
4534
4535 - all revision numbers that match a keyword::
4535 - all revision numbers that match a keyword::
4536
4536
4537 hg log -k bug --template "{rev}\\n"
4537 hg log -k bug --template "{rev}\\n"
4538
4538
4539 - the full hash identifier of the working directory parent::
4539 - the full hash identifier of the working directory parent::
4540
4540
4541 hg log -r . --template "{node}\\n"
4541 hg log -r . --template "{node}\\n"
4542
4542
4543 - list available log templates::
4543 - list available log templates::
4544
4544
4545 hg log -T list
4545 hg log -T list
4546
4546
4547 - check if a given changeset is included in a tagged release::
4547 - check if a given changeset is included in a tagged release::
4548
4548
4549 hg log -r "a21ccf and ancestor(1.9)"
4549 hg log -r "a21ccf and ancestor(1.9)"
4550
4550
4551 - find all changesets by some user in a date range::
4551 - find all changesets by some user in a date range::
4552
4552
4553 hg log -k alice -d "may 2008 to jul 2008"
4553 hg log -k alice -d "may 2008 to jul 2008"
4554
4554
4555 - summary of all changesets after the last tag::
4555 - summary of all changesets after the last tag::
4556
4556
4557 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4557 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4558
4558
4559 - changesets touching lines 13 to 23 for file.c::
4559 - changesets touching lines 13 to 23 for file.c::
4560
4560
4561 hg log -L file.c,13:23
4561 hg log -L file.c,13:23
4562
4562
4563 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4563 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4564 main.c with patch::
4564 main.c with patch::
4565
4565
4566 hg log -L file.c,13:23 -L main.c,2:6 -p
4566 hg log -L file.c,13:23 -L main.c,2:6 -p
4567
4567
4568 See :hg:`help dates` for a list of formats valid for -d/--date.
4568 See :hg:`help dates` for a list of formats valid for -d/--date.
4569
4569
4570 See :hg:`help revisions` for more about specifying and ordering
4570 See :hg:`help revisions` for more about specifying and ordering
4571 revisions.
4571 revisions.
4572
4572
4573 See :hg:`help templates` for more about pre-packaged styles and
4573 See :hg:`help templates` for more about pre-packaged styles and
4574 specifying custom templates. The default template used by the log
4574 specifying custom templates. The default template used by the log
4575 command can be customized via the ``command-templates.log`` configuration
4575 command can be customized via the ``command-templates.log`` configuration
4576 setting.
4576 setting.
4577
4577
4578 Returns 0 on success.
4578 Returns 0 on success.
4579
4579
4580 """
4580 """
4581 opts = pycompat.byteskwargs(opts)
4581 opts = pycompat.byteskwargs(opts)
4582 linerange = opts.get(b'line_range')
4582 linerange = opts.get(b'line_range')
4583
4583
4584 if linerange and not opts.get(b'follow'):
4584 if linerange and not opts.get(b'follow'):
4585 raise error.Abort(_(b'--line-range requires --follow'))
4585 raise error.Abort(_(b'--line-range requires --follow'))
4586
4586
4587 if linerange and pats:
4587 if linerange and pats:
4588 # TODO: take pats as patterns with no line-range filter
4588 # TODO: take pats as patterns with no line-range filter
4589 raise error.Abort(
4589 raise error.Abort(
4590 _(b'FILE arguments are not compatible with --line-range option')
4590 _(b'FILE arguments are not compatible with --line-range option')
4591 )
4591 )
4592
4592
4593 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4593 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4594 revs, differ = logcmdutil.getrevs(
4594 revs, differ = logcmdutil.getrevs(
4595 repo, logcmdutil.parseopts(ui, pats, opts)
4595 repo, logcmdutil.parseopts(ui, pats, opts)
4596 )
4596 )
4597 if linerange:
4597 if linerange:
4598 # TODO: should follow file history from logcmdutil._initialrevs(),
4598 # TODO: should follow file history from logcmdutil._initialrevs(),
4599 # then filter the result by logcmdutil._makerevset() and --limit
4599 # then filter the result by logcmdutil._makerevset() and --limit
4600 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4600 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4601
4601
4602 getcopies = None
4602 getcopies = None
4603 if opts.get(b'copies'):
4603 if opts.get(b'copies'):
4604 endrev = None
4604 endrev = None
4605 if revs:
4605 if revs:
4606 endrev = revs.max() + 1
4606 endrev = revs.max() + 1
4607 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4607 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4608
4608
4609 ui.pager(b'log')
4609 ui.pager(b'log')
4610 displayer = logcmdutil.changesetdisplayer(
4610 displayer = logcmdutil.changesetdisplayer(
4611 ui, repo, opts, differ, buffered=True
4611 ui, repo, opts, differ, buffered=True
4612 )
4612 )
4613 if opts.get(b'graph'):
4613 if opts.get(b'graph'):
4614 displayfn = logcmdutil.displaygraphrevs
4614 displayfn = logcmdutil.displaygraphrevs
4615 else:
4615 else:
4616 displayfn = logcmdutil.displayrevs
4616 displayfn = logcmdutil.displayrevs
4617 displayfn(ui, repo, revs, displayer, getcopies)
4617 displayfn(ui, repo, revs, displayer, getcopies)
4618
4618
4619
4619
4620 @command(
4620 @command(
4621 b'manifest',
4621 b'manifest',
4622 [
4622 [
4623 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4623 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4624 (b'', b'all', False, _(b"list files from all revisions")),
4624 (b'', b'all', False, _(b"list files from all revisions")),
4625 ]
4625 ]
4626 + formatteropts,
4626 + formatteropts,
4627 _(b'[-r REV]'),
4627 _(b'[-r REV]'),
4628 helpcategory=command.CATEGORY_MAINTENANCE,
4628 helpcategory=command.CATEGORY_MAINTENANCE,
4629 intents={INTENT_READONLY},
4629 intents={INTENT_READONLY},
4630 )
4630 )
4631 def manifest(ui, repo, node=None, rev=None, **opts):
4631 def manifest(ui, repo, node=None, rev=None, **opts):
4632 """output the current or given revision of the project manifest
4632 """output the current or given revision of the project manifest
4633
4633
4634 Print a list of version controlled files for the given revision.
4634 Print a list of version controlled files for the given revision.
4635 If no revision is given, the first parent of the working directory
4635 If no revision is given, the first parent of the working directory
4636 is used, or the null revision if no revision is checked out.
4636 is used, or the null revision if no revision is checked out.
4637
4637
4638 With -v, print file permissions, symlink and executable bits.
4638 With -v, print file permissions, symlink and executable bits.
4639 With --debug, print file revision hashes.
4639 With --debug, print file revision hashes.
4640
4640
4641 If option --all is specified, the list of all files from all revisions
4641 If option --all is specified, the list of all files from all revisions
4642 is printed. This includes deleted and renamed files.
4642 is printed. This includes deleted and renamed files.
4643
4643
4644 Returns 0 on success.
4644 Returns 0 on success.
4645 """
4645 """
4646 opts = pycompat.byteskwargs(opts)
4646 opts = pycompat.byteskwargs(opts)
4647 fm = ui.formatter(b'manifest', opts)
4647 fm = ui.formatter(b'manifest', opts)
4648
4648
4649 if opts.get(b'all'):
4649 if opts.get(b'all'):
4650 if rev or node:
4650 if rev or node:
4651 raise error.Abort(_(b"can't specify a revision with --all"))
4651 raise error.Abort(_(b"can't specify a revision with --all"))
4652
4652
4653 res = set()
4653 res = set()
4654 for rev in repo:
4654 for rev in repo:
4655 ctx = repo[rev]
4655 ctx = repo[rev]
4656 res |= set(ctx.files())
4656 res |= set(ctx.files())
4657
4657
4658 ui.pager(b'manifest')
4658 ui.pager(b'manifest')
4659 for f in sorted(res):
4659 for f in sorted(res):
4660 fm.startitem()
4660 fm.startitem()
4661 fm.write(b"path", b'%s\n', f)
4661 fm.write(b"path", b'%s\n', f)
4662 fm.end()
4662 fm.end()
4663 return
4663 return
4664
4664
4665 if rev and node:
4665 if rev and node:
4666 raise error.Abort(_(b"please specify just one revision"))
4666 raise error.Abort(_(b"please specify just one revision"))
4667
4667
4668 if not node:
4668 if not node:
4669 node = rev
4669 node = rev
4670
4670
4671 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4671 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4672 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4672 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4673 if node:
4673 if node:
4674 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4674 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4675 ctx = scmutil.revsingle(repo, node)
4675 ctx = scmutil.revsingle(repo, node)
4676 mf = ctx.manifest()
4676 mf = ctx.manifest()
4677 ui.pager(b'manifest')
4677 ui.pager(b'manifest')
4678 for f in ctx:
4678 for f in ctx:
4679 fm.startitem()
4679 fm.startitem()
4680 fm.context(ctx=ctx)
4680 fm.context(ctx=ctx)
4681 fl = ctx[f].flags()
4681 fl = ctx[f].flags()
4682 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4682 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4683 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4683 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4684 fm.write(b'path', b'%s\n', f)
4684 fm.write(b'path', b'%s\n', f)
4685 fm.end()
4685 fm.end()
4686
4686
4687
4687
4688 @command(
4688 @command(
4689 b'merge',
4689 b'merge',
4690 [
4690 [
4691 (
4691 (
4692 b'f',
4692 b'f',
4693 b'force',
4693 b'force',
4694 None,
4694 None,
4695 _(b'force a merge including outstanding changes (DEPRECATED)'),
4695 _(b'force a merge including outstanding changes (DEPRECATED)'),
4696 ),
4696 ),
4697 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4697 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4698 (
4698 (
4699 b'P',
4699 b'P',
4700 b'preview',
4700 b'preview',
4701 None,
4701 None,
4702 _(b'review revisions to merge (no merge is performed)'),
4702 _(b'review revisions to merge (no merge is performed)'),
4703 ),
4703 ),
4704 (b'', b'abort', None, _(b'abort the ongoing merge')),
4704 (b'', b'abort', None, _(b'abort the ongoing merge')),
4705 ]
4705 ]
4706 + mergetoolopts,
4706 + mergetoolopts,
4707 _(b'[-P] [[-r] REV]'),
4707 _(b'[-P] [[-r] REV]'),
4708 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4708 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4709 helpbasic=True,
4709 helpbasic=True,
4710 )
4710 )
4711 def merge(ui, repo, node=None, **opts):
4711 def merge(ui, repo, node=None, **opts):
4712 """merge another revision into working directory
4712 """merge another revision into working directory
4713
4713
4714 The current working directory is updated with all changes made in
4714 The current working directory is updated with all changes made in
4715 the requested revision since the last common predecessor revision.
4715 the requested revision since the last common predecessor revision.
4716
4716
4717 Files that changed between either parent are marked as changed for
4717 Files that changed between either parent are marked as changed for
4718 the next commit and a commit must be performed before any further
4718 the next commit and a commit must be performed before any further
4719 updates to the repository are allowed. The next commit will have
4719 updates to the repository are allowed. The next commit will have
4720 two parents.
4720 two parents.
4721
4721
4722 ``--tool`` can be used to specify the merge tool used for file
4722 ``--tool`` can be used to specify the merge tool used for file
4723 merges. It overrides the HGMERGE environment variable and your
4723 merges. It overrides the HGMERGE environment variable and your
4724 configuration files. See :hg:`help merge-tools` for options.
4724 configuration files. See :hg:`help merge-tools` for options.
4725
4725
4726 If no revision is specified, the working directory's parent is a
4726 If no revision is specified, the working directory's parent is a
4727 head revision, and the current branch contains exactly one other
4727 head revision, and the current branch contains exactly one other
4728 head, the other head is merged with by default. Otherwise, an
4728 head, the other head is merged with by default. Otherwise, an
4729 explicit revision with which to merge must be provided.
4729 explicit revision with which to merge must be provided.
4730
4730
4731 See :hg:`help resolve` for information on handling file conflicts.
4731 See :hg:`help resolve` for information on handling file conflicts.
4732
4732
4733 To undo an uncommitted merge, use :hg:`merge --abort` which
4733 To undo an uncommitted merge, use :hg:`merge --abort` which
4734 will check out a clean copy of the original merge parent, losing
4734 will check out a clean copy of the original merge parent, losing
4735 all changes.
4735 all changes.
4736
4736
4737 Returns 0 on success, 1 if there are unresolved files.
4737 Returns 0 on success, 1 if there are unresolved files.
4738 """
4738 """
4739
4739
4740 opts = pycompat.byteskwargs(opts)
4740 opts = pycompat.byteskwargs(opts)
4741 abort = opts.get(b'abort')
4741 abort = opts.get(b'abort')
4742 if abort and repo.dirstate.p2() == nullid:
4742 if abort and repo.dirstate.p2() == nullid:
4743 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4743 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4744 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4744 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4745 if abort:
4745 if abort:
4746 state = cmdutil.getunfinishedstate(repo)
4746 state = cmdutil.getunfinishedstate(repo)
4747 if state and state._opname != b'merge':
4747 if state and state._opname != b'merge':
4748 raise error.Abort(
4748 raise error.Abort(
4749 _(b'cannot abort merge with %s in progress') % (state._opname),
4749 _(b'cannot abort merge with %s in progress') % (state._opname),
4750 hint=state.hint(),
4750 hint=state.hint(),
4751 )
4751 )
4752 if node:
4752 if node:
4753 raise error.Abort(_(b"cannot specify a node with --abort"))
4753 raise error.Abort(_(b"cannot specify a node with --abort"))
4754 return hg.abortmerge(repo.ui, repo)
4754 return hg.abortmerge(repo.ui, repo)
4755
4755
4756 if opts.get(b'rev') and node:
4756 if opts.get(b'rev') and node:
4757 raise error.Abort(_(b"please specify just one revision"))
4757 raise error.Abort(_(b"please specify just one revision"))
4758 if not node:
4758 if not node:
4759 node = opts.get(b'rev')
4759 node = opts.get(b'rev')
4760
4760
4761 if node:
4761 if node:
4762 ctx = scmutil.revsingle(repo, node)
4762 ctx = scmutil.revsingle(repo, node)
4763 else:
4763 else:
4764 if ui.configbool(b'commands', b'merge.require-rev'):
4764 if ui.configbool(b'commands', b'merge.require-rev'):
4765 raise error.Abort(
4765 raise error.Abort(
4766 _(
4766 _(
4767 b'configuration requires specifying revision to merge '
4767 b'configuration requires specifying revision to merge '
4768 b'with'
4768 b'with'
4769 )
4769 )
4770 )
4770 )
4771 ctx = repo[destutil.destmerge(repo)]
4771 ctx = repo[destutil.destmerge(repo)]
4772
4772
4773 if ctx.node() is None:
4773 if ctx.node() is None:
4774 raise error.Abort(_(b'merging with the working copy has no effect'))
4774 raise error.Abort(_(b'merging with the working copy has no effect'))
4775
4775
4776 if opts.get(b'preview'):
4776 if opts.get(b'preview'):
4777 # find nodes that are ancestors of p2 but not of p1
4777 # find nodes that are ancestors of p2 but not of p1
4778 p1 = repo[b'.'].node()
4778 p1 = repo[b'.'].node()
4779 p2 = ctx.node()
4779 p2 = ctx.node()
4780 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4780 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4781
4781
4782 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4782 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4783 for node in nodes:
4783 for node in nodes:
4784 displayer.show(repo[node])
4784 displayer.show(repo[node])
4785 displayer.close()
4785 displayer.close()
4786 return 0
4786 return 0
4787
4787
4788 # ui.forcemerge is an internal variable, do not document
4788 # ui.forcemerge is an internal variable, do not document
4789 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4789 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4790 with ui.configoverride(overrides, b'merge'):
4790 with ui.configoverride(overrides, b'merge'):
4791 force = opts.get(b'force')
4791 force = opts.get(b'force')
4792 labels = [b'working copy', b'merge rev']
4792 labels = [b'working copy', b'merge rev']
4793 return hg.merge(ctx, force=force, labels=labels)
4793 return hg.merge(ctx, force=force, labels=labels)
4794
4794
4795
4795
4796 statemod.addunfinished(
4796 statemod.addunfinished(
4797 b'merge',
4797 b'merge',
4798 fname=None,
4798 fname=None,
4799 clearable=True,
4799 clearable=True,
4800 allowcommit=True,
4800 allowcommit=True,
4801 cmdmsg=_(b'outstanding uncommitted merge'),
4801 cmdmsg=_(b'outstanding uncommitted merge'),
4802 abortfunc=hg.abortmerge,
4802 abortfunc=hg.abortmerge,
4803 statushint=_(
4803 statushint=_(
4804 b'To continue: hg commit\nTo abort: hg merge --abort'
4804 b'To continue: hg commit\nTo abort: hg merge --abort'
4805 ),
4805 ),
4806 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4806 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4807 )
4807 )
4808
4808
4809
4809
4810 @command(
4810 @command(
4811 b'outgoing|out',
4811 b'outgoing|out',
4812 [
4812 [
4813 (
4813 (
4814 b'f',
4814 b'f',
4815 b'force',
4815 b'force',
4816 None,
4816 None,
4817 _(b'run even when the destination is unrelated'),
4817 _(b'run even when the destination is unrelated'),
4818 ),
4818 ),
4819 (
4819 (
4820 b'r',
4820 b'r',
4821 b'rev',
4821 b'rev',
4822 [],
4822 [],
4823 _(b'a changeset intended to be included in the destination'),
4823 _(b'a changeset intended to be included in the destination'),
4824 _(b'REV'),
4824 _(b'REV'),
4825 ),
4825 ),
4826 (b'n', b'newest-first', None, _(b'show newest record first')),
4826 (b'n', b'newest-first', None, _(b'show newest record first')),
4827 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4827 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4828 (
4828 (
4829 b'b',
4829 b'b',
4830 b'branch',
4830 b'branch',
4831 [],
4831 [],
4832 _(b'a specific branch you would like to push'),
4832 _(b'a specific branch you would like to push'),
4833 _(b'BRANCH'),
4833 _(b'BRANCH'),
4834 ),
4834 ),
4835 ]
4835 ]
4836 + logopts
4836 + logopts
4837 + remoteopts
4837 + remoteopts
4838 + subrepoopts,
4838 + subrepoopts,
4839 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4839 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4840 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4840 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4841 )
4841 )
4842 def outgoing(ui, repo, dest=None, **opts):
4842 def outgoing(ui, repo, dest=None, **opts):
4843 """show changesets not found in the destination
4843 """show changesets not found in the destination
4844
4844
4845 Show changesets not found in the specified destination repository
4845 Show changesets not found in the specified destination repository
4846 or the default push location. These are the changesets that would
4846 or the default push location. These are the changesets that would
4847 be pushed if a push was requested.
4847 be pushed if a push was requested.
4848
4848
4849 See pull for details of valid destination formats.
4849 See pull for details of valid destination formats.
4850
4850
4851 .. container:: verbose
4851 .. container:: verbose
4852
4852
4853 With -B/--bookmarks, the result of bookmark comparison between
4853 With -B/--bookmarks, the result of bookmark comparison between
4854 local and remote repositories is displayed. With -v/--verbose,
4854 local and remote repositories is displayed. With -v/--verbose,
4855 status is also displayed for each bookmark like below::
4855 status is also displayed for each bookmark like below::
4856
4856
4857 BM1 01234567890a added
4857 BM1 01234567890a added
4858 BM2 deleted
4858 BM2 deleted
4859 BM3 234567890abc advanced
4859 BM3 234567890abc advanced
4860 BM4 34567890abcd diverged
4860 BM4 34567890abcd diverged
4861 BM5 4567890abcde changed
4861 BM5 4567890abcde changed
4862
4862
4863 The action taken when pushing depends on the
4863 The action taken when pushing depends on the
4864 status of each bookmark:
4864 status of each bookmark:
4865
4865
4866 :``added``: push with ``-B`` will create it
4866 :``added``: push with ``-B`` will create it
4867 :``deleted``: push with ``-B`` will delete it
4867 :``deleted``: push with ``-B`` will delete it
4868 :``advanced``: push will update it
4868 :``advanced``: push will update it
4869 :``diverged``: push with ``-B`` will update it
4869 :``diverged``: push with ``-B`` will update it
4870 :``changed``: push with ``-B`` will update it
4870 :``changed``: push with ``-B`` will update it
4871
4871
4872 From the point of view of pushing behavior, bookmarks
4872 From the point of view of pushing behavior, bookmarks
4873 existing only in the remote repository are treated as
4873 existing only in the remote repository are treated as
4874 ``deleted``, even if it is in fact added remotely.
4874 ``deleted``, even if it is in fact added remotely.
4875
4875
4876 Returns 0 if there are outgoing changes, 1 otherwise.
4876 Returns 0 if there are outgoing changes, 1 otherwise.
4877 """
4877 """
4878 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4878 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4879 # style URLs, so don't overwrite dest.
4879 # style URLs, so don't overwrite dest.
4880 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
4880 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
4881 if not path:
4881 if not path:
4882 raise error.Abort(
4882 raise error.Abort(
4883 _(b'default repository not configured!'),
4883 _(b'default repository not configured!'),
4884 hint=_(b"see 'hg help config.paths'"),
4884 hint=_(b"see 'hg help config.paths'"),
4885 )
4885 )
4886
4886
4887 opts = pycompat.byteskwargs(opts)
4887 opts = pycompat.byteskwargs(opts)
4888 if opts.get(b'graph'):
4888 if opts.get(b'graph'):
4889 logcmdutil.checkunsupportedgraphflags([], opts)
4889 logcmdutil.checkunsupportedgraphflags([], opts)
4890 o, other = hg._outgoing(ui, repo, dest, opts)
4890 o, other = hg._outgoing(ui, repo, dest, opts)
4891 if not o:
4891 if not o:
4892 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4892 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4893 return
4893 return
4894
4894
4895 revdag = logcmdutil.graphrevs(repo, o, opts)
4895 revdag = logcmdutil.graphrevs(repo, o, opts)
4896 ui.pager(b'outgoing')
4896 ui.pager(b'outgoing')
4897 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4897 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4898 logcmdutil.displaygraph(
4898 logcmdutil.displaygraph(
4899 ui, repo, revdag, displayer, graphmod.asciiedges
4899 ui, repo, revdag, displayer, graphmod.asciiedges
4900 )
4900 )
4901 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4901 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4902 return 0
4902 return 0
4903
4903
4904 if opts.get(b'bookmarks'):
4904 if opts.get(b'bookmarks'):
4905 dest = path.pushloc or path.loc
4905 dest = path.pushloc or path.loc
4906 other = hg.peer(repo, opts, dest)
4906 other = hg.peer(repo, opts, dest)
4907 if b'bookmarks' not in other.listkeys(b'namespaces'):
4907 if b'bookmarks' not in other.listkeys(b'namespaces'):
4908 ui.warn(_(b"remote doesn't support bookmarks\n"))
4908 ui.warn(_(b"remote doesn't support bookmarks\n"))
4909 return 0
4909 return 0
4910 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
4910 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
4911 ui.pager(b'outgoing')
4911 ui.pager(b'outgoing')
4912 return bookmarks.outgoing(ui, repo, other)
4912 return bookmarks.outgoing(ui, repo, other)
4913
4913
4914 repo._subtoppath = path.pushloc or path.loc
4914 repo._subtoppath = path.pushloc or path.loc
4915 try:
4915 try:
4916 return hg.outgoing(ui, repo, dest, opts)
4916 return hg.outgoing(ui, repo, dest, opts)
4917 finally:
4917 finally:
4918 del repo._subtoppath
4918 del repo._subtoppath
4919
4919
4920
4920
4921 @command(
4921 @command(
4922 b'parents',
4922 b'parents',
4923 [
4923 [
4924 (
4924 (
4925 b'r',
4925 b'r',
4926 b'rev',
4926 b'rev',
4927 b'',
4927 b'',
4928 _(b'show parents of the specified revision'),
4928 _(b'show parents of the specified revision'),
4929 _(b'REV'),
4929 _(b'REV'),
4930 ),
4930 ),
4931 ]
4931 ]
4932 + templateopts,
4932 + templateopts,
4933 _(b'[-r REV] [FILE]'),
4933 _(b'[-r REV] [FILE]'),
4934 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4934 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4935 inferrepo=True,
4935 inferrepo=True,
4936 )
4936 )
4937 def parents(ui, repo, file_=None, **opts):
4937 def parents(ui, repo, file_=None, **opts):
4938 """show the parents of the working directory or revision (DEPRECATED)
4938 """show the parents of the working directory or revision (DEPRECATED)
4939
4939
4940 Print the working directory's parent revisions. If a revision is
4940 Print the working directory's parent revisions. If a revision is
4941 given via -r/--rev, the parent of that revision will be printed.
4941 given via -r/--rev, the parent of that revision will be printed.
4942 If a file argument is given, the revision in which the file was
4942 If a file argument is given, the revision in which the file was
4943 last changed (before the working directory revision or the
4943 last changed (before the working directory revision or the
4944 argument to --rev if given) is printed.
4944 argument to --rev if given) is printed.
4945
4945
4946 This command is equivalent to::
4946 This command is equivalent to::
4947
4947
4948 hg log -r "p1()+p2()" or
4948 hg log -r "p1()+p2()" or
4949 hg log -r "p1(REV)+p2(REV)" or
4949 hg log -r "p1(REV)+p2(REV)" or
4950 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
4950 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
4951 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
4951 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
4952
4952
4953 See :hg:`summary` and :hg:`help revsets` for related information.
4953 See :hg:`summary` and :hg:`help revsets` for related information.
4954
4954
4955 Returns 0 on success.
4955 Returns 0 on success.
4956 """
4956 """
4957
4957
4958 opts = pycompat.byteskwargs(opts)
4958 opts = pycompat.byteskwargs(opts)
4959 rev = opts.get(b'rev')
4959 rev = opts.get(b'rev')
4960 if rev:
4960 if rev:
4961 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
4961 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
4962 ctx = scmutil.revsingle(repo, rev, None)
4962 ctx = scmutil.revsingle(repo, rev, None)
4963
4963
4964 if file_:
4964 if file_:
4965 m = scmutil.match(ctx, (file_,), opts)
4965 m = scmutil.match(ctx, (file_,), opts)
4966 if m.anypats() or len(m.files()) != 1:
4966 if m.anypats() or len(m.files()) != 1:
4967 raise error.Abort(_(b'can only specify an explicit filename'))
4967 raise error.Abort(_(b'can only specify an explicit filename'))
4968 file_ = m.files()[0]
4968 file_ = m.files()[0]
4969 filenodes = []
4969 filenodes = []
4970 for cp in ctx.parents():
4970 for cp in ctx.parents():
4971 if not cp:
4971 if not cp:
4972 continue
4972 continue
4973 try:
4973 try:
4974 filenodes.append(cp.filenode(file_))
4974 filenodes.append(cp.filenode(file_))
4975 except error.LookupError:
4975 except error.LookupError:
4976 pass
4976 pass
4977 if not filenodes:
4977 if not filenodes:
4978 raise error.Abort(_(b"'%s' not found in manifest!") % file_)
4978 raise error.Abort(_(b"'%s' not found in manifest!") % file_)
4979 p = []
4979 p = []
4980 for fn in filenodes:
4980 for fn in filenodes:
4981 fctx = repo.filectx(file_, fileid=fn)
4981 fctx = repo.filectx(file_, fileid=fn)
4982 p.append(fctx.node())
4982 p.append(fctx.node())
4983 else:
4983 else:
4984 p = [cp.node() for cp in ctx.parents()]
4984 p = [cp.node() for cp in ctx.parents()]
4985
4985
4986 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4986 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4987 for n in p:
4987 for n in p:
4988 if n != nullid:
4988 if n != nullid:
4989 displayer.show(repo[n])
4989 displayer.show(repo[n])
4990 displayer.close()
4990 displayer.close()
4991
4991
4992
4992
4993 @command(
4993 @command(
4994 b'paths',
4994 b'paths',
4995 formatteropts,
4995 formatteropts,
4996 _(b'[NAME]'),
4996 _(b'[NAME]'),
4997 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4997 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4998 optionalrepo=True,
4998 optionalrepo=True,
4999 intents={INTENT_READONLY},
4999 intents={INTENT_READONLY},
5000 )
5000 )
5001 def paths(ui, repo, search=None, **opts):
5001 def paths(ui, repo, search=None, **opts):
5002 """show aliases for remote repositories
5002 """show aliases for remote repositories
5003
5003
5004 Show definition of symbolic path name NAME. If no name is given,
5004 Show definition of symbolic path name NAME. If no name is given,
5005 show definition of all available names.
5005 show definition of all available names.
5006
5006
5007 Option -q/--quiet suppresses all output when searching for NAME
5007 Option -q/--quiet suppresses all output when searching for NAME
5008 and shows only the path names when listing all definitions.
5008 and shows only the path names when listing all definitions.
5009
5009
5010 Path names are defined in the [paths] section of your
5010 Path names are defined in the [paths] section of your
5011 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5011 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5012 repository, ``.hg/hgrc`` is used, too.
5012 repository, ``.hg/hgrc`` is used, too.
5013
5013
5014 The path names ``default`` and ``default-push`` have a special
5014 The path names ``default`` and ``default-push`` have a special
5015 meaning. When performing a push or pull operation, they are used
5015 meaning. When performing a push or pull operation, they are used
5016 as fallbacks if no location is specified on the command-line.
5016 as fallbacks if no location is specified on the command-line.
5017 When ``default-push`` is set, it will be used for push and
5017 When ``default-push`` is set, it will be used for push and
5018 ``default`` will be used for pull; otherwise ``default`` is used
5018 ``default`` will be used for pull; otherwise ``default`` is used
5019 as the fallback for both. When cloning a repository, the clone
5019 as the fallback for both. When cloning a repository, the clone
5020 source is written as ``default`` in ``.hg/hgrc``.
5020 source is written as ``default`` in ``.hg/hgrc``.
5021
5021
5022 .. note::
5022 .. note::
5023
5023
5024 ``default`` and ``default-push`` apply to all inbound (e.g.
5024 ``default`` and ``default-push`` apply to all inbound (e.g.
5025 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5025 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5026 and :hg:`bundle`) operations.
5026 and :hg:`bundle`) operations.
5027
5027
5028 See :hg:`help urls` for more information.
5028 See :hg:`help urls` for more information.
5029
5029
5030 .. container:: verbose
5030 .. container:: verbose
5031
5031
5032 Template:
5032 Template:
5033
5033
5034 The following keywords are supported. See also :hg:`help templates`.
5034 The following keywords are supported. See also :hg:`help templates`.
5035
5035
5036 :name: String. Symbolic name of the path alias.
5036 :name: String. Symbolic name of the path alias.
5037 :pushurl: String. URL for push operations.
5037 :pushurl: String. URL for push operations.
5038 :url: String. URL or directory path for the other operations.
5038 :url: String. URL or directory path for the other operations.
5039
5039
5040 Returns 0 on success.
5040 Returns 0 on success.
5041 """
5041 """
5042
5042
5043 opts = pycompat.byteskwargs(opts)
5043 opts = pycompat.byteskwargs(opts)
5044 ui.pager(b'paths')
5044 ui.pager(b'paths')
5045 if search:
5045 if search:
5046 pathitems = [
5046 pathitems = [
5047 (name, path)
5047 (name, path)
5048 for name, path in pycompat.iteritems(ui.paths)
5048 for name, path in pycompat.iteritems(ui.paths)
5049 if name == search
5049 if name == search
5050 ]
5050 ]
5051 else:
5051 else:
5052 pathitems = sorted(pycompat.iteritems(ui.paths))
5052 pathitems = sorted(pycompat.iteritems(ui.paths))
5053
5053
5054 fm = ui.formatter(b'paths', opts)
5054 fm = ui.formatter(b'paths', opts)
5055 if fm.isplain():
5055 if fm.isplain():
5056 hidepassword = util.hidepassword
5056 hidepassword = util.hidepassword
5057 else:
5057 else:
5058 hidepassword = bytes
5058 hidepassword = bytes
5059 if ui.quiet:
5059 if ui.quiet:
5060 namefmt = b'%s\n'
5060 namefmt = b'%s\n'
5061 else:
5061 else:
5062 namefmt = b'%s = '
5062 namefmt = b'%s = '
5063 showsubopts = not search and not ui.quiet
5063 showsubopts = not search and not ui.quiet
5064
5064
5065 for name, path in pathitems:
5065 for name, path in pathitems:
5066 fm.startitem()
5066 fm.startitem()
5067 fm.condwrite(not search, b'name', namefmt, name)
5067 fm.condwrite(not search, b'name', namefmt, name)
5068 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5068 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5069 for subopt, value in sorted(path.suboptions.items()):
5069 for subopt, value in sorted(path.suboptions.items()):
5070 assert subopt not in (b'name', b'url')
5070 assert subopt not in (b'name', b'url')
5071 if showsubopts:
5071 if showsubopts:
5072 fm.plain(b'%s:%s = ' % (name, subopt))
5072 fm.plain(b'%s:%s = ' % (name, subopt))
5073 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5073 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5074
5074
5075 fm.end()
5075 fm.end()
5076
5076
5077 if search and not pathitems:
5077 if search and not pathitems:
5078 if not ui.quiet:
5078 if not ui.quiet:
5079 ui.warn(_(b"not found!\n"))
5079 ui.warn(_(b"not found!\n"))
5080 return 1
5080 return 1
5081 else:
5081 else:
5082 return 0
5082 return 0
5083
5083
5084
5084
5085 @command(
5085 @command(
5086 b'phase',
5086 b'phase',
5087 [
5087 [
5088 (b'p', b'public', False, _(b'set changeset phase to public')),
5088 (b'p', b'public', False, _(b'set changeset phase to public')),
5089 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5089 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5090 (b's', b'secret', False, _(b'set changeset phase to secret')),
5090 (b's', b'secret', False, _(b'set changeset phase to secret')),
5091 (b'f', b'force', False, _(b'allow to move boundary backward')),
5091 (b'f', b'force', False, _(b'allow to move boundary backward')),
5092 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5092 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5093 ],
5093 ],
5094 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5094 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5095 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5095 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5096 )
5096 )
5097 def phase(ui, repo, *revs, **opts):
5097 def phase(ui, repo, *revs, **opts):
5098 """set or show the current phase name
5098 """set or show the current phase name
5099
5099
5100 With no argument, show the phase name of the current revision(s).
5100 With no argument, show the phase name of the current revision(s).
5101
5101
5102 With one of -p/--public, -d/--draft or -s/--secret, change the
5102 With one of -p/--public, -d/--draft or -s/--secret, change the
5103 phase value of the specified revisions.
5103 phase value of the specified revisions.
5104
5104
5105 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5105 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5106 lower phase to a higher phase. Phases are ordered as follows::
5106 lower phase to a higher phase. Phases are ordered as follows::
5107
5107
5108 public < draft < secret
5108 public < draft < secret
5109
5109
5110 Returns 0 on success, 1 if some phases could not be changed.
5110 Returns 0 on success, 1 if some phases could not be changed.
5111
5111
5112 (For more information about the phases concept, see :hg:`help phases`.)
5112 (For more information about the phases concept, see :hg:`help phases`.)
5113 """
5113 """
5114 opts = pycompat.byteskwargs(opts)
5114 opts = pycompat.byteskwargs(opts)
5115 # search for a unique phase argument
5115 # search for a unique phase argument
5116 targetphase = None
5116 targetphase = None
5117 for idx, name in enumerate(phases.cmdphasenames):
5117 for idx, name in enumerate(phases.cmdphasenames):
5118 if opts[name]:
5118 if opts[name]:
5119 if targetphase is not None:
5119 if targetphase is not None:
5120 raise error.Abort(_(b'only one phase can be specified'))
5120 raise error.Abort(_(b'only one phase can be specified'))
5121 targetphase = idx
5121 targetphase = idx
5122
5122
5123 # look for specified revision
5123 # look for specified revision
5124 revs = list(revs)
5124 revs = list(revs)
5125 revs.extend(opts[b'rev'])
5125 revs.extend(opts[b'rev'])
5126 if not revs:
5126 if not revs:
5127 # display both parents as the second parent phase can influence
5127 # display both parents as the second parent phase can influence
5128 # the phase of a merge commit
5128 # the phase of a merge commit
5129 revs = [c.rev() for c in repo[None].parents()]
5129 revs = [c.rev() for c in repo[None].parents()]
5130
5130
5131 revs = scmutil.revrange(repo, revs)
5131 revs = scmutil.revrange(repo, revs)
5132
5132
5133 ret = 0
5133 ret = 0
5134 if targetphase is None:
5134 if targetphase is None:
5135 # display
5135 # display
5136 for r in revs:
5136 for r in revs:
5137 ctx = repo[r]
5137 ctx = repo[r]
5138 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5138 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5139 else:
5139 else:
5140 with repo.lock(), repo.transaction(b"phase") as tr:
5140 with repo.lock(), repo.transaction(b"phase") as tr:
5141 # set phase
5141 # set phase
5142 if not revs:
5142 if not revs:
5143 raise error.Abort(_(b'empty revision set'))
5143 raise error.Abort(_(b'empty revision set'))
5144 nodes = [repo[r].node() for r in revs]
5144 nodes = [repo[r].node() for r in revs]
5145 # moving revision from public to draft may hide them
5145 # moving revision from public to draft may hide them
5146 # We have to check result on an unfiltered repository
5146 # We have to check result on an unfiltered repository
5147 unfi = repo.unfiltered()
5147 unfi = repo.unfiltered()
5148 getphase = unfi._phasecache.phase
5148 getphase = unfi._phasecache.phase
5149 olddata = [getphase(unfi, r) for r in unfi]
5149 olddata = [getphase(unfi, r) for r in unfi]
5150 phases.advanceboundary(repo, tr, targetphase, nodes)
5150 phases.advanceboundary(repo, tr, targetphase, nodes)
5151 if opts[b'force']:
5151 if opts[b'force']:
5152 phases.retractboundary(repo, tr, targetphase, nodes)
5152 phases.retractboundary(repo, tr, targetphase, nodes)
5153 getphase = unfi._phasecache.phase
5153 getphase = unfi._phasecache.phase
5154 newdata = [getphase(unfi, r) for r in unfi]
5154 newdata = [getphase(unfi, r) for r in unfi]
5155 changes = sum(newdata[r] != olddata[r] for r in unfi)
5155 changes = sum(newdata[r] != olddata[r] for r in unfi)
5156 cl = unfi.changelog
5156 cl = unfi.changelog
5157 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5157 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5158 if rejected:
5158 if rejected:
5159 ui.warn(
5159 ui.warn(
5160 _(
5160 _(
5161 b'cannot move %i changesets to a higher '
5161 b'cannot move %i changesets to a higher '
5162 b'phase, use --force\n'
5162 b'phase, use --force\n'
5163 )
5163 )
5164 % len(rejected)
5164 % len(rejected)
5165 )
5165 )
5166 ret = 1
5166 ret = 1
5167 if changes:
5167 if changes:
5168 msg = _(b'phase changed for %i changesets\n') % changes
5168 msg = _(b'phase changed for %i changesets\n') % changes
5169 if ret:
5169 if ret:
5170 ui.status(msg)
5170 ui.status(msg)
5171 else:
5171 else:
5172 ui.note(msg)
5172 ui.note(msg)
5173 else:
5173 else:
5174 ui.warn(_(b'no phases changed\n'))
5174 ui.warn(_(b'no phases changed\n'))
5175 return ret
5175 return ret
5176
5176
5177
5177
5178 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5178 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5179 """Run after a changegroup has been added via pull/unbundle
5179 """Run after a changegroup has been added via pull/unbundle
5180
5180
5181 This takes arguments below:
5181 This takes arguments below:
5182
5182
5183 :modheads: change of heads by pull/unbundle
5183 :modheads: change of heads by pull/unbundle
5184 :optupdate: updating working directory is needed or not
5184 :optupdate: updating working directory is needed or not
5185 :checkout: update destination revision (or None to default destination)
5185 :checkout: update destination revision (or None to default destination)
5186 :brev: a name, which might be a bookmark to be activated after updating
5186 :brev: a name, which might be a bookmark to be activated after updating
5187 """
5187 """
5188 if modheads == 0:
5188 if modheads == 0:
5189 return
5189 return
5190 if optupdate:
5190 if optupdate:
5191 try:
5191 try:
5192 return hg.updatetotally(ui, repo, checkout, brev)
5192 return hg.updatetotally(ui, repo, checkout, brev)
5193 except error.UpdateAbort as inst:
5193 except error.UpdateAbort as inst:
5194 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5194 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5195 hint = inst.hint
5195 hint = inst.hint
5196 raise error.UpdateAbort(msg, hint=hint)
5196 raise error.UpdateAbort(msg, hint=hint)
5197 if modheads is not None and modheads > 1:
5197 if modheads is not None and modheads > 1:
5198 currentbranchheads = len(repo.branchheads())
5198 currentbranchheads = len(repo.branchheads())
5199 if currentbranchheads == modheads:
5199 if currentbranchheads == modheads:
5200 ui.status(
5200 ui.status(
5201 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5201 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5202 )
5202 )
5203 elif currentbranchheads > 1:
5203 elif currentbranchheads > 1:
5204 ui.status(
5204 ui.status(
5205 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5205 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5206 )
5206 )
5207 else:
5207 else:
5208 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5208 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5209 elif not ui.configbool(b'commands', b'update.requiredest'):
5209 elif not ui.configbool(b'commands', b'update.requiredest'):
5210 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5210 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5211
5211
5212
5212
5213 @command(
5213 @command(
5214 b'pull',
5214 b'pull',
5215 [
5215 [
5216 (
5216 (
5217 b'u',
5217 b'u',
5218 b'update',
5218 b'update',
5219 None,
5219 None,
5220 _(b'update to new branch head if new descendants were pulled'),
5220 _(b'update to new branch head if new descendants were pulled'),
5221 ),
5221 ),
5222 (
5222 (
5223 b'f',
5223 b'f',
5224 b'force',
5224 b'force',
5225 None,
5225 None,
5226 _(b'run even when remote repository is unrelated'),
5226 _(b'run even when remote repository is unrelated'),
5227 ),
5227 ),
5228 (b'', b'confirm', None, _(b'confirm pull before applying changes'),),
5228 (b'', b'confirm', None, _(b'confirm pull before applying changes'),),
5229 (
5229 (
5230 b'r',
5230 b'r',
5231 b'rev',
5231 b'rev',
5232 [],
5232 [],
5233 _(b'a remote changeset intended to be added'),
5233 _(b'a remote changeset intended to be added'),
5234 _(b'REV'),
5234 _(b'REV'),
5235 ),
5235 ),
5236 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5236 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5237 (
5237 (
5238 b'b',
5238 b'b',
5239 b'branch',
5239 b'branch',
5240 [],
5240 [],
5241 _(b'a specific branch you would like to pull'),
5241 _(b'a specific branch you would like to pull'),
5242 _(b'BRANCH'),
5242 _(b'BRANCH'),
5243 ),
5243 ),
5244 ]
5244 ]
5245 + remoteopts,
5245 + remoteopts,
5246 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
5246 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
5247 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5247 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5248 helpbasic=True,
5248 helpbasic=True,
5249 )
5249 )
5250 def pull(ui, repo, source=b"default", **opts):
5250 def pull(ui, repo, source=b"default", **opts):
5251 """pull changes from the specified source
5251 """pull changes from the specified source
5252
5252
5253 Pull changes from a remote repository to a local one.
5253 Pull changes from a remote repository to a local one.
5254
5254
5255 This finds all changes from the repository at the specified path
5255 This finds all changes from the repository at the specified path
5256 or URL and adds them to a local repository (the current one unless
5256 or URL and adds them to a local repository (the current one unless
5257 -R is specified). By default, this does not update the copy of the
5257 -R is specified). By default, this does not update the copy of the
5258 project in the working directory.
5258 project in the working directory.
5259
5259
5260 When cloning from servers that support it, Mercurial may fetch
5260 When cloning from servers that support it, Mercurial may fetch
5261 pre-generated data. When this is done, hooks operating on incoming
5261 pre-generated data. When this is done, hooks operating on incoming
5262 changesets and changegroups may fire more than once, once for each
5262 changesets and changegroups may fire more than once, once for each
5263 pre-generated bundle and as well as for any additional remaining
5263 pre-generated bundle and as well as for any additional remaining
5264 data. See :hg:`help -e clonebundles` for more.
5264 data. See :hg:`help -e clonebundles` for more.
5265
5265
5266 Use :hg:`incoming` if you want to see what would have been added
5266 Use :hg:`incoming` if you want to see what would have been added
5267 by a pull at the time you issued this command. If you then decide
5267 by a pull at the time you issued this command. If you then decide
5268 to add those changes to the repository, you should use :hg:`pull
5268 to add those changes to the repository, you should use :hg:`pull
5269 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5269 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5270
5270
5271 If SOURCE is omitted, the 'default' path will be used.
5271 If SOURCE is omitted, the 'default' path will be used.
5272 See :hg:`help urls` for more information.
5272 See :hg:`help urls` for more information.
5273
5273
5274 Specifying bookmark as ``.`` is equivalent to specifying the active
5274 Specifying bookmark as ``.`` is equivalent to specifying the active
5275 bookmark's name.
5275 bookmark's name.
5276
5276
5277 Returns 0 on success, 1 if an update had unresolved files.
5277 Returns 0 on success, 1 if an update had unresolved files.
5278 """
5278 """
5279
5279
5280 opts = pycompat.byteskwargs(opts)
5280 opts = pycompat.byteskwargs(opts)
5281 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5281 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5282 b'update'
5282 b'update'
5283 ):
5283 ):
5284 msg = _(b'update destination required by configuration')
5284 msg = _(b'update destination required by configuration')
5285 hint = _(b'use hg pull followed by hg update DEST')
5285 hint = _(b'use hg pull followed by hg update DEST')
5286 raise error.Abort(msg, hint=hint)
5286 raise error.Abort(msg, hint=hint)
5287
5287
5288 source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
5288 source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
5289 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5289 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5290 other = hg.peer(repo, opts, source)
5290 other = hg.peer(repo, opts, source)
5291 try:
5291 try:
5292 revs, checkout = hg.addbranchrevs(
5292 revs, checkout = hg.addbranchrevs(
5293 repo, other, branches, opts.get(b'rev')
5293 repo, other, branches, opts.get(b'rev')
5294 )
5294 )
5295
5295
5296 pullopargs = {}
5296 pullopargs = {}
5297
5297
5298 nodes = None
5298 nodes = None
5299 if opts.get(b'bookmark') or revs:
5299 if opts.get(b'bookmark') or revs:
5300 # The list of bookmark used here is the same used to actually update
5300 # The list of bookmark used here is the same used to actually update
5301 # the bookmark names, to avoid the race from issue 4689 and we do
5301 # the bookmark names, to avoid the race from issue 4689 and we do
5302 # all lookup and bookmark queries in one go so they see the same
5302 # all lookup and bookmark queries in one go so they see the same
5303 # version of the server state (issue 4700).
5303 # version of the server state (issue 4700).
5304 nodes = []
5304 nodes = []
5305 fnodes = []
5305 fnodes = []
5306 revs = revs or []
5306 revs = revs or []
5307 if revs and not other.capable(b'lookup'):
5307 if revs and not other.capable(b'lookup'):
5308 err = _(
5308 err = _(
5309 b"other repository doesn't support revision lookup, "
5309 b"other repository doesn't support revision lookup, "
5310 b"so a rev cannot be specified."
5310 b"so a rev cannot be specified."
5311 )
5311 )
5312 raise error.Abort(err)
5312 raise error.Abort(err)
5313 with other.commandexecutor() as e:
5313 with other.commandexecutor() as e:
5314 fremotebookmarks = e.callcommand(
5314 fremotebookmarks = e.callcommand(
5315 b'listkeys', {b'namespace': b'bookmarks'}
5315 b'listkeys', {b'namespace': b'bookmarks'}
5316 )
5316 )
5317 for r in revs:
5317 for r in revs:
5318 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5318 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5319 remotebookmarks = fremotebookmarks.result()
5319 remotebookmarks = fremotebookmarks.result()
5320 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5320 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5321 pullopargs[b'remotebookmarks'] = remotebookmarks
5321 pullopargs[b'remotebookmarks'] = remotebookmarks
5322 for b in opts.get(b'bookmark', []):
5322 for b in opts.get(b'bookmark', []):
5323 b = repo._bookmarks.expandname(b)
5323 b = repo._bookmarks.expandname(b)
5324 if b not in remotebookmarks:
5324 if b not in remotebookmarks:
5325 raise error.Abort(_(b'remote bookmark %s not found!') % b)
5325 raise error.Abort(_(b'remote bookmark %s not found!') % b)
5326 nodes.append(remotebookmarks[b])
5326 nodes.append(remotebookmarks[b])
5327 for i, rev in enumerate(revs):
5327 for i, rev in enumerate(revs):
5328 node = fnodes[i].result()
5328 node = fnodes[i].result()
5329 nodes.append(node)
5329 nodes.append(node)
5330 if rev == checkout:
5330 if rev == checkout:
5331 checkout = node
5331 checkout = node
5332
5332
5333 wlock = util.nullcontextmanager()
5333 wlock = util.nullcontextmanager()
5334 if opts.get(b'update'):
5334 if opts.get(b'update'):
5335 wlock = repo.wlock()
5335 wlock = repo.wlock()
5336 with wlock:
5336 with wlock:
5337 pullopargs.update(opts.get(b'opargs', {}))
5337 pullopargs.update(opts.get(b'opargs', {}))
5338 modheads = exchange.pull(
5338 modheads = exchange.pull(
5339 repo,
5339 repo,
5340 other,
5340 other,
5341 heads=nodes,
5341 heads=nodes,
5342 force=opts.get(b'force'),
5342 force=opts.get(b'force'),
5343 bookmarks=opts.get(b'bookmark', ()),
5343 bookmarks=opts.get(b'bookmark', ()),
5344 opargs=pullopargs,
5344 opargs=pullopargs,
5345 confirm=opts.get(b'confirm'),
5345 confirm=opts.get(b'confirm'),
5346 ).cgresult
5346 ).cgresult
5347
5347
5348 # brev is a name, which might be a bookmark to be activated at
5348 # brev is a name, which might be a bookmark to be activated at
5349 # the end of the update. In other words, it is an explicit
5349 # the end of the update. In other words, it is an explicit
5350 # destination of the update
5350 # destination of the update
5351 brev = None
5351 brev = None
5352
5352
5353 if checkout:
5353 if checkout:
5354 checkout = repo.unfiltered().changelog.rev(checkout)
5354 checkout = repo.unfiltered().changelog.rev(checkout)
5355
5355
5356 # order below depends on implementation of
5356 # order below depends on implementation of
5357 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5357 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5358 # because 'checkout' is determined without it.
5358 # because 'checkout' is determined without it.
5359 if opts.get(b'rev'):
5359 if opts.get(b'rev'):
5360 brev = opts[b'rev'][0]
5360 brev = opts[b'rev'][0]
5361 elif opts.get(b'branch'):
5361 elif opts.get(b'branch'):
5362 brev = opts[b'branch'][0]
5362 brev = opts[b'branch'][0]
5363 else:
5363 else:
5364 brev = branches[0]
5364 brev = branches[0]
5365 repo._subtoppath = source
5365 repo._subtoppath = source
5366 try:
5366 try:
5367 ret = postincoming(
5367 ret = postincoming(
5368 ui, repo, modheads, opts.get(b'update'), checkout, brev
5368 ui, repo, modheads, opts.get(b'update'), checkout, brev
5369 )
5369 )
5370 except error.FilteredRepoLookupError as exc:
5370 except error.FilteredRepoLookupError as exc:
5371 msg = _(b'cannot update to target: %s') % exc.args[0]
5371 msg = _(b'cannot update to target: %s') % exc.args[0]
5372 exc.args = (msg,) + exc.args[1:]
5372 exc.args = (msg,) + exc.args[1:]
5373 raise
5373 raise
5374 finally:
5374 finally:
5375 del repo._subtoppath
5375 del repo._subtoppath
5376
5376
5377 finally:
5377 finally:
5378 other.close()
5378 other.close()
5379 return ret
5379 return ret
5380
5380
5381
5381
5382 @command(
5382 @command(
5383 b'push',
5383 b'push',
5384 [
5384 [
5385 (b'f', b'force', None, _(b'force push')),
5385 (b'f', b'force', None, _(b'force push')),
5386 (
5386 (
5387 b'r',
5387 b'r',
5388 b'rev',
5388 b'rev',
5389 [],
5389 [],
5390 _(b'a changeset intended to be included in the destination'),
5390 _(b'a changeset intended to be included in the destination'),
5391 _(b'REV'),
5391 _(b'REV'),
5392 ),
5392 ),
5393 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5393 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5394 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5394 (
5395 (
5395 b'b',
5396 b'b',
5396 b'branch',
5397 b'branch',
5397 [],
5398 [],
5398 _(b'a specific branch you would like to push'),
5399 _(b'a specific branch you would like to push'),
5399 _(b'BRANCH'),
5400 _(b'BRANCH'),
5400 ),
5401 ),
5401 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5402 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5402 (
5403 (
5403 b'',
5404 b'',
5404 b'pushvars',
5405 b'pushvars',
5405 [],
5406 [],
5406 _(b'variables that can be sent to server (ADVANCED)'),
5407 _(b'variables that can be sent to server (ADVANCED)'),
5407 ),
5408 ),
5408 (
5409 (
5409 b'',
5410 b'',
5410 b'publish',
5411 b'publish',
5411 False,
5412 False,
5412 _(b'push the changeset as public (EXPERIMENTAL)'),
5413 _(b'push the changeset as public (EXPERIMENTAL)'),
5413 ),
5414 ),
5414 ]
5415 ]
5415 + remoteopts,
5416 + remoteopts,
5416 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
5417 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
5417 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5418 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5418 helpbasic=True,
5419 helpbasic=True,
5419 )
5420 )
5420 def push(ui, repo, dest=None, **opts):
5421 def push(ui, repo, dest=None, **opts):
5421 """push changes to the specified destination
5422 """push changes to the specified destination
5422
5423
5423 Push changesets from the local repository to the specified
5424 Push changesets from the local repository to the specified
5424 destination.
5425 destination.
5425
5426
5426 This operation is symmetrical to pull: it is identical to a pull
5427 This operation is symmetrical to pull: it is identical to a pull
5427 in the destination repository from the current one.
5428 in the destination repository from the current one.
5428
5429
5429 By default, push will not allow creation of new heads at the
5430 By default, push will not allow creation of new heads at the
5430 destination, since multiple heads would make it unclear which head
5431 destination, since multiple heads would make it unclear which head
5431 to use. In this situation, it is recommended to pull and merge
5432 to use. In this situation, it is recommended to pull and merge
5432 before pushing.
5433 before pushing.
5433
5434
5434 Use --new-branch if you want to allow push to create a new named
5435 Use --new-branch if you want to allow push to create a new named
5435 branch that is not present at the destination. This allows you to
5436 branch that is not present at the destination. This allows you to
5436 only create a new branch without forcing other changes.
5437 only create a new branch without forcing other changes.
5437
5438
5438 .. note::
5439 .. note::
5439
5440
5440 Extra care should be taken with the -f/--force option,
5441 Extra care should be taken with the -f/--force option,
5441 which will push all new heads on all branches, an action which will
5442 which will push all new heads on all branches, an action which will
5442 almost always cause confusion for collaborators.
5443 almost always cause confusion for collaborators.
5443
5444
5444 If -r/--rev is used, the specified revision and all its ancestors
5445 If -r/--rev is used, the specified revision and all its ancestors
5445 will be pushed to the remote repository.
5446 will be pushed to the remote repository.
5446
5447
5447 If -B/--bookmark is used, the specified bookmarked revision, its
5448 If -B/--bookmark is used, the specified bookmarked revision, its
5448 ancestors, and the bookmark will be pushed to the remote
5449 ancestors, and the bookmark will be pushed to the remote
5449 repository. Specifying ``.`` is equivalent to specifying the active
5450 repository. Specifying ``.`` is equivalent to specifying the active
5450 bookmark's name.
5451 bookmark's name. Use the --all-bookmarks option for pushing all
5452 current bookmarks.
5451
5453
5452 Please see :hg:`help urls` for important details about ``ssh://``
5454 Please see :hg:`help urls` for important details about ``ssh://``
5453 URLs. If DESTINATION is omitted, a default path will be used.
5455 URLs. If DESTINATION is omitted, a default path will be used.
5454
5456
5455 .. container:: verbose
5457 .. container:: verbose
5456
5458
5457 The --pushvars option sends strings to the server that become
5459 The --pushvars option sends strings to the server that become
5458 environment variables prepended with ``HG_USERVAR_``. For example,
5460 environment variables prepended with ``HG_USERVAR_``. For example,
5459 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5461 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5460 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5462 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5461
5463
5462 pushvars can provide for user-overridable hooks as well as set debug
5464 pushvars can provide for user-overridable hooks as well as set debug
5463 levels. One example is having a hook that blocks commits containing
5465 levels. One example is having a hook that blocks commits containing
5464 conflict markers, but enables the user to override the hook if the file
5466 conflict markers, but enables the user to override the hook if the file
5465 is using conflict markers for testing purposes or the file format has
5467 is using conflict markers for testing purposes or the file format has
5466 strings that look like conflict markers.
5468 strings that look like conflict markers.
5467
5469
5468 By default, servers will ignore `--pushvars`. To enable it add the
5470 By default, servers will ignore `--pushvars`. To enable it add the
5469 following to your configuration file::
5471 following to your configuration file::
5470
5472
5471 [push]
5473 [push]
5472 pushvars.server = true
5474 pushvars.server = true
5473
5475
5474 Returns 0 if push was successful, 1 if nothing to push.
5476 Returns 0 if push was successful, 1 if nothing to push.
5475 """
5477 """
5476
5478
5477 opts = pycompat.byteskwargs(opts)
5479 opts = pycompat.byteskwargs(opts)
5480
5481 if opts.get(b'all_bookmarks'):
5482 cmdutil.check_incompatible_arguments(
5483 opts, b'all_bookmarks', [b'bookmark', b'rev'],
5484 )
5485 opts[b'bookmark'] = list(repo._bookmarks)
5486
5478 if opts.get(b'bookmark'):
5487 if opts.get(b'bookmark'):
5479 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5488 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5480 for b in opts[b'bookmark']:
5489 for b in opts[b'bookmark']:
5481 # translate -B options to -r so changesets get pushed
5490 # translate -B options to -r so changesets get pushed
5482 b = repo._bookmarks.expandname(b)
5491 b = repo._bookmarks.expandname(b)
5483 if b in repo._bookmarks:
5492 if b in repo._bookmarks:
5484 opts.setdefault(b'rev', []).append(b)
5493 opts.setdefault(b'rev', []).append(b)
5485 else:
5494 else:
5486 # if we try to push a deleted bookmark, translate it to null
5495 # if we try to push a deleted bookmark, translate it to null
5487 # this lets simultaneous -r, -b options continue working
5496 # this lets simultaneous -r, -b options continue working
5488 opts.setdefault(b'rev', []).append(b"null")
5497 opts.setdefault(b'rev', []).append(b"null")
5489
5498
5490 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5499 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5491 if not path:
5500 if not path:
5492 raise error.Abort(
5501 raise error.Abort(
5493 _(b'default repository not configured!'),
5502 _(b'default repository not configured!'),
5494 hint=_(b"see 'hg help config.paths'"),
5503 hint=_(b"see 'hg help config.paths'"),
5495 )
5504 )
5496 dest = path.pushloc or path.loc
5505 dest = path.pushloc or path.loc
5497 branches = (path.branch, opts.get(b'branch') or [])
5506 branches = (path.branch, opts.get(b'branch') or [])
5498 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5507 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5499 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
5508 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
5500 other = hg.peer(repo, opts, dest)
5509 other = hg.peer(repo, opts, dest)
5501
5510
5502 if revs:
5511 if revs:
5503 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5512 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5504 if not revs:
5513 if not revs:
5505 raise error.Abort(
5514 raise error.Abort(
5506 _(b"specified revisions evaluate to an empty set"),
5515 _(b"specified revisions evaluate to an empty set"),
5507 hint=_(b"use different revision arguments"),
5516 hint=_(b"use different revision arguments"),
5508 )
5517 )
5509 elif path.pushrev:
5518 elif path.pushrev:
5510 # It doesn't make any sense to specify ancestor revisions. So limit
5519 # It doesn't make any sense to specify ancestor revisions. So limit
5511 # to DAG heads to make discovery simpler.
5520 # to DAG heads to make discovery simpler.
5512 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5521 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5513 revs = scmutil.revrange(repo, [expr])
5522 revs = scmutil.revrange(repo, [expr])
5514 revs = [repo[rev].node() for rev in revs]
5523 revs = [repo[rev].node() for rev in revs]
5515 if not revs:
5524 if not revs:
5516 raise error.Abort(
5525 raise error.Abort(
5517 _(b'default push revset for path evaluates to an empty set')
5526 _(b'default push revset for path evaluates to an empty set')
5518 )
5527 )
5519 elif ui.configbool(b'commands', b'push.require-revs'):
5528 elif ui.configbool(b'commands', b'push.require-revs'):
5520 raise error.Abort(
5529 raise error.Abort(
5521 _(b'no revisions specified to push'),
5530 _(b'no revisions specified to push'),
5522 hint=_(b'did you mean "hg push -r ."?'),
5531 hint=_(b'did you mean "hg push -r ."?'),
5523 )
5532 )
5524
5533
5525 repo._subtoppath = dest
5534 repo._subtoppath = dest
5526 try:
5535 try:
5527 # push subrepos depth-first for coherent ordering
5536 # push subrepos depth-first for coherent ordering
5528 c = repo[b'.']
5537 c = repo[b'.']
5529 subs = c.substate # only repos that are committed
5538 subs = c.substate # only repos that are committed
5530 for s in sorted(subs):
5539 for s in sorted(subs):
5531 result = c.sub(s).push(opts)
5540 result = c.sub(s).push(opts)
5532 if result == 0:
5541 if result == 0:
5533 return not result
5542 return not result
5534 finally:
5543 finally:
5535 del repo._subtoppath
5544 del repo._subtoppath
5536
5545
5537 opargs = dict(opts.get(b'opargs', {})) # copy opargs since we may mutate it
5546 opargs = dict(opts.get(b'opargs', {})) # copy opargs since we may mutate it
5538 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5547 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5539
5548
5540 pushop = exchange.push(
5549 pushop = exchange.push(
5541 repo,
5550 repo,
5542 other,
5551 other,
5543 opts.get(b'force'),
5552 opts.get(b'force'),
5544 revs=revs,
5553 revs=revs,
5545 newbranch=opts.get(b'new_branch'),
5554 newbranch=opts.get(b'new_branch'),
5546 bookmarks=opts.get(b'bookmark', ()),
5555 bookmarks=opts.get(b'bookmark', ()),
5547 publish=opts.get(b'publish'),
5556 publish=opts.get(b'publish'),
5548 opargs=opargs,
5557 opargs=opargs,
5549 )
5558 )
5550
5559
5551 result = not pushop.cgresult
5560 result = not pushop.cgresult
5552
5561
5553 if pushop.bkresult is not None:
5562 if pushop.bkresult is not None:
5554 if pushop.bkresult == 2:
5563 if pushop.bkresult == 2:
5555 result = 2
5564 result = 2
5556 elif not result and pushop.bkresult:
5565 elif not result and pushop.bkresult:
5557 result = 2
5566 result = 2
5558
5567
5559 return result
5568 return result
5560
5569
5561
5570
5562 @command(
5571 @command(
5563 b'recover',
5572 b'recover',
5564 [(b'', b'verify', False, b"run `hg verify` after successful recover"),],
5573 [(b'', b'verify', False, b"run `hg verify` after successful recover"),],
5565 helpcategory=command.CATEGORY_MAINTENANCE,
5574 helpcategory=command.CATEGORY_MAINTENANCE,
5566 )
5575 )
5567 def recover(ui, repo, **opts):
5576 def recover(ui, repo, **opts):
5568 """roll back an interrupted transaction
5577 """roll back an interrupted transaction
5569
5578
5570 Recover from an interrupted commit or pull.
5579 Recover from an interrupted commit or pull.
5571
5580
5572 This command tries to fix the repository status after an
5581 This command tries to fix the repository status after an
5573 interrupted operation. It should only be necessary when Mercurial
5582 interrupted operation. It should only be necessary when Mercurial
5574 suggests it.
5583 suggests it.
5575
5584
5576 Returns 0 if successful, 1 if nothing to recover or verify fails.
5585 Returns 0 if successful, 1 if nothing to recover or verify fails.
5577 """
5586 """
5578 ret = repo.recover()
5587 ret = repo.recover()
5579 if ret:
5588 if ret:
5580 if opts['verify']:
5589 if opts['verify']:
5581 return hg.verify(repo)
5590 return hg.verify(repo)
5582 else:
5591 else:
5583 msg = _(
5592 msg = _(
5584 b"(verify step skipped, run `hg verify` to check your "
5593 b"(verify step skipped, run `hg verify` to check your "
5585 b"repository content)\n"
5594 b"repository content)\n"
5586 )
5595 )
5587 ui.warn(msg)
5596 ui.warn(msg)
5588 return 0
5597 return 0
5589 return 1
5598 return 1
5590
5599
5591
5600
5592 @command(
5601 @command(
5593 b'remove|rm',
5602 b'remove|rm',
5594 [
5603 [
5595 (b'A', b'after', None, _(b'record delete for missing files')),
5604 (b'A', b'after', None, _(b'record delete for missing files')),
5596 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5605 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5597 ]
5606 ]
5598 + subrepoopts
5607 + subrepoopts
5599 + walkopts
5608 + walkopts
5600 + dryrunopts,
5609 + dryrunopts,
5601 _(b'[OPTION]... FILE...'),
5610 _(b'[OPTION]... FILE...'),
5602 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5611 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5603 helpbasic=True,
5612 helpbasic=True,
5604 inferrepo=True,
5613 inferrepo=True,
5605 )
5614 )
5606 def remove(ui, repo, *pats, **opts):
5615 def remove(ui, repo, *pats, **opts):
5607 """remove the specified files on the next commit
5616 """remove the specified files on the next commit
5608
5617
5609 Schedule the indicated files for removal from the current branch.
5618 Schedule the indicated files for removal from the current branch.
5610
5619
5611 This command schedules the files to be removed at the next commit.
5620 This command schedules the files to be removed at the next commit.
5612 To undo a remove before that, see :hg:`revert`. To undo added
5621 To undo a remove before that, see :hg:`revert`. To undo added
5613 files, see :hg:`forget`.
5622 files, see :hg:`forget`.
5614
5623
5615 .. container:: verbose
5624 .. container:: verbose
5616
5625
5617 -A/--after can be used to remove only files that have already
5626 -A/--after can be used to remove only files that have already
5618 been deleted, -f/--force can be used to force deletion, and -Af
5627 been deleted, -f/--force can be used to force deletion, and -Af
5619 can be used to remove files from the next revision without
5628 can be used to remove files from the next revision without
5620 deleting them from the working directory.
5629 deleting them from the working directory.
5621
5630
5622 The following table details the behavior of remove for different
5631 The following table details the behavior of remove for different
5623 file states (columns) and option combinations (rows). The file
5632 file states (columns) and option combinations (rows). The file
5624 states are Added [A], Clean [C], Modified [M] and Missing [!]
5633 states are Added [A], Clean [C], Modified [M] and Missing [!]
5625 (as reported by :hg:`status`). The actions are Warn, Remove
5634 (as reported by :hg:`status`). The actions are Warn, Remove
5626 (from branch) and Delete (from disk):
5635 (from branch) and Delete (from disk):
5627
5636
5628 ========= == == == ==
5637 ========= == == == ==
5629 opt/state A C M !
5638 opt/state A C M !
5630 ========= == == == ==
5639 ========= == == == ==
5631 none W RD W R
5640 none W RD W R
5632 -f R RD RD R
5641 -f R RD RD R
5633 -A W W W R
5642 -A W W W R
5634 -Af R R R R
5643 -Af R R R R
5635 ========= == == == ==
5644 ========= == == == ==
5636
5645
5637 .. note::
5646 .. note::
5638
5647
5639 :hg:`remove` never deletes files in Added [A] state from the
5648 :hg:`remove` never deletes files in Added [A] state from the
5640 working directory, not even if ``--force`` is specified.
5649 working directory, not even if ``--force`` is specified.
5641
5650
5642 Returns 0 on success, 1 if any warnings encountered.
5651 Returns 0 on success, 1 if any warnings encountered.
5643 """
5652 """
5644
5653
5645 opts = pycompat.byteskwargs(opts)
5654 opts = pycompat.byteskwargs(opts)
5646 after, force = opts.get(b'after'), opts.get(b'force')
5655 after, force = opts.get(b'after'), opts.get(b'force')
5647 dryrun = opts.get(b'dry_run')
5656 dryrun = opts.get(b'dry_run')
5648 if not pats and not after:
5657 if not pats and not after:
5649 raise error.Abort(_(b'no files specified'))
5658 raise error.Abort(_(b'no files specified'))
5650
5659
5651 m = scmutil.match(repo[None], pats, opts)
5660 m = scmutil.match(repo[None], pats, opts)
5652 subrepos = opts.get(b'subrepos')
5661 subrepos = opts.get(b'subrepos')
5653 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5662 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5654 return cmdutil.remove(
5663 return cmdutil.remove(
5655 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5664 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5656 )
5665 )
5657
5666
5658
5667
5659 @command(
5668 @command(
5660 b'rename|move|mv',
5669 b'rename|move|mv',
5661 [
5670 [
5662 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5671 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5663 (
5672 (
5664 b'',
5673 b'',
5665 b'at-rev',
5674 b'at-rev',
5666 b'',
5675 b'',
5667 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5676 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5668 _(b'REV'),
5677 _(b'REV'),
5669 ),
5678 ),
5670 (
5679 (
5671 b'f',
5680 b'f',
5672 b'force',
5681 b'force',
5673 None,
5682 None,
5674 _(b'forcibly move over an existing managed file'),
5683 _(b'forcibly move over an existing managed file'),
5675 ),
5684 ),
5676 ]
5685 ]
5677 + walkopts
5686 + walkopts
5678 + dryrunopts,
5687 + dryrunopts,
5679 _(b'[OPTION]... SOURCE... DEST'),
5688 _(b'[OPTION]... SOURCE... DEST'),
5680 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5689 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5681 )
5690 )
5682 def rename(ui, repo, *pats, **opts):
5691 def rename(ui, repo, *pats, **opts):
5683 """rename files; equivalent of copy + remove
5692 """rename files; equivalent of copy + remove
5684
5693
5685 Mark dest as copies of sources; mark sources for deletion. If dest
5694 Mark dest as copies of sources; mark sources for deletion. If dest
5686 is a directory, copies are put in that directory. If dest is a
5695 is a directory, copies are put in that directory. If dest is a
5687 file, there can only be one source.
5696 file, there can only be one source.
5688
5697
5689 By default, this command copies the contents of files as they
5698 By default, this command copies the contents of files as they
5690 exist in the working directory. If invoked with -A/--after, the
5699 exist in the working directory. If invoked with -A/--after, the
5691 operation is recorded, but no copying is performed.
5700 operation is recorded, but no copying is performed.
5692
5701
5693 This command takes effect at the next commit. To undo a rename
5702 This command takes effect at the next commit. To undo a rename
5694 before that, see :hg:`revert`.
5703 before that, see :hg:`revert`.
5695
5704
5696 Returns 0 on success, 1 if errors are encountered.
5705 Returns 0 on success, 1 if errors are encountered.
5697 """
5706 """
5698 opts = pycompat.byteskwargs(opts)
5707 opts = pycompat.byteskwargs(opts)
5699 with repo.wlock():
5708 with repo.wlock():
5700 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5709 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5701
5710
5702
5711
5703 @command(
5712 @command(
5704 b'resolve',
5713 b'resolve',
5705 [
5714 [
5706 (b'a', b'all', None, _(b'select all unresolved files')),
5715 (b'a', b'all', None, _(b'select all unresolved files')),
5707 (b'l', b'list', None, _(b'list state of files needing merge')),
5716 (b'l', b'list', None, _(b'list state of files needing merge')),
5708 (b'm', b'mark', None, _(b'mark files as resolved')),
5717 (b'm', b'mark', None, _(b'mark files as resolved')),
5709 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5718 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5710 (b'n', b'no-status', None, _(b'hide status prefix')),
5719 (b'n', b'no-status', None, _(b'hide status prefix')),
5711 (b'', b're-merge', None, _(b're-merge files')),
5720 (b'', b're-merge', None, _(b're-merge files')),
5712 ]
5721 ]
5713 + mergetoolopts
5722 + mergetoolopts
5714 + walkopts
5723 + walkopts
5715 + formatteropts,
5724 + formatteropts,
5716 _(b'[OPTION]... [FILE]...'),
5725 _(b'[OPTION]... [FILE]...'),
5717 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5726 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5718 inferrepo=True,
5727 inferrepo=True,
5719 )
5728 )
5720 def resolve(ui, repo, *pats, **opts):
5729 def resolve(ui, repo, *pats, **opts):
5721 """redo merges or set/view the merge status of files
5730 """redo merges or set/view the merge status of files
5722
5731
5723 Merges with unresolved conflicts are often the result of
5732 Merges with unresolved conflicts are often the result of
5724 non-interactive merging using the ``internal:merge`` configuration
5733 non-interactive merging using the ``internal:merge`` configuration
5725 setting, or a command-line merge tool like ``diff3``. The resolve
5734 setting, or a command-line merge tool like ``diff3``. The resolve
5726 command is used to manage the files involved in a merge, after
5735 command is used to manage the files involved in a merge, after
5727 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5736 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5728 working directory must have two parents). See :hg:`help
5737 working directory must have two parents). See :hg:`help
5729 merge-tools` for information on configuring merge tools.
5738 merge-tools` for information on configuring merge tools.
5730
5739
5731 The resolve command can be used in the following ways:
5740 The resolve command can be used in the following ways:
5732
5741
5733 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5742 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5734 the specified files, discarding any previous merge attempts. Re-merging
5743 the specified files, discarding any previous merge attempts. Re-merging
5735 is not performed for files already marked as resolved. Use ``--all/-a``
5744 is not performed for files already marked as resolved. Use ``--all/-a``
5736 to select all unresolved files. ``--tool`` can be used to specify
5745 to select all unresolved files. ``--tool`` can be used to specify
5737 the merge tool used for the given files. It overrides the HGMERGE
5746 the merge tool used for the given files. It overrides the HGMERGE
5738 environment variable and your configuration files. Previous file
5747 environment variable and your configuration files. Previous file
5739 contents are saved with a ``.orig`` suffix.
5748 contents are saved with a ``.orig`` suffix.
5740
5749
5741 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5750 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5742 (e.g. after having manually fixed-up the files). The default is
5751 (e.g. after having manually fixed-up the files). The default is
5743 to mark all unresolved files.
5752 to mark all unresolved files.
5744
5753
5745 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5754 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5746 default is to mark all resolved files.
5755 default is to mark all resolved files.
5747
5756
5748 - :hg:`resolve -l`: list files which had or still have conflicts.
5757 - :hg:`resolve -l`: list files which had or still have conflicts.
5749 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5758 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5750 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5759 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5751 the list. See :hg:`help filesets` for details.
5760 the list. See :hg:`help filesets` for details.
5752
5761
5753 .. note::
5762 .. note::
5754
5763
5755 Mercurial will not let you commit files with unresolved merge
5764 Mercurial will not let you commit files with unresolved merge
5756 conflicts. You must use :hg:`resolve -m ...` before you can
5765 conflicts. You must use :hg:`resolve -m ...` before you can
5757 commit after a conflicting merge.
5766 commit after a conflicting merge.
5758
5767
5759 .. container:: verbose
5768 .. container:: verbose
5760
5769
5761 Template:
5770 Template:
5762
5771
5763 The following keywords are supported in addition to the common template
5772 The following keywords are supported in addition to the common template
5764 keywords and functions. See also :hg:`help templates`.
5773 keywords and functions. See also :hg:`help templates`.
5765
5774
5766 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
5775 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
5767 :path: String. Repository-absolute path of the file.
5776 :path: String. Repository-absolute path of the file.
5768
5777
5769 Returns 0 on success, 1 if any files fail a resolve attempt.
5778 Returns 0 on success, 1 if any files fail a resolve attempt.
5770 """
5779 """
5771
5780
5772 opts = pycompat.byteskwargs(opts)
5781 opts = pycompat.byteskwargs(opts)
5773 confirm = ui.configbool(b'commands', b'resolve.confirm')
5782 confirm = ui.configbool(b'commands', b'resolve.confirm')
5774 flaglist = b'all mark unmark list no_status re_merge'.split()
5783 flaglist = b'all mark unmark list no_status re_merge'.split()
5775 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
5784 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
5776
5785
5777 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
5786 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
5778 if actioncount > 1:
5787 if actioncount > 1:
5779 raise error.Abort(_(b"too many actions specified"))
5788 raise error.Abort(_(b"too many actions specified"))
5780 elif actioncount == 0 and ui.configbool(
5789 elif actioncount == 0 and ui.configbool(
5781 b'commands', b'resolve.explicit-re-merge'
5790 b'commands', b'resolve.explicit-re-merge'
5782 ):
5791 ):
5783 hint = _(b'use --mark, --unmark, --list or --re-merge')
5792 hint = _(b'use --mark, --unmark, --list or --re-merge')
5784 raise error.Abort(_(b'no action specified'), hint=hint)
5793 raise error.Abort(_(b'no action specified'), hint=hint)
5785 if pats and all:
5794 if pats and all:
5786 raise error.Abort(_(b"can't specify --all and patterns"))
5795 raise error.Abort(_(b"can't specify --all and patterns"))
5787 if not (all or pats or show or mark or unmark):
5796 if not (all or pats or show or mark or unmark):
5788 raise error.Abort(
5797 raise error.Abort(
5789 _(b'no files or directories specified'),
5798 _(b'no files or directories specified'),
5790 hint=b'use --all to re-merge all unresolved files',
5799 hint=b'use --all to re-merge all unresolved files',
5791 )
5800 )
5792
5801
5793 if confirm:
5802 if confirm:
5794 if all:
5803 if all:
5795 if ui.promptchoice(
5804 if ui.promptchoice(
5796 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
5805 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
5797 ):
5806 ):
5798 raise error.Abort(_(b'user quit'))
5807 raise error.Abort(_(b'user quit'))
5799 if mark and not pats:
5808 if mark and not pats:
5800 if ui.promptchoice(
5809 if ui.promptchoice(
5801 _(
5810 _(
5802 b'mark all unresolved files as resolved (yn)?'
5811 b'mark all unresolved files as resolved (yn)?'
5803 b'$$ &Yes $$ &No'
5812 b'$$ &Yes $$ &No'
5804 )
5813 )
5805 ):
5814 ):
5806 raise error.Abort(_(b'user quit'))
5815 raise error.Abort(_(b'user quit'))
5807 if unmark and not pats:
5816 if unmark and not pats:
5808 if ui.promptchoice(
5817 if ui.promptchoice(
5809 _(
5818 _(
5810 b'mark all resolved files as unresolved (yn)?'
5819 b'mark all resolved files as unresolved (yn)?'
5811 b'$$ &Yes $$ &No'
5820 b'$$ &Yes $$ &No'
5812 )
5821 )
5813 ):
5822 ):
5814 raise error.Abort(_(b'user quit'))
5823 raise error.Abort(_(b'user quit'))
5815
5824
5816 uipathfn = scmutil.getuipathfn(repo)
5825 uipathfn = scmutil.getuipathfn(repo)
5817
5826
5818 if show:
5827 if show:
5819 ui.pager(b'resolve')
5828 ui.pager(b'resolve')
5820 fm = ui.formatter(b'resolve', opts)
5829 fm = ui.formatter(b'resolve', opts)
5821 ms = mergestatemod.mergestate.read(repo)
5830 ms = mergestatemod.mergestate.read(repo)
5822 wctx = repo[None]
5831 wctx = repo[None]
5823 m = scmutil.match(wctx, pats, opts)
5832 m = scmutil.match(wctx, pats, opts)
5824
5833
5825 # Labels and keys based on merge state. Unresolved path conflicts show
5834 # Labels and keys based on merge state. Unresolved path conflicts show
5826 # as 'P'. Resolved path conflicts show as 'R', the same as normal
5835 # as 'P'. Resolved path conflicts show as 'R', the same as normal
5827 # resolved conflicts.
5836 # resolved conflicts.
5828 mergestateinfo = {
5837 mergestateinfo = {
5829 mergestatemod.MERGE_RECORD_UNRESOLVED: (
5838 mergestatemod.MERGE_RECORD_UNRESOLVED: (
5830 b'resolve.unresolved',
5839 b'resolve.unresolved',
5831 b'U',
5840 b'U',
5832 ),
5841 ),
5833 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
5842 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
5834 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
5843 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
5835 b'resolve.unresolved',
5844 b'resolve.unresolved',
5836 b'P',
5845 b'P',
5837 ),
5846 ),
5838 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
5847 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
5839 b'resolve.resolved',
5848 b'resolve.resolved',
5840 b'R',
5849 b'R',
5841 ),
5850 ),
5842 }
5851 }
5843
5852
5844 for f in ms:
5853 for f in ms:
5845 if not m(f):
5854 if not m(f):
5846 continue
5855 continue
5847
5856
5848 label, key = mergestateinfo[ms[f]]
5857 label, key = mergestateinfo[ms[f]]
5849 fm.startitem()
5858 fm.startitem()
5850 fm.context(ctx=wctx)
5859 fm.context(ctx=wctx)
5851 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
5860 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
5852 fm.data(path=f)
5861 fm.data(path=f)
5853 fm.plain(b'%s\n' % uipathfn(f), label=label)
5862 fm.plain(b'%s\n' % uipathfn(f), label=label)
5854 fm.end()
5863 fm.end()
5855 return 0
5864 return 0
5856
5865
5857 with repo.wlock():
5866 with repo.wlock():
5858 ms = mergestatemod.mergestate.read(repo)
5867 ms = mergestatemod.mergestate.read(repo)
5859
5868
5860 if not (ms.active() or repo.dirstate.p2() != nullid):
5869 if not (ms.active() or repo.dirstate.p2() != nullid):
5861 raise error.Abort(
5870 raise error.Abort(
5862 _(b'resolve command not applicable when not merging')
5871 _(b'resolve command not applicable when not merging')
5863 )
5872 )
5864
5873
5865 wctx = repo[None]
5874 wctx = repo[None]
5866 m = scmutil.match(wctx, pats, opts)
5875 m = scmutil.match(wctx, pats, opts)
5867 ret = 0
5876 ret = 0
5868 didwork = False
5877 didwork = False
5869
5878
5870 tocomplete = []
5879 tocomplete = []
5871 hasconflictmarkers = []
5880 hasconflictmarkers = []
5872 if mark:
5881 if mark:
5873 markcheck = ui.config(b'commands', b'resolve.mark-check')
5882 markcheck = ui.config(b'commands', b'resolve.mark-check')
5874 if markcheck not in [b'warn', b'abort']:
5883 if markcheck not in [b'warn', b'abort']:
5875 # Treat all invalid / unrecognized values as 'none'.
5884 # Treat all invalid / unrecognized values as 'none'.
5876 markcheck = False
5885 markcheck = False
5877 for f in ms:
5886 for f in ms:
5878 if not m(f):
5887 if not m(f):
5879 continue
5888 continue
5880
5889
5881 didwork = True
5890 didwork = True
5882
5891
5883 # path conflicts must be resolved manually
5892 # path conflicts must be resolved manually
5884 if ms[f] in (
5893 if ms[f] in (
5885 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
5894 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
5886 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
5895 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
5887 ):
5896 ):
5888 if mark:
5897 if mark:
5889 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
5898 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
5890 elif unmark:
5899 elif unmark:
5891 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
5900 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
5892 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
5901 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
5893 ui.warn(
5902 ui.warn(
5894 _(b'%s: path conflict must be resolved manually\n')
5903 _(b'%s: path conflict must be resolved manually\n')
5895 % uipathfn(f)
5904 % uipathfn(f)
5896 )
5905 )
5897 continue
5906 continue
5898
5907
5899 if mark:
5908 if mark:
5900 if markcheck:
5909 if markcheck:
5901 fdata = repo.wvfs.tryread(f)
5910 fdata = repo.wvfs.tryread(f)
5902 if (
5911 if (
5903 filemerge.hasconflictmarkers(fdata)
5912 filemerge.hasconflictmarkers(fdata)
5904 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
5913 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
5905 ):
5914 ):
5906 hasconflictmarkers.append(f)
5915 hasconflictmarkers.append(f)
5907 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
5916 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
5908 elif unmark:
5917 elif unmark:
5909 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
5918 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
5910 else:
5919 else:
5911 # backup pre-resolve (merge uses .orig for its own purposes)
5920 # backup pre-resolve (merge uses .orig for its own purposes)
5912 a = repo.wjoin(f)
5921 a = repo.wjoin(f)
5913 try:
5922 try:
5914 util.copyfile(a, a + b".resolve")
5923 util.copyfile(a, a + b".resolve")
5915 except (IOError, OSError) as inst:
5924 except (IOError, OSError) as inst:
5916 if inst.errno != errno.ENOENT:
5925 if inst.errno != errno.ENOENT:
5917 raise
5926 raise
5918
5927
5919 try:
5928 try:
5920 # preresolve file
5929 # preresolve file
5921 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
5930 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
5922 with ui.configoverride(overrides, b'resolve'):
5931 with ui.configoverride(overrides, b'resolve'):
5923 complete, r = ms.preresolve(f, wctx)
5932 complete, r = ms.preresolve(f, wctx)
5924 if not complete:
5933 if not complete:
5925 tocomplete.append(f)
5934 tocomplete.append(f)
5926 elif r:
5935 elif r:
5927 ret = 1
5936 ret = 1
5928 finally:
5937 finally:
5929 ms.commit()
5938 ms.commit()
5930
5939
5931 # replace filemerge's .orig file with our resolve file, but only
5940 # replace filemerge's .orig file with our resolve file, but only
5932 # for merges that are complete
5941 # for merges that are complete
5933 if complete:
5942 if complete:
5934 try:
5943 try:
5935 util.rename(
5944 util.rename(
5936 a + b".resolve", scmutil.backuppath(ui, repo, f)
5945 a + b".resolve", scmutil.backuppath(ui, repo, f)
5937 )
5946 )
5938 except OSError as inst:
5947 except OSError as inst:
5939 if inst.errno != errno.ENOENT:
5948 if inst.errno != errno.ENOENT:
5940 raise
5949 raise
5941
5950
5942 if hasconflictmarkers:
5951 if hasconflictmarkers:
5943 ui.warn(
5952 ui.warn(
5944 _(
5953 _(
5945 b'warning: the following files still have conflict '
5954 b'warning: the following files still have conflict '
5946 b'markers:\n'
5955 b'markers:\n'
5947 )
5956 )
5948 + b''.join(
5957 + b''.join(
5949 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
5958 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
5950 )
5959 )
5951 )
5960 )
5952 if markcheck == b'abort' and not all and not pats:
5961 if markcheck == b'abort' and not all and not pats:
5953 raise error.Abort(
5962 raise error.Abort(
5954 _(b'conflict markers detected'),
5963 _(b'conflict markers detected'),
5955 hint=_(b'use --all to mark anyway'),
5964 hint=_(b'use --all to mark anyway'),
5956 )
5965 )
5957
5966
5958 for f in tocomplete:
5967 for f in tocomplete:
5959 try:
5968 try:
5960 # resolve file
5969 # resolve file
5961 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
5970 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
5962 with ui.configoverride(overrides, b'resolve'):
5971 with ui.configoverride(overrides, b'resolve'):
5963 r = ms.resolve(f, wctx)
5972 r = ms.resolve(f, wctx)
5964 if r:
5973 if r:
5965 ret = 1
5974 ret = 1
5966 finally:
5975 finally:
5967 ms.commit()
5976 ms.commit()
5968
5977
5969 # replace filemerge's .orig file with our resolve file
5978 # replace filemerge's .orig file with our resolve file
5970 a = repo.wjoin(f)
5979 a = repo.wjoin(f)
5971 try:
5980 try:
5972 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
5981 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
5973 except OSError as inst:
5982 except OSError as inst:
5974 if inst.errno != errno.ENOENT:
5983 if inst.errno != errno.ENOENT:
5975 raise
5984 raise
5976
5985
5977 ms.commit()
5986 ms.commit()
5978 branchmerge = repo.dirstate.p2() != nullid
5987 branchmerge = repo.dirstate.p2() != nullid
5979 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
5988 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
5980
5989
5981 if not didwork and pats:
5990 if not didwork and pats:
5982 hint = None
5991 hint = None
5983 if not any([p for p in pats if p.find(b':') >= 0]):
5992 if not any([p for p in pats if p.find(b':') >= 0]):
5984 pats = [b'path:%s' % p for p in pats]
5993 pats = [b'path:%s' % p for p in pats]
5985 m = scmutil.match(wctx, pats, opts)
5994 m = scmutil.match(wctx, pats, opts)
5986 for f in ms:
5995 for f in ms:
5987 if not m(f):
5996 if not m(f):
5988 continue
5997 continue
5989
5998
5990 def flag(o):
5999 def flag(o):
5991 if o == b're_merge':
6000 if o == b're_merge':
5992 return b'--re-merge '
6001 return b'--re-merge '
5993 return b'-%s ' % o[0:1]
6002 return b'-%s ' % o[0:1]
5994
6003
5995 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6004 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
5996 hint = _(b"(try: hg resolve %s%s)\n") % (
6005 hint = _(b"(try: hg resolve %s%s)\n") % (
5997 flags,
6006 flags,
5998 b' '.join(pats),
6007 b' '.join(pats),
5999 )
6008 )
6000 break
6009 break
6001 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6010 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6002 if hint:
6011 if hint:
6003 ui.warn(hint)
6012 ui.warn(hint)
6004
6013
6005 unresolvedf = list(ms.unresolved())
6014 unresolvedf = list(ms.unresolved())
6006 if not unresolvedf:
6015 if not unresolvedf:
6007 ui.status(_(b'(no more unresolved files)\n'))
6016 ui.status(_(b'(no more unresolved files)\n'))
6008 cmdutil.checkafterresolved(repo)
6017 cmdutil.checkafterresolved(repo)
6009
6018
6010 return ret
6019 return ret
6011
6020
6012
6021
6013 @command(
6022 @command(
6014 b'revert',
6023 b'revert',
6015 [
6024 [
6016 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6025 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6017 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6026 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6018 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6027 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6019 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6028 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6020 (b'i', b'interactive', None, _(b'interactively select the changes')),
6029 (b'i', b'interactive', None, _(b'interactively select the changes')),
6021 ]
6030 ]
6022 + walkopts
6031 + walkopts
6023 + dryrunopts,
6032 + dryrunopts,
6024 _(b'[OPTION]... [-r REV] [NAME]...'),
6033 _(b'[OPTION]... [-r REV] [NAME]...'),
6025 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6034 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6026 )
6035 )
6027 def revert(ui, repo, *pats, **opts):
6036 def revert(ui, repo, *pats, **opts):
6028 """restore files to their checkout state
6037 """restore files to their checkout state
6029
6038
6030 .. note::
6039 .. note::
6031
6040
6032 To check out earlier revisions, you should use :hg:`update REV`.
6041 To check out earlier revisions, you should use :hg:`update REV`.
6033 To cancel an uncommitted merge (and lose your changes),
6042 To cancel an uncommitted merge (and lose your changes),
6034 use :hg:`merge --abort`.
6043 use :hg:`merge --abort`.
6035
6044
6036 With no revision specified, revert the specified files or directories
6045 With no revision specified, revert the specified files or directories
6037 to the contents they had in the parent of the working directory.
6046 to the contents they had in the parent of the working directory.
6038 This restores the contents of files to an unmodified
6047 This restores the contents of files to an unmodified
6039 state and unschedules adds, removes, copies, and renames. If the
6048 state and unschedules adds, removes, copies, and renames. If the
6040 working directory has two parents, you must explicitly specify a
6049 working directory has two parents, you must explicitly specify a
6041 revision.
6050 revision.
6042
6051
6043 Using the -r/--rev or -d/--date options, revert the given files or
6052 Using the -r/--rev or -d/--date options, revert the given files or
6044 directories to their states as of a specific revision. Because
6053 directories to their states as of a specific revision. Because
6045 revert does not change the working directory parents, this will
6054 revert does not change the working directory parents, this will
6046 cause these files to appear modified. This can be helpful to "back
6055 cause these files to appear modified. This can be helpful to "back
6047 out" some or all of an earlier change. See :hg:`backout` for a
6056 out" some or all of an earlier change. See :hg:`backout` for a
6048 related method.
6057 related method.
6049
6058
6050 Modified files are saved with a .orig suffix before reverting.
6059 Modified files are saved with a .orig suffix before reverting.
6051 To disable these backups, use --no-backup. It is possible to store
6060 To disable these backups, use --no-backup. It is possible to store
6052 the backup files in a custom directory relative to the root of the
6061 the backup files in a custom directory relative to the root of the
6053 repository by setting the ``ui.origbackuppath`` configuration
6062 repository by setting the ``ui.origbackuppath`` configuration
6054 option.
6063 option.
6055
6064
6056 See :hg:`help dates` for a list of formats valid for -d/--date.
6065 See :hg:`help dates` for a list of formats valid for -d/--date.
6057
6066
6058 See :hg:`help backout` for a way to reverse the effect of an
6067 See :hg:`help backout` for a way to reverse the effect of an
6059 earlier changeset.
6068 earlier changeset.
6060
6069
6061 Returns 0 on success.
6070 Returns 0 on success.
6062 """
6071 """
6063
6072
6064 opts = pycompat.byteskwargs(opts)
6073 opts = pycompat.byteskwargs(opts)
6065 if opts.get(b"date"):
6074 if opts.get(b"date"):
6066 cmdutil.check_incompatible_arguments(opts, b'date', [b'rev'])
6075 cmdutil.check_incompatible_arguments(opts, b'date', [b'rev'])
6067 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6076 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6068
6077
6069 parent, p2 = repo.dirstate.parents()
6078 parent, p2 = repo.dirstate.parents()
6070 if not opts.get(b'rev') and p2 != nullid:
6079 if not opts.get(b'rev') and p2 != nullid:
6071 # revert after merge is a trap for new users (issue2915)
6080 # revert after merge is a trap for new users (issue2915)
6072 raise error.Abort(
6081 raise error.Abort(
6073 _(b'uncommitted merge with no revision specified'),
6082 _(b'uncommitted merge with no revision specified'),
6074 hint=_(b"use 'hg update' or see 'hg help revert'"),
6083 hint=_(b"use 'hg update' or see 'hg help revert'"),
6075 )
6084 )
6076
6085
6077 rev = opts.get(b'rev')
6086 rev = opts.get(b'rev')
6078 if rev:
6087 if rev:
6079 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6088 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6080 ctx = scmutil.revsingle(repo, rev)
6089 ctx = scmutil.revsingle(repo, rev)
6081
6090
6082 if not (
6091 if not (
6083 pats
6092 pats
6084 or opts.get(b'include')
6093 or opts.get(b'include')
6085 or opts.get(b'exclude')
6094 or opts.get(b'exclude')
6086 or opts.get(b'all')
6095 or opts.get(b'all')
6087 or opts.get(b'interactive')
6096 or opts.get(b'interactive')
6088 ):
6097 ):
6089 msg = _(b"no files or directories specified")
6098 msg = _(b"no files or directories specified")
6090 if p2 != nullid:
6099 if p2 != nullid:
6091 hint = _(
6100 hint = _(
6092 b"uncommitted merge, use --all to discard all changes,"
6101 b"uncommitted merge, use --all to discard all changes,"
6093 b" or 'hg update -C .' to abort the merge"
6102 b" or 'hg update -C .' to abort the merge"
6094 )
6103 )
6095 raise error.Abort(msg, hint=hint)
6104 raise error.Abort(msg, hint=hint)
6096 dirty = any(repo.status())
6105 dirty = any(repo.status())
6097 node = ctx.node()
6106 node = ctx.node()
6098 if node != parent:
6107 if node != parent:
6099 if dirty:
6108 if dirty:
6100 hint = (
6109 hint = (
6101 _(
6110 _(
6102 b"uncommitted changes, use --all to discard all"
6111 b"uncommitted changes, use --all to discard all"
6103 b" changes, or 'hg update %d' to update"
6112 b" changes, or 'hg update %d' to update"
6104 )
6113 )
6105 % ctx.rev()
6114 % ctx.rev()
6106 )
6115 )
6107 else:
6116 else:
6108 hint = (
6117 hint = (
6109 _(
6118 _(
6110 b"use --all to revert all files,"
6119 b"use --all to revert all files,"
6111 b" or 'hg update %d' to update"
6120 b" or 'hg update %d' to update"
6112 )
6121 )
6113 % ctx.rev()
6122 % ctx.rev()
6114 )
6123 )
6115 elif dirty:
6124 elif dirty:
6116 hint = _(b"uncommitted changes, use --all to discard all changes")
6125 hint = _(b"uncommitted changes, use --all to discard all changes")
6117 else:
6126 else:
6118 hint = _(b"use --all to revert all files")
6127 hint = _(b"use --all to revert all files")
6119 raise error.Abort(msg, hint=hint)
6128 raise error.Abort(msg, hint=hint)
6120
6129
6121 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6130 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6122
6131
6123
6132
6124 @command(
6133 @command(
6125 b'rollback',
6134 b'rollback',
6126 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6135 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6127 helpcategory=command.CATEGORY_MAINTENANCE,
6136 helpcategory=command.CATEGORY_MAINTENANCE,
6128 )
6137 )
6129 def rollback(ui, repo, **opts):
6138 def rollback(ui, repo, **opts):
6130 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6139 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6131
6140
6132 Please use :hg:`commit --amend` instead of rollback to correct
6141 Please use :hg:`commit --amend` instead of rollback to correct
6133 mistakes in the last commit.
6142 mistakes in the last commit.
6134
6143
6135 This command should be used with care. There is only one level of
6144 This command should be used with care. There is only one level of
6136 rollback, and there is no way to undo a rollback. It will also
6145 rollback, and there is no way to undo a rollback. It will also
6137 restore the dirstate at the time of the last transaction, losing
6146 restore the dirstate at the time of the last transaction, losing
6138 any dirstate changes since that time. This command does not alter
6147 any dirstate changes since that time. This command does not alter
6139 the working directory.
6148 the working directory.
6140
6149
6141 Transactions are used to encapsulate the effects of all commands
6150 Transactions are used to encapsulate the effects of all commands
6142 that create new changesets or propagate existing changesets into a
6151 that create new changesets or propagate existing changesets into a
6143 repository.
6152 repository.
6144
6153
6145 .. container:: verbose
6154 .. container:: verbose
6146
6155
6147 For example, the following commands are transactional, and their
6156 For example, the following commands are transactional, and their
6148 effects can be rolled back:
6157 effects can be rolled back:
6149
6158
6150 - commit
6159 - commit
6151 - import
6160 - import
6152 - pull
6161 - pull
6153 - push (with this repository as the destination)
6162 - push (with this repository as the destination)
6154 - unbundle
6163 - unbundle
6155
6164
6156 To avoid permanent data loss, rollback will refuse to rollback a
6165 To avoid permanent data loss, rollback will refuse to rollback a
6157 commit transaction if it isn't checked out. Use --force to
6166 commit transaction if it isn't checked out. Use --force to
6158 override this protection.
6167 override this protection.
6159
6168
6160 The rollback command can be entirely disabled by setting the
6169 The rollback command can be entirely disabled by setting the
6161 ``ui.rollback`` configuration setting to false. If you're here
6170 ``ui.rollback`` configuration setting to false. If you're here
6162 because you want to use rollback and it's disabled, you can
6171 because you want to use rollback and it's disabled, you can
6163 re-enable the command by setting ``ui.rollback`` to true.
6172 re-enable the command by setting ``ui.rollback`` to true.
6164
6173
6165 This command is not intended for use on public repositories. Once
6174 This command is not intended for use on public repositories. Once
6166 changes are visible for pull by other users, rolling a transaction
6175 changes are visible for pull by other users, rolling a transaction
6167 back locally is ineffective (someone else may already have pulled
6176 back locally is ineffective (someone else may already have pulled
6168 the changes). Furthermore, a race is possible with readers of the
6177 the changes). Furthermore, a race is possible with readers of the
6169 repository; for example an in-progress pull from the repository
6178 repository; for example an in-progress pull from the repository
6170 may fail if a rollback is performed.
6179 may fail if a rollback is performed.
6171
6180
6172 Returns 0 on success, 1 if no rollback data is available.
6181 Returns 0 on success, 1 if no rollback data is available.
6173 """
6182 """
6174 if not ui.configbool(b'ui', b'rollback'):
6183 if not ui.configbool(b'ui', b'rollback'):
6175 raise error.Abort(
6184 raise error.Abort(
6176 _(b'rollback is disabled because it is unsafe'),
6185 _(b'rollback is disabled because it is unsafe'),
6177 hint=b'see `hg help -v rollback` for information',
6186 hint=b'see `hg help -v rollback` for information',
6178 )
6187 )
6179 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6188 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6180
6189
6181
6190
6182 @command(
6191 @command(
6183 b'root',
6192 b'root',
6184 [] + formatteropts,
6193 [] + formatteropts,
6185 intents={INTENT_READONLY},
6194 intents={INTENT_READONLY},
6186 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6195 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6187 )
6196 )
6188 def root(ui, repo, **opts):
6197 def root(ui, repo, **opts):
6189 """print the root (top) of the current working directory
6198 """print the root (top) of the current working directory
6190
6199
6191 Print the root directory of the current repository.
6200 Print the root directory of the current repository.
6192
6201
6193 .. container:: verbose
6202 .. container:: verbose
6194
6203
6195 Template:
6204 Template:
6196
6205
6197 The following keywords are supported in addition to the common template
6206 The following keywords are supported in addition to the common template
6198 keywords and functions. See also :hg:`help templates`.
6207 keywords and functions. See also :hg:`help templates`.
6199
6208
6200 :hgpath: String. Path to the .hg directory.
6209 :hgpath: String. Path to the .hg directory.
6201 :storepath: String. Path to the directory holding versioned data.
6210 :storepath: String. Path to the directory holding versioned data.
6202
6211
6203 Returns 0 on success.
6212 Returns 0 on success.
6204 """
6213 """
6205 opts = pycompat.byteskwargs(opts)
6214 opts = pycompat.byteskwargs(opts)
6206 with ui.formatter(b'root', opts) as fm:
6215 with ui.formatter(b'root', opts) as fm:
6207 fm.startitem()
6216 fm.startitem()
6208 fm.write(b'reporoot', b'%s\n', repo.root)
6217 fm.write(b'reporoot', b'%s\n', repo.root)
6209 fm.data(hgpath=repo.path, storepath=repo.spath)
6218 fm.data(hgpath=repo.path, storepath=repo.spath)
6210
6219
6211
6220
6212 @command(
6221 @command(
6213 b'serve',
6222 b'serve',
6214 [
6223 [
6215 (
6224 (
6216 b'A',
6225 b'A',
6217 b'accesslog',
6226 b'accesslog',
6218 b'',
6227 b'',
6219 _(b'name of access log file to write to'),
6228 _(b'name of access log file to write to'),
6220 _(b'FILE'),
6229 _(b'FILE'),
6221 ),
6230 ),
6222 (b'd', b'daemon', None, _(b'run server in background')),
6231 (b'd', b'daemon', None, _(b'run server in background')),
6223 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6232 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6224 (
6233 (
6225 b'E',
6234 b'E',
6226 b'errorlog',
6235 b'errorlog',
6227 b'',
6236 b'',
6228 _(b'name of error log file to write to'),
6237 _(b'name of error log file to write to'),
6229 _(b'FILE'),
6238 _(b'FILE'),
6230 ),
6239 ),
6231 # use string type, then we can check if something was passed
6240 # use string type, then we can check if something was passed
6232 (
6241 (
6233 b'p',
6242 b'p',
6234 b'port',
6243 b'port',
6235 b'',
6244 b'',
6236 _(b'port to listen on (default: 8000)'),
6245 _(b'port to listen on (default: 8000)'),
6237 _(b'PORT'),
6246 _(b'PORT'),
6238 ),
6247 ),
6239 (
6248 (
6240 b'a',
6249 b'a',
6241 b'address',
6250 b'address',
6242 b'',
6251 b'',
6243 _(b'address to listen on (default: all interfaces)'),
6252 _(b'address to listen on (default: all interfaces)'),
6244 _(b'ADDR'),
6253 _(b'ADDR'),
6245 ),
6254 ),
6246 (
6255 (
6247 b'',
6256 b'',
6248 b'prefix',
6257 b'prefix',
6249 b'',
6258 b'',
6250 _(b'prefix path to serve from (default: server root)'),
6259 _(b'prefix path to serve from (default: server root)'),
6251 _(b'PREFIX'),
6260 _(b'PREFIX'),
6252 ),
6261 ),
6253 (
6262 (
6254 b'n',
6263 b'n',
6255 b'name',
6264 b'name',
6256 b'',
6265 b'',
6257 _(b'name to show in web pages (default: working directory)'),
6266 _(b'name to show in web pages (default: working directory)'),
6258 _(b'NAME'),
6267 _(b'NAME'),
6259 ),
6268 ),
6260 (
6269 (
6261 b'',
6270 b'',
6262 b'web-conf',
6271 b'web-conf',
6263 b'',
6272 b'',
6264 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6273 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6265 _(b'FILE'),
6274 _(b'FILE'),
6266 ),
6275 ),
6267 (
6276 (
6268 b'',
6277 b'',
6269 b'webdir-conf',
6278 b'webdir-conf',
6270 b'',
6279 b'',
6271 _(b'name of the hgweb config file (DEPRECATED)'),
6280 _(b'name of the hgweb config file (DEPRECATED)'),
6272 _(b'FILE'),
6281 _(b'FILE'),
6273 ),
6282 ),
6274 (
6283 (
6275 b'',
6284 b'',
6276 b'pid-file',
6285 b'pid-file',
6277 b'',
6286 b'',
6278 _(b'name of file to write process ID to'),
6287 _(b'name of file to write process ID to'),
6279 _(b'FILE'),
6288 _(b'FILE'),
6280 ),
6289 ),
6281 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6290 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6282 (
6291 (
6283 b'',
6292 b'',
6284 b'cmdserver',
6293 b'cmdserver',
6285 b'',
6294 b'',
6286 _(b'for remote clients (ADVANCED)'),
6295 _(b'for remote clients (ADVANCED)'),
6287 _(b'MODE'),
6296 _(b'MODE'),
6288 ),
6297 ),
6289 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6298 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6290 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6299 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6291 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6300 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6292 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6301 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6293 (b'', b'print-url', None, _(b'start and print only the URL')),
6302 (b'', b'print-url', None, _(b'start and print only the URL')),
6294 ]
6303 ]
6295 + subrepoopts,
6304 + subrepoopts,
6296 _(b'[OPTION]...'),
6305 _(b'[OPTION]...'),
6297 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6306 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6298 helpbasic=True,
6307 helpbasic=True,
6299 optionalrepo=True,
6308 optionalrepo=True,
6300 )
6309 )
6301 def serve(ui, repo, **opts):
6310 def serve(ui, repo, **opts):
6302 """start stand-alone webserver
6311 """start stand-alone webserver
6303
6312
6304 Start a local HTTP repository browser and pull server. You can use
6313 Start a local HTTP repository browser and pull server. You can use
6305 this for ad-hoc sharing and browsing of repositories. It is
6314 this for ad-hoc sharing and browsing of repositories. It is
6306 recommended to use a real web server to serve a repository for
6315 recommended to use a real web server to serve a repository for
6307 longer periods of time.
6316 longer periods of time.
6308
6317
6309 Please note that the server does not implement access control.
6318 Please note that the server does not implement access control.
6310 This means that, by default, anybody can read from the server and
6319 This means that, by default, anybody can read from the server and
6311 nobody can write to it by default. Set the ``web.allow-push``
6320 nobody can write to it by default. Set the ``web.allow-push``
6312 option to ``*`` to allow everybody to push to the server. You
6321 option to ``*`` to allow everybody to push to the server. You
6313 should use a real web server if you need to authenticate users.
6322 should use a real web server if you need to authenticate users.
6314
6323
6315 By default, the server logs accesses to stdout and errors to
6324 By default, the server logs accesses to stdout and errors to
6316 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6325 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6317 files.
6326 files.
6318
6327
6319 To have the server choose a free port number to listen on, specify
6328 To have the server choose a free port number to listen on, specify
6320 a port number of 0; in this case, the server will print the port
6329 a port number of 0; in this case, the server will print the port
6321 number it uses.
6330 number it uses.
6322
6331
6323 Returns 0 on success.
6332 Returns 0 on success.
6324 """
6333 """
6325
6334
6326 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6335 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6327 opts = pycompat.byteskwargs(opts)
6336 opts = pycompat.byteskwargs(opts)
6328 if opts[b"print_url"] and ui.verbose:
6337 if opts[b"print_url"] and ui.verbose:
6329 raise error.Abort(_(b"cannot use --print-url with --verbose"))
6338 raise error.Abort(_(b"cannot use --print-url with --verbose"))
6330
6339
6331 if opts[b"stdio"]:
6340 if opts[b"stdio"]:
6332 if repo is None:
6341 if repo is None:
6333 raise error.RepoError(
6342 raise error.RepoError(
6334 _(b"there is no Mercurial repository here (.hg not found)")
6343 _(b"there is no Mercurial repository here (.hg not found)")
6335 )
6344 )
6336 s = wireprotoserver.sshserver(ui, repo)
6345 s = wireprotoserver.sshserver(ui, repo)
6337 s.serve_forever()
6346 s.serve_forever()
6338
6347
6339 service = server.createservice(ui, repo, opts)
6348 service = server.createservice(ui, repo, opts)
6340 return server.runservice(opts, initfn=service.init, runfn=service.run)
6349 return server.runservice(opts, initfn=service.init, runfn=service.run)
6341
6350
6342
6351
6343 @command(
6352 @command(
6344 b'shelve',
6353 b'shelve',
6345 [
6354 [
6346 (
6355 (
6347 b'A',
6356 b'A',
6348 b'addremove',
6357 b'addremove',
6349 None,
6358 None,
6350 _(b'mark new/missing files as added/removed before shelving'),
6359 _(b'mark new/missing files as added/removed before shelving'),
6351 ),
6360 ),
6352 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6361 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6353 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6362 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6354 (
6363 (
6355 b'',
6364 b'',
6356 b'date',
6365 b'date',
6357 b'',
6366 b'',
6358 _(b'shelve with the specified commit date'),
6367 _(b'shelve with the specified commit date'),
6359 _(b'DATE'),
6368 _(b'DATE'),
6360 ),
6369 ),
6361 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6370 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6362 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6371 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6363 (
6372 (
6364 b'k',
6373 b'k',
6365 b'keep',
6374 b'keep',
6366 False,
6375 False,
6367 _(b'shelve, but keep changes in the working directory'),
6376 _(b'shelve, but keep changes in the working directory'),
6368 ),
6377 ),
6369 (b'l', b'list', None, _(b'list current shelves')),
6378 (b'l', b'list', None, _(b'list current shelves')),
6370 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6379 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6371 (
6380 (
6372 b'n',
6381 b'n',
6373 b'name',
6382 b'name',
6374 b'',
6383 b'',
6375 _(b'use the given name for the shelved commit'),
6384 _(b'use the given name for the shelved commit'),
6376 _(b'NAME'),
6385 _(b'NAME'),
6377 ),
6386 ),
6378 (
6387 (
6379 b'p',
6388 b'p',
6380 b'patch',
6389 b'patch',
6381 None,
6390 None,
6382 _(
6391 _(
6383 b'output patches for changes (provide the names of the shelved '
6392 b'output patches for changes (provide the names of the shelved '
6384 b'changes as positional arguments)'
6393 b'changes as positional arguments)'
6385 ),
6394 ),
6386 ),
6395 ),
6387 (b'i', b'interactive', None, _(b'interactive mode')),
6396 (b'i', b'interactive', None, _(b'interactive mode')),
6388 (
6397 (
6389 b'',
6398 b'',
6390 b'stat',
6399 b'stat',
6391 None,
6400 None,
6392 _(
6401 _(
6393 b'output diffstat-style summary of changes (provide the names of '
6402 b'output diffstat-style summary of changes (provide the names of '
6394 b'the shelved changes as positional arguments)'
6403 b'the shelved changes as positional arguments)'
6395 ),
6404 ),
6396 ),
6405 ),
6397 ]
6406 ]
6398 + cmdutil.walkopts,
6407 + cmdutil.walkopts,
6399 _(b'hg shelve [OPTION]... [FILE]...'),
6408 _(b'hg shelve [OPTION]... [FILE]...'),
6400 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6409 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6401 )
6410 )
6402 def shelve(ui, repo, *pats, **opts):
6411 def shelve(ui, repo, *pats, **opts):
6403 '''save and set aside changes from the working directory
6412 '''save and set aside changes from the working directory
6404
6413
6405 Shelving takes files that "hg status" reports as not clean, saves
6414 Shelving takes files that "hg status" reports as not clean, saves
6406 the modifications to a bundle (a shelved change), and reverts the
6415 the modifications to a bundle (a shelved change), and reverts the
6407 files so that their state in the working directory becomes clean.
6416 files so that their state in the working directory becomes clean.
6408
6417
6409 To restore these changes to the working directory, using "hg
6418 To restore these changes to the working directory, using "hg
6410 unshelve"; this will work even if you switch to a different
6419 unshelve"; this will work even if you switch to a different
6411 commit.
6420 commit.
6412
6421
6413 When no files are specified, "hg shelve" saves all not-clean
6422 When no files are specified, "hg shelve" saves all not-clean
6414 files. If specific files or directories are named, only changes to
6423 files. If specific files or directories are named, only changes to
6415 those files are shelved.
6424 those files are shelved.
6416
6425
6417 In bare shelve (when no files are specified, without interactive,
6426 In bare shelve (when no files are specified, without interactive,
6418 include and exclude option), shelving remembers information if the
6427 include and exclude option), shelving remembers information if the
6419 working directory was on newly created branch, in other words working
6428 working directory was on newly created branch, in other words working
6420 directory was on different branch than its first parent. In this
6429 directory was on different branch than its first parent. In this
6421 situation unshelving restores branch information to the working directory.
6430 situation unshelving restores branch information to the working directory.
6422
6431
6423 Each shelved change has a name that makes it easier to find later.
6432 Each shelved change has a name that makes it easier to find later.
6424 The name of a shelved change defaults to being based on the active
6433 The name of a shelved change defaults to being based on the active
6425 bookmark, or if there is no active bookmark, the current named
6434 bookmark, or if there is no active bookmark, the current named
6426 branch. To specify a different name, use ``--name``.
6435 branch. To specify a different name, use ``--name``.
6427
6436
6428 To see a list of existing shelved changes, use the ``--list``
6437 To see a list of existing shelved changes, use the ``--list``
6429 option. For each shelved change, this will print its name, age,
6438 option. For each shelved change, this will print its name, age,
6430 and description; use ``--patch`` or ``--stat`` for more details.
6439 and description; use ``--patch`` or ``--stat`` for more details.
6431
6440
6432 To delete specific shelved changes, use ``--delete``. To delete
6441 To delete specific shelved changes, use ``--delete``. To delete
6433 all shelved changes, use ``--cleanup``.
6442 all shelved changes, use ``--cleanup``.
6434 '''
6443 '''
6435 opts = pycompat.byteskwargs(opts)
6444 opts = pycompat.byteskwargs(opts)
6436 allowables = [
6445 allowables = [
6437 (b'addremove', {b'create'}), # 'create' is pseudo action
6446 (b'addremove', {b'create'}), # 'create' is pseudo action
6438 (b'unknown', {b'create'}),
6447 (b'unknown', {b'create'}),
6439 (b'cleanup', {b'cleanup'}),
6448 (b'cleanup', {b'cleanup'}),
6440 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6449 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6441 (b'delete', {b'delete'}),
6450 (b'delete', {b'delete'}),
6442 (b'edit', {b'create'}),
6451 (b'edit', {b'create'}),
6443 (b'keep', {b'create'}),
6452 (b'keep', {b'create'}),
6444 (b'list', {b'list'}),
6453 (b'list', {b'list'}),
6445 (b'message', {b'create'}),
6454 (b'message', {b'create'}),
6446 (b'name', {b'create'}),
6455 (b'name', {b'create'}),
6447 (b'patch', {b'patch', b'list'}),
6456 (b'patch', {b'patch', b'list'}),
6448 (b'stat', {b'stat', b'list'}),
6457 (b'stat', {b'stat', b'list'}),
6449 ]
6458 ]
6450
6459
6451 def checkopt(opt):
6460 def checkopt(opt):
6452 if opts.get(opt):
6461 if opts.get(opt):
6453 for i, allowable in allowables:
6462 for i, allowable in allowables:
6454 if opts[i] and opt not in allowable:
6463 if opts[i] and opt not in allowable:
6455 raise error.Abort(
6464 raise error.Abort(
6456 _(
6465 _(
6457 b"options '--%s' and '--%s' may not be "
6466 b"options '--%s' and '--%s' may not be "
6458 b"used together"
6467 b"used together"
6459 )
6468 )
6460 % (opt, i)
6469 % (opt, i)
6461 )
6470 )
6462 return True
6471 return True
6463
6472
6464 if checkopt(b'cleanup'):
6473 if checkopt(b'cleanup'):
6465 if pats:
6474 if pats:
6466 raise error.Abort(_(b"cannot specify names when using '--cleanup'"))
6475 raise error.Abort(_(b"cannot specify names when using '--cleanup'"))
6467 return shelvemod.cleanupcmd(ui, repo)
6476 return shelvemod.cleanupcmd(ui, repo)
6468 elif checkopt(b'delete'):
6477 elif checkopt(b'delete'):
6469 return shelvemod.deletecmd(ui, repo, pats)
6478 return shelvemod.deletecmd(ui, repo, pats)
6470 elif checkopt(b'list'):
6479 elif checkopt(b'list'):
6471 return shelvemod.listcmd(ui, repo, pats, opts)
6480 return shelvemod.listcmd(ui, repo, pats, opts)
6472 elif checkopt(b'patch') or checkopt(b'stat'):
6481 elif checkopt(b'patch') or checkopt(b'stat'):
6473 return shelvemod.patchcmds(ui, repo, pats, opts)
6482 return shelvemod.patchcmds(ui, repo, pats, opts)
6474 else:
6483 else:
6475 return shelvemod.createcmd(ui, repo, pats, opts)
6484 return shelvemod.createcmd(ui, repo, pats, opts)
6476
6485
6477
6486
6478 _NOTTERSE = b'nothing'
6487 _NOTTERSE = b'nothing'
6479
6488
6480
6489
6481 @command(
6490 @command(
6482 b'status|st',
6491 b'status|st',
6483 [
6492 [
6484 (b'A', b'all', None, _(b'show status of all files')),
6493 (b'A', b'all', None, _(b'show status of all files')),
6485 (b'm', b'modified', None, _(b'show only modified files')),
6494 (b'm', b'modified', None, _(b'show only modified files')),
6486 (b'a', b'added', None, _(b'show only added files')),
6495 (b'a', b'added', None, _(b'show only added files')),
6487 (b'r', b'removed', None, _(b'show only removed files')),
6496 (b'r', b'removed', None, _(b'show only removed files')),
6488 (b'd', b'deleted', None, _(b'show only missing files')),
6497 (b'd', b'deleted', None, _(b'show only missing files')),
6489 (b'c', b'clean', None, _(b'show only files without changes')),
6498 (b'c', b'clean', None, _(b'show only files without changes')),
6490 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6499 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6491 (b'i', b'ignored', None, _(b'show only ignored files')),
6500 (b'i', b'ignored', None, _(b'show only ignored files')),
6492 (b'n', b'no-status', None, _(b'hide status prefix')),
6501 (b'n', b'no-status', None, _(b'hide status prefix')),
6493 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6502 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6494 (
6503 (
6495 b'C',
6504 b'C',
6496 b'copies',
6505 b'copies',
6497 None,
6506 None,
6498 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6507 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6499 ),
6508 ),
6500 (
6509 (
6501 b'0',
6510 b'0',
6502 b'print0',
6511 b'print0',
6503 None,
6512 None,
6504 _(b'end filenames with NUL, for use with xargs'),
6513 _(b'end filenames with NUL, for use with xargs'),
6505 ),
6514 ),
6506 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6515 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6507 (
6516 (
6508 b'',
6517 b'',
6509 b'change',
6518 b'change',
6510 b'',
6519 b'',
6511 _(b'list the changed files of a revision'),
6520 _(b'list the changed files of a revision'),
6512 _(b'REV'),
6521 _(b'REV'),
6513 ),
6522 ),
6514 ]
6523 ]
6515 + walkopts
6524 + walkopts
6516 + subrepoopts
6525 + subrepoopts
6517 + formatteropts,
6526 + formatteropts,
6518 _(b'[OPTION]... [FILE]...'),
6527 _(b'[OPTION]... [FILE]...'),
6519 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6528 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6520 helpbasic=True,
6529 helpbasic=True,
6521 inferrepo=True,
6530 inferrepo=True,
6522 intents={INTENT_READONLY},
6531 intents={INTENT_READONLY},
6523 )
6532 )
6524 def status(ui, repo, *pats, **opts):
6533 def status(ui, repo, *pats, **opts):
6525 """show changed files in the working directory
6534 """show changed files in the working directory
6526
6535
6527 Show status of files in the repository. If names are given, only
6536 Show status of files in the repository. If names are given, only
6528 files that match are shown. Files that are clean or ignored or
6537 files that match are shown. Files that are clean or ignored or
6529 the source of a copy/move operation, are not listed unless
6538 the source of a copy/move operation, are not listed unless
6530 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6539 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6531 Unless options described with "show only ..." are given, the
6540 Unless options described with "show only ..." are given, the
6532 options -mardu are used.
6541 options -mardu are used.
6533
6542
6534 Option -q/--quiet hides untracked (unknown and ignored) files
6543 Option -q/--quiet hides untracked (unknown and ignored) files
6535 unless explicitly requested with -u/--unknown or -i/--ignored.
6544 unless explicitly requested with -u/--unknown or -i/--ignored.
6536
6545
6537 .. note::
6546 .. note::
6538
6547
6539 :hg:`status` may appear to disagree with diff if permissions have
6548 :hg:`status` may appear to disagree with diff if permissions have
6540 changed or a merge has occurred. The standard diff format does
6549 changed or a merge has occurred. The standard diff format does
6541 not report permission changes and diff only reports changes
6550 not report permission changes and diff only reports changes
6542 relative to one merge parent.
6551 relative to one merge parent.
6543
6552
6544 If one revision is given, it is used as the base revision.
6553 If one revision is given, it is used as the base revision.
6545 If two revisions are given, the differences between them are
6554 If two revisions are given, the differences between them are
6546 shown. The --change option can also be used as a shortcut to list
6555 shown. The --change option can also be used as a shortcut to list
6547 the changed files of a revision from its first parent.
6556 the changed files of a revision from its first parent.
6548
6557
6549 The codes used to show the status of files are::
6558 The codes used to show the status of files are::
6550
6559
6551 M = modified
6560 M = modified
6552 A = added
6561 A = added
6553 R = removed
6562 R = removed
6554 C = clean
6563 C = clean
6555 ! = missing (deleted by non-hg command, but still tracked)
6564 ! = missing (deleted by non-hg command, but still tracked)
6556 ? = not tracked
6565 ? = not tracked
6557 I = ignored
6566 I = ignored
6558 = origin of the previous file (with --copies)
6567 = origin of the previous file (with --copies)
6559
6568
6560 .. container:: verbose
6569 .. container:: verbose
6561
6570
6562 The -t/--terse option abbreviates the output by showing only the directory
6571 The -t/--terse option abbreviates the output by showing only the directory
6563 name if all the files in it share the same status. The option takes an
6572 name if all the files in it share the same status. The option takes an
6564 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6573 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6565 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6574 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6566 for 'ignored' and 'c' for clean.
6575 for 'ignored' and 'c' for clean.
6567
6576
6568 It abbreviates only those statuses which are passed. Note that clean and
6577 It abbreviates only those statuses which are passed. Note that clean and
6569 ignored files are not displayed with '--terse ic' unless the -c/--clean
6578 ignored files are not displayed with '--terse ic' unless the -c/--clean
6570 and -i/--ignored options are also used.
6579 and -i/--ignored options are also used.
6571
6580
6572 The -v/--verbose option shows information when the repository is in an
6581 The -v/--verbose option shows information when the repository is in an
6573 unfinished merge, shelve, rebase state etc. You can have this behavior
6582 unfinished merge, shelve, rebase state etc. You can have this behavior
6574 turned on by default by enabling the ``commands.status.verbose`` option.
6583 turned on by default by enabling the ``commands.status.verbose`` option.
6575
6584
6576 You can skip displaying some of these states by setting
6585 You can skip displaying some of these states by setting
6577 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6586 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6578 'histedit', 'merge', 'rebase', or 'unshelve'.
6587 'histedit', 'merge', 'rebase', or 'unshelve'.
6579
6588
6580 Template:
6589 Template:
6581
6590
6582 The following keywords are supported in addition to the common template
6591 The following keywords are supported in addition to the common template
6583 keywords and functions. See also :hg:`help templates`.
6592 keywords and functions. See also :hg:`help templates`.
6584
6593
6585 :path: String. Repository-absolute path of the file.
6594 :path: String. Repository-absolute path of the file.
6586 :source: String. Repository-absolute path of the file originated from.
6595 :source: String. Repository-absolute path of the file originated from.
6587 Available if ``--copies`` is specified.
6596 Available if ``--copies`` is specified.
6588 :status: String. Character denoting file's status.
6597 :status: String. Character denoting file's status.
6589
6598
6590 Examples:
6599 Examples:
6591
6600
6592 - show changes in the working directory relative to a
6601 - show changes in the working directory relative to a
6593 changeset::
6602 changeset::
6594
6603
6595 hg status --rev 9353
6604 hg status --rev 9353
6596
6605
6597 - show changes in the working directory relative to the
6606 - show changes in the working directory relative to the
6598 current directory (see :hg:`help patterns` for more information)::
6607 current directory (see :hg:`help patterns` for more information)::
6599
6608
6600 hg status re:
6609 hg status re:
6601
6610
6602 - show all changes including copies in an existing changeset::
6611 - show all changes including copies in an existing changeset::
6603
6612
6604 hg status --copies --change 9353
6613 hg status --copies --change 9353
6605
6614
6606 - get a NUL separated list of added files, suitable for xargs::
6615 - get a NUL separated list of added files, suitable for xargs::
6607
6616
6608 hg status -an0
6617 hg status -an0
6609
6618
6610 - show more information about the repository status, abbreviating
6619 - show more information about the repository status, abbreviating
6611 added, removed, modified, deleted, and untracked paths::
6620 added, removed, modified, deleted, and untracked paths::
6612
6621
6613 hg status -v -t mardu
6622 hg status -v -t mardu
6614
6623
6615 Returns 0 on success.
6624 Returns 0 on success.
6616
6625
6617 """
6626 """
6618
6627
6619 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6628 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6620 opts = pycompat.byteskwargs(opts)
6629 opts = pycompat.byteskwargs(opts)
6621 revs = opts.get(b'rev')
6630 revs = opts.get(b'rev')
6622 change = opts.get(b'change')
6631 change = opts.get(b'change')
6623 terse = opts.get(b'terse')
6632 terse = opts.get(b'terse')
6624 if terse is _NOTTERSE:
6633 if terse is _NOTTERSE:
6625 if revs:
6634 if revs:
6626 terse = b''
6635 terse = b''
6627 else:
6636 else:
6628 terse = ui.config(b'commands', b'status.terse')
6637 terse = ui.config(b'commands', b'status.terse')
6629
6638
6630 if revs and terse:
6639 if revs and terse:
6631 msg = _(b'cannot use --terse with --rev')
6640 msg = _(b'cannot use --terse with --rev')
6632 raise error.Abort(msg)
6641 raise error.Abort(msg)
6633 elif change:
6642 elif change:
6634 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6643 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6635 ctx2 = scmutil.revsingle(repo, change, None)
6644 ctx2 = scmutil.revsingle(repo, change, None)
6636 ctx1 = ctx2.p1()
6645 ctx1 = ctx2.p1()
6637 else:
6646 else:
6638 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6647 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6639 ctx1, ctx2 = scmutil.revpair(repo, revs)
6648 ctx1, ctx2 = scmutil.revpair(repo, revs)
6640
6649
6641 forcerelativevalue = None
6650 forcerelativevalue = None
6642 if ui.hasconfig(b'commands', b'status.relative'):
6651 if ui.hasconfig(b'commands', b'status.relative'):
6643 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6652 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6644 uipathfn = scmutil.getuipathfn(
6653 uipathfn = scmutil.getuipathfn(
6645 repo,
6654 repo,
6646 legacyrelativevalue=bool(pats),
6655 legacyrelativevalue=bool(pats),
6647 forcerelativevalue=forcerelativevalue,
6656 forcerelativevalue=forcerelativevalue,
6648 )
6657 )
6649
6658
6650 if opts.get(b'print0'):
6659 if opts.get(b'print0'):
6651 end = b'\0'
6660 end = b'\0'
6652 else:
6661 else:
6653 end = b'\n'
6662 end = b'\n'
6654 states = b'modified added removed deleted unknown ignored clean'.split()
6663 states = b'modified added removed deleted unknown ignored clean'.split()
6655 show = [k for k in states if opts.get(k)]
6664 show = [k for k in states if opts.get(k)]
6656 if opts.get(b'all'):
6665 if opts.get(b'all'):
6657 show += ui.quiet and (states[:4] + [b'clean']) or states
6666 show += ui.quiet and (states[:4] + [b'clean']) or states
6658
6667
6659 if not show:
6668 if not show:
6660 if ui.quiet:
6669 if ui.quiet:
6661 show = states[:4]
6670 show = states[:4]
6662 else:
6671 else:
6663 show = states[:5]
6672 show = states[:5]
6664
6673
6665 m = scmutil.match(ctx2, pats, opts)
6674 m = scmutil.match(ctx2, pats, opts)
6666 if terse:
6675 if terse:
6667 # we need to compute clean and unknown to terse
6676 # we need to compute clean and unknown to terse
6668 stat = repo.status(
6677 stat = repo.status(
6669 ctx1.node(),
6678 ctx1.node(),
6670 ctx2.node(),
6679 ctx2.node(),
6671 m,
6680 m,
6672 b'ignored' in show or b'i' in terse,
6681 b'ignored' in show or b'i' in terse,
6673 clean=True,
6682 clean=True,
6674 unknown=True,
6683 unknown=True,
6675 listsubrepos=opts.get(b'subrepos'),
6684 listsubrepos=opts.get(b'subrepos'),
6676 )
6685 )
6677
6686
6678 stat = cmdutil.tersedir(stat, terse)
6687 stat = cmdutil.tersedir(stat, terse)
6679 else:
6688 else:
6680 stat = repo.status(
6689 stat = repo.status(
6681 ctx1.node(),
6690 ctx1.node(),
6682 ctx2.node(),
6691 ctx2.node(),
6683 m,
6692 m,
6684 b'ignored' in show,
6693 b'ignored' in show,
6685 b'clean' in show,
6694 b'clean' in show,
6686 b'unknown' in show,
6695 b'unknown' in show,
6687 opts.get(b'subrepos'),
6696 opts.get(b'subrepos'),
6688 )
6697 )
6689
6698
6690 changestates = zip(
6699 changestates = zip(
6691 states,
6700 states,
6692 pycompat.iterbytestr(b'MAR!?IC'),
6701 pycompat.iterbytestr(b'MAR!?IC'),
6693 [getattr(stat, s.decode('utf8')) for s in states],
6702 [getattr(stat, s.decode('utf8')) for s in states],
6694 )
6703 )
6695
6704
6696 copy = {}
6705 copy = {}
6697 if (
6706 if (
6698 opts.get(b'all')
6707 opts.get(b'all')
6699 or opts.get(b'copies')
6708 or opts.get(b'copies')
6700 or ui.configbool(b'ui', b'statuscopies')
6709 or ui.configbool(b'ui', b'statuscopies')
6701 ) and not opts.get(b'no_status'):
6710 ) and not opts.get(b'no_status'):
6702 copy = copies.pathcopies(ctx1, ctx2, m)
6711 copy = copies.pathcopies(ctx1, ctx2, m)
6703
6712
6704 morestatus = None
6713 morestatus = None
6705 if (
6714 if (
6706 ui.verbose or ui.configbool(b'commands', b'status.verbose')
6715 ui.verbose or ui.configbool(b'commands', b'status.verbose')
6707 ) and not ui.plain():
6716 ) and not ui.plain():
6708 morestatus = cmdutil.readmorestatus(repo)
6717 morestatus = cmdutil.readmorestatus(repo)
6709
6718
6710 ui.pager(b'status')
6719 ui.pager(b'status')
6711 fm = ui.formatter(b'status', opts)
6720 fm = ui.formatter(b'status', opts)
6712 fmt = b'%s' + end
6721 fmt = b'%s' + end
6713 showchar = not opts.get(b'no_status')
6722 showchar = not opts.get(b'no_status')
6714
6723
6715 for state, char, files in changestates:
6724 for state, char, files in changestates:
6716 if state in show:
6725 if state in show:
6717 label = b'status.' + state
6726 label = b'status.' + state
6718 for f in files:
6727 for f in files:
6719 fm.startitem()
6728 fm.startitem()
6720 fm.context(ctx=ctx2)
6729 fm.context(ctx=ctx2)
6721 fm.data(itemtype=b'file', path=f)
6730 fm.data(itemtype=b'file', path=f)
6722 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6731 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6723 fm.plain(fmt % uipathfn(f), label=label)
6732 fm.plain(fmt % uipathfn(f), label=label)
6724 if f in copy:
6733 if f in copy:
6725 fm.data(source=copy[f])
6734 fm.data(source=copy[f])
6726 fm.plain(
6735 fm.plain(
6727 (b' %s' + end) % uipathfn(copy[f]),
6736 (b' %s' + end) % uipathfn(copy[f]),
6728 label=b'status.copied',
6737 label=b'status.copied',
6729 )
6738 )
6730 if morestatus:
6739 if morestatus:
6731 morestatus.formatfile(f, fm)
6740 morestatus.formatfile(f, fm)
6732
6741
6733 if morestatus:
6742 if morestatus:
6734 morestatus.formatfooter(fm)
6743 morestatus.formatfooter(fm)
6735 fm.end()
6744 fm.end()
6736
6745
6737
6746
6738 @command(
6747 @command(
6739 b'summary|sum',
6748 b'summary|sum',
6740 [(b'', b'remote', None, _(b'check for push and pull'))],
6749 [(b'', b'remote', None, _(b'check for push and pull'))],
6741 b'[--remote]',
6750 b'[--remote]',
6742 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6751 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6743 helpbasic=True,
6752 helpbasic=True,
6744 intents={INTENT_READONLY},
6753 intents={INTENT_READONLY},
6745 )
6754 )
6746 def summary(ui, repo, **opts):
6755 def summary(ui, repo, **opts):
6747 """summarize working directory state
6756 """summarize working directory state
6748
6757
6749 This generates a brief summary of the working directory state,
6758 This generates a brief summary of the working directory state,
6750 including parents, branch, commit status, phase and available updates.
6759 including parents, branch, commit status, phase and available updates.
6751
6760
6752 With the --remote option, this will check the default paths for
6761 With the --remote option, this will check the default paths for
6753 incoming and outgoing changes. This can be time-consuming.
6762 incoming and outgoing changes. This can be time-consuming.
6754
6763
6755 Returns 0 on success.
6764 Returns 0 on success.
6756 """
6765 """
6757
6766
6758 opts = pycompat.byteskwargs(opts)
6767 opts = pycompat.byteskwargs(opts)
6759 ui.pager(b'summary')
6768 ui.pager(b'summary')
6760 ctx = repo[None]
6769 ctx = repo[None]
6761 parents = ctx.parents()
6770 parents = ctx.parents()
6762 pnode = parents[0].node()
6771 pnode = parents[0].node()
6763 marks = []
6772 marks = []
6764
6773
6765 try:
6774 try:
6766 ms = mergestatemod.mergestate.read(repo)
6775 ms = mergestatemod.mergestate.read(repo)
6767 except error.UnsupportedMergeRecords as e:
6776 except error.UnsupportedMergeRecords as e:
6768 s = b' '.join(e.recordtypes)
6777 s = b' '.join(e.recordtypes)
6769 ui.warn(
6778 ui.warn(
6770 _(b'warning: merge state has unsupported record types: %s\n') % s
6779 _(b'warning: merge state has unsupported record types: %s\n') % s
6771 )
6780 )
6772 unresolved = []
6781 unresolved = []
6773 else:
6782 else:
6774 unresolved = list(ms.unresolved())
6783 unresolved = list(ms.unresolved())
6775
6784
6776 for p in parents:
6785 for p in parents:
6777 # label with log.changeset (instead of log.parent) since this
6786 # label with log.changeset (instead of log.parent) since this
6778 # shows a working directory parent *changeset*:
6787 # shows a working directory parent *changeset*:
6779 # i18n: column positioning for "hg summary"
6788 # i18n: column positioning for "hg summary"
6780 ui.write(
6789 ui.write(
6781 _(b'parent: %d:%s ') % (p.rev(), p),
6790 _(b'parent: %d:%s ') % (p.rev(), p),
6782 label=logcmdutil.changesetlabels(p),
6791 label=logcmdutil.changesetlabels(p),
6783 )
6792 )
6784 ui.write(b' '.join(p.tags()), label=b'log.tag')
6793 ui.write(b' '.join(p.tags()), label=b'log.tag')
6785 if p.bookmarks():
6794 if p.bookmarks():
6786 marks.extend(p.bookmarks())
6795 marks.extend(p.bookmarks())
6787 if p.rev() == -1:
6796 if p.rev() == -1:
6788 if not len(repo):
6797 if not len(repo):
6789 ui.write(_(b' (empty repository)'))
6798 ui.write(_(b' (empty repository)'))
6790 else:
6799 else:
6791 ui.write(_(b' (no revision checked out)'))
6800 ui.write(_(b' (no revision checked out)'))
6792 if p.obsolete():
6801 if p.obsolete():
6793 ui.write(_(b' (obsolete)'))
6802 ui.write(_(b' (obsolete)'))
6794 if p.isunstable():
6803 if p.isunstable():
6795 instabilities = (
6804 instabilities = (
6796 ui.label(instability, b'trouble.%s' % instability)
6805 ui.label(instability, b'trouble.%s' % instability)
6797 for instability in p.instabilities()
6806 for instability in p.instabilities()
6798 )
6807 )
6799 ui.write(b' (' + b', '.join(instabilities) + b')')
6808 ui.write(b' (' + b', '.join(instabilities) + b')')
6800 ui.write(b'\n')
6809 ui.write(b'\n')
6801 if p.description():
6810 if p.description():
6802 ui.status(
6811 ui.status(
6803 b' ' + p.description().splitlines()[0].strip() + b'\n',
6812 b' ' + p.description().splitlines()[0].strip() + b'\n',
6804 label=b'log.summary',
6813 label=b'log.summary',
6805 )
6814 )
6806
6815
6807 branch = ctx.branch()
6816 branch = ctx.branch()
6808 bheads = repo.branchheads(branch)
6817 bheads = repo.branchheads(branch)
6809 # i18n: column positioning for "hg summary"
6818 # i18n: column positioning for "hg summary"
6810 m = _(b'branch: %s\n') % branch
6819 m = _(b'branch: %s\n') % branch
6811 if branch != b'default':
6820 if branch != b'default':
6812 ui.write(m, label=b'log.branch')
6821 ui.write(m, label=b'log.branch')
6813 else:
6822 else:
6814 ui.status(m, label=b'log.branch')
6823 ui.status(m, label=b'log.branch')
6815
6824
6816 if marks:
6825 if marks:
6817 active = repo._activebookmark
6826 active = repo._activebookmark
6818 # i18n: column positioning for "hg summary"
6827 # i18n: column positioning for "hg summary"
6819 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
6828 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
6820 if active is not None:
6829 if active is not None:
6821 if active in marks:
6830 if active in marks:
6822 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
6831 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
6823 marks.remove(active)
6832 marks.remove(active)
6824 else:
6833 else:
6825 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
6834 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
6826 for m in marks:
6835 for m in marks:
6827 ui.write(b' ' + m, label=b'log.bookmark')
6836 ui.write(b' ' + m, label=b'log.bookmark')
6828 ui.write(b'\n', label=b'log.bookmark')
6837 ui.write(b'\n', label=b'log.bookmark')
6829
6838
6830 status = repo.status(unknown=True)
6839 status = repo.status(unknown=True)
6831
6840
6832 c = repo.dirstate.copies()
6841 c = repo.dirstate.copies()
6833 copied, renamed = [], []
6842 copied, renamed = [], []
6834 for d, s in pycompat.iteritems(c):
6843 for d, s in pycompat.iteritems(c):
6835 if s in status.removed:
6844 if s in status.removed:
6836 status.removed.remove(s)
6845 status.removed.remove(s)
6837 renamed.append(d)
6846 renamed.append(d)
6838 else:
6847 else:
6839 copied.append(d)
6848 copied.append(d)
6840 if d in status.added:
6849 if d in status.added:
6841 status.added.remove(d)
6850 status.added.remove(d)
6842
6851
6843 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6852 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6844
6853
6845 labels = [
6854 labels = [
6846 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
6855 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
6847 (ui.label(_(b'%d added'), b'status.added'), status.added),
6856 (ui.label(_(b'%d added'), b'status.added'), status.added),
6848 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
6857 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
6849 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
6858 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
6850 (ui.label(_(b'%d copied'), b'status.copied'), copied),
6859 (ui.label(_(b'%d copied'), b'status.copied'), copied),
6851 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
6860 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
6852 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
6861 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
6853 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
6862 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
6854 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
6863 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
6855 ]
6864 ]
6856 t = []
6865 t = []
6857 for l, s in labels:
6866 for l, s in labels:
6858 if s:
6867 if s:
6859 t.append(l % len(s))
6868 t.append(l % len(s))
6860
6869
6861 t = b', '.join(t)
6870 t = b', '.join(t)
6862 cleanworkdir = False
6871 cleanworkdir = False
6863
6872
6864 if repo.vfs.exists(b'graftstate'):
6873 if repo.vfs.exists(b'graftstate'):
6865 t += _(b' (graft in progress)')
6874 t += _(b' (graft in progress)')
6866 if repo.vfs.exists(b'updatestate'):
6875 if repo.vfs.exists(b'updatestate'):
6867 t += _(b' (interrupted update)')
6876 t += _(b' (interrupted update)')
6868 elif len(parents) > 1:
6877 elif len(parents) > 1:
6869 t += _(b' (merge)')
6878 t += _(b' (merge)')
6870 elif branch != parents[0].branch():
6879 elif branch != parents[0].branch():
6871 t += _(b' (new branch)')
6880 t += _(b' (new branch)')
6872 elif parents[0].closesbranch() and pnode in repo.branchheads(
6881 elif parents[0].closesbranch() and pnode in repo.branchheads(
6873 branch, closed=True
6882 branch, closed=True
6874 ):
6883 ):
6875 t += _(b' (head closed)')
6884 t += _(b' (head closed)')
6876 elif not (
6885 elif not (
6877 status.modified
6886 status.modified
6878 or status.added
6887 or status.added
6879 or status.removed
6888 or status.removed
6880 or renamed
6889 or renamed
6881 or copied
6890 or copied
6882 or subs
6891 or subs
6883 ):
6892 ):
6884 t += _(b' (clean)')
6893 t += _(b' (clean)')
6885 cleanworkdir = True
6894 cleanworkdir = True
6886 elif pnode not in bheads:
6895 elif pnode not in bheads:
6887 t += _(b' (new branch head)')
6896 t += _(b' (new branch head)')
6888
6897
6889 if parents:
6898 if parents:
6890 pendingphase = max(p.phase() for p in parents)
6899 pendingphase = max(p.phase() for p in parents)
6891 else:
6900 else:
6892 pendingphase = phases.public
6901 pendingphase = phases.public
6893
6902
6894 if pendingphase > phases.newcommitphase(ui):
6903 if pendingphase > phases.newcommitphase(ui):
6895 t += b' (%s)' % phases.phasenames[pendingphase]
6904 t += b' (%s)' % phases.phasenames[pendingphase]
6896
6905
6897 if cleanworkdir:
6906 if cleanworkdir:
6898 # i18n: column positioning for "hg summary"
6907 # i18n: column positioning for "hg summary"
6899 ui.status(_(b'commit: %s\n') % t.strip())
6908 ui.status(_(b'commit: %s\n') % t.strip())
6900 else:
6909 else:
6901 # i18n: column positioning for "hg summary"
6910 # i18n: column positioning for "hg summary"
6902 ui.write(_(b'commit: %s\n') % t.strip())
6911 ui.write(_(b'commit: %s\n') % t.strip())
6903
6912
6904 # all ancestors of branch heads - all ancestors of parent = new csets
6913 # all ancestors of branch heads - all ancestors of parent = new csets
6905 new = len(
6914 new = len(
6906 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
6915 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
6907 )
6916 )
6908
6917
6909 if new == 0:
6918 if new == 0:
6910 # i18n: column positioning for "hg summary"
6919 # i18n: column positioning for "hg summary"
6911 ui.status(_(b'update: (current)\n'))
6920 ui.status(_(b'update: (current)\n'))
6912 elif pnode not in bheads:
6921 elif pnode not in bheads:
6913 # i18n: column positioning for "hg summary"
6922 # i18n: column positioning for "hg summary"
6914 ui.write(_(b'update: %d new changesets (update)\n') % new)
6923 ui.write(_(b'update: %d new changesets (update)\n') % new)
6915 else:
6924 else:
6916 # i18n: column positioning for "hg summary"
6925 # i18n: column positioning for "hg summary"
6917 ui.write(
6926 ui.write(
6918 _(b'update: %d new changesets, %d branch heads (merge)\n')
6927 _(b'update: %d new changesets, %d branch heads (merge)\n')
6919 % (new, len(bheads))
6928 % (new, len(bheads))
6920 )
6929 )
6921
6930
6922 t = []
6931 t = []
6923 draft = len(repo.revs(b'draft()'))
6932 draft = len(repo.revs(b'draft()'))
6924 if draft:
6933 if draft:
6925 t.append(_(b'%d draft') % draft)
6934 t.append(_(b'%d draft') % draft)
6926 secret = len(repo.revs(b'secret()'))
6935 secret = len(repo.revs(b'secret()'))
6927 if secret:
6936 if secret:
6928 t.append(_(b'%d secret') % secret)
6937 t.append(_(b'%d secret') % secret)
6929
6938
6930 if draft or secret:
6939 if draft or secret:
6931 ui.status(_(b'phases: %s\n') % b', '.join(t))
6940 ui.status(_(b'phases: %s\n') % b', '.join(t))
6932
6941
6933 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6942 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6934 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
6943 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
6935 numtrouble = len(repo.revs(trouble + b"()"))
6944 numtrouble = len(repo.revs(trouble + b"()"))
6936 # We write all the possibilities to ease translation
6945 # We write all the possibilities to ease translation
6937 troublemsg = {
6946 troublemsg = {
6938 b"orphan": _(b"orphan: %d changesets"),
6947 b"orphan": _(b"orphan: %d changesets"),
6939 b"contentdivergent": _(b"content-divergent: %d changesets"),
6948 b"contentdivergent": _(b"content-divergent: %d changesets"),
6940 b"phasedivergent": _(b"phase-divergent: %d changesets"),
6949 b"phasedivergent": _(b"phase-divergent: %d changesets"),
6941 }
6950 }
6942 if numtrouble > 0:
6951 if numtrouble > 0:
6943 ui.status(troublemsg[trouble] % numtrouble + b"\n")
6952 ui.status(troublemsg[trouble] % numtrouble + b"\n")
6944
6953
6945 cmdutil.summaryhooks(ui, repo)
6954 cmdutil.summaryhooks(ui, repo)
6946
6955
6947 if opts.get(b'remote'):
6956 if opts.get(b'remote'):
6948 needsincoming, needsoutgoing = True, True
6957 needsincoming, needsoutgoing = True, True
6949 else:
6958 else:
6950 needsincoming, needsoutgoing = False, False
6959 needsincoming, needsoutgoing = False, False
6951 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6960 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6952 if i:
6961 if i:
6953 needsincoming = True
6962 needsincoming = True
6954 if o:
6963 if o:
6955 needsoutgoing = True
6964 needsoutgoing = True
6956 if not needsincoming and not needsoutgoing:
6965 if not needsincoming and not needsoutgoing:
6957 return
6966 return
6958
6967
6959 def getincoming():
6968 def getincoming():
6960 source, branches = hg.parseurl(ui.expandpath(b'default'))
6969 source, branches = hg.parseurl(ui.expandpath(b'default'))
6961 sbranch = branches[0]
6970 sbranch = branches[0]
6962 try:
6971 try:
6963 other = hg.peer(repo, {}, source)
6972 other = hg.peer(repo, {}, source)
6964 except error.RepoError:
6973 except error.RepoError:
6965 if opts.get(b'remote'):
6974 if opts.get(b'remote'):
6966 raise
6975 raise
6967 return source, sbranch, None, None, None
6976 return source, sbranch, None, None, None
6968 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6977 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6969 if revs:
6978 if revs:
6970 revs = [other.lookup(rev) for rev in revs]
6979 revs = [other.lookup(rev) for rev in revs]
6971 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
6980 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
6972 repo.ui.pushbuffer()
6981 repo.ui.pushbuffer()
6973 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6982 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6974 repo.ui.popbuffer()
6983 repo.ui.popbuffer()
6975 return source, sbranch, other, commoninc, commoninc[1]
6984 return source, sbranch, other, commoninc, commoninc[1]
6976
6985
6977 if needsincoming:
6986 if needsincoming:
6978 source, sbranch, sother, commoninc, incoming = getincoming()
6987 source, sbranch, sother, commoninc, incoming = getincoming()
6979 else:
6988 else:
6980 source = sbranch = sother = commoninc = incoming = None
6989 source = sbranch = sother = commoninc = incoming = None
6981
6990
6982 def getoutgoing():
6991 def getoutgoing():
6983 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
6992 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
6984 dbranch = branches[0]
6993 dbranch = branches[0]
6985 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6994 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6986 if source != dest:
6995 if source != dest:
6987 try:
6996 try:
6988 dother = hg.peer(repo, {}, dest)
6997 dother = hg.peer(repo, {}, dest)
6989 except error.RepoError:
6998 except error.RepoError:
6990 if opts.get(b'remote'):
6999 if opts.get(b'remote'):
6991 raise
7000 raise
6992 return dest, dbranch, None, None
7001 return dest, dbranch, None, None
6993 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7002 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
6994 elif sother is None:
7003 elif sother is None:
6995 # there is no explicit destination peer, but source one is invalid
7004 # there is no explicit destination peer, but source one is invalid
6996 return dest, dbranch, None, None
7005 return dest, dbranch, None, None
6997 else:
7006 else:
6998 dother = sother
7007 dother = sother
6999 if source != dest or (sbranch is not None and sbranch != dbranch):
7008 if source != dest or (sbranch is not None and sbranch != dbranch):
7000 common = None
7009 common = None
7001 else:
7010 else:
7002 common = commoninc
7011 common = commoninc
7003 if revs:
7012 if revs:
7004 revs = [repo.lookup(rev) for rev in revs]
7013 revs = [repo.lookup(rev) for rev in revs]
7005 repo.ui.pushbuffer()
7014 repo.ui.pushbuffer()
7006 outgoing = discovery.findcommonoutgoing(
7015 outgoing = discovery.findcommonoutgoing(
7007 repo, dother, onlyheads=revs, commoninc=common
7016 repo, dother, onlyheads=revs, commoninc=common
7008 )
7017 )
7009 repo.ui.popbuffer()
7018 repo.ui.popbuffer()
7010 return dest, dbranch, dother, outgoing
7019 return dest, dbranch, dother, outgoing
7011
7020
7012 if needsoutgoing:
7021 if needsoutgoing:
7013 dest, dbranch, dother, outgoing = getoutgoing()
7022 dest, dbranch, dother, outgoing = getoutgoing()
7014 else:
7023 else:
7015 dest = dbranch = dother = outgoing = None
7024 dest = dbranch = dother = outgoing = None
7016
7025
7017 if opts.get(b'remote'):
7026 if opts.get(b'remote'):
7018 t = []
7027 t = []
7019 if incoming:
7028 if incoming:
7020 t.append(_(b'1 or more incoming'))
7029 t.append(_(b'1 or more incoming'))
7021 o = outgoing.missing
7030 o = outgoing.missing
7022 if o:
7031 if o:
7023 t.append(_(b'%d outgoing') % len(o))
7032 t.append(_(b'%d outgoing') % len(o))
7024 other = dother or sother
7033 other = dother or sother
7025 if b'bookmarks' in other.listkeys(b'namespaces'):
7034 if b'bookmarks' in other.listkeys(b'namespaces'):
7026 counts = bookmarks.summary(repo, other)
7035 counts = bookmarks.summary(repo, other)
7027 if counts[0] > 0:
7036 if counts[0] > 0:
7028 t.append(_(b'%d incoming bookmarks') % counts[0])
7037 t.append(_(b'%d incoming bookmarks') % counts[0])
7029 if counts[1] > 0:
7038 if counts[1] > 0:
7030 t.append(_(b'%d outgoing bookmarks') % counts[1])
7039 t.append(_(b'%d outgoing bookmarks') % counts[1])
7031
7040
7032 if t:
7041 if t:
7033 # i18n: column positioning for "hg summary"
7042 # i18n: column positioning for "hg summary"
7034 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7043 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7035 else:
7044 else:
7036 # i18n: column positioning for "hg summary"
7045 # i18n: column positioning for "hg summary"
7037 ui.status(_(b'remote: (synced)\n'))
7046 ui.status(_(b'remote: (synced)\n'))
7038
7047
7039 cmdutil.summaryremotehooks(
7048 cmdutil.summaryremotehooks(
7040 ui,
7049 ui,
7041 repo,
7050 repo,
7042 opts,
7051 opts,
7043 (
7052 (
7044 (source, sbranch, sother, commoninc),
7053 (source, sbranch, sother, commoninc),
7045 (dest, dbranch, dother, outgoing),
7054 (dest, dbranch, dother, outgoing),
7046 ),
7055 ),
7047 )
7056 )
7048
7057
7049
7058
7050 @command(
7059 @command(
7051 b'tag',
7060 b'tag',
7052 [
7061 [
7053 (b'f', b'force', None, _(b'force tag')),
7062 (b'f', b'force', None, _(b'force tag')),
7054 (b'l', b'local', None, _(b'make the tag local')),
7063 (b'l', b'local', None, _(b'make the tag local')),
7055 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7064 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7056 (b'', b'remove', None, _(b'remove a tag')),
7065 (b'', b'remove', None, _(b'remove a tag')),
7057 # -l/--local is already there, commitopts cannot be used
7066 # -l/--local is already there, commitopts cannot be used
7058 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7067 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7059 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7068 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7060 ]
7069 ]
7061 + commitopts2,
7070 + commitopts2,
7062 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7071 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7063 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7072 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7064 )
7073 )
7065 def tag(ui, repo, name1, *names, **opts):
7074 def tag(ui, repo, name1, *names, **opts):
7066 """add one or more tags for the current or given revision
7075 """add one or more tags for the current or given revision
7067
7076
7068 Name a particular revision using <name>.
7077 Name a particular revision using <name>.
7069
7078
7070 Tags are used to name particular revisions of the repository and are
7079 Tags are used to name particular revisions of the repository and are
7071 very useful to compare different revisions, to go back to significant
7080 very useful to compare different revisions, to go back to significant
7072 earlier versions or to mark branch points as releases, etc. Changing
7081 earlier versions or to mark branch points as releases, etc. Changing
7073 an existing tag is normally disallowed; use -f/--force to override.
7082 an existing tag is normally disallowed; use -f/--force to override.
7074
7083
7075 If no revision is given, the parent of the working directory is
7084 If no revision is given, the parent of the working directory is
7076 used.
7085 used.
7077
7086
7078 To facilitate version control, distribution, and merging of tags,
7087 To facilitate version control, distribution, and merging of tags,
7079 they are stored as a file named ".hgtags" which is managed similarly
7088 they are stored as a file named ".hgtags" which is managed similarly
7080 to other project files and can be hand-edited if necessary. This
7089 to other project files and can be hand-edited if necessary. This
7081 also means that tagging creates a new commit. The file
7090 also means that tagging creates a new commit. The file
7082 ".hg/localtags" is used for local tags (not shared among
7091 ".hg/localtags" is used for local tags (not shared among
7083 repositories).
7092 repositories).
7084
7093
7085 Tag commits are usually made at the head of a branch. If the parent
7094 Tag commits are usually made at the head of a branch. If the parent
7086 of the working directory is not a branch head, :hg:`tag` aborts; use
7095 of the working directory is not a branch head, :hg:`tag` aborts; use
7087 -f/--force to force the tag commit to be based on a non-head
7096 -f/--force to force the tag commit to be based on a non-head
7088 changeset.
7097 changeset.
7089
7098
7090 See :hg:`help dates` for a list of formats valid for -d/--date.
7099 See :hg:`help dates` for a list of formats valid for -d/--date.
7091
7100
7092 Since tag names have priority over branch names during revision
7101 Since tag names have priority over branch names during revision
7093 lookup, using an existing branch name as a tag name is discouraged.
7102 lookup, using an existing branch name as a tag name is discouraged.
7094
7103
7095 Returns 0 on success.
7104 Returns 0 on success.
7096 """
7105 """
7097 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7106 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7098 opts = pycompat.byteskwargs(opts)
7107 opts = pycompat.byteskwargs(opts)
7099 with repo.wlock(), repo.lock():
7108 with repo.wlock(), repo.lock():
7100 rev_ = b"."
7109 rev_ = b"."
7101 names = [t.strip() for t in (name1,) + names]
7110 names = [t.strip() for t in (name1,) + names]
7102 if len(names) != len(set(names)):
7111 if len(names) != len(set(names)):
7103 raise error.Abort(_(b'tag names must be unique'))
7112 raise error.Abort(_(b'tag names must be unique'))
7104 for n in names:
7113 for n in names:
7105 scmutil.checknewlabel(repo, n, b'tag')
7114 scmutil.checknewlabel(repo, n, b'tag')
7106 if not n:
7115 if not n:
7107 raise error.Abort(
7116 raise error.Abort(
7108 _(b'tag names cannot consist entirely of whitespace')
7117 _(b'tag names cannot consist entirely of whitespace')
7109 )
7118 )
7110 if opts.get(b'rev'):
7119 if opts.get(b'rev'):
7111 rev_ = opts[b'rev']
7120 rev_ = opts[b'rev']
7112 message = opts.get(b'message')
7121 message = opts.get(b'message')
7113 if opts.get(b'remove'):
7122 if opts.get(b'remove'):
7114 if opts.get(b'local'):
7123 if opts.get(b'local'):
7115 expectedtype = b'local'
7124 expectedtype = b'local'
7116 else:
7125 else:
7117 expectedtype = b'global'
7126 expectedtype = b'global'
7118
7127
7119 for n in names:
7128 for n in names:
7120 if repo.tagtype(n) == b'global':
7129 if repo.tagtype(n) == b'global':
7121 alltags = tagsmod.findglobaltags(ui, repo)
7130 alltags = tagsmod.findglobaltags(ui, repo)
7122 if alltags[n][0] == nullid:
7131 if alltags[n][0] == nullid:
7123 raise error.Abort(_(b"tag '%s' is already removed") % n)
7132 raise error.Abort(_(b"tag '%s' is already removed") % n)
7124 if not repo.tagtype(n):
7133 if not repo.tagtype(n):
7125 raise error.Abort(_(b"tag '%s' does not exist") % n)
7134 raise error.Abort(_(b"tag '%s' does not exist") % n)
7126 if repo.tagtype(n) != expectedtype:
7135 if repo.tagtype(n) != expectedtype:
7127 if expectedtype == b'global':
7136 if expectedtype == b'global':
7128 raise error.Abort(
7137 raise error.Abort(
7129 _(b"tag '%s' is not a global tag") % n
7138 _(b"tag '%s' is not a global tag") % n
7130 )
7139 )
7131 else:
7140 else:
7132 raise error.Abort(_(b"tag '%s' is not a local tag") % n)
7141 raise error.Abort(_(b"tag '%s' is not a local tag") % n)
7133 rev_ = b'null'
7142 rev_ = b'null'
7134 if not message:
7143 if not message:
7135 # we don't translate commit messages
7144 # we don't translate commit messages
7136 message = b'Removed tag %s' % b', '.join(names)
7145 message = b'Removed tag %s' % b', '.join(names)
7137 elif not opts.get(b'force'):
7146 elif not opts.get(b'force'):
7138 for n in names:
7147 for n in names:
7139 if n in repo.tags():
7148 if n in repo.tags():
7140 raise error.Abort(
7149 raise error.Abort(
7141 _(b"tag '%s' already exists (use -f to force)") % n
7150 _(b"tag '%s' already exists (use -f to force)") % n
7142 )
7151 )
7143 if not opts.get(b'local'):
7152 if not opts.get(b'local'):
7144 p1, p2 = repo.dirstate.parents()
7153 p1, p2 = repo.dirstate.parents()
7145 if p2 != nullid:
7154 if p2 != nullid:
7146 raise error.Abort(_(b'uncommitted merge'))
7155 raise error.Abort(_(b'uncommitted merge'))
7147 bheads = repo.branchheads()
7156 bheads = repo.branchheads()
7148 if not opts.get(b'force') and bheads and p1 not in bheads:
7157 if not opts.get(b'force') and bheads and p1 not in bheads:
7149 raise error.Abort(
7158 raise error.Abort(
7150 _(
7159 _(
7151 b'working directory is not at a branch head '
7160 b'working directory is not at a branch head '
7152 b'(use -f to force)'
7161 b'(use -f to force)'
7153 )
7162 )
7154 )
7163 )
7155 node = scmutil.revsingle(repo, rev_).node()
7164 node = scmutil.revsingle(repo, rev_).node()
7156
7165
7157 if not message:
7166 if not message:
7158 # we don't translate commit messages
7167 # we don't translate commit messages
7159 message = b'Added tag %s for changeset %s' % (
7168 message = b'Added tag %s for changeset %s' % (
7160 b', '.join(names),
7169 b', '.join(names),
7161 short(node),
7170 short(node),
7162 )
7171 )
7163
7172
7164 date = opts.get(b'date')
7173 date = opts.get(b'date')
7165 if date:
7174 if date:
7166 date = dateutil.parsedate(date)
7175 date = dateutil.parsedate(date)
7167
7176
7168 if opts.get(b'remove'):
7177 if opts.get(b'remove'):
7169 editform = b'tag.remove'
7178 editform = b'tag.remove'
7170 else:
7179 else:
7171 editform = b'tag.add'
7180 editform = b'tag.add'
7172 editor = cmdutil.getcommiteditor(
7181 editor = cmdutil.getcommiteditor(
7173 editform=editform, **pycompat.strkwargs(opts)
7182 editform=editform, **pycompat.strkwargs(opts)
7174 )
7183 )
7175
7184
7176 # don't allow tagging the null rev
7185 # don't allow tagging the null rev
7177 if (
7186 if (
7178 not opts.get(b'remove')
7187 not opts.get(b'remove')
7179 and scmutil.revsingle(repo, rev_).rev() == nullrev
7188 and scmutil.revsingle(repo, rev_).rev() == nullrev
7180 ):
7189 ):
7181 raise error.Abort(_(b"cannot tag null revision"))
7190 raise error.Abort(_(b"cannot tag null revision"))
7182
7191
7183 tagsmod.tag(
7192 tagsmod.tag(
7184 repo,
7193 repo,
7185 names,
7194 names,
7186 node,
7195 node,
7187 message,
7196 message,
7188 opts.get(b'local'),
7197 opts.get(b'local'),
7189 opts.get(b'user'),
7198 opts.get(b'user'),
7190 date,
7199 date,
7191 editor=editor,
7200 editor=editor,
7192 )
7201 )
7193
7202
7194
7203
7195 @command(
7204 @command(
7196 b'tags',
7205 b'tags',
7197 formatteropts,
7206 formatteropts,
7198 b'',
7207 b'',
7199 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7208 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7200 intents={INTENT_READONLY},
7209 intents={INTENT_READONLY},
7201 )
7210 )
7202 def tags(ui, repo, **opts):
7211 def tags(ui, repo, **opts):
7203 """list repository tags
7212 """list repository tags
7204
7213
7205 This lists both regular and local tags. When the -v/--verbose
7214 This lists both regular and local tags. When the -v/--verbose
7206 switch is used, a third column "local" is printed for local tags.
7215 switch is used, a third column "local" is printed for local tags.
7207 When the -q/--quiet switch is used, only the tag name is printed.
7216 When the -q/--quiet switch is used, only the tag name is printed.
7208
7217
7209 .. container:: verbose
7218 .. container:: verbose
7210
7219
7211 Template:
7220 Template:
7212
7221
7213 The following keywords are supported in addition to the common template
7222 The following keywords are supported in addition to the common template
7214 keywords and functions such as ``{tag}``. See also
7223 keywords and functions such as ``{tag}``. See also
7215 :hg:`help templates`.
7224 :hg:`help templates`.
7216
7225
7217 :type: String. ``local`` for local tags.
7226 :type: String. ``local`` for local tags.
7218
7227
7219 Returns 0 on success.
7228 Returns 0 on success.
7220 """
7229 """
7221
7230
7222 opts = pycompat.byteskwargs(opts)
7231 opts = pycompat.byteskwargs(opts)
7223 ui.pager(b'tags')
7232 ui.pager(b'tags')
7224 fm = ui.formatter(b'tags', opts)
7233 fm = ui.formatter(b'tags', opts)
7225 hexfunc = fm.hexfunc
7234 hexfunc = fm.hexfunc
7226
7235
7227 for t, n in reversed(repo.tagslist()):
7236 for t, n in reversed(repo.tagslist()):
7228 hn = hexfunc(n)
7237 hn = hexfunc(n)
7229 label = b'tags.normal'
7238 label = b'tags.normal'
7230 tagtype = b''
7239 tagtype = b''
7231 if repo.tagtype(t) == b'local':
7240 if repo.tagtype(t) == b'local':
7232 label = b'tags.local'
7241 label = b'tags.local'
7233 tagtype = b'local'
7242 tagtype = b'local'
7234
7243
7235 fm.startitem()
7244 fm.startitem()
7236 fm.context(repo=repo)
7245 fm.context(repo=repo)
7237 fm.write(b'tag', b'%s', t, label=label)
7246 fm.write(b'tag', b'%s', t, label=label)
7238 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7247 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7239 fm.condwrite(
7248 fm.condwrite(
7240 not ui.quiet,
7249 not ui.quiet,
7241 b'rev node',
7250 b'rev node',
7242 fmt,
7251 fmt,
7243 repo.changelog.rev(n),
7252 repo.changelog.rev(n),
7244 hn,
7253 hn,
7245 label=label,
7254 label=label,
7246 )
7255 )
7247 fm.condwrite(
7256 fm.condwrite(
7248 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7257 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7249 )
7258 )
7250 fm.plain(b'\n')
7259 fm.plain(b'\n')
7251 fm.end()
7260 fm.end()
7252
7261
7253
7262
7254 @command(
7263 @command(
7255 b'tip',
7264 b'tip',
7256 [
7265 [
7257 (b'p', b'patch', None, _(b'show patch')),
7266 (b'p', b'patch', None, _(b'show patch')),
7258 (b'g', b'git', None, _(b'use git extended diff format')),
7267 (b'g', b'git', None, _(b'use git extended diff format')),
7259 ]
7268 ]
7260 + templateopts,
7269 + templateopts,
7261 _(b'[-p] [-g]'),
7270 _(b'[-p] [-g]'),
7262 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7271 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7263 )
7272 )
7264 def tip(ui, repo, **opts):
7273 def tip(ui, repo, **opts):
7265 """show the tip revision (DEPRECATED)
7274 """show the tip revision (DEPRECATED)
7266
7275
7267 The tip revision (usually just called the tip) is the changeset
7276 The tip revision (usually just called the tip) is the changeset
7268 most recently added to the repository (and therefore the most
7277 most recently added to the repository (and therefore the most
7269 recently changed head).
7278 recently changed head).
7270
7279
7271 If you have just made a commit, that commit will be the tip. If
7280 If you have just made a commit, that commit will be the tip. If
7272 you have just pulled changes from another repository, the tip of
7281 you have just pulled changes from another repository, the tip of
7273 that repository becomes the current tip. The "tip" tag is special
7282 that repository becomes the current tip. The "tip" tag is special
7274 and cannot be renamed or assigned to a different changeset.
7283 and cannot be renamed or assigned to a different changeset.
7275
7284
7276 This command is deprecated, please use :hg:`heads` instead.
7285 This command is deprecated, please use :hg:`heads` instead.
7277
7286
7278 Returns 0 on success.
7287 Returns 0 on success.
7279 """
7288 """
7280 opts = pycompat.byteskwargs(opts)
7289 opts = pycompat.byteskwargs(opts)
7281 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7290 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7282 displayer.show(repo[b'tip'])
7291 displayer.show(repo[b'tip'])
7283 displayer.close()
7292 displayer.close()
7284
7293
7285
7294
7286 @command(
7295 @command(
7287 b'unbundle',
7296 b'unbundle',
7288 [
7297 [
7289 (
7298 (
7290 b'u',
7299 b'u',
7291 b'update',
7300 b'update',
7292 None,
7301 None,
7293 _(b'update to new branch head if changesets were unbundled'),
7302 _(b'update to new branch head if changesets were unbundled'),
7294 )
7303 )
7295 ],
7304 ],
7296 _(b'[-u] FILE...'),
7305 _(b'[-u] FILE...'),
7297 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7306 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7298 )
7307 )
7299 def unbundle(ui, repo, fname1, *fnames, **opts):
7308 def unbundle(ui, repo, fname1, *fnames, **opts):
7300 """apply one or more bundle files
7309 """apply one or more bundle files
7301
7310
7302 Apply one or more bundle files generated by :hg:`bundle`.
7311 Apply one or more bundle files generated by :hg:`bundle`.
7303
7312
7304 Returns 0 on success, 1 if an update has unresolved files.
7313 Returns 0 on success, 1 if an update has unresolved files.
7305 """
7314 """
7306 fnames = (fname1,) + fnames
7315 fnames = (fname1,) + fnames
7307
7316
7308 with repo.lock():
7317 with repo.lock():
7309 for fname in fnames:
7318 for fname in fnames:
7310 f = hg.openpath(ui, fname)
7319 f = hg.openpath(ui, fname)
7311 gen = exchange.readbundle(ui, f, fname)
7320 gen = exchange.readbundle(ui, f, fname)
7312 if isinstance(gen, streamclone.streamcloneapplier):
7321 if isinstance(gen, streamclone.streamcloneapplier):
7313 raise error.Abort(
7322 raise error.Abort(
7314 _(
7323 _(
7315 b'packed bundles cannot be applied with '
7324 b'packed bundles cannot be applied with '
7316 b'"hg unbundle"'
7325 b'"hg unbundle"'
7317 ),
7326 ),
7318 hint=_(b'use "hg debugapplystreamclonebundle"'),
7327 hint=_(b'use "hg debugapplystreamclonebundle"'),
7319 )
7328 )
7320 url = b'bundle:' + fname
7329 url = b'bundle:' + fname
7321 try:
7330 try:
7322 txnname = b'unbundle'
7331 txnname = b'unbundle'
7323 if not isinstance(gen, bundle2.unbundle20):
7332 if not isinstance(gen, bundle2.unbundle20):
7324 txnname = b'unbundle\n%s' % util.hidepassword(url)
7333 txnname = b'unbundle\n%s' % util.hidepassword(url)
7325 with repo.transaction(txnname) as tr:
7334 with repo.transaction(txnname) as tr:
7326 op = bundle2.applybundle(
7335 op = bundle2.applybundle(
7327 repo, gen, tr, source=b'unbundle', url=url
7336 repo, gen, tr, source=b'unbundle', url=url
7328 )
7337 )
7329 except error.BundleUnknownFeatureError as exc:
7338 except error.BundleUnknownFeatureError as exc:
7330 raise error.Abort(
7339 raise error.Abort(
7331 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7340 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7332 hint=_(
7341 hint=_(
7333 b"see https://mercurial-scm.org/"
7342 b"see https://mercurial-scm.org/"
7334 b"wiki/BundleFeature for more "
7343 b"wiki/BundleFeature for more "
7335 b"information"
7344 b"information"
7336 ),
7345 ),
7337 )
7346 )
7338 modheads = bundle2.combinechangegroupresults(op)
7347 modheads = bundle2.combinechangegroupresults(op)
7339
7348
7340 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7349 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7341
7350
7342
7351
7343 @command(
7352 @command(
7344 b'unshelve',
7353 b'unshelve',
7345 [
7354 [
7346 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7355 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7347 (
7356 (
7348 b'c',
7357 b'c',
7349 b'continue',
7358 b'continue',
7350 None,
7359 None,
7351 _(b'continue an incomplete unshelve operation'),
7360 _(b'continue an incomplete unshelve operation'),
7352 ),
7361 ),
7353 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7362 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7354 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7363 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7355 (
7364 (
7356 b'n',
7365 b'n',
7357 b'name',
7366 b'name',
7358 b'',
7367 b'',
7359 _(b'restore shelved change with given name'),
7368 _(b'restore shelved change with given name'),
7360 _(b'NAME'),
7369 _(b'NAME'),
7361 ),
7370 ),
7362 (b't', b'tool', b'', _(b'specify merge tool')),
7371 (b't', b'tool', b'', _(b'specify merge tool')),
7363 (
7372 (
7364 b'',
7373 b'',
7365 b'date',
7374 b'date',
7366 b'',
7375 b'',
7367 _(b'set date for temporary commits (DEPRECATED)'),
7376 _(b'set date for temporary commits (DEPRECATED)'),
7368 _(b'DATE'),
7377 _(b'DATE'),
7369 ),
7378 ),
7370 ],
7379 ],
7371 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7380 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7372 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7381 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7373 )
7382 )
7374 def unshelve(ui, repo, *shelved, **opts):
7383 def unshelve(ui, repo, *shelved, **opts):
7375 """restore a shelved change to the working directory
7384 """restore a shelved change to the working directory
7376
7385
7377 This command accepts an optional name of a shelved change to
7386 This command accepts an optional name of a shelved change to
7378 restore. If none is given, the most recent shelved change is used.
7387 restore. If none is given, the most recent shelved change is used.
7379
7388
7380 If a shelved change is applied successfully, the bundle that
7389 If a shelved change is applied successfully, the bundle that
7381 contains the shelved changes is moved to a backup location
7390 contains the shelved changes is moved to a backup location
7382 (.hg/shelve-backup).
7391 (.hg/shelve-backup).
7383
7392
7384 Since you can restore a shelved change on top of an arbitrary
7393 Since you can restore a shelved change on top of an arbitrary
7385 commit, it is possible that unshelving will result in a conflict
7394 commit, it is possible that unshelving will result in a conflict
7386 between your changes and the commits you are unshelving onto. If
7395 between your changes and the commits you are unshelving onto. If
7387 this occurs, you must resolve the conflict, then use
7396 this occurs, you must resolve the conflict, then use
7388 ``--continue`` to complete the unshelve operation. (The bundle
7397 ``--continue`` to complete the unshelve operation. (The bundle
7389 will not be moved until you successfully complete the unshelve.)
7398 will not be moved until you successfully complete the unshelve.)
7390
7399
7391 (Alternatively, you can use ``--abort`` to abandon an unshelve
7400 (Alternatively, you can use ``--abort`` to abandon an unshelve
7392 that causes a conflict. This reverts the unshelved changes, and
7401 that causes a conflict. This reverts the unshelved changes, and
7393 leaves the bundle in place.)
7402 leaves the bundle in place.)
7394
7403
7395 If bare shelved change (without interactive, include and exclude
7404 If bare shelved change (without interactive, include and exclude
7396 option) was done on newly created branch it would restore branch
7405 option) was done on newly created branch it would restore branch
7397 information to the working directory.
7406 information to the working directory.
7398
7407
7399 After a successful unshelve, the shelved changes are stored in a
7408 After a successful unshelve, the shelved changes are stored in a
7400 backup directory. Only the N most recent backups are kept. N
7409 backup directory. Only the N most recent backups are kept. N
7401 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7410 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7402 configuration option.
7411 configuration option.
7403
7412
7404 .. container:: verbose
7413 .. container:: verbose
7405
7414
7406 Timestamp in seconds is used to decide order of backups. More
7415 Timestamp in seconds is used to decide order of backups. More
7407 than ``maxbackups`` backups are kept, if same timestamp
7416 than ``maxbackups`` backups are kept, if same timestamp
7408 prevents from deciding exact order of them, for safety.
7417 prevents from deciding exact order of them, for safety.
7409
7418
7410 Selected changes can be unshelved with ``--interactive`` flag.
7419 Selected changes can be unshelved with ``--interactive`` flag.
7411 The working directory is updated with the selected changes, and
7420 The working directory is updated with the selected changes, and
7412 only the unselected changes remain shelved.
7421 only the unselected changes remain shelved.
7413 Note: The whole shelve is applied to working directory first before
7422 Note: The whole shelve is applied to working directory first before
7414 running interactively. So, this will bring up all the conflicts between
7423 running interactively. So, this will bring up all the conflicts between
7415 working directory and the shelve, irrespective of which changes will be
7424 working directory and the shelve, irrespective of which changes will be
7416 unshelved.
7425 unshelved.
7417 """
7426 """
7418 with repo.wlock():
7427 with repo.wlock():
7419 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7428 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7420
7429
7421
7430
7422 statemod.addunfinished(
7431 statemod.addunfinished(
7423 b'unshelve',
7432 b'unshelve',
7424 fname=b'shelvedstate',
7433 fname=b'shelvedstate',
7425 continueflag=True,
7434 continueflag=True,
7426 abortfunc=shelvemod.hgabortunshelve,
7435 abortfunc=shelvemod.hgabortunshelve,
7427 continuefunc=shelvemod.hgcontinueunshelve,
7436 continuefunc=shelvemod.hgcontinueunshelve,
7428 cmdmsg=_(b'unshelve already in progress'),
7437 cmdmsg=_(b'unshelve already in progress'),
7429 )
7438 )
7430
7439
7431
7440
7432 @command(
7441 @command(
7433 b'update|up|checkout|co',
7442 b'update|up|checkout|co',
7434 [
7443 [
7435 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7444 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7436 (b'c', b'check', None, _(b'require clean working directory')),
7445 (b'c', b'check', None, _(b'require clean working directory')),
7437 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7446 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7438 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7447 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7439 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7448 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7440 ]
7449 ]
7441 + mergetoolopts,
7450 + mergetoolopts,
7442 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7451 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7443 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7452 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7444 helpbasic=True,
7453 helpbasic=True,
7445 )
7454 )
7446 def update(ui, repo, node=None, **opts):
7455 def update(ui, repo, node=None, **opts):
7447 """update working directory (or switch revisions)
7456 """update working directory (or switch revisions)
7448
7457
7449 Update the repository's working directory to the specified
7458 Update the repository's working directory to the specified
7450 changeset. If no changeset is specified, update to the tip of the
7459 changeset. If no changeset is specified, update to the tip of the
7451 current named branch and move the active bookmark (see :hg:`help
7460 current named branch and move the active bookmark (see :hg:`help
7452 bookmarks`).
7461 bookmarks`).
7453
7462
7454 Update sets the working directory's parent revision to the specified
7463 Update sets the working directory's parent revision to the specified
7455 changeset (see :hg:`help parents`).
7464 changeset (see :hg:`help parents`).
7456
7465
7457 If the changeset is not a descendant or ancestor of the working
7466 If the changeset is not a descendant or ancestor of the working
7458 directory's parent and there are uncommitted changes, the update is
7467 directory's parent and there are uncommitted changes, the update is
7459 aborted. With the -c/--check option, the working directory is checked
7468 aborted. With the -c/--check option, the working directory is checked
7460 for uncommitted changes; if none are found, the working directory is
7469 for uncommitted changes; if none are found, the working directory is
7461 updated to the specified changeset.
7470 updated to the specified changeset.
7462
7471
7463 .. container:: verbose
7472 .. container:: verbose
7464
7473
7465 The -C/--clean, -c/--check, and -m/--merge options control what
7474 The -C/--clean, -c/--check, and -m/--merge options control what
7466 happens if the working directory contains uncommitted changes.
7475 happens if the working directory contains uncommitted changes.
7467 At most of one of them can be specified.
7476 At most of one of them can be specified.
7468
7477
7469 1. If no option is specified, and if
7478 1. If no option is specified, and if
7470 the requested changeset is an ancestor or descendant of
7479 the requested changeset is an ancestor or descendant of
7471 the working directory's parent, the uncommitted changes
7480 the working directory's parent, the uncommitted changes
7472 are merged into the requested changeset and the merged
7481 are merged into the requested changeset and the merged
7473 result is left uncommitted. If the requested changeset is
7482 result is left uncommitted. If the requested changeset is
7474 not an ancestor or descendant (that is, it is on another
7483 not an ancestor or descendant (that is, it is on another
7475 branch), the update is aborted and the uncommitted changes
7484 branch), the update is aborted and the uncommitted changes
7476 are preserved.
7485 are preserved.
7477
7486
7478 2. With the -m/--merge option, the update is allowed even if the
7487 2. With the -m/--merge option, the update is allowed even if the
7479 requested changeset is not an ancestor or descendant of
7488 requested changeset is not an ancestor or descendant of
7480 the working directory's parent.
7489 the working directory's parent.
7481
7490
7482 3. With the -c/--check option, the update is aborted and the
7491 3. With the -c/--check option, the update is aborted and the
7483 uncommitted changes are preserved.
7492 uncommitted changes are preserved.
7484
7493
7485 4. With the -C/--clean option, uncommitted changes are discarded and
7494 4. With the -C/--clean option, uncommitted changes are discarded and
7486 the working directory is updated to the requested changeset.
7495 the working directory is updated to the requested changeset.
7487
7496
7488 To cancel an uncommitted merge (and lose your changes), use
7497 To cancel an uncommitted merge (and lose your changes), use
7489 :hg:`merge --abort`.
7498 :hg:`merge --abort`.
7490
7499
7491 Use null as the changeset to remove the working directory (like
7500 Use null as the changeset to remove the working directory (like
7492 :hg:`clone -U`).
7501 :hg:`clone -U`).
7493
7502
7494 If you want to revert just one file to an older revision, use
7503 If you want to revert just one file to an older revision, use
7495 :hg:`revert [-r REV] NAME`.
7504 :hg:`revert [-r REV] NAME`.
7496
7505
7497 See :hg:`help dates` for a list of formats valid for -d/--date.
7506 See :hg:`help dates` for a list of formats valid for -d/--date.
7498
7507
7499 Returns 0 on success, 1 if there are unresolved files.
7508 Returns 0 on success, 1 if there are unresolved files.
7500 """
7509 """
7501 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7510 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7502 rev = opts.get('rev')
7511 rev = opts.get('rev')
7503 date = opts.get('date')
7512 date = opts.get('date')
7504 clean = opts.get('clean')
7513 clean = opts.get('clean')
7505 check = opts.get('check')
7514 check = opts.get('check')
7506 merge = opts.get('merge')
7515 merge = opts.get('merge')
7507 if rev and node:
7516 if rev and node:
7508 raise error.Abort(_(b"please specify just one revision"))
7517 raise error.Abort(_(b"please specify just one revision"))
7509
7518
7510 if ui.configbool(b'commands', b'update.requiredest'):
7519 if ui.configbool(b'commands', b'update.requiredest'):
7511 if not node and not rev and not date:
7520 if not node and not rev and not date:
7512 raise error.Abort(
7521 raise error.Abort(
7513 _(b'you must specify a destination'),
7522 _(b'you must specify a destination'),
7514 hint=_(b'for example: hg update ".::"'),
7523 hint=_(b'for example: hg update ".::"'),
7515 )
7524 )
7516
7525
7517 if rev is None or rev == b'':
7526 if rev is None or rev == b'':
7518 rev = node
7527 rev = node
7519
7528
7520 if date and rev is not None:
7529 if date and rev is not None:
7521 raise error.Abort(_(b"you can't specify a revision and a date"))
7530 raise error.Abort(_(b"you can't specify a revision and a date"))
7522
7531
7523 updatecheck = None
7532 updatecheck = None
7524 if check:
7533 if check:
7525 updatecheck = b'abort'
7534 updatecheck = b'abort'
7526 elif merge:
7535 elif merge:
7527 updatecheck = b'none'
7536 updatecheck = b'none'
7528
7537
7529 with repo.wlock():
7538 with repo.wlock():
7530 cmdutil.clearunfinished(repo)
7539 cmdutil.clearunfinished(repo)
7531 if date:
7540 if date:
7532 rev = cmdutil.finddate(ui, repo, date)
7541 rev = cmdutil.finddate(ui, repo, date)
7533
7542
7534 # if we defined a bookmark, we have to remember the original name
7543 # if we defined a bookmark, we have to remember the original name
7535 brev = rev
7544 brev = rev
7536 if rev:
7545 if rev:
7537 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7546 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7538 ctx = scmutil.revsingle(repo, rev, default=None)
7547 ctx = scmutil.revsingle(repo, rev, default=None)
7539 rev = ctx.rev()
7548 rev = ctx.rev()
7540 hidden = ctx.hidden()
7549 hidden = ctx.hidden()
7541 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7550 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7542 with ui.configoverride(overrides, b'update'):
7551 with ui.configoverride(overrides, b'update'):
7543 ret = hg.updatetotally(
7552 ret = hg.updatetotally(
7544 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7553 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7545 )
7554 )
7546 if hidden:
7555 if hidden:
7547 ctxstr = ctx.hex()[:12]
7556 ctxstr = ctx.hex()[:12]
7548 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7557 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7549
7558
7550 if ctx.obsolete():
7559 if ctx.obsolete():
7551 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7560 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7552 ui.warn(b"(%s)\n" % obsfatemsg)
7561 ui.warn(b"(%s)\n" % obsfatemsg)
7553 return ret
7562 return ret
7554
7563
7555
7564
7556 @command(
7565 @command(
7557 b'verify',
7566 b'verify',
7558 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7567 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7559 helpcategory=command.CATEGORY_MAINTENANCE,
7568 helpcategory=command.CATEGORY_MAINTENANCE,
7560 )
7569 )
7561 def verify(ui, repo, **opts):
7570 def verify(ui, repo, **opts):
7562 """verify the integrity of the repository
7571 """verify the integrity of the repository
7563
7572
7564 Verify the integrity of the current repository.
7573 Verify the integrity of the current repository.
7565
7574
7566 This will perform an extensive check of the repository's
7575 This will perform an extensive check of the repository's
7567 integrity, validating the hashes and checksums of each entry in
7576 integrity, validating the hashes and checksums of each entry in
7568 the changelog, manifest, and tracked files, as well as the
7577 the changelog, manifest, and tracked files, as well as the
7569 integrity of their crosslinks and indices.
7578 integrity of their crosslinks and indices.
7570
7579
7571 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7580 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7572 for more information about recovery from corruption of the
7581 for more information about recovery from corruption of the
7573 repository.
7582 repository.
7574
7583
7575 Returns 0 on success, 1 if errors are encountered.
7584 Returns 0 on success, 1 if errors are encountered.
7576 """
7585 """
7577 opts = pycompat.byteskwargs(opts)
7586 opts = pycompat.byteskwargs(opts)
7578
7587
7579 level = None
7588 level = None
7580 if opts[b'full']:
7589 if opts[b'full']:
7581 level = verifymod.VERIFY_FULL
7590 level = verifymod.VERIFY_FULL
7582 return hg.verify(repo, level)
7591 return hg.verify(repo, level)
7583
7592
7584
7593
7585 @command(
7594 @command(
7586 b'version',
7595 b'version',
7587 [] + formatteropts,
7596 [] + formatteropts,
7588 helpcategory=command.CATEGORY_HELP,
7597 helpcategory=command.CATEGORY_HELP,
7589 norepo=True,
7598 norepo=True,
7590 intents={INTENT_READONLY},
7599 intents={INTENT_READONLY},
7591 )
7600 )
7592 def version_(ui, **opts):
7601 def version_(ui, **opts):
7593 """output version and copyright information
7602 """output version and copyright information
7594
7603
7595 .. container:: verbose
7604 .. container:: verbose
7596
7605
7597 Template:
7606 Template:
7598
7607
7599 The following keywords are supported. See also :hg:`help templates`.
7608 The following keywords are supported. See also :hg:`help templates`.
7600
7609
7601 :extensions: List of extensions.
7610 :extensions: List of extensions.
7602 :ver: String. Version number.
7611 :ver: String. Version number.
7603
7612
7604 And each entry of ``{extensions}`` provides the following sub-keywords
7613 And each entry of ``{extensions}`` provides the following sub-keywords
7605 in addition to ``{ver}``.
7614 in addition to ``{ver}``.
7606
7615
7607 :bundled: Boolean. True if included in the release.
7616 :bundled: Boolean. True if included in the release.
7608 :name: String. Extension name.
7617 :name: String. Extension name.
7609 """
7618 """
7610 opts = pycompat.byteskwargs(opts)
7619 opts = pycompat.byteskwargs(opts)
7611 if ui.verbose:
7620 if ui.verbose:
7612 ui.pager(b'version')
7621 ui.pager(b'version')
7613 fm = ui.formatter(b"version", opts)
7622 fm = ui.formatter(b"version", opts)
7614 fm.startitem()
7623 fm.startitem()
7615 fm.write(
7624 fm.write(
7616 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7625 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7617 )
7626 )
7618 license = _(
7627 license = _(
7619 b"(see https://mercurial-scm.org for more information)\n"
7628 b"(see https://mercurial-scm.org for more information)\n"
7620 b"\nCopyright (C) 2005-2020 Matt Mackall and others\n"
7629 b"\nCopyright (C) 2005-2020 Matt Mackall and others\n"
7621 b"This is free software; see the source for copying conditions. "
7630 b"This is free software; see the source for copying conditions. "
7622 b"There is NO\nwarranty; "
7631 b"There is NO\nwarranty; "
7623 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7632 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7624 )
7633 )
7625 if not ui.quiet:
7634 if not ui.quiet:
7626 fm.plain(license)
7635 fm.plain(license)
7627
7636
7628 if ui.verbose:
7637 if ui.verbose:
7629 fm.plain(_(b"\nEnabled extensions:\n\n"))
7638 fm.plain(_(b"\nEnabled extensions:\n\n"))
7630 # format names and versions into columns
7639 # format names and versions into columns
7631 names = []
7640 names = []
7632 vers = []
7641 vers = []
7633 isinternals = []
7642 isinternals = []
7634 for name, module in sorted(extensions.extensions()):
7643 for name, module in sorted(extensions.extensions()):
7635 names.append(name)
7644 names.append(name)
7636 vers.append(extensions.moduleversion(module) or None)
7645 vers.append(extensions.moduleversion(module) or None)
7637 isinternals.append(extensions.ismoduleinternal(module))
7646 isinternals.append(extensions.ismoduleinternal(module))
7638 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7647 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7639 if names:
7648 if names:
7640 namefmt = b" %%-%ds " % max(len(n) for n in names)
7649 namefmt = b" %%-%ds " % max(len(n) for n in names)
7641 places = [_(b"external"), _(b"internal")]
7650 places = [_(b"external"), _(b"internal")]
7642 for n, v, p in zip(names, vers, isinternals):
7651 for n, v, p in zip(names, vers, isinternals):
7643 fn.startitem()
7652 fn.startitem()
7644 fn.condwrite(ui.verbose, b"name", namefmt, n)
7653 fn.condwrite(ui.verbose, b"name", namefmt, n)
7645 if ui.verbose:
7654 if ui.verbose:
7646 fn.plain(b"%s " % places[p])
7655 fn.plain(b"%s " % places[p])
7647 fn.data(bundled=p)
7656 fn.data(bundled=p)
7648 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7657 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7649 if ui.verbose:
7658 if ui.verbose:
7650 fn.plain(b"\n")
7659 fn.plain(b"\n")
7651 fn.end()
7660 fn.end()
7652 fm.end()
7661 fm.end()
7653
7662
7654
7663
7655 def loadcmdtable(ui, name, cmdtable):
7664 def loadcmdtable(ui, name, cmdtable):
7656 """Load command functions from specified cmdtable
7665 """Load command functions from specified cmdtable
7657 """
7666 """
7658 overrides = [cmd for cmd in cmdtable if cmd in table]
7667 overrides = [cmd for cmd in cmdtable if cmd in table]
7659 if overrides:
7668 if overrides:
7660 ui.warn(
7669 ui.warn(
7661 _(b"extension '%s' overrides commands: %s\n")
7670 _(b"extension '%s' overrides commands: %s\n")
7662 % (name, b" ".join(overrides))
7671 % (name, b" ".join(overrides))
7663 )
7672 )
7664 table.update(cmdtable)
7673 table.update(cmdtable)
@@ -1,1366 +1,1396 b''
1 #testcases b2-pushkey b2-binary
1 #testcases b2-pushkey b2-binary
2
2
3 #if b2-pushkey
3 #if b2-pushkey
4 $ cat << EOF >> $HGRCPATH
4 $ cat << EOF >> $HGRCPATH
5 > [devel]
5 > [devel]
6 > legacy.exchange=bookmarks
6 > legacy.exchange=bookmarks
7 > EOF
7 > EOF
8 #endif
8 #endif
9
9
10 #require serve
10 #require serve
11
11
12 $ cat << EOF >> $HGRCPATH
12 $ cat << EOF >> $HGRCPATH
13 > [command-templates]
13 > [command-templates]
14 > log={rev}:{node|short} {desc|firstline}
14 > log={rev}:{node|short} {desc|firstline}
15 > [phases]
15 > [phases]
16 > publish=False
16 > publish=False
17 > [experimental]
17 > [experimental]
18 > evolution.createmarkers=True
18 > evolution.createmarkers=True
19 > evolution.exchange=True
19 > evolution.exchange=True
20 > EOF
20 > EOF
21
21
22 $ cat > $TESTTMP/hook.sh <<'EOF'
22 $ cat > $TESTTMP/hook.sh <<'EOF'
23 > echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"
23 > echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"
24 > EOF
24 > EOF
25 $ TESTHOOK="hooks.txnclose-bookmark.test=sh $TESTTMP/hook.sh"
25 $ TESTHOOK="hooks.txnclose-bookmark.test=sh $TESTTMP/hook.sh"
26
26
27 initialize
27 initialize
28
28
29 $ hg init a
29 $ hg init a
30 $ cd a
30 $ cd a
31 $ echo 'test' > test
31 $ echo 'test' > test
32 $ hg commit -Am'test'
32 $ hg commit -Am'test'
33 adding test
33 adding test
34
34
35 set bookmarks
35 set bookmarks
36
36
37 $ hg bookmark X
37 $ hg bookmark X
38 $ hg bookmark Y
38 $ hg bookmark Y
39 $ hg bookmark Z
39 $ hg bookmark Z
40
40
41 import bookmark by name
41 import bookmark by name
42
42
43 $ hg init ../b
43 $ hg init ../b
44 $ cd ../b
44 $ cd ../b
45 $ hg book Y
45 $ hg book Y
46 $ hg book
46 $ hg book
47 * Y -1:000000000000
47 * Y -1:000000000000
48 $ hg pull ../a --config "$TESTHOOK"
48 $ hg pull ../a --config "$TESTHOOK"
49 pulling from ../a
49 pulling from ../a
50 requesting all changes
50 requesting all changes
51 adding changesets
51 adding changesets
52 adding manifests
52 adding manifests
53 adding file changes
53 adding file changes
54 adding remote bookmark X
54 adding remote bookmark X
55 updating bookmark Y
55 updating bookmark Y
56 adding remote bookmark Z
56 adding remote bookmark Z
57 added 1 changesets with 1 changes to 1 files
57 added 1 changesets with 1 changes to 1 files
58 new changesets 4e3505fd9583 (1 drafts)
58 new changesets 4e3505fd9583 (1 drafts)
59 test-hook-bookmark: X: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
59 test-hook-bookmark: X: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
60 test-hook-bookmark: Y: 0000000000000000000000000000000000000000 -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
60 test-hook-bookmark: Y: 0000000000000000000000000000000000000000 -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
61 test-hook-bookmark: Z: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
61 test-hook-bookmark: Z: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
62 (run 'hg update' to get a working copy)
62 (run 'hg update' to get a working copy)
63 $ hg bookmarks
63 $ hg bookmarks
64 X 0:4e3505fd9583
64 X 0:4e3505fd9583
65 * Y 0:4e3505fd9583
65 * Y 0:4e3505fd9583
66 Z 0:4e3505fd9583
66 Z 0:4e3505fd9583
67 $ hg debugpushkey ../a namespaces
67 $ hg debugpushkey ../a namespaces
68 bookmarks
68 bookmarks
69 namespaces
69 namespaces
70 obsolete
70 obsolete
71 phases
71 phases
72 $ hg debugpushkey ../a bookmarks
72 $ hg debugpushkey ../a bookmarks
73 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
73 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
74 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
74 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
75 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
75 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
76
76
77 delete the bookmark to re-pull it
77 delete the bookmark to re-pull it
78
78
79 $ hg book -d X
79 $ hg book -d X
80 $ hg pull -B X ../a
80 $ hg pull -B X ../a
81 pulling from ../a
81 pulling from ../a
82 no changes found
82 no changes found
83 adding remote bookmark X
83 adding remote bookmark X
84
84
85 finally no-op pull
85 finally no-op pull
86
86
87 $ hg pull -B X ../a
87 $ hg pull -B X ../a
88 pulling from ../a
88 pulling from ../a
89 no changes found
89 no changes found
90 $ hg bookmark
90 $ hg bookmark
91 X 0:4e3505fd9583
91 X 0:4e3505fd9583
92 * Y 0:4e3505fd9583
92 * Y 0:4e3505fd9583
93 Z 0:4e3505fd9583
93 Z 0:4e3505fd9583
94
94
95 export bookmark by name
95 export bookmark by name
96
96
97 $ hg bookmark W
97 $ hg bookmark W
98 $ hg bookmark foo
98 $ hg bookmark foo
99 $ hg bookmark foobar
99 $ hg bookmark foobar
100 $ hg push -B W ../a
100 $ hg push -B W ../a
101 pushing to ../a
101 pushing to ../a
102 searching for changes
102 searching for changes
103 no changes found
103 no changes found
104 exporting bookmark W
104 exporting bookmark W
105 [1]
105 [1]
106 $ hg -R ../a bookmarks
106 $ hg -R ../a bookmarks
107 W -1:000000000000
107 W -1:000000000000
108 X 0:4e3505fd9583
108 X 0:4e3505fd9583
109 Y 0:4e3505fd9583
109 Y 0:4e3505fd9583
110 * Z 0:4e3505fd9583
110 * Z 0:4e3505fd9583
111
111
112 delete a remote bookmark
112 delete a remote bookmark
113
113
114 $ hg book -d W
114 $ hg book -d W
115
115
116 #if b2-pushkey
116 #if b2-pushkey
117
117
118 $ hg push -B W ../a --config "$TESTHOOK" --debug --config devel.bundle2.debug=yes
118 $ hg push -B W ../a --config "$TESTHOOK" --debug --config devel.bundle2.debug=yes
119 pushing to ../a
119 pushing to ../a
120 query 1; heads
120 query 1; heads
121 searching for changes
121 searching for changes
122 all remote heads known locally
122 all remote heads known locally
123 listing keys for "phases"
123 listing keys for "phases"
124 checking for updated bookmarks
124 checking for updated bookmarks
125 listing keys for "bookmarks"
125 listing keys for "bookmarks"
126 no changes found
126 no changes found
127 bundle2-output-bundle: "HG20", 4 parts total
127 bundle2-output-bundle: "HG20", 4 parts total
128 bundle2-output: start emission of HG20 stream
128 bundle2-output: start emission of HG20 stream
129 bundle2-output: bundle parameter:
129 bundle2-output: bundle parameter:
130 bundle2-output: start of parts
130 bundle2-output: start of parts
131 bundle2-output: bundle part: "replycaps"
131 bundle2-output: bundle part: "replycaps"
132 bundle2-output-part: "replycaps" 241 bytes payload
132 bundle2-output-part: "replycaps" 241 bytes payload
133 bundle2-output: part 0: "REPLYCAPS"
133 bundle2-output: part 0: "REPLYCAPS"
134 bundle2-output: header chunk size: 16
134 bundle2-output: header chunk size: 16
135 bundle2-output: payload chunk size: 241
135 bundle2-output: payload chunk size: 241
136 bundle2-output: closing payload chunk
136 bundle2-output: closing payload chunk
137 bundle2-output: bundle part: "check:bookmarks"
137 bundle2-output: bundle part: "check:bookmarks"
138 bundle2-output-part: "check:bookmarks" 23 bytes payload
138 bundle2-output-part: "check:bookmarks" 23 bytes payload
139 bundle2-output: part 1: "CHECK:BOOKMARKS"
139 bundle2-output: part 1: "CHECK:BOOKMARKS"
140 bundle2-output: header chunk size: 22
140 bundle2-output: header chunk size: 22
141 bundle2-output: payload chunk size: 23
141 bundle2-output: payload chunk size: 23
142 bundle2-output: closing payload chunk
142 bundle2-output: closing payload chunk
143 bundle2-output: bundle part: "check:phases"
143 bundle2-output: bundle part: "check:phases"
144 bundle2-output-part: "check:phases" 24 bytes payload
144 bundle2-output-part: "check:phases" 24 bytes payload
145 bundle2-output: part 2: "CHECK:PHASES"
145 bundle2-output: part 2: "CHECK:PHASES"
146 bundle2-output: header chunk size: 19
146 bundle2-output: header chunk size: 19
147 bundle2-output: payload chunk size: 24
147 bundle2-output: payload chunk size: 24
148 bundle2-output: closing payload chunk
148 bundle2-output: closing payload chunk
149 bundle2-output: bundle part: "pushkey"
149 bundle2-output: bundle part: "pushkey"
150 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
150 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
151 bundle2-output: part 3: "PUSHKEY"
151 bundle2-output: part 3: "PUSHKEY"
152 bundle2-output: header chunk size: 90
152 bundle2-output: header chunk size: 90
153 bundle2-output: closing payload chunk
153 bundle2-output: closing payload chunk
154 bundle2-output: end of bundle
154 bundle2-output: end of bundle
155 bundle2-input: start processing of HG20 stream
155 bundle2-input: start processing of HG20 stream
156 bundle2-input: reading bundle2 stream parameters
156 bundle2-input: reading bundle2 stream parameters
157 bundle2-input-bundle: with-transaction
157 bundle2-input-bundle: with-transaction
158 bundle2-input: start extraction of bundle2 parts
158 bundle2-input: start extraction of bundle2 parts
159 bundle2-input: part header size: 16
159 bundle2-input: part header size: 16
160 bundle2-input: part type: "REPLYCAPS"
160 bundle2-input: part type: "REPLYCAPS"
161 bundle2-input: part id: "0"
161 bundle2-input: part id: "0"
162 bundle2-input: part parameters: 0
162 bundle2-input: part parameters: 0
163 bundle2-input: found a handler for part replycaps
163 bundle2-input: found a handler for part replycaps
164 bundle2-input-part: "replycaps" supported
164 bundle2-input-part: "replycaps" supported
165 bundle2-input: payload chunk size: 241
165 bundle2-input: payload chunk size: 241
166 bundle2-input: payload chunk size: 0
166 bundle2-input: payload chunk size: 0
167 bundle2-input-part: total payload size 241
167 bundle2-input-part: total payload size 241
168 bundle2-input: part header size: 22
168 bundle2-input: part header size: 22
169 bundle2-input: part type: "CHECK:BOOKMARKS"
169 bundle2-input: part type: "CHECK:BOOKMARKS"
170 bundle2-input: part id: "1"
170 bundle2-input: part id: "1"
171 bundle2-input: part parameters: 0
171 bundle2-input: part parameters: 0
172 bundle2-input: found a handler for part check:bookmarks
172 bundle2-input: found a handler for part check:bookmarks
173 bundle2-input-part: "check:bookmarks" supported
173 bundle2-input-part: "check:bookmarks" supported
174 bundle2-input: payload chunk size: 23
174 bundle2-input: payload chunk size: 23
175 bundle2-input: payload chunk size: 0
175 bundle2-input: payload chunk size: 0
176 bundle2-input-part: total payload size 23
176 bundle2-input-part: total payload size 23
177 bundle2-input: part header size: 19
177 bundle2-input: part header size: 19
178 bundle2-input: part type: "CHECK:PHASES"
178 bundle2-input: part type: "CHECK:PHASES"
179 bundle2-input: part id: "2"
179 bundle2-input: part id: "2"
180 bundle2-input: part parameters: 0
180 bundle2-input: part parameters: 0
181 bundle2-input: found a handler for part check:phases
181 bundle2-input: found a handler for part check:phases
182 bundle2-input-part: "check:phases" supported
182 bundle2-input-part: "check:phases" supported
183 bundle2-input: payload chunk size: 24
183 bundle2-input: payload chunk size: 24
184 bundle2-input: payload chunk size: 0
184 bundle2-input: payload chunk size: 0
185 bundle2-input-part: total payload size 24
185 bundle2-input-part: total payload size 24
186 bundle2-input: part header size: 90
186 bundle2-input: part header size: 90
187 bundle2-input: part type: "PUSHKEY"
187 bundle2-input: part type: "PUSHKEY"
188 bundle2-input: part id: "3"
188 bundle2-input: part id: "3"
189 bundle2-input: part parameters: 4
189 bundle2-input: part parameters: 4
190 bundle2-input: found a handler for part pushkey
190 bundle2-input: found a handler for part pushkey
191 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
191 bundle2-input-part: "pushkey" (params: 4 mandatory) supported
192 pushing key for "bookmarks:W"
192 pushing key for "bookmarks:W"
193 bundle2-input: payload chunk size: 0
193 bundle2-input: payload chunk size: 0
194 bundle2-input: part header size: 0
194 bundle2-input: part header size: 0
195 bundle2-input: end of bundle2 stream
195 bundle2-input: end of bundle2 stream
196 bundle2-input-bundle: 4 parts total
196 bundle2-input-bundle: 4 parts total
197 running hook txnclose-bookmark.test: sh $TESTTMP/hook.sh
197 running hook txnclose-bookmark.test: sh $TESTTMP/hook.sh
198 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
198 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
199 bundle2-output-bundle: "HG20", 1 parts total
199 bundle2-output-bundle: "HG20", 1 parts total
200 bundle2-output: start emission of HG20 stream
200 bundle2-output: start emission of HG20 stream
201 bundle2-output: bundle parameter:
201 bundle2-output: bundle parameter:
202 bundle2-output: start of parts
202 bundle2-output: start of parts
203 bundle2-output: bundle part: "reply:pushkey"
203 bundle2-output: bundle part: "reply:pushkey"
204 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
204 bundle2-output-part: "reply:pushkey" (params: 0 advisory) empty payload
205 bundle2-output: part 0: "REPLY:PUSHKEY"
205 bundle2-output: part 0: "REPLY:PUSHKEY"
206 bundle2-output: header chunk size: 43
206 bundle2-output: header chunk size: 43
207 bundle2-output: closing payload chunk
207 bundle2-output: closing payload chunk
208 bundle2-output: end of bundle
208 bundle2-output: end of bundle
209 bundle2-input: start processing of HG20 stream
209 bundle2-input: start processing of HG20 stream
210 bundle2-input: reading bundle2 stream parameters
210 bundle2-input: reading bundle2 stream parameters
211 bundle2-input-bundle: no-transaction
211 bundle2-input-bundle: no-transaction
212 bundle2-input: start extraction of bundle2 parts
212 bundle2-input: start extraction of bundle2 parts
213 bundle2-input: part header size: 43
213 bundle2-input: part header size: 43
214 bundle2-input: part type: "REPLY:PUSHKEY"
214 bundle2-input: part type: "REPLY:PUSHKEY"
215 bundle2-input: part id: "0"
215 bundle2-input: part id: "0"
216 bundle2-input: part parameters: 2
216 bundle2-input: part parameters: 2
217 bundle2-input: found a handler for part reply:pushkey
217 bundle2-input: found a handler for part reply:pushkey
218 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
218 bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
219 bundle2-input: payload chunk size: 0
219 bundle2-input: payload chunk size: 0
220 bundle2-input: part header size: 0
220 bundle2-input: part header size: 0
221 bundle2-input: end of bundle2 stream
221 bundle2-input: end of bundle2 stream
222 bundle2-input-bundle: 1 parts total
222 bundle2-input-bundle: 1 parts total
223 deleting remote bookmark W
223 deleting remote bookmark W
224 listing keys for "phases"
224 listing keys for "phases"
225 [1]
225 [1]
226
226
227 #endif
227 #endif
228 #if b2-binary
228 #if b2-binary
229
229
230 $ hg push -B W ../a --config "$TESTHOOK" --debug --config devel.bundle2.debug=yes
230 $ hg push -B W ../a --config "$TESTHOOK" --debug --config devel.bundle2.debug=yes
231 pushing to ../a
231 pushing to ../a
232 query 1; heads
232 query 1; heads
233 searching for changes
233 searching for changes
234 all remote heads known locally
234 all remote heads known locally
235 listing keys for "phases"
235 listing keys for "phases"
236 checking for updated bookmarks
236 checking for updated bookmarks
237 listing keys for "bookmarks"
237 listing keys for "bookmarks"
238 no changes found
238 no changes found
239 bundle2-output-bundle: "HG20", 4 parts total
239 bundle2-output-bundle: "HG20", 4 parts total
240 bundle2-output: start emission of HG20 stream
240 bundle2-output: start emission of HG20 stream
241 bundle2-output: bundle parameter:
241 bundle2-output: bundle parameter:
242 bundle2-output: start of parts
242 bundle2-output: start of parts
243 bundle2-output: bundle part: "replycaps"
243 bundle2-output: bundle part: "replycaps"
244 bundle2-output-part: "replycaps" 241 bytes payload
244 bundle2-output-part: "replycaps" 241 bytes payload
245 bundle2-output: part 0: "REPLYCAPS"
245 bundle2-output: part 0: "REPLYCAPS"
246 bundle2-output: header chunk size: 16
246 bundle2-output: header chunk size: 16
247 bundle2-output: payload chunk size: 241
247 bundle2-output: payload chunk size: 241
248 bundle2-output: closing payload chunk
248 bundle2-output: closing payload chunk
249 bundle2-output: bundle part: "check:bookmarks"
249 bundle2-output: bundle part: "check:bookmarks"
250 bundle2-output-part: "check:bookmarks" 23 bytes payload
250 bundle2-output-part: "check:bookmarks" 23 bytes payload
251 bundle2-output: part 1: "CHECK:BOOKMARKS"
251 bundle2-output: part 1: "CHECK:BOOKMARKS"
252 bundle2-output: header chunk size: 22
252 bundle2-output: header chunk size: 22
253 bundle2-output: payload chunk size: 23
253 bundle2-output: payload chunk size: 23
254 bundle2-output: closing payload chunk
254 bundle2-output: closing payload chunk
255 bundle2-output: bundle part: "check:phases"
255 bundle2-output: bundle part: "check:phases"
256 bundle2-output-part: "check:phases" 24 bytes payload
256 bundle2-output-part: "check:phases" 24 bytes payload
257 bundle2-output: part 2: "CHECK:PHASES"
257 bundle2-output: part 2: "CHECK:PHASES"
258 bundle2-output: header chunk size: 19
258 bundle2-output: header chunk size: 19
259 bundle2-output: payload chunk size: 24
259 bundle2-output: payload chunk size: 24
260 bundle2-output: closing payload chunk
260 bundle2-output: closing payload chunk
261 bundle2-output: bundle part: "bookmarks"
261 bundle2-output: bundle part: "bookmarks"
262 bundle2-output-part: "bookmarks" 23 bytes payload
262 bundle2-output-part: "bookmarks" 23 bytes payload
263 bundle2-output: part 3: "BOOKMARKS"
263 bundle2-output: part 3: "BOOKMARKS"
264 bundle2-output: header chunk size: 16
264 bundle2-output: header chunk size: 16
265 bundle2-output: payload chunk size: 23
265 bundle2-output: payload chunk size: 23
266 bundle2-output: closing payload chunk
266 bundle2-output: closing payload chunk
267 bundle2-output: end of bundle
267 bundle2-output: end of bundle
268 bundle2-input: start processing of HG20 stream
268 bundle2-input: start processing of HG20 stream
269 bundle2-input: reading bundle2 stream parameters
269 bundle2-input: reading bundle2 stream parameters
270 bundle2-input-bundle: with-transaction
270 bundle2-input-bundle: with-transaction
271 bundle2-input: start extraction of bundle2 parts
271 bundle2-input: start extraction of bundle2 parts
272 bundle2-input: part header size: 16
272 bundle2-input: part header size: 16
273 bundle2-input: part type: "REPLYCAPS"
273 bundle2-input: part type: "REPLYCAPS"
274 bundle2-input: part id: "0"
274 bundle2-input: part id: "0"
275 bundle2-input: part parameters: 0
275 bundle2-input: part parameters: 0
276 bundle2-input: found a handler for part replycaps
276 bundle2-input: found a handler for part replycaps
277 bundle2-input-part: "replycaps" supported
277 bundle2-input-part: "replycaps" supported
278 bundle2-input: payload chunk size: 241
278 bundle2-input: payload chunk size: 241
279 bundle2-input: payload chunk size: 0
279 bundle2-input: payload chunk size: 0
280 bundle2-input-part: total payload size 241
280 bundle2-input-part: total payload size 241
281 bundle2-input: part header size: 22
281 bundle2-input: part header size: 22
282 bundle2-input: part type: "CHECK:BOOKMARKS"
282 bundle2-input: part type: "CHECK:BOOKMARKS"
283 bundle2-input: part id: "1"
283 bundle2-input: part id: "1"
284 bundle2-input: part parameters: 0
284 bundle2-input: part parameters: 0
285 bundle2-input: found a handler for part check:bookmarks
285 bundle2-input: found a handler for part check:bookmarks
286 bundle2-input-part: "check:bookmarks" supported
286 bundle2-input-part: "check:bookmarks" supported
287 bundle2-input: payload chunk size: 23
287 bundle2-input: payload chunk size: 23
288 bundle2-input: payload chunk size: 0
288 bundle2-input: payload chunk size: 0
289 bundle2-input-part: total payload size 23
289 bundle2-input-part: total payload size 23
290 bundle2-input: part header size: 19
290 bundle2-input: part header size: 19
291 bundle2-input: part type: "CHECK:PHASES"
291 bundle2-input: part type: "CHECK:PHASES"
292 bundle2-input: part id: "2"
292 bundle2-input: part id: "2"
293 bundle2-input: part parameters: 0
293 bundle2-input: part parameters: 0
294 bundle2-input: found a handler for part check:phases
294 bundle2-input: found a handler for part check:phases
295 bundle2-input-part: "check:phases" supported
295 bundle2-input-part: "check:phases" supported
296 bundle2-input: payload chunk size: 24
296 bundle2-input: payload chunk size: 24
297 bundle2-input: payload chunk size: 0
297 bundle2-input: payload chunk size: 0
298 bundle2-input-part: total payload size 24
298 bundle2-input-part: total payload size 24
299 bundle2-input: part header size: 16
299 bundle2-input: part header size: 16
300 bundle2-input: part type: "BOOKMARKS"
300 bundle2-input: part type: "BOOKMARKS"
301 bundle2-input: part id: "3"
301 bundle2-input: part id: "3"
302 bundle2-input: part parameters: 0
302 bundle2-input: part parameters: 0
303 bundle2-input: found a handler for part bookmarks
303 bundle2-input: found a handler for part bookmarks
304 bundle2-input-part: "bookmarks" supported
304 bundle2-input-part: "bookmarks" supported
305 bundle2-input: payload chunk size: 23
305 bundle2-input: payload chunk size: 23
306 bundle2-input: payload chunk size: 0
306 bundle2-input: payload chunk size: 0
307 bundle2-input-part: total payload size 23
307 bundle2-input-part: total payload size 23
308 bundle2-input: part header size: 0
308 bundle2-input: part header size: 0
309 bundle2-input: end of bundle2 stream
309 bundle2-input: end of bundle2 stream
310 bundle2-input-bundle: 4 parts total
310 bundle2-input-bundle: 4 parts total
311 running hook txnclose-bookmark.test: sh $TESTTMP/hook.sh
311 running hook txnclose-bookmark.test: sh $TESTTMP/hook.sh
312 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
312 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
313 bundle2-output-bundle: "HG20", 0 parts total
313 bundle2-output-bundle: "HG20", 0 parts total
314 bundle2-output: start emission of HG20 stream
314 bundle2-output: start emission of HG20 stream
315 bundle2-output: bundle parameter:
315 bundle2-output: bundle parameter:
316 bundle2-output: start of parts
316 bundle2-output: start of parts
317 bundle2-output: end of bundle
317 bundle2-output: end of bundle
318 bundle2-input: start processing of HG20 stream
318 bundle2-input: start processing of HG20 stream
319 bundle2-input: reading bundle2 stream parameters
319 bundle2-input: reading bundle2 stream parameters
320 bundle2-input-bundle: no-transaction
320 bundle2-input-bundle: no-transaction
321 bundle2-input: start extraction of bundle2 parts
321 bundle2-input: start extraction of bundle2 parts
322 bundle2-input: part header size: 0
322 bundle2-input: part header size: 0
323 bundle2-input: end of bundle2 stream
323 bundle2-input: end of bundle2 stream
324 bundle2-input-bundle: 0 parts total
324 bundle2-input-bundle: 0 parts total
325 deleting remote bookmark W
325 deleting remote bookmark W
326 listing keys for "phases"
326 listing keys for "phases"
327 [1]
327 [1]
328
328
329 #endif
329 #endif
330
330
331 Divergent bookmark cannot be exported
331 Divergent bookmark cannot be exported
332
332
333 $ hg book W@default
333 $ hg book W@default
334 $ hg push -B W@default ../a
334 $ hg push -B W@default ../a
335 pushing to ../a
335 pushing to ../a
336 searching for changes
336 searching for changes
337 cannot push divergent bookmark W@default!
337 cannot push divergent bookmark W@default!
338 no changes found
338 no changes found
339 [2]
339 [2]
340 $ hg book -d W@default
340 $ hg book -d W@default
341
341
342 export the active bookmark
342 export the active bookmark
343
343
344 $ hg bookmark V
344 $ hg bookmark V
345 $ hg push -B . ../a
345 $ hg push -B . ../a
346 pushing to ../a
346 pushing to ../a
347 searching for changes
347 searching for changes
348 no changes found
348 no changes found
349 exporting bookmark V
349 exporting bookmark V
350 [1]
350 [1]
351
351
352 exporting the active bookmark with 'push -B .'
352 exporting the active bookmark with 'push -B .'
353 demand that one of the bookmarks is activated
353 demand that one of the bookmarks is activated
354
354
355 $ hg update -r default
355 $ hg update -r default
356 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
356 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 (leaving bookmark V)
357 (leaving bookmark V)
358 $ hg push -B . ../a
358 $ hg push -B . ../a
359 abort: no active bookmark!
359 abort: no active bookmark!
360 [255]
360 [255]
361 $ hg update -r V
361 $ hg update -r V
362 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
362 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
363 (activating bookmark V)
363 (activating bookmark V)
364
364
365 delete the bookmark
365 delete the bookmark
366
366
367 $ hg book -d V
367 $ hg book -d V
368 $ hg push -B V ../a
368 $ hg push -B V ../a
369 pushing to ../a
369 pushing to ../a
370 searching for changes
370 searching for changes
371 no changes found
371 no changes found
372 deleting remote bookmark V
372 deleting remote bookmark V
373 [1]
373 [1]
374 $ hg up foobar
374 $ hg up foobar
375 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 (activating bookmark foobar)
376 (activating bookmark foobar)
377
377
378 push/pull name that doesn't exist
378 push/pull name that doesn't exist
379
379
380 $ hg push -B badname ../a
380 $ hg push -B badname ../a
381 pushing to ../a
381 pushing to ../a
382 searching for changes
382 searching for changes
383 bookmark badname does not exist on the local or remote repository!
383 bookmark badname does not exist on the local or remote repository!
384 no changes found
384 no changes found
385 [2]
385 [2]
386 $ hg pull -B anotherbadname ../a
386 $ hg pull -B anotherbadname ../a
387 pulling from ../a
387 pulling from ../a
388 abort: remote bookmark anotherbadname not found!
388 abort: remote bookmark anotherbadname not found!
389 [255]
389 [255]
390
390
391 divergent bookmarks
391 divergent bookmarks
392
392
393 $ cd ../a
393 $ cd ../a
394 $ echo c1 > f1
394 $ echo c1 > f1
395 $ hg ci -Am1
395 $ hg ci -Am1
396 adding f1
396 adding f1
397 $ hg book -f @
397 $ hg book -f @
398 $ hg book -f X
398 $ hg book -f X
399 $ hg book
399 $ hg book
400 @ 1:0d2164f0ce0d
400 @ 1:0d2164f0ce0d
401 * X 1:0d2164f0ce0d
401 * X 1:0d2164f0ce0d
402 Y 0:4e3505fd9583
402 Y 0:4e3505fd9583
403 Z 1:0d2164f0ce0d
403 Z 1:0d2164f0ce0d
404
404
405 $ cd ../b
405 $ cd ../b
406 $ hg up
406 $ hg up
407 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
408 updating bookmark foobar
408 updating bookmark foobar
409 $ echo c2 > f2
409 $ echo c2 > f2
410 $ hg ci -Am2
410 $ hg ci -Am2
411 adding f2
411 adding f2
412 $ hg book -if @
412 $ hg book -if @
413 $ hg book -if X
413 $ hg book -if X
414 $ hg book
414 $ hg book
415 @ 1:9b140be10808
415 @ 1:9b140be10808
416 X 1:9b140be10808
416 X 1:9b140be10808
417 Y 0:4e3505fd9583
417 Y 0:4e3505fd9583
418 Z 0:4e3505fd9583
418 Z 0:4e3505fd9583
419 foo -1:000000000000
419 foo -1:000000000000
420 * foobar 1:9b140be10808
420 * foobar 1:9b140be10808
421
421
422 $ hg pull --config paths.foo=../a foo --config "$TESTHOOK"
422 $ hg pull --config paths.foo=../a foo --config "$TESTHOOK"
423 pulling from $TESTTMP/a
423 pulling from $TESTTMP/a
424 searching for changes
424 searching for changes
425 adding changesets
425 adding changesets
426 adding manifests
426 adding manifests
427 adding file changes
427 adding file changes
428 divergent bookmark @ stored as @foo
428 divergent bookmark @ stored as @foo
429 divergent bookmark X stored as X@foo
429 divergent bookmark X stored as X@foo
430 updating bookmark Z
430 updating bookmark Z
431 added 1 changesets with 1 changes to 1 files (+1 heads)
431 added 1 changesets with 1 changes to 1 files (+1 heads)
432 new changesets 0d2164f0ce0d (1 drafts)
432 new changesets 0d2164f0ce0d (1 drafts)
433 test-hook-bookmark: @foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
433 test-hook-bookmark: @foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
434 test-hook-bookmark: X@foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
434 test-hook-bookmark: X@foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
435 test-hook-bookmark: Z: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
435 test-hook-bookmark: Z: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
436 (run 'hg heads' to see heads, 'hg merge' to merge)
436 (run 'hg heads' to see heads, 'hg merge' to merge)
437 $ hg book
437 $ hg book
438 @ 1:9b140be10808
438 @ 1:9b140be10808
439 @foo 2:0d2164f0ce0d
439 @foo 2:0d2164f0ce0d
440 X 1:9b140be10808
440 X 1:9b140be10808
441 X@foo 2:0d2164f0ce0d
441 X@foo 2:0d2164f0ce0d
442 Y 0:4e3505fd9583
442 Y 0:4e3505fd9583
443 Z 2:0d2164f0ce0d
443 Z 2:0d2164f0ce0d
444 foo -1:000000000000
444 foo -1:000000000000
445 * foobar 1:9b140be10808
445 * foobar 1:9b140be10808
446
446
447 (test that too many divergence of bookmark)
447 (test that too many divergence of bookmark)
448
448
449 $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
449 $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
450 $ hg pull ../a
450 $ hg pull ../a
451 pulling from ../a
451 pulling from ../a
452 searching for changes
452 searching for changes
453 no changes found
453 no changes found
454 warning: failed to assign numbered name to divergent bookmark X
454 warning: failed to assign numbered name to divergent bookmark X
455 divergent bookmark @ stored as @1
455 divergent bookmark @ stored as @1
456 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
456 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
457 X 1:9b140be10808
457 X 1:9b140be10808
458 X@foo 2:0d2164f0ce0d
458 X@foo 2:0d2164f0ce0d
459
459
460 (test that remotely diverged bookmarks are reused if they aren't changed)
460 (test that remotely diverged bookmarks are reused if they aren't changed)
461
461
462 $ hg bookmarks | grep '^ @'
462 $ hg bookmarks | grep '^ @'
463 @ 1:9b140be10808
463 @ 1:9b140be10808
464 @1 2:0d2164f0ce0d
464 @1 2:0d2164f0ce0d
465 @foo 2:0d2164f0ce0d
465 @foo 2:0d2164f0ce0d
466 $ hg pull ../a
466 $ hg pull ../a
467 pulling from ../a
467 pulling from ../a
468 searching for changes
468 searching for changes
469 no changes found
469 no changes found
470 warning: failed to assign numbered name to divergent bookmark X
470 warning: failed to assign numbered name to divergent bookmark X
471 divergent bookmark @ stored as @1
471 divergent bookmark @ stored as @1
472 $ hg bookmarks | grep '^ @'
472 $ hg bookmarks | grep '^ @'
473 @ 1:9b140be10808
473 @ 1:9b140be10808
474 @1 2:0d2164f0ce0d
474 @1 2:0d2164f0ce0d
475 @foo 2:0d2164f0ce0d
475 @foo 2:0d2164f0ce0d
476
476
477 $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
477 $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
478 $ hg bookmarks -d "@1"
478 $ hg bookmarks -d "@1"
479
479
480 $ hg push -f ../a
480 $ hg push -f ../a
481 pushing to ../a
481 pushing to ../a
482 searching for changes
482 searching for changes
483 adding changesets
483 adding changesets
484 adding manifests
484 adding manifests
485 adding file changes
485 adding file changes
486 added 1 changesets with 1 changes to 1 files (+1 heads)
486 added 1 changesets with 1 changes to 1 files (+1 heads)
487 $ hg -R ../a book
487 $ hg -R ../a book
488 @ 1:0d2164f0ce0d
488 @ 1:0d2164f0ce0d
489 * X 1:0d2164f0ce0d
489 * X 1:0d2164f0ce0d
490 Y 0:4e3505fd9583
490 Y 0:4e3505fd9583
491 Z 1:0d2164f0ce0d
491 Z 1:0d2164f0ce0d
492
492
493 explicit pull should overwrite the local version (issue4439)
493 explicit pull should overwrite the local version (issue4439)
494
494
495 $ hg update -r X
495 $ hg update -r X
496 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
496 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
497 (activating bookmark X)
497 (activating bookmark X)
498 $ hg pull --config paths.foo=../a foo -B . --config "$TESTHOOK"
498 $ hg pull --config paths.foo=../a foo -B . --config "$TESTHOOK"
499 pulling from $TESTTMP/a
499 pulling from $TESTTMP/a
500 no changes found
500 no changes found
501 divergent bookmark @ stored as @foo
501 divergent bookmark @ stored as @foo
502 importing bookmark X
502 importing bookmark X
503 test-hook-bookmark: @foo: 0d2164f0ce0d8f1d6f94351eba04b794909be66c -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
503 test-hook-bookmark: @foo: 0d2164f0ce0d8f1d6f94351eba04b794909be66c -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
504 test-hook-bookmark: X: 9b140be1080824d768c5a4691a564088eede71f9 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
504 test-hook-bookmark: X: 9b140be1080824d768c5a4691a564088eede71f9 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
505
505
506 reinstall state for further testing:
506 reinstall state for further testing:
507
507
508 $ hg book -fr 9b140be10808 X
508 $ hg book -fr 9b140be10808 X
509
509
510 revsets should not ignore divergent bookmarks
510 revsets should not ignore divergent bookmarks
511
511
512 $ hg bookmark -fr 1 Z
512 $ hg bookmark -fr 1 Z
513 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
513 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
514 0:4e3505fd9583 Y
514 0:4e3505fd9583 Y
515 1:9b140be10808 @ X Z foobar
515 1:9b140be10808 @ X Z foobar
516 2:0d2164f0ce0d @foo X@foo
516 2:0d2164f0ce0d @foo X@foo
517 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
517 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
518 2:0d2164f0ce0d @foo X@foo
518 2:0d2164f0ce0d @foo X@foo
519 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
519 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
520 2:0d2164f0ce0d @foo X@foo
520 2:0d2164f0ce0d @foo X@foo
521
521
522 update a remote bookmark from a non-head to a head
522 update a remote bookmark from a non-head to a head
523
523
524 $ hg up -q Y
524 $ hg up -q Y
525 $ echo c3 > f2
525 $ echo c3 > f2
526 $ hg ci -Am3
526 $ hg ci -Am3
527 adding f2
527 adding f2
528 created new head
528 created new head
529 $ hg push ../a --config "$TESTHOOK"
529 $ hg push ../a --config "$TESTHOOK"
530 pushing to ../a
530 pushing to ../a
531 searching for changes
531 searching for changes
532 adding changesets
532 adding changesets
533 adding manifests
533 adding manifests
534 adding file changes
534 adding file changes
535 added 1 changesets with 1 changes to 1 files (+1 heads)
535 added 1 changesets with 1 changes to 1 files (+1 heads)
536 test-hook-bookmark: Y: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
536 test-hook-bookmark: Y: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
537 updating bookmark Y
537 updating bookmark Y
538 $ hg -R ../a book
538 $ hg -R ../a book
539 @ 1:0d2164f0ce0d
539 @ 1:0d2164f0ce0d
540 * X 1:0d2164f0ce0d
540 * X 1:0d2164f0ce0d
541 Y 3:f6fc62dde3c0
541 Y 3:f6fc62dde3c0
542 Z 1:0d2164f0ce0d
542 Z 1:0d2164f0ce0d
543
543
544 update a bookmark in the middle of a client pulling changes
544 update a bookmark in the middle of a client pulling changes
545
545
546 $ cd ..
546 $ cd ..
547 $ hg clone -q a pull-race
547 $ hg clone -q a pull-race
548
548
549 We want to use http because it is stateless and therefore more susceptible to
549 We want to use http because it is stateless and therefore more susceptible to
550 race conditions
550 race conditions
551
551
552 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
552 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
553 $ cat pull-race.pid >> $DAEMON_PIDS
553 $ cat pull-race.pid >> $DAEMON_PIDS
554
554
555 $ cat <<EOF > $TESTTMP/out_makecommit.sh
555 $ cat <<EOF > $TESTTMP/out_makecommit.sh
556 > #!/bin/sh
556 > #!/bin/sh
557 > hg ci -Am5
557 > hg ci -Am5
558 > echo committed in pull-race
558 > echo committed in pull-race
559 > EOF
559 > EOF
560
560
561 $ hg clone -q http://localhost:$HGPORT/ pull-race2 --config "$TESTHOOK"
561 $ hg clone -q http://localhost:$HGPORT/ pull-race2 --config "$TESTHOOK"
562 test-hook-bookmark: @: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
562 test-hook-bookmark: @: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
563 test-hook-bookmark: X: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
563 test-hook-bookmark: X: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
564 test-hook-bookmark: Y: -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
564 test-hook-bookmark: Y: -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
565 test-hook-bookmark: Z: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
565 test-hook-bookmark: Z: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
566 $ cd pull-race
566 $ cd pull-race
567 $ hg up -q Y
567 $ hg up -q Y
568 $ echo c4 > f2
568 $ echo c4 > f2
569 $ hg ci -Am4
569 $ hg ci -Am4
570 $ echo c5 > f3
570 $ echo c5 > f3
571 $ cat <<EOF > .hg/hgrc
571 $ cat <<EOF > .hg/hgrc
572 > [hooks]
572 > [hooks]
573 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
573 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
574 > EOF
574 > EOF
575
575
576 (new config needs a server restart)
576 (new config needs a server restart)
577
577
578 $ cd ..
578 $ cd ..
579 $ killdaemons.py
579 $ killdaemons.py
580 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
580 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
581 $ cat pull-race.pid >> $DAEMON_PIDS
581 $ cat pull-race.pid >> $DAEMON_PIDS
582 $ cd pull-race2
582 $ cd pull-race2
583 $ hg -R $TESTTMP/pull-race book
583 $ hg -R $TESTTMP/pull-race book
584 @ 1:0d2164f0ce0d
584 @ 1:0d2164f0ce0d
585 X 1:0d2164f0ce0d
585 X 1:0d2164f0ce0d
586 * Y 4:b0a5eff05604
586 * Y 4:b0a5eff05604
587 Z 1:0d2164f0ce0d
587 Z 1:0d2164f0ce0d
588 $ hg pull
588 $ hg pull
589 pulling from http://localhost:$HGPORT/
589 pulling from http://localhost:$HGPORT/
590 searching for changes
590 searching for changes
591 adding changesets
591 adding changesets
592 adding manifests
592 adding manifests
593 adding file changes
593 adding file changes
594 updating bookmark Y
594 updating bookmark Y
595 added 1 changesets with 1 changes to 1 files
595 added 1 changesets with 1 changes to 1 files
596 new changesets b0a5eff05604 (1 drafts)
596 new changesets b0a5eff05604 (1 drafts)
597 (run 'hg update' to get a working copy)
597 (run 'hg update' to get a working copy)
598 $ hg book
598 $ hg book
599 * @ 1:0d2164f0ce0d
599 * @ 1:0d2164f0ce0d
600 X 1:0d2164f0ce0d
600 X 1:0d2164f0ce0d
601 Y 4:b0a5eff05604
601 Y 4:b0a5eff05604
602 Z 1:0d2164f0ce0d
602 Z 1:0d2164f0ce0d
603
603
604 Update a bookmark right after the initial lookup -B (issue4689)
604 Update a bookmark right after the initial lookup -B (issue4689)
605
605
606 $ echo c6 > ../pull-race/f3 # to be committed during the race
606 $ echo c6 > ../pull-race/f3 # to be committed during the race
607 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
607 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
608 > #!/bin/sh
608 > #!/bin/sh
609 > if hg st | grep -q M; then
609 > if hg st | grep -q M; then
610 > hg commit -m race
610 > hg commit -m race
611 > echo committed in pull-race
611 > echo committed in pull-race
612 > else
612 > else
613 > exit 0
613 > exit 0
614 > fi
614 > fi
615 > EOF
615 > EOF
616 $ cat <<EOF > ../pull-race/.hg/hgrc
616 $ cat <<EOF > ../pull-race/.hg/hgrc
617 > [hooks]
617 > [hooks]
618 > # If anything to commit, commit it right after the first key listing used
618 > # If anything to commit, commit it right after the first key listing used
619 > # during lookup. This makes the commit appear before the actual getbundle
619 > # during lookup. This makes the commit appear before the actual getbundle
620 > # call.
620 > # call.
621 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
621 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
622 > EOF
622 > EOF
623 $ restart_server() {
623 $ restart_server() {
624 > "$TESTDIR/killdaemons.py" $DAEMON_PIDS
624 > "$TESTDIR/killdaemons.py" $DAEMON_PIDS
625 > hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
625 > hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
626 > cat ../pull-race.pid >> $DAEMON_PIDS
626 > cat ../pull-race.pid >> $DAEMON_PIDS
627 > }
627 > }
628 $ restart_server # new config need server restart
628 $ restart_server # new config need server restart
629 $ hg -R $TESTTMP/pull-race book
629 $ hg -R $TESTTMP/pull-race book
630 @ 1:0d2164f0ce0d
630 @ 1:0d2164f0ce0d
631 X 1:0d2164f0ce0d
631 X 1:0d2164f0ce0d
632 * Y 5:35d1ef0a8d1b
632 * Y 5:35d1ef0a8d1b
633 Z 1:0d2164f0ce0d
633 Z 1:0d2164f0ce0d
634 $ hg update -r Y
634 $ hg update -r Y
635 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
635 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
636 (activating bookmark Y)
636 (activating bookmark Y)
637 $ hg pull -B .
637 $ hg pull -B .
638 pulling from http://localhost:$HGPORT/
638 pulling from http://localhost:$HGPORT/
639 searching for changes
639 searching for changes
640 adding changesets
640 adding changesets
641 adding manifests
641 adding manifests
642 adding file changes
642 adding file changes
643 updating bookmark Y
643 updating bookmark Y
644 added 1 changesets with 1 changes to 1 files
644 added 1 changesets with 1 changes to 1 files
645 new changesets 35d1ef0a8d1b (1 drafts)
645 new changesets 35d1ef0a8d1b (1 drafts)
646 (run 'hg update' to get a working copy)
646 (run 'hg update' to get a working copy)
647 $ hg book
647 $ hg book
648 @ 1:0d2164f0ce0d
648 @ 1:0d2164f0ce0d
649 X 1:0d2164f0ce0d
649 X 1:0d2164f0ce0d
650 * Y 5:35d1ef0a8d1b
650 * Y 5:35d1ef0a8d1b
651 Z 1:0d2164f0ce0d
651 Z 1:0d2164f0ce0d
652
652
653 Update a bookmark right after the initial lookup -r (issue4700)
653 Update a bookmark right after the initial lookup -r (issue4700)
654
654
655 $ echo c7 > ../pull-race/f3 # to be committed during the race
655 $ echo c7 > ../pull-race/f3 # to be committed during the race
656 $ cat <<EOF > ../lookuphook.py
656 $ cat <<EOF > ../lookuphook.py
657 > """small extensions adding a hook after wireprotocol lookup to test race"""
657 > """small extensions adding a hook after wireprotocol lookup to test race"""
658 > import functools
658 > import functools
659 > from mercurial import wireprotov1server, wireprotov2server
659 > from mercurial import wireprotov1server, wireprotov2server
660 >
660 >
661 > def wrappedlookup(orig, repo, *args, **kwargs):
661 > def wrappedlookup(orig, repo, *args, **kwargs):
662 > ret = orig(repo, *args, **kwargs)
662 > ret = orig(repo, *args, **kwargs)
663 > repo.hook(b'lookup')
663 > repo.hook(b'lookup')
664 > return ret
664 > return ret
665 > for table in [wireprotov1server.commands, wireprotov2server.COMMANDS]:
665 > for table in [wireprotov1server.commands, wireprotov2server.COMMANDS]:
666 > table[b'lookup'].func = functools.partial(wrappedlookup, table[b'lookup'].func)
666 > table[b'lookup'].func = functools.partial(wrappedlookup, table[b'lookup'].func)
667 > EOF
667 > EOF
668 $ cat <<EOF > ../pull-race/.hg/hgrc
668 $ cat <<EOF > ../pull-race/.hg/hgrc
669 > [extensions]
669 > [extensions]
670 > lookuphook=$TESTTMP/lookuphook.py
670 > lookuphook=$TESTTMP/lookuphook.py
671 > [hooks]
671 > [hooks]
672 > lookup.makecommit= sh $TESTTMP/listkeys_makecommit.sh
672 > lookup.makecommit= sh $TESTTMP/listkeys_makecommit.sh
673 > EOF
673 > EOF
674 $ restart_server # new config need server restart
674 $ restart_server # new config need server restart
675 $ hg -R $TESTTMP/pull-race book
675 $ hg -R $TESTTMP/pull-race book
676 @ 1:0d2164f0ce0d
676 @ 1:0d2164f0ce0d
677 X 1:0d2164f0ce0d
677 X 1:0d2164f0ce0d
678 * Y 6:0d60821d2197
678 * Y 6:0d60821d2197
679 Z 1:0d2164f0ce0d
679 Z 1:0d2164f0ce0d
680 $ hg pull -r Y
680 $ hg pull -r Y
681 pulling from http://localhost:$HGPORT/
681 pulling from http://localhost:$HGPORT/
682 searching for changes
682 searching for changes
683 adding changesets
683 adding changesets
684 adding manifests
684 adding manifests
685 adding file changes
685 adding file changes
686 updating bookmark Y
686 updating bookmark Y
687 added 1 changesets with 1 changes to 1 files
687 added 1 changesets with 1 changes to 1 files
688 new changesets 0d60821d2197 (1 drafts)
688 new changesets 0d60821d2197 (1 drafts)
689 (run 'hg update' to get a working copy)
689 (run 'hg update' to get a working copy)
690 $ hg book
690 $ hg book
691 @ 1:0d2164f0ce0d
691 @ 1:0d2164f0ce0d
692 X 1:0d2164f0ce0d
692 X 1:0d2164f0ce0d
693 * Y 6:0d60821d2197
693 * Y 6:0d60821d2197
694 Z 1:0d2164f0ce0d
694 Z 1:0d2164f0ce0d
695 $ hg -R $TESTTMP/pull-race book
695 $ hg -R $TESTTMP/pull-race book
696 @ 1:0d2164f0ce0d
696 @ 1:0d2164f0ce0d
697 X 1:0d2164f0ce0d
697 X 1:0d2164f0ce0d
698 * Y 7:714424d9e8b8
698 * Y 7:714424d9e8b8
699 Z 1:0d2164f0ce0d
699 Z 1:0d2164f0ce0d
700
700
701 (done with this section of the test)
701 (done with this section of the test)
702
702
703 $ killdaemons.py
703 $ killdaemons.py
704 $ cd ../b
704 $ cd ../b
705
705
706 diverging a remote bookmark fails
706 diverging a remote bookmark fails
707
707
708 $ hg up -q 4e3505fd9583
708 $ hg up -q 4e3505fd9583
709 $ echo c4 > f2
709 $ echo c4 > f2
710 $ hg ci -Am4
710 $ hg ci -Am4
711 adding f2
711 adding f2
712 created new head
712 created new head
713 $ echo c5 > f2
713 $ echo c5 > f2
714 $ hg ci -Am5
714 $ hg ci -Am5
715 $ hg log -G
715 $ hg log -G
716 @ 5:c922c0139ca0 5
716 @ 5:c922c0139ca0 5
717 |
717 |
718 o 4:4efff6d98829 4
718 o 4:4efff6d98829 4
719 |
719 |
720 | o 3:f6fc62dde3c0 3
720 | o 3:f6fc62dde3c0 3
721 |/
721 |/
722 | o 2:0d2164f0ce0d 1
722 | o 2:0d2164f0ce0d 1
723 |/
723 |/
724 | o 1:9b140be10808 2
724 | o 1:9b140be10808 2
725 |/
725 |/
726 o 0:4e3505fd9583 test
726 o 0:4e3505fd9583 test
727
727
728
728
729 $ hg book -f Y
729 $ hg book -f Y
730
730
731 $ cat <<EOF > ../a/.hg/hgrc
731 $ cat <<EOF > ../a/.hg/hgrc
732 > [web]
732 > [web]
733 > push_ssl = false
733 > push_ssl = false
734 > allow_push = *
734 > allow_push = *
735 > EOF
735 > EOF
736
736
737 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
737 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
738 $ cat ../hg2.pid >> $DAEMON_PIDS
738 $ cat ../hg2.pid >> $DAEMON_PIDS
739
739
740 $ hg push http://localhost:$HGPORT2/
740 $ hg push http://localhost:$HGPORT2/
741 pushing to http://localhost:$HGPORT2/
741 pushing to http://localhost:$HGPORT2/
742 searching for changes
742 searching for changes
743 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
743 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
744 (merge or see 'hg help push' for details about pushing new heads)
744 (merge or see 'hg help push' for details about pushing new heads)
745 [255]
745 [255]
746 $ hg -R ../a book
746 $ hg -R ../a book
747 @ 1:0d2164f0ce0d
747 @ 1:0d2164f0ce0d
748 * X 1:0d2164f0ce0d
748 * X 1:0d2164f0ce0d
749 Y 3:f6fc62dde3c0
749 Y 3:f6fc62dde3c0
750 Z 1:0d2164f0ce0d
750 Z 1:0d2164f0ce0d
751
751
752
752
753 Unrelated marker does not alter the decision
753 Unrelated marker does not alter the decision
754
754
755 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
755 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
756 1 new obsolescence markers
756 1 new obsolescence markers
757 $ hg push http://localhost:$HGPORT2/
757 $ hg push http://localhost:$HGPORT2/
758 pushing to http://localhost:$HGPORT2/
758 pushing to http://localhost:$HGPORT2/
759 searching for changes
759 searching for changes
760 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
760 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
761 (merge or see 'hg help push' for details about pushing new heads)
761 (merge or see 'hg help push' for details about pushing new heads)
762 [255]
762 [255]
763 $ hg -R ../a book
763 $ hg -R ../a book
764 @ 1:0d2164f0ce0d
764 @ 1:0d2164f0ce0d
765 * X 1:0d2164f0ce0d
765 * X 1:0d2164f0ce0d
766 Y 3:f6fc62dde3c0
766 Y 3:f6fc62dde3c0
767 Z 1:0d2164f0ce0d
767 Z 1:0d2164f0ce0d
768
768
769 Update to a successor works
769 Update to a successor works
770
770
771 $ hg id --debug -r 3
771 $ hg id --debug -r 3
772 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
772 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
773 $ hg id --debug -r 4
773 $ hg id --debug -r 4
774 4efff6d98829d9c824c621afd6e3f01865f5439f
774 4efff6d98829d9c824c621afd6e3f01865f5439f
775 $ hg id --debug -r 5
775 $ hg id --debug -r 5
776 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
776 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
777 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
777 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
778 1 new obsolescence markers
778 1 new obsolescence markers
779 obsoleted 1 changesets
779 obsoleted 1 changesets
780 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
780 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
781 1 new obsolescence markers
781 1 new obsolescence markers
782 $ hg push http://localhost:$HGPORT2/
782 $ hg push http://localhost:$HGPORT2/
783 pushing to http://localhost:$HGPORT2/
783 pushing to http://localhost:$HGPORT2/
784 searching for changes
784 searching for changes
785 remote: adding changesets
785 remote: adding changesets
786 remote: adding manifests
786 remote: adding manifests
787 remote: adding file changes
787 remote: adding file changes
788 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
788 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
789 remote: 2 new obsolescence markers
789 remote: 2 new obsolescence markers
790 remote: obsoleted 1 changesets
790 remote: obsoleted 1 changesets
791 updating bookmark Y
791 updating bookmark Y
792 $ hg -R ../a book
792 $ hg -R ../a book
793 @ 1:0d2164f0ce0d
793 @ 1:0d2164f0ce0d
794 * X 1:0d2164f0ce0d
794 * X 1:0d2164f0ce0d
795 Y 5:c922c0139ca0
795 Y 5:c922c0139ca0
796 Z 1:0d2164f0ce0d
796 Z 1:0d2164f0ce0d
797
797
798 hgweb
798 hgweb
799
799
800 $ cat <<EOF > .hg/hgrc
800 $ cat <<EOF > .hg/hgrc
801 > [web]
801 > [web]
802 > push_ssl = false
802 > push_ssl = false
803 > allow_push = *
803 > allow_push = *
804 > EOF
804 > EOF
805
805
806 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
806 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
807 $ cat ../hg.pid >> $DAEMON_PIDS
807 $ cat ../hg.pid >> $DAEMON_PIDS
808 $ cd ../a
808 $ cd ../a
809
809
810 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
810 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
811 bookmarks
811 bookmarks
812 namespaces
812 namespaces
813 obsolete
813 obsolete
814 phases
814 phases
815 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
815 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
816 @ 9b140be1080824d768c5a4691a564088eede71f9
816 @ 9b140be1080824d768c5a4691a564088eede71f9
817 X 9b140be1080824d768c5a4691a564088eede71f9
817 X 9b140be1080824d768c5a4691a564088eede71f9
818 Y c922c0139ca03858f655e4a2af4dd02796a63969
818 Y c922c0139ca03858f655e4a2af4dd02796a63969
819 Z 9b140be1080824d768c5a4691a564088eede71f9
819 Z 9b140be1080824d768c5a4691a564088eede71f9
820 foo 0000000000000000000000000000000000000000
820 foo 0000000000000000000000000000000000000000
821 foobar 9b140be1080824d768c5a4691a564088eede71f9
821 foobar 9b140be1080824d768c5a4691a564088eede71f9
822 $ hg out -B http://localhost:$HGPORT/
822 $ hg out -B http://localhost:$HGPORT/
823 comparing with http://localhost:$HGPORT/
823 comparing with http://localhost:$HGPORT/
824 searching for changed bookmarks
824 searching for changed bookmarks
825 @ 0d2164f0ce0d
825 @ 0d2164f0ce0d
826 X 0d2164f0ce0d
826 X 0d2164f0ce0d
827 Z 0d2164f0ce0d
827 Z 0d2164f0ce0d
828 foo
828 foo
829 foobar
829 foobar
830 $ hg push -B Z http://localhost:$HGPORT/
830 $ hg push -B Z http://localhost:$HGPORT/
831 pushing to http://localhost:$HGPORT/
831 pushing to http://localhost:$HGPORT/
832 searching for changes
832 searching for changes
833 no changes found
833 no changes found
834 updating bookmark Z
834 updating bookmark Z
835 [1]
835 [1]
836 $ hg book -d Z
836 $ hg book -d Z
837 $ hg in -B http://localhost:$HGPORT/
837 $ hg in -B http://localhost:$HGPORT/
838 comparing with http://localhost:$HGPORT/
838 comparing with http://localhost:$HGPORT/
839 searching for changed bookmarks
839 searching for changed bookmarks
840 @ 9b140be10808
840 @ 9b140be10808
841 X 9b140be10808
841 X 9b140be10808
842 Z 0d2164f0ce0d
842 Z 0d2164f0ce0d
843 foo 000000000000
843 foo 000000000000
844 foobar 9b140be10808
844 foobar 9b140be10808
845 $ hg pull -B Z http://localhost:$HGPORT/
845 $ hg pull -B Z http://localhost:$HGPORT/
846 pulling from http://localhost:$HGPORT/
846 pulling from http://localhost:$HGPORT/
847 no changes found
847 no changes found
848 divergent bookmark @ stored as @1
848 divergent bookmark @ stored as @1
849 divergent bookmark X stored as X@1
849 divergent bookmark X stored as X@1
850 adding remote bookmark Z
850 adding remote bookmark Z
851 adding remote bookmark foo
851 adding remote bookmark foo
852 adding remote bookmark foobar
852 adding remote bookmark foobar
853 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
853 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
854 requesting all changes
854 requesting all changes
855 adding changesets
855 adding changesets
856 adding manifests
856 adding manifests
857 adding file changes
857 adding file changes
858 added 5 changesets with 5 changes to 3 files (+2 heads)
858 added 5 changesets with 5 changes to 3 files (+2 heads)
859 2 new obsolescence markers
859 2 new obsolescence markers
860 new changesets 4e3505fd9583:c922c0139ca0 (5 drafts)
860 new changesets 4e3505fd9583:c922c0139ca0 (5 drafts)
861 updating to bookmark @
861 updating to bookmark @
862 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
862 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
863 $ hg -R cloned-bookmarks bookmarks
863 $ hg -R cloned-bookmarks bookmarks
864 * @ 1:9b140be10808
864 * @ 1:9b140be10808
865 X 1:9b140be10808
865 X 1:9b140be10808
866 Y 4:c922c0139ca0
866 Y 4:c922c0139ca0
867 Z 2:0d2164f0ce0d
867 Z 2:0d2164f0ce0d
868 foo -1:000000000000
868 foo -1:000000000000
869 foobar 1:9b140be10808
869 foobar 1:9b140be10808
870
870
871 $ cd ..
871 $ cd ..
872
872
873 Test to show result of bookmarks comparison
873 Test to show result of bookmarks comparison
874
874
875 $ mkdir bmcomparison
875 $ mkdir bmcomparison
876 $ cd bmcomparison
876 $ cd bmcomparison
877
877
878 $ hg init source
878 $ hg init source
879 $ hg -R source debugbuilddag '+2*2*3*4'
879 $ hg -R source debugbuilddag '+2*2*3*4'
880 $ hg -R source log -G --template '{rev}:{node|short}'
880 $ hg -R source log -G --template '{rev}:{node|short}'
881 o 4:e7bd5218ca15
881 o 4:e7bd5218ca15
882 |
882 |
883 | o 3:6100d3090acf
883 | o 3:6100d3090acf
884 |/
884 |/
885 | o 2:fa942426a6fd
885 | o 2:fa942426a6fd
886 |/
886 |/
887 | o 1:66f7d451a68b
887 | o 1:66f7d451a68b
888 |/
888 |/
889 o 0:1ea73414a91b
889 o 0:1ea73414a91b
890
890
891 $ hg -R source bookmarks -r 0 SAME
891 $ hg -R source bookmarks -r 0 SAME
892 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
892 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
893 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
893 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
894 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
894 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
895 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
895 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
896 $ hg -R source bookmarks -r 1 DIVERGED
896 $ hg -R source bookmarks -r 1 DIVERGED
897
897
898 $ hg clone -U source repo1
898 $ hg clone -U source repo1
899
899
900 (test that incoming/outgoing exit with 1, if there is no bookmark to
900 (test that incoming/outgoing exit with 1, if there is no bookmark to
901 be exchanged)
901 be exchanged)
902
902
903 $ hg -R repo1 incoming -B
903 $ hg -R repo1 incoming -B
904 comparing with $TESTTMP/bmcomparison/source
904 comparing with $TESTTMP/bmcomparison/source
905 searching for changed bookmarks
905 searching for changed bookmarks
906 no changed bookmarks found
906 no changed bookmarks found
907 [1]
907 [1]
908 $ hg -R repo1 outgoing -B
908 $ hg -R repo1 outgoing -B
909 comparing with $TESTTMP/bmcomparison/source
909 comparing with $TESTTMP/bmcomparison/source
910 searching for changed bookmarks
910 searching for changed bookmarks
911 no changed bookmarks found
911 no changed bookmarks found
912 [1]
912 [1]
913
913
914 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
914 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
915 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
915 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
916 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
916 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
917 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
917 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
918 $ hg -R repo1 -q --config extensions.mq= strip 4
918 $ hg -R repo1 -q --config extensions.mq= strip 4
919 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
919 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
920 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
920 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
921 |
921 |
922 | o fa942426a6fd (ADV_ON_REPO1)
922 | o fa942426a6fd (ADV_ON_REPO1)
923 |/
923 |/
924 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
924 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
925 |/
925 |/
926 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
926 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
927
927
928
928
929 $ hg clone -U source repo2
929 $ hg clone -U source repo2
930 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
930 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
931 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
931 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
932 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
932 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
933 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
933 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
934 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
934 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
935 $ hg -R repo2 -q --config extensions.mq= strip 3
935 $ hg -R repo2 -q --config extensions.mq= strip 3
936 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
936 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
937 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
937 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
938 |
938 |
939 | o fa942426a6fd (DIVERGED)
939 | o fa942426a6fd (DIVERGED)
940 |/
940 |/
941 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
941 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
942 |/
942 |/
943 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
943 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
944
944
945
945
946 (test that difference of bookmarks between repositories are fully shown)
946 (test that difference of bookmarks between repositories are fully shown)
947
947
948 $ hg -R repo1 incoming -B repo2 -v
948 $ hg -R repo1 incoming -B repo2 -v
949 comparing with repo2
949 comparing with repo2
950 searching for changed bookmarks
950 searching for changed bookmarks
951 ADD_ON_REPO2 66f7d451a68b added
951 ADD_ON_REPO2 66f7d451a68b added
952 ADV_ON_REPO2 66f7d451a68b advanced
952 ADV_ON_REPO2 66f7d451a68b advanced
953 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
953 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
954 DIFF_DIVERGED e7bd5218ca15 changed
954 DIFF_DIVERGED e7bd5218ca15 changed
955 DIVERGED fa942426a6fd diverged
955 DIVERGED fa942426a6fd diverged
956 $ hg -R repo1 outgoing -B repo2 -v
956 $ hg -R repo1 outgoing -B repo2 -v
957 comparing with repo2
957 comparing with repo2
958 searching for changed bookmarks
958 searching for changed bookmarks
959 ADD_ON_REPO1 66f7d451a68b added
959 ADD_ON_REPO1 66f7d451a68b added
960 ADD_ON_REPO2 deleted
960 ADD_ON_REPO2 deleted
961 ADV_ON_REPO1 fa942426a6fd advanced
961 ADV_ON_REPO1 fa942426a6fd advanced
962 DIFF_ADV_ON_REPO1 6100d3090acf advanced
962 DIFF_ADV_ON_REPO1 6100d3090acf advanced
963 DIFF_ADV_ON_REPO2 1ea73414a91b changed
963 DIFF_ADV_ON_REPO2 1ea73414a91b changed
964 DIFF_DIVERGED 6100d3090acf changed
964 DIFF_DIVERGED 6100d3090acf changed
965 DIVERGED 66f7d451a68b diverged
965 DIVERGED 66f7d451a68b diverged
966
966
967 $ hg -R repo2 incoming -B repo1 -v
967 $ hg -R repo2 incoming -B repo1 -v
968 comparing with repo1
968 comparing with repo1
969 searching for changed bookmarks
969 searching for changed bookmarks
970 ADD_ON_REPO1 66f7d451a68b added
970 ADD_ON_REPO1 66f7d451a68b added
971 ADV_ON_REPO1 fa942426a6fd advanced
971 ADV_ON_REPO1 fa942426a6fd advanced
972 DIFF_ADV_ON_REPO1 6100d3090acf changed
972 DIFF_ADV_ON_REPO1 6100d3090acf changed
973 DIFF_DIVERGED 6100d3090acf changed
973 DIFF_DIVERGED 6100d3090acf changed
974 DIVERGED 66f7d451a68b diverged
974 DIVERGED 66f7d451a68b diverged
975 $ hg -R repo2 outgoing -B repo1 -v
975 $ hg -R repo2 outgoing -B repo1 -v
976 comparing with repo1
976 comparing with repo1
977 searching for changed bookmarks
977 searching for changed bookmarks
978 ADD_ON_REPO1 deleted
978 ADD_ON_REPO1 deleted
979 ADD_ON_REPO2 66f7d451a68b added
979 ADD_ON_REPO2 66f7d451a68b added
980 ADV_ON_REPO2 66f7d451a68b advanced
980 ADV_ON_REPO2 66f7d451a68b advanced
981 DIFF_ADV_ON_REPO1 1ea73414a91b changed
981 DIFF_ADV_ON_REPO1 1ea73414a91b changed
982 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
982 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
983 DIFF_DIVERGED e7bd5218ca15 changed
983 DIFF_DIVERGED e7bd5218ca15 changed
984 DIVERGED fa942426a6fd diverged
984 DIVERGED fa942426a6fd diverged
985
985
986 $ cd ..
986 $ cd ..
987
987
988 Pushing a bookmark should only push the changes required by that
988 Pushing a bookmark should only push the changes required by that
989 bookmark, not all outgoing changes:
989 bookmark, not all outgoing changes:
990 $ hg clone http://localhost:$HGPORT/ addmarks
990 $ hg clone http://localhost:$HGPORT/ addmarks
991 requesting all changes
991 requesting all changes
992 adding changesets
992 adding changesets
993 adding manifests
993 adding manifests
994 adding file changes
994 adding file changes
995 added 5 changesets with 5 changes to 3 files (+2 heads)
995 added 5 changesets with 5 changes to 3 files (+2 heads)
996 2 new obsolescence markers
996 2 new obsolescence markers
997 new changesets 4e3505fd9583:c922c0139ca0 (5 drafts)
997 new changesets 4e3505fd9583:c922c0139ca0 (5 drafts)
998 updating to bookmark @
998 updating to bookmark @
999 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
999 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1000 $ cd addmarks
1000 $ cd addmarks
1001 $ echo foo > foo
1001 $ echo foo > foo
1002 $ hg add foo
1002 $ hg add foo
1003 $ hg commit -m 'add foo'
1003 $ hg commit -m 'add foo'
1004 $ echo bar > bar
1004 $ echo bar > bar
1005 $ hg add bar
1005 $ hg add bar
1006 $ hg commit -m 'add bar'
1006 $ hg commit -m 'add bar'
1007 $ hg co "tip^"
1007 $ hg co "tip^"
1008 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1008 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1009 (leaving bookmark @)
1009 (leaving bookmark @)
1010 $ hg book add-foo
1010 $ hg book add-foo
1011 $ hg book -r tip add-bar
1011 $ hg book -r tip add-bar
1012 Note: this push *must* push only a single changeset, as that's the point
1012 Note: this push *must* push only a single changeset, as that's the point
1013 of this test.
1013 of this test.
1014 $ hg push -B add-foo --traceback
1014 $ hg push -B add-foo --traceback
1015 pushing to http://localhost:$HGPORT/
1015 pushing to http://localhost:$HGPORT/
1016 searching for changes
1016 searching for changes
1017 remote: adding changesets
1017 remote: adding changesets
1018 remote: adding manifests
1018 remote: adding manifests
1019 remote: adding file changes
1019 remote: adding file changes
1020 remote: added 1 changesets with 1 changes to 1 files
1020 remote: added 1 changesets with 1 changes to 1 files
1021 exporting bookmark add-foo
1021 exporting bookmark add-foo
1022
1022
1023 pushing a new bookmark on a new head does not require -f if -B is specified
1023 pushing a new bookmark on a new head does not require -f if -B is specified
1024
1024
1025 $ hg up -q X
1025 $ hg up -q X
1026 $ hg book W
1026 $ hg book W
1027 $ echo c5 > f2
1027 $ echo c5 > f2
1028 $ hg ci -Am5
1028 $ hg ci -Am5
1029 created new head
1029 created new head
1030 $ hg push -B .
1030 $ hg push -B .
1031 pushing to http://localhost:$HGPORT/
1031 pushing to http://localhost:$HGPORT/
1032 searching for changes
1032 searching for changes
1033 remote: adding changesets
1033 remote: adding changesets
1034 remote: adding manifests
1034 remote: adding manifests
1035 remote: adding file changes
1035 remote: adding file changes
1036 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
1036 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
1037 exporting bookmark W
1037 exporting bookmark W
1038 $ hg -R ../b id -r W
1038 $ hg -R ../b id -r W
1039 cc978a373a53 tip W
1039 cc978a373a53 tip W
1040
1040
1041 pushing an existing but divergent bookmark with -B still requires -f
1041 pushing an existing but divergent bookmark with -B still requires -f
1042
1042
1043 $ hg clone -q . ../r
1043 $ hg clone -q . ../r
1044 $ hg up -q X
1044 $ hg up -q X
1045 $ echo 1 > f2
1045 $ echo 1 > f2
1046 $ hg ci -qAml
1046 $ hg ci -qAml
1047
1047
1048 $ cd ../r
1048 $ cd ../r
1049 $ hg up -q X
1049 $ hg up -q X
1050 $ echo 2 > f2
1050 $ echo 2 > f2
1051 $ hg ci -qAmr
1051 $ hg ci -qAmr
1052 $ hg push -B X
1052 $ hg push -B X
1053 pushing to $TESTTMP/addmarks
1053 pushing to $TESTTMP/addmarks
1054 searching for changes
1054 searching for changes
1055 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
1055 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
1056 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
1056 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
1057 (pull and merge or see 'hg help push' for details about pushing new heads)
1057 (pull and merge or see 'hg help push' for details about pushing new heads)
1058 [255]
1058 [255]
1059 $ cd ../addmarks
1059 $ cd ../addmarks
1060
1060
1061 Check summary output for incoming/outgoing bookmarks
1061 Check summary output for incoming/outgoing bookmarks
1062
1062
1063 $ hg bookmarks -d X
1063 $ hg bookmarks -d X
1064 $ hg bookmarks -d Y
1064 $ hg bookmarks -d Y
1065 $ hg summary --remote | grep '^remote:'
1065 $ hg summary --remote | grep '^remote:'
1066 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
1066 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
1067
1067
1068 $ cd ..
1068 $ cd ..
1069
1069
1070 pushing an unchanged bookmark should result in no changes
1070 pushing an unchanged bookmark should result in no changes
1071
1071
1072 $ hg init unchanged-a
1072 $ hg init unchanged-a
1073 $ hg init unchanged-b
1073 $ hg init unchanged-b
1074 $ cd unchanged-a
1074 $ cd unchanged-a
1075 $ echo initial > foo
1075 $ echo initial > foo
1076 $ hg commit -A -m initial
1076 $ hg commit -A -m initial
1077 adding foo
1077 adding foo
1078 $ hg bookmark @
1078 $ hg bookmark @
1079 $ hg push -B @ ../unchanged-b
1079 $ hg push -B @ ../unchanged-b
1080 pushing to ../unchanged-b
1080 pushing to ../unchanged-b
1081 searching for changes
1081 searching for changes
1082 adding changesets
1082 adding changesets
1083 adding manifests
1083 adding manifests
1084 adding file changes
1084 adding file changes
1085 added 1 changesets with 1 changes to 1 files
1085 added 1 changesets with 1 changes to 1 files
1086 exporting bookmark @
1086 exporting bookmark @
1087
1087
1088 $ hg push -B @ ../unchanged-b
1088 $ hg push -B @ ../unchanged-b
1089 pushing to ../unchanged-b
1089 pushing to ../unchanged-b
1090 searching for changes
1090 searching for changes
1091 no changes found
1091 no changes found
1092 [1]
1092 [1]
1093
1093
1094 Pushing a really long bookmark should work fine (issue5165)
1094 Pushing a really long bookmark should work fine (issue5165)
1095 ===============================================
1095 ===============================================
1096
1096
1097 #if b2-binary
1097 #if b2-binary
1098 >>> with open('longname', 'w') as f:
1098 >>> with open('longname', 'w') as f:
1099 ... f.write('wat' * 100) and None
1099 ... f.write('wat' * 100) and None
1100 $ hg book `cat longname`
1100 $ hg book `cat longname`
1101 $ hg push -B `cat longname` ../unchanged-b
1101 $ hg push -B `cat longname` ../unchanged-b
1102 pushing to ../unchanged-b
1102 pushing to ../unchanged-b
1103 searching for changes
1103 searching for changes
1104 no changes found
1104 no changes found
1105 exporting bookmark (wat){100} (re)
1105 exporting bookmark (wat){100} (re)
1106 [1]
1106 [1]
1107 $ hg -R ../unchanged-b book --delete `cat longname`
1107 $ hg -R ../unchanged-b book --delete `cat longname`
1108
1108
1109 Test again but forcing bundle2 exchange to make sure that doesn't regress.
1109 Test again but forcing bundle2 exchange to make sure that doesn't regress.
1110
1110
1111 $ hg push -B `cat longname` ../unchanged-b --config devel.legacy.exchange=bundle1
1111 $ hg push -B `cat longname` ../unchanged-b --config devel.legacy.exchange=bundle1
1112 pushing to ../unchanged-b
1112 pushing to ../unchanged-b
1113 searching for changes
1113 searching for changes
1114 no changes found
1114 no changes found
1115 exporting bookmark (wat){100} (re)
1115 exporting bookmark (wat){100} (re)
1116 [1]
1116 [1]
1117 $ hg -R ../unchanged-b book --delete `cat longname`
1117 $ hg -R ../unchanged-b book --delete `cat longname`
1118 $ hg book --delete `cat longname`
1118 $ hg book --delete `cat longname`
1119 $ hg co @
1119 $ hg co @
1120 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1120 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1121 (activating bookmark @)
1121 (activating bookmark @)
1122 #endif
1122 #endif
1123
1123
1124 Check hook preventing push (issue4455)
1124 Check hook preventing push (issue4455)
1125 ======================================
1125 ======================================
1126
1126
1127 $ hg bookmarks
1127 $ hg bookmarks
1128 * @ 0:55482a6fb4b1
1128 * @ 0:55482a6fb4b1
1129 $ hg log -G
1129 $ hg log -G
1130 @ 0:55482a6fb4b1 initial
1130 @ 0:55482a6fb4b1 initial
1131
1131
1132 $ hg init ../issue4455-dest
1132 $ hg init ../issue4455-dest
1133 $ hg push ../issue4455-dest # changesets only
1133 $ hg push ../issue4455-dest # changesets only
1134 pushing to ../issue4455-dest
1134 pushing to ../issue4455-dest
1135 searching for changes
1135 searching for changes
1136 adding changesets
1136 adding changesets
1137 adding manifests
1137 adding manifests
1138 adding file changes
1138 adding file changes
1139 added 1 changesets with 1 changes to 1 files
1139 added 1 changesets with 1 changes to 1 files
1140 $ cat >> .hg/hgrc << EOF
1140 $ cat >> .hg/hgrc << EOF
1141 > [paths]
1141 > [paths]
1142 > local=../issue4455-dest/
1142 > local=../issue4455-dest/
1143 > ssh=ssh://user@dummy/issue4455-dest
1143 > ssh=ssh://user@dummy/issue4455-dest
1144 > http=http://localhost:$HGPORT/
1144 > http=http://localhost:$HGPORT/
1145 > [ui]
1145 > [ui]
1146 > ssh="$PYTHON" "$TESTDIR/dummyssh"
1146 > ssh="$PYTHON" "$TESTDIR/dummyssh"
1147 > EOF
1147 > EOF
1148 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
1148 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
1149 > [hooks]
1149 > [hooks]
1150 > prepushkey=false
1150 > prepushkey=false
1151 > [web]
1151 > [web]
1152 > push_ssl = false
1152 > push_ssl = false
1153 > allow_push = *
1153 > allow_push = *
1154 > EOF
1154 > EOF
1155 $ killdaemons.py
1155 $ killdaemons.py
1156 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
1156 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
1157 $ cat ../issue4455.pid >> $DAEMON_PIDS
1157 $ cat ../issue4455.pid >> $DAEMON_PIDS
1158
1158
1159 Local push
1159 Local push
1160 ----------
1160 ----------
1161
1161
1162 #if b2-pushkey
1162 #if b2-pushkey
1163
1163
1164 $ hg push -B @ local
1164 $ hg push -B @ local
1165 pushing to $TESTTMP/issue4455-dest
1165 pushing to $TESTTMP/issue4455-dest
1166 searching for changes
1166 searching for changes
1167 no changes found
1167 no changes found
1168 pushkey-abort: prepushkey hook exited with status 1
1168 pushkey-abort: prepushkey hook exited with status 1
1169 abort: exporting bookmark @ failed!
1169 abort: exporting bookmark @ failed!
1170 [255]
1170 [255]
1171
1171
1172 #endif
1172 #endif
1173 #if b2-binary
1173 #if b2-binary
1174
1174
1175 $ hg push -B @ local
1175 $ hg push -B @ local
1176 pushing to $TESTTMP/issue4455-dest
1176 pushing to $TESTTMP/issue4455-dest
1177 searching for changes
1177 searching for changes
1178 no changes found
1178 no changes found
1179 abort: prepushkey hook exited with status 1
1179 abort: prepushkey hook exited with status 1
1180 [255]
1180 [255]
1181
1181
1182 #endif
1182 #endif
1183
1183
1184 $ hg -R ../issue4455-dest/ bookmarks
1184 $ hg -R ../issue4455-dest/ bookmarks
1185 no bookmarks set
1185 no bookmarks set
1186
1186
1187 Using ssh
1187 Using ssh
1188 ---------
1188 ---------
1189
1189
1190 #if b2-pushkey
1190 #if b2-pushkey
1191
1191
1192 $ hg push -B @ ssh # bundle2+
1192 $ hg push -B @ ssh # bundle2+
1193 pushing to ssh://user@dummy/issue4455-dest
1193 pushing to ssh://user@dummy/issue4455-dest
1194 searching for changes
1194 searching for changes
1195 no changes found
1195 no changes found
1196 remote: pushkey-abort: prepushkey hook exited with status 1
1196 remote: pushkey-abort: prepushkey hook exited with status 1
1197 abort: exporting bookmark @ failed!
1197 abort: exporting bookmark @ failed!
1198 [255]
1198 [255]
1199
1199
1200 $ hg -R ../issue4455-dest/ bookmarks
1200 $ hg -R ../issue4455-dest/ bookmarks
1201 no bookmarks set
1201 no bookmarks set
1202
1202
1203 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
1203 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
1204 pushing to ssh://user@dummy/issue4455-dest
1204 pushing to ssh://user@dummy/issue4455-dest
1205 searching for changes
1205 searching for changes
1206 no changes found
1206 no changes found
1207 remote: pushkey-abort: prepushkey hook exited with status 1
1207 remote: pushkey-abort: prepushkey hook exited with status 1
1208 exporting bookmark @ failed!
1208 exporting bookmark @ failed!
1209 [1]
1209 [1]
1210
1210
1211 #endif
1211 #endif
1212 #if b2-binary
1212 #if b2-binary
1213
1213
1214 $ hg push -B @ ssh # bundle2+
1214 $ hg push -B @ ssh # bundle2+
1215 pushing to ssh://user@dummy/issue4455-dest
1215 pushing to ssh://user@dummy/issue4455-dest
1216 searching for changes
1216 searching for changes
1217 no changes found
1217 no changes found
1218 remote: prepushkey hook exited with status 1
1218 remote: prepushkey hook exited with status 1
1219 abort: push failed on remote
1219 abort: push failed on remote
1220 [255]
1220 [255]
1221
1221
1222 #endif
1222 #endif
1223
1223
1224 $ hg -R ../issue4455-dest/ bookmarks
1224 $ hg -R ../issue4455-dest/ bookmarks
1225 no bookmarks set
1225 no bookmarks set
1226
1226
1227 Using http
1227 Using http
1228 ----------
1228 ----------
1229
1229
1230 #if b2-pushkey
1230 #if b2-pushkey
1231 $ hg push -B @ http # bundle2+
1231 $ hg push -B @ http # bundle2+
1232 pushing to http://localhost:$HGPORT/
1232 pushing to http://localhost:$HGPORT/
1233 searching for changes
1233 searching for changes
1234 no changes found
1234 no changes found
1235 remote: pushkey-abort: prepushkey hook exited with status 1
1235 remote: pushkey-abort: prepushkey hook exited with status 1
1236 abort: exporting bookmark @ failed!
1236 abort: exporting bookmark @ failed!
1237 [255]
1237 [255]
1238
1238
1239 $ hg -R ../issue4455-dest/ bookmarks
1239 $ hg -R ../issue4455-dest/ bookmarks
1240 no bookmarks set
1240 no bookmarks set
1241
1241
1242 $ hg push -B @ http --config devel.legacy.exchange=bundle1
1242 $ hg push -B @ http --config devel.legacy.exchange=bundle1
1243 pushing to http://localhost:$HGPORT/
1243 pushing to http://localhost:$HGPORT/
1244 searching for changes
1244 searching for changes
1245 no changes found
1245 no changes found
1246 remote: pushkey-abort: prepushkey hook exited with status 1
1246 remote: pushkey-abort: prepushkey hook exited with status 1
1247 exporting bookmark @ failed!
1247 exporting bookmark @ failed!
1248 [1]
1248 [1]
1249
1249
1250 #endif
1250 #endif
1251
1251
1252 #if b2-binary
1252 #if b2-binary
1253
1253
1254 $ hg push -B @ ssh # bundle2+
1254 $ hg push -B @ ssh # bundle2+
1255 pushing to ssh://user@dummy/issue4455-dest
1255 pushing to ssh://user@dummy/issue4455-dest
1256 searching for changes
1256 searching for changes
1257 no changes found
1257 no changes found
1258 remote: prepushkey hook exited with status 1
1258 remote: prepushkey hook exited with status 1
1259 abort: push failed on remote
1259 abort: push failed on remote
1260 [255]
1260 [255]
1261
1261
1262 #endif
1262 #endif
1263
1263
1264 $ hg -R ../issue4455-dest/ bookmarks
1264 $ hg -R ../issue4455-dest/ bookmarks
1265 no bookmarks set
1265 no bookmarks set
1266
1266
1267 $ cd ..
1267 $ cd ..
1268
1268
1269 Test that pre-pushkey compat for bookmark works as expected (issue5777)
1269 Test that pre-pushkey compat for bookmark works as expected (issue5777)
1270
1270
1271 $ cat << EOF >> $HGRCPATH
1271 $ cat << EOF >> $HGRCPATH
1272 > [ui]
1272 > [ui]
1273 > ssh="$PYTHON" "$TESTDIR/dummyssh"
1273 > ssh="$PYTHON" "$TESTDIR/dummyssh"
1274 > [server]
1274 > [server]
1275 > bookmarks-pushkey-compat = yes
1275 > bookmarks-pushkey-compat = yes
1276 > EOF
1276 > EOF
1277
1277
1278 $ hg init server
1278 $ hg init server
1279 $ echo foo > server/a
1279 $ echo foo > server/a
1280 $ hg -R server book foo
1280 $ hg -R server book foo
1281 $ hg -R server commit -Am a
1281 $ hg -R server commit -Am a
1282 adding a
1282 adding a
1283 $ hg clone ssh://user@dummy/server client
1283 $ hg clone ssh://user@dummy/server client
1284 requesting all changes
1284 requesting all changes
1285 adding changesets
1285 adding changesets
1286 adding manifests
1286 adding manifests
1287 adding file changes
1287 adding file changes
1288 added 1 changesets with 1 changes to 1 files
1288 added 1 changesets with 1 changes to 1 files
1289 new changesets 79513d0d7716 (1 drafts)
1289 new changesets 79513d0d7716 (1 drafts)
1290 updating to branch default
1290 updating to branch default
1291 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1291 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1292
1292
1293 Forbid bookmark move on the server
1293 Forbid bookmark move on the server
1294
1294
1295 $ cat << EOF >> $TESTTMP/no-bm-move.sh
1295 $ cat << EOF >> $TESTTMP/no-bm-move.sh
1296 > #!/bin/sh
1296 > #!/bin/sh
1297 > echo \$HG_NAMESPACE | grep -v bookmarks
1297 > echo \$HG_NAMESPACE | grep -v bookmarks
1298 > EOF
1298 > EOF
1299 $ cat << EOF >> server/.hg/hgrc
1299 $ cat << EOF >> server/.hg/hgrc
1300 > [hooks]
1300 > [hooks]
1301 > prepushkey.no-bm-move= sh $TESTTMP/no-bm-move.sh
1301 > prepushkey.no-bm-move= sh $TESTTMP/no-bm-move.sh
1302 > EOF
1302 > EOF
1303
1303
1304 pushing changeset is okay
1304 pushing changeset is okay
1305
1305
1306 $ echo bar >> client/a
1306 $ echo bar >> client/a
1307 $ hg -R client commit -m b
1307 $ hg -R client commit -m b
1308 $ hg -R client push
1308 $ hg -R client push
1309 pushing to ssh://user@dummy/server
1309 pushing to ssh://user@dummy/server
1310 searching for changes
1310 searching for changes
1311 remote: adding changesets
1311 remote: adding changesets
1312 remote: adding manifests
1312 remote: adding manifests
1313 remote: adding file changes
1313 remote: adding file changes
1314 remote: added 1 changesets with 1 changes to 1 files
1314 remote: added 1 changesets with 1 changes to 1 files
1315
1315
1316 attempt to move the bookmark is rejected
1316 attempt to move the bookmark is rejected
1317
1317
1318 $ hg -R client book foo -r .
1318 $ hg -R client book foo -r .
1319 moving bookmark 'foo' forward from 79513d0d7716
1319 moving bookmark 'foo' forward from 79513d0d7716
1320
1320
1321 #if b2-pushkey
1321 #if b2-pushkey
1322 $ hg -R client push
1322 $ hg -R client push
1323 pushing to ssh://user@dummy/server
1323 pushing to ssh://user@dummy/server
1324 searching for changes
1324 searching for changes
1325 no changes found
1325 no changes found
1326 remote: pushkey-abort: prepushkey.no-bm-move hook exited with status 1
1326 remote: pushkey-abort: prepushkey.no-bm-move hook exited with status 1
1327 abort: updating bookmark foo failed!
1327 abort: updating bookmark foo failed!
1328 [255]
1328 [255]
1329 #endif
1329 #endif
1330 #if b2-binary
1330 #if b2-binary
1331 $ hg -R client push
1331 $ hg -R client push
1332 pushing to ssh://user@dummy/server
1332 pushing to ssh://user@dummy/server
1333 searching for changes
1333 searching for changes
1334 no changes found
1334 no changes found
1335 remote: prepushkey.no-bm-move hook exited with status 1
1335 remote: prepushkey.no-bm-move hook exited with status 1
1336 abort: push failed on remote
1336 abort: push failed on remote
1337 [255]
1337 [255]
1338 #endif
1338 #endif
1339
1339
1340 -- test for pushing bookmarks pointing to secret changesets
1340 -- test for pushing bookmarks pointing to secret changesets
1341
1341
1342 Set up a "remote" repo
1342 Set up a "remote" repo
1343 $ hg init issue6159remote
1343 $ hg init issue6159remote
1344 $ cd issue6159remote
1344 $ cd issue6159remote
1345 $ echo a > a
1345 $ echo a > a
1346 $ hg add a
1346 $ hg add a
1347 $ hg commit -m_
1347 $ hg commit -m_
1348 $ hg bookmark foo
1348 $ hg bookmark foo
1349 $ cd ..
1349 $ cd ..
1350
1350
1351 Clone a local repo
1351 Clone a local repo
1352 $ hg clone -q issue6159remote issue6159local
1352 $ hg clone -q issue6159remote issue6159local
1353 $ cd issue6159local
1353 $ cd issue6159local
1354 $ hg up -qr foo
1354 $ hg up -qr foo
1355 $ echo b > b
1355 $ echo b > b
1356
1356
1357 Move the bookmark "foo" to point at a secret changeset
1357 Move the bookmark "foo" to point at a secret changeset
1358 $ hg commit -qAm_ --config phases.new-commit=secret
1358 $ hg commit -qAm_ --config phases.new-commit=secret
1359
1359
1360 Pushing the bookmark "foo" now fails as it contains a secret changeset
1360 Pushing the bookmark "foo" now fails as it contains a secret changeset
1361 $ hg push -r foo
1361 $ hg push -r foo
1362 pushing to $TESTTMP/issue6159remote
1362 pushing to $TESTTMP/issue6159remote
1363 searching for changes
1363 searching for changes
1364 no changes found (ignored 1 secret changesets)
1364 no changes found (ignored 1 secret changesets)
1365 abort: cannot push bookmark foo as it points to a secret changeset
1365 abort: cannot push bookmark foo as it points to a secret changeset
1366 [255]
1366 [255]
1367
1368 Test pushing all bookmarks
1369
1370 $ hg init $TESTTMP/ab1
1371 $ cd $TESTTMP/ab1
1372 $ "$PYTHON" $TESTDIR/seq.py 1 5 | while read i; do
1373 > echo $i > test && hg ci -Am test
1374 > done
1375 adding test
1376 $ hg clone -U . ../ab2
1377 $ hg book -r 1 A; hg book -r 2 B; hg book -r 3 C
1378 $ hg push ../ab2
1379 pushing to ../ab2
1380 searching for changes
1381 no changes found
1382 [1]
1383 $ hg push --all-bookmarks -r 1 ../ab2
1384 abort: cannot specify both --all-bookmarks and --rev
1385 [255]
1386 $ hg push --all-bookmarks -B A ../ab2
1387 abort: cannot specify both --all-bookmarks and --bookmark
1388 [255]
1389 $ hg push --all-bookmarks ../ab2
1390 pushing to ../ab2
1391 searching for changes
1392 no changes found
1393 exporting bookmark A
1394 exporting bookmark B
1395 exporting bookmark C
1396 [1]
@@ -1,437 +1,437 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 abort
3 abort
4 add
4 add
5 addremove
5 addremove
6 annotate
6 annotate
7 archive
7 archive
8 backout
8 backout
9 bisect
9 bisect
10 bookmarks
10 bookmarks
11 branch
11 branch
12 branches
12 branches
13 bundle
13 bundle
14 cat
14 cat
15 clone
15 clone
16 commit
16 commit
17 config
17 config
18 continue
18 continue
19 copy
19 copy
20 diff
20 diff
21 export
21 export
22 files
22 files
23 forget
23 forget
24 graft
24 graft
25 grep
25 grep
26 heads
26 heads
27 help
27 help
28 identify
28 identify
29 import
29 import
30 incoming
30 incoming
31 init
31 init
32 locate
32 locate
33 log
33 log
34 manifest
34 manifest
35 merge
35 merge
36 outgoing
36 outgoing
37 parents
37 parents
38 paths
38 paths
39 phase
39 phase
40 pull
40 pull
41 push
41 push
42 recover
42 recover
43 remove
43 remove
44 rename
44 rename
45 resolve
45 resolve
46 revert
46 revert
47 rollback
47 rollback
48 root
48 root
49 serve
49 serve
50 shelve
50 shelve
51 status
51 status
52 summary
52 summary
53 tag
53 tag
54 tags
54 tags
55 tip
55 tip
56 unbundle
56 unbundle
57 unshelve
57 unshelve
58 update
58 update
59 verify
59 verify
60 version
60 version
61
61
62 Show all commands that start with "a"
62 Show all commands that start with "a"
63 $ hg debugcomplete a
63 $ hg debugcomplete a
64 abort
64 abort
65 add
65 add
66 addremove
66 addremove
67 annotate
67 annotate
68 archive
68 archive
69
69
70 Do not show debug commands if there are other candidates
70 Do not show debug commands if there are other candidates
71 $ hg debugcomplete d
71 $ hg debugcomplete d
72 diff
72 diff
73
73
74 Show debug commands if there are no other candidates
74 Show debug commands if there are no other candidates
75 $ hg debugcomplete debug
75 $ hg debugcomplete debug
76 debugancestor
76 debugancestor
77 debugantivirusrunning
77 debugantivirusrunning
78 debugapplystreamclonebundle
78 debugapplystreamclonebundle
79 debugbackupbundle
79 debugbackupbundle
80 debugbuilddag
80 debugbuilddag
81 debugbundle
81 debugbundle
82 debugcapabilities
82 debugcapabilities
83 debugchangedfiles
83 debugchangedfiles
84 debugcheckstate
84 debugcheckstate
85 debugcolor
85 debugcolor
86 debugcommands
86 debugcommands
87 debugcomplete
87 debugcomplete
88 debugconfig
88 debugconfig
89 debugcreatestreamclonebundle
89 debugcreatestreamclonebundle
90 debugdag
90 debugdag
91 debugdata
91 debugdata
92 debugdate
92 debugdate
93 debugdeltachain
93 debugdeltachain
94 debugdirstate
94 debugdirstate
95 debugdiscovery
95 debugdiscovery
96 debugdownload
96 debugdownload
97 debugextensions
97 debugextensions
98 debugfileset
98 debugfileset
99 debugformat
99 debugformat
100 debugfsinfo
100 debugfsinfo
101 debuggetbundle
101 debuggetbundle
102 debugignore
102 debugignore
103 debugindex
103 debugindex
104 debugindexdot
104 debugindexdot
105 debugindexstats
105 debugindexstats
106 debuginstall
106 debuginstall
107 debugknown
107 debugknown
108 debuglabelcomplete
108 debuglabelcomplete
109 debuglocks
109 debuglocks
110 debugmanifestfulltextcache
110 debugmanifestfulltextcache
111 debugmergestate
111 debugmergestate
112 debugnamecomplete
112 debugnamecomplete
113 debugnodemap
113 debugnodemap
114 debugobsolete
114 debugobsolete
115 debugp1copies
115 debugp1copies
116 debugp2copies
116 debugp2copies
117 debugpathcomplete
117 debugpathcomplete
118 debugpathcopies
118 debugpathcopies
119 debugpeer
119 debugpeer
120 debugpickmergetool
120 debugpickmergetool
121 debugpushkey
121 debugpushkey
122 debugpvec
122 debugpvec
123 debugrebuilddirstate
123 debugrebuilddirstate
124 debugrebuildfncache
124 debugrebuildfncache
125 debugrename
125 debugrename
126 debugrequires
126 debugrequires
127 debugrevlog
127 debugrevlog
128 debugrevlogindex
128 debugrevlogindex
129 debugrevspec
129 debugrevspec
130 debugserve
130 debugserve
131 debugsetparents
131 debugsetparents
132 debugsidedata
132 debugsidedata
133 debugssl
133 debugssl
134 debugsub
134 debugsub
135 debugsuccessorssets
135 debugsuccessorssets
136 debugtagscache
136 debugtagscache
137 debugtemplate
137 debugtemplate
138 debuguigetpass
138 debuguigetpass
139 debuguiprompt
139 debuguiprompt
140 debugupdatecaches
140 debugupdatecaches
141 debugupgraderepo
141 debugupgraderepo
142 debugwalk
142 debugwalk
143 debugwhyunstable
143 debugwhyunstable
144 debugwireargs
144 debugwireargs
145 debugwireproto
145 debugwireproto
146
146
147 Do not show the alias of a debug command if there are other candidates
147 Do not show the alias of a debug command if there are other candidates
148 (this should hide rawcommit)
148 (this should hide rawcommit)
149 $ hg debugcomplete r
149 $ hg debugcomplete r
150 recover
150 recover
151 remove
151 remove
152 rename
152 rename
153 resolve
153 resolve
154 revert
154 revert
155 rollback
155 rollback
156 root
156 root
157 Show the alias of a debug command if there are no other candidates
157 Show the alias of a debug command if there are no other candidates
158 $ hg debugcomplete rawc
158 $ hg debugcomplete rawc
159
159
160
160
161 Show the global options
161 Show the global options
162 $ hg debugcomplete --options | sort
162 $ hg debugcomplete --options | sort
163 --color
163 --color
164 --config
164 --config
165 --cwd
165 --cwd
166 --debug
166 --debug
167 --debugger
167 --debugger
168 --encoding
168 --encoding
169 --encodingmode
169 --encodingmode
170 --help
170 --help
171 --hidden
171 --hidden
172 --noninteractive
172 --noninteractive
173 --pager
173 --pager
174 --profile
174 --profile
175 --quiet
175 --quiet
176 --repository
176 --repository
177 --time
177 --time
178 --traceback
178 --traceback
179 --verbose
179 --verbose
180 --version
180 --version
181 -R
181 -R
182 -h
182 -h
183 -q
183 -q
184 -v
184 -v
185 -y
185 -y
186
186
187 Show the options for the "serve" command
187 Show the options for the "serve" command
188 $ hg debugcomplete --options serve | sort
188 $ hg debugcomplete --options serve | sort
189 --accesslog
189 --accesslog
190 --address
190 --address
191 --certificate
191 --certificate
192 --cmdserver
192 --cmdserver
193 --color
193 --color
194 --config
194 --config
195 --cwd
195 --cwd
196 --daemon
196 --daemon
197 --daemon-postexec
197 --daemon-postexec
198 --debug
198 --debug
199 --debugger
199 --debugger
200 --encoding
200 --encoding
201 --encodingmode
201 --encodingmode
202 --errorlog
202 --errorlog
203 --help
203 --help
204 --hidden
204 --hidden
205 --ipv6
205 --ipv6
206 --name
206 --name
207 --noninteractive
207 --noninteractive
208 --pager
208 --pager
209 --pid-file
209 --pid-file
210 --port
210 --port
211 --prefix
211 --prefix
212 --print-url
212 --print-url
213 --profile
213 --profile
214 --quiet
214 --quiet
215 --repository
215 --repository
216 --stdio
216 --stdio
217 --style
217 --style
218 --subrepos
218 --subrepos
219 --templates
219 --templates
220 --time
220 --time
221 --traceback
221 --traceback
222 --verbose
222 --verbose
223 --version
223 --version
224 --web-conf
224 --web-conf
225 -6
225 -6
226 -A
226 -A
227 -E
227 -E
228 -R
228 -R
229 -S
229 -S
230 -a
230 -a
231 -d
231 -d
232 -h
232 -h
233 -n
233 -n
234 -p
234 -p
235 -q
235 -q
236 -t
236 -t
237 -v
237 -v
238 -y
238 -y
239
239
240 Show an error if we use --options with an ambiguous abbreviation
240 Show an error if we use --options with an ambiguous abbreviation
241 $ hg debugcomplete --options s
241 $ hg debugcomplete --options s
242 hg: command 's' is ambiguous:
242 hg: command 's' is ambiguous:
243 serve shelve showconfig status summary
243 serve shelve showconfig status summary
244 [255]
244 [255]
245
245
246 Show all commands + options
246 Show all commands + options
247 $ hg debugcommands
247 $ hg debugcommands
248 abort: dry-run
248 abort: dry-run
249 add: include, exclude, subrepos, dry-run
249 add: include, exclude, subrepos, dry-run
250 addremove: similarity, subrepos, include, exclude, dry-run
250 addremove: similarity, subrepos, include, exclude, dry-run
251 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
251 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
252 archive: no-decode, prefix, rev, type, subrepos, include, exclude
252 archive: no-decode, prefix, rev, type, subrepos, include, exclude
253 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
253 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
254 bisect: reset, good, bad, skip, extend, command, noupdate
254 bisect: reset, good, bad, skip, extend, command, noupdate
255 bookmarks: force, rev, delete, rename, inactive, list, template
255 bookmarks: force, rev, delete, rename, inactive, list, template
256 branch: force, clean, rev
256 branch: force, clean, rev
257 branches: active, closed, rev, template
257 branches: active, closed, rev, template
258 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
258 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
259 cat: output, rev, decode, include, exclude, template
259 cat: output, rev, decode, include, exclude, template
260 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
260 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
261 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
261 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
262 config: untrusted, edit, local, shared, non-shared, global, template
262 config: untrusted, edit, local, shared, non-shared, global, template
263 continue: dry-run
263 continue: dry-run
264 copy: forget, after, at-rev, force, include, exclude, dry-run
264 copy: forget, after, at-rev, force, include, exclude, dry-run
265 debugancestor:
265 debugancestor:
266 debugantivirusrunning:
266 debugantivirusrunning:
267 debugapplystreamclonebundle:
267 debugapplystreamclonebundle:
268 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
268 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
269 debugbuilddag: mergeable-file, overwritten-file, new-file
269 debugbuilddag: mergeable-file, overwritten-file, new-file
270 debugbundle: all, part-type, spec
270 debugbundle: all, part-type, spec
271 debugcapabilities:
271 debugcapabilities:
272 debugchangedfiles:
272 debugchangedfiles:
273 debugcheckstate:
273 debugcheckstate:
274 debugcolor: style
274 debugcolor: style
275 debugcommands:
275 debugcommands:
276 debugcomplete: options
276 debugcomplete: options
277 debugcreatestreamclonebundle:
277 debugcreatestreamclonebundle:
278 debugdag: tags, branches, dots, spaces
278 debugdag: tags, branches, dots, spaces
279 debugdata: changelog, manifest, dir
279 debugdata: changelog, manifest, dir
280 debugdate: extended
280 debugdate: extended
281 debugdeltachain: changelog, manifest, dir, template
281 debugdeltachain: changelog, manifest, dir, template
282 debugdirstate: nodates, dates, datesort
282 debugdirstate: nodates, dates, datesort
283 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
283 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
284 debugdownload: output
284 debugdownload: output
285 debugextensions: template
285 debugextensions: template
286 debugfileset: rev, all-files, show-matcher, show-stage
286 debugfileset: rev, all-files, show-matcher, show-stage
287 debugformat: template
287 debugformat: template
288 debugfsinfo:
288 debugfsinfo:
289 debuggetbundle: head, common, type
289 debuggetbundle: head, common, type
290 debugignore:
290 debugignore:
291 debugindex: changelog, manifest, dir, template
291 debugindex: changelog, manifest, dir, template
292 debugindexdot: changelog, manifest, dir
292 debugindexdot: changelog, manifest, dir
293 debugindexstats:
293 debugindexstats:
294 debuginstall: template
294 debuginstall: template
295 debugknown:
295 debugknown:
296 debuglabelcomplete:
296 debuglabelcomplete:
297 debuglocks: force-lock, force-wlock, set-lock, set-wlock
297 debuglocks: force-lock, force-wlock, set-lock, set-wlock
298 debugmanifestfulltextcache: clear, add
298 debugmanifestfulltextcache: clear, add
299 debugmergestate: style, template
299 debugmergestate: style, template
300 debugnamecomplete:
300 debugnamecomplete:
301 debugnodemap: dump-new, dump-disk, check, metadata
301 debugnodemap: dump-new, dump-disk, check, metadata
302 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
302 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
303 debugp1copies: rev
303 debugp1copies: rev
304 debugp2copies: rev
304 debugp2copies: rev
305 debugpathcomplete: full, normal, added, removed
305 debugpathcomplete: full, normal, added, removed
306 debugpathcopies: include, exclude
306 debugpathcopies: include, exclude
307 debugpeer:
307 debugpeer:
308 debugpickmergetool: rev, changedelete, include, exclude, tool
308 debugpickmergetool: rev, changedelete, include, exclude, tool
309 debugpushkey:
309 debugpushkey:
310 debugpvec:
310 debugpvec:
311 debugrebuilddirstate: rev, minimal
311 debugrebuilddirstate: rev, minimal
312 debugrebuildfncache:
312 debugrebuildfncache:
313 debugrename: rev
313 debugrename: rev
314 debugrequires:
314 debugrequires:
315 debugrevlog: changelog, manifest, dir, dump
315 debugrevlog: changelog, manifest, dir, dump
316 debugrevlogindex: changelog, manifest, dir, format
316 debugrevlogindex: changelog, manifest, dir, format
317 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
317 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
318 debugserve: sshstdio, logiofd, logiofile
318 debugserve: sshstdio, logiofd, logiofile
319 debugsetparents:
319 debugsetparents:
320 debugsidedata: changelog, manifest, dir
320 debugsidedata: changelog, manifest, dir
321 debugssl:
321 debugssl:
322 debugsub: rev
322 debugsub: rev
323 debugsuccessorssets: closest
323 debugsuccessorssets: closest
324 debugtagscache:
324 debugtagscache:
325 debugtemplate: rev, define
325 debugtemplate: rev, define
326 debuguigetpass: prompt
326 debuguigetpass: prompt
327 debuguiprompt: prompt
327 debuguiprompt: prompt
328 debugupdatecaches:
328 debugupdatecaches:
329 debugupgraderepo: optimize, run, backup, changelog, manifest
329 debugupgraderepo: optimize, run, backup, changelog, manifest
330 debugwalk: include, exclude
330 debugwalk: include, exclude
331 debugwhyunstable:
331 debugwhyunstable:
332 debugwireargs: three, four, five, ssh, remotecmd, insecure
332 debugwireargs: three, four, five, ssh, remotecmd, insecure
333 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
333 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
334 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
334 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
335 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
335 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
336 files: rev, print0, include, exclude, template, subrepos
336 files: rev, print0, include, exclude, template, subrepos
337 forget: interactive, include, exclude, dry-run
337 forget: interactive, include, exclude, dry-run
338 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
338 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
339 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
339 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
340 heads: rev, topo, active, closed, style, template
340 heads: rev, topo, active, closed, style, template
341 help: extension, command, keyword, system
341 help: extension, command, keyword, system
342 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
342 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
343 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
343 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
344 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
344 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
345 init: ssh, remotecmd, insecure
345 init: ssh, remotecmd, insecure
346 locate: rev, print0, fullpath, include, exclude
346 locate: rev, print0, fullpath, include, exclude
347 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
347 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
348 manifest: rev, all, template
348 manifest: rev, all, template
349 merge: force, rev, preview, abort, tool
349 merge: force, rev, preview, abort, tool
350 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
350 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
351 parents: rev, style, template
351 parents: rev, style, template
352 paths: template
352 paths: template
353 phase: public, draft, secret, force, rev
353 phase: public, draft, secret, force, rev
354 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
354 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
355 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
355 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
356 recover: verify
356 recover: verify
357 remove: after, force, subrepos, include, exclude, dry-run
357 remove: after, force, subrepos, include, exclude, dry-run
358 rename: after, at-rev, force, include, exclude, dry-run
358 rename: after, at-rev, force, include, exclude, dry-run
359 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
359 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
360 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
360 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
361 rollback: dry-run, force
361 rollback: dry-run, force
362 root: template
362 root: template
363 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
363 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
364 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
364 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
365 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
365 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
366 summary: remote
366 summary: remote
367 tag: force, local, rev, remove, edit, message, date, user
367 tag: force, local, rev, remove, edit, message, date, user
368 tags: template
368 tags: template
369 tip: patch, git, style, template
369 tip: patch, git, style, template
370 unbundle: update
370 unbundle: update
371 unshelve: abort, continue, interactive, keep, name, tool, date
371 unshelve: abort, continue, interactive, keep, name, tool, date
372 update: clean, check, merge, date, rev, tool
372 update: clean, check, merge, date, rev, tool
373 verify: full
373 verify: full
374 version: template
374 version: template
375
375
376 $ hg init a
376 $ hg init a
377 $ cd a
377 $ cd a
378 $ echo fee > fee
378 $ echo fee > fee
379 $ hg ci -q -Amfee
379 $ hg ci -q -Amfee
380 $ hg tag fee
380 $ hg tag fee
381 $ mkdir fie
381 $ mkdir fie
382 $ echo dead > fie/dead
382 $ echo dead > fie/dead
383 $ echo live > fie/live
383 $ echo live > fie/live
384 $ hg bookmark fo
384 $ hg bookmark fo
385 $ hg branch -q fie
385 $ hg branch -q fie
386 $ hg ci -q -Amfie
386 $ hg ci -q -Amfie
387 $ echo fo > fo
387 $ echo fo > fo
388 $ hg branch -qf default
388 $ hg branch -qf default
389 $ hg ci -q -Amfo
389 $ hg ci -q -Amfo
390 $ echo Fum > Fum
390 $ echo Fum > Fum
391 $ hg ci -q -AmFum
391 $ hg ci -q -AmFum
392 $ hg bookmark Fum
392 $ hg bookmark Fum
393
393
394 Test debugpathcomplete
394 Test debugpathcomplete
395
395
396 $ hg debugpathcomplete f
396 $ hg debugpathcomplete f
397 fee
397 fee
398 fie
398 fie
399 fo
399 fo
400 $ hg debugpathcomplete -f f
400 $ hg debugpathcomplete -f f
401 fee
401 fee
402 fie/dead
402 fie/dead
403 fie/live
403 fie/live
404 fo
404 fo
405
405
406 $ hg rm Fum
406 $ hg rm Fum
407 $ hg debugpathcomplete -r F
407 $ hg debugpathcomplete -r F
408 Fum
408 Fum
409
409
410 Test debugnamecomplete
410 Test debugnamecomplete
411
411
412 $ hg debugnamecomplete
412 $ hg debugnamecomplete
413 Fum
413 Fum
414 default
414 default
415 fee
415 fee
416 fie
416 fie
417 fo
417 fo
418 tip
418 tip
419 $ hg debugnamecomplete f
419 $ hg debugnamecomplete f
420 fee
420 fee
421 fie
421 fie
422 fo
422 fo
423
423
424 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
424 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
425 used for completions in some shells.
425 used for completions in some shells.
426
426
427 $ hg debuglabelcomplete
427 $ hg debuglabelcomplete
428 Fum
428 Fum
429 default
429 default
430 fee
430 fee
431 fie
431 fie
432 fo
432 fo
433 tip
433 tip
434 $ hg debuglabelcomplete f
434 $ hg debuglabelcomplete f
435 fee
435 fee
436 fie
436 fie
437 fo
437 fo
General Comments 0
You need to be logged in to leave comments. Login now