##// END OF EJS Templates
bundle: introduce a --exact option...
marmoute -
r50305:2bbd7bc7 default
parent child Browse files
Show More
@@ -1,7955 +1,7975 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2007 Olivia Mackall <olivia@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
8
9 import os
9 import os
10 import re
10 import re
11 import sys
11 import sys
12
12
13 from .i18n import _
13 from .i18n import _
14 from .node import (
14 from .node import (
15 hex,
15 hex,
16 nullrev,
16 nullrev,
17 short,
17 short,
18 wdirrev,
18 wdirrev,
19 )
19 )
20 from .pycompat import open
20 from .pycompat import open
21 from . import (
21 from . import (
22 archival,
22 archival,
23 bookmarks,
23 bookmarks,
24 bundle2,
24 bundle2,
25 bundlecaches,
25 bundlecaches,
26 changegroup,
26 changegroup,
27 cmdutil,
27 cmdutil,
28 copies,
28 copies,
29 debugcommands as debugcommandsmod,
29 debugcommands as debugcommandsmod,
30 destutil,
30 destutil,
31 dirstateguard,
31 dirstateguard,
32 discovery,
32 discovery,
33 encoding,
33 encoding,
34 error,
34 error,
35 exchange,
35 exchange,
36 extensions,
36 extensions,
37 filemerge,
37 filemerge,
38 formatter,
38 formatter,
39 graphmod,
39 graphmod,
40 grep as grepmod,
40 grep as grepmod,
41 hbisect,
41 hbisect,
42 help,
42 help,
43 hg,
43 hg,
44 logcmdutil,
44 logcmdutil,
45 merge as mergemod,
45 merge as mergemod,
46 mergestate as mergestatemod,
46 mergestate as mergestatemod,
47 narrowspec,
47 narrowspec,
48 obsolete,
48 obsolete,
49 obsutil,
49 obsutil,
50 patch,
50 patch,
51 phases,
51 phases,
52 pycompat,
52 pycompat,
53 rcutil,
53 rcutil,
54 registrar,
54 registrar,
55 requirements,
55 requirements,
56 revsetlang,
56 revsetlang,
57 rewriteutil,
57 rewriteutil,
58 scmutil,
58 scmutil,
59 server,
59 server,
60 shelve as shelvemod,
60 shelve as shelvemod,
61 state as statemod,
61 state as statemod,
62 streamclone,
62 streamclone,
63 tags as tagsmod,
63 tags as tagsmod,
64 ui as uimod,
64 ui as uimod,
65 util,
65 util,
66 verify as verifymod,
66 verify as verifymod,
67 vfs as vfsmod,
67 vfs as vfsmod,
68 wireprotoserver,
68 wireprotoserver,
69 )
69 )
70 from .utils import (
70 from .utils import (
71 dateutil,
71 dateutil,
72 stringutil,
72 stringutil,
73 urlutil,
73 urlutil,
74 )
74 )
75
75
76 table = {}
76 table = {}
77 table.update(debugcommandsmod.command._table)
77 table.update(debugcommandsmod.command._table)
78
78
79 command = registrar.command(table)
79 command = registrar.command(table)
80 INTENT_READONLY = registrar.INTENT_READONLY
80 INTENT_READONLY = registrar.INTENT_READONLY
81
81
82 # common command options
82 # common command options
83
83
84 globalopts = [
84 globalopts = [
85 (
85 (
86 b'R',
86 b'R',
87 b'repository',
87 b'repository',
88 b'',
88 b'',
89 _(b'repository root directory or name of overlay bundle file'),
89 _(b'repository root directory or name of overlay bundle file'),
90 _(b'REPO'),
90 _(b'REPO'),
91 ),
91 ),
92 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
92 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
93 (
93 (
94 b'y',
94 b'y',
95 b'noninteractive',
95 b'noninteractive',
96 None,
96 None,
97 _(
97 _(
98 b'do not prompt, automatically pick the first choice for all prompts'
98 b'do not prompt, automatically pick the first choice for all prompts'
99 ),
99 ),
100 ),
100 ),
101 (b'q', b'quiet', None, _(b'suppress output')),
101 (b'q', b'quiet', None, _(b'suppress output')),
102 (b'v', b'verbose', None, _(b'enable additional output')),
102 (b'v', b'verbose', None, _(b'enable additional output')),
103 (
103 (
104 b'',
104 b'',
105 b'color',
105 b'color',
106 b'',
106 b'',
107 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
107 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
108 # and should not be translated
108 # and should not be translated
109 _(b"when to colorize (boolean, always, auto, never, or debug)"),
109 _(b"when to colorize (boolean, always, auto, never, or debug)"),
110 _(b'TYPE'),
110 _(b'TYPE'),
111 ),
111 ),
112 (
112 (
113 b'',
113 b'',
114 b'config',
114 b'config',
115 [],
115 [],
116 _(b'set/override config option (use \'section.name=value\')'),
116 _(b'set/override config option (use \'section.name=value\')'),
117 _(b'CONFIG'),
117 _(b'CONFIG'),
118 ),
118 ),
119 (b'', b'debug', None, _(b'enable debugging output')),
119 (b'', b'debug', None, _(b'enable debugging output')),
120 (b'', b'debugger', None, _(b'start debugger')),
120 (b'', b'debugger', None, _(b'start debugger')),
121 (
121 (
122 b'',
122 b'',
123 b'encoding',
123 b'encoding',
124 encoding.encoding,
124 encoding.encoding,
125 _(b'set the charset encoding'),
125 _(b'set the charset encoding'),
126 _(b'ENCODE'),
126 _(b'ENCODE'),
127 ),
127 ),
128 (
128 (
129 b'',
129 b'',
130 b'encodingmode',
130 b'encodingmode',
131 encoding.encodingmode,
131 encoding.encodingmode,
132 _(b'set the charset encoding mode'),
132 _(b'set the charset encoding mode'),
133 _(b'MODE'),
133 _(b'MODE'),
134 ),
134 ),
135 (b'', b'traceback', None, _(b'always print a traceback on exception')),
135 (b'', b'traceback', None, _(b'always print a traceback on exception')),
136 (b'', b'time', None, _(b'time how long the command takes')),
136 (b'', b'time', None, _(b'time how long the command takes')),
137 (b'', b'profile', None, _(b'print command execution profile')),
137 (b'', b'profile', None, _(b'print command execution profile')),
138 (b'', b'version', None, _(b'output version information and exit')),
138 (b'', b'version', None, _(b'output version information and exit')),
139 (b'h', b'help', None, _(b'display help and exit')),
139 (b'h', b'help', None, _(b'display help and exit')),
140 (b'', b'hidden', False, _(b'consider hidden changesets')),
140 (b'', b'hidden', False, _(b'consider hidden changesets')),
141 (
141 (
142 b'',
142 b'',
143 b'pager',
143 b'pager',
144 b'auto',
144 b'auto',
145 _(b"when to paginate (boolean, always, auto, or never)"),
145 _(b"when to paginate (boolean, always, auto, or never)"),
146 _(b'TYPE'),
146 _(b'TYPE'),
147 ),
147 ),
148 ]
148 ]
149
149
150 dryrunopts = cmdutil.dryrunopts
150 dryrunopts = cmdutil.dryrunopts
151 remoteopts = cmdutil.remoteopts
151 remoteopts = cmdutil.remoteopts
152 walkopts = cmdutil.walkopts
152 walkopts = cmdutil.walkopts
153 commitopts = cmdutil.commitopts
153 commitopts = cmdutil.commitopts
154 commitopts2 = cmdutil.commitopts2
154 commitopts2 = cmdutil.commitopts2
155 commitopts3 = cmdutil.commitopts3
155 commitopts3 = cmdutil.commitopts3
156 formatteropts = cmdutil.formatteropts
156 formatteropts = cmdutil.formatteropts
157 templateopts = cmdutil.templateopts
157 templateopts = cmdutil.templateopts
158 logopts = cmdutil.logopts
158 logopts = cmdutil.logopts
159 diffopts = cmdutil.diffopts
159 diffopts = cmdutil.diffopts
160 diffwsopts = cmdutil.diffwsopts
160 diffwsopts = cmdutil.diffwsopts
161 diffopts2 = cmdutil.diffopts2
161 diffopts2 = cmdutil.diffopts2
162 mergetoolopts = cmdutil.mergetoolopts
162 mergetoolopts = cmdutil.mergetoolopts
163 similarityopts = cmdutil.similarityopts
163 similarityopts = cmdutil.similarityopts
164 subrepoopts = cmdutil.subrepoopts
164 subrepoopts = cmdutil.subrepoopts
165 debugrevlogopts = cmdutil.debugrevlogopts
165 debugrevlogopts = cmdutil.debugrevlogopts
166
166
167 # Commands start here, listed alphabetically
167 # Commands start here, listed alphabetically
168
168
169
169
170 @command(
170 @command(
171 b'abort',
171 b'abort',
172 dryrunopts,
172 dryrunopts,
173 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
173 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
174 helpbasic=True,
174 helpbasic=True,
175 )
175 )
176 def abort(ui, repo, **opts):
176 def abort(ui, repo, **opts):
177 """abort an unfinished operation (EXPERIMENTAL)
177 """abort an unfinished operation (EXPERIMENTAL)
178
178
179 Aborts a multistep operation like graft, histedit, rebase, merge,
179 Aborts a multistep operation like graft, histedit, rebase, merge,
180 and unshelve if they are in an unfinished state.
180 and unshelve if they are in an unfinished state.
181
181
182 use --dry-run/-n to dry run the command.
182 use --dry-run/-n to dry run the command.
183 """
183 """
184 dryrun = opts.get('dry_run')
184 dryrun = opts.get('dry_run')
185 abortstate = cmdutil.getunfinishedstate(repo)
185 abortstate = cmdutil.getunfinishedstate(repo)
186 if not abortstate:
186 if not abortstate:
187 raise error.StateError(_(b'no operation in progress'))
187 raise error.StateError(_(b'no operation in progress'))
188 if not abortstate.abortfunc:
188 if not abortstate.abortfunc:
189 raise error.InputError(
189 raise error.InputError(
190 (
190 (
191 _(b"%s in progress but does not support 'hg abort'")
191 _(b"%s in progress but does not support 'hg abort'")
192 % (abortstate._opname)
192 % (abortstate._opname)
193 ),
193 ),
194 hint=abortstate.hint(),
194 hint=abortstate.hint(),
195 )
195 )
196 if dryrun:
196 if dryrun:
197 ui.status(
197 ui.status(
198 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
198 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
199 )
199 )
200 return
200 return
201 return abortstate.abortfunc(ui, repo)
201 return abortstate.abortfunc(ui, repo)
202
202
203
203
204 @command(
204 @command(
205 b'add',
205 b'add',
206 walkopts + subrepoopts + dryrunopts,
206 walkopts + subrepoopts + dryrunopts,
207 _(b'[OPTION]... [FILE]...'),
207 _(b'[OPTION]... [FILE]...'),
208 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
208 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
209 helpbasic=True,
209 helpbasic=True,
210 inferrepo=True,
210 inferrepo=True,
211 )
211 )
212 def add(ui, repo, *pats, **opts):
212 def add(ui, repo, *pats, **opts):
213 """add the specified files on the next commit
213 """add the specified files on the next commit
214
214
215 Schedule files to be version controlled and added to the
215 Schedule files to be version controlled and added to the
216 repository.
216 repository.
217
217
218 The files will be added to the repository at the next commit. To
218 The files will be added to the repository at the next commit. To
219 undo an add before that, see :hg:`forget`.
219 undo an add before that, see :hg:`forget`.
220
220
221 If no names are given, add all files to the repository (except
221 If no names are given, add all files to the repository (except
222 files matching ``.hgignore``).
222 files matching ``.hgignore``).
223
223
224 .. container:: verbose
224 .. container:: verbose
225
225
226 Examples:
226 Examples:
227
227
228 - New (unknown) files are added
228 - New (unknown) files are added
229 automatically by :hg:`add`::
229 automatically by :hg:`add`::
230
230
231 $ ls
231 $ ls
232 foo.c
232 foo.c
233 $ hg status
233 $ hg status
234 ? foo.c
234 ? foo.c
235 $ hg add
235 $ hg add
236 adding foo.c
236 adding foo.c
237 $ hg status
237 $ hg status
238 A foo.c
238 A foo.c
239
239
240 - Specific files to be added can be specified::
240 - Specific files to be added can be specified::
241
241
242 $ ls
242 $ ls
243 bar.c foo.c
243 bar.c foo.c
244 $ hg status
244 $ hg status
245 ? bar.c
245 ? bar.c
246 ? foo.c
246 ? foo.c
247 $ hg add bar.c
247 $ hg add bar.c
248 $ hg status
248 $ hg status
249 A bar.c
249 A bar.c
250 ? foo.c
250 ? foo.c
251
251
252 Returns 0 if all files are successfully added.
252 Returns 0 if all files are successfully added.
253 """
253 """
254
254
255 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
255 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
256 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
256 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
257 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
257 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
258 return rejected and 1 or 0
258 return rejected and 1 or 0
259
259
260
260
261 @command(
261 @command(
262 b'addremove',
262 b'addremove',
263 similarityopts + subrepoopts + walkopts + dryrunopts,
263 similarityopts + subrepoopts + walkopts + dryrunopts,
264 _(b'[OPTION]... [FILE]...'),
264 _(b'[OPTION]... [FILE]...'),
265 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
265 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
266 inferrepo=True,
266 inferrepo=True,
267 )
267 )
268 def addremove(ui, repo, *pats, **opts):
268 def addremove(ui, repo, *pats, **opts):
269 """add all new files, delete all missing files
269 """add all new files, delete all missing files
270
270
271 Add all new files and remove all missing files from the
271 Add all new files and remove all missing files from the
272 repository.
272 repository.
273
273
274 Unless names are given, new files are ignored if they match any of
274 Unless names are given, new files are ignored if they match any of
275 the patterns in ``.hgignore``. As with add, these changes take
275 the patterns in ``.hgignore``. As with add, these changes take
276 effect at the next commit.
276 effect at the next commit.
277
277
278 Use the -s/--similarity option to detect renamed files. This
278 Use the -s/--similarity option to detect renamed files. This
279 option takes a percentage between 0 (disabled) and 100 (files must
279 option takes a percentage between 0 (disabled) and 100 (files must
280 be identical) as its parameter. With a parameter greater than 0,
280 be identical) as its parameter. With a parameter greater than 0,
281 this compares every removed file with every added file and records
281 this compares every removed file with every added file and records
282 those similar enough as renames. Detecting renamed files this way
282 those similar enough as renames. Detecting renamed files this way
283 can be expensive. After using this option, :hg:`status -C` can be
283 can be expensive. After using this option, :hg:`status -C` can be
284 used to check which files were identified as moved or renamed. If
284 used to check which files were identified as moved or renamed. If
285 not specified, -s/--similarity defaults to 100 and only renames of
285 not specified, -s/--similarity defaults to 100 and only renames of
286 identical files are detected.
286 identical files are detected.
287
287
288 .. container:: verbose
288 .. container:: verbose
289
289
290 Examples:
290 Examples:
291
291
292 - A number of files (bar.c and foo.c) are new,
292 - A number of files (bar.c and foo.c) are new,
293 while foobar.c has been removed (without using :hg:`remove`)
293 while foobar.c has been removed (without using :hg:`remove`)
294 from the repository::
294 from the repository::
295
295
296 $ ls
296 $ ls
297 bar.c foo.c
297 bar.c foo.c
298 $ hg status
298 $ hg status
299 ! foobar.c
299 ! foobar.c
300 ? bar.c
300 ? bar.c
301 ? foo.c
301 ? foo.c
302 $ hg addremove
302 $ hg addremove
303 adding bar.c
303 adding bar.c
304 adding foo.c
304 adding foo.c
305 removing foobar.c
305 removing foobar.c
306 $ hg status
306 $ hg status
307 A bar.c
307 A bar.c
308 A foo.c
308 A foo.c
309 R foobar.c
309 R foobar.c
310
310
311 - A file foobar.c was moved to foo.c without using :hg:`rename`.
311 - A file foobar.c was moved to foo.c without using :hg:`rename`.
312 Afterwards, it was edited slightly::
312 Afterwards, it was edited slightly::
313
313
314 $ ls
314 $ ls
315 foo.c
315 foo.c
316 $ hg status
316 $ hg status
317 ! foobar.c
317 ! foobar.c
318 ? foo.c
318 ? foo.c
319 $ hg addremove --similarity 90
319 $ hg addremove --similarity 90
320 removing foobar.c
320 removing foobar.c
321 adding foo.c
321 adding foo.c
322 recording removal of foobar.c as rename to foo.c (94% similar)
322 recording removal of foobar.c as rename to foo.c (94% similar)
323 $ hg status -C
323 $ hg status -C
324 A foo.c
324 A foo.c
325 foobar.c
325 foobar.c
326 R foobar.c
326 R foobar.c
327
327
328 Returns 0 if all files are successfully added.
328 Returns 0 if all files are successfully added.
329 """
329 """
330 opts = pycompat.byteskwargs(opts)
330 opts = pycompat.byteskwargs(opts)
331 if not opts.get(b'similarity'):
331 if not opts.get(b'similarity'):
332 opts[b'similarity'] = b'100'
332 opts[b'similarity'] = b'100'
333 matcher = scmutil.match(repo[None], pats, opts)
333 matcher = scmutil.match(repo[None], pats, opts)
334 relative = scmutil.anypats(pats, opts)
334 relative = scmutil.anypats(pats, opts)
335 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
335 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
336 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
336 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
337
337
338
338
339 @command(
339 @command(
340 b'annotate|blame',
340 b'annotate|blame',
341 [
341 [
342 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
342 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
343 (
343 (
344 b'',
344 b'',
345 b'follow',
345 b'follow',
346 None,
346 None,
347 _(b'follow copies/renames and list the filename (DEPRECATED)'),
347 _(b'follow copies/renames and list the filename (DEPRECATED)'),
348 ),
348 ),
349 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
349 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
350 (b'a', b'text', None, _(b'treat all files as text')),
350 (b'a', b'text', None, _(b'treat all files as text')),
351 (b'u', b'user', None, _(b'list the author (long with -v)')),
351 (b'u', b'user', None, _(b'list the author (long with -v)')),
352 (b'f', b'file', None, _(b'list the filename')),
352 (b'f', b'file', None, _(b'list the filename')),
353 (b'd', b'date', None, _(b'list the date (short with -q)')),
353 (b'd', b'date', None, _(b'list the date (short with -q)')),
354 (b'n', b'number', None, _(b'list the revision number (default)')),
354 (b'n', b'number', None, _(b'list the revision number (default)')),
355 (b'c', b'changeset', None, _(b'list the changeset')),
355 (b'c', b'changeset', None, _(b'list the changeset')),
356 (
356 (
357 b'l',
357 b'l',
358 b'line-number',
358 b'line-number',
359 None,
359 None,
360 _(b'show line number at the first appearance'),
360 _(b'show line number at the first appearance'),
361 ),
361 ),
362 (
362 (
363 b'',
363 b'',
364 b'skip',
364 b'skip',
365 [],
365 [],
366 _(b'revset to not display (EXPERIMENTAL)'),
366 _(b'revset to not display (EXPERIMENTAL)'),
367 _(b'REV'),
367 _(b'REV'),
368 ),
368 ),
369 ]
369 ]
370 + diffwsopts
370 + diffwsopts
371 + walkopts
371 + walkopts
372 + formatteropts,
372 + formatteropts,
373 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
373 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
374 helpcategory=command.CATEGORY_FILE_CONTENTS,
374 helpcategory=command.CATEGORY_FILE_CONTENTS,
375 helpbasic=True,
375 helpbasic=True,
376 inferrepo=True,
376 inferrepo=True,
377 )
377 )
378 def annotate(ui, repo, *pats, **opts):
378 def annotate(ui, repo, *pats, **opts):
379 """show changeset information by line for each file
379 """show changeset information by line for each file
380
380
381 List changes in files, showing the revision id responsible for
381 List changes in files, showing the revision id responsible for
382 each line.
382 each line.
383
383
384 This command is useful for discovering when a change was made and
384 This command is useful for discovering when a change was made and
385 by whom.
385 by whom.
386
386
387 If you include --file, --user, or --date, the revision number is
387 If you include --file, --user, or --date, the revision number is
388 suppressed unless you also include --number.
388 suppressed unless you also include --number.
389
389
390 Without the -a/--text option, annotate will avoid processing files
390 Without the -a/--text option, annotate will avoid processing files
391 it detects as binary. With -a, annotate will annotate the file
391 it detects as binary. With -a, annotate will annotate the file
392 anyway, although the results will probably be neither useful
392 anyway, although the results will probably be neither useful
393 nor desirable.
393 nor desirable.
394
394
395 .. container:: verbose
395 .. container:: verbose
396
396
397 Template:
397 Template:
398
398
399 The following keywords are supported in addition to the common template
399 The following keywords are supported in addition to the common template
400 keywords and functions. See also :hg:`help templates`.
400 keywords and functions. See also :hg:`help templates`.
401
401
402 :lines: List of lines with annotation data.
402 :lines: List of lines with annotation data.
403 :path: String. Repository-absolute path of the specified file.
403 :path: String. Repository-absolute path of the specified file.
404
404
405 And each entry of ``{lines}`` provides the following sub-keywords in
405 And each entry of ``{lines}`` provides the following sub-keywords in
406 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
406 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
407
407
408 :line: String. Line content.
408 :line: String. Line content.
409 :lineno: Integer. Line number at that revision.
409 :lineno: Integer. Line number at that revision.
410 :path: String. Repository-absolute path of the file at that revision.
410 :path: String. Repository-absolute path of the file at that revision.
411
411
412 See :hg:`help templates.operators` for the list expansion syntax.
412 See :hg:`help templates.operators` for the list expansion syntax.
413
413
414 Returns 0 on success.
414 Returns 0 on success.
415 """
415 """
416 opts = pycompat.byteskwargs(opts)
416 opts = pycompat.byteskwargs(opts)
417 if not pats:
417 if not pats:
418 raise error.InputError(
418 raise error.InputError(
419 _(b'at least one filename or pattern is required')
419 _(b'at least one filename or pattern is required')
420 )
420 )
421
421
422 if opts.get(b'follow'):
422 if opts.get(b'follow'):
423 # --follow is deprecated and now just an alias for -f/--file
423 # --follow is deprecated and now just an alias for -f/--file
424 # to mimic the behavior of Mercurial before version 1.5
424 # to mimic the behavior of Mercurial before version 1.5
425 opts[b'file'] = True
425 opts[b'file'] = True
426
426
427 if (
427 if (
428 not opts.get(b'user')
428 not opts.get(b'user')
429 and not opts.get(b'changeset')
429 and not opts.get(b'changeset')
430 and not opts.get(b'date')
430 and not opts.get(b'date')
431 and not opts.get(b'file')
431 and not opts.get(b'file')
432 ):
432 ):
433 opts[b'number'] = True
433 opts[b'number'] = True
434
434
435 linenumber = opts.get(b'line_number') is not None
435 linenumber = opts.get(b'line_number') is not None
436 if (
436 if (
437 linenumber
437 linenumber
438 and (not opts.get(b'changeset'))
438 and (not opts.get(b'changeset'))
439 and (not opts.get(b'number'))
439 and (not opts.get(b'number'))
440 ):
440 ):
441 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
441 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
442
442
443 rev = opts.get(b'rev')
443 rev = opts.get(b'rev')
444 if rev:
444 if rev:
445 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
445 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
446 ctx = logcmdutil.revsingle(repo, rev)
446 ctx = logcmdutil.revsingle(repo, rev)
447
447
448 ui.pager(b'annotate')
448 ui.pager(b'annotate')
449 rootfm = ui.formatter(b'annotate', opts)
449 rootfm = ui.formatter(b'annotate', opts)
450 if ui.debugflag:
450 if ui.debugflag:
451 shorthex = pycompat.identity
451 shorthex = pycompat.identity
452 else:
452 else:
453
453
454 def shorthex(h):
454 def shorthex(h):
455 return h[:12]
455 return h[:12]
456
456
457 if ui.quiet:
457 if ui.quiet:
458 datefunc = dateutil.shortdate
458 datefunc = dateutil.shortdate
459 else:
459 else:
460 datefunc = dateutil.datestr
460 datefunc = dateutil.datestr
461 if ctx.rev() is None:
461 if ctx.rev() is None:
462 if opts.get(b'changeset'):
462 if opts.get(b'changeset'):
463 # omit "+" suffix which is appended to node hex
463 # omit "+" suffix which is appended to node hex
464 def formatrev(rev):
464 def formatrev(rev):
465 if rev == wdirrev:
465 if rev == wdirrev:
466 return b'%d' % ctx.p1().rev()
466 return b'%d' % ctx.p1().rev()
467 else:
467 else:
468 return b'%d' % rev
468 return b'%d' % rev
469
469
470 else:
470 else:
471
471
472 def formatrev(rev):
472 def formatrev(rev):
473 if rev == wdirrev:
473 if rev == wdirrev:
474 return b'%d+' % ctx.p1().rev()
474 return b'%d+' % ctx.p1().rev()
475 else:
475 else:
476 return b'%d ' % rev
476 return b'%d ' % rev
477
477
478 def formathex(h):
478 def formathex(h):
479 if h == repo.nodeconstants.wdirhex:
479 if h == repo.nodeconstants.wdirhex:
480 return b'%s+' % shorthex(hex(ctx.p1().node()))
480 return b'%s+' % shorthex(hex(ctx.p1().node()))
481 else:
481 else:
482 return b'%s ' % shorthex(h)
482 return b'%s ' % shorthex(h)
483
483
484 else:
484 else:
485 formatrev = b'%d'.__mod__
485 formatrev = b'%d'.__mod__
486 formathex = shorthex
486 formathex = shorthex
487
487
488 opmap = [
488 opmap = [
489 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
489 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
490 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
490 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
491 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
491 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
492 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
492 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
493 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
493 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
494 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
494 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
495 ]
495 ]
496 opnamemap = {
496 opnamemap = {
497 b'rev': b'number',
497 b'rev': b'number',
498 b'node': b'changeset',
498 b'node': b'changeset',
499 b'path': b'file',
499 b'path': b'file',
500 b'lineno': b'line_number',
500 b'lineno': b'line_number',
501 }
501 }
502
502
503 if rootfm.isplain():
503 if rootfm.isplain():
504
504
505 def makefunc(get, fmt):
505 def makefunc(get, fmt):
506 return lambda x: fmt(get(x))
506 return lambda x: fmt(get(x))
507
507
508 else:
508 else:
509
509
510 def makefunc(get, fmt):
510 def makefunc(get, fmt):
511 return get
511 return get
512
512
513 datahint = rootfm.datahint()
513 datahint = rootfm.datahint()
514 funcmap = [
514 funcmap = [
515 (makefunc(get, fmt), sep)
515 (makefunc(get, fmt), sep)
516 for fn, sep, get, fmt in opmap
516 for fn, sep, get, fmt in opmap
517 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
517 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
518 ]
518 ]
519 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
519 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
520 fields = b' '.join(
520 fields = b' '.join(
521 fn
521 fn
522 for fn, sep, get, fmt in opmap
522 for fn, sep, get, fmt in opmap
523 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
523 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
524 )
524 )
525
525
526 def bad(x, y):
526 def bad(x, y):
527 raise error.InputError(b"%s: %s" % (x, y))
527 raise error.InputError(b"%s: %s" % (x, y))
528
528
529 m = scmutil.match(ctx, pats, opts, badfn=bad)
529 m = scmutil.match(ctx, pats, opts, badfn=bad)
530
530
531 follow = not opts.get(b'no_follow')
531 follow = not opts.get(b'no_follow')
532 diffopts = patch.difffeatureopts(
532 diffopts = patch.difffeatureopts(
533 ui, opts, section=b'annotate', whitespace=True
533 ui, opts, section=b'annotate', whitespace=True
534 )
534 )
535 skiprevs = opts.get(b'skip')
535 skiprevs = opts.get(b'skip')
536 if skiprevs:
536 if skiprevs:
537 skiprevs = logcmdutil.revrange(repo, skiprevs)
537 skiprevs = logcmdutil.revrange(repo, skiprevs)
538
538
539 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
539 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
540 for abs in ctx.walk(m):
540 for abs in ctx.walk(m):
541 fctx = ctx[abs]
541 fctx = ctx[abs]
542 rootfm.startitem()
542 rootfm.startitem()
543 rootfm.data(path=abs)
543 rootfm.data(path=abs)
544 if not opts.get(b'text') and fctx.isbinary():
544 if not opts.get(b'text') and fctx.isbinary():
545 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
545 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
546 continue
546 continue
547
547
548 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
548 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
549 lines = fctx.annotate(
549 lines = fctx.annotate(
550 follow=follow, skiprevs=skiprevs, diffopts=diffopts
550 follow=follow, skiprevs=skiprevs, diffopts=diffopts
551 )
551 )
552 if not lines:
552 if not lines:
553 fm.end()
553 fm.end()
554 continue
554 continue
555 formats = []
555 formats = []
556 pieces = []
556 pieces = []
557
557
558 for f, sep in funcmap:
558 for f, sep in funcmap:
559 l = [f(n) for n in lines]
559 l = [f(n) for n in lines]
560 if fm.isplain():
560 if fm.isplain():
561 sizes = [encoding.colwidth(x) for x in l]
561 sizes = [encoding.colwidth(x) for x in l]
562 ml = max(sizes)
562 ml = max(sizes)
563 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
563 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
564 else:
564 else:
565 formats.append([b'%s'] * len(l))
565 formats.append([b'%s'] * len(l))
566 pieces.append(l)
566 pieces.append(l)
567
567
568 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
568 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
569 fm.startitem()
569 fm.startitem()
570 fm.context(fctx=n.fctx)
570 fm.context(fctx=n.fctx)
571 fm.write(fields, b"".join(f), *p)
571 fm.write(fields, b"".join(f), *p)
572 if n.skip:
572 if n.skip:
573 fmt = b"* %s"
573 fmt = b"* %s"
574 else:
574 else:
575 fmt = b": %s"
575 fmt = b": %s"
576 fm.write(b'line', fmt, n.text)
576 fm.write(b'line', fmt, n.text)
577
577
578 if not lines[-1].text.endswith(b'\n'):
578 if not lines[-1].text.endswith(b'\n'):
579 fm.plain(b'\n')
579 fm.plain(b'\n')
580 fm.end()
580 fm.end()
581
581
582 rootfm.end()
582 rootfm.end()
583
583
584
584
585 @command(
585 @command(
586 b'archive',
586 b'archive',
587 [
587 [
588 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
588 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
589 (
589 (
590 b'p',
590 b'p',
591 b'prefix',
591 b'prefix',
592 b'',
592 b'',
593 _(b'directory prefix for files in archive'),
593 _(b'directory prefix for files in archive'),
594 _(b'PREFIX'),
594 _(b'PREFIX'),
595 ),
595 ),
596 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
596 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
597 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
597 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
598 ]
598 ]
599 + subrepoopts
599 + subrepoopts
600 + walkopts,
600 + walkopts,
601 _(b'[OPTION]... DEST'),
601 _(b'[OPTION]... DEST'),
602 helpcategory=command.CATEGORY_IMPORT_EXPORT,
602 helpcategory=command.CATEGORY_IMPORT_EXPORT,
603 )
603 )
604 def archive(ui, repo, dest, **opts):
604 def archive(ui, repo, dest, **opts):
605 """create an unversioned archive of a repository revision
605 """create an unversioned archive of a repository revision
606
606
607 By default, the revision used is the parent of the working
607 By default, the revision used is the parent of the working
608 directory; use -r/--rev to specify a different revision.
608 directory; use -r/--rev to specify a different revision.
609
609
610 The archive type is automatically detected based on file
610 The archive type is automatically detected based on file
611 extension (to override, use -t/--type).
611 extension (to override, use -t/--type).
612
612
613 .. container:: verbose
613 .. container:: verbose
614
614
615 Examples:
615 Examples:
616
616
617 - create a zip file containing the 1.0 release::
617 - create a zip file containing the 1.0 release::
618
618
619 hg archive -r 1.0 project-1.0.zip
619 hg archive -r 1.0 project-1.0.zip
620
620
621 - create a tarball excluding .hg files::
621 - create a tarball excluding .hg files::
622
622
623 hg archive project.tar.gz -X ".hg*"
623 hg archive project.tar.gz -X ".hg*"
624
624
625 Valid types are:
625 Valid types are:
626
626
627 :``files``: a directory full of files (default)
627 :``files``: a directory full of files (default)
628 :``tar``: tar archive, uncompressed
628 :``tar``: tar archive, uncompressed
629 :``tbz2``: tar archive, compressed using bzip2
629 :``tbz2``: tar archive, compressed using bzip2
630 :``tgz``: tar archive, compressed using gzip
630 :``tgz``: tar archive, compressed using gzip
631 :``txz``: tar archive, compressed using lzma (only in Python 3)
631 :``txz``: tar archive, compressed using lzma (only in Python 3)
632 :``uzip``: zip archive, uncompressed
632 :``uzip``: zip archive, uncompressed
633 :``zip``: zip archive, compressed using deflate
633 :``zip``: zip archive, compressed using deflate
634
634
635 The exact name of the destination archive or directory is given
635 The exact name of the destination archive or directory is given
636 using a format string; see :hg:`help export` for details.
636 using a format string; see :hg:`help export` for details.
637
637
638 Each member added to an archive file has a directory prefix
638 Each member added to an archive file has a directory prefix
639 prepended. Use -p/--prefix to specify a format string for the
639 prepended. Use -p/--prefix to specify a format string for the
640 prefix. The default is the basename of the archive, with suffixes
640 prefix. The default is the basename of the archive, with suffixes
641 removed.
641 removed.
642
642
643 Returns 0 on success.
643 Returns 0 on success.
644 """
644 """
645
645
646 opts = pycompat.byteskwargs(opts)
646 opts = pycompat.byteskwargs(opts)
647 rev = opts.get(b'rev')
647 rev = opts.get(b'rev')
648 if rev:
648 if rev:
649 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
649 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
650 ctx = logcmdutil.revsingle(repo, rev)
650 ctx = logcmdutil.revsingle(repo, rev)
651 if not ctx:
651 if not ctx:
652 raise error.InputError(
652 raise error.InputError(
653 _(b'no working directory: please specify a revision')
653 _(b'no working directory: please specify a revision')
654 )
654 )
655 node = ctx.node()
655 node = ctx.node()
656 dest = cmdutil.makefilename(ctx, dest)
656 dest = cmdutil.makefilename(ctx, dest)
657 if os.path.realpath(dest) == repo.root:
657 if os.path.realpath(dest) == repo.root:
658 raise error.InputError(_(b'repository root cannot be destination'))
658 raise error.InputError(_(b'repository root cannot be destination'))
659
659
660 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
660 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
661 prefix = opts.get(b'prefix')
661 prefix = opts.get(b'prefix')
662
662
663 if dest == b'-':
663 if dest == b'-':
664 if kind == b'files':
664 if kind == b'files':
665 raise error.InputError(_(b'cannot archive plain files to stdout'))
665 raise error.InputError(_(b'cannot archive plain files to stdout'))
666 dest = cmdutil.makefileobj(ctx, dest)
666 dest = cmdutil.makefileobj(ctx, dest)
667 if not prefix:
667 if not prefix:
668 prefix = os.path.basename(repo.root) + b'-%h'
668 prefix = os.path.basename(repo.root) + b'-%h'
669
669
670 prefix = cmdutil.makefilename(ctx, prefix)
670 prefix = cmdutil.makefilename(ctx, prefix)
671 match = scmutil.match(ctx, [], opts)
671 match = scmutil.match(ctx, [], opts)
672 archival.archive(
672 archival.archive(
673 repo,
673 repo,
674 dest,
674 dest,
675 node,
675 node,
676 kind,
676 kind,
677 not opts.get(b'no_decode'),
677 not opts.get(b'no_decode'),
678 match,
678 match,
679 prefix,
679 prefix,
680 subrepos=opts.get(b'subrepos'),
680 subrepos=opts.get(b'subrepos'),
681 )
681 )
682
682
683
683
684 @command(
684 @command(
685 b'backout',
685 b'backout',
686 [
686 [
687 (
687 (
688 b'',
688 b'',
689 b'merge',
689 b'merge',
690 None,
690 None,
691 _(b'merge with old dirstate parent after backout'),
691 _(b'merge with old dirstate parent after backout'),
692 ),
692 ),
693 (
693 (
694 b'',
694 b'',
695 b'commit',
695 b'commit',
696 None,
696 None,
697 _(b'commit if no conflicts were encountered (DEPRECATED)'),
697 _(b'commit if no conflicts were encountered (DEPRECATED)'),
698 ),
698 ),
699 (b'', b'no-commit', None, _(b'do not commit')),
699 (b'', b'no-commit', None, _(b'do not commit')),
700 (
700 (
701 b'',
701 b'',
702 b'parent',
702 b'parent',
703 b'',
703 b'',
704 _(b'parent to choose when backing out merge (DEPRECATED)'),
704 _(b'parent to choose when backing out merge (DEPRECATED)'),
705 _(b'REV'),
705 _(b'REV'),
706 ),
706 ),
707 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
707 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
708 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
708 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
709 ]
709 ]
710 + mergetoolopts
710 + mergetoolopts
711 + walkopts
711 + walkopts
712 + commitopts
712 + commitopts
713 + commitopts2,
713 + commitopts2,
714 _(b'[OPTION]... [-r] REV'),
714 _(b'[OPTION]... [-r] REV'),
715 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
715 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
716 )
716 )
717 def backout(ui, repo, node=None, rev=None, **opts):
717 def backout(ui, repo, node=None, rev=None, **opts):
718 """reverse effect of earlier changeset
718 """reverse effect of earlier changeset
719
719
720 Prepare a new changeset with the effect of REV undone in the
720 Prepare a new changeset with the effect of REV undone in the
721 current working directory. If no conflicts were encountered,
721 current working directory. If no conflicts were encountered,
722 it will be committed immediately.
722 it will be committed immediately.
723
723
724 If REV is the parent of the working directory, then this new changeset
724 If REV is the parent of the working directory, then this new changeset
725 is committed automatically (unless --no-commit is specified).
725 is committed automatically (unless --no-commit is specified).
726
726
727 .. note::
727 .. note::
728
728
729 :hg:`backout` cannot be used to fix either an unwanted or
729 :hg:`backout` cannot be used to fix either an unwanted or
730 incorrect merge.
730 incorrect merge.
731
731
732 .. container:: verbose
732 .. container:: verbose
733
733
734 Examples:
734 Examples:
735
735
736 - Reverse the effect of the parent of the working directory.
736 - Reverse the effect of the parent of the working directory.
737 This backout will be committed immediately::
737 This backout will be committed immediately::
738
738
739 hg backout -r .
739 hg backout -r .
740
740
741 - Reverse the effect of previous bad revision 23::
741 - Reverse the effect of previous bad revision 23::
742
742
743 hg backout -r 23
743 hg backout -r 23
744
744
745 - Reverse the effect of previous bad revision 23 and
745 - Reverse the effect of previous bad revision 23 and
746 leave changes uncommitted::
746 leave changes uncommitted::
747
747
748 hg backout -r 23 --no-commit
748 hg backout -r 23 --no-commit
749 hg commit -m "Backout revision 23"
749 hg commit -m "Backout revision 23"
750
750
751 By default, the pending changeset will have one parent,
751 By default, the pending changeset will have one parent,
752 maintaining a linear history. With --merge, the pending
752 maintaining a linear history. With --merge, the pending
753 changeset will instead have two parents: the old parent of the
753 changeset will instead have two parents: the old parent of the
754 working directory and a new child of REV that simply undoes REV.
754 working directory and a new child of REV that simply undoes REV.
755
755
756 Before version 1.7, the behavior without --merge was equivalent
756 Before version 1.7, the behavior without --merge was equivalent
757 to specifying --merge followed by :hg:`update --clean .` to
757 to specifying --merge followed by :hg:`update --clean .` to
758 cancel the merge and leave the child of REV as a head to be
758 cancel the merge and leave the child of REV as a head to be
759 merged separately.
759 merged separately.
760
760
761 See :hg:`help dates` for a list of formats valid for -d/--date.
761 See :hg:`help dates` for a list of formats valid for -d/--date.
762
762
763 See :hg:`help revert` for a way to restore files to the state
763 See :hg:`help revert` for a way to restore files to the state
764 of another revision.
764 of another revision.
765
765
766 Returns 0 on success, 1 if nothing to backout or there are unresolved
766 Returns 0 on success, 1 if nothing to backout or there are unresolved
767 files.
767 files.
768 """
768 """
769 with repo.wlock(), repo.lock():
769 with repo.wlock(), repo.lock():
770 return _dobackout(ui, repo, node, rev, **opts)
770 return _dobackout(ui, repo, node, rev, **opts)
771
771
772
772
773 def _dobackout(ui, repo, node=None, rev=None, **opts):
773 def _dobackout(ui, repo, node=None, rev=None, **opts):
774 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
774 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
775 opts = pycompat.byteskwargs(opts)
775 opts = pycompat.byteskwargs(opts)
776
776
777 if rev and node:
777 if rev and node:
778 raise error.InputError(_(b"please specify just one revision"))
778 raise error.InputError(_(b"please specify just one revision"))
779
779
780 if not rev:
780 if not rev:
781 rev = node
781 rev = node
782
782
783 if not rev:
783 if not rev:
784 raise error.InputError(_(b"please specify a revision to backout"))
784 raise error.InputError(_(b"please specify a revision to backout"))
785
785
786 date = opts.get(b'date')
786 date = opts.get(b'date')
787 if date:
787 if date:
788 opts[b'date'] = dateutil.parsedate(date)
788 opts[b'date'] = dateutil.parsedate(date)
789
789
790 cmdutil.checkunfinished(repo)
790 cmdutil.checkunfinished(repo)
791 cmdutil.bailifchanged(repo)
791 cmdutil.bailifchanged(repo)
792 ctx = logcmdutil.revsingle(repo, rev)
792 ctx = logcmdutil.revsingle(repo, rev)
793 node = ctx.node()
793 node = ctx.node()
794
794
795 op1, op2 = repo.dirstate.parents()
795 op1, op2 = repo.dirstate.parents()
796 if not repo.changelog.isancestor(node, op1):
796 if not repo.changelog.isancestor(node, op1):
797 raise error.InputError(
797 raise error.InputError(
798 _(b'cannot backout change that is not an ancestor')
798 _(b'cannot backout change that is not an ancestor')
799 )
799 )
800
800
801 p1, p2 = repo.changelog.parents(node)
801 p1, p2 = repo.changelog.parents(node)
802 if p1 == repo.nullid:
802 if p1 == repo.nullid:
803 raise error.InputError(_(b'cannot backout a change with no parents'))
803 raise error.InputError(_(b'cannot backout a change with no parents'))
804 if p2 != repo.nullid:
804 if p2 != repo.nullid:
805 if not opts.get(b'parent'):
805 if not opts.get(b'parent'):
806 raise error.InputError(_(b'cannot backout a merge changeset'))
806 raise error.InputError(_(b'cannot backout a merge changeset'))
807 p = repo.lookup(opts[b'parent'])
807 p = repo.lookup(opts[b'parent'])
808 if p not in (p1, p2):
808 if p not in (p1, p2):
809 raise error.InputError(
809 raise error.InputError(
810 _(b'%s is not a parent of %s') % (short(p), short(node))
810 _(b'%s is not a parent of %s') % (short(p), short(node))
811 )
811 )
812 parent = p
812 parent = p
813 else:
813 else:
814 if opts.get(b'parent'):
814 if opts.get(b'parent'):
815 raise error.InputError(
815 raise error.InputError(
816 _(b'cannot use --parent on non-merge changeset')
816 _(b'cannot use --parent on non-merge changeset')
817 )
817 )
818 parent = p1
818 parent = p1
819
819
820 # the backout should appear on the same branch
820 # the backout should appear on the same branch
821 branch = repo.dirstate.branch()
821 branch = repo.dirstate.branch()
822 bheads = repo.branchheads(branch)
822 bheads = repo.branchheads(branch)
823 rctx = scmutil.revsingle(repo, hex(parent))
823 rctx = scmutil.revsingle(repo, hex(parent))
824 if not opts.get(b'merge') and op1 != node:
824 if not opts.get(b'merge') and op1 != node:
825 with dirstateguard.dirstateguard(repo, b'backout'):
825 with dirstateguard.dirstateguard(repo, b'backout'):
826 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
826 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
827 with ui.configoverride(overrides, b'backout'):
827 with ui.configoverride(overrides, b'backout'):
828 stats = mergemod.back_out(ctx, parent=repo[parent])
828 stats = mergemod.back_out(ctx, parent=repo[parent])
829 repo.setparents(op1, op2)
829 repo.setparents(op1, op2)
830 hg._showstats(repo, stats)
830 hg._showstats(repo, stats)
831 if stats.unresolvedcount:
831 if stats.unresolvedcount:
832 repo.ui.status(
832 repo.ui.status(
833 _(b"use 'hg resolve' to retry unresolved file merges\n")
833 _(b"use 'hg resolve' to retry unresolved file merges\n")
834 )
834 )
835 return 1
835 return 1
836 else:
836 else:
837 hg.clean(repo, node, show_stats=False)
837 hg.clean(repo, node, show_stats=False)
838 repo.dirstate.setbranch(branch)
838 repo.dirstate.setbranch(branch)
839 cmdutil.revert(ui, repo, rctx)
839 cmdutil.revert(ui, repo, rctx)
840
840
841 if opts.get(b'no_commit'):
841 if opts.get(b'no_commit'):
842 msg = _(b"changeset %s backed out, don't forget to commit.\n")
842 msg = _(b"changeset %s backed out, don't forget to commit.\n")
843 ui.status(msg % short(node))
843 ui.status(msg % short(node))
844 return 0
844 return 0
845
845
846 def commitfunc(ui, repo, message, match, opts):
846 def commitfunc(ui, repo, message, match, opts):
847 editform = b'backout'
847 editform = b'backout'
848 e = cmdutil.getcommiteditor(
848 e = cmdutil.getcommiteditor(
849 editform=editform, **pycompat.strkwargs(opts)
849 editform=editform, **pycompat.strkwargs(opts)
850 )
850 )
851 if not message:
851 if not message:
852 # we don't translate commit messages
852 # we don't translate commit messages
853 message = b"Backed out changeset %s" % short(node)
853 message = b"Backed out changeset %s" % short(node)
854 e = cmdutil.getcommiteditor(edit=True, editform=editform)
854 e = cmdutil.getcommiteditor(edit=True, editform=editform)
855 return repo.commit(
855 return repo.commit(
856 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
856 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
857 )
857 )
858
858
859 # save to detect changes
859 # save to detect changes
860 tip = repo.changelog.tip()
860 tip = repo.changelog.tip()
861
861
862 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
862 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
863 if not newnode:
863 if not newnode:
864 ui.status(_(b"nothing changed\n"))
864 ui.status(_(b"nothing changed\n"))
865 return 1
865 return 1
866 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
866 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
867
867
868 def nice(node):
868 def nice(node):
869 return b'%d:%s' % (repo.changelog.rev(node), short(node))
869 return b'%d:%s' % (repo.changelog.rev(node), short(node))
870
870
871 ui.status(
871 ui.status(
872 _(b'changeset %s backs out changeset %s\n')
872 _(b'changeset %s backs out changeset %s\n')
873 % (nice(newnode), nice(node))
873 % (nice(newnode), nice(node))
874 )
874 )
875 if opts.get(b'merge') and op1 != node:
875 if opts.get(b'merge') and op1 != node:
876 hg.clean(repo, op1, show_stats=False)
876 hg.clean(repo, op1, show_stats=False)
877 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
877 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
878 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
878 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
879 with ui.configoverride(overrides, b'backout'):
879 with ui.configoverride(overrides, b'backout'):
880 return hg.merge(repo[b'tip'])
880 return hg.merge(repo[b'tip'])
881 return 0
881 return 0
882
882
883
883
884 @command(
884 @command(
885 b'bisect',
885 b'bisect',
886 [
886 [
887 (b'r', b'reset', False, _(b'reset bisect state')),
887 (b'r', b'reset', False, _(b'reset bisect state')),
888 (b'g', b'good', False, _(b'mark changeset good')),
888 (b'g', b'good', False, _(b'mark changeset good')),
889 (b'b', b'bad', False, _(b'mark changeset bad')),
889 (b'b', b'bad', False, _(b'mark changeset bad')),
890 (b's', b'skip', False, _(b'skip testing changeset')),
890 (b's', b'skip', False, _(b'skip testing changeset')),
891 (b'e', b'extend', False, _(b'extend the bisect range')),
891 (b'e', b'extend', False, _(b'extend the bisect range')),
892 (
892 (
893 b'c',
893 b'c',
894 b'command',
894 b'command',
895 b'',
895 b'',
896 _(b'use command to check changeset state'),
896 _(b'use command to check changeset state'),
897 _(b'CMD'),
897 _(b'CMD'),
898 ),
898 ),
899 (b'U', b'noupdate', False, _(b'do not update to target')),
899 (b'U', b'noupdate', False, _(b'do not update to target')),
900 ],
900 ],
901 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
901 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
902 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
902 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
903 )
903 )
904 def bisect(
904 def bisect(
905 ui,
905 ui,
906 repo,
906 repo,
907 positional_1=None,
907 positional_1=None,
908 positional_2=None,
908 positional_2=None,
909 command=None,
909 command=None,
910 reset=None,
910 reset=None,
911 good=None,
911 good=None,
912 bad=None,
912 bad=None,
913 skip=None,
913 skip=None,
914 extend=None,
914 extend=None,
915 noupdate=None,
915 noupdate=None,
916 ):
916 ):
917 """subdivision search of changesets
917 """subdivision search of changesets
918
918
919 This command helps to find changesets which introduce problems. To
919 This command helps to find changesets which introduce problems. To
920 use, mark the earliest changeset you know exhibits the problem as
920 use, mark the earliest changeset you know exhibits the problem as
921 bad, then mark the latest changeset which is free from the problem
921 bad, then mark the latest changeset which is free from the problem
922 as good. Bisect will update your working directory to a revision
922 as good. Bisect will update your working directory to a revision
923 for testing (unless the -U/--noupdate option is specified). Once
923 for testing (unless the -U/--noupdate option is specified). Once
924 you have performed tests, mark the working directory as good or
924 you have performed tests, mark the working directory as good or
925 bad, and bisect will either update to another candidate changeset
925 bad, and bisect will either update to another candidate changeset
926 or announce that it has found the bad revision.
926 or announce that it has found the bad revision.
927
927
928 As a shortcut, you can also use the revision argument to mark a
928 As a shortcut, you can also use the revision argument to mark a
929 revision as good or bad without checking it out first.
929 revision as good or bad without checking it out first.
930
930
931 If you supply a command, it will be used for automatic bisection.
931 If you supply a command, it will be used for automatic bisection.
932 The environment variable HG_NODE will contain the ID of the
932 The environment variable HG_NODE will contain the ID of the
933 changeset being tested. The exit status of the command will be
933 changeset being tested. The exit status of the command will be
934 used to mark revisions as good or bad: status 0 means good, 125
934 used to mark revisions as good or bad: status 0 means good, 125
935 means to skip the revision, 127 (command not found) will abort the
935 means to skip the revision, 127 (command not found) will abort the
936 bisection, and any other non-zero exit status means the revision
936 bisection, and any other non-zero exit status means the revision
937 is bad.
937 is bad.
938
938
939 .. container:: verbose
939 .. container:: verbose
940
940
941 Some examples:
941 Some examples:
942
942
943 - start a bisection with known bad revision 34, and good revision 12::
943 - start a bisection with known bad revision 34, and good revision 12::
944
944
945 hg bisect --bad 34
945 hg bisect --bad 34
946 hg bisect --good 12
946 hg bisect --good 12
947
947
948 - advance the current bisection by marking current revision as good or
948 - advance the current bisection by marking current revision as good or
949 bad::
949 bad::
950
950
951 hg bisect --good
951 hg bisect --good
952 hg bisect --bad
952 hg bisect --bad
953
953
954 - mark the current revision, or a known revision, to be skipped (e.g. if
954 - mark the current revision, or a known revision, to be skipped (e.g. if
955 that revision is not usable because of another issue)::
955 that revision is not usable because of another issue)::
956
956
957 hg bisect --skip
957 hg bisect --skip
958 hg bisect --skip 23
958 hg bisect --skip 23
959
959
960 - skip all revisions that do not touch directories ``foo`` or ``bar``::
960 - skip all revisions that do not touch directories ``foo`` or ``bar``::
961
961
962 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
962 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
963
963
964 - forget the current bisection::
964 - forget the current bisection::
965
965
966 hg bisect --reset
966 hg bisect --reset
967
967
968 - use 'make && make tests' to automatically find the first broken
968 - use 'make && make tests' to automatically find the first broken
969 revision::
969 revision::
970
970
971 hg bisect --reset
971 hg bisect --reset
972 hg bisect --bad 34
972 hg bisect --bad 34
973 hg bisect --good 12
973 hg bisect --good 12
974 hg bisect --command "make && make tests"
974 hg bisect --command "make && make tests"
975
975
976 - see all changesets whose states are already known in the current
976 - see all changesets whose states are already known in the current
977 bisection::
977 bisection::
978
978
979 hg log -r "bisect(pruned)"
979 hg log -r "bisect(pruned)"
980
980
981 - see the changeset currently being bisected (especially useful
981 - see the changeset currently being bisected (especially useful
982 if running with -U/--noupdate)::
982 if running with -U/--noupdate)::
983
983
984 hg log -r "bisect(current)"
984 hg log -r "bisect(current)"
985
985
986 - see all changesets that took part in the current bisection::
986 - see all changesets that took part in the current bisection::
987
987
988 hg log -r "bisect(range)"
988 hg log -r "bisect(range)"
989
989
990 - you can even get a nice graph::
990 - you can even get a nice graph::
991
991
992 hg log --graph -r "bisect(range)"
992 hg log --graph -r "bisect(range)"
993
993
994 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
994 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
995
995
996 Returns 0 on success.
996 Returns 0 on success.
997 """
997 """
998 rev = []
998 rev = []
999 # backward compatibility
999 # backward compatibility
1000 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1000 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1001 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1001 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1002 cmd = positional_1
1002 cmd = positional_1
1003 rev.append(positional_2)
1003 rev.append(positional_2)
1004 if cmd == b"good":
1004 if cmd == b"good":
1005 good = True
1005 good = True
1006 elif cmd == b"bad":
1006 elif cmd == b"bad":
1007 bad = True
1007 bad = True
1008 else:
1008 else:
1009 reset = True
1009 reset = True
1010 elif positional_2:
1010 elif positional_2:
1011 raise error.InputError(_(b'incompatible arguments'))
1011 raise error.InputError(_(b'incompatible arguments'))
1012 elif positional_1 is not None:
1012 elif positional_1 is not None:
1013 rev.append(positional_1)
1013 rev.append(positional_1)
1014
1014
1015 incompatibles = {
1015 incompatibles = {
1016 b'--bad': bad,
1016 b'--bad': bad,
1017 b'--command': bool(command),
1017 b'--command': bool(command),
1018 b'--extend': extend,
1018 b'--extend': extend,
1019 b'--good': good,
1019 b'--good': good,
1020 b'--reset': reset,
1020 b'--reset': reset,
1021 b'--skip': skip,
1021 b'--skip': skip,
1022 }
1022 }
1023
1023
1024 enabled = [x for x in incompatibles if incompatibles[x]]
1024 enabled = [x for x in incompatibles if incompatibles[x]]
1025
1025
1026 if len(enabled) > 1:
1026 if len(enabled) > 1:
1027 raise error.InputError(
1027 raise error.InputError(
1028 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1028 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1029 )
1029 )
1030
1030
1031 if reset:
1031 if reset:
1032 hbisect.resetstate(repo)
1032 hbisect.resetstate(repo)
1033 return
1033 return
1034
1034
1035 state = hbisect.load_state(repo)
1035 state = hbisect.load_state(repo)
1036
1036
1037 if rev:
1037 if rev:
1038 nodes = [repo[i].node() for i in logcmdutil.revrange(repo, rev)]
1038 nodes = [repo[i].node() for i in logcmdutil.revrange(repo, rev)]
1039 else:
1039 else:
1040 nodes = [repo.lookup(b'.')]
1040 nodes = [repo.lookup(b'.')]
1041
1041
1042 # update state
1042 # update state
1043 if good or bad or skip:
1043 if good or bad or skip:
1044 if good:
1044 if good:
1045 state[b'good'] += nodes
1045 state[b'good'] += nodes
1046 elif bad:
1046 elif bad:
1047 state[b'bad'] += nodes
1047 state[b'bad'] += nodes
1048 elif skip:
1048 elif skip:
1049 state[b'skip'] += nodes
1049 state[b'skip'] += nodes
1050 hbisect.save_state(repo, state)
1050 hbisect.save_state(repo, state)
1051 if not (state[b'good'] and state[b'bad']):
1051 if not (state[b'good'] and state[b'bad']):
1052 return
1052 return
1053
1053
1054 def mayupdate(repo, node, show_stats=True):
1054 def mayupdate(repo, node, show_stats=True):
1055 """common used update sequence"""
1055 """common used update sequence"""
1056 if noupdate:
1056 if noupdate:
1057 return
1057 return
1058 cmdutil.checkunfinished(repo)
1058 cmdutil.checkunfinished(repo)
1059 cmdutil.bailifchanged(repo)
1059 cmdutil.bailifchanged(repo)
1060 return hg.clean(repo, node, show_stats=show_stats)
1060 return hg.clean(repo, node, show_stats=show_stats)
1061
1061
1062 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1062 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1063
1063
1064 if command:
1064 if command:
1065 changesets = 1
1065 changesets = 1
1066 if noupdate:
1066 if noupdate:
1067 try:
1067 try:
1068 node = state[b'current'][0]
1068 node = state[b'current'][0]
1069 except LookupError:
1069 except LookupError:
1070 raise error.StateError(
1070 raise error.StateError(
1071 _(
1071 _(
1072 b'current bisect revision is unknown - '
1072 b'current bisect revision is unknown - '
1073 b'start a new bisect to fix'
1073 b'start a new bisect to fix'
1074 )
1074 )
1075 )
1075 )
1076 else:
1076 else:
1077 node, p2 = repo.dirstate.parents()
1077 node, p2 = repo.dirstate.parents()
1078 if p2 != repo.nullid:
1078 if p2 != repo.nullid:
1079 raise error.StateError(_(b'current bisect revision is a merge'))
1079 raise error.StateError(_(b'current bisect revision is a merge'))
1080 if rev:
1080 if rev:
1081 if not nodes:
1081 if not nodes:
1082 raise error.InputError(_(b'empty revision set'))
1082 raise error.InputError(_(b'empty revision set'))
1083 node = repo[nodes[-1]].node()
1083 node = repo[nodes[-1]].node()
1084 with hbisect.restore_state(repo, state, node):
1084 with hbisect.restore_state(repo, state, node):
1085 while changesets:
1085 while changesets:
1086 # update state
1086 # update state
1087 state[b'current'] = [node]
1087 state[b'current'] = [node]
1088 hbisect.save_state(repo, state)
1088 hbisect.save_state(repo, state)
1089 status = ui.system(
1089 status = ui.system(
1090 command,
1090 command,
1091 environ={b'HG_NODE': hex(node)},
1091 environ={b'HG_NODE': hex(node)},
1092 blockedtag=b'bisect_check',
1092 blockedtag=b'bisect_check',
1093 )
1093 )
1094 if status == 125:
1094 if status == 125:
1095 transition = b"skip"
1095 transition = b"skip"
1096 elif status == 0:
1096 elif status == 0:
1097 transition = b"good"
1097 transition = b"good"
1098 # status < 0 means process was killed
1098 # status < 0 means process was killed
1099 elif status == 127:
1099 elif status == 127:
1100 raise error.Abort(_(b"failed to execute %s") % command)
1100 raise error.Abort(_(b"failed to execute %s") % command)
1101 elif status < 0:
1101 elif status < 0:
1102 raise error.Abort(_(b"%s killed") % command)
1102 raise error.Abort(_(b"%s killed") % command)
1103 else:
1103 else:
1104 transition = b"bad"
1104 transition = b"bad"
1105 state[transition].append(node)
1105 state[transition].append(node)
1106 ctx = repo[node]
1106 ctx = repo[node]
1107 summary = cmdutil.format_changeset_summary(ui, ctx, b'bisect')
1107 summary = cmdutil.format_changeset_summary(ui, ctx, b'bisect')
1108 ui.status(_(b'changeset %s: %s\n') % (summary, transition))
1108 ui.status(_(b'changeset %s: %s\n') % (summary, transition))
1109 hbisect.checkstate(state)
1109 hbisect.checkstate(state)
1110 # bisect
1110 # bisect
1111 nodes, changesets, bgood = hbisect.bisect(repo, state)
1111 nodes, changesets, bgood = hbisect.bisect(repo, state)
1112 # update to next check
1112 # update to next check
1113 node = nodes[0]
1113 node = nodes[0]
1114 mayupdate(repo, node, show_stats=False)
1114 mayupdate(repo, node, show_stats=False)
1115 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1115 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1116 return
1116 return
1117
1117
1118 hbisect.checkstate(state)
1118 hbisect.checkstate(state)
1119
1119
1120 # actually bisect
1120 # actually bisect
1121 nodes, changesets, good = hbisect.bisect(repo, state)
1121 nodes, changesets, good = hbisect.bisect(repo, state)
1122 if extend:
1122 if extend:
1123 if not changesets:
1123 if not changesets:
1124 extendctx = hbisect.extendrange(repo, state, nodes, good)
1124 extendctx = hbisect.extendrange(repo, state, nodes, good)
1125 if extendctx is not None:
1125 if extendctx is not None:
1126 ui.write(
1126 ui.write(
1127 _(b"Extending search to changeset %s\n")
1127 _(b"Extending search to changeset %s\n")
1128 % cmdutil.format_changeset_summary(ui, extendctx, b'bisect')
1128 % cmdutil.format_changeset_summary(ui, extendctx, b'bisect')
1129 )
1129 )
1130 state[b'current'] = [extendctx.node()]
1130 state[b'current'] = [extendctx.node()]
1131 hbisect.save_state(repo, state)
1131 hbisect.save_state(repo, state)
1132 return mayupdate(repo, extendctx.node())
1132 return mayupdate(repo, extendctx.node())
1133 raise error.StateError(_(b"nothing to extend"))
1133 raise error.StateError(_(b"nothing to extend"))
1134
1134
1135 if changesets == 0:
1135 if changesets == 0:
1136 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1136 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1137 else:
1137 else:
1138 assert len(nodes) == 1 # only a single node can be tested next
1138 assert len(nodes) == 1 # only a single node can be tested next
1139 node = nodes[0]
1139 node = nodes[0]
1140 # compute the approximate number of remaining tests
1140 # compute the approximate number of remaining tests
1141 tests, size = 0, 2
1141 tests, size = 0, 2
1142 while size <= changesets:
1142 while size <= changesets:
1143 tests, size = tests + 1, size * 2
1143 tests, size = tests + 1, size * 2
1144 rev = repo.changelog.rev(node)
1144 rev = repo.changelog.rev(node)
1145 summary = cmdutil.format_changeset_summary(ui, repo[rev], b'bisect')
1145 summary = cmdutil.format_changeset_summary(ui, repo[rev], b'bisect')
1146 ui.write(
1146 ui.write(
1147 _(
1147 _(
1148 b"Testing changeset %s "
1148 b"Testing changeset %s "
1149 b"(%d changesets remaining, ~%d tests)\n"
1149 b"(%d changesets remaining, ~%d tests)\n"
1150 )
1150 )
1151 % (summary, changesets, tests)
1151 % (summary, changesets, tests)
1152 )
1152 )
1153 state[b'current'] = [node]
1153 state[b'current'] = [node]
1154 hbisect.save_state(repo, state)
1154 hbisect.save_state(repo, state)
1155 return mayupdate(repo, node)
1155 return mayupdate(repo, node)
1156
1156
1157
1157
1158 @command(
1158 @command(
1159 b'bookmarks|bookmark',
1159 b'bookmarks|bookmark',
1160 [
1160 [
1161 (b'f', b'force', False, _(b'force')),
1161 (b'f', b'force', False, _(b'force')),
1162 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1162 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1163 (b'd', b'delete', False, _(b'delete a given bookmark')),
1163 (b'd', b'delete', False, _(b'delete a given bookmark')),
1164 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1164 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1165 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1165 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1166 (b'l', b'list', False, _(b'list existing bookmarks')),
1166 (b'l', b'list', False, _(b'list existing bookmarks')),
1167 ]
1167 ]
1168 + formatteropts,
1168 + formatteropts,
1169 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1169 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1170 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1170 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1171 )
1171 )
1172 def bookmark(ui, repo, *names, **opts):
1172 def bookmark(ui, repo, *names, **opts):
1173 """create a new bookmark or list existing bookmarks
1173 """create a new bookmark or list existing bookmarks
1174
1174
1175 Bookmarks are labels on changesets to help track lines of development.
1175 Bookmarks are labels on changesets to help track lines of development.
1176 Bookmarks are unversioned and can be moved, renamed and deleted.
1176 Bookmarks are unversioned and can be moved, renamed and deleted.
1177 Deleting or moving a bookmark has no effect on the associated changesets.
1177 Deleting or moving a bookmark has no effect on the associated changesets.
1178
1178
1179 Creating or updating to a bookmark causes it to be marked as 'active'.
1179 Creating or updating to a bookmark causes it to be marked as 'active'.
1180 The active bookmark is indicated with a '*'.
1180 The active bookmark is indicated with a '*'.
1181 When a commit is made, the active bookmark will advance to the new commit.
1181 When a commit is made, the active bookmark will advance to the new commit.
1182 A plain :hg:`update` will also advance an active bookmark, if possible.
1182 A plain :hg:`update` will also advance an active bookmark, if possible.
1183 Updating away from a bookmark will cause it to be deactivated.
1183 Updating away from a bookmark will cause it to be deactivated.
1184
1184
1185 Bookmarks can be pushed and pulled between repositories (see
1185 Bookmarks can be pushed and pulled between repositories (see
1186 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1186 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1187 diverged, a new 'divergent bookmark' of the form 'name@path' will
1187 diverged, a new 'divergent bookmark' of the form 'name@path' will
1188 be created. Using :hg:`merge` will resolve the divergence.
1188 be created. Using :hg:`merge` will resolve the divergence.
1189
1189
1190 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1190 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1191 the active bookmark's name.
1191 the active bookmark's name.
1192
1192
1193 A bookmark named '@' has the special property that :hg:`clone` will
1193 A bookmark named '@' has the special property that :hg:`clone` will
1194 check it out by default if it exists.
1194 check it out by default if it exists.
1195
1195
1196 .. container:: verbose
1196 .. container:: verbose
1197
1197
1198 Template:
1198 Template:
1199
1199
1200 The following keywords are supported in addition to the common template
1200 The following keywords are supported in addition to the common template
1201 keywords and functions such as ``{bookmark}``. See also
1201 keywords and functions such as ``{bookmark}``. See also
1202 :hg:`help templates`.
1202 :hg:`help templates`.
1203
1203
1204 :active: Boolean. True if the bookmark is active.
1204 :active: Boolean. True if the bookmark is active.
1205
1205
1206 Examples:
1206 Examples:
1207
1207
1208 - create an active bookmark for a new line of development::
1208 - create an active bookmark for a new line of development::
1209
1209
1210 hg book new-feature
1210 hg book new-feature
1211
1211
1212 - create an inactive bookmark as a place marker::
1212 - create an inactive bookmark as a place marker::
1213
1213
1214 hg book -i reviewed
1214 hg book -i reviewed
1215
1215
1216 - create an inactive bookmark on another changeset::
1216 - create an inactive bookmark on another changeset::
1217
1217
1218 hg book -r .^ tested
1218 hg book -r .^ tested
1219
1219
1220 - rename bookmark turkey to dinner::
1220 - rename bookmark turkey to dinner::
1221
1221
1222 hg book -m turkey dinner
1222 hg book -m turkey dinner
1223
1223
1224 - move the '@' bookmark from another branch::
1224 - move the '@' bookmark from another branch::
1225
1225
1226 hg book -f @
1226 hg book -f @
1227
1227
1228 - print only the active bookmark name::
1228 - print only the active bookmark name::
1229
1229
1230 hg book -ql .
1230 hg book -ql .
1231 """
1231 """
1232 opts = pycompat.byteskwargs(opts)
1232 opts = pycompat.byteskwargs(opts)
1233 force = opts.get(b'force')
1233 force = opts.get(b'force')
1234 rev = opts.get(b'rev')
1234 rev = opts.get(b'rev')
1235 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1235 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1236
1236
1237 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1237 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1238 if action:
1238 if action:
1239 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1239 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1240 elif names or rev:
1240 elif names or rev:
1241 action = b'add'
1241 action = b'add'
1242 elif inactive:
1242 elif inactive:
1243 action = b'inactive' # meaning deactivate
1243 action = b'inactive' # meaning deactivate
1244 else:
1244 else:
1245 action = b'list'
1245 action = b'list'
1246
1246
1247 cmdutil.check_incompatible_arguments(
1247 cmdutil.check_incompatible_arguments(
1248 opts, b'inactive', [b'delete', b'list']
1248 opts, b'inactive', [b'delete', b'list']
1249 )
1249 )
1250 if not names and action in {b'add', b'delete'}:
1250 if not names and action in {b'add', b'delete'}:
1251 raise error.InputError(_(b"bookmark name required"))
1251 raise error.InputError(_(b"bookmark name required"))
1252
1252
1253 if action in {b'add', b'delete', b'rename', b'inactive'}:
1253 if action in {b'add', b'delete', b'rename', b'inactive'}:
1254 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1254 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1255 if action == b'delete':
1255 if action == b'delete':
1256 names = pycompat.maplist(repo._bookmarks.expandname, names)
1256 names = pycompat.maplist(repo._bookmarks.expandname, names)
1257 bookmarks.delete(repo, tr, names)
1257 bookmarks.delete(repo, tr, names)
1258 elif action == b'rename':
1258 elif action == b'rename':
1259 if not names:
1259 if not names:
1260 raise error.InputError(_(b"new bookmark name required"))
1260 raise error.InputError(_(b"new bookmark name required"))
1261 elif len(names) > 1:
1261 elif len(names) > 1:
1262 raise error.InputError(
1262 raise error.InputError(
1263 _(b"only one new bookmark name allowed")
1263 _(b"only one new bookmark name allowed")
1264 )
1264 )
1265 oldname = repo._bookmarks.expandname(opts[b'rename'])
1265 oldname = repo._bookmarks.expandname(opts[b'rename'])
1266 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1266 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1267 elif action == b'add':
1267 elif action == b'add':
1268 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1268 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1269 elif action == b'inactive':
1269 elif action == b'inactive':
1270 if len(repo._bookmarks) == 0:
1270 if len(repo._bookmarks) == 0:
1271 ui.status(_(b"no bookmarks set\n"))
1271 ui.status(_(b"no bookmarks set\n"))
1272 elif not repo._activebookmark:
1272 elif not repo._activebookmark:
1273 ui.status(_(b"no active bookmark\n"))
1273 ui.status(_(b"no active bookmark\n"))
1274 else:
1274 else:
1275 bookmarks.deactivate(repo)
1275 bookmarks.deactivate(repo)
1276 elif action == b'list':
1276 elif action == b'list':
1277 names = pycompat.maplist(repo._bookmarks.expandname, names)
1277 names = pycompat.maplist(repo._bookmarks.expandname, names)
1278 with ui.formatter(b'bookmarks', opts) as fm:
1278 with ui.formatter(b'bookmarks', opts) as fm:
1279 bookmarks.printbookmarks(ui, repo, fm, names)
1279 bookmarks.printbookmarks(ui, repo, fm, names)
1280 else:
1280 else:
1281 raise error.ProgrammingError(b'invalid action: %s' % action)
1281 raise error.ProgrammingError(b'invalid action: %s' % action)
1282
1282
1283
1283
1284 @command(
1284 @command(
1285 b'branch',
1285 b'branch',
1286 [
1286 [
1287 (
1287 (
1288 b'f',
1288 b'f',
1289 b'force',
1289 b'force',
1290 None,
1290 None,
1291 _(b'set branch name even if it shadows an existing branch'),
1291 _(b'set branch name even if it shadows an existing branch'),
1292 ),
1292 ),
1293 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1293 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1294 (
1294 (
1295 b'r',
1295 b'r',
1296 b'rev',
1296 b'rev',
1297 [],
1297 [],
1298 _(b'change branches of the given revs (EXPERIMENTAL)'),
1298 _(b'change branches of the given revs (EXPERIMENTAL)'),
1299 ),
1299 ),
1300 ],
1300 ],
1301 _(b'[-fC] [NAME]'),
1301 _(b'[-fC] [NAME]'),
1302 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1302 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1303 )
1303 )
1304 def branch(ui, repo, label=None, **opts):
1304 def branch(ui, repo, label=None, **opts):
1305 """set or show the current branch name
1305 """set or show the current branch name
1306
1306
1307 .. note::
1307 .. note::
1308
1308
1309 Branch names are permanent and global. Use :hg:`bookmark` to create a
1309 Branch names are permanent and global. Use :hg:`bookmark` to create a
1310 light-weight bookmark instead. See :hg:`help glossary` for more
1310 light-weight bookmark instead. See :hg:`help glossary` for more
1311 information about named branches and bookmarks.
1311 information about named branches and bookmarks.
1312
1312
1313 With no argument, show the current branch name. With one argument,
1313 With no argument, show the current branch name. With one argument,
1314 set the working directory branch name (the branch will not exist
1314 set the working directory branch name (the branch will not exist
1315 in the repository until the next commit). Standard practice
1315 in the repository until the next commit). Standard practice
1316 recommends that primary development take place on the 'default'
1316 recommends that primary development take place on the 'default'
1317 branch.
1317 branch.
1318
1318
1319 Unless -f/--force is specified, branch will not let you set a
1319 Unless -f/--force is specified, branch will not let you set a
1320 branch name that already exists.
1320 branch name that already exists.
1321
1321
1322 Use -C/--clean to reset the working directory branch to that of
1322 Use -C/--clean to reset the working directory branch to that of
1323 the parent of the working directory, negating a previous branch
1323 the parent of the working directory, negating a previous branch
1324 change.
1324 change.
1325
1325
1326 Use the command :hg:`update` to switch to an existing branch. Use
1326 Use the command :hg:`update` to switch to an existing branch. Use
1327 :hg:`commit --close-branch` to mark this branch head as closed.
1327 :hg:`commit --close-branch` to mark this branch head as closed.
1328 When all heads of a branch are closed, the branch will be
1328 When all heads of a branch are closed, the branch will be
1329 considered closed.
1329 considered closed.
1330
1330
1331 Returns 0 on success.
1331 Returns 0 on success.
1332 """
1332 """
1333 opts = pycompat.byteskwargs(opts)
1333 opts = pycompat.byteskwargs(opts)
1334 revs = opts.get(b'rev')
1334 revs = opts.get(b'rev')
1335 if label:
1335 if label:
1336 label = label.strip()
1336 label = label.strip()
1337
1337
1338 if not opts.get(b'clean') and not label:
1338 if not opts.get(b'clean') and not label:
1339 if revs:
1339 if revs:
1340 raise error.InputError(
1340 raise error.InputError(
1341 _(b"no branch name specified for the revisions")
1341 _(b"no branch name specified for the revisions")
1342 )
1342 )
1343 ui.write(b"%s\n" % repo.dirstate.branch())
1343 ui.write(b"%s\n" % repo.dirstate.branch())
1344 return
1344 return
1345
1345
1346 with repo.wlock():
1346 with repo.wlock():
1347 if opts.get(b'clean'):
1347 if opts.get(b'clean'):
1348 label = repo[b'.'].branch()
1348 label = repo[b'.'].branch()
1349 repo.dirstate.setbranch(label)
1349 repo.dirstate.setbranch(label)
1350 ui.status(_(b'reset working directory to branch %s\n') % label)
1350 ui.status(_(b'reset working directory to branch %s\n') % label)
1351 elif label:
1351 elif label:
1352
1352
1353 scmutil.checknewlabel(repo, label, b'branch')
1353 scmutil.checknewlabel(repo, label, b'branch')
1354 if revs:
1354 if revs:
1355 return cmdutil.changebranch(ui, repo, revs, label, opts)
1355 return cmdutil.changebranch(ui, repo, revs, label, opts)
1356
1356
1357 if not opts.get(b'force') and label in repo.branchmap():
1357 if not opts.get(b'force') and label in repo.branchmap():
1358 if label not in [p.branch() for p in repo[None].parents()]:
1358 if label not in [p.branch() for p in repo[None].parents()]:
1359 raise error.InputError(
1359 raise error.InputError(
1360 _(b'a branch of the same name already exists'),
1360 _(b'a branch of the same name already exists'),
1361 # i18n: "it" refers to an existing branch
1361 # i18n: "it" refers to an existing branch
1362 hint=_(b"use 'hg update' to switch to it"),
1362 hint=_(b"use 'hg update' to switch to it"),
1363 )
1363 )
1364
1364
1365 repo.dirstate.setbranch(label)
1365 repo.dirstate.setbranch(label)
1366 ui.status(_(b'marked working directory as branch %s\n') % label)
1366 ui.status(_(b'marked working directory as branch %s\n') % label)
1367
1367
1368 # find any open named branches aside from default
1368 # find any open named branches aside from default
1369 for n, h, t, c in repo.branchmap().iterbranches():
1369 for n, h, t, c in repo.branchmap().iterbranches():
1370 if n != b"default" and not c:
1370 if n != b"default" and not c:
1371 return 0
1371 return 0
1372 ui.status(
1372 ui.status(
1373 _(
1373 _(
1374 b'(branches are permanent and global, '
1374 b'(branches are permanent and global, '
1375 b'did you want a bookmark?)\n'
1375 b'did you want a bookmark?)\n'
1376 )
1376 )
1377 )
1377 )
1378
1378
1379
1379
1380 @command(
1380 @command(
1381 b'branches',
1381 b'branches',
1382 [
1382 [
1383 (
1383 (
1384 b'a',
1384 b'a',
1385 b'active',
1385 b'active',
1386 False,
1386 False,
1387 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1387 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1388 ),
1388 ),
1389 (b'c', b'closed', False, _(b'show normal and closed branches')),
1389 (b'c', b'closed', False, _(b'show normal and closed branches')),
1390 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1390 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1391 ]
1391 ]
1392 + formatteropts,
1392 + formatteropts,
1393 _(b'[-c]'),
1393 _(b'[-c]'),
1394 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1394 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1395 intents={INTENT_READONLY},
1395 intents={INTENT_READONLY},
1396 )
1396 )
1397 def branches(ui, repo, active=False, closed=False, **opts):
1397 def branches(ui, repo, active=False, closed=False, **opts):
1398 """list repository named branches
1398 """list repository named branches
1399
1399
1400 List the repository's named branches, indicating which ones are
1400 List the repository's named branches, indicating which ones are
1401 inactive. If -c/--closed is specified, also list branches which have
1401 inactive. If -c/--closed is specified, also list branches which have
1402 been marked closed (see :hg:`commit --close-branch`).
1402 been marked closed (see :hg:`commit --close-branch`).
1403
1403
1404 Use the command :hg:`update` to switch to an existing branch.
1404 Use the command :hg:`update` to switch to an existing branch.
1405
1405
1406 .. container:: verbose
1406 .. container:: verbose
1407
1407
1408 Template:
1408 Template:
1409
1409
1410 The following keywords are supported in addition to the common template
1410 The following keywords are supported in addition to the common template
1411 keywords and functions such as ``{branch}``. See also
1411 keywords and functions such as ``{branch}``. See also
1412 :hg:`help templates`.
1412 :hg:`help templates`.
1413
1413
1414 :active: Boolean. True if the branch is active.
1414 :active: Boolean. True if the branch is active.
1415 :closed: Boolean. True if the branch is closed.
1415 :closed: Boolean. True if the branch is closed.
1416 :current: Boolean. True if it is the current branch.
1416 :current: Boolean. True if it is the current branch.
1417
1417
1418 Returns 0.
1418 Returns 0.
1419 """
1419 """
1420
1420
1421 opts = pycompat.byteskwargs(opts)
1421 opts = pycompat.byteskwargs(opts)
1422 revs = opts.get(b'rev')
1422 revs = opts.get(b'rev')
1423 selectedbranches = None
1423 selectedbranches = None
1424 if revs:
1424 if revs:
1425 revs = logcmdutil.revrange(repo, revs)
1425 revs = logcmdutil.revrange(repo, revs)
1426 getbi = repo.revbranchcache().branchinfo
1426 getbi = repo.revbranchcache().branchinfo
1427 selectedbranches = {getbi(r)[0] for r in revs}
1427 selectedbranches = {getbi(r)[0] for r in revs}
1428
1428
1429 ui.pager(b'branches')
1429 ui.pager(b'branches')
1430 fm = ui.formatter(b'branches', opts)
1430 fm = ui.formatter(b'branches', opts)
1431 hexfunc = fm.hexfunc
1431 hexfunc = fm.hexfunc
1432
1432
1433 allheads = set(repo.heads())
1433 allheads = set(repo.heads())
1434 branches = []
1434 branches = []
1435 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1435 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1436 if selectedbranches is not None and tag not in selectedbranches:
1436 if selectedbranches is not None and tag not in selectedbranches:
1437 continue
1437 continue
1438 isactive = False
1438 isactive = False
1439 if not isclosed:
1439 if not isclosed:
1440 openheads = set(repo.branchmap().iteropen(heads))
1440 openheads = set(repo.branchmap().iteropen(heads))
1441 isactive = bool(openheads & allheads)
1441 isactive = bool(openheads & allheads)
1442 branches.append((tag, repo[tip], isactive, not isclosed))
1442 branches.append((tag, repo[tip], isactive, not isclosed))
1443 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1443 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1444
1444
1445 for tag, ctx, isactive, isopen in branches:
1445 for tag, ctx, isactive, isopen in branches:
1446 if active and not isactive:
1446 if active and not isactive:
1447 continue
1447 continue
1448 if isactive:
1448 if isactive:
1449 label = b'branches.active'
1449 label = b'branches.active'
1450 notice = b''
1450 notice = b''
1451 elif not isopen:
1451 elif not isopen:
1452 if not closed:
1452 if not closed:
1453 continue
1453 continue
1454 label = b'branches.closed'
1454 label = b'branches.closed'
1455 notice = _(b' (closed)')
1455 notice = _(b' (closed)')
1456 else:
1456 else:
1457 label = b'branches.inactive'
1457 label = b'branches.inactive'
1458 notice = _(b' (inactive)')
1458 notice = _(b' (inactive)')
1459 current = tag == repo.dirstate.branch()
1459 current = tag == repo.dirstate.branch()
1460 if current:
1460 if current:
1461 label = b'branches.current'
1461 label = b'branches.current'
1462
1462
1463 fm.startitem()
1463 fm.startitem()
1464 fm.write(b'branch', b'%s', tag, label=label)
1464 fm.write(b'branch', b'%s', tag, label=label)
1465 rev = ctx.rev()
1465 rev = ctx.rev()
1466 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1466 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1467 fmt = b' ' * padsize + b' %d:%s'
1467 fmt = b' ' * padsize + b' %d:%s'
1468 fm.condwrite(
1468 fm.condwrite(
1469 not ui.quiet,
1469 not ui.quiet,
1470 b'rev node',
1470 b'rev node',
1471 fmt,
1471 fmt,
1472 rev,
1472 rev,
1473 hexfunc(ctx.node()),
1473 hexfunc(ctx.node()),
1474 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1474 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1475 )
1475 )
1476 fm.context(ctx=ctx)
1476 fm.context(ctx=ctx)
1477 fm.data(active=isactive, closed=not isopen, current=current)
1477 fm.data(active=isactive, closed=not isopen, current=current)
1478 if not ui.quiet:
1478 if not ui.quiet:
1479 fm.plain(notice)
1479 fm.plain(notice)
1480 fm.plain(b'\n')
1480 fm.plain(b'\n')
1481 fm.end()
1481 fm.end()
1482
1482
1483
1483
1484 @command(
1484 @command(
1485 b'bundle',
1485 b'bundle',
1486 [
1486 [
1487
1488 (
1489 b'',
1490 b'exact',
1491 None,
1492 _(b'compute the base from the revision specified'),
1493 ),
1487 (
1494 (
1488 b'f',
1495 b'f',
1489 b'force',
1496 b'force',
1490 None,
1497 None,
1491 _(b'run even when the destination is unrelated'),
1498 _(b'run even when the destination is unrelated'),
1492 ),
1499 ),
1493 (
1500 (
1494 b'r',
1501 b'r',
1495 b'rev',
1502 b'rev',
1496 [],
1503 [],
1497 _(b'a changeset intended to be added to the destination'),
1504 _(b'a changeset intended to be added to the destination'),
1498 _(b'REV'),
1505 _(b'REV'),
1499 ),
1506 ),
1500 (
1507 (
1501 b'b',
1508 b'b',
1502 b'branch',
1509 b'branch',
1503 [],
1510 [],
1504 _(b'a specific branch you would like to bundle'),
1511 _(b'a specific branch you would like to bundle'),
1505 _(b'BRANCH'),
1512 _(b'BRANCH'),
1506 ),
1513 ),
1507 (
1514 (
1508 b'',
1515 b'',
1509 b'base',
1516 b'base',
1510 [],
1517 [],
1511 _(b'a base changeset assumed to be available at the destination'),
1518 _(b'a base changeset assumed to be available at the destination'),
1512 _(b'REV'),
1519 _(b'REV'),
1513 ),
1520 ),
1514 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1521 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1515 (
1522 (
1516 b't',
1523 b't',
1517 b'type',
1524 b'type',
1518 b'bzip2',
1525 b'bzip2',
1519 _(b'bundle compression type to use'),
1526 _(b'bundle compression type to use'),
1520 _(b'TYPE'),
1527 _(b'TYPE'),
1521 ),
1528 ),
1522 ]
1529 ]
1523 + remoteopts,
1530 + remoteopts,
1524 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]...'),
1531 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]...'),
1525 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1532 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1526 )
1533 )
1527 def bundle(ui, repo, fname, *dests, **opts):
1534 def bundle(ui, repo, fname, *dests, **opts):
1528 """create a bundle file
1535 """create a bundle file
1529
1536
1530 Generate a bundle file containing data to be transferred to another
1537 Generate a bundle file containing data to be transferred to another
1531 repository.
1538 repository.
1532
1539
1533 To create a bundle containing all changesets, use -a/--all
1540 To create a bundle containing all changesets, use -a/--all
1534 (or --base null). Otherwise, hg assumes the destination will have
1541 (or --base null). Otherwise, hg assumes the destination will have
1535 all the nodes you specify with --base parameters. Otherwise, hg
1542 all the nodes you specify with --base parameters. Otherwise, hg
1536 will assume the repository has all the nodes in destination, or
1543 will assume the repository has all the nodes in destination, or
1537 default-push/default if no destination is specified, where destination
1544 default-push/default if no destination is specified, where destination
1538 is the repositories you provide through DEST option.
1545 is the repositories you provide through DEST option.
1539
1546
1540 You can change bundle format with the -t/--type option. See
1547 You can change bundle format with the -t/--type option. See
1541 :hg:`help bundlespec` for documentation on this format. By default,
1548 :hg:`help bundlespec` for documentation on this format. By default,
1542 the most appropriate format is used and compression defaults to
1549 the most appropriate format is used and compression defaults to
1543 bzip2.
1550 bzip2.
1544
1551
1545 The bundle file can then be transferred using conventional means
1552 The bundle file can then be transferred using conventional means
1546 and applied to another repository with the unbundle or pull
1553 and applied to another repository with the unbundle or pull
1547 command. This is useful when direct push and pull are not
1554 command. This is useful when direct push and pull are not
1548 available or when exporting an entire repository is undesirable.
1555 available or when exporting an entire repository is undesirable.
1549
1556
1550 Applying bundles preserves all changeset contents including
1557 Applying bundles preserves all changeset contents including
1551 permissions, copy/rename information, and revision history.
1558 permissions, copy/rename information, and revision history.
1552
1559
1553 Returns 0 on success, 1 if no changes found.
1560 Returns 0 on success, 1 if no changes found.
1554 """
1561 """
1555 opts = pycompat.byteskwargs(opts)
1562 opts = pycompat.byteskwargs(opts)
1563
1556 revs = None
1564 revs = None
1557 if b'rev' in opts:
1565 if b'rev' in opts:
1558 revstrings = opts[b'rev']
1566 revstrings = opts[b'rev']
1559 revs = logcmdutil.revrange(repo, revstrings)
1567 revs = logcmdutil.revrange(repo, revstrings)
1560 if revstrings and not revs:
1568 if revstrings and not revs:
1561 raise error.InputError(_(b'no commits to bundle'))
1569 raise error.InputError(_(b'no commits to bundle'))
1562
1570
1563 bundletype = opts.get(b'type', b'bzip2').lower()
1571 bundletype = opts.get(b'type', b'bzip2').lower()
1564 try:
1572 try:
1565 bundlespec = bundlecaches.parsebundlespec(
1573 bundlespec = bundlecaches.parsebundlespec(
1566 repo, bundletype, strict=False
1574 repo, bundletype, strict=False
1567 )
1575 )
1568 except error.UnsupportedBundleSpecification as e:
1576 except error.UnsupportedBundleSpecification as e:
1569 raise error.InputError(
1577 raise error.InputError(
1570 pycompat.bytestr(e),
1578 pycompat.bytestr(e),
1571 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1579 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1572 )
1580 )
1573 cgversion = bundlespec.params[b"cg.version"]
1581 cgversion = bundlespec.params[b"cg.version"]
1574
1582
1575 # Packed bundles are a pseudo bundle format for now.
1583 # Packed bundles are a pseudo bundle format for now.
1576 if cgversion == b's1':
1584 if cgversion == b's1':
1577 raise error.InputError(
1585 raise error.InputError(
1578 _(b'packed bundles cannot be produced by "hg bundle"'),
1586 _(b'packed bundles cannot be produced by "hg bundle"'),
1579 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1587 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1580 )
1588 )
1581
1589
1582 if opts.get(b'all'):
1590 if opts.get(b'all'):
1583 if dests:
1591 if dests:
1584 raise error.InputError(
1592 raise error.InputError(
1585 _(b"--all is incompatible with specifying destinations")
1593 _(b"--all is incompatible with specifying destinations")
1586 )
1594 )
1587 if opts.get(b'base'):
1595 if opts.get(b'base'):
1588 ui.warn(_(b"ignoring --base because --all was specified\n"))
1596 ui.warn(_(b"ignoring --base because --all was specified\n"))
1597 if opts.get(b'exact'):
1598 ui.warn(_(b"ignoring --exact because --all was specified\n"))
1589 base = [nullrev]
1599 base = [nullrev]
1600 elif opts.get(b'exact'):
1601 if dests:
1602 raise error.InputError(
1603 _(b"--exact is incompatible with specifying destinations")
1604 )
1605 if opts.get(b'base'):
1606 ui.warn(_(b"ignoring --base because --exact was specified\n"))
1607 base = repo.revs(b'parents(%ld) - %ld', revs, revs)
1608 if not base:
1609 base = [nullrev]
1590 else:
1610 else:
1591 base = logcmdutil.revrange(repo, opts.get(b'base'))
1611 base = logcmdutil.revrange(repo, opts.get(b'base'))
1592 if cgversion not in changegroup.supportedoutgoingversions(repo):
1612 if cgversion not in changegroup.supportedoutgoingversions(repo):
1593 raise error.Abort(
1613 raise error.Abort(
1594 _(b"repository does not support bundle version %s") % cgversion
1614 _(b"repository does not support bundle version %s") % cgversion
1595 )
1615 )
1596
1616
1597 if base:
1617 if base:
1598 if dests:
1618 if dests:
1599 raise error.InputError(
1619 raise error.InputError(
1600 _(b"--base is incompatible with specifying destinations")
1620 _(b"--base is incompatible with specifying destinations")
1601 )
1621 )
1602 cl = repo.changelog
1622 cl = repo.changelog
1603 common = [cl.node(rev) for rev in base]
1623 common = [cl.node(rev) for rev in base]
1604 heads = [cl.node(r) for r in revs] if revs else None
1624 heads = [cl.node(r) for r in revs] if revs else None
1605 outgoing = discovery.outgoing(repo, common, heads)
1625 outgoing = discovery.outgoing(repo, common, heads)
1606 missing = outgoing.missing
1626 missing = outgoing.missing
1607 excluded = outgoing.excluded
1627 excluded = outgoing.excluded
1608 else:
1628 else:
1609 missing = set()
1629 missing = set()
1610 excluded = set()
1630 excluded = set()
1611 for path in urlutil.get_push_paths(repo, ui, dests):
1631 for path in urlutil.get_push_paths(repo, ui, dests):
1612 other = hg.peer(repo, opts, path.rawloc)
1632 other = hg.peer(repo, opts, path.rawloc)
1613 if revs is not None:
1633 if revs is not None:
1614 hex_revs = [repo[r].hex() for r in revs]
1634 hex_revs = [repo[r].hex() for r in revs]
1615 else:
1635 else:
1616 hex_revs = None
1636 hex_revs = None
1617 branches = (path.branch, [])
1637 branches = (path.branch, [])
1618 head_revs, checkout = hg.addbranchrevs(
1638 head_revs, checkout = hg.addbranchrevs(
1619 repo, repo, branches, hex_revs
1639 repo, repo, branches, hex_revs
1620 )
1640 )
1621 heads = (
1641 heads = (
1622 head_revs
1642 head_revs
1623 and pycompat.maplist(repo.lookup, head_revs)
1643 and pycompat.maplist(repo.lookup, head_revs)
1624 or head_revs
1644 or head_revs
1625 )
1645 )
1626 outgoing = discovery.findcommonoutgoing(
1646 outgoing = discovery.findcommonoutgoing(
1627 repo,
1647 repo,
1628 other,
1648 other,
1629 onlyheads=heads,
1649 onlyheads=heads,
1630 force=opts.get(b'force'),
1650 force=opts.get(b'force'),
1631 portable=True,
1651 portable=True,
1632 )
1652 )
1633 missing.update(outgoing.missing)
1653 missing.update(outgoing.missing)
1634 excluded.update(outgoing.excluded)
1654 excluded.update(outgoing.excluded)
1635
1655
1636 if not missing:
1656 if not missing:
1637 scmutil.nochangesfound(ui, repo, not base and excluded)
1657 scmutil.nochangesfound(ui, repo, not base and excluded)
1638 return 1
1658 return 1
1639
1659
1640 if heads:
1660 if heads:
1641 outgoing = discovery.outgoing(
1661 outgoing = discovery.outgoing(
1642 repo, missingroots=missing, ancestorsof=heads
1662 repo, missingroots=missing, ancestorsof=heads
1643 )
1663 )
1644 else:
1664 else:
1645 outgoing = discovery.outgoing(repo, missingroots=missing)
1665 outgoing = discovery.outgoing(repo, missingroots=missing)
1646 outgoing.excluded = sorted(excluded)
1666 outgoing.excluded = sorted(excluded)
1647
1667
1648 if cgversion == b'01': # bundle1
1668 if cgversion == b'01': # bundle1
1649 bversion = b'HG10' + bundlespec.wirecompression
1669 bversion = b'HG10' + bundlespec.wirecompression
1650 bcompression = None
1670 bcompression = None
1651 elif cgversion in (b'02', b'03'):
1671 elif cgversion in (b'02', b'03'):
1652 bversion = b'HG20'
1672 bversion = b'HG20'
1653 bcompression = bundlespec.wirecompression
1673 bcompression = bundlespec.wirecompression
1654 else:
1674 else:
1655 raise error.ProgrammingError(
1675 raise error.ProgrammingError(
1656 b'bundle: unexpected changegroup version %s' % cgversion
1676 b'bundle: unexpected changegroup version %s' % cgversion
1657 )
1677 )
1658
1678
1659 # TODO compression options should be derived from bundlespec parsing.
1679 # TODO compression options should be derived from bundlespec parsing.
1660 # This is a temporary hack to allow adjusting bundle compression
1680 # This is a temporary hack to allow adjusting bundle compression
1661 # level without a) formalizing the bundlespec changes to declare it
1681 # level without a) formalizing the bundlespec changes to declare it
1662 # b) introducing a command flag.
1682 # b) introducing a command flag.
1663 compopts = {}
1683 compopts = {}
1664 complevel = ui.configint(
1684 complevel = ui.configint(
1665 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1685 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1666 )
1686 )
1667 if complevel is None:
1687 if complevel is None:
1668 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1688 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1669 if complevel is not None:
1689 if complevel is not None:
1670 compopts[b'level'] = complevel
1690 compopts[b'level'] = complevel
1671
1691
1672 compthreads = ui.configint(
1692 compthreads = ui.configint(
1673 b'experimental', b'bundlecompthreads.' + bundlespec.compression
1693 b'experimental', b'bundlecompthreads.' + bundlespec.compression
1674 )
1694 )
1675 if compthreads is None:
1695 if compthreads is None:
1676 compthreads = ui.configint(b'experimental', b'bundlecompthreads')
1696 compthreads = ui.configint(b'experimental', b'bundlecompthreads')
1677 if compthreads is not None:
1697 if compthreads is not None:
1678 compopts[b'threads'] = compthreads
1698 compopts[b'threads'] = compthreads
1679
1699
1680 # Bundling of obsmarker and phases is optional as not all clients
1700 # Bundling of obsmarker and phases is optional as not all clients
1681 # support the necessary features.
1701 # support the necessary features.
1682 cfg = ui.configbool
1702 cfg = ui.configbool
1683 obsolescence_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker')
1703 obsolescence_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker')
1684 bundlespec.set_param(b'obsolescence', obsolescence_cfg, overwrite=False)
1704 bundlespec.set_param(b'obsolescence', obsolescence_cfg, overwrite=False)
1685 obs_mand_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker:mandatory')
1705 obs_mand_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker:mandatory')
1686 bundlespec.set_param(
1706 bundlespec.set_param(
1687 b'obsolescence-mandatory', obs_mand_cfg, overwrite=False
1707 b'obsolescence-mandatory', obs_mand_cfg, overwrite=False
1688 )
1708 )
1689 phases_cfg = cfg(b'experimental', b'bundle-phases')
1709 phases_cfg = cfg(b'experimental', b'bundle-phases')
1690 bundlespec.set_param(b'phases', phases_cfg, overwrite=False)
1710 bundlespec.set_param(b'phases', phases_cfg, overwrite=False)
1691
1711
1692 bundle2.writenewbundle(
1712 bundle2.writenewbundle(
1693 ui,
1713 ui,
1694 repo,
1714 repo,
1695 b'bundle',
1715 b'bundle',
1696 fname,
1716 fname,
1697 bversion,
1717 bversion,
1698 outgoing,
1718 outgoing,
1699 bundlespec.params,
1719 bundlespec.params,
1700 compression=bcompression,
1720 compression=bcompression,
1701 compopts=compopts,
1721 compopts=compopts,
1702 )
1722 )
1703
1723
1704
1724
1705 @command(
1725 @command(
1706 b'cat',
1726 b'cat',
1707 [
1727 [
1708 (
1728 (
1709 b'o',
1729 b'o',
1710 b'output',
1730 b'output',
1711 b'',
1731 b'',
1712 _(b'print output to file with formatted name'),
1732 _(b'print output to file with formatted name'),
1713 _(b'FORMAT'),
1733 _(b'FORMAT'),
1714 ),
1734 ),
1715 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1735 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1716 (b'', b'decode', None, _(b'apply any matching decode filter')),
1736 (b'', b'decode', None, _(b'apply any matching decode filter')),
1717 ]
1737 ]
1718 + walkopts
1738 + walkopts
1719 + formatteropts,
1739 + formatteropts,
1720 _(b'[OPTION]... FILE...'),
1740 _(b'[OPTION]... FILE...'),
1721 helpcategory=command.CATEGORY_FILE_CONTENTS,
1741 helpcategory=command.CATEGORY_FILE_CONTENTS,
1722 inferrepo=True,
1742 inferrepo=True,
1723 intents={INTENT_READONLY},
1743 intents={INTENT_READONLY},
1724 )
1744 )
1725 def cat(ui, repo, file1, *pats, **opts):
1745 def cat(ui, repo, file1, *pats, **opts):
1726 """output the current or given revision of files
1746 """output the current or given revision of files
1727
1747
1728 Print the specified files as they were at the given revision. If
1748 Print the specified files as they were at the given revision. If
1729 no revision is given, the parent of the working directory is used.
1749 no revision is given, the parent of the working directory is used.
1730
1750
1731 Output may be to a file, in which case the name of the file is
1751 Output may be to a file, in which case the name of the file is
1732 given using a template string. See :hg:`help templates`. In addition
1752 given using a template string. See :hg:`help templates`. In addition
1733 to the common template keywords, the following formatting rules are
1753 to the common template keywords, the following formatting rules are
1734 supported:
1754 supported:
1735
1755
1736 :``%%``: literal "%" character
1756 :``%%``: literal "%" character
1737 :``%s``: basename of file being printed
1757 :``%s``: basename of file being printed
1738 :``%d``: dirname of file being printed, or '.' if in repository root
1758 :``%d``: dirname of file being printed, or '.' if in repository root
1739 :``%p``: root-relative path name of file being printed
1759 :``%p``: root-relative path name of file being printed
1740 :``%H``: changeset hash (40 hexadecimal digits)
1760 :``%H``: changeset hash (40 hexadecimal digits)
1741 :``%R``: changeset revision number
1761 :``%R``: changeset revision number
1742 :``%h``: short-form changeset hash (12 hexadecimal digits)
1762 :``%h``: short-form changeset hash (12 hexadecimal digits)
1743 :``%r``: zero-padded changeset revision number
1763 :``%r``: zero-padded changeset revision number
1744 :``%b``: basename of the exporting repository
1764 :``%b``: basename of the exporting repository
1745 :``\\``: literal "\\" character
1765 :``\\``: literal "\\" character
1746
1766
1747 .. container:: verbose
1767 .. container:: verbose
1748
1768
1749 Template:
1769 Template:
1750
1770
1751 The following keywords are supported in addition to the common template
1771 The following keywords are supported in addition to the common template
1752 keywords and functions. See also :hg:`help templates`.
1772 keywords and functions. See also :hg:`help templates`.
1753
1773
1754 :data: String. File content.
1774 :data: String. File content.
1755 :path: String. Repository-absolute path of the file.
1775 :path: String. Repository-absolute path of the file.
1756
1776
1757 Returns 0 on success.
1777 Returns 0 on success.
1758 """
1778 """
1759 opts = pycompat.byteskwargs(opts)
1779 opts = pycompat.byteskwargs(opts)
1760 rev = opts.get(b'rev')
1780 rev = opts.get(b'rev')
1761 if rev:
1781 if rev:
1762 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1782 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1763 ctx = logcmdutil.revsingle(repo, rev)
1783 ctx = logcmdutil.revsingle(repo, rev)
1764 m = scmutil.match(ctx, (file1,) + pats, opts)
1784 m = scmutil.match(ctx, (file1,) + pats, opts)
1765 fntemplate = opts.pop(b'output', b'')
1785 fntemplate = opts.pop(b'output', b'')
1766 if cmdutil.isstdiofilename(fntemplate):
1786 if cmdutil.isstdiofilename(fntemplate):
1767 fntemplate = b''
1787 fntemplate = b''
1768
1788
1769 if fntemplate:
1789 if fntemplate:
1770 fm = formatter.nullformatter(ui, b'cat', opts)
1790 fm = formatter.nullformatter(ui, b'cat', opts)
1771 else:
1791 else:
1772 ui.pager(b'cat')
1792 ui.pager(b'cat')
1773 fm = ui.formatter(b'cat', opts)
1793 fm = ui.formatter(b'cat', opts)
1774 with fm:
1794 with fm:
1775 return cmdutil.cat(
1795 return cmdutil.cat(
1776 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1796 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1777 )
1797 )
1778
1798
1779
1799
1780 @command(
1800 @command(
1781 b'clone',
1801 b'clone',
1782 [
1802 [
1783 (
1803 (
1784 b'U',
1804 b'U',
1785 b'noupdate',
1805 b'noupdate',
1786 None,
1806 None,
1787 _(
1807 _(
1788 b'the clone will include an empty working '
1808 b'the clone will include an empty working '
1789 b'directory (only a repository)'
1809 b'directory (only a repository)'
1790 ),
1810 ),
1791 ),
1811 ),
1792 (
1812 (
1793 b'u',
1813 b'u',
1794 b'updaterev',
1814 b'updaterev',
1795 b'',
1815 b'',
1796 _(b'revision, tag, or branch to check out'),
1816 _(b'revision, tag, or branch to check out'),
1797 _(b'REV'),
1817 _(b'REV'),
1798 ),
1818 ),
1799 (
1819 (
1800 b'r',
1820 b'r',
1801 b'rev',
1821 b'rev',
1802 [],
1822 [],
1803 _(
1823 _(
1804 b'do not clone everything, but include this changeset'
1824 b'do not clone everything, but include this changeset'
1805 b' and its ancestors'
1825 b' and its ancestors'
1806 ),
1826 ),
1807 _(b'REV'),
1827 _(b'REV'),
1808 ),
1828 ),
1809 (
1829 (
1810 b'b',
1830 b'b',
1811 b'branch',
1831 b'branch',
1812 [],
1832 [],
1813 _(
1833 _(
1814 b'do not clone everything, but include this branch\'s'
1834 b'do not clone everything, but include this branch\'s'
1815 b' changesets and their ancestors'
1835 b' changesets and their ancestors'
1816 ),
1836 ),
1817 _(b'BRANCH'),
1837 _(b'BRANCH'),
1818 ),
1838 ),
1819 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1839 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1820 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1840 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1821 (b'', b'stream', None, _(b'clone with minimal data processing')),
1841 (b'', b'stream', None, _(b'clone with minimal data processing')),
1822 ]
1842 ]
1823 + remoteopts,
1843 + remoteopts,
1824 _(b'[OPTION]... SOURCE [DEST]'),
1844 _(b'[OPTION]... SOURCE [DEST]'),
1825 helpcategory=command.CATEGORY_REPO_CREATION,
1845 helpcategory=command.CATEGORY_REPO_CREATION,
1826 helpbasic=True,
1846 helpbasic=True,
1827 norepo=True,
1847 norepo=True,
1828 )
1848 )
1829 def clone(ui, source, dest=None, **opts):
1849 def clone(ui, source, dest=None, **opts):
1830 """make a copy of an existing repository
1850 """make a copy of an existing repository
1831
1851
1832 Create a copy of an existing repository in a new directory.
1852 Create a copy of an existing repository in a new directory.
1833
1853
1834 If no destination directory name is specified, it defaults to the
1854 If no destination directory name is specified, it defaults to the
1835 basename of the source.
1855 basename of the source.
1836
1856
1837 The location of the source is added to the new repository's
1857 The location of the source is added to the new repository's
1838 ``.hg/hgrc`` file, as the default to be used for future pulls.
1858 ``.hg/hgrc`` file, as the default to be used for future pulls.
1839
1859
1840 Only local paths and ``ssh://`` URLs are supported as
1860 Only local paths and ``ssh://`` URLs are supported as
1841 destinations. For ``ssh://`` destinations, no working directory or
1861 destinations. For ``ssh://`` destinations, no working directory or
1842 ``.hg/hgrc`` will be created on the remote side.
1862 ``.hg/hgrc`` will be created on the remote side.
1843
1863
1844 If the source repository has a bookmark called '@' set, that
1864 If the source repository has a bookmark called '@' set, that
1845 revision will be checked out in the new repository by default.
1865 revision will be checked out in the new repository by default.
1846
1866
1847 To check out a particular version, use -u/--update, or
1867 To check out a particular version, use -u/--update, or
1848 -U/--noupdate to create a clone with no working directory.
1868 -U/--noupdate to create a clone with no working directory.
1849
1869
1850 To pull only a subset of changesets, specify one or more revisions
1870 To pull only a subset of changesets, specify one or more revisions
1851 identifiers with -r/--rev or branches with -b/--branch. The
1871 identifiers with -r/--rev or branches with -b/--branch. The
1852 resulting clone will contain only the specified changesets and
1872 resulting clone will contain only the specified changesets and
1853 their ancestors. These options (or 'clone src#rev dest') imply
1873 their ancestors. These options (or 'clone src#rev dest') imply
1854 --pull, even for local source repositories.
1874 --pull, even for local source repositories.
1855
1875
1856 In normal clone mode, the remote normalizes repository data into a common
1876 In normal clone mode, the remote normalizes repository data into a common
1857 exchange format and the receiving end translates this data into its local
1877 exchange format and the receiving end translates this data into its local
1858 storage format. --stream activates a different clone mode that essentially
1878 storage format. --stream activates a different clone mode that essentially
1859 copies repository files from the remote with minimal data processing. This
1879 copies repository files from the remote with minimal data processing. This
1860 significantly reduces the CPU cost of a clone both remotely and locally.
1880 significantly reduces the CPU cost of a clone both remotely and locally.
1861 However, it often increases the transferred data size by 30-40%. This can
1881 However, it often increases the transferred data size by 30-40%. This can
1862 result in substantially faster clones where I/O throughput is plentiful,
1882 result in substantially faster clones where I/O throughput is plentiful,
1863 especially for larger repositories. A side-effect of --stream clones is
1883 especially for larger repositories. A side-effect of --stream clones is
1864 that storage settings and requirements on the remote are applied locally:
1884 that storage settings and requirements on the remote are applied locally:
1865 a modern client may inherit legacy or inefficient storage used by the
1885 a modern client may inherit legacy or inefficient storage used by the
1866 remote or a legacy Mercurial client may not be able to clone from a
1886 remote or a legacy Mercurial client may not be able to clone from a
1867 modern Mercurial remote.
1887 modern Mercurial remote.
1868
1888
1869 .. note::
1889 .. note::
1870
1890
1871 Specifying a tag will include the tagged changeset but not the
1891 Specifying a tag will include the tagged changeset but not the
1872 changeset containing the tag.
1892 changeset containing the tag.
1873
1893
1874 .. container:: verbose
1894 .. container:: verbose
1875
1895
1876 For efficiency, hardlinks are used for cloning whenever the
1896 For efficiency, hardlinks are used for cloning whenever the
1877 source and destination are on the same filesystem (note this
1897 source and destination are on the same filesystem (note this
1878 applies only to the repository data, not to the working
1898 applies only to the repository data, not to the working
1879 directory). Some filesystems, such as AFS, implement hardlinking
1899 directory). Some filesystems, such as AFS, implement hardlinking
1880 incorrectly, but do not report errors. In these cases, use the
1900 incorrectly, but do not report errors. In these cases, use the
1881 --pull option to avoid hardlinking.
1901 --pull option to avoid hardlinking.
1882
1902
1883 Mercurial will update the working directory to the first applicable
1903 Mercurial will update the working directory to the first applicable
1884 revision from this list:
1904 revision from this list:
1885
1905
1886 a) null if -U or the source repository has no changesets
1906 a) null if -U or the source repository has no changesets
1887 b) if -u . and the source repository is local, the first parent of
1907 b) if -u . and the source repository is local, the first parent of
1888 the source repository's working directory
1908 the source repository's working directory
1889 c) the changeset specified with -u (if a branch name, this means the
1909 c) the changeset specified with -u (if a branch name, this means the
1890 latest head of that branch)
1910 latest head of that branch)
1891 d) the changeset specified with -r
1911 d) the changeset specified with -r
1892 e) the tipmost head specified with -b
1912 e) the tipmost head specified with -b
1893 f) the tipmost head specified with the url#branch source syntax
1913 f) the tipmost head specified with the url#branch source syntax
1894 g) the revision marked with the '@' bookmark, if present
1914 g) the revision marked with the '@' bookmark, if present
1895 h) the tipmost head of the default branch
1915 h) the tipmost head of the default branch
1896 i) tip
1916 i) tip
1897
1917
1898 When cloning from servers that support it, Mercurial may fetch
1918 When cloning from servers that support it, Mercurial may fetch
1899 pre-generated data from a server-advertised URL or inline from the
1919 pre-generated data from a server-advertised URL or inline from the
1900 same stream. When this is done, hooks operating on incoming changesets
1920 same stream. When this is done, hooks operating on incoming changesets
1901 and changegroups may fire more than once, once for each pre-generated
1921 and changegroups may fire more than once, once for each pre-generated
1902 bundle and as well as for any additional remaining data. In addition,
1922 bundle and as well as for any additional remaining data. In addition,
1903 if an error occurs, the repository may be rolled back to a partial
1923 if an error occurs, the repository may be rolled back to a partial
1904 clone. This behavior may change in future releases.
1924 clone. This behavior may change in future releases.
1905 See :hg:`help -e clonebundles` for more.
1925 See :hg:`help -e clonebundles` for more.
1906
1926
1907 Examples:
1927 Examples:
1908
1928
1909 - clone a remote repository to a new directory named hg/::
1929 - clone a remote repository to a new directory named hg/::
1910
1930
1911 hg clone https://www.mercurial-scm.org/repo/hg/
1931 hg clone https://www.mercurial-scm.org/repo/hg/
1912
1932
1913 - create a lightweight local clone::
1933 - create a lightweight local clone::
1914
1934
1915 hg clone project/ project-feature/
1935 hg clone project/ project-feature/
1916
1936
1917 - clone from an absolute path on an ssh server (note double-slash)::
1937 - clone from an absolute path on an ssh server (note double-slash)::
1918
1938
1919 hg clone ssh://user@server//home/projects/alpha/
1939 hg clone ssh://user@server//home/projects/alpha/
1920
1940
1921 - do a streaming clone while checking out a specified version::
1941 - do a streaming clone while checking out a specified version::
1922
1942
1923 hg clone --stream http://server/repo -u 1.5
1943 hg clone --stream http://server/repo -u 1.5
1924
1944
1925 - create a repository without changesets after a particular revision::
1945 - create a repository without changesets after a particular revision::
1926
1946
1927 hg clone -r 04e544 experimental/ good/
1947 hg clone -r 04e544 experimental/ good/
1928
1948
1929 - clone (and track) a particular named branch::
1949 - clone (and track) a particular named branch::
1930
1950
1931 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1951 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1932
1952
1933 See :hg:`help urls` for details on specifying URLs.
1953 See :hg:`help urls` for details on specifying URLs.
1934
1954
1935 Returns 0 on success.
1955 Returns 0 on success.
1936 """
1956 """
1937 opts = pycompat.byteskwargs(opts)
1957 opts = pycompat.byteskwargs(opts)
1938 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1958 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1939
1959
1940 # --include/--exclude can come from narrow or sparse.
1960 # --include/--exclude can come from narrow or sparse.
1941 includepats, excludepats = None, None
1961 includepats, excludepats = None, None
1942
1962
1943 # hg.clone() differentiates between None and an empty set. So make sure
1963 # hg.clone() differentiates between None and an empty set. So make sure
1944 # patterns are sets if narrow is requested without patterns.
1964 # patterns are sets if narrow is requested without patterns.
1945 if opts.get(b'narrow'):
1965 if opts.get(b'narrow'):
1946 includepats = set()
1966 includepats = set()
1947 excludepats = set()
1967 excludepats = set()
1948
1968
1949 if opts.get(b'include'):
1969 if opts.get(b'include'):
1950 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1970 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1951 if opts.get(b'exclude'):
1971 if opts.get(b'exclude'):
1952 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1972 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1953
1973
1954 r = hg.clone(
1974 r = hg.clone(
1955 ui,
1975 ui,
1956 opts,
1976 opts,
1957 source,
1977 source,
1958 dest,
1978 dest,
1959 pull=opts.get(b'pull'),
1979 pull=opts.get(b'pull'),
1960 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1980 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1961 revs=opts.get(b'rev'),
1981 revs=opts.get(b'rev'),
1962 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1982 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1963 branch=opts.get(b'branch'),
1983 branch=opts.get(b'branch'),
1964 shareopts=opts.get(b'shareopts'),
1984 shareopts=opts.get(b'shareopts'),
1965 storeincludepats=includepats,
1985 storeincludepats=includepats,
1966 storeexcludepats=excludepats,
1986 storeexcludepats=excludepats,
1967 depth=opts.get(b'depth') or None,
1987 depth=opts.get(b'depth') or None,
1968 )
1988 )
1969
1989
1970 return r is None
1990 return r is None
1971
1991
1972
1992
1973 @command(
1993 @command(
1974 b'commit|ci',
1994 b'commit|ci',
1975 [
1995 [
1976 (
1996 (
1977 b'A',
1997 b'A',
1978 b'addremove',
1998 b'addremove',
1979 None,
1999 None,
1980 _(b'mark new/missing files as added/removed before committing'),
2000 _(b'mark new/missing files as added/removed before committing'),
1981 ),
2001 ),
1982 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
2002 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1983 (b'', b'amend', None, _(b'amend the parent of the working directory')),
2003 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1984 (b's', b'secret', None, _(b'use the secret phase for committing')),
2004 (b's', b'secret', None, _(b'use the secret phase for committing')),
1985 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
2005 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1986 (
2006 (
1987 b'',
2007 b'',
1988 b'force-close-branch',
2008 b'force-close-branch',
1989 None,
2009 None,
1990 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
2010 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1991 ),
2011 ),
1992 (b'i', b'interactive', None, _(b'use interactive mode')),
2012 (b'i', b'interactive', None, _(b'use interactive mode')),
1993 ]
2013 ]
1994 + walkopts
2014 + walkopts
1995 + commitopts
2015 + commitopts
1996 + commitopts2
2016 + commitopts2
1997 + subrepoopts,
2017 + subrepoopts,
1998 _(b'[OPTION]... [FILE]...'),
2018 _(b'[OPTION]... [FILE]...'),
1999 helpcategory=command.CATEGORY_COMMITTING,
2019 helpcategory=command.CATEGORY_COMMITTING,
2000 helpbasic=True,
2020 helpbasic=True,
2001 inferrepo=True,
2021 inferrepo=True,
2002 )
2022 )
2003 def commit(ui, repo, *pats, **opts):
2023 def commit(ui, repo, *pats, **opts):
2004 """commit the specified files or all outstanding changes
2024 """commit the specified files or all outstanding changes
2005
2025
2006 Commit changes to the given files into the repository. Unlike a
2026 Commit changes to the given files into the repository. Unlike a
2007 centralized SCM, this operation is a local operation. See
2027 centralized SCM, this operation is a local operation. See
2008 :hg:`push` for a way to actively distribute your changes.
2028 :hg:`push` for a way to actively distribute your changes.
2009
2029
2010 If a list of files is omitted, all changes reported by :hg:`status`
2030 If a list of files is omitted, all changes reported by :hg:`status`
2011 will be committed.
2031 will be committed.
2012
2032
2013 If you are committing the result of a merge, do not provide any
2033 If you are committing the result of a merge, do not provide any
2014 filenames or -I/-X filters.
2034 filenames or -I/-X filters.
2015
2035
2016 If no commit message is specified, Mercurial starts your
2036 If no commit message is specified, Mercurial starts your
2017 configured editor where you can enter a message. In case your
2037 configured editor where you can enter a message. In case your
2018 commit fails, you will find a backup of your message in
2038 commit fails, you will find a backup of your message in
2019 ``.hg/last-message.txt``.
2039 ``.hg/last-message.txt``.
2020
2040
2021 The --close-branch flag can be used to mark the current branch
2041 The --close-branch flag can be used to mark the current branch
2022 head closed. When all heads of a branch are closed, the branch
2042 head closed. When all heads of a branch are closed, the branch
2023 will be considered closed and no longer listed.
2043 will be considered closed and no longer listed.
2024
2044
2025 The --amend flag can be used to amend the parent of the
2045 The --amend flag can be used to amend the parent of the
2026 working directory with a new commit that contains the changes
2046 working directory with a new commit that contains the changes
2027 in the parent in addition to those currently reported by :hg:`status`,
2047 in the parent in addition to those currently reported by :hg:`status`,
2028 if there are any. The old commit is stored in a backup bundle in
2048 if there are any. The old commit is stored in a backup bundle in
2029 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2049 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2030 on how to restore it).
2050 on how to restore it).
2031
2051
2032 Message, user and date are taken from the amended commit unless
2052 Message, user and date are taken from the amended commit unless
2033 specified. When a message isn't specified on the command line,
2053 specified. When a message isn't specified on the command line,
2034 the editor will open with the message of the amended commit.
2054 the editor will open with the message of the amended commit.
2035
2055
2036 It is not possible to amend public changesets (see :hg:`help phases`)
2056 It is not possible to amend public changesets (see :hg:`help phases`)
2037 or changesets that have children.
2057 or changesets that have children.
2038
2058
2039 See :hg:`help dates` for a list of formats valid for -d/--date.
2059 See :hg:`help dates` for a list of formats valid for -d/--date.
2040
2060
2041 Returns 0 on success, 1 if nothing changed.
2061 Returns 0 on success, 1 if nothing changed.
2042
2062
2043 .. container:: verbose
2063 .. container:: verbose
2044
2064
2045 Examples:
2065 Examples:
2046
2066
2047 - commit all files ending in .py::
2067 - commit all files ending in .py::
2048
2068
2049 hg commit --include "set:**.py"
2069 hg commit --include "set:**.py"
2050
2070
2051 - commit all non-binary files::
2071 - commit all non-binary files::
2052
2072
2053 hg commit --exclude "set:binary()"
2073 hg commit --exclude "set:binary()"
2054
2074
2055 - amend the current commit and set the date to now::
2075 - amend the current commit and set the date to now::
2056
2076
2057 hg commit --amend --date now
2077 hg commit --amend --date now
2058 """
2078 """
2059 with repo.wlock(), repo.lock():
2079 with repo.wlock(), repo.lock():
2060 return _docommit(ui, repo, *pats, **opts)
2080 return _docommit(ui, repo, *pats, **opts)
2061
2081
2062
2082
2063 def _docommit(ui, repo, *pats, **opts):
2083 def _docommit(ui, repo, *pats, **opts):
2064 if opts.get('interactive'):
2084 if opts.get('interactive'):
2065 opts.pop('interactive')
2085 opts.pop('interactive')
2066 ret = cmdutil.dorecord(
2086 ret = cmdutil.dorecord(
2067 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2087 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2068 )
2088 )
2069 # ret can be 0 (no changes to record) or the value returned by
2089 # ret can be 0 (no changes to record) or the value returned by
2070 # commit(), 1 if nothing changed or None on success.
2090 # commit(), 1 if nothing changed or None on success.
2071 return 1 if ret == 0 else ret
2091 return 1 if ret == 0 else ret
2072
2092
2073 if opts.get('subrepos'):
2093 if opts.get('subrepos'):
2074 cmdutil.check_incompatible_arguments(opts, 'subrepos', ['amend'])
2094 cmdutil.check_incompatible_arguments(opts, 'subrepos', ['amend'])
2075 # Let --subrepos on the command line override config setting.
2095 # Let --subrepos on the command line override config setting.
2076 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2096 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2077
2097
2078 cmdutil.checkunfinished(repo, commit=True)
2098 cmdutil.checkunfinished(repo, commit=True)
2079
2099
2080 branch = repo[None].branch()
2100 branch = repo[None].branch()
2081 bheads = repo.branchheads(branch)
2101 bheads = repo.branchheads(branch)
2082 tip = repo.changelog.tip()
2102 tip = repo.changelog.tip()
2083
2103
2084 extra = {}
2104 extra = {}
2085 if opts.get('close_branch') or opts.get('force_close_branch'):
2105 if opts.get('close_branch') or opts.get('force_close_branch'):
2086 extra[b'close'] = b'1'
2106 extra[b'close'] = b'1'
2087
2107
2088 if repo[b'.'].closesbranch():
2108 if repo[b'.'].closesbranch():
2089 # Not ideal, but let us do an extra status early to prevent early
2109 # Not ideal, but let us do an extra status early to prevent early
2090 # bail out.
2110 # bail out.
2091 matcher = scmutil.match(repo[None], pats, opts)
2111 matcher = scmutil.match(repo[None], pats, opts)
2092 s = repo.status(match=matcher)
2112 s = repo.status(match=matcher)
2093 if s.modified or s.added or s.removed:
2113 if s.modified or s.added or s.removed:
2094 bheads = repo.branchheads(branch, closed=True)
2114 bheads = repo.branchheads(branch, closed=True)
2095 else:
2115 else:
2096 msg = _(b'current revision is already a branch closing head')
2116 msg = _(b'current revision is already a branch closing head')
2097 raise error.InputError(msg)
2117 raise error.InputError(msg)
2098
2118
2099 if not bheads:
2119 if not bheads:
2100 raise error.InputError(
2120 raise error.InputError(
2101 _(b'branch "%s" has no heads to close') % branch
2121 _(b'branch "%s" has no heads to close') % branch
2102 )
2122 )
2103 elif (
2123 elif (
2104 branch == repo[b'.'].branch()
2124 branch == repo[b'.'].branch()
2105 and repo[b'.'].node() not in bheads
2125 and repo[b'.'].node() not in bheads
2106 and not opts.get('force_close_branch')
2126 and not opts.get('force_close_branch')
2107 ):
2127 ):
2108 hint = _(
2128 hint = _(
2109 b'use --force-close-branch to close branch from a non-head'
2129 b'use --force-close-branch to close branch from a non-head'
2110 b' changeset'
2130 b' changeset'
2111 )
2131 )
2112 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2132 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2113 elif opts.get('amend'):
2133 elif opts.get('amend'):
2114 if (
2134 if (
2115 repo[b'.'].p1().branch() != branch
2135 repo[b'.'].p1().branch() != branch
2116 and repo[b'.'].p2().branch() != branch
2136 and repo[b'.'].p2().branch() != branch
2117 ):
2137 ):
2118 raise error.InputError(_(b'can only close branch heads'))
2138 raise error.InputError(_(b'can only close branch heads'))
2119
2139
2120 if opts.get('amend'):
2140 if opts.get('amend'):
2121 if ui.configbool(b'ui', b'commitsubrepos'):
2141 if ui.configbool(b'ui', b'commitsubrepos'):
2122 raise error.InputError(
2142 raise error.InputError(
2123 _(b'cannot amend with ui.commitsubrepos enabled')
2143 _(b'cannot amend with ui.commitsubrepos enabled')
2124 )
2144 )
2125
2145
2126 old = repo[b'.']
2146 old = repo[b'.']
2127 rewriteutil.precheck(repo, [old.rev()], b'amend')
2147 rewriteutil.precheck(repo, [old.rev()], b'amend')
2128
2148
2129 # Currently histedit gets confused if an amend happens while histedit
2149 # Currently histedit gets confused if an amend happens while histedit
2130 # is in progress. Since we have a checkunfinished command, we are
2150 # is in progress. Since we have a checkunfinished command, we are
2131 # temporarily honoring it.
2151 # temporarily honoring it.
2132 #
2152 #
2133 # Note: eventually this guard will be removed. Please do not expect
2153 # Note: eventually this guard will be removed. Please do not expect
2134 # this behavior to remain.
2154 # this behavior to remain.
2135 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2155 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2136 cmdutil.checkunfinished(repo)
2156 cmdutil.checkunfinished(repo)
2137
2157
2138 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2158 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2139 opts = pycompat.byteskwargs(opts)
2159 opts = pycompat.byteskwargs(opts)
2140 if node == old.node():
2160 if node == old.node():
2141 ui.status(_(b"nothing changed\n"))
2161 ui.status(_(b"nothing changed\n"))
2142 return 1
2162 return 1
2143 else:
2163 else:
2144
2164
2145 def commitfunc(ui, repo, message, match, opts):
2165 def commitfunc(ui, repo, message, match, opts):
2146 overrides = {}
2166 overrides = {}
2147 if opts.get(b'secret'):
2167 if opts.get(b'secret'):
2148 overrides[(b'phases', b'new-commit')] = b'secret'
2168 overrides[(b'phases', b'new-commit')] = b'secret'
2149
2169
2150 baseui = repo.baseui
2170 baseui = repo.baseui
2151 with baseui.configoverride(overrides, b'commit'):
2171 with baseui.configoverride(overrides, b'commit'):
2152 with ui.configoverride(overrides, b'commit'):
2172 with ui.configoverride(overrides, b'commit'):
2153 editform = cmdutil.mergeeditform(
2173 editform = cmdutil.mergeeditform(
2154 repo[None], b'commit.normal'
2174 repo[None], b'commit.normal'
2155 )
2175 )
2156 editor = cmdutil.getcommiteditor(
2176 editor = cmdutil.getcommiteditor(
2157 editform=editform, **pycompat.strkwargs(opts)
2177 editform=editform, **pycompat.strkwargs(opts)
2158 )
2178 )
2159 return repo.commit(
2179 return repo.commit(
2160 message,
2180 message,
2161 opts.get(b'user'),
2181 opts.get(b'user'),
2162 opts.get(b'date'),
2182 opts.get(b'date'),
2163 match,
2183 match,
2164 editor=editor,
2184 editor=editor,
2165 extra=extra,
2185 extra=extra,
2166 )
2186 )
2167
2187
2168 opts = pycompat.byteskwargs(opts)
2188 opts = pycompat.byteskwargs(opts)
2169 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2189 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2170
2190
2171 if not node:
2191 if not node:
2172 stat = cmdutil.postcommitstatus(repo, pats, opts)
2192 stat = cmdutil.postcommitstatus(repo, pats, opts)
2173 if stat.deleted:
2193 if stat.deleted:
2174 ui.status(
2194 ui.status(
2175 _(
2195 _(
2176 b"nothing changed (%d missing files, see "
2196 b"nothing changed (%d missing files, see "
2177 b"'hg status')\n"
2197 b"'hg status')\n"
2178 )
2198 )
2179 % len(stat.deleted)
2199 % len(stat.deleted)
2180 )
2200 )
2181 else:
2201 else:
2182 ui.status(_(b"nothing changed\n"))
2202 ui.status(_(b"nothing changed\n"))
2183 return 1
2203 return 1
2184
2204
2185 cmdutil.commitstatus(repo, node, branch, bheads, tip, opts)
2205 cmdutil.commitstatus(repo, node, branch, bheads, tip, opts)
2186
2206
2187 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2207 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2188 status(
2208 status(
2189 ui,
2209 ui,
2190 repo,
2210 repo,
2191 modified=True,
2211 modified=True,
2192 added=True,
2212 added=True,
2193 removed=True,
2213 removed=True,
2194 deleted=True,
2214 deleted=True,
2195 unknown=True,
2215 unknown=True,
2196 subrepos=opts.get(b'subrepos'),
2216 subrepos=opts.get(b'subrepos'),
2197 )
2217 )
2198
2218
2199
2219
2200 @command(
2220 @command(
2201 b'config|showconfig|debugconfig',
2221 b'config|showconfig|debugconfig',
2202 [
2222 [
2203 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2223 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2204 # This is experimental because we need
2224 # This is experimental because we need
2205 # * reasonable behavior around aliases,
2225 # * reasonable behavior around aliases,
2206 # * decide if we display [debug] [experimental] and [devel] section par
2226 # * decide if we display [debug] [experimental] and [devel] section par
2207 # default
2227 # default
2208 # * some way to display "generic" config entry (the one matching
2228 # * some way to display "generic" config entry (the one matching
2209 # regexp,
2229 # regexp,
2210 # * proper display of the different value type
2230 # * proper display of the different value type
2211 # * a better way to handle <DYNAMIC> values (and variable types),
2231 # * a better way to handle <DYNAMIC> values (and variable types),
2212 # * maybe some type information ?
2232 # * maybe some type information ?
2213 (
2233 (
2214 b'',
2234 b'',
2215 b'exp-all-known',
2235 b'exp-all-known',
2216 None,
2236 None,
2217 _(b'show all known config option (EXPERIMENTAL)'),
2237 _(b'show all known config option (EXPERIMENTAL)'),
2218 ),
2238 ),
2219 (b'e', b'edit', None, _(b'edit user config')),
2239 (b'e', b'edit', None, _(b'edit user config')),
2220 (b'l', b'local', None, _(b'edit repository config')),
2240 (b'l', b'local', None, _(b'edit repository config')),
2221 (b'', b'source', None, _(b'show source of configuration value')),
2241 (b'', b'source', None, _(b'show source of configuration value')),
2222 (
2242 (
2223 b'',
2243 b'',
2224 b'shared',
2244 b'shared',
2225 None,
2245 None,
2226 _(b'edit shared source repository config (EXPERIMENTAL)'),
2246 _(b'edit shared source repository config (EXPERIMENTAL)'),
2227 ),
2247 ),
2228 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2248 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2229 (b'g', b'global', None, _(b'edit global config')),
2249 (b'g', b'global', None, _(b'edit global config')),
2230 ]
2250 ]
2231 + formatteropts,
2251 + formatteropts,
2232 _(b'[-u] [NAME]...'),
2252 _(b'[-u] [NAME]...'),
2233 helpcategory=command.CATEGORY_HELP,
2253 helpcategory=command.CATEGORY_HELP,
2234 optionalrepo=True,
2254 optionalrepo=True,
2235 intents={INTENT_READONLY},
2255 intents={INTENT_READONLY},
2236 )
2256 )
2237 def config(ui, repo, *values, **opts):
2257 def config(ui, repo, *values, **opts):
2238 """show combined config settings from all hgrc files
2258 """show combined config settings from all hgrc files
2239
2259
2240 With no arguments, print names and values of all config items.
2260 With no arguments, print names and values of all config items.
2241
2261
2242 With one argument of the form section.name, print just the value
2262 With one argument of the form section.name, print just the value
2243 of that config item.
2263 of that config item.
2244
2264
2245 With multiple arguments, print names and values of all config
2265 With multiple arguments, print names and values of all config
2246 items with matching section names or section.names.
2266 items with matching section names or section.names.
2247
2267
2248 With --edit, start an editor on the user-level config file. With
2268 With --edit, start an editor on the user-level config file. With
2249 --global, edit the system-wide config file. With --local, edit the
2269 --global, edit the system-wide config file. With --local, edit the
2250 repository-level config file.
2270 repository-level config file.
2251
2271
2252 With --source, the source (filename and line number) is printed
2272 With --source, the source (filename and line number) is printed
2253 for each config item.
2273 for each config item.
2254
2274
2255 See :hg:`help config` for more information about config files.
2275 See :hg:`help config` for more information about config files.
2256
2276
2257 .. container:: verbose
2277 .. container:: verbose
2258
2278
2259 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2279 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2260 This file is not shared across shares when in share-safe mode.
2280 This file is not shared across shares when in share-safe mode.
2261
2281
2262 Template:
2282 Template:
2263
2283
2264 The following keywords are supported. See also :hg:`help templates`.
2284 The following keywords are supported. See also :hg:`help templates`.
2265
2285
2266 :name: String. Config name.
2286 :name: String. Config name.
2267 :source: String. Filename and line number where the item is defined.
2287 :source: String. Filename and line number where the item is defined.
2268 :value: String. Config value.
2288 :value: String. Config value.
2269
2289
2270 The --shared flag can be used to edit the config file of shared source
2290 The --shared flag can be used to edit the config file of shared source
2271 repository. It only works when you have shared using the experimental
2291 repository. It only works when you have shared using the experimental
2272 share safe feature.
2292 share safe feature.
2273
2293
2274 Returns 0 on success, 1 if NAME does not exist.
2294 Returns 0 on success, 1 if NAME does not exist.
2275
2295
2276 """
2296 """
2277
2297
2278 opts = pycompat.byteskwargs(opts)
2298 opts = pycompat.byteskwargs(opts)
2279 editopts = (b'edit', b'local', b'global', b'shared', b'non_shared')
2299 editopts = (b'edit', b'local', b'global', b'shared', b'non_shared')
2280 if any(opts.get(o) for o in editopts):
2300 if any(opts.get(o) for o in editopts):
2281 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2301 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2282 if opts.get(b'local'):
2302 if opts.get(b'local'):
2283 if not repo:
2303 if not repo:
2284 raise error.InputError(
2304 raise error.InputError(
2285 _(b"can't use --local outside a repository")
2305 _(b"can't use --local outside a repository")
2286 )
2306 )
2287 paths = [repo.vfs.join(b'hgrc')]
2307 paths = [repo.vfs.join(b'hgrc')]
2288 elif opts.get(b'global'):
2308 elif opts.get(b'global'):
2289 paths = rcutil.systemrcpath()
2309 paths = rcutil.systemrcpath()
2290 elif opts.get(b'shared'):
2310 elif opts.get(b'shared'):
2291 if not repo.shared():
2311 if not repo.shared():
2292 raise error.InputError(
2312 raise error.InputError(
2293 _(b"repository is not shared; can't use --shared")
2313 _(b"repository is not shared; can't use --shared")
2294 )
2314 )
2295 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2315 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2296 raise error.InputError(
2316 raise error.InputError(
2297 _(
2317 _(
2298 b"share safe feature not enabled; "
2318 b"share safe feature not enabled; "
2299 b"unable to edit shared source repository config"
2319 b"unable to edit shared source repository config"
2300 )
2320 )
2301 )
2321 )
2302 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2322 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2303 elif opts.get(b'non_shared'):
2323 elif opts.get(b'non_shared'):
2304 paths = [repo.vfs.join(b'hgrc-not-shared')]
2324 paths = [repo.vfs.join(b'hgrc-not-shared')]
2305 else:
2325 else:
2306 paths = rcutil.userrcpath()
2326 paths = rcutil.userrcpath()
2307
2327
2308 for f in paths:
2328 for f in paths:
2309 if os.path.exists(f):
2329 if os.path.exists(f):
2310 break
2330 break
2311 else:
2331 else:
2312 if opts.get(b'global'):
2332 if opts.get(b'global'):
2313 samplehgrc = uimod.samplehgrcs[b'global']
2333 samplehgrc = uimod.samplehgrcs[b'global']
2314 elif opts.get(b'local'):
2334 elif opts.get(b'local'):
2315 samplehgrc = uimod.samplehgrcs[b'local']
2335 samplehgrc = uimod.samplehgrcs[b'local']
2316 else:
2336 else:
2317 samplehgrc = uimod.samplehgrcs[b'user']
2337 samplehgrc = uimod.samplehgrcs[b'user']
2318
2338
2319 f = paths[0]
2339 f = paths[0]
2320 fp = open(f, b"wb")
2340 fp = open(f, b"wb")
2321 fp.write(util.tonativeeol(samplehgrc))
2341 fp.write(util.tonativeeol(samplehgrc))
2322 fp.close()
2342 fp.close()
2323
2343
2324 editor = ui.geteditor()
2344 editor = ui.geteditor()
2325 ui.system(
2345 ui.system(
2326 b"%s \"%s\"" % (editor, f),
2346 b"%s \"%s\"" % (editor, f),
2327 onerr=error.InputError,
2347 onerr=error.InputError,
2328 errprefix=_(b"edit failed"),
2348 errprefix=_(b"edit failed"),
2329 blockedtag=b'config_edit',
2349 blockedtag=b'config_edit',
2330 )
2350 )
2331 return
2351 return
2332 ui.pager(b'config')
2352 ui.pager(b'config')
2333 fm = ui.formatter(b'config', opts)
2353 fm = ui.formatter(b'config', opts)
2334 for t, f in rcutil.rccomponents():
2354 for t, f in rcutil.rccomponents():
2335 if t == b'path':
2355 if t == b'path':
2336 ui.debug(b'read config from: %s\n' % f)
2356 ui.debug(b'read config from: %s\n' % f)
2337 elif t == b'resource':
2357 elif t == b'resource':
2338 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2358 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2339 elif t == b'items':
2359 elif t == b'items':
2340 # Don't print anything for 'items'.
2360 # Don't print anything for 'items'.
2341 pass
2361 pass
2342 else:
2362 else:
2343 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2363 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2344 untrusted = bool(opts.get(b'untrusted'))
2364 untrusted = bool(opts.get(b'untrusted'))
2345
2365
2346 selsections = selentries = []
2366 selsections = selentries = []
2347 if values:
2367 if values:
2348 selsections = [v for v in values if b'.' not in v]
2368 selsections = [v for v in values if b'.' not in v]
2349 selentries = [v for v in values if b'.' in v]
2369 selentries = [v for v in values if b'.' in v]
2350 uniquesel = len(selentries) == 1 and not selsections
2370 uniquesel = len(selentries) == 1 and not selsections
2351 selsections = set(selsections)
2371 selsections = set(selsections)
2352 selentries = set(selentries)
2372 selentries = set(selentries)
2353
2373
2354 matched = False
2374 matched = False
2355 all_known = opts[b'exp_all_known']
2375 all_known = opts[b'exp_all_known']
2356 show_source = ui.debugflag or opts.get(b'source')
2376 show_source = ui.debugflag or opts.get(b'source')
2357 entries = ui.walkconfig(untrusted=untrusted, all_known=all_known)
2377 entries = ui.walkconfig(untrusted=untrusted, all_known=all_known)
2358 for section, name, value in entries:
2378 for section, name, value in entries:
2359 source = ui.configsource(section, name, untrusted)
2379 source = ui.configsource(section, name, untrusted)
2360 value = pycompat.bytestr(value)
2380 value = pycompat.bytestr(value)
2361 defaultvalue = ui.configdefault(section, name)
2381 defaultvalue = ui.configdefault(section, name)
2362 if fm.isplain():
2382 if fm.isplain():
2363 source = source or b'none'
2383 source = source or b'none'
2364 value = value.replace(b'\n', b'\\n')
2384 value = value.replace(b'\n', b'\\n')
2365 entryname = section + b'.' + name
2385 entryname = section + b'.' + name
2366 if values and not (section in selsections or entryname in selentries):
2386 if values and not (section in selsections or entryname in selentries):
2367 continue
2387 continue
2368 fm.startitem()
2388 fm.startitem()
2369 fm.condwrite(show_source, b'source', b'%s: ', source)
2389 fm.condwrite(show_source, b'source', b'%s: ', source)
2370 if uniquesel:
2390 if uniquesel:
2371 fm.data(name=entryname)
2391 fm.data(name=entryname)
2372 fm.write(b'value', b'%s\n', value)
2392 fm.write(b'value', b'%s\n', value)
2373 else:
2393 else:
2374 fm.write(b'name value', b'%s=%s\n', entryname, value)
2394 fm.write(b'name value', b'%s=%s\n', entryname, value)
2375 if formatter.isprintable(defaultvalue):
2395 if formatter.isprintable(defaultvalue):
2376 fm.data(defaultvalue=defaultvalue)
2396 fm.data(defaultvalue=defaultvalue)
2377 elif isinstance(defaultvalue, list) and all(
2397 elif isinstance(defaultvalue, list) and all(
2378 formatter.isprintable(e) for e in defaultvalue
2398 formatter.isprintable(e) for e in defaultvalue
2379 ):
2399 ):
2380 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2400 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2381 # TODO: no idea how to process unsupported defaultvalue types
2401 # TODO: no idea how to process unsupported defaultvalue types
2382 matched = True
2402 matched = True
2383 fm.end()
2403 fm.end()
2384 if matched:
2404 if matched:
2385 return 0
2405 return 0
2386 return 1
2406 return 1
2387
2407
2388
2408
2389 @command(
2409 @command(
2390 b'continue',
2410 b'continue',
2391 dryrunopts,
2411 dryrunopts,
2392 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2412 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2393 helpbasic=True,
2413 helpbasic=True,
2394 )
2414 )
2395 def continuecmd(ui, repo, **opts):
2415 def continuecmd(ui, repo, **opts):
2396 """resumes an interrupted operation (EXPERIMENTAL)
2416 """resumes an interrupted operation (EXPERIMENTAL)
2397
2417
2398 Finishes a multistep operation like graft, histedit, rebase, merge,
2418 Finishes a multistep operation like graft, histedit, rebase, merge,
2399 and unshelve if they are in an interrupted state.
2419 and unshelve if they are in an interrupted state.
2400
2420
2401 use --dry-run/-n to dry run the command.
2421 use --dry-run/-n to dry run the command.
2402 """
2422 """
2403 dryrun = opts.get('dry_run')
2423 dryrun = opts.get('dry_run')
2404 contstate = cmdutil.getunfinishedstate(repo)
2424 contstate = cmdutil.getunfinishedstate(repo)
2405 if not contstate:
2425 if not contstate:
2406 raise error.StateError(_(b'no operation in progress'))
2426 raise error.StateError(_(b'no operation in progress'))
2407 if not contstate.continuefunc:
2427 if not contstate.continuefunc:
2408 raise error.StateError(
2428 raise error.StateError(
2409 (
2429 (
2410 _(b"%s in progress but does not support 'hg continue'")
2430 _(b"%s in progress but does not support 'hg continue'")
2411 % (contstate._opname)
2431 % (contstate._opname)
2412 ),
2432 ),
2413 hint=contstate.continuemsg(),
2433 hint=contstate.continuemsg(),
2414 )
2434 )
2415 if dryrun:
2435 if dryrun:
2416 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2436 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2417 return
2437 return
2418 return contstate.continuefunc(ui, repo)
2438 return contstate.continuefunc(ui, repo)
2419
2439
2420
2440
2421 @command(
2441 @command(
2422 b'copy|cp',
2442 b'copy|cp',
2423 [
2443 [
2424 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2444 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2425 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2445 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2426 (
2446 (
2427 b'',
2447 b'',
2428 b'at-rev',
2448 b'at-rev',
2429 b'',
2449 b'',
2430 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2450 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2431 _(b'REV'),
2451 _(b'REV'),
2432 ),
2452 ),
2433 (
2453 (
2434 b'f',
2454 b'f',
2435 b'force',
2455 b'force',
2436 None,
2456 None,
2437 _(b'forcibly copy over an existing managed file'),
2457 _(b'forcibly copy over an existing managed file'),
2438 ),
2458 ),
2439 ]
2459 ]
2440 + walkopts
2460 + walkopts
2441 + dryrunopts,
2461 + dryrunopts,
2442 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2462 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2443 helpcategory=command.CATEGORY_FILE_CONTENTS,
2463 helpcategory=command.CATEGORY_FILE_CONTENTS,
2444 )
2464 )
2445 def copy(ui, repo, *pats, **opts):
2465 def copy(ui, repo, *pats, **opts):
2446 """mark files as copied for the next commit
2466 """mark files as copied for the next commit
2447
2467
2448 Mark dest as having copies of source files. If dest is a
2468 Mark dest as having copies of source files. If dest is a
2449 directory, copies are put in that directory. If dest is a file,
2469 directory, copies are put in that directory. If dest is a file,
2450 the source must be a single file.
2470 the source must be a single file.
2451
2471
2452 By default, this command copies the contents of files as they
2472 By default, this command copies the contents of files as they
2453 exist in the working directory. If invoked with -A/--after, the
2473 exist in the working directory. If invoked with -A/--after, the
2454 operation is recorded, but no copying is performed.
2474 operation is recorded, but no copying is performed.
2455
2475
2456 To undo marking a destination file as copied, use --forget. With that
2476 To undo marking a destination file as copied, use --forget. With that
2457 option, all given (positional) arguments are unmarked as copies. The
2477 option, all given (positional) arguments are unmarked as copies. The
2458 destination file(s) will be left in place (still tracked). Note that
2478 destination file(s) will be left in place (still tracked). Note that
2459 :hg:`copy --forget` behaves the same way as :hg:`rename --forget`.
2479 :hg:`copy --forget` behaves the same way as :hg:`rename --forget`.
2460
2480
2461 This command takes effect with the next commit by default.
2481 This command takes effect with the next commit by default.
2462
2482
2463 Returns 0 on success, 1 if errors are encountered.
2483 Returns 0 on success, 1 if errors are encountered.
2464 """
2484 """
2465 opts = pycompat.byteskwargs(opts)
2485 opts = pycompat.byteskwargs(opts)
2466 with repo.wlock():
2486 with repo.wlock():
2467 return cmdutil.copy(ui, repo, pats, opts)
2487 return cmdutil.copy(ui, repo, pats, opts)
2468
2488
2469
2489
2470 @command(
2490 @command(
2471 b'debugcommands',
2491 b'debugcommands',
2472 [],
2492 [],
2473 _(b'[COMMAND]'),
2493 _(b'[COMMAND]'),
2474 helpcategory=command.CATEGORY_HELP,
2494 helpcategory=command.CATEGORY_HELP,
2475 norepo=True,
2495 norepo=True,
2476 )
2496 )
2477 def debugcommands(ui, cmd=b'', *args):
2497 def debugcommands(ui, cmd=b'', *args):
2478 """list all available commands and options"""
2498 """list all available commands and options"""
2479 for cmd, vals in sorted(table.items()):
2499 for cmd, vals in sorted(table.items()):
2480 cmd = cmd.split(b'|')[0]
2500 cmd = cmd.split(b'|')[0]
2481 opts = b', '.join([i[1] for i in vals[1]])
2501 opts = b', '.join([i[1] for i in vals[1]])
2482 ui.write(b'%s: %s\n' % (cmd, opts))
2502 ui.write(b'%s: %s\n' % (cmd, opts))
2483
2503
2484
2504
2485 @command(
2505 @command(
2486 b'debugcomplete',
2506 b'debugcomplete',
2487 [(b'o', b'options', None, _(b'show the command options'))],
2507 [(b'o', b'options', None, _(b'show the command options'))],
2488 _(b'[-o] CMD'),
2508 _(b'[-o] CMD'),
2489 helpcategory=command.CATEGORY_HELP,
2509 helpcategory=command.CATEGORY_HELP,
2490 norepo=True,
2510 norepo=True,
2491 )
2511 )
2492 def debugcomplete(ui, cmd=b'', **opts):
2512 def debugcomplete(ui, cmd=b'', **opts):
2493 """returns the completion list associated with the given command"""
2513 """returns the completion list associated with the given command"""
2494
2514
2495 if opts.get('options'):
2515 if opts.get('options'):
2496 options = []
2516 options = []
2497 otables = [globalopts]
2517 otables = [globalopts]
2498 if cmd:
2518 if cmd:
2499 aliases, entry = cmdutil.findcmd(cmd, table, False)
2519 aliases, entry = cmdutil.findcmd(cmd, table, False)
2500 otables.append(entry[1])
2520 otables.append(entry[1])
2501 for t in otables:
2521 for t in otables:
2502 for o in t:
2522 for o in t:
2503 if b"(DEPRECATED)" in o[3]:
2523 if b"(DEPRECATED)" in o[3]:
2504 continue
2524 continue
2505 if o[0]:
2525 if o[0]:
2506 options.append(b'-%s' % o[0])
2526 options.append(b'-%s' % o[0])
2507 options.append(b'--%s' % o[1])
2527 options.append(b'--%s' % o[1])
2508 ui.write(b"%s\n" % b"\n".join(options))
2528 ui.write(b"%s\n" % b"\n".join(options))
2509 return
2529 return
2510
2530
2511 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2531 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2512 if ui.verbose:
2532 if ui.verbose:
2513 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2533 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2514 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2534 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2515
2535
2516
2536
2517 @command(
2537 @command(
2518 b'diff',
2538 b'diff',
2519 [
2539 [
2520 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2540 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2521 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2541 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2522 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2542 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2523 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2543 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2524 ]
2544 ]
2525 + diffopts
2545 + diffopts
2526 + diffopts2
2546 + diffopts2
2527 + walkopts
2547 + walkopts
2528 + subrepoopts,
2548 + subrepoopts,
2529 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2549 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2530 helpcategory=command.CATEGORY_FILE_CONTENTS,
2550 helpcategory=command.CATEGORY_FILE_CONTENTS,
2531 helpbasic=True,
2551 helpbasic=True,
2532 inferrepo=True,
2552 inferrepo=True,
2533 intents={INTENT_READONLY},
2553 intents={INTENT_READONLY},
2534 )
2554 )
2535 def diff(ui, repo, *pats, **opts):
2555 def diff(ui, repo, *pats, **opts):
2536 """diff repository (or selected files)
2556 """diff repository (or selected files)
2537
2557
2538 Show differences between revisions for the specified files.
2558 Show differences between revisions for the specified files.
2539
2559
2540 Differences between files are shown using the unified diff format.
2560 Differences between files are shown using the unified diff format.
2541
2561
2542 .. note::
2562 .. note::
2543
2563
2544 :hg:`diff` may generate unexpected results for merges, as it will
2564 :hg:`diff` may generate unexpected results for merges, as it will
2545 default to comparing against the working directory's first
2565 default to comparing against the working directory's first
2546 parent changeset if no revisions are specified. To diff against the
2566 parent changeset if no revisions are specified. To diff against the
2547 conflict regions, you can use `--config diff.merge=yes`.
2567 conflict regions, you can use `--config diff.merge=yes`.
2548
2568
2549 By default, the working directory files are compared to its first parent. To
2569 By default, the working directory files are compared to its first parent. To
2550 see the differences from another revision, use --from. To see the difference
2570 see the differences from another revision, use --from. To see the difference
2551 to another revision, use --to. For example, :hg:`diff --from .^` will show
2571 to another revision, use --to. For example, :hg:`diff --from .^` will show
2552 the differences from the working copy's grandparent to the working copy,
2572 the differences from the working copy's grandparent to the working copy,
2553 :hg:`diff --to .` will show the diff from the working copy to its parent
2573 :hg:`diff --to .` will show the diff from the working copy to its parent
2554 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2574 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2555 show the diff between those two revisions.
2575 show the diff between those two revisions.
2556
2576
2557 Alternatively you can specify -c/--change with a revision to see the changes
2577 Alternatively you can specify -c/--change with a revision to see the changes
2558 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2578 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2559 equivalent to :hg:`diff --from 42^ --to 42`)
2579 equivalent to :hg:`diff --from 42^ --to 42`)
2560
2580
2561 Without the -a/--text option, diff will avoid generating diffs of
2581 Without the -a/--text option, diff will avoid generating diffs of
2562 files it detects as binary. With -a, diff will generate a diff
2582 files it detects as binary. With -a, diff will generate a diff
2563 anyway, probably with undesirable results.
2583 anyway, probably with undesirable results.
2564
2584
2565 Use the -g/--git option to generate diffs in the git extended diff
2585 Use the -g/--git option to generate diffs in the git extended diff
2566 format. For more information, read :hg:`help diffs`.
2586 format. For more information, read :hg:`help diffs`.
2567
2587
2568 .. container:: verbose
2588 .. container:: verbose
2569
2589
2570 Examples:
2590 Examples:
2571
2591
2572 - compare a file in the current working directory to its parent::
2592 - compare a file in the current working directory to its parent::
2573
2593
2574 hg diff foo.c
2594 hg diff foo.c
2575
2595
2576 - compare two historical versions of a directory, with rename info::
2596 - compare two historical versions of a directory, with rename info::
2577
2597
2578 hg diff --git --from 1.0 --to 1.2 lib/
2598 hg diff --git --from 1.0 --to 1.2 lib/
2579
2599
2580 - get change stats relative to the last change on some date::
2600 - get change stats relative to the last change on some date::
2581
2601
2582 hg diff --stat --from "date('may 2')"
2602 hg diff --stat --from "date('may 2')"
2583
2603
2584 - diff all newly-added files that contain a keyword::
2604 - diff all newly-added files that contain a keyword::
2585
2605
2586 hg diff "set:added() and grep(GNU)"
2606 hg diff "set:added() and grep(GNU)"
2587
2607
2588 - compare a revision and its parents::
2608 - compare a revision and its parents::
2589
2609
2590 hg diff -c 9353 # compare against first parent
2610 hg diff -c 9353 # compare against first parent
2591 hg diff --from 9353^ --to 9353 # same using revset syntax
2611 hg diff --from 9353^ --to 9353 # same using revset syntax
2592 hg diff --from 9353^2 --to 9353 # compare against the second parent
2612 hg diff --from 9353^2 --to 9353 # compare against the second parent
2593
2613
2594 Returns 0 on success.
2614 Returns 0 on success.
2595 """
2615 """
2596
2616
2597 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2617 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2598 opts = pycompat.byteskwargs(opts)
2618 opts = pycompat.byteskwargs(opts)
2599 revs = opts.get(b'rev')
2619 revs = opts.get(b'rev')
2600 change = opts.get(b'change')
2620 change = opts.get(b'change')
2601 from_rev = opts.get(b'from')
2621 from_rev = opts.get(b'from')
2602 to_rev = opts.get(b'to')
2622 to_rev = opts.get(b'to')
2603 stat = opts.get(b'stat')
2623 stat = opts.get(b'stat')
2604 reverse = opts.get(b'reverse')
2624 reverse = opts.get(b'reverse')
2605
2625
2606 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2626 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2607 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2627 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2608 if change:
2628 if change:
2609 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2629 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2610 ctx2 = logcmdutil.revsingle(repo, change, None)
2630 ctx2 = logcmdutil.revsingle(repo, change, None)
2611 ctx1 = logcmdutil.diff_parent(ctx2)
2631 ctx1 = logcmdutil.diff_parent(ctx2)
2612 elif from_rev or to_rev:
2632 elif from_rev or to_rev:
2613 repo = scmutil.unhidehashlikerevs(
2633 repo = scmutil.unhidehashlikerevs(
2614 repo, [from_rev] + [to_rev], b'nowarn'
2634 repo, [from_rev] + [to_rev], b'nowarn'
2615 )
2635 )
2616 ctx1 = logcmdutil.revsingle(repo, from_rev, None)
2636 ctx1 = logcmdutil.revsingle(repo, from_rev, None)
2617 ctx2 = logcmdutil.revsingle(repo, to_rev, None)
2637 ctx2 = logcmdutil.revsingle(repo, to_rev, None)
2618 else:
2638 else:
2619 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2639 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2620 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
2640 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
2621
2641
2622 if reverse:
2642 if reverse:
2623 ctxleft = ctx2
2643 ctxleft = ctx2
2624 ctxright = ctx1
2644 ctxright = ctx1
2625 else:
2645 else:
2626 ctxleft = ctx1
2646 ctxleft = ctx1
2627 ctxright = ctx2
2647 ctxright = ctx2
2628
2648
2629 diffopts = patch.diffallopts(ui, opts)
2649 diffopts = patch.diffallopts(ui, opts)
2630 m = scmutil.match(ctx2, pats, opts)
2650 m = scmutil.match(ctx2, pats, opts)
2631 m = repo.narrowmatch(m)
2651 m = repo.narrowmatch(m)
2632 ui.pager(b'diff')
2652 ui.pager(b'diff')
2633 logcmdutil.diffordiffstat(
2653 logcmdutil.diffordiffstat(
2634 ui,
2654 ui,
2635 repo,
2655 repo,
2636 diffopts,
2656 diffopts,
2637 ctxleft,
2657 ctxleft,
2638 ctxright,
2658 ctxright,
2639 m,
2659 m,
2640 stat=stat,
2660 stat=stat,
2641 listsubrepos=opts.get(b'subrepos'),
2661 listsubrepos=opts.get(b'subrepos'),
2642 root=opts.get(b'root'),
2662 root=opts.get(b'root'),
2643 )
2663 )
2644
2664
2645
2665
2646 @command(
2666 @command(
2647 b'export',
2667 b'export',
2648 [
2668 [
2649 (
2669 (
2650 b'B',
2670 b'B',
2651 b'bookmark',
2671 b'bookmark',
2652 b'',
2672 b'',
2653 _(b'export changes only reachable by given bookmark'),
2673 _(b'export changes only reachable by given bookmark'),
2654 _(b'BOOKMARK'),
2674 _(b'BOOKMARK'),
2655 ),
2675 ),
2656 (
2676 (
2657 b'o',
2677 b'o',
2658 b'output',
2678 b'output',
2659 b'',
2679 b'',
2660 _(b'print output to file with formatted name'),
2680 _(b'print output to file with formatted name'),
2661 _(b'FORMAT'),
2681 _(b'FORMAT'),
2662 ),
2682 ),
2663 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2683 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2664 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2684 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2665 ]
2685 ]
2666 + diffopts
2686 + diffopts
2667 + formatteropts,
2687 + formatteropts,
2668 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2688 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2669 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2689 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2670 helpbasic=True,
2690 helpbasic=True,
2671 intents={INTENT_READONLY},
2691 intents={INTENT_READONLY},
2672 )
2692 )
2673 def export(ui, repo, *changesets, **opts):
2693 def export(ui, repo, *changesets, **opts):
2674 """dump the header and diffs for one or more changesets
2694 """dump the header and diffs for one or more changesets
2675
2695
2676 Print the changeset header and diffs for one or more revisions.
2696 Print the changeset header and diffs for one or more revisions.
2677 If no revision is given, the parent of the working directory is used.
2697 If no revision is given, the parent of the working directory is used.
2678
2698
2679 The information shown in the changeset header is: author, date,
2699 The information shown in the changeset header is: author, date,
2680 branch name (if non-default), changeset hash, parent(s) and commit
2700 branch name (if non-default), changeset hash, parent(s) and commit
2681 comment.
2701 comment.
2682
2702
2683 .. note::
2703 .. note::
2684
2704
2685 :hg:`export` may generate unexpected diff output for merge
2705 :hg:`export` may generate unexpected diff output for merge
2686 changesets, as it will compare the merge changeset against its
2706 changesets, as it will compare the merge changeset against its
2687 first parent only.
2707 first parent only.
2688
2708
2689 Output may be to a file, in which case the name of the file is
2709 Output may be to a file, in which case the name of the file is
2690 given using a template string. See :hg:`help templates`. In addition
2710 given using a template string. See :hg:`help templates`. In addition
2691 to the common template keywords, the following formatting rules are
2711 to the common template keywords, the following formatting rules are
2692 supported:
2712 supported:
2693
2713
2694 :``%%``: literal "%" character
2714 :``%%``: literal "%" character
2695 :``%H``: changeset hash (40 hexadecimal digits)
2715 :``%H``: changeset hash (40 hexadecimal digits)
2696 :``%N``: number of patches being generated
2716 :``%N``: number of patches being generated
2697 :``%R``: changeset revision number
2717 :``%R``: changeset revision number
2698 :``%b``: basename of the exporting repository
2718 :``%b``: basename of the exporting repository
2699 :``%h``: short-form changeset hash (12 hexadecimal digits)
2719 :``%h``: short-form changeset hash (12 hexadecimal digits)
2700 :``%m``: first line of the commit message (only alphanumeric characters)
2720 :``%m``: first line of the commit message (only alphanumeric characters)
2701 :``%n``: zero-padded sequence number, starting at 1
2721 :``%n``: zero-padded sequence number, starting at 1
2702 :``%r``: zero-padded changeset revision number
2722 :``%r``: zero-padded changeset revision number
2703 :``\\``: literal "\\" character
2723 :``\\``: literal "\\" character
2704
2724
2705 Without the -a/--text option, export will avoid generating diffs
2725 Without the -a/--text option, export will avoid generating diffs
2706 of files it detects as binary. With -a, export will generate a
2726 of files it detects as binary. With -a, export will generate a
2707 diff anyway, probably with undesirable results.
2727 diff anyway, probably with undesirable results.
2708
2728
2709 With -B/--bookmark changesets reachable by the given bookmark are
2729 With -B/--bookmark changesets reachable by the given bookmark are
2710 selected.
2730 selected.
2711
2731
2712 Use the -g/--git option to generate diffs in the git extended diff
2732 Use the -g/--git option to generate diffs in the git extended diff
2713 format. See :hg:`help diffs` for more information.
2733 format. See :hg:`help diffs` for more information.
2714
2734
2715 With the --switch-parent option, the diff will be against the
2735 With the --switch-parent option, the diff will be against the
2716 second parent. It can be useful to review a merge.
2736 second parent. It can be useful to review a merge.
2717
2737
2718 .. container:: verbose
2738 .. container:: verbose
2719
2739
2720 Template:
2740 Template:
2721
2741
2722 The following keywords are supported in addition to the common template
2742 The following keywords are supported in addition to the common template
2723 keywords and functions. See also :hg:`help templates`.
2743 keywords and functions. See also :hg:`help templates`.
2724
2744
2725 :diff: String. Diff content.
2745 :diff: String. Diff content.
2726 :parents: List of strings. Parent nodes of the changeset.
2746 :parents: List of strings. Parent nodes of the changeset.
2727
2747
2728 Examples:
2748 Examples:
2729
2749
2730 - use export and import to transplant a bugfix to the current
2750 - use export and import to transplant a bugfix to the current
2731 branch::
2751 branch::
2732
2752
2733 hg export -r 9353 | hg import -
2753 hg export -r 9353 | hg import -
2734
2754
2735 - export all the changesets between two revisions to a file with
2755 - export all the changesets between two revisions to a file with
2736 rename information::
2756 rename information::
2737
2757
2738 hg export --git -r 123:150 > changes.txt
2758 hg export --git -r 123:150 > changes.txt
2739
2759
2740 - split outgoing changes into a series of patches with
2760 - split outgoing changes into a series of patches with
2741 descriptive names::
2761 descriptive names::
2742
2762
2743 hg export -r "outgoing()" -o "%n-%m.patch"
2763 hg export -r "outgoing()" -o "%n-%m.patch"
2744
2764
2745 Returns 0 on success.
2765 Returns 0 on success.
2746 """
2766 """
2747 opts = pycompat.byteskwargs(opts)
2767 opts = pycompat.byteskwargs(opts)
2748 bookmark = opts.get(b'bookmark')
2768 bookmark = opts.get(b'bookmark')
2749 changesets += tuple(opts.get(b'rev', []))
2769 changesets += tuple(opts.get(b'rev', []))
2750
2770
2751 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2771 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2752
2772
2753 if bookmark:
2773 if bookmark:
2754 if bookmark not in repo._bookmarks:
2774 if bookmark not in repo._bookmarks:
2755 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2775 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2756
2776
2757 revs = scmutil.bookmarkrevs(repo, bookmark)
2777 revs = scmutil.bookmarkrevs(repo, bookmark)
2758 else:
2778 else:
2759 if not changesets:
2779 if not changesets:
2760 changesets = [b'.']
2780 changesets = [b'.']
2761
2781
2762 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2782 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2763 revs = logcmdutil.revrange(repo, changesets)
2783 revs = logcmdutil.revrange(repo, changesets)
2764
2784
2765 if not revs:
2785 if not revs:
2766 raise error.InputError(_(b"export requires at least one changeset"))
2786 raise error.InputError(_(b"export requires at least one changeset"))
2767 if len(revs) > 1:
2787 if len(revs) > 1:
2768 ui.note(_(b'exporting patches:\n'))
2788 ui.note(_(b'exporting patches:\n'))
2769 else:
2789 else:
2770 ui.note(_(b'exporting patch:\n'))
2790 ui.note(_(b'exporting patch:\n'))
2771
2791
2772 fntemplate = opts.get(b'output')
2792 fntemplate = opts.get(b'output')
2773 if cmdutil.isstdiofilename(fntemplate):
2793 if cmdutil.isstdiofilename(fntemplate):
2774 fntemplate = b''
2794 fntemplate = b''
2775
2795
2776 if fntemplate:
2796 if fntemplate:
2777 fm = formatter.nullformatter(ui, b'export', opts)
2797 fm = formatter.nullformatter(ui, b'export', opts)
2778 else:
2798 else:
2779 ui.pager(b'export')
2799 ui.pager(b'export')
2780 fm = ui.formatter(b'export', opts)
2800 fm = ui.formatter(b'export', opts)
2781 with fm:
2801 with fm:
2782 cmdutil.export(
2802 cmdutil.export(
2783 repo,
2803 repo,
2784 revs,
2804 revs,
2785 fm,
2805 fm,
2786 fntemplate=fntemplate,
2806 fntemplate=fntemplate,
2787 switch_parent=opts.get(b'switch_parent'),
2807 switch_parent=opts.get(b'switch_parent'),
2788 opts=patch.diffallopts(ui, opts),
2808 opts=patch.diffallopts(ui, opts),
2789 )
2809 )
2790
2810
2791
2811
2792 @command(
2812 @command(
2793 b'files',
2813 b'files',
2794 [
2814 [
2795 (
2815 (
2796 b'r',
2816 b'r',
2797 b'rev',
2817 b'rev',
2798 b'',
2818 b'',
2799 _(b'search the repository as it is in REV'),
2819 _(b'search the repository as it is in REV'),
2800 _(b'REV'),
2820 _(b'REV'),
2801 ),
2821 ),
2802 (
2822 (
2803 b'0',
2823 b'0',
2804 b'print0',
2824 b'print0',
2805 None,
2825 None,
2806 _(b'end filenames with NUL, for use with xargs'),
2826 _(b'end filenames with NUL, for use with xargs'),
2807 ),
2827 ),
2808 ]
2828 ]
2809 + walkopts
2829 + walkopts
2810 + formatteropts
2830 + formatteropts
2811 + subrepoopts,
2831 + subrepoopts,
2812 _(b'[OPTION]... [FILE]...'),
2832 _(b'[OPTION]... [FILE]...'),
2813 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2833 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2814 intents={INTENT_READONLY},
2834 intents={INTENT_READONLY},
2815 )
2835 )
2816 def files(ui, repo, *pats, **opts):
2836 def files(ui, repo, *pats, **opts):
2817 """list tracked files
2837 """list tracked files
2818
2838
2819 Print files under Mercurial control in the working directory or
2839 Print files under Mercurial control in the working directory or
2820 specified revision for given files (excluding removed files).
2840 specified revision for given files (excluding removed files).
2821 Files can be specified as filenames or filesets.
2841 Files can be specified as filenames or filesets.
2822
2842
2823 If no files are given to match, this command prints the names
2843 If no files are given to match, this command prints the names
2824 of all files under Mercurial control.
2844 of all files under Mercurial control.
2825
2845
2826 .. container:: verbose
2846 .. container:: verbose
2827
2847
2828 Template:
2848 Template:
2829
2849
2830 The following keywords are supported in addition to the common template
2850 The following keywords are supported in addition to the common template
2831 keywords and functions. See also :hg:`help templates`.
2851 keywords and functions. See also :hg:`help templates`.
2832
2852
2833 :flags: String. Character denoting file's symlink and executable bits.
2853 :flags: String. Character denoting file's symlink and executable bits.
2834 :path: String. Repository-absolute path of the file.
2854 :path: String. Repository-absolute path of the file.
2835 :size: Integer. Size of the file in bytes.
2855 :size: Integer. Size of the file in bytes.
2836
2856
2837 Examples:
2857 Examples:
2838
2858
2839 - list all files under the current directory::
2859 - list all files under the current directory::
2840
2860
2841 hg files .
2861 hg files .
2842
2862
2843 - shows sizes and flags for current revision::
2863 - shows sizes and flags for current revision::
2844
2864
2845 hg files -vr .
2865 hg files -vr .
2846
2866
2847 - list all files named README::
2867 - list all files named README::
2848
2868
2849 hg files -I "**/README"
2869 hg files -I "**/README"
2850
2870
2851 - list all binary files::
2871 - list all binary files::
2852
2872
2853 hg files "set:binary()"
2873 hg files "set:binary()"
2854
2874
2855 - find files containing a regular expression::
2875 - find files containing a regular expression::
2856
2876
2857 hg files "set:grep('bob')"
2877 hg files "set:grep('bob')"
2858
2878
2859 - search tracked file contents with xargs and grep::
2879 - search tracked file contents with xargs and grep::
2860
2880
2861 hg files -0 | xargs -0 grep foo
2881 hg files -0 | xargs -0 grep foo
2862
2882
2863 See :hg:`help patterns` and :hg:`help filesets` for more information
2883 See :hg:`help patterns` and :hg:`help filesets` for more information
2864 on specifying file patterns.
2884 on specifying file patterns.
2865
2885
2866 Returns 0 if a match is found, 1 otherwise.
2886 Returns 0 if a match is found, 1 otherwise.
2867
2887
2868 """
2888 """
2869
2889
2870 opts = pycompat.byteskwargs(opts)
2890 opts = pycompat.byteskwargs(opts)
2871 rev = opts.get(b'rev')
2891 rev = opts.get(b'rev')
2872 if rev:
2892 if rev:
2873 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2893 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2874 ctx = logcmdutil.revsingle(repo, rev, None)
2894 ctx = logcmdutil.revsingle(repo, rev, None)
2875
2895
2876 end = b'\n'
2896 end = b'\n'
2877 if opts.get(b'print0'):
2897 if opts.get(b'print0'):
2878 end = b'\0'
2898 end = b'\0'
2879 fmt = b'%s' + end
2899 fmt = b'%s' + end
2880
2900
2881 m = scmutil.match(ctx, pats, opts)
2901 m = scmutil.match(ctx, pats, opts)
2882 ui.pager(b'files')
2902 ui.pager(b'files')
2883 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2903 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2884 with ui.formatter(b'files', opts) as fm:
2904 with ui.formatter(b'files', opts) as fm:
2885 return cmdutil.files(
2905 return cmdutil.files(
2886 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2906 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2887 )
2907 )
2888
2908
2889
2909
2890 @command(
2910 @command(
2891 b'forget',
2911 b'forget',
2892 [
2912 [
2893 (b'i', b'interactive', None, _(b'use interactive mode')),
2913 (b'i', b'interactive', None, _(b'use interactive mode')),
2894 ]
2914 ]
2895 + walkopts
2915 + walkopts
2896 + dryrunopts,
2916 + dryrunopts,
2897 _(b'[OPTION]... FILE...'),
2917 _(b'[OPTION]... FILE...'),
2898 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2918 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2899 helpbasic=True,
2919 helpbasic=True,
2900 inferrepo=True,
2920 inferrepo=True,
2901 )
2921 )
2902 def forget(ui, repo, *pats, **opts):
2922 def forget(ui, repo, *pats, **opts):
2903 """forget the specified files on the next commit
2923 """forget the specified files on the next commit
2904
2924
2905 Mark the specified files so they will no longer be tracked
2925 Mark the specified files so they will no longer be tracked
2906 after the next commit.
2926 after the next commit.
2907
2927
2908 This only removes files from the current branch, not from the
2928 This only removes files from the current branch, not from the
2909 entire project history, and it does not delete them from the
2929 entire project history, and it does not delete them from the
2910 working directory.
2930 working directory.
2911
2931
2912 To delete the file from the working directory, see :hg:`remove`.
2932 To delete the file from the working directory, see :hg:`remove`.
2913
2933
2914 To undo a forget before the next commit, see :hg:`add`.
2934 To undo a forget before the next commit, see :hg:`add`.
2915
2935
2916 .. container:: verbose
2936 .. container:: verbose
2917
2937
2918 Examples:
2938 Examples:
2919
2939
2920 - forget newly-added binary files::
2940 - forget newly-added binary files::
2921
2941
2922 hg forget "set:added() and binary()"
2942 hg forget "set:added() and binary()"
2923
2943
2924 - forget files that would be excluded by .hgignore::
2944 - forget files that would be excluded by .hgignore::
2925
2945
2926 hg forget "set:hgignore()"
2946 hg forget "set:hgignore()"
2927
2947
2928 Returns 0 on success.
2948 Returns 0 on success.
2929 """
2949 """
2930
2950
2931 opts = pycompat.byteskwargs(opts)
2951 opts = pycompat.byteskwargs(opts)
2932 if not pats:
2952 if not pats:
2933 raise error.InputError(_(b'no files specified'))
2953 raise error.InputError(_(b'no files specified'))
2934
2954
2935 m = scmutil.match(repo[None], pats, opts)
2955 m = scmutil.match(repo[None], pats, opts)
2936 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2956 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2937 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2957 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2938 rejected = cmdutil.forget(
2958 rejected = cmdutil.forget(
2939 ui,
2959 ui,
2940 repo,
2960 repo,
2941 m,
2961 m,
2942 prefix=b"",
2962 prefix=b"",
2943 uipathfn=uipathfn,
2963 uipathfn=uipathfn,
2944 explicitonly=False,
2964 explicitonly=False,
2945 dryrun=dryrun,
2965 dryrun=dryrun,
2946 interactive=interactive,
2966 interactive=interactive,
2947 )[0]
2967 )[0]
2948 return rejected and 1 or 0
2968 return rejected and 1 or 0
2949
2969
2950
2970
2951 @command(
2971 @command(
2952 b'graft',
2972 b'graft',
2953 [
2973 [
2954 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2974 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2955 (
2975 (
2956 b'',
2976 b'',
2957 b'base',
2977 b'base',
2958 b'',
2978 b'',
2959 _(b'base revision when doing the graft merge (ADVANCED)'),
2979 _(b'base revision when doing the graft merge (ADVANCED)'),
2960 _(b'REV'),
2980 _(b'REV'),
2961 ),
2981 ),
2962 (b'c', b'continue', False, _(b'resume interrupted graft')),
2982 (b'c', b'continue', False, _(b'resume interrupted graft')),
2963 (b'', b'stop', False, _(b'stop interrupted graft')),
2983 (b'', b'stop', False, _(b'stop interrupted graft')),
2964 (b'', b'abort', False, _(b'abort interrupted graft')),
2984 (b'', b'abort', False, _(b'abort interrupted graft')),
2965 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2985 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2966 (b'', b'log', None, _(b'append graft info to log message')),
2986 (b'', b'log', None, _(b'append graft info to log message')),
2967 (
2987 (
2968 b'',
2988 b'',
2969 b'no-commit',
2989 b'no-commit',
2970 None,
2990 None,
2971 _(b"don't commit, just apply the changes in working directory"),
2991 _(b"don't commit, just apply the changes in working directory"),
2972 ),
2992 ),
2973 (b'f', b'force', False, _(b'force graft')),
2993 (b'f', b'force', False, _(b'force graft')),
2974 (
2994 (
2975 b'D',
2995 b'D',
2976 b'currentdate',
2996 b'currentdate',
2977 False,
2997 False,
2978 _(b'record the current date as commit date'),
2998 _(b'record the current date as commit date'),
2979 ),
2999 ),
2980 (
3000 (
2981 b'U',
3001 b'U',
2982 b'currentuser',
3002 b'currentuser',
2983 False,
3003 False,
2984 _(b'record the current user as committer'),
3004 _(b'record the current user as committer'),
2985 ),
3005 ),
2986 ]
3006 ]
2987 + commitopts2
3007 + commitopts2
2988 + mergetoolopts
3008 + mergetoolopts
2989 + dryrunopts,
3009 + dryrunopts,
2990 _(b'[OPTION]... [-r REV]... REV...'),
3010 _(b'[OPTION]... [-r REV]... REV...'),
2991 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
3011 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2992 )
3012 )
2993 def graft(ui, repo, *revs, **opts):
3013 def graft(ui, repo, *revs, **opts):
2994 """copy changes from other branches onto the current branch
3014 """copy changes from other branches onto the current branch
2995
3015
2996 This command uses Mercurial's merge logic to copy individual
3016 This command uses Mercurial's merge logic to copy individual
2997 changes from other branches without merging branches in the
3017 changes from other branches without merging branches in the
2998 history graph. This is sometimes known as 'backporting' or
3018 history graph. This is sometimes known as 'backporting' or
2999 'cherry-picking'. By default, graft will copy user, date, and
3019 'cherry-picking'. By default, graft will copy user, date, and
3000 description from the source changesets.
3020 description from the source changesets.
3001
3021
3002 Changesets that are ancestors of the current revision, that have
3022 Changesets that are ancestors of the current revision, that have
3003 already been grafted, or that are merges will be skipped.
3023 already been grafted, or that are merges will be skipped.
3004
3024
3005 If --log is specified, log messages will have a comment appended
3025 If --log is specified, log messages will have a comment appended
3006 of the form::
3026 of the form::
3007
3027
3008 (grafted from CHANGESETHASH)
3028 (grafted from CHANGESETHASH)
3009
3029
3010 If --force is specified, revisions will be grafted even if they
3030 If --force is specified, revisions will be grafted even if they
3011 are already ancestors of, or have been grafted to, the destination.
3031 are already ancestors of, or have been grafted to, the destination.
3012 This is useful when the revisions have since been backed out.
3032 This is useful when the revisions have since been backed out.
3013
3033
3014 If a graft merge results in conflicts, the graft process is
3034 If a graft merge results in conflicts, the graft process is
3015 interrupted so that the current merge can be manually resolved.
3035 interrupted so that the current merge can be manually resolved.
3016 Once all conflicts are addressed, the graft process can be
3036 Once all conflicts are addressed, the graft process can be
3017 continued with the -c/--continue option.
3037 continued with the -c/--continue option.
3018
3038
3019 The -c/--continue option reapplies all the earlier options.
3039 The -c/--continue option reapplies all the earlier options.
3020
3040
3021 .. container:: verbose
3041 .. container:: verbose
3022
3042
3023 The --base option exposes more of how graft internally uses merge with a
3043 The --base option exposes more of how graft internally uses merge with a
3024 custom base revision. --base can be used to specify another ancestor than
3044 custom base revision. --base can be used to specify another ancestor than
3025 the first and only parent.
3045 the first and only parent.
3026
3046
3027 The command::
3047 The command::
3028
3048
3029 hg graft -r 345 --base 234
3049 hg graft -r 345 --base 234
3030
3050
3031 is thus pretty much the same as::
3051 is thus pretty much the same as::
3032
3052
3033 hg diff --from 234 --to 345 | hg import
3053 hg diff --from 234 --to 345 | hg import
3034
3054
3035 but using merge to resolve conflicts and track moved files.
3055 but using merge to resolve conflicts and track moved files.
3036
3056
3037 The result of a merge can thus be backported as a single commit by
3057 The result of a merge can thus be backported as a single commit by
3038 specifying one of the merge parents as base, and thus effectively
3058 specifying one of the merge parents as base, and thus effectively
3039 grafting the changes from the other side.
3059 grafting the changes from the other side.
3040
3060
3041 It is also possible to collapse multiple changesets and clean up history
3061 It is also possible to collapse multiple changesets and clean up history
3042 by specifying another ancestor as base, much like rebase --collapse
3062 by specifying another ancestor as base, much like rebase --collapse
3043 --keep.
3063 --keep.
3044
3064
3045 The commit message can be tweaked after the fact using commit --amend .
3065 The commit message can be tweaked after the fact using commit --amend .
3046
3066
3047 For using non-ancestors as the base to backout changes, see the backout
3067 For using non-ancestors as the base to backout changes, see the backout
3048 command and the hidden --parent option.
3068 command and the hidden --parent option.
3049
3069
3050 .. container:: verbose
3070 .. container:: verbose
3051
3071
3052 Examples:
3072 Examples:
3053
3073
3054 - copy a single change to the stable branch and edit its description::
3074 - copy a single change to the stable branch and edit its description::
3055
3075
3056 hg update stable
3076 hg update stable
3057 hg graft --edit 9393
3077 hg graft --edit 9393
3058
3078
3059 - graft a range of changesets with one exception, updating dates::
3079 - graft a range of changesets with one exception, updating dates::
3060
3080
3061 hg graft -D "2085::2093 and not 2091"
3081 hg graft -D "2085::2093 and not 2091"
3062
3082
3063 - continue a graft after resolving conflicts::
3083 - continue a graft after resolving conflicts::
3064
3084
3065 hg graft -c
3085 hg graft -c
3066
3086
3067 - show the source of a grafted changeset::
3087 - show the source of a grafted changeset::
3068
3088
3069 hg log --debug -r .
3089 hg log --debug -r .
3070
3090
3071 - show revisions sorted by date::
3091 - show revisions sorted by date::
3072
3092
3073 hg log -r "sort(all(), date)"
3093 hg log -r "sort(all(), date)"
3074
3094
3075 - backport the result of a merge as a single commit::
3095 - backport the result of a merge as a single commit::
3076
3096
3077 hg graft -r 123 --base 123^
3097 hg graft -r 123 --base 123^
3078
3098
3079 - land a feature branch as one changeset::
3099 - land a feature branch as one changeset::
3080
3100
3081 hg up -cr default
3101 hg up -cr default
3082 hg graft -r featureX --base "ancestor('featureX', 'default')"
3102 hg graft -r featureX --base "ancestor('featureX', 'default')"
3083
3103
3084 See :hg:`help revisions` for more about specifying revisions.
3104 See :hg:`help revisions` for more about specifying revisions.
3085
3105
3086 Returns 0 on successful completion, 1 if there are unresolved files.
3106 Returns 0 on successful completion, 1 if there are unresolved files.
3087 """
3107 """
3088 with repo.wlock():
3108 with repo.wlock():
3089 return _dograft(ui, repo, *revs, **opts)
3109 return _dograft(ui, repo, *revs, **opts)
3090
3110
3091
3111
3092 def _dograft(ui, repo, *revs, **opts):
3112 def _dograft(ui, repo, *revs, **opts):
3093 if revs and opts.get('rev'):
3113 if revs and opts.get('rev'):
3094 ui.warn(
3114 ui.warn(
3095 _(
3115 _(
3096 b'warning: inconsistent use of --rev might give unexpected '
3116 b'warning: inconsistent use of --rev might give unexpected '
3097 b'revision ordering!\n'
3117 b'revision ordering!\n'
3098 )
3118 )
3099 )
3119 )
3100
3120
3101 revs = list(revs)
3121 revs = list(revs)
3102 revs.extend(opts.get('rev'))
3122 revs.extend(opts.get('rev'))
3103 # a dict of data to be stored in state file
3123 # a dict of data to be stored in state file
3104 statedata = {}
3124 statedata = {}
3105 # list of new nodes created by ongoing graft
3125 # list of new nodes created by ongoing graft
3106 statedata[b'newnodes'] = []
3126 statedata[b'newnodes'] = []
3107
3127
3108 cmdutil.resolve_commit_options(ui, opts)
3128 cmdutil.resolve_commit_options(ui, opts)
3109
3129
3110 editor = cmdutil.getcommiteditor(editform=b'graft', **opts)
3130 editor = cmdutil.getcommiteditor(editform=b'graft', **opts)
3111
3131
3112 cmdutil.check_at_most_one_arg(opts, 'abort', 'stop', 'continue')
3132 cmdutil.check_at_most_one_arg(opts, 'abort', 'stop', 'continue')
3113
3133
3114 cont = False
3134 cont = False
3115 if opts.get('no_commit'):
3135 if opts.get('no_commit'):
3116 cmdutil.check_incompatible_arguments(
3136 cmdutil.check_incompatible_arguments(
3117 opts,
3137 opts,
3118 'no_commit',
3138 'no_commit',
3119 ['edit', 'currentuser', 'currentdate', 'log'],
3139 ['edit', 'currentuser', 'currentdate', 'log'],
3120 )
3140 )
3121
3141
3122 graftstate = statemod.cmdstate(repo, b'graftstate')
3142 graftstate = statemod.cmdstate(repo, b'graftstate')
3123
3143
3124 if opts.get('stop'):
3144 if opts.get('stop'):
3125 cmdutil.check_incompatible_arguments(
3145 cmdutil.check_incompatible_arguments(
3126 opts,
3146 opts,
3127 'stop',
3147 'stop',
3128 [
3148 [
3129 'edit',
3149 'edit',
3130 'log',
3150 'log',
3131 'user',
3151 'user',
3132 'date',
3152 'date',
3133 'currentdate',
3153 'currentdate',
3134 'currentuser',
3154 'currentuser',
3135 'rev',
3155 'rev',
3136 ],
3156 ],
3137 )
3157 )
3138 return _stopgraft(ui, repo, graftstate)
3158 return _stopgraft(ui, repo, graftstate)
3139 elif opts.get('abort'):
3159 elif opts.get('abort'):
3140 cmdutil.check_incompatible_arguments(
3160 cmdutil.check_incompatible_arguments(
3141 opts,
3161 opts,
3142 'abort',
3162 'abort',
3143 [
3163 [
3144 'edit',
3164 'edit',
3145 'log',
3165 'log',
3146 'user',
3166 'user',
3147 'date',
3167 'date',
3148 'currentdate',
3168 'currentdate',
3149 'currentuser',
3169 'currentuser',
3150 'rev',
3170 'rev',
3151 ],
3171 ],
3152 )
3172 )
3153 return cmdutil.abortgraft(ui, repo, graftstate)
3173 return cmdutil.abortgraft(ui, repo, graftstate)
3154 elif opts.get('continue'):
3174 elif opts.get('continue'):
3155 cont = True
3175 cont = True
3156 if revs:
3176 if revs:
3157 raise error.InputError(_(b"can't specify --continue and revisions"))
3177 raise error.InputError(_(b"can't specify --continue and revisions"))
3158 # read in unfinished revisions
3178 # read in unfinished revisions
3159 if graftstate.exists():
3179 if graftstate.exists():
3160 statedata = cmdutil.readgraftstate(repo, graftstate)
3180 statedata = cmdutil.readgraftstate(repo, graftstate)
3161 if statedata.get(b'date'):
3181 if statedata.get(b'date'):
3162 opts['date'] = statedata[b'date']
3182 opts['date'] = statedata[b'date']
3163 if statedata.get(b'user'):
3183 if statedata.get(b'user'):
3164 opts['user'] = statedata[b'user']
3184 opts['user'] = statedata[b'user']
3165 if statedata.get(b'log'):
3185 if statedata.get(b'log'):
3166 opts['log'] = True
3186 opts['log'] = True
3167 if statedata.get(b'no_commit'):
3187 if statedata.get(b'no_commit'):
3168 opts['no_commit'] = statedata.get(b'no_commit')
3188 opts['no_commit'] = statedata.get(b'no_commit')
3169 if statedata.get(b'base'):
3189 if statedata.get(b'base'):
3170 opts['base'] = statedata.get(b'base')
3190 opts['base'] = statedata.get(b'base')
3171 nodes = statedata[b'nodes']
3191 nodes = statedata[b'nodes']
3172 revs = [repo[node].rev() for node in nodes]
3192 revs = [repo[node].rev() for node in nodes]
3173 else:
3193 else:
3174 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3194 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3175 else:
3195 else:
3176 if not revs:
3196 if not revs:
3177 raise error.InputError(_(b'no revisions specified'))
3197 raise error.InputError(_(b'no revisions specified'))
3178 cmdutil.checkunfinished(repo)
3198 cmdutil.checkunfinished(repo)
3179 cmdutil.bailifchanged(repo)
3199 cmdutil.bailifchanged(repo)
3180 revs = logcmdutil.revrange(repo, revs)
3200 revs = logcmdutil.revrange(repo, revs)
3181
3201
3182 skipped = set()
3202 skipped = set()
3183 basectx = None
3203 basectx = None
3184 if opts.get('base'):
3204 if opts.get('base'):
3185 basectx = logcmdutil.revsingle(repo, opts['base'], None)
3205 basectx = logcmdutil.revsingle(repo, opts['base'], None)
3186 if basectx is None:
3206 if basectx is None:
3187 # check for merges
3207 # check for merges
3188 for rev in repo.revs(b'%ld and merge()', revs):
3208 for rev in repo.revs(b'%ld and merge()', revs):
3189 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3209 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3190 skipped.add(rev)
3210 skipped.add(rev)
3191 revs = [r for r in revs if r not in skipped]
3211 revs = [r for r in revs if r not in skipped]
3192 if not revs:
3212 if not revs:
3193 return -1
3213 return -1
3194 if basectx is not None and len(revs) != 1:
3214 if basectx is not None and len(revs) != 1:
3195 raise error.InputError(_(b'only one revision allowed with --base '))
3215 raise error.InputError(_(b'only one revision allowed with --base '))
3196
3216
3197 # Don't check in the --continue case, in effect retaining --force across
3217 # Don't check in the --continue case, in effect retaining --force across
3198 # --continues. That's because without --force, any revisions we decided to
3218 # --continues. That's because without --force, any revisions we decided to
3199 # skip would have been filtered out here, so they wouldn't have made their
3219 # skip would have been filtered out here, so they wouldn't have made their
3200 # way to the graftstate. With --force, any revisions we would have otherwise
3220 # way to the graftstate. With --force, any revisions we would have otherwise
3201 # skipped would not have been filtered out, and if they hadn't been applied
3221 # skipped would not have been filtered out, and if they hadn't been applied
3202 # already, they'd have been in the graftstate.
3222 # already, they'd have been in the graftstate.
3203 if not (cont or opts.get('force')) and basectx is None:
3223 if not (cont or opts.get('force')) and basectx is None:
3204 # check for ancestors of dest branch
3224 # check for ancestors of dest branch
3205 ancestors = repo.revs(b'%ld & (::.)', revs)
3225 ancestors = repo.revs(b'%ld & (::.)', revs)
3206 for rev in ancestors:
3226 for rev in ancestors:
3207 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3227 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3208
3228
3209 revs = [r for r in revs if r not in ancestors]
3229 revs = [r for r in revs if r not in ancestors]
3210
3230
3211 if not revs:
3231 if not revs:
3212 return -1
3232 return -1
3213
3233
3214 # analyze revs for earlier grafts
3234 # analyze revs for earlier grafts
3215 ids = {}
3235 ids = {}
3216 for ctx in repo.set(b"%ld", revs):
3236 for ctx in repo.set(b"%ld", revs):
3217 ids[ctx.hex()] = ctx.rev()
3237 ids[ctx.hex()] = ctx.rev()
3218 n = ctx.extra().get(b'source')
3238 n = ctx.extra().get(b'source')
3219 if n:
3239 if n:
3220 ids[n] = ctx.rev()
3240 ids[n] = ctx.rev()
3221
3241
3222 # check ancestors for earlier grafts
3242 # check ancestors for earlier grafts
3223 ui.debug(b'scanning for duplicate grafts\n')
3243 ui.debug(b'scanning for duplicate grafts\n')
3224
3244
3225 # The only changesets we can be sure doesn't contain grafts of any
3245 # The only changesets we can be sure doesn't contain grafts of any
3226 # revs, are the ones that are common ancestors of *all* revs:
3246 # revs, are the ones that are common ancestors of *all* revs:
3227 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3247 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3228 ctx = repo[rev]
3248 ctx = repo[rev]
3229 n = ctx.extra().get(b'source')
3249 n = ctx.extra().get(b'source')
3230 if n in ids:
3250 if n in ids:
3231 try:
3251 try:
3232 r = repo[n].rev()
3252 r = repo[n].rev()
3233 except error.RepoLookupError:
3253 except error.RepoLookupError:
3234 r = None
3254 r = None
3235 if r in revs:
3255 if r in revs:
3236 ui.warn(
3256 ui.warn(
3237 _(
3257 _(
3238 b'skipping revision %d:%s '
3258 b'skipping revision %d:%s '
3239 b'(already grafted to %d:%s)\n'
3259 b'(already grafted to %d:%s)\n'
3240 )
3260 )
3241 % (r, repo[r], rev, ctx)
3261 % (r, repo[r], rev, ctx)
3242 )
3262 )
3243 revs.remove(r)
3263 revs.remove(r)
3244 elif ids[n] in revs:
3264 elif ids[n] in revs:
3245 if r is None:
3265 if r is None:
3246 ui.warn(
3266 ui.warn(
3247 _(
3267 _(
3248 b'skipping already grafted revision %d:%s '
3268 b'skipping already grafted revision %d:%s '
3249 b'(%d:%s also has unknown origin %s)\n'
3269 b'(%d:%s also has unknown origin %s)\n'
3250 )
3270 )
3251 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3271 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3252 )
3272 )
3253 else:
3273 else:
3254 ui.warn(
3274 ui.warn(
3255 _(
3275 _(
3256 b'skipping already grafted revision %d:%s '
3276 b'skipping already grafted revision %d:%s '
3257 b'(%d:%s also has origin %d:%s)\n'
3277 b'(%d:%s also has origin %d:%s)\n'
3258 )
3278 )
3259 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3279 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3260 )
3280 )
3261 revs.remove(ids[n])
3281 revs.remove(ids[n])
3262 elif ctx.hex() in ids:
3282 elif ctx.hex() in ids:
3263 r = ids[ctx.hex()]
3283 r = ids[ctx.hex()]
3264 if r in revs:
3284 if r in revs:
3265 ui.warn(
3285 ui.warn(
3266 _(
3286 _(
3267 b'skipping already grafted revision %d:%s '
3287 b'skipping already grafted revision %d:%s '
3268 b'(was grafted from %d:%s)\n'
3288 b'(was grafted from %d:%s)\n'
3269 )
3289 )
3270 % (r, repo[r], rev, ctx)
3290 % (r, repo[r], rev, ctx)
3271 )
3291 )
3272 revs.remove(r)
3292 revs.remove(r)
3273 if not revs:
3293 if not revs:
3274 return -1
3294 return -1
3275
3295
3276 if opts.get('no_commit'):
3296 if opts.get('no_commit'):
3277 statedata[b'no_commit'] = True
3297 statedata[b'no_commit'] = True
3278 if opts.get('base'):
3298 if opts.get('base'):
3279 statedata[b'base'] = opts['base']
3299 statedata[b'base'] = opts['base']
3280 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3300 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3281 desc = b'%d:%s "%s"' % (
3301 desc = b'%d:%s "%s"' % (
3282 ctx.rev(),
3302 ctx.rev(),
3283 ctx,
3303 ctx,
3284 ctx.description().split(b'\n', 1)[0],
3304 ctx.description().split(b'\n', 1)[0],
3285 )
3305 )
3286 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3306 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3287 if names:
3307 if names:
3288 desc += b' (%s)' % b' '.join(names)
3308 desc += b' (%s)' % b' '.join(names)
3289 ui.status(_(b'grafting %s\n') % desc)
3309 ui.status(_(b'grafting %s\n') % desc)
3290 if opts.get('dry_run'):
3310 if opts.get('dry_run'):
3291 continue
3311 continue
3292
3312
3293 source = ctx.extra().get(b'source')
3313 source = ctx.extra().get(b'source')
3294 extra = {}
3314 extra = {}
3295 if source:
3315 if source:
3296 extra[b'source'] = source
3316 extra[b'source'] = source
3297 extra[b'intermediate-source'] = ctx.hex()
3317 extra[b'intermediate-source'] = ctx.hex()
3298 else:
3318 else:
3299 extra[b'source'] = ctx.hex()
3319 extra[b'source'] = ctx.hex()
3300 user = ctx.user()
3320 user = ctx.user()
3301 if opts.get('user'):
3321 if opts.get('user'):
3302 user = opts['user']
3322 user = opts['user']
3303 statedata[b'user'] = user
3323 statedata[b'user'] = user
3304 date = ctx.date()
3324 date = ctx.date()
3305 if opts.get('date'):
3325 if opts.get('date'):
3306 date = opts['date']
3326 date = opts['date']
3307 statedata[b'date'] = date
3327 statedata[b'date'] = date
3308 message = ctx.description()
3328 message = ctx.description()
3309 if opts.get('log'):
3329 if opts.get('log'):
3310 message += b'\n(grafted from %s)' % ctx.hex()
3330 message += b'\n(grafted from %s)' % ctx.hex()
3311 statedata[b'log'] = True
3331 statedata[b'log'] = True
3312
3332
3313 # we don't merge the first commit when continuing
3333 # we don't merge the first commit when continuing
3314 if not cont:
3334 if not cont:
3315 # perform the graft merge with p1(rev) as 'ancestor'
3335 # perform the graft merge with p1(rev) as 'ancestor'
3316 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
3336 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
3317 base = ctx.p1() if basectx is None else basectx
3337 base = ctx.p1() if basectx is None else basectx
3318 with ui.configoverride(overrides, b'graft'):
3338 with ui.configoverride(overrides, b'graft'):
3319 stats = mergemod.graft(
3339 stats = mergemod.graft(
3320 repo, ctx, base, [b'local', b'graft', b'parent of graft']
3340 repo, ctx, base, [b'local', b'graft', b'parent of graft']
3321 )
3341 )
3322 # report any conflicts
3342 # report any conflicts
3323 if stats.unresolvedcount > 0:
3343 if stats.unresolvedcount > 0:
3324 # write out state for --continue
3344 # write out state for --continue
3325 nodes = [repo[rev].hex() for rev in revs[pos:]]
3345 nodes = [repo[rev].hex() for rev in revs[pos:]]
3326 statedata[b'nodes'] = nodes
3346 statedata[b'nodes'] = nodes
3327 stateversion = 1
3347 stateversion = 1
3328 graftstate.save(stateversion, statedata)
3348 graftstate.save(stateversion, statedata)
3329 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3349 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3330 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3350 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3331 return 1
3351 return 1
3332 else:
3352 else:
3333 cont = False
3353 cont = False
3334
3354
3335 # commit if --no-commit is false
3355 # commit if --no-commit is false
3336 if not opts.get('no_commit'):
3356 if not opts.get('no_commit'):
3337 node = repo.commit(
3357 node = repo.commit(
3338 text=message, user=user, date=date, extra=extra, editor=editor
3358 text=message, user=user, date=date, extra=extra, editor=editor
3339 )
3359 )
3340 if node is None:
3360 if node is None:
3341 ui.warn(
3361 ui.warn(
3342 _(b'note: graft of %d:%s created no changes to commit\n')
3362 _(b'note: graft of %d:%s created no changes to commit\n')
3343 % (ctx.rev(), ctx)
3363 % (ctx.rev(), ctx)
3344 )
3364 )
3345 # checking that newnodes exist because old state files won't have it
3365 # checking that newnodes exist because old state files won't have it
3346 elif statedata.get(b'newnodes') is not None:
3366 elif statedata.get(b'newnodes') is not None:
3347 nn = statedata[b'newnodes']
3367 nn = statedata[b'newnodes']
3348 assert isinstance(nn, list) # list of bytes
3368 assert isinstance(nn, list) # list of bytes
3349 nn.append(node)
3369 nn.append(node)
3350
3370
3351 # remove state when we complete successfully
3371 # remove state when we complete successfully
3352 if not opts.get('dry_run'):
3372 if not opts.get('dry_run'):
3353 graftstate.delete()
3373 graftstate.delete()
3354
3374
3355 return 0
3375 return 0
3356
3376
3357
3377
3358 def _stopgraft(ui, repo, graftstate):
3378 def _stopgraft(ui, repo, graftstate):
3359 """stop the interrupted graft"""
3379 """stop the interrupted graft"""
3360 if not graftstate.exists():
3380 if not graftstate.exists():
3361 raise error.StateError(_(b"no interrupted graft found"))
3381 raise error.StateError(_(b"no interrupted graft found"))
3362 pctx = repo[b'.']
3382 pctx = repo[b'.']
3363 mergemod.clean_update(pctx)
3383 mergemod.clean_update(pctx)
3364 graftstate.delete()
3384 graftstate.delete()
3365 ui.status(_(b"stopped the interrupted graft\n"))
3385 ui.status(_(b"stopped the interrupted graft\n"))
3366 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3386 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3367 return 0
3387 return 0
3368
3388
3369
3389
3370 statemod.addunfinished(
3390 statemod.addunfinished(
3371 b'graft',
3391 b'graft',
3372 fname=b'graftstate',
3392 fname=b'graftstate',
3373 clearable=True,
3393 clearable=True,
3374 stopflag=True,
3394 stopflag=True,
3375 continueflag=True,
3395 continueflag=True,
3376 abortfunc=cmdutil.hgabortgraft,
3396 abortfunc=cmdutil.hgabortgraft,
3377 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3397 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3378 )
3398 )
3379
3399
3380
3400
3381 @command(
3401 @command(
3382 b'grep',
3402 b'grep',
3383 [
3403 [
3384 (b'0', b'print0', None, _(b'end fields with NUL')),
3404 (b'0', b'print0', None, _(b'end fields with NUL')),
3385 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3405 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3386 (
3406 (
3387 b'',
3407 b'',
3388 b'diff',
3408 b'diff',
3389 None,
3409 None,
3390 _(
3410 _(
3391 b'search revision differences for when the pattern was added '
3411 b'search revision differences for when the pattern was added '
3392 b'or removed'
3412 b'or removed'
3393 ),
3413 ),
3394 ),
3414 ),
3395 (b'a', b'text', None, _(b'treat all files as text')),
3415 (b'a', b'text', None, _(b'treat all files as text')),
3396 (
3416 (
3397 b'f',
3417 b'f',
3398 b'follow',
3418 b'follow',
3399 None,
3419 None,
3400 _(
3420 _(
3401 b'follow changeset history,'
3421 b'follow changeset history,'
3402 b' or file history across copies and renames'
3422 b' or file history across copies and renames'
3403 ),
3423 ),
3404 ),
3424 ),
3405 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3425 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3406 (
3426 (
3407 b'l',
3427 b'l',
3408 b'files-with-matches',
3428 b'files-with-matches',
3409 None,
3429 None,
3410 _(b'print only filenames and revisions that match'),
3430 _(b'print only filenames and revisions that match'),
3411 ),
3431 ),
3412 (b'n', b'line-number', None, _(b'print matching line numbers')),
3432 (b'n', b'line-number', None, _(b'print matching line numbers')),
3413 (
3433 (
3414 b'r',
3434 b'r',
3415 b'rev',
3435 b'rev',
3416 [],
3436 [],
3417 _(b'search files changed within revision range'),
3437 _(b'search files changed within revision range'),
3418 _(b'REV'),
3438 _(b'REV'),
3419 ),
3439 ),
3420 (
3440 (
3421 b'',
3441 b'',
3422 b'all-files',
3442 b'all-files',
3423 None,
3443 None,
3424 _(
3444 _(
3425 b'include all files in the changeset while grepping (DEPRECATED)'
3445 b'include all files in the changeset while grepping (DEPRECATED)'
3426 ),
3446 ),
3427 ),
3447 ),
3428 (b'u', b'user', None, _(b'list the author (long with -v)')),
3448 (b'u', b'user', None, _(b'list the author (long with -v)')),
3429 (b'd', b'date', None, _(b'list the date (short with -q)')),
3449 (b'd', b'date', None, _(b'list the date (short with -q)')),
3430 ]
3450 ]
3431 + formatteropts
3451 + formatteropts
3432 + walkopts,
3452 + walkopts,
3433 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3453 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3434 helpcategory=command.CATEGORY_FILE_CONTENTS,
3454 helpcategory=command.CATEGORY_FILE_CONTENTS,
3435 inferrepo=True,
3455 inferrepo=True,
3436 intents={INTENT_READONLY},
3456 intents={INTENT_READONLY},
3437 )
3457 )
3438 def grep(ui, repo, pattern, *pats, **opts):
3458 def grep(ui, repo, pattern, *pats, **opts):
3439 """search for a pattern in specified files
3459 """search for a pattern in specified files
3440
3460
3441 Search the working directory or revision history for a regular
3461 Search the working directory or revision history for a regular
3442 expression in the specified files for the entire repository.
3462 expression in the specified files for the entire repository.
3443
3463
3444 By default, grep searches the repository files in the working
3464 By default, grep searches the repository files in the working
3445 directory and prints the files where it finds a match. To specify
3465 directory and prints the files where it finds a match. To specify
3446 historical revisions instead of the working directory, use the
3466 historical revisions instead of the working directory, use the
3447 --rev flag.
3467 --rev flag.
3448
3468
3449 To search instead historical revision differences that contains a
3469 To search instead historical revision differences that contains a
3450 change in match status ("-" for a match that becomes a non-match,
3470 change in match status ("-" for a match that becomes a non-match,
3451 or "+" for a non-match that becomes a match), use the --diff flag.
3471 or "+" for a non-match that becomes a match), use the --diff flag.
3452
3472
3453 PATTERN can be any Python (roughly Perl-compatible) regular
3473 PATTERN can be any Python (roughly Perl-compatible) regular
3454 expression.
3474 expression.
3455
3475
3456 If no FILEs are specified and the --rev flag isn't supplied, all
3476 If no FILEs are specified and the --rev flag isn't supplied, all
3457 files in the working directory are searched. When using the --rev
3477 files in the working directory are searched. When using the --rev
3458 flag and specifying FILEs, use the --follow argument to also
3478 flag and specifying FILEs, use the --follow argument to also
3459 follow the specified FILEs across renames and copies.
3479 follow the specified FILEs across renames and copies.
3460
3480
3461 .. container:: verbose
3481 .. container:: verbose
3462
3482
3463 Template:
3483 Template:
3464
3484
3465 The following keywords are supported in addition to the common template
3485 The following keywords are supported in addition to the common template
3466 keywords and functions. See also :hg:`help templates`.
3486 keywords and functions. See also :hg:`help templates`.
3467
3487
3468 :change: String. Character denoting insertion ``+`` or removal ``-``.
3488 :change: String. Character denoting insertion ``+`` or removal ``-``.
3469 Available if ``--diff`` is specified.
3489 Available if ``--diff`` is specified.
3470 :lineno: Integer. Line number of the match.
3490 :lineno: Integer. Line number of the match.
3471 :path: String. Repository-absolute path of the file.
3491 :path: String. Repository-absolute path of the file.
3472 :texts: List of text chunks.
3492 :texts: List of text chunks.
3473
3493
3474 And each entry of ``{texts}`` provides the following sub-keywords.
3494 And each entry of ``{texts}`` provides the following sub-keywords.
3475
3495
3476 :matched: Boolean. True if the chunk matches the specified pattern.
3496 :matched: Boolean. True if the chunk matches the specified pattern.
3477 :text: String. Chunk content.
3497 :text: String. Chunk content.
3478
3498
3479 See :hg:`help templates.operators` for the list expansion syntax.
3499 See :hg:`help templates.operators` for the list expansion syntax.
3480
3500
3481 Returns 0 if a match is found, 1 otherwise.
3501 Returns 0 if a match is found, 1 otherwise.
3482
3502
3483 """
3503 """
3484 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3504 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3485 opts = pycompat.byteskwargs(opts)
3505 opts = pycompat.byteskwargs(opts)
3486 diff = opts.get(b'all') or opts.get(b'diff')
3506 diff = opts.get(b'all') or opts.get(b'diff')
3487 follow = opts.get(b'follow')
3507 follow = opts.get(b'follow')
3488 if opts.get(b'all_files') is None and not diff:
3508 if opts.get(b'all_files') is None and not diff:
3489 opts[b'all_files'] = True
3509 opts[b'all_files'] = True
3490 plaingrep = (
3510 plaingrep = (
3491 opts.get(b'all_files')
3511 opts.get(b'all_files')
3492 and not opts.get(b'rev')
3512 and not opts.get(b'rev')
3493 and not opts.get(b'follow')
3513 and not opts.get(b'follow')
3494 )
3514 )
3495 all_files = opts.get(b'all_files')
3515 all_files = opts.get(b'all_files')
3496 if plaingrep:
3516 if plaingrep:
3497 opts[b'rev'] = [b'wdir()']
3517 opts[b'rev'] = [b'wdir()']
3498
3518
3499 reflags = re.M
3519 reflags = re.M
3500 if opts.get(b'ignore_case'):
3520 if opts.get(b'ignore_case'):
3501 reflags |= re.I
3521 reflags |= re.I
3502 try:
3522 try:
3503 regexp = util.re.compile(pattern, reflags)
3523 regexp = util.re.compile(pattern, reflags)
3504 except re.error as inst:
3524 except re.error as inst:
3505 ui.warn(
3525 ui.warn(
3506 _(b"grep: invalid match pattern: %s\n")
3526 _(b"grep: invalid match pattern: %s\n")
3507 % stringutil.forcebytestr(inst)
3527 % stringutil.forcebytestr(inst)
3508 )
3528 )
3509 return 1
3529 return 1
3510 sep, eol = b':', b'\n'
3530 sep, eol = b':', b'\n'
3511 if opts.get(b'print0'):
3531 if opts.get(b'print0'):
3512 sep = eol = b'\0'
3532 sep = eol = b'\0'
3513
3533
3514 searcher = grepmod.grepsearcher(
3534 searcher = grepmod.grepsearcher(
3515 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3535 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3516 )
3536 )
3517
3537
3518 getfile = searcher._getfile
3538 getfile = searcher._getfile
3519
3539
3520 uipathfn = scmutil.getuipathfn(repo)
3540 uipathfn = scmutil.getuipathfn(repo)
3521
3541
3522 def display(fm, fn, ctx, pstates, states):
3542 def display(fm, fn, ctx, pstates, states):
3523 rev = scmutil.intrev(ctx)
3543 rev = scmutil.intrev(ctx)
3524 if fm.isplain():
3544 if fm.isplain():
3525 formatuser = ui.shortuser
3545 formatuser = ui.shortuser
3526 else:
3546 else:
3527 formatuser = pycompat.bytestr
3547 formatuser = pycompat.bytestr
3528 if ui.quiet:
3548 if ui.quiet:
3529 datefmt = b'%Y-%m-%d'
3549 datefmt = b'%Y-%m-%d'
3530 else:
3550 else:
3531 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3551 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3532 found = False
3552 found = False
3533
3553
3534 @util.cachefunc
3554 @util.cachefunc
3535 def binary():
3555 def binary():
3536 flog = getfile(fn)
3556 flog = getfile(fn)
3537 try:
3557 try:
3538 return stringutil.binary(flog.read(ctx.filenode(fn)))
3558 return stringutil.binary(flog.read(ctx.filenode(fn)))
3539 except error.WdirUnsupported:
3559 except error.WdirUnsupported:
3540 return ctx[fn].isbinary()
3560 return ctx[fn].isbinary()
3541
3561
3542 fieldnamemap = {b'linenumber': b'lineno'}
3562 fieldnamemap = {b'linenumber': b'lineno'}
3543 if diff:
3563 if diff:
3544 iter = grepmod.difflinestates(pstates, states)
3564 iter = grepmod.difflinestates(pstates, states)
3545 else:
3565 else:
3546 iter = [(b'', l) for l in states]
3566 iter = [(b'', l) for l in states]
3547 for change, l in iter:
3567 for change, l in iter:
3548 fm.startitem()
3568 fm.startitem()
3549 fm.context(ctx=ctx)
3569 fm.context(ctx=ctx)
3550 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3570 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3551 fm.plain(uipathfn(fn), label=b'grep.filename')
3571 fm.plain(uipathfn(fn), label=b'grep.filename')
3552
3572
3553 cols = [
3573 cols = [
3554 (b'rev', b'%d', rev, not plaingrep, b''),
3574 (b'rev', b'%d', rev, not plaingrep, b''),
3555 (
3575 (
3556 b'linenumber',
3576 b'linenumber',
3557 b'%d',
3577 b'%d',
3558 l.linenum,
3578 l.linenum,
3559 opts.get(b'line_number'),
3579 opts.get(b'line_number'),
3560 b'',
3580 b'',
3561 ),
3581 ),
3562 ]
3582 ]
3563 if diff:
3583 if diff:
3564 cols.append(
3584 cols.append(
3565 (
3585 (
3566 b'change',
3586 b'change',
3567 b'%s',
3587 b'%s',
3568 change,
3588 change,
3569 True,
3589 True,
3570 b'grep.inserted '
3590 b'grep.inserted '
3571 if change == b'+'
3591 if change == b'+'
3572 else b'grep.deleted ',
3592 else b'grep.deleted ',
3573 )
3593 )
3574 )
3594 )
3575 cols.extend(
3595 cols.extend(
3576 [
3596 [
3577 (
3597 (
3578 b'user',
3598 b'user',
3579 b'%s',
3599 b'%s',
3580 formatuser(ctx.user()),
3600 formatuser(ctx.user()),
3581 opts.get(b'user'),
3601 opts.get(b'user'),
3582 b'',
3602 b'',
3583 ),
3603 ),
3584 (
3604 (
3585 b'date',
3605 b'date',
3586 b'%s',
3606 b'%s',
3587 fm.formatdate(ctx.date(), datefmt),
3607 fm.formatdate(ctx.date(), datefmt),
3588 opts.get(b'date'),
3608 opts.get(b'date'),
3589 b'',
3609 b'',
3590 ),
3610 ),
3591 ]
3611 ]
3592 )
3612 )
3593 for name, fmt, data, cond, extra_label in cols:
3613 for name, fmt, data, cond, extra_label in cols:
3594 if cond:
3614 if cond:
3595 fm.plain(sep, label=b'grep.sep')
3615 fm.plain(sep, label=b'grep.sep')
3596 field = fieldnamemap.get(name, name)
3616 field = fieldnamemap.get(name, name)
3597 label = extra_label + (b'grep.%s' % name)
3617 label = extra_label + (b'grep.%s' % name)
3598 fm.condwrite(cond, field, fmt, data, label=label)
3618 fm.condwrite(cond, field, fmt, data, label=label)
3599 if not opts.get(b'files_with_matches'):
3619 if not opts.get(b'files_with_matches'):
3600 fm.plain(sep, label=b'grep.sep')
3620 fm.plain(sep, label=b'grep.sep')
3601 if not opts.get(b'text') and binary():
3621 if not opts.get(b'text') and binary():
3602 fm.plain(_(b" Binary file matches"))
3622 fm.plain(_(b" Binary file matches"))
3603 else:
3623 else:
3604 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3624 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3605 fm.plain(eol)
3625 fm.plain(eol)
3606 found = True
3626 found = True
3607 if opts.get(b'files_with_matches'):
3627 if opts.get(b'files_with_matches'):
3608 break
3628 break
3609 return found
3629 return found
3610
3630
3611 def displaymatches(fm, l):
3631 def displaymatches(fm, l):
3612 p = 0
3632 p = 0
3613 for s, e in l.findpos(regexp):
3633 for s, e in l.findpos(regexp):
3614 if p < s:
3634 if p < s:
3615 fm.startitem()
3635 fm.startitem()
3616 fm.write(b'text', b'%s', l.line[p:s])
3636 fm.write(b'text', b'%s', l.line[p:s])
3617 fm.data(matched=False)
3637 fm.data(matched=False)
3618 fm.startitem()
3638 fm.startitem()
3619 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3639 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3620 fm.data(matched=True)
3640 fm.data(matched=True)
3621 p = e
3641 p = e
3622 if p < len(l.line):
3642 if p < len(l.line):
3623 fm.startitem()
3643 fm.startitem()
3624 fm.write(b'text', b'%s', l.line[p:])
3644 fm.write(b'text', b'%s', l.line[p:])
3625 fm.data(matched=False)
3645 fm.data(matched=False)
3626 fm.end()
3646 fm.end()
3627
3647
3628 found = False
3648 found = False
3629
3649
3630 wopts = logcmdutil.walkopts(
3650 wopts = logcmdutil.walkopts(
3631 pats=pats,
3651 pats=pats,
3632 opts=opts,
3652 opts=opts,
3633 revspec=opts[b'rev'],
3653 revspec=opts[b'rev'],
3634 include_pats=opts[b'include'],
3654 include_pats=opts[b'include'],
3635 exclude_pats=opts[b'exclude'],
3655 exclude_pats=opts[b'exclude'],
3636 follow=follow,
3656 follow=follow,
3637 force_changelog_traversal=all_files,
3657 force_changelog_traversal=all_files,
3638 filter_revisions_by_pats=not all_files,
3658 filter_revisions_by_pats=not all_files,
3639 )
3659 )
3640 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3660 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3641
3661
3642 ui.pager(b'grep')
3662 ui.pager(b'grep')
3643 fm = ui.formatter(b'grep', opts)
3663 fm = ui.formatter(b'grep', opts)
3644 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3664 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3645 r = display(fm, fn, ctx, pstates, states)
3665 r = display(fm, fn, ctx, pstates, states)
3646 found = found or r
3666 found = found or r
3647 if r and not diff and not all_files:
3667 if r and not diff and not all_files:
3648 searcher.skipfile(fn, ctx.rev())
3668 searcher.skipfile(fn, ctx.rev())
3649 fm.end()
3669 fm.end()
3650
3670
3651 return not found
3671 return not found
3652
3672
3653
3673
3654 @command(
3674 @command(
3655 b'heads',
3675 b'heads',
3656 [
3676 [
3657 (
3677 (
3658 b'r',
3678 b'r',
3659 b'rev',
3679 b'rev',
3660 b'',
3680 b'',
3661 _(b'show only heads which are descendants of STARTREV'),
3681 _(b'show only heads which are descendants of STARTREV'),
3662 _(b'STARTREV'),
3682 _(b'STARTREV'),
3663 ),
3683 ),
3664 (b't', b'topo', False, _(b'show topological heads only')),
3684 (b't', b'topo', False, _(b'show topological heads only')),
3665 (
3685 (
3666 b'a',
3686 b'a',
3667 b'active',
3687 b'active',
3668 False,
3688 False,
3669 _(b'show active branchheads only (DEPRECATED)'),
3689 _(b'show active branchheads only (DEPRECATED)'),
3670 ),
3690 ),
3671 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3691 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3672 ]
3692 ]
3673 + templateopts,
3693 + templateopts,
3674 _(b'[-ct] [-r STARTREV] [REV]...'),
3694 _(b'[-ct] [-r STARTREV] [REV]...'),
3675 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3695 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3676 intents={INTENT_READONLY},
3696 intents={INTENT_READONLY},
3677 )
3697 )
3678 def heads(ui, repo, *branchrevs, **opts):
3698 def heads(ui, repo, *branchrevs, **opts):
3679 """show branch heads
3699 """show branch heads
3680
3700
3681 With no arguments, show all open branch heads in the repository.
3701 With no arguments, show all open branch heads in the repository.
3682 Branch heads are changesets that have no descendants on the
3702 Branch heads are changesets that have no descendants on the
3683 same branch. They are where development generally takes place and
3703 same branch. They are where development generally takes place and
3684 are the usual targets for update and merge operations.
3704 are the usual targets for update and merge operations.
3685
3705
3686 If one or more REVs are given, only open branch heads on the
3706 If one or more REVs are given, only open branch heads on the
3687 branches associated with the specified changesets are shown. This
3707 branches associated with the specified changesets are shown. This
3688 means that you can use :hg:`heads .` to see the heads on the
3708 means that you can use :hg:`heads .` to see the heads on the
3689 currently checked-out branch.
3709 currently checked-out branch.
3690
3710
3691 If -c/--closed is specified, also show branch heads marked closed
3711 If -c/--closed is specified, also show branch heads marked closed
3692 (see :hg:`commit --close-branch`).
3712 (see :hg:`commit --close-branch`).
3693
3713
3694 If STARTREV is specified, only those heads that are descendants of
3714 If STARTREV is specified, only those heads that are descendants of
3695 STARTREV will be displayed.
3715 STARTREV will be displayed.
3696
3716
3697 If -t/--topo is specified, named branch mechanics will be ignored and only
3717 If -t/--topo is specified, named branch mechanics will be ignored and only
3698 topological heads (changesets with no children) will be shown.
3718 topological heads (changesets with no children) will be shown.
3699
3719
3700 Returns 0 if matching heads are found, 1 if not.
3720 Returns 0 if matching heads are found, 1 if not.
3701 """
3721 """
3702
3722
3703 opts = pycompat.byteskwargs(opts)
3723 opts = pycompat.byteskwargs(opts)
3704 start = None
3724 start = None
3705 rev = opts.get(b'rev')
3725 rev = opts.get(b'rev')
3706 if rev:
3726 if rev:
3707 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3727 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3708 start = logcmdutil.revsingle(repo, rev, None).node()
3728 start = logcmdutil.revsingle(repo, rev, None).node()
3709
3729
3710 if opts.get(b'topo'):
3730 if opts.get(b'topo'):
3711 heads = [repo[h] for h in repo.heads(start)]
3731 heads = [repo[h] for h in repo.heads(start)]
3712 else:
3732 else:
3713 heads = []
3733 heads = []
3714 for branch in repo.branchmap():
3734 for branch in repo.branchmap():
3715 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3735 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3716 heads = [repo[h] for h in heads]
3736 heads = [repo[h] for h in heads]
3717
3737
3718 if branchrevs:
3738 if branchrevs:
3719 branches = {
3739 branches = {
3720 repo[r].branch() for r in logcmdutil.revrange(repo, branchrevs)
3740 repo[r].branch() for r in logcmdutil.revrange(repo, branchrevs)
3721 }
3741 }
3722 heads = [h for h in heads if h.branch() in branches]
3742 heads = [h for h in heads if h.branch() in branches]
3723
3743
3724 if opts.get(b'active') and branchrevs:
3744 if opts.get(b'active') and branchrevs:
3725 dagheads = repo.heads(start)
3745 dagheads = repo.heads(start)
3726 heads = [h for h in heads if h.node() in dagheads]
3746 heads = [h for h in heads if h.node() in dagheads]
3727
3747
3728 if branchrevs:
3748 if branchrevs:
3729 haveheads = {h.branch() for h in heads}
3749 haveheads = {h.branch() for h in heads}
3730 if branches - haveheads:
3750 if branches - haveheads:
3731 headless = b', '.join(b for b in branches - haveheads)
3751 headless = b', '.join(b for b in branches - haveheads)
3732 msg = _(b'no open branch heads found on branches %s')
3752 msg = _(b'no open branch heads found on branches %s')
3733 if opts.get(b'rev'):
3753 if opts.get(b'rev'):
3734 msg += _(b' (started at %s)') % opts[b'rev']
3754 msg += _(b' (started at %s)') % opts[b'rev']
3735 ui.warn((msg + b'\n') % headless)
3755 ui.warn((msg + b'\n') % headless)
3736
3756
3737 if not heads:
3757 if not heads:
3738 return 1
3758 return 1
3739
3759
3740 ui.pager(b'heads')
3760 ui.pager(b'heads')
3741 heads = sorted(heads, key=lambda x: -(x.rev()))
3761 heads = sorted(heads, key=lambda x: -(x.rev()))
3742 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3762 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3743 for ctx in heads:
3763 for ctx in heads:
3744 displayer.show(ctx)
3764 displayer.show(ctx)
3745 displayer.close()
3765 displayer.close()
3746
3766
3747
3767
3748 @command(
3768 @command(
3749 b'help',
3769 b'help',
3750 [
3770 [
3751 (b'e', b'extension', None, _(b'show only help for extensions')),
3771 (b'e', b'extension', None, _(b'show only help for extensions')),
3752 (b'c', b'command', None, _(b'show only help for commands')),
3772 (b'c', b'command', None, _(b'show only help for commands')),
3753 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3773 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3754 (
3774 (
3755 b's',
3775 b's',
3756 b'system',
3776 b'system',
3757 [],
3777 [],
3758 _(b'show help for specific platform(s)'),
3778 _(b'show help for specific platform(s)'),
3759 _(b'PLATFORM'),
3779 _(b'PLATFORM'),
3760 ),
3780 ),
3761 ],
3781 ],
3762 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3782 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3763 helpcategory=command.CATEGORY_HELP,
3783 helpcategory=command.CATEGORY_HELP,
3764 norepo=True,
3784 norepo=True,
3765 intents={INTENT_READONLY},
3785 intents={INTENT_READONLY},
3766 )
3786 )
3767 def help_(ui, name=None, **opts):
3787 def help_(ui, name=None, **opts):
3768 """show help for a given topic or a help overview
3788 """show help for a given topic or a help overview
3769
3789
3770 With no arguments, print a list of commands with short help messages.
3790 With no arguments, print a list of commands with short help messages.
3771
3791
3772 Given a topic, extension, or command name, print help for that
3792 Given a topic, extension, or command name, print help for that
3773 topic.
3793 topic.
3774
3794
3775 Returns 0 if successful.
3795 Returns 0 if successful.
3776 """
3796 """
3777
3797
3778 keep = opts.get('system') or []
3798 keep = opts.get('system') or []
3779 if len(keep) == 0:
3799 if len(keep) == 0:
3780 if pycompat.sysplatform.startswith(b'win'):
3800 if pycompat.sysplatform.startswith(b'win'):
3781 keep.append(b'windows')
3801 keep.append(b'windows')
3782 elif pycompat.sysplatform == b'OpenVMS':
3802 elif pycompat.sysplatform == b'OpenVMS':
3783 keep.append(b'vms')
3803 keep.append(b'vms')
3784 elif pycompat.sysplatform == b'plan9':
3804 elif pycompat.sysplatform == b'plan9':
3785 keep.append(b'plan9')
3805 keep.append(b'plan9')
3786 else:
3806 else:
3787 keep.append(b'unix')
3807 keep.append(b'unix')
3788 keep.append(pycompat.sysplatform.lower())
3808 keep.append(pycompat.sysplatform.lower())
3789 if ui.verbose:
3809 if ui.verbose:
3790 keep.append(b'verbose')
3810 keep.append(b'verbose')
3791
3811
3792 commands = sys.modules[__name__]
3812 commands = sys.modules[__name__]
3793 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3813 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3794 ui.pager(b'help')
3814 ui.pager(b'help')
3795 ui.write(formatted)
3815 ui.write(formatted)
3796
3816
3797
3817
3798 @command(
3818 @command(
3799 b'identify|id',
3819 b'identify|id',
3800 [
3820 [
3801 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3821 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3802 (b'n', b'num', None, _(b'show local revision number')),
3822 (b'n', b'num', None, _(b'show local revision number')),
3803 (b'i', b'id', None, _(b'show global revision id')),
3823 (b'i', b'id', None, _(b'show global revision id')),
3804 (b'b', b'branch', None, _(b'show branch')),
3824 (b'b', b'branch', None, _(b'show branch')),
3805 (b't', b'tags', None, _(b'show tags')),
3825 (b't', b'tags', None, _(b'show tags')),
3806 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3826 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3807 ]
3827 ]
3808 + remoteopts
3828 + remoteopts
3809 + formatteropts,
3829 + formatteropts,
3810 _(b'[-nibtB] [-r REV] [SOURCE]'),
3830 _(b'[-nibtB] [-r REV] [SOURCE]'),
3811 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3831 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3812 optionalrepo=True,
3832 optionalrepo=True,
3813 intents={INTENT_READONLY},
3833 intents={INTENT_READONLY},
3814 )
3834 )
3815 def identify(
3835 def identify(
3816 ui,
3836 ui,
3817 repo,
3837 repo,
3818 source=None,
3838 source=None,
3819 rev=None,
3839 rev=None,
3820 num=None,
3840 num=None,
3821 id=None,
3841 id=None,
3822 branch=None,
3842 branch=None,
3823 tags=None,
3843 tags=None,
3824 bookmarks=None,
3844 bookmarks=None,
3825 **opts
3845 **opts
3826 ):
3846 ):
3827 """identify the working directory or specified revision
3847 """identify the working directory or specified revision
3828
3848
3829 Print a summary identifying the repository state at REV using one or
3849 Print a summary identifying the repository state at REV using one or
3830 two parent hash identifiers, followed by a "+" if the working
3850 two parent hash identifiers, followed by a "+" if the working
3831 directory has uncommitted changes, the branch name (if not default),
3851 directory has uncommitted changes, the branch name (if not default),
3832 a list of tags, and a list of bookmarks.
3852 a list of tags, and a list of bookmarks.
3833
3853
3834 When REV is not given, print a summary of the current state of the
3854 When REV is not given, print a summary of the current state of the
3835 repository including the working directory. Specify -r. to get information
3855 repository including the working directory. Specify -r. to get information
3836 of the working directory parent without scanning uncommitted changes.
3856 of the working directory parent without scanning uncommitted changes.
3837
3857
3838 Specifying a path to a repository root or Mercurial bundle will
3858 Specifying a path to a repository root or Mercurial bundle will
3839 cause lookup to operate on that repository/bundle.
3859 cause lookup to operate on that repository/bundle.
3840
3860
3841 .. container:: verbose
3861 .. container:: verbose
3842
3862
3843 Template:
3863 Template:
3844
3864
3845 The following keywords are supported in addition to the common template
3865 The following keywords are supported in addition to the common template
3846 keywords and functions. See also :hg:`help templates`.
3866 keywords and functions. See also :hg:`help templates`.
3847
3867
3848 :dirty: String. Character ``+`` denoting if the working directory has
3868 :dirty: String. Character ``+`` denoting if the working directory has
3849 uncommitted changes.
3869 uncommitted changes.
3850 :id: String. One or two nodes, optionally followed by ``+``.
3870 :id: String. One or two nodes, optionally followed by ``+``.
3851 :parents: List of strings. Parent nodes of the changeset.
3871 :parents: List of strings. Parent nodes of the changeset.
3852
3872
3853 Examples:
3873 Examples:
3854
3874
3855 - generate a build identifier for the working directory::
3875 - generate a build identifier for the working directory::
3856
3876
3857 hg id --id > build-id.dat
3877 hg id --id > build-id.dat
3858
3878
3859 - find the revision corresponding to a tag::
3879 - find the revision corresponding to a tag::
3860
3880
3861 hg id -n -r 1.3
3881 hg id -n -r 1.3
3862
3882
3863 - check the most recent revision of a remote repository::
3883 - check the most recent revision of a remote repository::
3864
3884
3865 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3885 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3866
3886
3867 See :hg:`log` for generating more information about specific revisions,
3887 See :hg:`log` for generating more information about specific revisions,
3868 including full hash identifiers.
3888 including full hash identifiers.
3869
3889
3870 Returns 0 if successful.
3890 Returns 0 if successful.
3871 """
3891 """
3872
3892
3873 opts = pycompat.byteskwargs(opts)
3893 opts = pycompat.byteskwargs(opts)
3874 if not repo and not source:
3894 if not repo and not source:
3875 raise error.InputError(
3895 raise error.InputError(
3876 _(b"there is no Mercurial repository here (.hg not found)")
3896 _(b"there is no Mercurial repository here (.hg not found)")
3877 )
3897 )
3878
3898
3879 default = not (num or id or branch or tags or bookmarks)
3899 default = not (num or id or branch or tags or bookmarks)
3880 output = []
3900 output = []
3881 revs = []
3901 revs = []
3882
3902
3883 peer = None
3903 peer = None
3884 try:
3904 try:
3885 if source:
3905 if source:
3886 source, branches = urlutil.get_unique_pull_path(
3906 source, branches = urlutil.get_unique_pull_path(
3887 b'identify', repo, ui, source
3907 b'identify', repo, ui, source
3888 )
3908 )
3889 # only pass ui when no repo
3909 # only pass ui when no repo
3890 peer = hg.peer(repo or ui, opts, source)
3910 peer = hg.peer(repo or ui, opts, source)
3891 repo = peer.local()
3911 repo = peer.local()
3892 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3912 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3893
3913
3894 fm = ui.formatter(b'identify', opts)
3914 fm = ui.formatter(b'identify', opts)
3895 fm.startitem()
3915 fm.startitem()
3896
3916
3897 if not repo:
3917 if not repo:
3898 if num or branch or tags:
3918 if num or branch or tags:
3899 raise error.InputError(
3919 raise error.InputError(
3900 _(b"can't query remote revision number, branch, or tags")
3920 _(b"can't query remote revision number, branch, or tags")
3901 )
3921 )
3902 if not rev and revs:
3922 if not rev and revs:
3903 rev = revs[0]
3923 rev = revs[0]
3904 if not rev:
3924 if not rev:
3905 rev = b"tip"
3925 rev = b"tip"
3906
3926
3907 remoterev = peer.lookup(rev)
3927 remoterev = peer.lookup(rev)
3908 hexrev = fm.hexfunc(remoterev)
3928 hexrev = fm.hexfunc(remoterev)
3909 if default or id:
3929 if default or id:
3910 output = [hexrev]
3930 output = [hexrev]
3911 fm.data(id=hexrev)
3931 fm.data(id=hexrev)
3912
3932
3913 @util.cachefunc
3933 @util.cachefunc
3914 def getbms():
3934 def getbms():
3915 bms = []
3935 bms = []
3916
3936
3917 if b'bookmarks' in peer.listkeys(b'namespaces'):
3937 if b'bookmarks' in peer.listkeys(b'namespaces'):
3918 hexremoterev = hex(remoterev)
3938 hexremoterev = hex(remoterev)
3919 bms = [
3939 bms = [
3920 bm
3940 bm
3921 for bm, bmr in peer.listkeys(b'bookmarks').items()
3941 for bm, bmr in peer.listkeys(b'bookmarks').items()
3922 if bmr == hexremoterev
3942 if bmr == hexremoterev
3923 ]
3943 ]
3924
3944
3925 return sorted(bms)
3945 return sorted(bms)
3926
3946
3927 if fm.isplain():
3947 if fm.isplain():
3928 if bookmarks:
3948 if bookmarks:
3929 output.extend(getbms())
3949 output.extend(getbms())
3930 elif default and not ui.quiet:
3950 elif default and not ui.quiet:
3931 # multiple bookmarks for a single parent separated by '/'
3951 # multiple bookmarks for a single parent separated by '/'
3932 bm = b'/'.join(getbms())
3952 bm = b'/'.join(getbms())
3933 if bm:
3953 if bm:
3934 output.append(bm)
3954 output.append(bm)
3935 else:
3955 else:
3936 fm.data(node=hex(remoterev))
3956 fm.data(node=hex(remoterev))
3937 if bookmarks or b'bookmarks' in fm.datahint():
3957 if bookmarks or b'bookmarks' in fm.datahint():
3938 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3958 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3939 else:
3959 else:
3940 if rev:
3960 if rev:
3941 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3961 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3942 ctx = logcmdutil.revsingle(repo, rev, None)
3962 ctx = logcmdutil.revsingle(repo, rev, None)
3943
3963
3944 if ctx.rev() is None:
3964 if ctx.rev() is None:
3945 ctx = repo[None]
3965 ctx = repo[None]
3946 parents = ctx.parents()
3966 parents = ctx.parents()
3947 taglist = []
3967 taglist = []
3948 for p in parents:
3968 for p in parents:
3949 taglist.extend(p.tags())
3969 taglist.extend(p.tags())
3950
3970
3951 dirty = b""
3971 dirty = b""
3952 if ctx.dirty(missing=True, merge=False, branch=False):
3972 if ctx.dirty(missing=True, merge=False, branch=False):
3953 dirty = b'+'
3973 dirty = b'+'
3954 fm.data(dirty=dirty)
3974 fm.data(dirty=dirty)
3955
3975
3956 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3976 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3957 if default or id:
3977 if default or id:
3958 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3978 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3959 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3979 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3960
3980
3961 if num:
3981 if num:
3962 numoutput = [b"%d" % p.rev() for p in parents]
3982 numoutput = [b"%d" % p.rev() for p in parents]
3963 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3983 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3964
3984
3965 fm.data(
3985 fm.data(
3966 parents=fm.formatlist(
3986 parents=fm.formatlist(
3967 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3987 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3968 )
3988 )
3969 )
3989 )
3970 else:
3990 else:
3971 hexoutput = fm.hexfunc(ctx.node())
3991 hexoutput = fm.hexfunc(ctx.node())
3972 if default or id:
3992 if default or id:
3973 output = [hexoutput]
3993 output = [hexoutput]
3974 fm.data(id=hexoutput)
3994 fm.data(id=hexoutput)
3975
3995
3976 if num:
3996 if num:
3977 output.append(pycompat.bytestr(ctx.rev()))
3997 output.append(pycompat.bytestr(ctx.rev()))
3978 taglist = ctx.tags()
3998 taglist = ctx.tags()
3979
3999
3980 if default and not ui.quiet:
4000 if default and not ui.quiet:
3981 b = ctx.branch()
4001 b = ctx.branch()
3982 if b != b'default':
4002 if b != b'default':
3983 output.append(b"(%s)" % b)
4003 output.append(b"(%s)" % b)
3984
4004
3985 # multiple tags for a single parent separated by '/'
4005 # multiple tags for a single parent separated by '/'
3986 t = b'/'.join(taglist)
4006 t = b'/'.join(taglist)
3987 if t:
4007 if t:
3988 output.append(t)
4008 output.append(t)
3989
4009
3990 # multiple bookmarks for a single parent separated by '/'
4010 # multiple bookmarks for a single parent separated by '/'
3991 bm = b'/'.join(ctx.bookmarks())
4011 bm = b'/'.join(ctx.bookmarks())
3992 if bm:
4012 if bm:
3993 output.append(bm)
4013 output.append(bm)
3994 else:
4014 else:
3995 if branch:
4015 if branch:
3996 output.append(ctx.branch())
4016 output.append(ctx.branch())
3997
4017
3998 if tags:
4018 if tags:
3999 output.extend(taglist)
4019 output.extend(taglist)
4000
4020
4001 if bookmarks:
4021 if bookmarks:
4002 output.extend(ctx.bookmarks())
4022 output.extend(ctx.bookmarks())
4003
4023
4004 fm.data(node=ctx.hex())
4024 fm.data(node=ctx.hex())
4005 fm.data(branch=ctx.branch())
4025 fm.data(branch=ctx.branch())
4006 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4026 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4007 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4027 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4008 fm.context(ctx=ctx)
4028 fm.context(ctx=ctx)
4009
4029
4010 fm.plain(b"%s\n" % b' '.join(output))
4030 fm.plain(b"%s\n" % b' '.join(output))
4011 fm.end()
4031 fm.end()
4012 finally:
4032 finally:
4013 if peer:
4033 if peer:
4014 peer.close()
4034 peer.close()
4015
4035
4016
4036
4017 @command(
4037 @command(
4018 b'import|patch',
4038 b'import|patch',
4019 [
4039 [
4020 (
4040 (
4021 b'p',
4041 b'p',
4022 b'strip',
4042 b'strip',
4023 1,
4043 1,
4024 _(
4044 _(
4025 b'directory strip option for patch. This has the same '
4045 b'directory strip option for patch. This has the same '
4026 b'meaning as the corresponding patch option'
4046 b'meaning as the corresponding patch option'
4027 ),
4047 ),
4028 _(b'NUM'),
4048 _(b'NUM'),
4029 ),
4049 ),
4030 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4050 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4031 (b'', b'secret', None, _(b'use the secret phase for committing')),
4051 (b'', b'secret', None, _(b'use the secret phase for committing')),
4032 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4052 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4033 (
4053 (
4034 b'f',
4054 b'f',
4035 b'force',
4055 b'force',
4036 None,
4056 None,
4037 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4057 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4038 ),
4058 ),
4039 (
4059 (
4040 b'',
4060 b'',
4041 b'no-commit',
4061 b'no-commit',
4042 None,
4062 None,
4043 _(b"don't commit, just update the working directory"),
4063 _(b"don't commit, just update the working directory"),
4044 ),
4064 ),
4045 (
4065 (
4046 b'',
4066 b'',
4047 b'bypass',
4067 b'bypass',
4048 None,
4068 None,
4049 _(b"apply patch without touching the working directory"),
4069 _(b"apply patch without touching the working directory"),
4050 ),
4070 ),
4051 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4071 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4052 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4072 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4053 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4073 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4054 (
4074 (
4055 b'',
4075 b'',
4056 b'import-branch',
4076 b'import-branch',
4057 None,
4077 None,
4058 _(b'use any branch information in patch (implied by --exact)'),
4078 _(b'use any branch information in patch (implied by --exact)'),
4059 ),
4079 ),
4060 ]
4080 ]
4061 + commitopts
4081 + commitopts
4062 + commitopts2
4082 + commitopts2
4063 + similarityopts,
4083 + similarityopts,
4064 _(b'[OPTION]... PATCH...'),
4084 _(b'[OPTION]... PATCH...'),
4065 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4085 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4066 )
4086 )
4067 def import_(ui, repo, patch1=None, *patches, **opts):
4087 def import_(ui, repo, patch1=None, *patches, **opts):
4068 """import an ordered set of patches
4088 """import an ordered set of patches
4069
4089
4070 Import a list of patches and commit them individually (unless
4090 Import a list of patches and commit them individually (unless
4071 --no-commit is specified).
4091 --no-commit is specified).
4072
4092
4073 To read a patch from standard input (stdin), use "-" as the patch
4093 To read a patch from standard input (stdin), use "-" as the patch
4074 name. If a URL is specified, the patch will be downloaded from
4094 name. If a URL is specified, the patch will be downloaded from
4075 there.
4095 there.
4076
4096
4077 Import first applies changes to the working directory (unless
4097 Import first applies changes to the working directory (unless
4078 --bypass is specified), import will abort if there are outstanding
4098 --bypass is specified), import will abort if there are outstanding
4079 changes.
4099 changes.
4080
4100
4081 Use --bypass to apply and commit patches directly to the
4101 Use --bypass to apply and commit patches directly to the
4082 repository, without affecting the working directory. Without
4102 repository, without affecting the working directory. Without
4083 --exact, patches will be applied on top of the working directory
4103 --exact, patches will be applied on top of the working directory
4084 parent revision.
4104 parent revision.
4085
4105
4086 You can import a patch straight from a mail message. Even patches
4106 You can import a patch straight from a mail message. Even patches
4087 as attachments work (to use the body part, it must have type
4107 as attachments work (to use the body part, it must have type
4088 text/plain or text/x-patch). From and Subject headers of email
4108 text/plain or text/x-patch). From and Subject headers of email
4089 message are used as default committer and commit message. All
4109 message are used as default committer and commit message. All
4090 text/plain body parts before first diff are added to the commit
4110 text/plain body parts before first diff are added to the commit
4091 message.
4111 message.
4092
4112
4093 If the imported patch was generated by :hg:`export`, user and
4113 If the imported patch was generated by :hg:`export`, user and
4094 description from patch override values from message headers and
4114 description from patch override values from message headers and
4095 body. Values given on command line with -m/--message and -u/--user
4115 body. Values given on command line with -m/--message and -u/--user
4096 override these.
4116 override these.
4097
4117
4098 If --exact is specified, import will set the working directory to
4118 If --exact is specified, import will set the working directory to
4099 the parent of each patch before applying it, and will abort if the
4119 the parent of each patch before applying it, and will abort if the
4100 resulting changeset has a different ID than the one recorded in
4120 resulting changeset has a different ID than the one recorded in
4101 the patch. This will guard against various ways that portable
4121 the patch. This will guard against various ways that portable
4102 patch formats and mail systems might fail to transfer Mercurial
4122 patch formats and mail systems might fail to transfer Mercurial
4103 data or metadata. See :hg:`bundle` for lossless transmission.
4123 data or metadata. See :hg:`bundle` for lossless transmission.
4104
4124
4105 Use --partial to ensure a changeset will be created from the patch
4125 Use --partial to ensure a changeset will be created from the patch
4106 even if some hunks fail to apply. Hunks that fail to apply will be
4126 even if some hunks fail to apply. Hunks that fail to apply will be
4107 written to a <target-file>.rej file. Conflicts can then be resolved
4127 written to a <target-file>.rej file. Conflicts can then be resolved
4108 by hand before :hg:`commit --amend` is run to update the created
4128 by hand before :hg:`commit --amend` is run to update the created
4109 changeset. This flag exists to let people import patches that
4129 changeset. This flag exists to let people import patches that
4110 partially apply without losing the associated metadata (author,
4130 partially apply without losing the associated metadata (author,
4111 date, description, ...).
4131 date, description, ...).
4112
4132
4113 .. note::
4133 .. note::
4114
4134
4115 When no hunks apply cleanly, :hg:`import --partial` will create
4135 When no hunks apply cleanly, :hg:`import --partial` will create
4116 an empty changeset, importing only the patch metadata.
4136 an empty changeset, importing only the patch metadata.
4117
4137
4118 With -s/--similarity, hg will attempt to discover renames and
4138 With -s/--similarity, hg will attempt to discover renames and
4119 copies in the patch in the same way as :hg:`addremove`.
4139 copies in the patch in the same way as :hg:`addremove`.
4120
4140
4121 It is possible to use external patch programs to perform the patch
4141 It is possible to use external patch programs to perform the patch
4122 by setting the ``ui.patch`` configuration option. For the default
4142 by setting the ``ui.patch`` configuration option. For the default
4123 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4143 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4124 See :hg:`help config` for more information about configuration
4144 See :hg:`help config` for more information about configuration
4125 files and how to use these options.
4145 files and how to use these options.
4126
4146
4127 See :hg:`help dates` for a list of formats valid for -d/--date.
4147 See :hg:`help dates` for a list of formats valid for -d/--date.
4128
4148
4129 .. container:: verbose
4149 .. container:: verbose
4130
4150
4131 Examples:
4151 Examples:
4132
4152
4133 - import a traditional patch from a website and detect renames::
4153 - import a traditional patch from a website and detect renames::
4134
4154
4135 hg import -s 80 http://example.com/bugfix.patch
4155 hg import -s 80 http://example.com/bugfix.patch
4136
4156
4137 - import a changeset from an hgweb server::
4157 - import a changeset from an hgweb server::
4138
4158
4139 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4159 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4140
4160
4141 - import all the patches in an Unix-style mbox::
4161 - import all the patches in an Unix-style mbox::
4142
4162
4143 hg import incoming-patches.mbox
4163 hg import incoming-patches.mbox
4144
4164
4145 - import patches from stdin::
4165 - import patches from stdin::
4146
4166
4147 hg import -
4167 hg import -
4148
4168
4149 - attempt to exactly restore an exported changeset (not always
4169 - attempt to exactly restore an exported changeset (not always
4150 possible)::
4170 possible)::
4151
4171
4152 hg import --exact proposed-fix.patch
4172 hg import --exact proposed-fix.patch
4153
4173
4154 - use an external tool to apply a patch which is too fuzzy for
4174 - use an external tool to apply a patch which is too fuzzy for
4155 the default internal tool.
4175 the default internal tool.
4156
4176
4157 hg import --config ui.patch="patch --merge" fuzzy.patch
4177 hg import --config ui.patch="patch --merge" fuzzy.patch
4158
4178
4159 - change the default fuzzing from 2 to a less strict 7
4179 - change the default fuzzing from 2 to a less strict 7
4160
4180
4161 hg import --config ui.fuzz=7 fuzz.patch
4181 hg import --config ui.fuzz=7 fuzz.patch
4162
4182
4163 Returns 0 on success, 1 on partial success (see --partial).
4183 Returns 0 on success, 1 on partial success (see --partial).
4164 """
4184 """
4165
4185
4166 cmdutil.check_incompatible_arguments(
4186 cmdutil.check_incompatible_arguments(
4167 opts, 'no_commit', ['bypass', 'secret']
4187 opts, 'no_commit', ['bypass', 'secret']
4168 )
4188 )
4169 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4189 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4170 opts = pycompat.byteskwargs(opts)
4190 opts = pycompat.byteskwargs(opts)
4171 if not patch1:
4191 if not patch1:
4172 raise error.InputError(_(b'need at least one patch to import'))
4192 raise error.InputError(_(b'need at least one patch to import'))
4173
4193
4174 patches = (patch1,) + patches
4194 patches = (patch1,) + patches
4175
4195
4176 date = opts.get(b'date')
4196 date = opts.get(b'date')
4177 if date:
4197 if date:
4178 opts[b'date'] = dateutil.parsedate(date)
4198 opts[b'date'] = dateutil.parsedate(date)
4179
4199
4180 exact = opts.get(b'exact')
4200 exact = opts.get(b'exact')
4181 update = not opts.get(b'bypass')
4201 update = not opts.get(b'bypass')
4182 try:
4202 try:
4183 sim = float(opts.get(b'similarity') or 0)
4203 sim = float(opts.get(b'similarity') or 0)
4184 except ValueError:
4204 except ValueError:
4185 raise error.InputError(_(b'similarity must be a number'))
4205 raise error.InputError(_(b'similarity must be a number'))
4186 if sim < 0 or sim > 100:
4206 if sim < 0 or sim > 100:
4187 raise error.InputError(_(b'similarity must be between 0 and 100'))
4207 raise error.InputError(_(b'similarity must be between 0 and 100'))
4188 if sim and not update:
4208 if sim and not update:
4189 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4209 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4190
4210
4191 base = opts[b"base"]
4211 base = opts[b"base"]
4192 msgs = []
4212 msgs = []
4193 ret = 0
4213 ret = 0
4194
4214
4195 with repo.wlock():
4215 with repo.wlock():
4196 if update:
4216 if update:
4197 cmdutil.checkunfinished(repo)
4217 cmdutil.checkunfinished(repo)
4198 if exact or not opts.get(b'force'):
4218 if exact or not opts.get(b'force'):
4199 cmdutil.bailifchanged(repo)
4219 cmdutil.bailifchanged(repo)
4200
4220
4201 if not opts.get(b'no_commit'):
4221 if not opts.get(b'no_commit'):
4202 lock = repo.lock
4222 lock = repo.lock
4203 tr = lambda: repo.transaction(b'import')
4223 tr = lambda: repo.transaction(b'import')
4204 dsguard = util.nullcontextmanager
4224 dsguard = util.nullcontextmanager
4205 else:
4225 else:
4206 lock = util.nullcontextmanager
4226 lock = util.nullcontextmanager
4207 tr = util.nullcontextmanager
4227 tr = util.nullcontextmanager
4208 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4228 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4209 with lock(), tr(), dsguard():
4229 with lock(), tr(), dsguard():
4210 parents = repo[None].parents()
4230 parents = repo[None].parents()
4211 for patchurl in patches:
4231 for patchurl in patches:
4212 if patchurl == b'-':
4232 if patchurl == b'-':
4213 ui.status(_(b'applying patch from stdin\n'))
4233 ui.status(_(b'applying patch from stdin\n'))
4214 patchfile = ui.fin
4234 patchfile = ui.fin
4215 patchurl = b'stdin' # for error message
4235 patchurl = b'stdin' # for error message
4216 else:
4236 else:
4217 patchurl = os.path.join(base, patchurl)
4237 patchurl = os.path.join(base, patchurl)
4218 ui.status(_(b'applying %s\n') % patchurl)
4238 ui.status(_(b'applying %s\n') % patchurl)
4219 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4239 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4220
4240
4221 haspatch = False
4241 haspatch = False
4222 for hunk in patch.split(patchfile):
4242 for hunk in patch.split(patchfile):
4223 with patch.extract(ui, hunk) as patchdata:
4243 with patch.extract(ui, hunk) as patchdata:
4224 msg, node, rej = cmdutil.tryimportone(
4244 msg, node, rej = cmdutil.tryimportone(
4225 ui, repo, patchdata, parents, opts, msgs, hg.clean
4245 ui, repo, patchdata, parents, opts, msgs, hg.clean
4226 )
4246 )
4227 if msg:
4247 if msg:
4228 haspatch = True
4248 haspatch = True
4229 ui.note(msg + b'\n')
4249 ui.note(msg + b'\n')
4230 if update or exact:
4250 if update or exact:
4231 parents = repo[None].parents()
4251 parents = repo[None].parents()
4232 else:
4252 else:
4233 parents = [repo[node]]
4253 parents = [repo[node]]
4234 if rej:
4254 if rej:
4235 ui.write_err(_(b"patch applied partially\n"))
4255 ui.write_err(_(b"patch applied partially\n"))
4236 ui.write_err(
4256 ui.write_err(
4237 _(
4257 _(
4238 b"(fix the .rej files and run "
4258 b"(fix the .rej files and run "
4239 b"`hg commit --amend`)\n"
4259 b"`hg commit --amend`)\n"
4240 )
4260 )
4241 )
4261 )
4242 ret = 1
4262 ret = 1
4243 break
4263 break
4244
4264
4245 if not haspatch:
4265 if not haspatch:
4246 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4266 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4247
4267
4248 if msgs:
4268 if msgs:
4249 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4269 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4250 return ret
4270 return ret
4251
4271
4252
4272
4253 @command(
4273 @command(
4254 b'incoming|in',
4274 b'incoming|in',
4255 [
4275 [
4256 (
4276 (
4257 b'f',
4277 b'f',
4258 b'force',
4278 b'force',
4259 None,
4279 None,
4260 _(b'run even if remote repository is unrelated'),
4280 _(b'run even if remote repository is unrelated'),
4261 ),
4281 ),
4262 (b'n', b'newest-first', None, _(b'show newest record first')),
4282 (b'n', b'newest-first', None, _(b'show newest record first')),
4263 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4283 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4264 (
4284 (
4265 b'r',
4285 b'r',
4266 b'rev',
4286 b'rev',
4267 [],
4287 [],
4268 _(b'a remote changeset intended to be added'),
4288 _(b'a remote changeset intended to be added'),
4269 _(b'REV'),
4289 _(b'REV'),
4270 ),
4290 ),
4271 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4291 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4272 (
4292 (
4273 b'b',
4293 b'b',
4274 b'branch',
4294 b'branch',
4275 [],
4295 [],
4276 _(b'a specific branch you would like to pull'),
4296 _(b'a specific branch you would like to pull'),
4277 _(b'BRANCH'),
4297 _(b'BRANCH'),
4278 ),
4298 ),
4279 ]
4299 ]
4280 + logopts
4300 + logopts
4281 + remoteopts
4301 + remoteopts
4282 + subrepoopts,
4302 + subrepoopts,
4283 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4303 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4284 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4304 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4285 )
4305 )
4286 def incoming(ui, repo, source=b"default", **opts):
4306 def incoming(ui, repo, source=b"default", **opts):
4287 """show new changesets found in source
4307 """show new changesets found in source
4288
4308
4289 Show new changesets found in the specified path/URL or the default
4309 Show new changesets found in the specified path/URL or the default
4290 pull location. These are the changesets that would have been pulled
4310 pull location. These are the changesets that would have been pulled
4291 by :hg:`pull` at the time you issued this command.
4311 by :hg:`pull` at the time you issued this command.
4292
4312
4293 See pull for valid source format details.
4313 See pull for valid source format details.
4294
4314
4295 .. container:: verbose
4315 .. container:: verbose
4296
4316
4297 With -B/--bookmarks, the result of bookmark comparison between
4317 With -B/--bookmarks, the result of bookmark comparison between
4298 local and remote repositories is displayed. With -v/--verbose,
4318 local and remote repositories is displayed. With -v/--verbose,
4299 status is also displayed for each bookmark like below::
4319 status is also displayed for each bookmark like below::
4300
4320
4301 BM1 01234567890a added
4321 BM1 01234567890a added
4302 BM2 1234567890ab advanced
4322 BM2 1234567890ab advanced
4303 BM3 234567890abc diverged
4323 BM3 234567890abc diverged
4304 BM4 34567890abcd changed
4324 BM4 34567890abcd changed
4305
4325
4306 The action taken locally when pulling depends on the
4326 The action taken locally when pulling depends on the
4307 status of each bookmark:
4327 status of each bookmark:
4308
4328
4309 :``added``: pull will create it
4329 :``added``: pull will create it
4310 :``advanced``: pull will update it
4330 :``advanced``: pull will update it
4311 :``diverged``: pull will create a divergent bookmark
4331 :``diverged``: pull will create a divergent bookmark
4312 :``changed``: result depends on remote changesets
4332 :``changed``: result depends on remote changesets
4313
4333
4314 From the point of view of pulling behavior, bookmark
4334 From the point of view of pulling behavior, bookmark
4315 existing only in the remote repository are treated as ``added``,
4335 existing only in the remote repository are treated as ``added``,
4316 even if it is in fact locally deleted.
4336 even if it is in fact locally deleted.
4317
4337
4318 .. container:: verbose
4338 .. container:: verbose
4319
4339
4320 For remote repository, using --bundle avoids downloading the
4340 For remote repository, using --bundle avoids downloading the
4321 changesets twice if the incoming is followed by a pull.
4341 changesets twice if the incoming is followed by a pull.
4322
4342
4323 Examples:
4343 Examples:
4324
4344
4325 - show incoming changes with patches and full description::
4345 - show incoming changes with patches and full description::
4326
4346
4327 hg incoming -vp
4347 hg incoming -vp
4328
4348
4329 - show incoming changes excluding merges, store a bundle::
4349 - show incoming changes excluding merges, store a bundle::
4330
4350
4331 hg in -vpM --bundle incoming.hg
4351 hg in -vpM --bundle incoming.hg
4332 hg pull incoming.hg
4352 hg pull incoming.hg
4333
4353
4334 - briefly list changes inside a bundle::
4354 - briefly list changes inside a bundle::
4335
4355
4336 hg in changes.hg -T "{desc|firstline}\\n"
4356 hg in changes.hg -T "{desc|firstline}\\n"
4337
4357
4338 Returns 0 if there are incoming changes, 1 otherwise.
4358 Returns 0 if there are incoming changes, 1 otherwise.
4339 """
4359 """
4340 opts = pycompat.byteskwargs(opts)
4360 opts = pycompat.byteskwargs(opts)
4341 if opts.get(b'graph'):
4361 if opts.get(b'graph'):
4342 logcmdutil.checkunsupportedgraphflags([], opts)
4362 logcmdutil.checkunsupportedgraphflags([], opts)
4343
4363
4344 def display(other, chlist, displayer):
4364 def display(other, chlist, displayer):
4345 revdag = logcmdutil.graphrevs(other, chlist, opts)
4365 revdag = logcmdutil.graphrevs(other, chlist, opts)
4346 logcmdutil.displaygraph(
4366 logcmdutil.displaygraph(
4347 ui, repo, revdag, displayer, graphmod.asciiedges
4367 ui, repo, revdag, displayer, graphmod.asciiedges
4348 )
4368 )
4349
4369
4350 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4370 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4351 return 0
4371 return 0
4352
4372
4353 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4373 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4354
4374
4355 if opts.get(b'bookmarks'):
4375 if opts.get(b'bookmarks'):
4356 srcs = urlutil.get_pull_paths(repo, ui, [source])
4376 srcs = urlutil.get_pull_paths(repo, ui, [source])
4357 for path in srcs:
4377 for path in srcs:
4358 source, branches = urlutil.parseurl(
4378 source, branches = urlutil.parseurl(
4359 path.rawloc, opts.get(b'branch')
4379 path.rawloc, opts.get(b'branch')
4360 )
4380 )
4361 other = hg.peer(repo, opts, source)
4381 other = hg.peer(repo, opts, source)
4362 try:
4382 try:
4363 if b'bookmarks' not in other.listkeys(b'namespaces'):
4383 if b'bookmarks' not in other.listkeys(b'namespaces'):
4364 ui.warn(_(b"remote doesn't support bookmarks\n"))
4384 ui.warn(_(b"remote doesn't support bookmarks\n"))
4365 return 0
4385 return 0
4366 ui.pager(b'incoming')
4386 ui.pager(b'incoming')
4367 ui.status(
4387 ui.status(
4368 _(b'comparing with %s\n') % urlutil.hidepassword(source)
4388 _(b'comparing with %s\n') % urlutil.hidepassword(source)
4369 )
4389 )
4370 return bookmarks.incoming(
4390 return bookmarks.incoming(
4371 ui, repo, other, mode=path.bookmarks_mode
4391 ui, repo, other, mode=path.bookmarks_mode
4372 )
4392 )
4373 finally:
4393 finally:
4374 other.close()
4394 other.close()
4375
4395
4376 return hg.incoming(ui, repo, source, opts)
4396 return hg.incoming(ui, repo, source, opts)
4377
4397
4378
4398
4379 @command(
4399 @command(
4380 b'init',
4400 b'init',
4381 remoteopts,
4401 remoteopts,
4382 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4402 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4383 helpcategory=command.CATEGORY_REPO_CREATION,
4403 helpcategory=command.CATEGORY_REPO_CREATION,
4384 helpbasic=True,
4404 helpbasic=True,
4385 norepo=True,
4405 norepo=True,
4386 )
4406 )
4387 def init(ui, dest=b".", **opts):
4407 def init(ui, dest=b".", **opts):
4388 """create a new repository in the given directory
4408 """create a new repository in the given directory
4389
4409
4390 Initialize a new repository in the given directory. If the given
4410 Initialize a new repository in the given directory. If the given
4391 directory does not exist, it will be created.
4411 directory does not exist, it will be created.
4392
4412
4393 If no directory is given, the current directory is used.
4413 If no directory is given, the current directory is used.
4394
4414
4395 It is possible to specify an ``ssh://`` URL as the destination.
4415 It is possible to specify an ``ssh://`` URL as the destination.
4396 See :hg:`help urls` for more information.
4416 See :hg:`help urls` for more information.
4397
4417
4398 Returns 0 on success.
4418 Returns 0 on success.
4399 """
4419 """
4400 opts = pycompat.byteskwargs(opts)
4420 opts = pycompat.byteskwargs(opts)
4401 path = urlutil.get_clone_path(ui, dest)[1]
4421 path = urlutil.get_clone_path(ui, dest)[1]
4402 peer = hg.peer(ui, opts, path, create=True)
4422 peer = hg.peer(ui, opts, path, create=True)
4403 peer.close()
4423 peer.close()
4404
4424
4405
4425
4406 @command(
4426 @command(
4407 b'locate',
4427 b'locate',
4408 [
4428 [
4409 (
4429 (
4410 b'r',
4430 b'r',
4411 b'rev',
4431 b'rev',
4412 b'',
4432 b'',
4413 _(b'search the repository as it is in REV'),
4433 _(b'search the repository as it is in REV'),
4414 _(b'REV'),
4434 _(b'REV'),
4415 ),
4435 ),
4416 (
4436 (
4417 b'0',
4437 b'0',
4418 b'print0',
4438 b'print0',
4419 None,
4439 None,
4420 _(b'end filenames with NUL, for use with xargs'),
4440 _(b'end filenames with NUL, for use with xargs'),
4421 ),
4441 ),
4422 (
4442 (
4423 b'f',
4443 b'f',
4424 b'fullpath',
4444 b'fullpath',
4425 None,
4445 None,
4426 _(b'print complete paths from the filesystem root'),
4446 _(b'print complete paths from the filesystem root'),
4427 ),
4447 ),
4428 ]
4448 ]
4429 + walkopts,
4449 + walkopts,
4430 _(b'[OPTION]... [PATTERN]...'),
4450 _(b'[OPTION]... [PATTERN]...'),
4431 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4451 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4432 )
4452 )
4433 def locate(ui, repo, *pats, **opts):
4453 def locate(ui, repo, *pats, **opts):
4434 """locate files matching specific patterns (DEPRECATED)
4454 """locate files matching specific patterns (DEPRECATED)
4435
4455
4436 Print files under Mercurial control in the working directory whose
4456 Print files under Mercurial control in the working directory whose
4437 names match the given patterns.
4457 names match the given patterns.
4438
4458
4439 By default, this command searches all directories in the working
4459 By default, this command searches all directories in the working
4440 directory. To search just the current directory and its
4460 directory. To search just the current directory and its
4441 subdirectories, use "--include .".
4461 subdirectories, use "--include .".
4442
4462
4443 If no patterns are given to match, this command prints the names
4463 If no patterns are given to match, this command prints the names
4444 of all files under Mercurial control in the working directory.
4464 of all files under Mercurial control in the working directory.
4445
4465
4446 If you want to feed the output of this command into the "xargs"
4466 If you want to feed the output of this command into the "xargs"
4447 command, use the -0 option to both this command and "xargs". This
4467 command, use the -0 option to both this command and "xargs". This
4448 will avoid the problem of "xargs" treating single filenames that
4468 will avoid the problem of "xargs" treating single filenames that
4449 contain whitespace as multiple filenames.
4469 contain whitespace as multiple filenames.
4450
4470
4451 See :hg:`help files` for a more versatile command.
4471 See :hg:`help files` for a more versatile command.
4452
4472
4453 Returns 0 if a match is found, 1 otherwise.
4473 Returns 0 if a match is found, 1 otherwise.
4454 """
4474 """
4455 opts = pycompat.byteskwargs(opts)
4475 opts = pycompat.byteskwargs(opts)
4456 if opts.get(b'print0'):
4476 if opts.get(b'print0'):
4457 end = b'\0'
4477 end = b'\0'
4458 else:
4478 else:
4459 end = b'\n'
4479 end = b'\n'
4460 ctx = logcmdutil.revsingle(repo, opts.get(b'rev'), None)
4480 ctx = logcmdutil.revsingle(repo, opts.get(b'rev'), None)
4461
4481
4462 ret = 1
4482 ret = 1
4463 m = scmutil.match(
4483 m = scmutil.match(
4464 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4484 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4465 )
4485 )
4466
4486
4467 ui.pager(b'locate')
4487 ui.pager(b'locate')
4468 if ctx.rev() is None:
4488 if ctx.rev() is None:
4469 # When run on the working copy, "locate" includes removed files, so
4489 # When run on the working copy, "locate" includes removed files, so
4470 # we get the list of files from the dirstate.
4490 # we get the list of files from the dirstate.
4471 filesgen = sorted(repo.dirstate.matches(m))
4491 filesgen = sorted(repo.dirstate.matches(m))
4472 else:
4492 else:
4473 filesgen = ctx.matches(m)
4493 filesgen = ctx.matches(m)
4474 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4494 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4475 for abs in filesgen:
4495 for abs in filesgen:
4476 if opts.get(b'fullpath'):
4496 if opts.get(b'fullpath'):
4477 ui.write(repo.wjoin(abs), end)
4497 ui.write(repo.wjoin(abs), end)
4478 else:
4498 else:
4479 ui.write(uipathfn(abs), end)
4499 ui.write(uipathfn(abs), end)
4480 ret = 0
4500 ret = 0
4481
4501
4482 return ret
4502 return ret
4483
4503
4484
4504
4485 @command(
4505 @command(
4486 b'log|history',
4506 b'log|history',
4487 [
4507 [
4488 (
4508 (
4489 b'f',
4509 b'f',
4490 b'follow',
4510 b'follow',
4491 None,
4511 None,
4492 _(
4512 _(
4493 b'follow changeset history, or file history across copies and renames'
4513 b'follow changeset history, or file history across copies and renames'
4494 ),
4514 ),
4495 ),
4515 ),
4496 (
4516 (
4497 b'',
4517 b'',
4498 b'follow-first',
4518 b'follow-first',
4499 None,
4519 None,
4500 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4520 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4501 ),
4521 ),
4502 (
4522 (
4503 b'd',
4523 b'd',
4504 b'date',
4524 b'date',
4505 b'',
4525 b'',
4506 _(b'show revisions matching date spec'),
4526 _(b'show revisions matching date spec'),
4507 _(b'DATE'),
4527 _(b'DATE'),
4508 ),
4528 ),
4509 (b'C', b'copies', None, _(b'show copied files')),
4529 (b'C', b'copies', None, _(b'show copied files')),
4510 (
4530 (
4511 b'k',
4531 b'k',
4512 b'keyword',
4532 b'keyword',
4513 [],
4533 [],
4514 _(b'do case-insensitive search for a given text'),
4534 _(b'do case-insensitive search for a given text'),
4515 _(b'TEXT'),
4535 _(b'TEXT'),
4516 ),
4536 ),
4517 (
4537 (
4518 b'r',
4538 b'r',
4519 b'rev',
4539 b'rev',
4520 [],
4540 [],
4521 _(b'revisions to select or follow from'),
4541 _(b'revisions to select or follow from'),
4522 _(b'REV'),
4542 _(b'REV'),
4523 ),
4543 ),
4524 (
4544 (
4525 b'L',
4545 b'L',
4526 b'line-range',
4546 b'line-range',
4527 [],
4547 [],
4528 _(b'follow line range of specified file (EXPERIMENTAL)'),
4548 _(b'follow line range of specified file (EXPERIMENTAL)'),
4529 _(b'FILE,RANGE'),
4549 _(b'FILE,RANGE'),
4530 ),
4550 ),
4531 (
4551 (
4532 b'',
4552 b'',
4533 b'removed',
4553 b'removed',
4534 None,
4554 None,
4535 _(b'include revisions where files were removed'),
4555 _(b'include revisions where files were removed'),
4536 ),
4556 ),
4537 (
4557 (
4538 b'm',
4558 b'm',
4539 b'only-merges',
4559 b'only-merges',
4540 None,
4560 None,
4541 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4561 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4542 ),
4562 ),
4543 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4563 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4544 (
4564 (
4545 b'',
4565 b'',
4546 b'only-branch',
4566 b'only-branch',
4547 [],
4567 [],
4548 _(
4568 _(
4549 b'show only changesets within the given named branch (DEPRECATED)'
4569 b'show only changesets within the given named branch (DEPRECATED)'
4550 ),
4570 ),
4551 _(b'BRANCH'),
4571 _(b'BRANCH'),
4552 ),
4572 ),
4553 (
4573 (
4554 b'b',
4574 b'b',
4555 b'branch',
4575 b'branch',
4556 [],
4576 [],
4557 _(b'show changesets within the given named branch'),
4577 _(b'show changesets within the given named branch'),
4558 _(b'BRANCH'),
4578 _(b'BRANCH'),
4559 ),
4579 ),
4560 (
4580 (
4561 b'B',
4581 b'B',
4562 b'bookmark',
4582 b'bookmark',
4563 [],
4583 [],
4564 _(b"show changesets within the given bookmark"),
4584 _(b"show changesets within the given bookmark"),
4565 _(b'BOOKMARK'),
4585 _(b'BOOKMARK'),
4566 ),
4586 ),
4567 (
4587 (
4568 b'P',
4588 b'P',
4569 b'prune',
4589 b'prune',
4570 [],
4590 [],
4571 _(b'do not display revision or any of its ancestors'),
4591 _(b'do not display revision or any of its ancestors'),
4572 _(b'REV'),
4592 _(b'REV'),
4573 ),
4593 ),
4574 ]
4594 ]
4575 + logopts
4595 + logopts
4576 + walkopts,
4596 + walkopts,
4577 _(b'[OPTION]... [FILE]'),
4597 _(b'[OPTION]... [FILE]'),
4578 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4598 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4579 helpbasic=True,
4599 helpbasic=True,
4580 inferrepo=True,
4600 inferrepo=True,
4581 intents={INTENT_READONLY},
4601 intents={INTENT_READONLY},
4582 )
4602 )
4583 def log(ui, repo, *pats, **opts):
4603 def log(ui, repo, *pats, **opts):
4584 """show revision history of entire repository or files
4604 """show revision history of entire repository or files
4585
4605
4586 Print the revision history of the specified files or the entire
4606 Print the revision history of the specified files or the entire
4587 project.
4607 project.
4588
4608
4589 If no revision range is specified, the default is ``tip:0`` unless
4609 If no revision range is specified, the default is ``tip:0`` unless
4590 --follow is set.
4610 --follow is set.
4591
4611
4592 File history is shown without following rename or copy history of
4612 File history is shown without following rename or copy history of
4593 files. Use -f/--follow with a filename to follow history across
4613 files. Use -f/--follow with a filename to follow history across
4594 renames and copies. --follow without a filename will only show
4614 renames and copies. --follow without a filename will only show
4595 ancestors of the starting revisions. The starting revisions can be
4615 ancestors of the starting revisions. The starting revisions can be
4596 specified by -r/--rev, which default to the working directory parent.
4616 specified by -r/--rev, which default to the working directory parent.
4597
4617
4598 By default this command prints revision number and changeset id,
4618 By default this command prints revision number and changeset id,
4599 tags, non-trivial parents, user, date and time, and a summary for
4619 tags, non-trivial parents, user, date and time, and a summary for
4600 each commit. When the -v/--verbose switch is used, the list of
4620 each commit. When the -v/--verbose switch is used, the list of
4601 changed files and full commit message are shown.
4621 changed files and full commit message are shown.
4602
4622
4603 With --graph the revisions are shown as an ASCII art DAG with the most
4623 With --graph the revisions are shown as an ASCII art DAG with the most
4604 recent changeset at the top.
4624 recent changeset at the top.
4605 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4625 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4606 involved in an unresolved merge conflict, '_' closes a branch,
4626 involved in an unresolved merge conflict, '_' closes a branch,
4607 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4627 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4608 changeset from the lines below is a parent of the 'o' merge on the same
4628 changeset from the lines below is a parent of the 'o' merge on the same
4609 line.
4629 line.
4610 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4630 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4611 of a '|' indicates one or more revisions in a path are omitted.
4631 of a '|' indicates one or more revisions in a path are omitted.
4612
4632
4613 .. container:: verbose
4633 .. container:: verbose
4614
4634
4615 Use -L/--line-range FILE,M:N options to follow the history of lines
4635 Use -L/--line-range FILE,M:N options to follow the history of lines
4616 from M to N in FILE. With -p/--patch only diff hunks affecting
4636 from M to N in FILE. With -p/--patch only diff hunks affecting
4617 specified line range will be shown. This option requires --follow;
4637 specified line range will be shown. This option requires --follow;
4618 it can be specified multiple times. Currently, this option is not
4638 it can be specified multiple times. Currently, this option is not
4619 compatible with --graph. This option is experimental.
4639 compatible with --graph. This option is experimental.
4620
4640
4621 .. note::
4641 .. note::
4622
4642
4623 :hg:`log --patch` may generate unexpected diff output for merge
4643 :hg:`log --patch` may generate unexpected diff output for merge
4624 changesets, as it will only compare the merge changeset against
4644 changesets, as it will only compare the merge changeset against
4625 its first parent. Also, only files different from BOTH parents
4645 its first parent. Also, only files different from BOTH parents
4626 will appear in files:.
4646 will appear in files:.
4627
4647
4628 .. note::
4648 .. note::
4629
4649
4630 For performance reasons, :hg:`log FILE` may omit duplicate changes
4650 For performance reasons, :hg:`log FILE` may omit duplicate changes
4631 made on branches and will not show removals or mode changes. To
4651 made on branches and will not show removals or mode changes. To
4632 see all such changes, use the --removed switch.
4652 see all such changes, use the --removed switch.
4633
4653
4634 .. container:: verbose
4654 .. container:: verbose
4635
4655
4636 .. note::
4656 .. note::
4637
4657
4638 The history resulting from -L/--line-range options depends on diff
4658 The history resulting from -L/--line-range options depends on diff
4639 options; for instance if white-spaces are ignored, respective changes
4659 options; for instance if white-spaces are ignored, respective changes
4640 with only white-spaces in specified line range will not be listed.
4660 with only white-spaces in specified line range will not be listed.
4641
4661
4642 .. container:: verbose
4662 .. container:: verbose
4643
4663
4644 Some examples:
4664 Some examples:
4645
4665
4646 - changesets with full descriptions and file lists::
4666 - changesets with full descriptions and file lists::
4647
4667
4648 hg log -v
4668 hg log -v
4649
4669
4650 - changesets ancestral to the working directory::
4670 - changesets ancestral to the working directory::
4651
4671
4652 hg log -f
4672 hg log -f
4653
4673
4654 - last 10 commits on the current branch::
4674 - last 10 commits on the current branch::
4655
4675
4656 hg log -l 10 -b .
4676 hg log -l 10 -b .
4657
4677
4658 - changesets showing all modifications of a file, including removals::
4678 - changesets showing all modifications of a file, including removals::
4659
4679
4660 hg log --removed file.c
4680 hg log --removed file.c
4661
4681
4662 - all changesets that touch a directory, with diffs, excluding merges::
4682 - all changesets that touch a directory, with diffs, excluding merges::
4663
4683
4664 hg log -Mp lib/
4684 hg log -Mp lib/
4665
4685
4666 - all revision numbers that match a keyword::
4686 - all revision numbers that match a keyword::
4667
4687
4668 hg log -k bug --template "{rev}\\n"
4688 hg log -k bug --template "{rev}\\n"
4669
4689
4670 - the full hash identifier of the working directory parent::
4690 - the full hash identifier of the working directory parent::
4671
4691
4672 hg log -r . --template "{node}\\n"
4692 hg log -r . --template "{node}\\n"
4673
4693
4674 - list available log templates::
4694 - list available log templates::
4675
4695
4676 hg log -T list
4696 hg log -T list
4677
4697
4678 - check if a given changeset is included in a tagged release::
4698 - check if a given changeset is included in a tagged release::
4679
4699
4680 hg log -r "a21ccf and ancestor(1.9)"
4700 hg log -r "a21ccf and ancestor(1.9)"
4681
4701
4682 - find all changesets by some user in a date range::
4702 - find all changesets by some user in a date range::
4683
4703
4684 hg log -k alice -d "may 2008 to jul 2008"
4704 hg log -k alice -d "may 2008 to jul 2008"
4685
4705
4686 - summary of all changesets after the last tag::
4706 - summary of all changesets after the last tag::
4687
4707
4688 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4708 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4689
4709
4690 - changesets touching lines 13 to 23 for file.c::
4710 - changesets touching lines 13 to 23 for file.c::
4691
4711
4692 hg log -L file.c,13:23
4712 hg log -L file.c,13:23
4693
4713
4694 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4714 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4695 main.c with patch::
4715 main.c with patch::
4696
4716
4697 hg log -L file.c,13:23 -L main.c,2:6 -p
4717 hg log -L file.c,13:23 -L main.c,2:6 -p
4698
4718
4699 See :hg:`help dates` for a list of formats valid for -d/--date.
4719 See :hg:`help dates` for a list of formats valid for -d/--date.
4700
4720
4701 See :hg:`help revisions` for more about specifying and ordering
4721 See :hg:`help revisions` for more about specifying and ordering
4702 revisions.
4722 revisions.
4703
4723
4704 See :hg:`help templates` for more about pre-packaged styles and
4724 See :hg:`help templates` for more about pre-packaged styles and
4705 specifying custom templates. The default template used by the log
4725 specifying custom templates. The default template used by the log
4706 command can be customized via the ``command-templates.log`` configuration
4726 command can be customized via the ``command-templates.log`` configuration
4707 setting.
4727 setting.
4708
4728
4709 Returns 0 on success.
4729 Returns 0 on success.
4710
4730
4711 """
4731 """
4712 opts = pycompat.byteskwargs(opts)
4732 opts = pycompat.byteskwargs(opts)
4713 linerange = opts.get(b'line_range')
4733 linerange = opts.get(b'line_range')
4714
4734
4715 if linerange and not opts.get(b'follow'):
4735 if linerange and not opts.get(b'follow'):
4716 raise error.InputError(_(b'--line-range requires --follow'))
4736 raise error.InputError(_(b'--line-range requires --follow'))
4717
4737
4718 if linerange and pats:
4738 if linerange and pats:
4719 # TODO: take pats as patterns with no line-range filter
4739 # TODO: take pats as patterns with no line-range filter
4720 raise error.InputError(
4740 raise error.InputError(
4721 _(b'FILE arguments are not compatible with --line-range option')
4741 _(b'FILE arguments are not compatible with --line-range option')
4722 )
4742 )
4723
4743
4724 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4744 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4725 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4745 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4726 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4746 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4727 if linerange:
4747 if linerange:
4728 # TODO: should follow file history from logcmdutil._initialrevs(),
4748 # TODO: should follow file history from logcmdutil._initialrevs(),
4729 # then filter the result by logcmdutil._makerevset() and --limit
4749 # then filter the result by logcmdutil._makerevset() and --limit
4730 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4750 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4731
4751
4732 getcopies = None
4752 getcopies = None
4733 if opts.get(b'copies'):
4753 if opts.get(b'copies'):
4734 endrev = None
4754 endrev = None
4735 if revs:
4755 if revs:
4736 endrev = revs.max() + 1
4756 endrev = revs.max() + 1
4737 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4757 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4738
4758
4739 ui.pager(b'log')
4759 ui.pager(b'log')
4740 displayer = logcmdutil.changesetdisplayer(
4760 displayer = logcmdutil.changesetdisplayer(
4741 ui, repo, opts, differ, buffered=True
4761 ui, repo, opts, differ, buffered=True
4742 )
4762 )
4743 if opts.get(b'graph'):
4763 if opts.get(b'graph'):
4744 displayfn = logcmdutil.displaygraphrevs
4764 displayfn = logcmdutil.displaygraphrevs
4745 else:
4765 else:
4746 displayfn = logcmdutil.displayrevs
4766 displayfn = logcmdutil.displayrevs
4747 displayfn(ui, repo, revs, displayer, getcopies)
4767 displayfn(ui, repo, revs, displayer, getcopies)
4748
4768
4749
4769
4750 @command(
4770 @command(
4751 b'manifest',
4771 b'manifest',
4752 [
4772 [
4753 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4773 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4754 (b'', b'all', False, _(b"list files from all revisions")),
4774 (b'', b'all', False, _(b"list files from all revisions")),
4755 ]
4775 ]
4756 + formatteropts,
4776 + formatteropts,
4757 _(b'[-r REV]'),
4777 _(b'[-r REV]'),
4758 helpcategory=command.CATEGORY_MAINTENANCE,
4778 helpcategory=command.CATEGORY_MAINTENANCE,
4759 intents={INTENT_READONLY},
4779 intents={INTENT_READONLY},
4760 )
4780 )
4761 def manifest(ui, repo, node=None, rev=None, **opts):
4781 def manifest(ui, repo, node=None, rev=None, **opts):
4762 """output the current or given revision of the project manifest
4782 """output the current or given revision of the project manifest
4763
4783
4764 Print a list of version controlled files for the given revision.
4784 Print a list of version controlled files for the given revision.
4765 If no revision is given, the first parent of the working directory
4785 If no revision is given, the first parent of the working directory
4766 is used, or the null revision if no revision is checked out.
4786 is used, or the null revision if no revision is checked out.
4767
4787
4768 With -v, print file permissions, symlink and executable bits.
4788 With -v, print file permissions, symlink and executable bits.
4769 With --debug, print file revision hashes.
4789 With --debug, print file revision hashes.
4770
4790
4771 If option --all is specified, the list of all files from all revisions
4791 If option --all is specified, the list of all files from all revisions
4772 is printed. This includes deleted and renamed files.
4792 is printed. This includes deleted and renamed files.
4773
4793
4774 Returns 0 on success.
4794 Returns 0 on success.
4775 """
4795 """
4776 opts = pycompat.byteskwargs(opts)
4796 opts = pycompat.byteskwargs(opts)
4777 fm = ui.formatter(b'manifest', opts)
4797 fm = ui.formatter(b'manifest', opts)
4778
4798
4779 if opts.get(b'all'):
4799 if opts.get(b'all'):
4780 if rev or node:
4800 if rev or node:
4781 raise error.InputError(_(b"can't specify a revision with --all"))
4801 raise error.InputError(_(b"can't specify a revision with --all"))
4782
4802
4783 res = set()
4803 res = set()
4784 for rev in repo:
4804 for rev in repo:
4785 ctx = repo[rev]
4805 ctx = repo[rev]
4786 res |= set(ctx.files())
4806 res |= set(ctx.files())
4787
4807
4788 ui.pager(b'manifest')
4808 ui.pager(b'manifest')
4789 for f in sorted(res):
4809 for f in sorted(res):
4790 fm.startitem()
4810 fm.startitem()
4791 fm.write(b"path", b'%s\n', f)
4811 fm.write(b"path", b'%s\n', f)
4792 fm.end()
4812 fm.end()
4793 return
4813 return
4794
4814
4795 if rev and node:
4815 if rev and node:
4796 raise error.InputError(_(b"please specify just one revision"))
4816 raise error.InputError(_(b"please specify just one revision"))
4797
4817
4798 if not node:
4818 if not node:
4799 node = rev
4819 node = rev
4800
4820
4801 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4821 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4802 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4822 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4803 if node:
4823 if node:
4804 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4824 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4805 ctx = logcmdutil.revsingle(repo, node)
4825 ctx = logcmdutil.revsingle(repo, node)
4806 mf = ctx.manifest()
4826 mf = ctx.manifest()
4807 ui.pager(b'manifest')
4827 ui.pager(b'manifest')
4808 for f in ctx:
4828 for f in ctx:
4809 fm.startitem()
4829 fm.startitem()
4810 fm.context(ctx=ctx)
4830 fm.context(ctx=ctx)
4811 fl = ctx[f].flags()
4831 fl = ctx[f].flags()
4812 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4832 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4813 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4833 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4814 fm.write(b'path', b'%s\n', f)
4834 fm.write(b'path', b'%s\n', f)
4815 fm.end()
4835 fm.end()
4816
4836
4817
4837
4818 @command(
4838 @command(
4819 b'merge',
4839 b'merge',
4820 [
4840 [
4821 (
4841 (
4822 b'f',
4842 b'f',
4823 b'force',
4843 b'force',
4824 None,
4844 None,
4825 _(b'force a merge including outstanding changes (DEPRECATED)'),
4845 _(b'force a merge including outstanding changes (DEPRECATED)'),
4826 ),
4846 ),
4827 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4847 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4828 (
4848 (
4829 b'P',
4849 b'P',
4830 b'preview',
4850 b'preview',
4831 None,
4851 None,
4832 _(b'review revisions to merge (no merge is performed)'),
4852 _(b'review revisions to merge (no merge is performed)'),
4833 ),
4853 ),
4834 (b'', b'abort', None, _(b'abort the ongoing merge')),
4854 (b'', b'abort', None, _(b'abort the ongoing merge')),
4835 ]
4855 ]
4836 + mergetoolopts,
4856 + mergetoolopts,
4837 _(b'[-P] [[-r] REV]'),
4857 _(b'[-P] [[-r] REV]'),
4838 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4858 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4839 helpbasic=True,
4859 helpbasic=True,
4840 )
4860 )
4841 def merge(ui, repo, node=None, **opts):
4861 def merge(ui, repo, node=None, **opts):
4842 """merge another revision into working directory
4862 """merge another revision into working directory
4843
4863
4844 The current working directory is updated with all changes made in
4864 The current working directory is updated with all changes made in
4845 the requested revision since the last common predecessor revision.
4865 the requested revision since the last common predecessor revision.
4846
4866
4847 Files that changed between either parent are marked as changed for
4867 Files that changed between either parent are marked as changed for
4848 the next commit and a commit must be performed before any further
4868 the next commit and a commit must be performed before any further
4849 updates to the repository are allowed. The next commit will have
4869 updates to the repository are allowed. The next commit will have
4850 two parents.
4870 two parents.
4851
4871
4852 ``--tool`` can be used to specify the merge tool used for file
4872 ``--tool`` can be used to specify the merge tool used for file
4853 merges. It overrides the HGMERGE environment variable and your
4873 merges. It overrides the HGMERGE environment variable and your
4854 configuration files. See :hg:`help merge-tools` for options.
4874 configuration files. See :hg:`help merge-tools` for options.
4855
4875
4856 If no revision is specified, the working directory's parent is a
4876 If no revision is specified, the working directory's parent is a
4857 head revision, and the current branch contains exactly one other
4877 head revision, and the current branch contains exactly one other
4858 head, the other head is merged with by default. Otherwise, an
4878 head, the other head is merged with by default. Otherwise, an
4859 explicit revision with which to merge must be provided.
4879 explicit revision with which to merge must be provided.
4860
4880
4861 See :hg:`help resolve` for information on handling file conflicts.
4881 See :hg:`help resolve` for information on handling file conflicts.
4862
4882
4863 To undo an uncommitted merge, use :hg:`merge --abort` which
4883 To undo an uncommitted merge, use :hg:`merge --abort` which
4864 will check out a clean copy of the original merge parent, losing
4884 will check out a clean copy of the original merge parent, losing
4865 all changes.
4885 all changes.
4866
4886
4867 Returns 0 on success, 1 if there are unresolved files.
4887 Returns 0 on success, 1 if there are unresolved files.
4868 """
4888 """
4869
4889
4870 opts = pycompat.byteskwargs(opts)
4890 opts = pycompat.byteskwargs(opts)
4871 abort = opts.get(b'abort')
4891 abort = opts.get(b'abort')
4872 if abort and repo.dirstate.p2() == repo.nullid:
4892 if abort and repo.dirstate.p2() == repo.nullid:
4873 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4893 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4874 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4894 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4875 if abort:
4895 if abort:
4876 state = cmdutil.getunfinishedstate(repo)
4896 state = cmdutil.getunfinishedstate(repo)
4877 if state and state._opname != b'merge':
4897 if state and state._opname != b'merge':
4878 raise error.StateError(
4898 raise error.StateError(
4879 _(b'cannot abort merge with %s in progress') % (state._opname),
4899 _(b'cannot abort merge with %s in progress') % (state._opname),
4880 hint=state.hint(),
4900 hint=state.hint(),
4881 )
4901 )
4882 if node:
4902 if node:
4883 raise error.InputError(_(b"cannot specify a node with --abort"))
4903 raise error.InputError(_(b"cannot specify a node with --abort"))
4884 return hg.abortmerge(repo.ui, repo)
4904 return hg.abortmerge(repo.ui, repo)
4885
4905
4886 if opts.get(b'rev') and node:
4906 if opts.get(b'rev') and node:
4887 raise error.InputError(_(b"please specify just one revision"))
4907 raise error.InputError(_(b"please specify just one revision"))
4888 if not node:
4908 if not node:
4889 node = opts.get(b'rev')
4909 node = opts.get(b'rev')
4890
4910
4891 if node:
4911 if node:
4892 ctx = logcmdutil.revsingle(repo, node)
4912 ctx = logcmdutil.revsingle(repo, node)
4893 else:
4913 else:
4894 if ui.configbool(b'commands', b'merge.require-rev'):
4914 if ui.configbool(b'commands', b'merge.require-rev'):
4895 raise error.InputError(
4915 raise error.InputError(
4896 _(
4916 _(
4897 b'configuration requires specifying revision to merge '
4917 b'configuration requires specifying revision to merge '
4898 b'with'
4918 b'with'
4899 )
4919 )
4900 )
4920 )
4901 ctx = repo[destutil.destmerge(repo)]
4921 ctx = repo[destutil.destmerge(repo)]
4902
4922
4903 if ctx.node() is None:
4923 if ctx.node() is None:
4904 raise error.InputError(
4924 raise error.InputError(
4905 _(b'merging with the working copy has no effect')
4925 _(b'merging with the working copy has no effect')
4906 )
4926 )
4907
4927
4908 if opts.get(b'preview'):
4928 if opts.get(b'preview'):
4909 # find nodes that are ancestors of p2 but not of p1
4929 # find nodes that are ancestors of p2 but not of p1
4910 p1 = repo[b'.'].node()
4930 p1 = repo[b'.'].node()
4911 p2 = ctx.node()
4931 p2 = ctx.node()
4912 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4932 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4913
4933
4914 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4934 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4915 for node in nodes:
4935 for node in nodes:
4916 displayer.show(repo[node])
4936 displayer.show(repo[node])
4917 displayer.close()
4937 displayer.close()
4918 return 0
4938 return 0
4919
4939
4920 # ui.forcemerge is an internal variable, do not document
4940 # ui.forcemerge is an internal variable, do not document
4921 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4941 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4922 with ui.configoverride(overrides, b'merge'):
4942 with ui.configoverride(overrides, b'merge'):
4923 force = opts.get(b'force')
4943 force = opts.get(b'force')
4924 labels = [b'working copy', b'merge rev', b'common ancestor']
4944 labels = [b'working copy', b'merge rev', b'common ancestor']
4925 return hg.merge(ctx, force=force, labels=labels)
4945 return hg.merge(ctx, force=force, labels=labels)
4926
4946
4927
4947
4928 statemod.addunfinished(
4948 statemod.addunfinished(
4929 b'merge',
4949 b'merge',
4930 fname=None,
4950 fname=None,
4931 clearable=True,
4951 clearable=True,
4932 allowcommit=True,
4952 allowcommit=True,
4933 cmdmsg=_(b'outstanding uncommitted merge'),
4953 cmdmsg=_(b'outstanding uncommitted merge'),
4934 abortfunc=hg.abortmerge,
4954 abortfunc=hg.abortmerge,
4935 statushint=_(
4955 statushint=_(
4936 b'To continue: hg commit\nTo abort: hg merge --abort'
4956 b'To continue: hg commit\nTo abort: hg merge --abort'
4937 ),
4957 ),
4938 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4958 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4939 )
4959 )
4940
4960
4941
4961
4942 @command(
4962 @command(
4943 b'outgoing|out',
4963 b'outgoing|out',
4944 [
4964 [
4945 (
4965 (
4946 b'f',
4966 b'f',
4947 b'force',
4967 b'force',
4948 None,
4968 None,
4949 _(b'run even when the destination is unrelated'),
4969 _(b'run even when the destination is unrelated'),
4950 ),
4970 ),
4951 (
4971 (
4952 b'r',
4972 b'r',
4953 b'rev',
4973 b'rev',
4954 [],
4974 [],
4955 _(b'a changeset intended to be included in the destination'),
4975 _(b'a changeset intended to be included in the destination'),
4956 _(b'REV'),
4976 _(b'REV'),
4957 ),
4977 ),
4958 (b'n', b'newest-first', None, _(b'show newest record first')),
4978 (b'n', b'newest-first', None, _(b'show newest record first')),
4959 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4979 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4960 (
4980 (
4961 b'b',
4981 b'b',
4962 b'branch',
4982 b'branch',
4963 [],
4983 [],
4964 _(b'a specific branch you would like to push'),
4984 _(b'a specific branch you would like to push'),
4965 _(b'BRANCH'),
4985 _(b'BRANCH'),
4966 ),
4986 ),
4967 ]
4987 ]
4968 + logopts
4988 + logopts
4969 + remoteopts
4989 + remoteopts
4970 + subrepoopts,
4990 + subrepoopts,
4971 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]...'),
4991 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]...'),
4972 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4992 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4973 )
4993 )
4974 def outgoing(ui, repo, *dests, **opts):
4994 def outgoing(ui, repo, *dests, **opts):
4975 """show changesets not found in the destination
4995 """show changesets not found in the destination
4976
4996
4977 Show changesets not found in the specified destination repository
4997 Show changesets not found in the specified destination repository
4978 or the default push location. These are the changesets that would
4998 or the default push location. These are the changesets that would
4979 be pushed if a push was requested.
4999 be pushed if a push was requested.
4980
5000
4981 See pull for details of valid destination formats.
5001 See pull for details of valid destination formats.
4982
5002
4983 .. container:: verbose
5003 .. container:: verbose
4984
5004
4985 With -B/--bookmarks, the result of bookmark comparison between
5005 With -B/--bookmarks, the result of bookmark comparison between
4986 local and remote repositories is displayed. With -v/--verbose,
5006 local and remote repositories is displayed. With -v/--verbose,
4987 status is also displayed for each bookmark like below::
5007 status is also displayed for each bookmark like below::
4988
5008
4989 BM1 01234567890a added
5009 BM1 01234567890a added
4990 BM2 deleted
5010 BM2 deleted
4991 BM3 234567890abc advanced
5011 BM3 234567890abc advanced
4992 BM4 34567890abcd diverged
5012 BM4 34567890abcd diverged
4993 BM5 4567890abcde changed
5013 BM5 4567890abcde changed
4994
5014
4995 The action taken when pushing depends on the
5015 The action taken when pushing depends on the
4996 status of each bookmark:
5016 status of each bookmark:
4997
5017
4998 :``added``: push with ``-B`` will create it
5018 :``added``: push with ``-B`` will create it
4999 :``deleted``: push with ``-B`` will delete it
5019 :``deleted``: push with ``-B`` will delete it
5000 :``advanced``: push will update it
5020 :``advanced``: push will update it
5001 :``diverged``: push with ``-B`` will update it
5021 :``diverged``: push with ``-B`` will update it
5002 :``changed``: push with ``-B`` will update it
5022 :``changed``: push with ``-B`` will update it
5003
5023
5004 From the point of view of pushing behavior, bookmarks
5024 From the point of view of pushing behavior, bookmarks
5005 existing only in the remote repository are treated as
5025 existing only in the remote repository are treated as
5006 ``deleted``, even if it is in fact added remotely.
5026 ``deleted``, even if it is in fact added remotely.
5007
5027
5008 Returns 0 if there are outgoing changes, 1 otherwise.
5028 Returns 0 if there are outgoing changes, 1 otherwise.
5009 """
5029 """
5010 opts = pycompat.byteskwargs(opts)
5030 opts = pycompat.byteskwargs(opts)
5011 if opts.get(b'bookmarks'):
5031 if opts.get(b'bookmarks'):
5012 for path in urlutil.get_push_paths(repo, ui, dests):
5032 for path in urlutil.get_push_paths(repo, ui, dests):
5013 dest = path.pushloc or path.loc
5033 dest = path.pushloc or path.loc
5014 other = hg.peer(repo, opts, dest)
5034 other = hg.peer(repo, opts, dest)
5015 try:
5035 try:
5016 if b'bookmarks' not in other.listkeys(b'namespaces'):
5036 if b'bookmarks' not in other.listkeys(b'namespaces'):
5017 ui.warn(_(b"remote doesn't support bookmarks\n"))
5037 ui.warn(_(b"remote doesn't support bookmarks\n"))
5018 return 0
5038 return 0
5019 ui.status(
5039 ui.status(
5020 _(b'comparing with %s\n') % urlutil.hidepassword(dest)
5040 _(b'comparing with %s\n') % urlutil.hidepassword(dest)
5021 )
5041 )
5022 ui.pager(b'outgoing')
5042 ui.pager(b'outgoing')
5023 return bookmarks.outgoing(ui, repo, other)
5043 return bookmarks.outgoing(ui, repo, other)
5024 finally:
5044 finally:
5025 other.close()
5045 other.close()
5026
5046
5027 return hg.outgoing(ui, repo, dests, opts)
5047 return hg.outgoing(ui, repo, dests, opts)
5028
5048
5029
5049
5030 @command(
5050 @command(
5031 b'parents',
5051 b'parents',
5032 [
5052 [
5033 (
5053 (
5034 b'r',
5054 b'r',
5035 b'rev',
5055 b'rev',
5036 b'',
5056 b'',
5037 _(b'show parents of the specified revision'),
5057 _(b'show parents of the specified revision'),
5038 _(b'REV'),
5058 _(b'REV'),
5039 ),
5059 ),
5040 ]
5060 ]
5041 + templateopts,
5061 + templateopts,
5042 _(b'[-r REV] [FILE]'),
5062 _(b'[-r REV] [FILE]'),
5043 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5063 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5044 inferrepo=True,
5064 inferrepo=True,
5045 )
5065 )
5046 def parents(ui, repo, file_=None, **opts):
5066 def parents(ui, repo, file_=None, **opts):
5047 """show the parents of the working directory or revision (DEPRECATED)
5067 """show the parents of the working directory or revision (DEPRECATED)
5048
5068
5049 Print the working directory's parent revisions. If a revision is
5069 Print the working directory's parent revisions. If a revision is
5050 given via -r/--rev, the parent of that revision will be printed.
5070 given via -r/--rev, the parent of that revision will be printed.
5051 If a file argument is given, the revision in which the file was
5071 If a file argument is given, the revision in which the file was
5052 last changed (before the working directory revision or the
5072 last changed (before the working directory revision or the
5053 argument to --rev if given) is printed.
5073 argument to --rev if given) is printed.
5054
5074
5055 This command is equivalent to::
5075 This command is equivalent to::
5056
5076
5057 hg log -r "p1()+p2()" or
5077 hg log -r "p1()+p2()" or
5058 hg log -r "p1(REV)+p2(REV)" or
5078 hg log -r "p1(REV)+p2(REV)" or
5059 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5079 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5060 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5080 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5061
5081
5062 See :hg:`summary` and :hg:`help revsets` for related information.
5082 See :hg:`summary` and :hg:`help revsets` for related information.
5063
5083
5064 Returns 0 on success.
5084 Returns 0 on success.
5065 """
5085 """
5066
5086
5067 opts = pycompat.byteskwargs(opts)
5087 opts = pycompat.byteskwargs(opts)
5068 rev = opts.get(b'rev')
5088 rev = opts.get(b'rev')
5069 if rev:
5089 if rev:
5070 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5090 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5071 ctx = logcmdutil.revsingle(repo, rev, None)
5091 ctx = logcmdutil.revsingle(repo, rev, None)
5072
5092
5073 if file_:
5093 if file_:
5074 m = scmutil.match(ctx, (file_,), opts)
5094 m = scmutil.match(ctx, (file_,), opts)
5075 if m.anypats() or len(m.files()) != 1:
5095 if m.anypats() or len(m.files()) != 1:
5076 raise error.InputError(_(b'can only specify an explicit filename'))
5096 raise error.InputError(_(b'can only specify an explicit filename'))
5077 file_ = m.files()[0]
5097 file_ = m.files()[0]
5078 filenodes = []
5098 filenodes = []
5079 for cp in ctx.parents():
5099 for cp in ctx.parents():
5080 if not cp:
5100 if not cp:
5081 continue
5101 continue
5082 try:
5102 try:
5083 filenodes.append(cp.filenode(file_))
5103 filenodes.append(cp.filenode(file_))
5084 except error.LookupError:
5104 except error.LookupError:
5085 pass
5105 pass
5086 if not filenodes:
5106 if not filenodes:
5087 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5107 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5088 p = []
5108 p = []
5089 for fn in filenodes:
5109 for fn in filenodes:
5090 fctx = repo.filectx(file_, fileid=fn)
5110 fctx = repo.filectx(file_, fileid=fn)
5091 p.append(fctx.node())
5111 p.append(fctx.node())
5092 else:
5112 else:
5093 p = [cp.node() for cp in ctx.parents()]
5113 p = [cp.node() for cp in ctx.parents()]
5094
5114
5095 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5115 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5096 for n in p:
5116 for n in p:
5097 if n != repo.nullid:
5117 if n != repo.nullid:
5098 displayer.show(repo[n])
5118 displayer.show(repo[n])
5099 displayer.close()
5119 displayer.close()
5100
5120
5101
5121
5102 @command(
5122 @command(
5103 b'paths',
5123 b'paths',
5104 formatteropts,
5124 formatteropts,
5105 _(b'[NAME]'),
5125 _(b'[NAME]'),
5106 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5126 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5107 optionalrepo=True,
5127 optionalrepo=True,
5108 intents={INTENT_READONLY},
5128 intents={INTENT_READONLY},
5109 )
5129 )
5110 def paths(ui, repo, search=None, **opts):
5130 def paths(ui, repo, search=None, **opts):
5111 """show aliases for remote repositories
5131 """show aliases for remote repositories
5112
5132
5113 Show definition of symbolic path name NAME. If no name is given,
5133 Show definition of symbolic path name NAME. If no name is given,
5114 show definition of all available names.
5134 show definition of all available names.
5115
5135
5116 Option -q/--quiet suppresses all output when searching for NAME
5136 Option -q/--quiet suppresses all output when searching for NAME
5117 and shows only the path names when listing all definitions.
5137 and shows only the path names when listing all definitions.
5118
5138
5119 Path names are defined in the [paths] section of your
5139 Path names are defined in the [paths] section of your
5120 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5140 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5121 repository, ``.hg/hgrc`` is used, too.
5141 repository, ``.hg/hgrc`` is used, too.
5122
5142
5123 The path names ``default`` and ``default-push`` have a special
5143 The path names ``default`` and ``default-push`` have a special
5124 meaning. When performing a push or pull operation, they are used
5144 meaning. When performing a push or pull operation, they are used
5125 as fallbacks if no location is specified on the command-line.
5145 as fallbacks if no location is specified on the command-line.
5126 When ``default-push`` is set, it will be used for push and
5146 When ``default-push`` is set, it will be used for push and
5127 ``default`` will be used for pull; otherwise ``default`` is used
5147 ``default`` will be used for pull; otherwise ``default`` is used
5128 as the fallback for both. When cloning a repository, the clone
5148 as the fallback for both. When cloning a repository, the clone
5129 source is written as ``default`` in ``.hg/hgrc``.
5149 source is written as ``default`` in ``.hg/hgrc``.
5130
5150
5131 .. note::
5151 .. note::
5132
5152
5133 ``default`` and ``default-push`` apply to all inbound (e.g.
5153 ``default`` and ``default-push`` apply to all inbound (e.g.
5134 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5154 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5135 and :hg:`bundle`) operations.
5155 and :hg:`bundle`) operations.
5136
5156
5137 See :hg:`help urls` for more information.
5157 See :hg:`help urls` for more information.
5138
5158
5139 .. container:: verbose
5159 .. container:: verbose
5140
5160
5141 Template:
5161 Template:
5142
5162
5143 The following keywords are supported. See also :hg:`help templates`.
5163 The following keywords are supported. See also :hg:`help templates`.
5144
5164
5145 :name: String. Symbolic name of the path alias.
5165 :name: String. Symbolic name of the path alias.
5146 :pushurl: String. URL for push operations.
5166 :pushurl: String. URL for push operations.
5147 :url: String. URL or directory path for the other operations.
5167 :url: String. URL or directory path for the other operations.
5148
5168
5149 Returns 0 on success.
5169 Returns 0 on success.
5150 """
5170 """
5151
5171
5152 opts = pycompat.byteskwargs(opts)
5172 opts = pycompat.byteskwargs(opts)
5153
5173
5154 pathitems = urlutil.list_paths(ui, search)
5174 pathitems = urlutil.list_paths(ui, search)
5155 ui.pager(b'paths')
5175 ui.pager(b'paths')
5156
5176
5157 fm = ui.formatter(b'paths', opts)
5177 fm = ui.formatter(b'paths', opts)
5158 if fm.isplain():
5178 if fm.isplain():
5159 hidepassword = urlutil.hidepassword
5179 hidepassword = urlutil.hidepassword
5160 else:
5180 else:
5161 hidepassword = bytes
5181 hidepassword = bytes
5162 if ui.quiet:
5182 if ui.quiet:
5163 namefmt = b'%s\n'
5183 namefmt = b'%s\n'
5164 else:
5184 else:
5165 namefmt = b'%s = '
5185 namefmt = b'%s = '
5166 showsubopts = not search and not ui.quiet
5186 showsubopts = not search and not ui.quiet
5167
5187
5168 for name, path in pathitems:
5188 for name, path in pathitems:
5169 fm.startitem()
5189 fm.startitem()
5170 fm.condwrite(not search, b'name', namefmt, name)
5190 fm.condwrite(not search, b'name', namefmt, name)
5171 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5191 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5172 for subopt, value in sorted(path.suboptions.items()):
5192 for subopt, value in sorted(path.suboptions.items()):
5173 assert subopt not in (b'name', b'url')
5193 assert subopt not in (b'name', b'url')
5174 if showsubopts:
5194 if showsubopts:
5175 fm.plain(b'%s:%s = ' % (name, subopt))
5195 fm.plain(b'%s:%s = ' % (name, subopt))
5176 if isinstance(value, bool):
5196 if isinstance(value, bool):
5177 if value:
5197 if value:
5178 value = b'yes'
5198 value = b'yes'
5179 else:
5199 else:
5180 value = b'no'
5200 value = b'no'
5181 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5201 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5182
5202
5183 fm.end()
5203 fm.end()
5184
5204
5185 if search and not pathitems:
5205 if search and not pathitems:
5186 if not ui.quiet:
5206 if not ui.quiet:
5187 ui.warn(_(b"not found!\n"))
5207 ui.warn(_(b"not found!\n"))
5188 return 1
5208 return 1
5189 else:
5209 else:
5190 return 0
5210 return 0
5191
5211
5192
5212
5193 @command(
5213 @command(
5194 b'phase',
5214 b'phase',
5195 [
5215 [
5196 (b'p', b'public', False, _(b'set changeset phase to public')),
5216 (b'p', b'public', False, _(b'set changeset phase to public')),
5197 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5217 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5198 (b's', b'secret', False, _(b'set changeset phase to secret')),
5218 (b's', b'secret', False, _(b'set changeset phase to secret')),
5199 (b'f', b'force', False, _(b'allow to move boundary backward')),
5219 (b'f', b'force', False, _(b'allow to move boundary backward')),
5200 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5220 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5201 ],
5221 ],
5202 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5222 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5203 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5223 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5204 )
5224 )
5205 def phase(ui, repo, *revs, **opts):
5225 def phase(ui, repo, *revs, **opts):
5206 """set or show the current phase name
5226 """set or show the current phase name
5207
5227
5208 With no argument, show the phase name of the current revision(s).
5228 With no argument, show the phase name of the current revision(s).
5209
5229
5210 With one of -p/--public, -d/--draft or -s/--secret, change the
5230 With one of -p/--public, -d/--draft or -s/--secret, change the
5211 phase value of the specified revisions.
5231 phase value of the specified revisions.
5212
5232
5213 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5233 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5214 lower phase to a higher phase. Phases are ordered as follows::
5234 lower phase to a higher phase. Phases are ordered as follows::
5215
5235
5216 public < draft < secret
5236 public < draft < secret
5217
5237
5218 Returns 0 on success, 1 if some phases could not be changed.
5238 Returns 0 on success, 1 if some phases could not be changed.
5219
5239
5220 (For more information about the phases concept, see :hg:`help phases`.)
5240 (For more information about the phases concept, see :hg:`help phases`.)
5221 """
5241 """
5222 opts = pycompat.byteskwargs(opts)
5242 opts = pycompat.byteskwargs(opts)
5223 # search for a unique phase argument
5243 # search for a unique phase argument
5224 targetphase = None
5244 targetphase = None
5225 for idx, name in enumerate(phases.cmdphasenames):
5245 for idx, name in enumerate(phases.cmdphasenames):
5226 if opts[name]:
5246 if opts[name]:
5227 if targetphase is not None:
5247 if targetphase is not None:
5228 raise error.InputError(_(b'only one phase can be specified'))
5248 raise error.InputError(_(b'only one phase can be specified'))
5229 targetphase = idx
5249 targetphase = idx
5230
5250
5231 # look for specified revision
5251 # look for specified revision
5232 revs = list(revs)
5252 revs = list(revs)
5233 revs.extend(opts[b'rev'])
5253 revs.extend(opts[b'rev'])
5234 if revs:
5254 if revs:
5235 revs = logcmdutil.revrange(repo, revs)
5255 revs = logcmdutil.revrange(repo, revs)
5236 else:
5256 else:
5237 # display both parents as the second parent phase can influence
5257 # display both parents as the second parent phase can influence
5238 # the phase of a merge commit
5258 # the phase of a merge commit
5239 revs = [c.rev() for c in repo[None].parents()]
5259 revs = [c.rev() for c in repo[None].parents()]
5240
5260
5241 ret = 0
5261 ret = 0
5242 if targetphase is None:
5262 if targetphase is None:
5243 # display
5263 # display
5244 for r in revs:
5264 for r in revs:
5245 ctx = repo[r]
5265 ctx = repo[r]
5246 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5266 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5247 else:
5267 else:
5248 with repo.lock(), repo.transaction(b"phase") as tr:
5268 with repo.lock(), repo.transaction(b"phase") as tr:
5249 # set phase
5269 # set phase
5250 if not revs:
5270 if not revs:
5251 raise error.InputError(_(b'empty revision set'))
5271 raise error.InputError(_(b'empty revision set'))
5252 nodes = [repo[r].node() for r in revs]
5272 nodes = [repo[r].node() for r in revs]
5253 # moving revision from public to draft may hide them
5273 # moving revision from public to draft may hide them
5254 # We have to check result on an unfiltered repository
5274 # We have to check result on an unfiltered repository
5255 unfi = repo.unfiltered()
5275 unfi = repo.unfiltered()
5256 getphase = unfi._phasecache.phase
5276 getphase = unfi._phasecache.phase
5257 olddata = [getphase(unfi, r) for r in unfi]
5277 olddata = [getphase(unfi, r) for r in unfi]
5258 phases.advanceboundary(repo, tr, targetphase, nodes)
5278 phases.advanceboundary(repo, tr, targetphase, nodes)
5259 if opts[b'force']:
5279 if opts[b'force']:
5260 phases.retractboundary(repo, tr, targetphase, nodes)
5280 phases.retractboundary(repo, tr, targetphase, nodes)
5261 getphase = unfi._phasecache.phase
5281 getphase = unfi._phasecache.phase
5262 newdata = [getphase(unfi, r) for r in unfi]
5282 newdata = [getphase(unfi, r) for r in unfi]
5263 changes = sum(newdata[r] != olddata[r] for r in unfi)
5283 changes = sum(newdata[r] != olddata[r] for r in unfi)
5264 cl = unfi.changelog
5284 cl = unfi.changelog
5265 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5285 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5266 if rejected:
5286 if rejected:
5267 ui.warn(
5287 ui.warn(
5268 _(
5288 _(
5269 b'cannot move %i changesets to a higher '
5289 b'cannot move %i changesets to a higher '
5270 b'phase, use --force\n'
5290 b'phase, use --force\n'
5271 )
5291 )
5272 % len(rejected)
5292 % len(rejected)
5273 )
5293 )
5274 ret = 1
5294 ret = 1
5275 if changes:
5295 if changes:
5276 msg = _(b'phase changed for %i changesets\n') % changes
5296 msg = _(b'phase changed for %i changesets\n') % changes
5277 if ret:
5297 if ret:
5278 ui.status(msg)
5298 ui.status(msg)
5279 else:
5299 else:
5280 ui.note(msg)
5300 ui.note(msg)
5281 else:
5301 else:
5282 ui.warn(_(b'no phases changed\n'))
5302 ui.warn(_(b'no phases changed\n'))
5283 return ret
5303 return ret
5284
5304
5285
5305
5286 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5306 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5287 """Run after a changegroup has been added via pull/unbundle
5307 """Run after a changegroup has been added via pull/unbundle
5288
5308
5289 This takes arguments below:
5309 This takes arguments below:
5290
5310
5291 :modheads: change of heads by pull/unbundle
5311 :modheads: change of heads by pull/unbundle
5292 :optupdate: updating working directory is needed or not
5312 :optupdate: updating working directory is needed or not
5293 :checkout: update destination revision (or None to default destination)
5313 :checkout: update destination revision (or None to default destination)
5294 :brev: a name, which might be a bookmark to be activated after updating
5314 :brev: a name, which might be a bookmark to be activated after updating
5295
5315
5296 return True if update raise any conflict, False otherwise.
5316 return True if update raise any conflict, False otherwise.
5297 """
5317 """
5298 if modheads == 0:
5318 if modheads == 0:
5299 return False
5319 return False
5300 if optupdate:
5320 if optupdate:
5301 try:
5321 try:
5302 return hg.updatetotally(ui, repo, checkout, brev)
5322 return hg.updatetotally(ui, repo, checkout, brev)
5303 except error.UpdateAbort as inst:
5323 except error.UpdateAbort as inst:
5304 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5324 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5305 hint = inst.hint
5325 hint = inst.hint
5306 raise error.UpdateAbort(msg, hint=hint)
5326 raise error.UpdateAbort(msg, hint=hint)
5307 if modheads is not None and modheads > 1:
5327 if modheads is not None and modheads > 1:
5308 currentbranchheads = len(repo.branchheads())
5328 currentbranchheads = len(repo.branchheads())
5309 if currentbranchheads == modheads:
5329 if currentbranchheads == modheads:
5310 ui.status(
5330 ui.status(
5311 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5331 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5312 )
5332 )
5313 elif currentbranchheads > 1:
5333 elif currentbranchheads > 1:
5314 ui.status(
5334 ui.status(
5315 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5335 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5316 )
5336 )
5317 else:
5337 else:
5318 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5338 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5319 elif not ui.configbool(b'commands', b'update.requiredest'):
5339 elif not ui.configbool(b'commands', b'update.requiredest'):
5320 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5340 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5321 return False
5341 return False
5322
5342
5323
5343
5324 @command(
5344 @command(
5325 b'pull',
5345 b'pull',
5326 [
5346 [
5327 (
5347 (
5328 b'u',
5348 b'u',
5329 b'update',
5349 b'update',
5330 None,
5350 None,
5331 _(b'update to new branch head if new descendants were pulled'),
5351 _(b'update to new branch head if new descendants were pulled'),
5332 ),
5352 ),
5333 (
5353 (
5334 b'f',
5354 b'f',
5335 b'force',
5355 b'force',
5336 None,
5356 None,
5337 _(b'run even when remote repository is unrelated'),
5357 _(b'run even when remote repository is unrelated'),
5338 ),
5358 ),
5339 (
5359 (
5340 b'',
5360 b'',
5341 b'confirm',
5361 b'confirm',
5342 None,
5362 None,
5343 _(b'confirm pull before applying changes'),
5363 _(b'confirm pull before applying changes'),
5344 ),
5364 ),
5345 (
5365 (
5346 b'r',
5366 b'r',
5347 b'rev',
5367 b'rev',
5348 [],
5368 [],
5349 _(b'a remote changeset intended to be added'),
5369 _(b'a remote changeset intended to be added'),
5350 _(b'REV'),
5370 _(b'REV'),
5351 ),
5371 ),
5352 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5372 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5353 (
5373 (
5354 b'b',
5374 b'b',
5355 b'branch',
5375 b'branch',
5356 [],
5376 [],
5357 _(b'a specific branch you would like to pull'),
5377 _(b'a specific branch you would like to pull'),
5358 _(b'BRANCH'),
5378 _(b'BRANCH'),
5359 ),
5379 ),
5360 ]
5380 ]
5361 + remoteopts,
5381 + remoteopts,
5362 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]...'),
5382 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]...'),
5363 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5383 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5364 helpbasic=True,
5384 helpbasic=True,
5365 )
5385 )
5366 def pull(ui, repo, *sources, **opts):
5386 def pull(ui, repo, *sources, **opts):
5367 """pull changes from the specified source
5387 """pull changes from the specified source
5368
5388
5369 Pull changes from a remote repository to a local one.
5389 Pull changes from a remote repository to a local one.
5370
5390
5371 This finds all changes from the repository at the specified path
5391 This finds all changes from the repository at the specified path
5372 or URL and adds them to a local repository (the current one unless
5392 or URL and adds them to a local repository (the current one unless
5373 -R is specified). By default, this does not update the copy of the
5393 -R is specified). By default, this does not update the copy of the
5374 project in the working directory.
5394 project in the working directory.
5375
5395
5376 When cloning from servers that support it, Mercurial may fetch
5396 When cloning from servers that support it, Mercurial may fetch
5377 pre-generated data. When this is done, hooks operating on incoming
5397 pre-generated data. When this is done, hooks operating on incoming
5378 changesets and changegroups may fire more than once, once for each
5398 changesets and changegroups may fire more than once, once for each
5379 pre-generated bundle and as well as for any additional remaining
5399 pre-generated bundle and as well as for any additional remaining
5380 data. See :hg:`help -e clonebundles` for more.
5400 data. See :hg:`help -e clonebundles` for more.
5381
5401
5382 Use :hg:`incoming` if you want to see what would have been added
5402 Use :hg:`incoming` if you want to see what would have been added
5383 by a pull at the time you issued this command. If you then decide
5403 by a pull at the time you issued this command. If you then decide
5384 to add those changes to the repository, you should use :hg:`pull
5404 to add those changes to the repository, you should use :hg:`pull
5385 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5405 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5386
5406
5387 If SOURCE is omitted, the 'default' path will be used.
5407 If SOURCE is omitted, the 'default' path will be used.
5388 See :hg:`help urls` for more information.
5408 See :hg:`help urls` for more information.
5389
5409
5390 If multiple sources are specified, they will be pulled sequentially as if
5410 If multiple sources are specified, they will be pulled sequentially as if
5391 the command was run multiple time. If --update is specify and the command
5411 the command was run multiple time. If --update is specify and the command
5392 will stop at the first failed --update.
5412 will stop at the first failed --update.
5393
5413
5394 Specifying bookmark as ``.`` is equivalent to specifying the active
5414 Specifying bookmark as ``.`` is equivalent to specifying the active
5395 bookmark's name.
5415 bookmark's name.
5396
5416
5397 Returns 0 on success, 1 if an update had unresolved files.
5417 Returns 0 on success, 1 if an update had unresolved files.
5398 """
5418 """
5399
5419
5400 opts = pycompat.byteskwargs(opts)
5420 opts = pycompat.byteskwargs(opts)
5401 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5421 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5402 b'update'
5422 b'update'
5403 ):
5423 ):
5404 msg = _(b'update destination required by configuration')
5424 msg = _(b'update destination required by configuration')
5405 hint = _(b'use hg pull followed by hg update DEST')
5425 hint = _(b'use hg pull followed by hg update DEST')
5406 raise error.InputError(msg, hint=hint)
5426 raise error.InputError(msg, hint=hint)
5407
5427
5408 for path in urlutil.get_pull_paths(repo, ui, sources):
5428 for path in urlutil.get_pull_paths(repo, ui, sources):
5409 source, branches = urlutil.parseurl(path.rawloc, opts.get(b'branch'))
5429 source, branches = urlutil.parseurl(path.rawloc, opts.get(b'branch'))
5410 ui.status(_(b'pulling from %s\n') % urlutil.hidepassword(source))
5430 ui.status(_(b'pulling from %s\n') % urlutil.hidepassword(source))
5411 ui.flush()
5431 ui.flush()
5412 other = hg.peer(repo, opts, source)
5432 other = hg.peer(repo, opts, source)
5413 update_conflict = None
5433 update_conflict = None
5414 try:
5434 try:
5415 revs, checkout = hg.addbranchrevs(
5435 revs, checkout = hg.addbranchrevs(
5416 repo, other, branches, opts.get(b'rev')
5436 repo, other, branches, opts.get(b'rev')
5417 )
5437 )
5418
5438
5419 pullopargs = {}
5439 pullopargs = {}
5420
5440
5421 nodes = None
5441 nodes = None
5422 if opts.get(b'bookmark') or revs:
5442 if opts.get(b'bookmark') or revs:
5423 # The list of bookmark used here is the same used to actually update
5443 # The list of bookmark used here is the same used to actually update
5424 # the bookmark names, to avoid the race from issue 4689 and we do
5444 # the bookmark names, to avoid the race from issue 4689 and we do
5425 # all lookup and bookmark queries in one go so they see the same
5445 # all lookup and bookmark queries in one go so they see the same
5426 # version of the server state (issue 4700).
5446 # version of the server state (issue 4700).
5427 nodes = []
5447 nodes = []
5428 fnodes = []
5448 fnodes = []
5429 revs = revs or []
5449 revs = revs or []
5430 if revs and not other.capable(b'lookup'):
5450 if revs and not other.capable(b'lookup'):
5431 err = _(
5451 err = _(
5432 b"other repository doesn't support revision lookup, "
5452 b"other repository doesn't support revision lookup, "
5433 b"so a rev cannot be specified."
5453 b"so a rev cannot be specified."
5434 )
5454 )
5435 raise error.Abort(err)
5455 raise error.Abort(err)
5436 with other.commandexecutor() as e:
5456 with other.commandexecutor() as e:
5437 fremotebookmarks = e.callcommand(
5457 fremotebookmarks = e.callcommand(
5438 b'listkeys', {b'namespace': b'bookmarks'}
5458 b'listkeys', {b'namespace': b'bookmarks'}
5439 )
5459 )
5440 for r in revs:
5460 for r in revs:
5441 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5461 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5442 remotebookmarks = fremotebookmarks.result()
5462 remotebookmarks = fremotebookmarks.result()
5443 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5463 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5444 pullopargs[b'remotebookmarks'] = remotebookmarks
5464 pullopargs[b'remotebookmarks'] = remotebookmarks
5445 for b in opts.get(b'bookmark', []):
5465 for b in opts.get(b'bookmark', []):
5446 b = repo._bookmarks.expandname(b)
5466 b = repo._bookmarks.expandname(b)
5447 if b not in remotebookmarks:
5467 if b not in remotebookmarks:
5448 raise error.InputError(
5468 raise error.InputError(
5449 _(b'remote bookmark %s not found!') % b
5469 _(b'remote bookmark %s not found!') % b
5450 )
5470 )
5451 nodes.append(remotebookmarks[b])
5471 nodes.append(remotebookmarks[b])
5452 for i, rev in enumerate(revs):
5472 for i, rev in enumerate(revs):
5453 node = fnodes[i].result()
5473 node = fnodes[i].result()
5454 nodes.append(node)
5474 nodes.append(node)
5455 if rev == checkout:
5475 if rev == checkout:
5456 checkout = node
5476 checkout = node
5457
5477
5458 wlock = util.nullcontextmanager()
5478 wlock = util.nullcontextmanager()
5459 if opts.get(b'update'):
5479 if opts.get(b'update'):
5460 wlock = repo.wlock()
5480 wlock = repo.wlock()
5461 with wlock:
5481 with wlock:
5462 pullopargs.update(opts.get(b'opargs', {}))
5482 pullopargs.update(opts.get(b'opargs', {}))
5463 modheads = exchange.pull(
5483 modheads = exchange.pull(
5464 repo,
5484 repo,
5465 other,
5485 other,
5466 path=path,
5486 path=path,
5467 heads=nodes,
5487 heads=nodes,
5468 force=opts.get(b'force'),
5488 force=opts.get(b'force'),
5469 bookmarks=opts.get(b'bookmark', ()),
5489 bookmarks=opts.get(b'bookmark', ()),
5470 opargs=pullopargs,
5490 opargs=pullopargs,
5471 confirm=opts.get(b'confirm'),
5491 confirm=opts.get(b'confirm'),
5472 ).cgresult
5492 ).cgresult
5473
5493
5474 # brev is a name, which might be a bookmark to be activated at
5494 # brev is a name, which might be a bookmark to be activated at
5475 # the end of the update. In other words, it is an explicit
5495 # the end of the update. In other words, it is an explicit
5476 # destination of the update
5496 # destination of the update
5477 brev = None
5497 brev = None
5478
5498
5479 if checkout:
5499 if checkout:
5480 checkout = repo.unfiltered().changelog.rev(checkout)
5500 checkout = repo.unfiltered().changelog.rev(checkout)
5481
5501
5482 # order below depends on implementation of
5502 # order below depends on implementation of
5483 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5503 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5484 # because 'checkout' is determined without it.
5504 # because 'checkout' is determined without it.
5485 if opts.get(b'rev'):
5505 if opts.get(b'rev'):
5486 brev = opts[b'rev'][0]
5506 brev = opts[b'rev'][0]
5487 elif opts.get(b'branch'):
5507 elif opts.get(b'branch'):
5488 brev = opts[b'branch'][0]
5508 brev = opts[b'branch'][0]
5489 else:
5509 else:
5490 brev = branches[0]
5510 brev = branches[0]
5491 repo._subtoppath = source
5511 repo._subtoppath = source
5492 try:
5512 try:
5493 update_conflict = postincoming(
5513 update_conflict = postincoming(
5494 ui, repo, modheads, opts.get(b'update'), checkout, brev
5514 ui, repo, modheads, opts.get(b'update'), checkout, brev
5495 )
5515 )
5496 except error.FilteredRepoLookupError as exc:
5516 except error.FilteredRepoLookupError as exc:
5497 msg = _(b'cannot update to target: %s') % exc.args[0]
5517 msg = _(b'cannot update to target: %s') % exc.args[0]
5498 exc.args = (msg,) + exc.args[1:]
5518 exc.args = (msg,) + exc.args[1:]
5499 raise
5519 raise
5500 finally:
5520 finally:
5501 del repo._subtoppath
5521 del repo._subtoppath
5502
5522
5503 finally:
5523 finally:
5504 other.close()
5524 other.close()
5505 # skip the remaining pull source if they are some conflict.
5525 # skip the remaining pull source if they are some conflict.
5506 if update_conflict:
5526 if update_conflict:
5507 break
5527 break
5508 if update_conflict:
5528 if update_conflict:
5509 return 1
5529 return 1
5510 else:
5530 else:
5511 return 0
5531 return 0
5512
5532
5513
5533
5514 @command(
5534 @command(
5515 b'purge|clean',
5535 b'purge|clean',
5516 [
5536 [
5517 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5537 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5518 (b'', b'all', None, _(b'purge ignored files too')),
5538 (b'', b'all', None, _(b'purge ignored files too')),
5519 (b'i', b'ignored', None, _(b'purge only ignored files')),
5539 (b'i', b'ignored', None, _(b'purge only ignored files')),
5520 (b'', b'dirs', None, _(b'purge empty directories')),
5540 (b'', b'dirs', None, _(b'purge empty directories')),
5521 (b'', b'files', None, _(b'purge files')),
5541 (b'', b'files', None, _(b'purge files')),
5522 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5542 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5523 (
5543 (
5524 b'0',
5544 b'0',
5525 b'print0',
5545 b'print0',
5526 None,
5546 None,
5527 _(
5547 _(
5528 b'end filenames with NUL, for use with xargs'
5548 b'end filenames with NUL, for use with xargs'
5529 b' (implies -p/--print)'
5549 b' (implies -p/--print)'
5530 ),
5550 ),
5531 ),
5551 ),
5532 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5552 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5533 ]
5553 ]
5534 + cmdutil.walkopts,
5554 + cmdutil.walkopts,
5535 _(b'hg purge [OPTION]... [DIR]...'),
5555 _(b'hg purge [OPTION]... [DIR]...'),
5536 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5556 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5537 )
5557 )
5538 def purge(ui, repo, *dirs, **opts):
5558 def purge(ui, repo, *dirs, **opts):
5539 """removes files not tracked by Mercurial
5559 """removes files not tracked by Mercurial
5540
5560
5541 Delete files not known to Mercurial. This is useful to test local
5561 Delete files not known to Mercurial. This is useful to test local
5542 and uncommitted changes in an otherwise-clean source tree.
5562 and uncommitted changes in an otherwise-clean source tree.
5543
5563
5544 This means that purge will delete the following by default:
5564 This means that purge will delete the following by default:
5545
5565
5546 - Unknown files: files marked with "?" by :hg:`status`
5566 - Unknown files: files marked with "?" by :hg:`status`
5547 - Empty directories: in fact Mercurial ignores directories unless
5567 - Empty directories: in fact Mercurial ignores directories unless
5548 they contain files under source control management
5568 they contain files under source control management
5549
5569
5550 But it will leave untouched:
5570 But it will leave untouched:
5551
5571
5552 - Modified and unmodified tracked files
5572 - Modified and unmodified tracked files
5553 - Ignored files (unless -i or --all is specified)
5573 - Ignored files (unless -i or --all is specified)
5554 - New files added to the repository (with :hg:`add`)
5574 - New files added to the repository (with :hg:`add`)
5555
5575
5556 The --files and --dirs options can be used to direct purge to delete
5576 The --files and --dirs options can be used to direct purge to delete
5557 only files, only directories, or both. If neither option is given,
5577 only files, only directories, or both. If neither option is given,
5558 both will be deleted.
5578 both will be deleted.
5559
5579
5560 If directories are given on the command line, only files in these
5580 If directories are given on the command line, only files in these
5561 directories are considered.
5581 directories are considered.
5562
5582
5563 Be careful with purge, as you could irreversibly delete some files
5583 Be careful with purge, as you could irreversibly delete some files
5564 you forgot to add to the repository. If you only want to print the
5584 you forgot to add to the repository. If you only want to print the
5565 list of files that this program would delete, use the --print
5585 list of files that this program would delete, use the --print
5566 option.
5586 option.
5567 """
5587 """
5568 opts = pycompat.byteskwargs(opts)
5588 opts = pycompat.byteskwargs(opts)
5569 cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
5589 cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
5570
5590
5571 act = not opts.get(b'print')
5591 act = not opts.get(b'print')
5572 eol = b'\n'
5592 eol = b'\n'
5573 if opts.get(b'print0'):
5593 if opts.get(b'print0'):
5574 eol = b'\0'
5594 eol = b'\0'
5575 act = False # --print0 implies --print
5595 act = False # --print0 implies --print
5576 if opts.get(b'all', False):
5596 if opts.get(b'all', False):
5577 ignored = True
5597 ignored = True
5578 unknown = True
5598 unknown = True
5579 else:
5599 else:
5580 ignored = opts.get(b'ignored', False)
5600 ignored = opts.get(b'ignored', False)
5581 unknown = not ignored
5601 unknown = not ignored
5582
5602
5583 removefiles = opts.get(b'files')
5603 removefiles = opts.get(b'files')
5584 removedirs = opts.get(b'dirs')
5604 removedirs = opts.get(b'dirs')
5585 confirm = opts.get(b'confirm')
5605 confirm = opts.get(b'confirm')
5586 if confirm is None:
5606 if confirm is None:
5587 try:
5607 try:
5588 extensions.find(b'purge')
5608 extensions.find(b'purge')
5589 confirm = False
5609 confirm = False
5590 except KeyError:
5610 except KeyError:
5591 confirm = True
5611 confirm = True
5592
5612
5593 if not removefiles and not removedirs:
5613 if not removefiles and not removedirs:
5594 removefiles = True
5614 removefiles = True
5595 removedirs = True
5615 removedirs = True
5596
5616
5597 match = scmutil.match(repo[None], dirs, opts)
5617 match = scmutil.match(repo[None], dirs, opts)
5598
5618
5599 paths = mergemod.purge(
5619 paths = mergemod.purge(
5600 repo,
5620 repo,
5601 match,
5621 match,
5602 unknown=unknown,
5622 unknown=unknown,
5603 ignored=ignored,
5623 ignored=ignored,
5604 removeemptydirs=removedirs,
5624 removeemptydirs=removedirs,
5605 removefiles=removefiles,
5625 removefiles=removefiles,
5606 abortonerror=opts.get(b'abort_on_err'),
5626 abortonerror=opts.get(b'abort_on_err'),
5607 noop=not act,
5627 noop=not act,
5608 confirm=confirm,
5628 confirm=confirm,
5609 )
5629 )
5610
5630
5611 for path in paths:
5631 for path in paths:
5612 if not act:
5632 if not act:
5613 ui.write(b'%s%s' % (path, eol))
5633 ui.write(b'%s%s' % (path, eol))
5614
5634
5615
5635
5616 @command(
5636 @command(
5617 b'push',
5637 b'push',
5618 [
5638 [
5619 (b'f', b'force', None, _(b'force push')),
5639 (b'f', b'force', None, _(b'force push')),
5620 (
5640 (
5621 b'r',
5641 b'r',
5622 b'rev',
5642 b'rev',
5623 [],
5643 [],
5624 _(b'a changeset intended to be included in the destination'),
5644 _(b'a changeset intended to be included in the destination'),
5625 _(b'REV'),
5645 _(b'REV'),
5626 ),
5646 ),
5627 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5647 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5628 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5648 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5629 (
5649 (
5630 b'b',
5650 b'b',
5631 b'branch',
5651 b'branch',
5632 [],
5652 [],
5633 _(b'a specific branch you would like to push'),
5653 _(b'a specific branch you would like to push'),
5634 _(b'BRANCH'),
5654 _(b'BRANCH'),
5635 ),
5655 ),
5636 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5656 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5637 (
5657 (
5638 b'',
5658 b'',
5639 b'pushvars',
5659 b'pushvars',
5640 [],
5660 [],
5641 _(b'variables that can be sent to server (ADVANCED)'),
5661 _(b'variables that can be sent to server (ADVANCED)'),
5642 ),
5662 ),
5643 (
5663 (
5644 b'',
5664 b'',
5645 b'publish',
5665 b'publish',
5646 False,
5666 False,
5647 _(b'push the changeset as public (EXPERIMENTAL)'),
5667 _(b'push the changeset as public (EXPERIMENTAL)'),
5648 ),
5668 ),
5649 ]
5669 ]
5650 + remoteopts,
5670 + remoteopts,
5651 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]...'),
5671 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]...'),
5652 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5672 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5653 helpbasic=True,
5673 helpbasic=True,
5654 )
5674 )
5655 def push(ui, repo, *dests, **opts):
5675 def push(ui, repo, *dests, **opts):
5656 """push changes to the specified destination
5676 """push changes to the specified destination
5657
5677
5658 Push changesets from the local repository to the specified
5678 Push changesets from the local repository to the specified
5659 destination.
5679 destination.
5660
5680
5661 This operation is symmetrical to pull: it is identical to a pull
5681 This operation is symmetrical to pull: it is identical to a pull
5662 in the destination repository from the current one.
5682 in the destination repository from the current one.
5663
5683
5664 By default, push will not allow creation of new heads at the
5684 By default, push will not allow creation of new heads at the
5665 destination, since multiple heads would make it unclear which head
5685 destination, since multiple heads would make it unclear which head
5666 to use. In this situation, it is recommended to pull and merge
5686 to use. In this situation, it is recommended to pull and merge
5667 before pushing.
5687 before pushing.
5668
5688
5669 Use --new-branch if you want to allow push to create a new named
5689 Use --new-branch if you want to allow push to create a new named
5670 branch that is not present at the destination. This allows you to
5690 branch that is not present at the destination. This allows you to
5671 only create a new branch without forcing other changes.
5691 only create a new branch without forcing other changes.
5672
5692
5673 .. note::
5693 .. note::
5674
5694
5675 Extra care should be taken with the -f/--force option,
5695 Extra care should be taken with the -f/--force option,
5676 which will push all new heads on all branches, an action which will
5696 which will push all new heads on all branches, an action which will
5677 almost always cause confusion for collaborators.
5697 almost always cause confusion for collaborators.
5678
5698
5679 If -r/--rev is used, the specified revision and all its ancestors
5699 If -r/--rev is used, the specified revision and all its ancestors
5680 will be pushed to the remote repository.
5700 will be pushed to the remote repository.
5681
5701
5682 If -B/--bookmark is used, the specified bookmarked revision, its
5702 If -B/--bookmark is used, the specified bookmarked revision, its
5683 ancestors, and the bookmark will be pushed to the remote
5703 ancestors, and the bookmark will be pushed to the remote
5684 repository. Specifying ``.`` is equivalent to specifying the active
5704 repository. Specifying ``.`` is equivalent to specifying the active
5685 bookmark's name. Use the --all-bookmarks option for pushing all
5705 bookmark's name. Use the --all-bookmarks option for pushing all
5686 current bookmarks.
5706 current bookmarks.
5687
5707
5688 Please see :hg:`help urls` for important details about ``ssh://``
5708 Please see :hg:`help urls` for important details about ``ssh://``
5689 URLs. If DESTINATION is omitted, a default path will be used.
5709 URLs. If DESTINATION is omitted, a default path will be used.
5690
5710
5691 When passed multiple destinations, push will process them one after the
5711 When passed multiple destinations, push will process them one after the
5692 other, but stop should an error occur.
5712 other, but stop should an error occur.
5693
5713
5694 .. container:: verbose
5714 .. container:: verbose
5695
5715
5696 The --pushvars option sends strings to the server that become
5716 The --pushvars option sends strings to the server that become
5697 environment variables prepended with ``HG_USERVAR_``. For example,
5717 environment variables prepended with ``HG_USERVAR_``. For example,
5698 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5718 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5699 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5719 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5700
5720
5701 pushvars can provide for user-overridable hooks as well as set debug
5721 pushvars can provide for user-overridable hooks as well as set debug
5702 levels. One example is having a hook that blocks commits containing
5722 levels. One example is having a hook that blocks commits containing
5703 conflict markers, but enables the user to override the hook if the file
5723 conflict markers, but enables the user to override the hook if the file
5704 is using conflict markers for testing purposes or the file format has
5724 is using conflict markers for testing purposes or the file format has
5705 strings that look like conflict markers.
5725 strings that look like conflict markers.
5706
5726
5707 By default, servers will ignore `--pushvars`. To enable it add the
5727 By default, servers will ignore `--pushvars`. To enable it add the
5708 following to your configuration file::
5728 following to your configuration file::
5709
5729
5710 [push]
5730 [push]
5711 pushvars.server = true
5731 pushvars.server = true
5712
5732
5713 Returns 0 if push was successful, 1 if nothing to push.
5733 Returns 0 if push was successful, 1 if nothing to push.
5714 """
5734 """
5715
5735
5716 opts = pycompat.byteskwargs(opts)
5736 opts = pycompat.byteskwargs(opts)
5717
5737
5718 if opts.get(b'all_bookmarks'):
5738 if opts.get(b'all_bookmarks'):
5719 cmdutil.check_incompatible_arguments(
5739 cmdutil.check_incompatible_arguments(
5720 opts,
5740 opts,
5721 b'all_bookmarks',
5741 b'all_bookmarks',
5722 [b'bookmark', b'rev'],
5742 [b'bookmark', b'rev'],
5723 )
5743 )
5724 opts[b'bookmark'] = list(repo._bookmarks)
5744 opts[b'bookmark'] = list(repo._bookmarks)
5725
5745
5726 if opts.get(b'bookmark'):
5746 if opts.get(b'bookmark'):
5727 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5747 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5728 for b in opts[b'bookmark']:
5748 for b in opts[b'bookmark']:
5729 # translate -B options to -r so changesets get pushed
5749 # translate -B options to -r so changesets get pushed
5730 b = repo._bookmarks.expandname(b)
5750 b = repo._bookmarks.expandname(b)
5731 if b in repo._bookmarks:
5751 if b in repo._bookmarks:
5732 opts.setdefault(b'rev', []).append(b)
5752 opts.setdefault(b'rev', []).append(b)
5733 else:
5753 else:
5734 # if we try to push a deleted bookmark, translate it to null
5754 # if we try to push a deleted bookmark, translate it to null
5735 # this lets simultaneous -r, -b options continue working
5755 # this lets simultaneous -r, -b options continue working
5736 opts.setdefault(b'rev', []).append(b"null")
5756 opts.setdefault(b'rev', []).append(b"null")
5737
5757
5738 some_pushed = False
5758 some_pushed = False
5739 result = 0
5759 result = 0
5740 for path in urlutil.get_push_paths(repo, ui, dests):
5760 for path in urlutil.get_push_paths(repo, ui, dests):
5741 dest = path.pushloc or path.loc
5761 dest = path.pushloc or path.loc
5742 branches = (path.branch, opts.get(b'branch') or [])
5762 branches = (path.branch, opts.get(b'branch') or [])
5743 ui.status(_(b'pushing to %s\n') % urlutil.hidepassword(dest))
5763 ui.status(_(b'pushing to %s\n') % urlutil.hidepassword(dest))
5744 revs, checkout = hg.addbranchrevs(
5764 revs, checkout = hg.addbranchrevs(
5745 repo, repo, branches, opts.get(b'rev')
5765 repo, repo, branches, opts.get(b'rev')
5746 )
5766 )
5747 other = hg.peer(repo, opts, dest)
5767 other = hg.peer(repo, opts, dest)
5748
5768
5749 try:
5769 try:
5750 if revs:
5770 if revs:
5751 revs = [repo[r].node() for r in logcmdutil.revrange(repo, revs)]
5771 revs = [repo[r].node() for r in logcmdutil.revrange(repo, revs)]
5752 if not revs:
5772 if not revs:
5753 raise error.InputError(
5773 raise error.InputError(
5754 _(b"specified revisions evaluate to an empty set"),
5774 _(b"specified revisions evaluate to an empty set"),
5755 hint=_(b"use different revision arguments"),
5775 hint=_(b"use different revision arguments"),
5756 )
5776 )
5757 elif path.pushrev:
5777 elif path.pushrev:
5758 # It doesn't make any sense to specify ancestor revisions. So limit
5778 # It doesn't make any sense to specify ancestor revisions. So limit
5759 # to DAG heads to make discovery simpler.
5779 # to DAG heads to make discovery simpler.
5760 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5780 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5761 revs = scmutil.revrange(repo, [expr])
5781 revs = scmutil.revrange(repo, [expr])
5762 revs = [repo[rev].node() for rev in revs]
5782 revs = [repo[rev].node() for rev in revs]
5763 if not revs:
5783 if not revs:
5764 raise error.InputError(
5784 raise error.InputError(
5765 _(
5785 _(
5766 b'default push revset for path evaluates to an empty set'
5786 b'default push revset for path evaluates to an empty set'
5767 )
5787 )
5768 )
5788 )
5769 elif ui.configbool(b'commands', b'push.require-revs'):
5789 elif ui.configbool(b'commands', b'push.require-revs'):
5770 raise error.InputError(
5790 raise error.InputError(
5771 _(b'no revisions specified to push'),
5791 _(b'no revisions specified to push'),
5772 hint=_(b'did you mean "hg push -r ."?'),
5792 hint=_(b'did you mean "hg push -r ."?'),
5773 )
5793 )
5774
5794
5775 repo._subtoppath = dest
5795 repo._subtoppath = dest
5776 try:
5796 try:
5777 # push subrepos depth-first for coherent ordering
5797 # push subrepos depth-first for coherent ordering
5778 c = repo[b'.']
5798 c = repo[b'.']
5779 subs = c.substate # only repos that are committed
5799 subs = c.substate # only repos that are committed
5780 for s in sorted(subs):
5800 for s in sorted(subs):
5781 sub_result = c.sub(s).push(opts)
5801 sub_result = c.sub(s).push(opts)
5782 if sub_result == 0:
5802 if sub_result == 0:
5783 return 1
5803 return 1
5784 finally:
5804 finally:
5785 del repo._subtoppath
5805 del repo._subtoppath
5786
5806
5787 opargs = dict(
5807 opargs = dict(
5788 opts.get(b'opargs', {})
5808 opts.get(b'opargs', {})
5789 ) # copy opargs since we may mutate it
5809 ) # copy opargs since we may mutate it
5790 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5810 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5791
5811
5792 pushop = exchange.push(
5812 pushop = exchange.push(
5793 repo,
5813 repo,
5794 other,
5814 other,
5795 opts.get(b'force'),
5815 opts.get(b'force'),
5796 revs=revs,
5816 revs=revs,
5797 newbranch=opts.get(b'new_branch'),
5817 newbranch=opts.get(b'new_branch'),
5798 bookmarks=opts.get(b'bookmark', ()),
5818 bookmarks=opts.get(b'bookmark', ()),
5799 publish=opts.get(b'publish'),
5819 publish=opts.get(b'publish'),
5800 opargs=opargs,
5820 opargs=opargs,
5801 )
5821 )
5802
5822
5803 if pushop.cgresult == 0:
5823 if pushop.cgresult == 0:
5804 result = 1
5824 result = 1
5805 elif pushop.cgresult is not None:
5825 elif pushop.cgresult is not None:
5806 some_pushed = True
5826 some_pushed = True
5807
5827
5808 if pushop.bkresult is not None:
5828 if pushop.bkresult is not None:
5809 if pushop.bkresult == 2:
5829 if pushop.bkresult == 2:
5810 result = 2
5830 result = 2
5811 elif not result and pushop.bkresult:
5831 elif not result and pushop.bkresult:
5812 result = 2
5832 result = 2
5813
5833
5814 if result:
5834 if result:
5815 break
5835 break
5816
5836
5817 finally:
5837 finally:
5818 other.close()
5838 other.close()
5819 if result == 0 and not some_pushed:
5839 if result == 0 and not some_pushed:
5820 result = 1
5840 result = 1
5821 return result
5841 return result
5822
5842
5823
5843
5824 @command(
5844 @command(
5825 b'recover',
5845 b'recover',
5826 [
5846 [
5827 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5847 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5828 ],
5848 ],
5829 helpcategory=command.CATEGORY_MAINTENANCE,
5849 helpcategory=command.CATEGORY_MAINTENANCE,
5830 )
5850 )
5831 def recover(ui, repo, **opts):
5851 def recover(ui, repo, **opts):
5832 """roll back an interrupted transaction
5852 """roll back an interrupted transaction
5833
5853
5834 Recover from an interrupted commit or pull.
5854 Recover from an interrupted commit or pull.
5835
5855
5836 This command tries to fix the repository status after an
5856 This command tries to fix the repository status after an
5837 interrupted operation. It should only be necessary when Mercurial
5857 interrupted operation. It should only be necessary when Mercurial
5838 suggests it.
5858 suggests it.
5839
5859
5840 Returns 0 if successful, 1 if nothing to recover or verify fails.
5860 Returns 0 if successful, 1 if nothing to recover or verify fails.
5841 """
5861 """
5842 ret = repo.recover()
5862 ret = repo.recover()
5843 if ret:
5863 if ret:
5844 if opts['verify']:
5864 if opts['verify']:
5845 return hg.verify(repo)
5865 return hg.verify(repo)
5846 else:
5866 else:
5847 msg = _(
5867 msg = _(
5848 b"(verify step skipped, run `hg verify` to check your "
5868 b"(verify step skipped, run `hg verify` to check your "
5849 b"repository content)\n"
5869 b"repository content)\n"
5850 )
5870 )
5851 ui.warn(msg)
5871 ui.warn(msg)
5852 return 0
5872 return 0
5853 return 1
5873 return 1
5854
5874
5855
5875
5856 @command(
5876 @command(
5857 b'remove|rm',
5877 b'remove|rm',
5858 [
5878 [
5859 (b'A', b'after', None, _(b'record delete for missing files')),
5879 (b'A', b'after', None, _(b'record delete for missing files')),
5860 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5880 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5861 ]
5881 ]
5862 + subrepoopts
5882 + subrepoopts
5863 + walkopts
5883 + walkopts
5864 + dryrunopts,
5884 + dryrunopts,
5865 _(b'[OPTION]... FILE...'),
5885 _(b'[OPTION]... FILE...'),
5866 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5886 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5867 helpbasic=True,
5887 helpbasic=True,
5868 inferrepo=True,
5888 inferrepo=True,
5869 )
5889 )
5870 def remove(ui, repo, *pats, **opts):
5890 def remove(ui, repo, *pats, **opts):
5871 """remove the specified files on the next commit
5891 """remove the specified files on the next commit
5872
5892
5873 Schedule the indicated files for removal from the current branch.
5893 Schedule the indicated files for removal from the current branch.
5874
5894
5875 This command schedules the files to be removed at the next commit.
5895 This command schedules the files to be removed at the next commit.
5876 To undo a remove before that, see :hg:`revert`. To undo added
5896 To undo a remove before that, see :hg:`revert`. To undo added
5877 files, see :hg:`forget`.
5897 files, see :hg:`forget`.
5878
5898
5879 .. container:: verbose
5899 .. container:: verbose
5880
5900
5881 -A/--after can be used to remove only files that have already
5901 -A/--after can be used to remove only files that have already
5882 been deleted, -f/--force can be used to force deletion, and -Af
5902 been deleted, -f/--force can be used to force deletion, and -Af
5883 can be used to remove files from the next revision without
5903 can be used to remove files from the next revision without
5884 deleting them from the working directory.
5904 deleting them from the working directory.
5885
5905
5886 The following table details the behavior of remove for different
5906 The following table details the behavior of remove for different
5887 file states (columns) and option combinations (rows). The file
5907 file states (columns) and option combinations (rows). The file
5888 states are Added [A], Clean [C], Modified [M] and Missing [!]
5908 states are Added [A], Clean [C], Modified [M] and Missing [!]
5889 (as reported by :hg:`status`). The actions are Warn, Remove
5909 (as reported by :hg:`status`). The actions are Warn, Remove
5890 (from branch) and Delete (from disk):
5910 (from branch) and Delete (from disk):
5891
5911
5892 ========= == == == ==
5912 ========= == == == ==
5893 opt/state A C M !
5913 opt/state A C M !
5894 ========= == == == ==
5914 ========= == == == ==
5895 none W RD W R
5915 none W RD W R
5896 -f R RD RD R
5916 -f R RD RD R
5897 -A W W W R
5917 -A W W W R
5898 -Af R R R R
5918 -Af R R R R
5899 ========= == == == ==
5919 ========= == == == ==
5900
5920
5901 .. note::
5921 .. note::
5902
5922
5903 :hg:`remove` never deletes files in Added [A] state from the
5923 :hg:`remove` never deletes files in Added [A] state from the
5904 working directory, not even if ``--force`` is specified.
5924 working directory, not even if ``--force`` is specified.
5905
5925
5906 Returns 0 on success, 1 if any warnings encountered.
5926 Returns 0 on success, 1 if any warnings encountered.
5907 """
5927 """
5908
5928
5909 opts = pycompat.byteskwargs(opts)
5929 opts = pycompat.byteskwargs(opts)
5910 after, force = opts.get(b'after'), opts.get(b'force')
5930 after, force = opts.get(b'after'), opts.get(b'force')
5911 dryrun = opts.get(b'dry_run')
5931 dryrun = opts.get(b'dry_run')
5912 if not pats and not after:
5932 if not pats and not after:
5913 raise error.InputError(_(b'no files specified'))
5933 raise error.InputError(_(b'no files specified'))
5914
5934
5915 m = scmutil.match(repo[None], pats, opts)
5935 m = scmutil.match(repo[None], pats, opts)
5916 subrepos = opts.get(b'subrepos')
5936 subrepos = opts.get(b'subrepos')
5917 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5937 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5918 return cmdutil.remove(
5938 return cmdutil.remove(
5919 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5939 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5920 )
5940 )
5921
5941
5922
5942
5923 @command(
5943 @command(
5924 b'rename|move|mv',
5944 b'rename|move|mv',
5925 [
5945 [
5926 (b'', b'forget', None, _(b'unmark a destination file as renamed')),
5946 (b'', b'forget', None, _(b'unmark a destination file as renamed')),
5927 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5947 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5928 (
5948 (
5929 b'',
5949 b'',
5930 b'at-rev',
5950 b'at-rev',
5931 b'',
5951 b'',
5932 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5952 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5933 _(b'REV'),
5953 _(b'REV'),
5934 ),
5954 ),
5935 (
5955 (
5936 b'f',
5956 b'f',
5937 b'force',
5957 b'force',
5938 None,
5958 None,
5939 _(b'forcibly move over an existing managed file'),
5959 _(b'forcibly move over an existing managed file'),
5940 ),
5960 ),
5941 ]
5961 ]
5942 + walkopts
5962 + walkopts
5943 + dryrunopts,
5963 + dryrunopts,
5944 _(b'[OPTION]... SOURCE... DEST'),
5964 _(b'[OPTION]... SOURCE... DEST'),
5945 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5965 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5946 )
5966 )
5947 def rename(ui, repo, *pats, **opts):
5967 def rename(ui, repo, *pats, **opts):
5948 """rename files; equivalent of copy + remove
5968 """rename files; equivalent of copy + remove
5949
5969
5950 Mark dest as copies of sources; mark sources for deletion. If dest
5970 Mark dest as copies of sources; mark sources for deletion. If dest
5951 is a directory, copies are put in that directory. If dest is a
5971 is a directory, copies are put in that directory. If dest is a
5952 file, there can only be one source.
5972 file, there can only be one source.
5953
5973
5954 By default, this command copies the contents of files as they
5974 By default, this command copies the contents of files as they
5955 exist in the working directory. If invoked with -A/--after, the
5975 exist in the working directory. If invoked with -A/--after, the
5956 operation is recorded, but no copying is performed.
5976 operation is recorded, but no copying is performed.
5957
5977
5958 To undo marking a destination file as renamed, use --forget. With that
5978 To undo marking a destination file as renamed, use --forget. With that
5959 option, all given (positional) arguments are unmarked as renames. The
5979 option, all given (positional) arguments are unmarked as renames. The
5960 destination file(s) will be left in place (still tracked). The source
5980 destination file(s) will be left in place (still tracked). The source
5961 file(s) will not be restored. Note that :hg:`rename --forget` behaves
5981 file(s) will not be restored. Note that :hg:`rename --forget` behaves
5962 the same way as :hg:`copy --forget`.
5982 the same way as :hg:`copy --forget`.
5963
5983
5964 This command takes effect with the next commit by default.
5984 This command takes effect with the next commit by default.
5965
5985
5966 Returns 0 on success, 1 if errors are encountered.
5986 Returns 0 on success, 1 if errors are encountered.
5967 """
5987 """
5968 opts = pycompat.byteskwargs(opts)
5988 opts = pycompat.byteskwargs(opts)
5969 with repo.wlock():
5989 with repo.wlock():
5970 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5990 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5971
5991
5972
5992
5973 @command(
5993 @command(
5974 b'resolve',
5994 b'resolve',
5975 [
5995 [
5976 (b'a', b'all', None, _(b'select all unresolved files')),
5996 (b'a', b'all', None, _(b'select all unresolved files')),
5977 (b'l', b'list', None, _(b'list state of files needing merge')),
5997 (b'l', b'list', None, _(b'list state of files needing merge')),
5978 (b'm', b'mark', None, _(b'mark files as resolved')),
5998 (b'm', b'mark', None, _(b'mark files as resolved')),
5979 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5999 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5980 (b'n', b'no-status', None, _(b'hide status prefix')),
6000 (b'n', b'no-status', None, _(b'hide status prefix')),
5981 (b'', b're-merge', None, _(b're-merge files')),
6001 (b'', b're-merge', None, _(b're-merge files')),
5982 ]
6002 ]
5983 + mergetoolopts
6003 + mergetoolopts
5984 + walkopts
6004 + walkopts
5985 + formatteropts,
6005 + formatteropts,
5986 _(b'[OPTION]... [FILE]...'),
6006 _(b'[OPTION]... [FILE]...'),
5987 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6007 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5988 inferrepo=True,
6008 inferrepo=True,
5989 )
6009 )
5990 def resolve(ui, repo, *pats, **opts):
6010 def resolve(ui, repo, *pats, **opts):
5991 """redo merges or set/view the merge status of files
6011 """redo merges or set/view the merge status of files
5992
6012
5993 Merges with unresolved conflicts are often the result of
6013 Merges with unresolved conflicts are often the result of
5994 non-interactive merging using the ``internal:merge`` configuration
6014 non-interactive merging using the ``internal:merge`` configuration
5995 setting, or a command-line merge tool like ``diff3``. The resolve
6015 setting, or a command-line merge tool like ``diff3``. The resolve
5996 command is used to manage the files involved in a merge, after
6016 command is used to manage the files involved in a merge, after
5997 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6017 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5998 working directory must have two parents). See :hg:`help
6018 working directory must have two parents). See :hg:`help
5999 merge-tools` for information on configuring merge tools.
6019 merge-tools` for information on configuring merge tools.
6000
6020
6001 The resolve command can be used in the following ways:
6021 The resolve command can be used in the following ways:
6002
6022
6003 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
6023 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
6004 the specified files, discarding any previous merge attempts. Re-merging
6024 the specified files, discarding any previous merge attempts. Re-merging
6005 is not performed for files already marked as resolved. Use ``--all/-a``
6025 is not performed for files already marked as resolved. Use ``--all/-a``
6006 to select all unresolved files. ``--tool`` can be used to specify
6026 to select all unresolved files. ``--tool`` can be used to specify
6007 the merge tool used for the given files. It overrides the HGMERGE
6027 the merge tool used for the given files. It overrides the HGMERGE
6008 environment variable and your configuration files. Previous file
6028 environment variable and your configuration files. Previous file
6009 contents are saved with a ``.orig`` suffix.
6029 contents are saved with a ``.orig`` suffix.
6010
6030
6011 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6031 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6012 (e.g. after having manually fixed-up the files). The default is
6032 (e.g. after having manually fixed-up the files). The default is
6013 to mark all unresolved files.
6033 to mark all unresolved files.
6014
6034
6015 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6035 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6016 default is to mark all resolved files.
6036 default is to mark all resolved files.
6017
6037
6018 - :hg:`resolve -l`: list files which had or still have conflicts.
6038 - :hg:`resolve -l`: list files which had or still have conflicts.
6019 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6039 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6020 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
6040 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
6021 the list. See :hg:`help filesets` for details.
6041 the list. See :hg:`help filesets` for details.
6022
6042
6023 .. note::
6043 .. note::
6024
6044
6025 Mercurial will not let you commit files with unresolved merge
6045 Mercurial will not let you commit files with unresolved merge
6026 conflicts. You must use :hg:`resolve -m ...` before you can
6046 conflicts. You must use :hg:`resolve -m ...` before you can
6027 commit after a conflicting merge.
6047 commit after a conflicting merge.
6028
6048
6029 .. container:: verbose
6049 .. container:: verbose
6030
6050
6031 Template:
6051 Template:
6032
6052
6033 The following keywords are supported in addition to the common template
6053 The following keywords are supported in addition to the common template
6034 keywords and functions. See also :hg:`help templates`.
6054 keywords and functions. See also :hg:`help templates`.
6035
6055
6036 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
6056 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
6037 :path: String. Repository-absolute path of the file.
6057 :path: String. Repository-absolute path of the file.
6038
6058
6039 Returns 0 on success, 1 if any files fail a resolve attempt.
6059 Returns 0 on success, 1 if any files fail a resolve attempt.
6040 """
6060 """
6041
6061
6042 opts = pycompat.byteskwargs(opts)
6062 opts = pycompat.byteskwargs(opts)
6043 confirm = ui.configbool(b'commands', b'resolve.confirm')
6063 confirm = ui.configbool(b'commands', b'resolve.confirm')
6044 flaglist = b'all mark unmark list no_status re_merge'.split()
6064 flaglist = b'all mark unmark list no_status re_merge'.split()
6045 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
6065 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
6046
6066
6047 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
6067 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
6048 if actioncount > 1:
6068 if actioncount > 1:
6049 raise error.InputError(_(b"too many actions specified"))
6069 raise error.InputError(_(b"too many actions specified"))
6050 elif actioncount == 0 and ui.configbool(
6070 elif actioncount == 0 and ui.configbool(
6051 b'commands', b'resolve.explicit-re-merge'
6071 b'commands', b'resolve.explicit-re-merge'
6052 ):
6072 ):
6053 hint = _(b'use --mark, --unmark, --list or --re-merge')
6073 hint = _(b'use --mark, --unmark, --list or --re-merge')
6054 raise error.InputError(_(b'no action specified'), hint=hint)
6074 raise error.InputError(_(b'no action specified'), hint=hint)
6055 if pats and all:
6075 if pats and all:
6056 raise error.InputError(_(b"can't specify --all and patterns"))
6076 raise error.InputError(_(b"can't specify --all and patterns"))
6057 if not (all or pats or show or mark or unmark):
6077 if not (all or pats or show or mark or unmark):
6058 raise error.InputError(
6078 raise error.InputError(
6059 _(b'no files or directories specified'),
6079 _(b'no files or directories specified'),
6060 hint=b'use --all to re-merge all unresolved files',
6080 hint=b'use --all to re-merge all unresolved files',
6061 )
6081 )
6062
6082
6063 if confirm:
6083 if confirm:
6064 if all:
6084 if all:
6065 if ui.promptchoice(
6085 if ui.promptchoice(
6066 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
6086 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
6067 ):
6087 ):
6068 raise error.CanceledError(_(b'user quit'))
6088 raise error.CanceledError(_(b'user quit'))
6069 if mark and not pats:
6089 if mark and not pats:
6070 if ui.promptchoice(
6090 if ui.promptchoice(
6071 _(
6091 _(
6072 b'mark all unresolved files as resolved (yn)?'
6092 b'mark all unresolved files as resolved (yn)?'
6073 b'$$ &Yes $$ &No'
6093 b'$$ &Yes $$ &No'
6074 )
6094 )
6075 ):
6095 ):
6076 raise error.CanceledError(_(b'user quit'))
6096 raise error.CanceledError(_(b'user quit'))
6077 if unmark and not pats:
6097 if unmark and not pats:
6078 if ui.promptchoice(
6098 if ui.promptchoice(
6079 _(
6099 _(
6080 b'mark all resolved files as unresolved (yn)?'
6100 b'mark all resolved files as unresolved (yn)?'
6081 b'$$ &Yes $$ &No'
6101 b'$$ &Yes $$ &No'
6082 )
6102 )
6083 ):
6103 ):
6084 raise error.CanceledError(_(b'user quit'))
6104 raise error.CanceledError(_(b'user quit'))
6085
6105
6086 uipathfn = scmutil.getuipathfn(repo)
6106 uipathfn = scmutil.getuipathfn(repo)
6087
6107
6088 if show:
6108 if show:
6089 ui.pager(b'resolve')
6109 ui.pager(b'resolve')
6090 fm = ui.formatter(b'resolve', opts)
6110 fm = ui.formatter(b'resolve', opts)
6091 ms = mergestatemod.mergestate.read(repo)
6111 ms = mergestatemod.mergestate.read(repo)
6092 wctx = repo[None]
6112 wctx = repo[None]
6093 m = scmutil.match(wctx, pats, opts)
6113 m = scmutil.match(wctx, pats, opts)
6094
6114
6095 # Labels and keys based on merge state. Unresolved path conflicts show
6115 # Labels and keys based on merge state. Unresolved path conflicts show
6096 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6116 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6097 # resolved conflicts.
6117 # resolved conflicts.
6098 mergestateinfo = {
6118 mergestateinfo = {
6099 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6119 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6100 b'resolve.unresolved',
6120 b'resolve.unresolved',
6101 b'U',
6121 b'U',
6102 ),
6122 ),
6103 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6123 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6104 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6124 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6105 b'resolve.unresolved',
6125 b'resolve.unresolved',
6106 b'P',
6126 b'P',
6107 ),
6127 ),
6108 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6128 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6109 b'resolve.resolved',
6129 b'resolve.resolved',
6110 b'R',
6130 b'R',
6111 ),
6131 ),
6112 }
6132 }
6113
6133
6114 for f in ms:
6134 for f in ms:
6115 if not m(f):
6135 if not m(f):
6116 continue
6136 continue
6117
6137
6118 label, key = mergestateinfo[ms[f]]
6138 label, key = mergestateinfo[ms[f]]
6119 fm.startitem()
6139 fm.startitem()
6120 fm.context(ctx=wctx)
6140 fm.context(ctx=wctx)
6121 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6141 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6122 fm.data(path=f)
6142 fm.data(path=f)
6123 fm.plain(b'%s\n' % uipathfn(f), label=label)
6143 fm.plain(b'%s\n' % uipathfn(f), label=label)
6124 fm.end()
6144 fm.end()
6125 return 0
6145 return 0
6126
6146
6127 with repo.wlock():
6147 with repo.wlock():
6128 ms = mergestatemod.mergestate.read(repo)
6148 ms = mergestatemod.mergestate.read(repo)
6129
6149
6130 if not (ms.active() or repo.dirstate.p2() != repo.nullid):
6150 if not (ms.active() or repo.dirstate.p2() != repo.nullid):
6131 raise error.StateError(
6151 raise error.StateError(
6132 _(b'resolve command not applicable when not merging')
6152 _(b'resolve command not applicable when not merging')
6133 )
6153 )
6134
6154
6135 wctx = repo[None]
6155 wctx = repo[None]
6136 m = scmutil.match(wctx, pats, opts)
6156 m = scmutil.match(wctx, pats, opts)
6137 ret = 0
6157 ret = 0
6138 didwork = False
6158 didwork = False
6139
6159
6140 hasconflictmarkers = []
6160 hasconflictmarkers = []
6141 if mark:
6161 if mark:
6142 markcheck = ui.config(b'commands', b'resolve.mark-check')
6162 markcheck = ui.config(b'commands', b'resolve.mark-check')
6143 if markcheck not in [b'warn', b'abort']:
6163 if markcheck not in [b'warn', b'abort']:
6144 # Treat all invalid / unrecognized values as 'none'.
6164 # Treat all invalid / unrecognized values as 'none'.
6145 markcheck = False
6165 markcheck = False
6146 for f in ms:
6166 for f in ms:
6147 if not m(f):
6167 if not m(f):
6148 continue
6168 continue
6149
6169
6150 didwork = True
6170 didwork = True
6151
6171
6152 # path conflicts must be resolved manually
6172 # path conflicts must be resolved manually
6153 if ms[f] in (
6173 if ms[f] in (
6154 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6174 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6155 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6175 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6156 ):
6176 ):
6157 if mark:
6177 if mark:
6158 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6178 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6159 elif unmark:
6179 elif unmark:
6160 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6180 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6161 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6181 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6162 ui.warn(
6182 ui.warn(
6163 _(b'%s: path conflict must be resolved manually\n')
6183 _(b'%s: path conflict must be resolved manually\n')
6164 % uipathfn(f)
6184 % uipathfn(f)
6165 )
6185 )
6166 continue
6186 continue
6167
6187
6168 if mark:
6188 if mark:
6169 if markcheck:
6189 if markcheck:
6170 fdata = repo.wvfs.tryread(f)
6190 fdata = repo.wvfs.tryread(f)
6171 if (
6191 if (
6172 filemerge.hasconflictmarkers(fdata)
6192 filemerge.hasconflictmarkers(fdata)
6173 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6193 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6174 ):
6194 ):
6175 hasconflictmarkers.append(f)
6195 hasconflictmarkers.append(f)
6176 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6196 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6177 elif unmark:
6197 elif unmark:
6178 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6198 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6179 else:
6199 else:
6180 # backup pre-resolve (merge uses .orig for its own purposes)
6200 # backup pre-resolve (merge uses .orig for its own purposes)
6181 a = repo.wjoin(f)
6201 a = repo.wjoin(f)
6182 try:
6202 try:
6183 util.copyfile(a, a + b".resolve")
6203 util.copyfile(a, a + b".resolve")
6184 except FileNotFoundError:
6204 except FileNotFoundError:
6185 pass
6205 pass
6186
6206
6187 try:
6207 try:
6188 # preresolve file
6208 # preresolve file
6189 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6209 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6190 with ui.configoverride(overrides, b'resolve'):
6210 with ui.configoverride(overrides, b'resolve'):
6191 r = ms.resolve(f, wctx)
6211 r = ms.resolve(f, wctx)
6192 if r:
6212 if r:
6193 ret = 1
6213 ret = 1
6194 finally:
6214 finally:
6195 ms.commit()
6215 ms.commit()
6196
6216
6197 # replace filemerge's .orig file with our resolve file
6217 # replace filemerge's .orig file with our resolve file
6198 try:
6218 try:
6199 util.rename(
6219 util.rename(
6200 a + b".resolve", scmutil.backuppath(ui, repo, f)
6220 a + b".resolve", scmutil.backuppath(ui, repo, f)
6201 )
6221 )
6202 except FileNotFoundError:
6222 except FileNotFoundError:
6203 pass
6223 pass
6204
6224
6205 if hasconflictmarkers:
6225 if hasconflictmarkers:
6206 ui.warn(
6226 ui.warn(
6207 _(
6227 _(
6208 b'warning: the following files still have conflict '
6228 b'warning: the following files still have conflict '
6209 b'markers:\n'
6229 b'markers:\n'
6210 )
6230 )
6211 + b''.join(
6231 + b''.join(
6212 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6232 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6213 )
6233 )
6214 )
6234 )
6215 if markcheck == b'abort' and not all and not pats:
6235 if markcheck == b'abort' and not all and not pats:
6216 raise error.StateError(
6236 raise error.StateError(
6217 _(b'conflict markers detected'),
6237 _(b'conflict markers detected'),
6218 hint=_(b'use --all to mark anyway'),
6238 hint=_(b'use --all to mark anyway'),
6219 )
6239 )
6220
6240
6221 ms.commit()
6241 ms.commit()
6222 branchmerge = repo.dirstate.p2() != repo.nullid
6242 branchmerge = repo.dirstate.p2() != repo.nullid
6223 # resolve is not doing a parent change here, however, `record updates`
6243 # resolve is not doing a parent change here, however, `record updates`
6224 # will call some dirstate API that at intended for parent changes call.
6244 # will call some dirstate API that at intended for parent changes call.
6225 # Ideally we would not need this and could implement a lighter version
6245 # Ideally we would not need this and could implement a lighter version
6226 # of the recordupdateslogic that will not have to deal with the part
6246 # of the recordupdateslogic that will not have to deal with the part
6227 # related to parent changes. However this would requires that:
6247 # related to parent changes. However this would requires that:
6228 # - we are sure we passed around enough information at update/merge
6248 # - we are sure we passed around enough information at update/merge
6229 # time to no longer needs it at `hg resolve time`
6249 # time to no longer needs it at `hg resolve time`
6230 # - we are sure we store that information well enough to be able to reuse it
6250 # - we are sure we store that information well enough to be able to reuse it
6231 # - we are the necessary logic to reuse it right.
6251 # - we are the necessary logic to reuse it right.
6232 #
6252 #
6233 # All this should eventually happens, but in the mean time, we use this
6253 # All this should eventually happens, but in the mean time, we use this
6234 # context manager slightly out of the context it should be.
6254 # context manager slightly out of the context it should be.
6235 with repo.dirstate.parentchange():
6255 with repo.dirstate.parentchange():
6236 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6256 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6237
6257
6238 if not didwork and pats:
6258 if not didwork and pats:
6239 hint = None
6259 hint = None
6240 if not any([p for p in pats if p.find(b':') >= 0]):
6260 if not any([p for p in pats if p.find(b':') >= 0]):
6241 pats = [b'path:%s' % p for p in pats]
6261 pats = [b'path:%s' % p for p in pats]
6242 m = scmutil.match(wctx, pats, opts)
6262 m = scmutil.match(wctx, pats, opts)
6243 for f in ms:
6263 for f in ms:
6244 if not m(f):
6264 if not m(f):
6245 continue
6265 continue
6246
6266
6247 def flag(o):
6267 def flag(o):
6248 if o == b're_merge':
6268 if o == b're_merge':
6249 return b'--re-merge '
6269 return b'--re-merge '
6250 return b'-%s ' % o[0:1]
6270 return b'-%s ' % o[0:1]
6251
6271
6252 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6272 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6253 hint = _(b"(try: hg resolve %s%s)\n") % (
6273 hint = _(b"(try: hg resolve %s%s)\n") % (
6254 flags,
6274 flags,
6255 b' '.join(pats),
6275 b' '.join(pats),
6256 )
6276 )
6257 break
6277 break
6258 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6278 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6259 if hint:
6279 if hint:
6260 ui.warn(hint)
6280 ui.warn(hint)
6261
6281
6262 unresolvedf = ms.unresolvedcount()
6282 unresolvedf = ms.unresolvedcount()
6263 if not unresolvedf:
6283 if not unresolvedf:
6264 ui.status(_(b'(no more unresolved files)\n'))
6284 ui.status(_(b'(no more unresolved files)\n'))
6265 cmdutil.checkafterresolved(repo)
6285 cmdutil.checkafterresolved(repo)
6266
6286
6267 return ret
6287 return ret
6268
6288
6269
6289
6270 @command(
6290 @command(
6271 b'revert',
6291 b'revert',
6272 [
6292 [
6273 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6293 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6274 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6294 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6275 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6295 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6276 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6296 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6277 (b'i', b'interactive', None, _(b'interactively select the changes')),
6297 (b'i', b'interactive', None, _(b'interactively select the changes')),
6278 ]
6298 ]
6279 + walkopts
6299 + walkopts
6280 + dryrunopts,
6300 + dryrunopts,
6281 _(b'[OPTION]... [-r REV] [NAME]...'),
6301 _(b'[OPTION]... [-r REV] [NAME]...'),
6282 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6302 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6283 )
6303 )
6284 def revert(ui, repo, *pats, **opts):
6304 def revert(ui, repo, *pats, **opts):
6285 """restore files to their checkout state
6305 """restore files to their checkout state
6286
6306
6287 .. note::
6307 .. note::
6288
6308
6289 To check out earlier revisions, you should use :hg:`update REV`.
6309 To check out earlier revisions, you should use :hg:`update REV`.
6290 To cancel an uncommitted merge (and lose your changes),
6310 To cancel an uncommitted merge (and lose your changes),
6291 use :hg:`merge --abort`.
6311 use :hg:`merge --abort`.
6292
6312
6293 With no revision specified, revert the specified files or directories
6313 With no revision specified, revert the specified files or directories
6294 to the contents they had in the parent of the working directory.
6314 to the contents they had in the parent of the working directory.
6295 This restores the contents of files to an unmodified
6315 This restores the contents of files to an unmodified
6296 state and unschedules adds, removes, copies, and renames. If the
6316 state and unschedules adds, removes, copies, and renames. If the
6297 working directory has two parents, you must explicitly specify a
6317 working directory has two parents, you must explicitly specify a
6298 revision.
6318 revision.
6299
6319
6300 Using the -r/--rev or -d/--date options, revert the given files or
6320 Using the -r/--rev or -d/--date options, revert the given files or
6301 directories to their states as of a specific revision. Because
6321 directories to their states as of a specific revision. Because
6302 revert does not change the working directory parents, this will
6322 revert does not change the working directory parents, this will
6303 cause these files to appear modified. This can be helpful to "back
6323 cause these files to appear modified. This can be helpful to "back
6304 out" some or all of an earlier change. See :hg:`backout` for a
6324 out" some or all of an earlier change. See :hg:`backout` for a
6305 related method.
6325 related method.
6306
6326
6307 Modified files are saved with a .orig suffix before reverting.
6327 Modified files are saved with a .orig suffix before reverting.
6308 To disable these backups, use --no-backup. It is possible to store
6328 To disable these backups, use --no-backup. It is possible to store
6309 the backup files in a custom directory relative to the root of the
6329 the backup files in a custom directory relative to the root of the
6310 repository by setting the ``ui.origbackuppath`` configuration
6330 repository by setting the ``ui.origbackuppath`` configuration
6311 option.
6331 option.
6312
6332
6313 See :hg:`help dates` for a list of formats valid for -d/--date.
6333 See :hg:`help dates` for a list of formats valid for -d/--date.
6314
6334
6315 See :hg:`help backout` for a way to reverse the effect of an
6335 See :hg:`help backout` for a way to reverse the effect of an
6316 earlier changeset.
6336 earlier changeset.
6317
6337
6318 Returns 0 on success.
6338 Returns 0 on success.
6319 """
6339 """
6320
6340
6321 opts = pycompat.byteskwargs(opts)
6341 opts = pycompat.byteskwargs(opts)
6322 if opts.get(b"date"):
6342 if opts.get(b"date"):
6323 cmdutil.check_incompatible_arguments(opts, b'date', [b'rev'])
6343 cmdutil.check_incompatible_arguments(opts, b'date', [b'rev'])
6324 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6344 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6325
6345
6326 parent, p2 = repo.dirstate.parents()
6346 parent, p2 = repo.dirstate.parents()
6327 if not opts.get(b'rev') and p2 != repo.nullid:
6347 if not opts.get(b'rev') and p2 != repo.nullid:
6328 # revert after merge is a trap for new users (issue2915)
6348 # revert after merge is a trap for new users (issue2915)
6329 raise error.InputError(
6349 raise error.InputError(
6330 _(b'uncommitted merge with no revision specified'),
6350 _(b'uncommitted merge with no revision specified'),
6331 hint=_(b"use 'hg update' or see 'hg help revert'"),
6351 hint=_(b"use 'hg update' or see 'hg help revert'"),
6332 )
6352 )
6333
6353
6334 rev = opts.get(b'rev')
6354 rev = opts.get(b'rev')
6335 if rev:
6355 if rev:
6336 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6356 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6337 ctx = logcmdutil.revsingle(repo, rev)
6357 ctx = logcmdutil.revsingle(repo, rev)
6338
6358
6339 if not (
6359 if not (
6340 pats
6360 pats
6341 or opts.get(b'include')
6361 or opts.get(b'include')
6342 or opts.get(b'exclude')
6362 or opts.get(b'exclude')
6343 or opts.get(b'all')
6363 or opts.get(b'all')
6344 or opts.get(b'interactive')
6364 or opts.get(b'interactive')
6345 ):
6365 ):
6346 msg = _(b"no files or directories specified")
6366 msg = _(b"no files or directories specified")
6347 if p2 != repo.nullid:
6367 if p2 != repo.nullid:
6348 hint = _(
6368 hint = _(
6349 b"uncommitted merge, use --all to discard all changes,"
6369 b"uncommitted merge, use --all to discard all changes,"
6350 b" or 'hg update -C .' to abort the merge"
6370 b" or 'hg update -C .' to abort the merge"
6351 )
6371 )
6352 raise error.InputError(msg, hint=hint)
6372 raise error.InputError(msg, hint=hint)
6353 dirty = any(repo.status())
6373 dirty = any(repo.status())
6354 node = ctx.node()
6374 node = ctx.node()
6355 if node != parent:
6375 if node != parent:
6356 if dirty:
6376 if dirty:
6357 hint = (
6377 hint = (
6358 _(
6378 _(
6359 b"uncommitted changes, use --all to discard all"
6379 b"uncommitted changes, use --all to discard all"
6360 b" changes, or 'hg update %d' to update"
6380 b" changes, or 'hg update %d' to update"
6361 )
6381 )
6362 % ctx.rev()
6382 % ctx.rev()
6363 )
6383 )
6364 else:
6384 else:
6365 hint = (
6385 hint = (
6366 _(
6386 _(
6367 b"use --all to revert all files,"
6387 b"use --all to revert all files,"
6368 b" or 'hg update %d' to update"
6388 b" or 'hg update %d' to update"
6369 )
6389 )
6370 % ctx.rev()
6390 % ctx.rev()
6371 )
6391 )
6372 elif dirty:
6392 elif dirty:
6373 hint = _(b"uncommitted changes, use --all to discard all changes")
6393 hint = _(b"uncommitted changes, use --all to discard all changes")
6374 else:
6394 else:
6375 hint = _(b"use --all to revert all files")
6395 hint = _(b"use --all to revert all files")
6376 raise error.InputError(msg, hint=hint)
6396 raise error.InputError(msg, hint=hint)
6377
6397
6378 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6398 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6379
6399
6380
6400
6381 @command(
6401 @command(
6382 b'rollback',
6402 b'rollback',
6383 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6403 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6384 helpcategory=command.CATEGORY_MAINTENANCE,
6404 helpcategory=command.CATEGORY_MAINTENANCE,
6385 )
6405 )
6386 def rollback(ui, repo, **opts):
6406 def rollback(ui, repo, **opts):
6387 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6407 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6388
6408
6389 Please use :hg:`commit --amend` instead of rollback to correct
6409 Please use :hg:`commit --amend` instead of rollback to correct
6390 mistakes in the last commit.
6410 mistakes in the last commit.
6391
6411
6392 This command should be used with care. There is only one level of
6412 This command should be used with care. There is only one level of
6393 rollback, and there is no way to undo a rollback. It will also
6413 rollback, and there is no way to undo a rollback. It will also
6394 restore the dirstate at the time of the last transaction, losing
6414 restore the dirstate at the time of the last transaction, losing
6395 any dirstate changes since that time. This command does not alter
6415 any dirstate changes since that time. This command does not alter
6396 the working directory.
6416 the working directory.
6397
6417
6398 Transactions are used to encapsulate the effects of all commands
6418 Transactions are used to encapsulate the effects of all commands
6399 that create new changesets or propagate existing changesets into a
6419 that create new changesets or propagate existing changesets into a
6400 repository.
6420 repository.
6401
6421
6402 .. container:: verbose
6422 .. container:: verbose
6403
6423
6404 For example, the following commands are transactional, and their
6424 For example, the following commands are transactional, and their
6405 effects can be rolled back:
6425 effects can be rolled back:
6406
6426
6407 - commit
6427 - commit
6408 - import
6428 - import
6409 - pull
6429 - pull
6410 - push (with this repository as the destination)
6430 - push (with this repository as the destination)
6411 - unbundle
6431 - unbundle
6412
6432
6413 To avoid permanent data loss, rollback will refuse to rollback a
6433 To avoid permanent data loss, rollback will refuse to rollback a
6414 commit transaction if it isn't checked out. Use --force to
6434 commit transaction if it isn't checked out. Use --force to
6415 override this protection.
6435 override this protection.
6416
6436
6417 The rollback command can be entirely disabled by setting the
6437 The rollback command can be entirely disabled by setting the
6418 ``ui.rollback`` configuration setting to false. If you're here
6438 ``ui.rollback`` configuration setting to false. If you're here
6419 because you want to use rollback and it's disabled, you can
6439 because you want to use rollback and it's disabled, you can
6420 re-enable the command by setting ``ui.rollback`` to true.
6440 re-enable the command by setting ``ui.rollback`` to true.
6421
6441
6422 This command is not intended for use on public repositories. Once
6442 This command is not intended for use on public repositories. Once
6423 changes are visible for pull by other users, rolling a transaction
6443 changes are visible for pull by other users, rolling a transaction
6424 back locally is ineffective (someone else may already have pulled
6444 back locally is ineffective (someone else may already have pulled
6425 the changes). Furthermore, a race is possible with readers of the
6445 the changes). Furthermore, a race is possible with readers of the
6426 repository; for example an in-progress pull from the repository
6446 repository; for example an in-progress pull from the repository
6427 may fail if a rollback is performed.
6447 may fail if a rollback is performed.
6428
6448
6429 Returns 0 on success, 1 if no rollback data is available.
6449 Returns 0 on success, 1 if no rollback data is available.
6430 """
6450 """
6431 if not ui.configbool(b'ui', b'rollback'):
6451 if not ui.configbool(b'ui', b'rollback'):
6432 raise error.Abort(
6452 raise error.Abort(
6433 _(b'rollback is disabled because it is unsafe'),
6453 _(b'rollback is disabled because it is unsafe'),
6434 hint=b'see `hg help -v rollback` for information',
6454 hint=b'see `hg help -v rollback` for information',
6435 )
6455 )
6436 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6456 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6437
6457
6438
6458
6439 @command(
6459 @command(
6440 b'root',
6460 b'root',
6441 [] + formatteropts,
6461 [] + formatteropts,
6442 intents={INTENT_READONLY},
6462 intents={INTENT_READONLY},
6443 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6463 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6444 )
6464 )
6445 def root(ui, repo, **opts):
6465 def root(ui, repo, **opts):
6446 """print the root (top) of the current working directory
6466 """print the root (top) of the current working directory
6447
6467
6448 Print the root directory of the current repository.
6468 Print the root directory of the current repository.
6449
6469
6450 .. container:: verbose
6470 .. container:: verbose
6451
6471
6452 Template:
6472 Template:
6453
6473
6454 The following keywords are supported in addition to the common template
6474 The following keywords are supported in addition to the common template
6455 keywords and functions. See also :hg:`help templates`.
6475 keywords and functions. See also :hg:`help templates`.
6456
6476
6457 :hgpath: String. Path to the .hg directory.
6477 :hgpath: String. Path to the .hg directory.
6458 :storepath: String. Path to the directory holding versioned data.
6478 :storepath: String. Path to the directory holding versioned data.
6459
6479
6460 Returns 0 on success.
6480 Returns 0 on success.
6461 """
6481 """
6462 opts = pycompat.byteskwargs(opts)
6482 opts = pycompat.byteskwargs(opts)
6463 with ui.formatter(b'root', opts) as fm:
6483 with ui.formatter(b'root', opts) as fm:
6464 fm.startitem()
6484 fm.startitem()
6465 fm.write(b'reporoot', b'%s\n', repo.root)
6485 fm.write(b'reporoot', b'%s\n', repo.root)
6466 fm.data(hgpath=repo.path, storepath=repo.spath)
6486 fm.data(hgpath=repo.path, storepath=repo.spath)
6467
6487
6468
6488
6469 @command(
6489 @command(
6470 b'serve',
6490 b'serve',
6471 [
6491 [
6472 (
6492 (
6473 b'A',
6493 b'A',
6474 b'accesslog',
6494 b'accesslog',
6475 b'',
6495 b'',
6476 _(b'name of access log file to write to'),
6496 _(b'name of access log file to write to'),
6477 _(b'FILE'),
6497 _(b'FILE'),
6478 ),
6498 ),
6479 (b'd', b'daemon', None, _(b'run server in background')),
6499 (b'd', b'daemon', None, _(b'run server in background')),
6480 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6500 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6481 (
6501 (
6482 b'E',
6502 b'E',
6483 b'errorlog',
6503 b'errorlog',
6484 b'',
6504 b'',
6485 _(b'name of error log file to write to'),
6505 _(b'name of error log file to write to'),
6486 _(b'FILE'),
6506 _(b'FILE'),
6487 ),
6507 ),
6488 # use string type, then we can check if something was passed
6508 # use string type, then we can check if something was passed
6489 (
6509 (
6490 b'p',
6510 b'p',
6491 b'port',
6511 b'port',
6492 b'',
6512 b'',
6493 _(b'port to listen on (default: 8000)'),
6513 _(b'port to listen on (default: 8000)'),
6494 _(b'PORT'),
6514 _(b'PORT'),
6495 ),
6515 ),
6496 (
6516 (
6497 b'a',
6517 b'a',
6498 b'address',
6518 b'address',
6499 b'',
6519 b'',
6500 _(b'address to listen on (default: all interfaces)'),
6520 _(b'address to listen on (default: all interfaces)'),
6501 _(b'ADDR'),
6521 _(b'ADDR'),
6502 ),
6522 ),
6503 (
6523 (
6504 b'',
6524 b'',
6505 b'prefix',
6525 b'prefix',
6506 b'',
6526 b'',
6507 _(b'prefix path to serve from (default: server root)'),
6527 _(b'prefix path to serve from (default: server root)'),
6508 _(b'PREFIX'),
6528 _(b'PREFIX'),
6509 ),
6529 ),
6510 (
6530 (
6511 b'n',
6531 b'n',
6512 b'name',
6532 b'name',
6513 b'',
6533 b'',
6514 _(b'name to show in web pages (default: working directory)'),
6534 _(b'name to show in web pages (default: working directory)'),
6515 _(b'NAME'),
6535 _(b'NAME'),
6516 ),
6536 ),
6517 (
6537 (
6518 b'',
6538 b'',
6519 b'web-conf',
6539 b'web-conf',
6520 b'',
6540 b'',
6521 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6541 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6522 _(b'FILE'),
6542 _(b'FILE'),
6523 ),
6543 ),
6524 (
6544 (
6525 b'',
6545 b'',
6526 b'webdir-conf',
6546 b'webdir-conf',
6527 b'',
6547 b'',
6528 _(b'name of the hgweb config file (DEPRECATED)'),
6548 _(b'name of the hgweb config file (DEPRECATED)'),
6529 _(b'FILE'),
6549 _(b'FILE'),
6530 ),
6550 ),
6531 (
6551 (
6532 b'',
6552 b'',
6533 b'pid-file',
6553 b'pid-file',
6534 b'',
6554 b'',
6535 _(b'name of file to write process ID to'),
6555 _(b'name of file to write process ID to'),
6536 _(b'FILE'),
6556 _(b'FILE'),
6537 ),
6557 ),
6538 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6558 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6539 (
6559 (
6540 b'',
6560 b'',
6541 b'cmdserver',
6561 b'cmdserver',
6542 b'',
6562 b'',
6543 _(b'for remote clients (ADVANCED)'),
6563 _(b'for remote clients (ADVANCED)'),
6544 _(b'MODE'),
6564 _(b'MODE'),
6545 ),
6565 ),
6546 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6566 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6547 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6567 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6548 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6568 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6549 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6569 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6550 (b'', b'print-url', None, _(b'start and print only the URL')),
6570 (b'', b'print-url', None, _(b'start and print only the URL')),
6551 ]
6571 ]
6552 + subrepoopts,
6572 + subrepoopts,
6553 _(b'[OPTION]...'),
6573 _(b'[OPTION]...'),
6554 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6574 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6555 helpbasic=True,
6575 helpbasic=True,
6556 optionalrepo=True,
6576 optionalrepo=True,
6557 )
6577 )
6558 def serve(ui, repo, **opts):
6578 def serve(ui, repo, **opts):
6559 """start stand-alone webserver
6579 """start stand-alone webserver
6560
6580
6561 Start a local HTTP repository browser and pull server. You can use
6581 Start a local HTTP repository browser and pull server. You can use
6562 this for ad-hoc sharing and browsing of repositories. It is
6582 this for ad-hoc sharing and browsing of repositories. It is
6563 recommended to use a real web server to serve a repository for
6583 recommended to use a real web server to serve a repository for
6564 longer periods of time.
6584 longer periods of time.
6565
6585
6566 Please note that the server does not implement access control.
6586 Please note that the server does not implement access control.
6567 This means that, by default, anybody can read from the server and
6587 This means that, by default, anybody can read from the server and
6568 nobody can write to it by default. Set the ``web.allow-push``
6588 nobody can write to it by default. Set the ``web.allow-push``
6569 option to ``*`` to allow everybody to push to the server. You
6589 option to ``*`` to allow everybody to push to the server. You
6570 should use a real web server if you need to authenticate users.
6590 should use a real web server if you need to authenticate users.
6571
6591
6572 By default, the server logs accesses to stdout and errors to
6592 By default, the server logs accesses to stdout and errors to
6573 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6593 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6574 files.
6594 files.
6575
6595
6576 To have the server choose a free port number to listen on, specify
6596 To have the server choose a free port number to listen on, specify
6577 a port number of 0; in this case, the server will print the port
6597 a port number of 0; in this case, the server will print the port
6578 number it uses.
6598 number it uses.
6579
6599
6580 Returns 0 on success.
6600 Returns 0 on success.
6581 """
6601 """
6582
6602
6583 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6603 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6584 opts = pycompat.byteskwargs(opts)
6604 opts = pycompat.byteskwargs(opts)
6585 if opts[b"print_url"] and ui.verbose:
6605 if opts[b"print_url"] and ui.verbose:
6586 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6606 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6587
6607
6588 if opts[b"stdio"]:
6608 if opts[b"stdio"]:
6589 if repo is None:
6609 if repo is None:
6590 raise error.RepoError(
6610 raise error.RepoError(
6591 _(b"there is no Mercurial repository here (.hg not found)")
6611 _(b"there is no Mercurial repository here (.hg not found)")
6592 )
6612 )
6593 s = wireprotoserver.sshserver(ui, repo)
6613 s = wireprotoserver.sshserver(ui, repo)
6594 s.serve_forever()
6614 s.serve_forever()
6595 return
6615 return
6596
6616
6597 service = server.createservice(ui, repo, opts)
6617 service = server.createservice(ui, repo, opts)
6598 return server.runservice(opts, initfn=service.init, runfn=service.run)
6618 return server.runservice(opts, initfn=service.init, runfn=service.run)
6599
6619
6600
6620
6601 @command(
6621 @command(
6602 b'shelve',
6622 b'shelve',
6603 [
6623 [
6604 (
6624 (
6605 b'A',
6625 b'A',
6606 b'addremove',
6626 b'addremove',
6607 None,
6627 None,
6608 _(b'mark new/missing files as added/removed before shelving'),
6628 _(b'mark new/missing files as added/removed before shelving'),
6609 ),
6629 ),
6610 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6630 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6611 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6631 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6612 (
6632 (
6613 b'',
6633 b'',
6614 b'date',
6634 b'date',
6615 b'',
6635 b'',
6616 _(b'shelve with the specified commit date'),
6636 _(b'shelve with the specified commit date'),
6617 _(b'DATE'),
6637 _(b'DATE'),
6618 ),
6638 ),
6619 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6639 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6620 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6640 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6621 (
6641 (
6622 b'k',
6642 b'k',
6623 b'keep',
6643 b'keep',
6624 False,
6644 False,
6625 _(b'shelve, but keep changes in the working directory'),
6645 _(b'shelve, but keep changes in the working directory'),
6626 ),
6646 ),
6627 (b'l', b'list', None, _(b'list current shelves')),
6647 (b'l', b'list', None, _(b'list current shelves')),
6628 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6648 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6629 (
6649 (
6630 b'n',
6650 b'n',
6631 b'name',
6651 b'name',
6632 b'',
6652 b'',
6633 _(b'use the given name for the shelved commit'),
6653 _(b'use the given name for the shelved commit'),
6634 _(b'NAME'),
6654 _(b'NAME'),
6635 ),
6655 ),
6636 (
6656 (
6637 b'p',
6657 b'p',
6638 b'patch',
6658 b'patch',
6639 None,
6659 None,
6640 _(
6660 _(
6641 b'output patches for changes (provide the names of the shelved '
6661 b'output patches for changes (provide the names of the shelved '
6642 b'changes as positional arguments)'
6662 b'changes as positional arguments)'
6643 ),
6663 ),
6644 ),
6664 ),
6645 (b'i', b'interactive', None, _(b'interactive mode')),
6665 (b'i', b'interactive', None, _(b'interactive mode')),
6646 (
6666 (
6647 b'',
6667 b'',
6648 b'stat',
6668 b'stat',
6649 None,
6669 None,
6650 _(
6670 _(
6651 b'output diffstat-style summary of changes (provide the names of '
6671 b'output diffstat-style summary of changes (provide the names of '
6652 b'the shelved changes as positional arguments)'
6672 b'the shelved changes as positional arguments)'
6653 ),
6673 ),
6654 ),
6674 ),
6655 ]
6675 ]
6656 + cmdutil.walkopts,
6676 + cmdutil.walkopts,
6657 _(b'hg shelve [OPTION]... [FILE]...'),
6677 _(b'hg shelve [OPTION]... [FILE]...'),
6658 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6678 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6659 )
6679 )
6660 def shelve(ui, repo, *pats, **opts):
6680 def shelve(ui, repo, *pats, **opts):
6661 """save and set aside changes from the working directory
6681 """save and set aside changes from the working directory
6662
6682
6663 Shelving takes files that "hg status" reports as not clean, saves
6683 Shelving takes files that "hg status" reports as not clean, saves
6664 the modifications to a bundle (a shelved change), and reverts the
6684 the modifications to a bundle (a shelved change), and reverts the
6665 files so that their state in the working directory becomes clean.
6685 files so that their state in the working directory becomes clean.
6666
6686
6667 To restore these changes to the working directory, using "hg
6687 To restore these changes to the working directory, using "hg
6668 unshelve"; this will work even if you switch to a different
6688 unshelve"; this will work even if you switch to a different
6669 commit.
6689 commit.
6670
6690
6671 When no files are specified, "hg shelve" saves all not-clean
6691 When no files are specified, "hg shelve" saves all not-clean
6672 files. If specific files or directories are named, only changes to
6692 files. If specific files or directories are named, only changes to
6673 those files are shelved.
6693 those files are shelved.
6674
6694
6675 In bare shelve (when no files are specified, without interactive,
6695 In bare shelve (when no files are specified, without interactive,
6676 include and exclude option), shelving remembers information if the
6696 include and exclude option), shelving remembers information if the
6677 working directory was on newly created branch, in other words working
6697 working directory was on newly created branch, in other words working
6678 directory was on different branch than its first parent. In this
6698 directory was on different branch than its first parent. In this
6679 situation unshelving restores branch information to the working directory.
6699 situation unshelving restores branch information to the working directory.
6680
6700
6681 Each shelved change has a name that makes it easier to find later.
6701 Each shelved change has a name that makes it easier to find later.
6682 The name of a shelved change defaults to being based on the active
6702 The name of a shelved change defaults to being based on the active
6683 bookmark, or if there is no active bookmark, the current named
6703 bookmark, or if there is no active bookmark, the current named
6684 branch. To specify a different name, use ``--name``.
6704 branch. To specify a different name, use ``--name``.
6685
6705
6686 To see a list of existing shelved changes, use the ``--list``
6706 To see a list of existing shelved changes, use the ``--list``
6687 option. For each shelved change, this will print its name, age,
6707 option. For each shelved change, this will print its name, age,
6688 and description; use ``--patch`` or ``--stat`` for more details.
6708 and description; use ``--patch`` or ``--stat`` for more details.
6689
6709
6690 To delete specific shelved changes, use ``--delete``. To delete
6710 To delete specific shelved changes, use ``--delete``. To delete
6691 all shelved changes, use ``--cleanup``.
6711 all shelved changes, use ``--cleanup``.
6692 """
6712 """
6693 opts = pycompat.byteskwargs(opts)
6713 opts = pycompat.byteskwargs(opts)
6694 allowables = [
6714 allowables = [
6695 (b'addremove', {b'create'}), # 'create' is pseudo action
6715 (b'addremove', {b'create'}), # 'create' is pseudo action
6696 (b'unknown', {b'create'}),
6716 (b'unknown', {b'create'}),
6697 (b'cleanup', {b'cleanup'}),
6717 (b'cleanup', {b'cleanup'}),
6698 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6718 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6699 (b'delete', {b'delete'}),
6719 (b'delete', {b'delete'}),
6700 (b'edit', {b'create'}),
6720 (b'edit', {b'create'}),
6701 (b'keep', {b'create'}),
6721 (b'keep', {b'create'}),
6702 (b'list', {b'list'}),
6722 (b'list', {b'list'}),
6703 (b'message', {b'create'}),
6723 (b'message', {b'create'}),
6704 (b'name', {b'create'}),
6724 (b'name', {b'create'}),
6705 (b'patch', {b'patch', b'list'}),
6725 (b'patch', {b'patch', b'list'}),
6706 (b'stat', {b'stat', b'list'}),
6726 (b'stat', {b'stat', b'list'}),
6707 ]
6727 ]
6708
6728
6709 def checkopt(opt):
6729 def checkopt(opt):
6710 if opts.get(opt):
6730 if opts.get(opt):
6711 for i, allowable in allowables:
6731 for i, allowable in allowables:
6712 if opts[i] and opt not in allowable:
6732 if opts[i] and opt not in allowable:
6713 raise error.InputError(
6733 raise error.InputError(
6714 _(
6734 _(
6715 b"options '--%s' and '--%s' may not be "
6735 b"options '--%s' and '--%s' may not be "
6716 b"used together"
6736 b"used together"
6717 )
6737 )
6718 % (opt, i)
6738 % (opt, i)
6719 )
6739 )
6720 return True
6740 return True
6721
6741
6722 if checkopt(b'cleanup'):
6742 if checkopt(b'cleanup'):
6723 if pats:
6743 if pats:
6724 raise error.InputError(
6744 raise error.InputError(
6725 _(b"cannot specify names when using '--cleanup'")
6745 _(b"cannot specify names when using '--cleanup'")
6726 )
6746 )
6727 return shelvemod.cleanupcmd(ui, repo)
6747 return shelvemod.cleanupcmd(ui, repo)
6728 elif checkopt(b'delete'):
6748 elif checkopt(b'delete'):
6729 return shelvemod.deletecmd(ui, repo, pats)
6749 return shelvemod.deletecmd(ui, repo, pats)
6730 elif checkopt(b'list'):
6750 elif checkopt(b'list'):
6731 return shelvemod.listcmd(ui, repo, pats, opts)
6751 return shelvemod.listcmd(ui, repo, pats, opts)
6732 elif checkopt(b'patch') or checkopt(b'stat'):
6752 elif checkopt(b'patch') or checkopt(b'stat'):
6733 return shelvemod.patchcmds(ui, repo, pats, opts)
6753 return shelvemod.patchcmds(ui, repo, pats, opts)
6734 else:
6754 else:
6735 return shelvemod.createcmd(ui, repo, pats, opts)
6755 return shelvemod.createcmd(ui, repo, pats, opts)
6736
6756
6737
6757
6738 _NOTTERSE = b'nothing'
6758 _NOTTERSE = b'nothing'
6739
6759
6740
6760
6741 @command(
6761 @command(
6742 b'status|st',
6762 b'status|st',
6743 [
6763 [
6744 (b'A', b'all', None, _(b'show status of all files')),
6764 (b'A', b'all', None, _(b'show status of all files')),
6745 (b'm', b'modified', None, _(b'show only modified files')),
6765 (b'm', b'modified', None, _(b'show only modified files')),
6746 (b'a', b'added', None, _(b'show only added files')),
6766 (b'a', b'added', None, _(b'show only added files')),
6747 (b'r', b'removed', None, _(b'show only removed files')),
6767 (b'r', b'removed', None, _(b'show only removed files')),
6748 (b'd', b'deleted', None, _(b'show only missing files')),
6768 (b'd', b'deleted', None, _(b'show only missing files')),
6749 (b'c', b'clean', None, _(b'show only files without changes')),
6769 (b'c', b'clean', None, _(b'show only files without changes')),
6750 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6770 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6751 (b'i', b'ignored', None, _(b'show only ignored files')),
6771 (b'i', b'ignored', None, _(b'show only ignored files')),
6752 (b'n', b'no-status', None, _(b'hide status prefix')),
6772 (b'n', b'no-status', None, _(b'hide status prefix')),
6753 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6773 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6754 (
6774 (
6755 b'C',
6775 b'C',
6756 b'copies',
6776 b'copies',
6757 None,
6777 None,
6758 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6778 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6759 ),
6779 ),
6760 (
6780 (
6761 b'0',
6781 b'0',
6762 b'print0',
6782 b'print0',
6763 None,
6783 None,
6764 _(b'end filenames with NUL, for use with xargs'),
6784 _(b'end filenames with NUL, for use with xargs'),
6765 ),
6785 ),
6766 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6786 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6767 (
6787 (
6768 b'',
6788 b'',
6769 b'change',
6789 b'change',
6770 b'',
6790 b'',
6771 _(b'list the changed files of a revision'),
6791 _(b'list the changed files of a revision'),
6772 _(b'REV'),
6792 _(b'REV'),
6773 ),
6793 ),
6774 ]
6794 ]
6775 + walkopts
6795 + walkopts
6776 + subrepoopts
6796 + subrepoopts
6777 + formatteropts,
6797 + formatteropts,
6778 _(b'[OPTION]... [FILE]...'),
6798 _(b'[OPTION]... [FILE]...'),
6779 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6799 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6780 helpbasic=True,
6800 helpbasic=True,
6781 inferrepo=True,
6801 inferrepo=True,
6782 intents={INTENT_READONLY},
6802 intents={INTENT_READONLY},
6783 )
6803 )
6784 def status(ui, repo, *pats, **opts):
6804 def status(ui, repo, *pats, **opts):
6785 """show changed files in the working directory
6805 """show changed files in the working directory
6786
6806
6787 Show status of files in the repository. If names are given, only
6807 Show status of files in the repository. If names are given, only
6788 files that match are shown. Files that are clean or ignored or
6808 files that match are shown. Files that are clean or ignored or
6789 the source of a copy/move operation, are not listed unless
6809 the source of a copy/move operation, are not listed unless
6790 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6810 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6791 Unless options described with "show only ..." are given, the
6811 Unless options described with "show only ..." are given, the
6792 options -mardu are used.
6812 options -mardu are used.
6793
6813
6794 Option -q/--quiet hides untracked (unknown and ignored) files
6814 Option -q/--quiet hides untracked (unknown and ignored) files
6795 unless explicitly requested with -u/--unknown or -i/--ignored.
6815 unless explicitly requested with -u/--unknown or -i/--ignored.
6796
6816
6797 .. note::
6817 .. note::
6798
6818
6799 :hg:`status` may appear to disagree with diff if permissions have
6819 :hg:`status` may appear to disagree with diff if permissions have
6800 changed or a merge has occurred. The standard diff format does
6820 changed or a merge has occurred. The standard diff format does
6801 not report permission changes and diff only reports changes
6821 not report permission changes and diff only reports changes
6802 relative to one merge parent.
6822 relative to one merge parent.
6803
6823
6804 If one revision is given, it is used as the base revision.
6824 If one revision is given, it is used as the base revision.
6805 If two revisions are given, the differences between them are
6825 If two revisions are given, the differences between them are
6806 shown. The --change option can also be used as a shortcut to list
6826 shown. The --change option can also be used as a shortcut to list
6807 the changed files of a revision from its first parent.
6827 the changed files of a revision from its first parent.
6808
6828
6809 The codes used to show the status of files are::
6829 The codes used to show the status of files are::
6810
6830
6811 M = modified
6831 M = modified
6812 A = added
6832 A = added
6813 R = removed
6833 R = removed
6814 C = clean
6834 C = clean
6815 ! = missing (deleted by non-hg command, but still tracked)
6835 ! = missing (deleted by non-hg command, but still tracked)
6816 ? = not tracked
6836 ? = not tracked
6817 I = ignored
6837 I = ignored
6818 = origin of the previous file (with --copies)
6838 = origin of the previous file (with --copies)
6819
6839
6820 .. container:: verbose
6840 .. container:: verbose
6821
6841
6822 The -t/--terse option abbreviates the output by showing only the directory
6842 The -t/--terse option abbreviates the output by showing only the directory
6823 name if all the files in it share the same status. The option takes an
6843 name if all the files in it share the same status. The option takes an
6824 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6844 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6825 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6845 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6826 for 'ignored' and 'c' for clean.
6846 for 'ignored' and 'c' for clean.
6827
6847
6828 It abbreviates only those statuses which are passed. Note that clean and
6848 It abbreviates only those statuses which are passed. Note that clean and
6829 ignored files are not displayed with '--terse ic' unless the -c/--clean
6849 ignored files are not displayed with '--terse ic' unless the -c/--clean
6830 and -i/--ignored options are also used.
6850 and -i/--ignored options are also used.
6831
6851
6832 The -v/--verbose option shows information when the repository is in an
6852 The -v/--verbose option shows information when the repository is in an
6833 unfinished merge, shelve, rebase state etc. You can have this behavior
6853 unfinished merge, shelve, rebase state etc. You can have this behavior
6834 turned on by default by enabling the ``commands.status.verbose`` option.
6854 turned on by default by enabling the ``commands.status.verbose`` option.
6835
6855
6836 You can skip displaying some of these states by setting
6856 You can skip displaying some of these states by setting
6837 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6857 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6838 'histedit', 'merge', 'rebase', or 'unshelve'.
6858 'histedit', 'merge', 'rebase', or 'unshelve'.
6839
6859
6840 Template:
6860 Template:
6841
6861
6842 The following keywords are supported in addition to the common template
6862 The following keywords are supported in addition to the common template
6843 keywords and functions. See also :hg:`help templates`.
6863 keywords and functions. See also :hg:`help templates`.
6844
6864
6845 :path: String. Repository-absolute path of the file.
6865 :path: String. Repository-absolute path of the file.
6846 :source: String. Repository-absolute path of the file originated from.
6866 :source: String. Repository-absolute path of the file originated from.
6847 Available if ``--copies`` is specified.
6867 Available if ``--copies`` is specified.
6848 :status: String. Character denoting file's status.
6868 :status: String. Character denoting file's status.
6849
6869
6850 Examples:
6870 Examples:
6851
6871
6852 - show changes in the working directory relative to a
6872 - show changes in the working directory relative to a
6853 changeset::
6873 changeset::
6854
6874
6855 hg status --rev 9353
6875 hg status --rev 9353
6856
6876
6857 - show changes in the working directory relative to the
6877 - show changes in the working directory relative to the
6858 current directory (see :hg:`help patterns` for more information)::
6878 current directory (see :hg:`help patterns` for more information)::
6859
6879
6860 hg status re:
6880 hg status re:
6861
6881
6862 - show all changes including copies in an existing changeset::
6882 - show all changes including copies in an existing changeset::
6863
6883
6864 hg status --copies --change 9353
6884 hg status --copies --change 9353
6865
6885
6866 - get a NUL separated list of added files, suitable for xargs::
6886 - get a NUL separated list of added files, suitable for xargs::
6867
6887
6868 hg status -an0
6888 hg status -an0
6869
6889
6870 - show more information about the repository status, abbreviating
6890 - show more information about the repository status, abbreviating
6871 added, removed, modified, deleted, and untracked paths::
6891 added, removed, modified, deleted, and untracked paths::
6872
6892
6873 hg status -v -t mardu
6893 hg status -v -t mardu
6874
6894
6875 Returns 0 on success.
6895 Returns 0 on success.
6876
6896
6877 """
6897 """
6878
6898
6879 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6899 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6880 opts = pycompat.byteskwargs(opts)
6900 opts = pycompat.byteskwargs(opts)
6881 revs = opts.get(b'rev', [])
6901 revs = opts.get(b'rev', [])
6882 change = opts.get(b'change', b'')
6902 change = opts.get(b'change', b'')
6883 terse = opts.get(b'terse', _NOTTERSE)
6903 terse = opts.get(b'terse', _NOTTERSE)
6884 if terse is _NOTTERSE:
6904 if terse is _NOTTERSE:
6885 if revs:
6905 if revs:
6886 terse = b''
6906 terse = b''
6887 else:
6907 else:
6888 terse = ui.config(b'commands', b'status.terse')
6908 terse = ui.config(b'commands', b'status.terse')
6889
6909
6890 if revs and terse:
6910 if revs and terse:
6891 msg = _(b'cannot use --terse with --rev')
6911 msg = _(b'cannot use --terse with --rev')
6892 raise error.InputError(msg)
6912 raise error.InputError(msg)
6893 elif change:
6913 elif change:
6894 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6914 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6895 ctx2 = logcmdutil.revsingle(repo, change, None)
6915 ctx2 = logcmdutil.revsingle(repo, change, None)
6896 ctx1 = ctx2.p1()
6916 ctx1 = ctx2.p1()
6897 else:
6917 else:
6898 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6918 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6899 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
6919 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
6900
6920
6901 forcerelativevalue = None
6921 forcerelativevalue = None
6902 if ui.hasconfig(b'commands', b'status.relative'):
6922 if ui.hasconfig(b'commands', b'status.relative'):
6903 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6923 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6904 uipathfn = scmutil.getuipathfn(
6924 uipathfn = scmutil.getuipathfn(
6905 repo,
6925 repo,
6906 legacyrelativevalue=bool(pats),
6926 legacyrelativevalue=bool(pats),
6907 forcerelativevalue=forcerelativevalue,
6927 forcerelativevalue=forcerelativevalue,
6908 )
6928 )
6909
6929
6910 if opts.get(b'print0'):
6930 if opts.get(b'print0'):
6911 end = b'\0'
6931 end = b'\0'
6912 else:
6932 else:
6913 end = b'\n'
6933 end = b'\n'
6914 states = b'modified added removed deleted unknown ignored clean'.split()
6934 states = b'modified added removed deleted unknown ignored clean'.split()
6915 show = [k for k in states if opts.get(k)]
6935 show = [k for k in states if opts.get(k)]
6916 if opts.get(b'all'):
6936 if opts.get(b'all'):
6917 show += ui.quiet and (states[:4] + [b'clean']) or states
6937 show += ui.quiet and (states[:4] + [b'clean']) or states
6918
6938
6919 if not show:
6939 if not show:
6920 if ui.quiet:
6940 if ui.quiet:
6921 show = states[:4]
6941 show = states[:4]
6922 else:
6942 else:
6923 show = states[:5]
6943 show = states[:5]
6924
6944
6925 m = scmutil.match(ctx2, pats, opts)
6945 m = scmutil.match(ctx2, pats, opts)
6926 if terse:
6946 if terse:
6927 # we need to compute clean and unknown to terse
6947 # we need to compute clean and unknown to terse
6928 stat = repo.status(
6948 stat = repo.status(
6929 ctx1.node(),
6949 ctx1.node(),
6930 ctx2.node(),
6950 ctx2.node(),
6931 m,
6951 m,
6932 b'ignored' in show or b'i' in terse,
6952 b'ignored' in show or b'i' in terse,
6933 clean=True,
6953 clean=True,
6934 unknown=True,
6954 unknown=True,
6935 listsubrepos=opts.get(b'subrepos'),
6955 listsubrepos=opts.get(b'subrepos'),
6936 )
6956 )
6937
6957
6938 stat = cmdutil.tersedir(stat, terse)
6958 stat = cmdutil.tersedir(stat, terse)
6939 else:
6959 else:
6940 stat = repo.status(
6960 stat = repo.status(
6941 ctx1.node(),
6961 ctx1.node(),
6942 ctx2.node(),
6962 ctx2.node(),
6943 m,
6963 m,
6944 b'ignored' in show,
6964 b'ignored' in show,
6945 b'clean' in show,
6965 b'clean' in show,
6946 b'unknown' in show,
6966 b'unknown' in show,
6947 opts.get(b'subrepos'),
6967 opts.get(b'subrepos'),
6948 )
6968 )
6949
6969
6950 changestates = zip(
6970 changestates = zip(
6951 states,
6971 states,
6952 pycompat.iterbytestr(b'MAR!?IC'),
6972 pycompat.iterbytestr(b'MAR!?IC'),
6953 [getattr(stat, s.decode('utf8')) for s in states],
6973 [getattr(stat, s.decode('utf8')) for s in states],
6954 )
6974 )
6955
6975
6956 copy = {}
6976 copy = {}
6957 if (
6977 if (
6958 opts.get(b'all')
6978 opts.get(b'all')
6959 or opts.get(b'copies')
6979 or opts.get(b'copies')
6960 or ui.configbool(b'ui', b'statuscopies')
6980 or ui.configbool(b'ui', b'statuscopies')
6961 ) and not opts.get(b'no_status'):
6981 ) and not opts.get(b'no_status'):
6962 copy = copies.pathcopies(ctx1, ctx2, m)
6982 copy = copies.pathcopies(ctx1, ctx2, m)
6963
6983
6964 morestatus = None
6984 morestatus = None
6965 if (
6985 if (
6966 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
6986 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
6967 and not ui.plain()
6987 and not ui.plain()
6968 and not opts.get(b'print0')
6988 and not opts.get(b'print0')
6969 ):
6989 ):
6970 morestatus = cmdutil.readmorestatus(repo)
6990 morestatus = cmdutil.readmorestatus(repo)
6971
6991
6972 ui.pager(b'status')
6992 ui.pager(b'status')
6973 fm = ui.formatter(b'status', opts)
6993 fm = ui.formatter(b'status', opts)
6974 fmt = b'%s' + end
6994 fmt = b'%s' + end
6975 showchar = not opts.get(b'no_status')
6995 showchar = not opts.get(b'no_status')
6976
6996
6977 for state, char, files in changestates:
6997 for state, char, files in changestates:
6978 if state in show:
6998 if state in show:
6979 label = b'status.' + state
6999 label = b'status.' + state
6980 for f in files:
7000 for f in files:
6981 fm.startitem()
7001 fm.startitem()
6982 fm.context(ctx=ctx2)
7002 fm.context(ctx=ctx2)
6983 fm.data(itemtype=b'file', path=f)
7003 fm.data(itemtype=b'file', path=f)
6984 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
7004 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6985 fm.plain(fmt % uipathfn(f), label=label)
7005 fm.plain(fmt % uipathfn(f), label=label)
6986 if f in copy:
7006 if f in copy:
6987 fm.data(source=copy[f])
7007 fm.data(source=copy[f])
6988 fm.plain(
7008 fm.plain(
6989 (b' %s' + end) % uipathfn(copy[f]),
7009 (b' %s' + end) % uipathfn(copy[f]),
6990 label=b'status.copied',
7010 label=b'status.copied',
6991 )
7011 )
6992 if morestatus:
7012 if morestatus:
6993 morestatus.formatfile(f, fm)
7013 morestatus.formatfile(f, fm)
6994
7014
6995 if morestatus:
7015 if morestatus:
6996 morestatus.formatfooter(fm)
7016 morestatus.formatfooter(fm)
6997 fm.end()
7017 fm.end()
6998
7018
6999
7019
7000 @command(
7020 @command(
7001 b'summary|sum',
7021 b'summary|sum',
7002 [(b'', b'remote', None, _(b'check for push and pull'))],
7022 [(b'', b'remote', None, _(b'check for push and pull'))],
7003 b'[--remote]',
7023 b'[--remote]',
7004 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7024 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7005 helpbasic=True,
7025 helpbasic=True,
7006 intents={INTENT_READONLY},
7026 intents={INTENT_READONLY},
7007 )
7027 )
7008 def summary(ui, repo, **opts):
7028 def summary(ui, repo, **opts):
7009 """summarize working directory state
7029 """summarize working directory state
7010
7030
7011 This generates a brief summary of the working directory state,
7031 This generates a brief summary of the working directory state,
7012 including parents, branch, commit status, phase and available updates.
7032 including parents, branch, commit status, phase and available updates.
7013
7033
7014 With the --remote option, this will check the default paths for
7034 With the --remote option, this will check the default paths for
7015 incoming and outgoing changes. This can be time-consuming.
7035 incoming and outgoing changes. This can be time-consuming.
7016
7036
7017 Returns 0 on success.
7037 Returns 0 on success.
7018 """
7038 """
7019
7039
7020 opts = pycompat.byteskwargs(opts)
7040 opts = pycompat.byteskwargs(opts)
7021 ui.pager(b'summary')
7041 ui.pager(b'summary')
7022 ctx = repo[None]
7042 ctx = repo[None]
7023 parents = ctx.parents()
7043 parents = ctx.parents()
7024 pnode = parents[0].node()
7044 pnode = parents[0].node()
7025 marks = []
7045 marks = []
7026
7046
7027 try:
7047 try:
7028 ms = mergestatemod.mergestate.read(repo)
7048 ms = mergestatemod.mergestate.read(repo)
7029 except error.UnsupportedMergeRecords as e:
7049 except error.UnsupportedMergeRecords as e:
7030 s = b' '.join(e.recordtypes)
7050 s = b' '.join(e.recordtypes)
7031 ui.warn(
7051 ui.warn(
7032 _(b'warning: merge state has unsupported record types: %s\n') % s
7052 _(b'warning: merge state has unsupported record types: %s\n') % s
7033 )
7053 )
7034 unresolved = []
7054 unresolved = []
7035 else:
7055 else:
7036 unresolved = list(ms.unresolved())
7056 unresolved = list(ms.unresolved())
7037
7057
7038 for p in parents:
7058 for p in parents:
7039 # label with log.changeset (instead of log.parent) since this
7059 # label with log.changeset (instead of log.parent) since this
7040 # shows a working directory parent *changeset*:
7060 # shows a working directory parent *changeset*:
7041 # i18n: column positioning for "hg summary"
7061 # i18n: column positioning for "hg summary"
7042 ui.write(
7062 ui.write(
7043 _(b'parent: %d:%s ') % (p.rev(), p),
7063 _(b'parent: %d:%s ') % (p.rev(), p),
7044 label=logcmdutil.changesetlabels(p),
7064 label=logcmdutil.changesetlabels(p),
7045 )
7065 )
7046 ui.write(b' '.join(p.tags()), label=b'log.tag')
7066 ui.write(b' '.join(p.tags()), label=b'log.tag')
7047 if p.bookmarks():
7067 if p.bookmarks():
7048 marks.extend(p.bookmarks())
7068 marks.extend(p.bookmarks())
7049 if p.rev() == -1:
7069 if p.rev() == -1:
7050 if not len(repo):
7070 if not len(repo):
7051 ui.write(_(b' (empty repository)'))
7071 ui.write(_(b' (empty repository)'))
7052 else:
7072 else:
7053 ui.write(_(b' (no revision checked out)'))
7073 ui.write(_(b' (no revision checked out)'))
7054 if p.obsolete():
7074 if p.obsolete():
7055 ui.write(_(b' (obsolete)'))
7075 ui.write(_(b' (obsolete)'))
7056 if p.isunstable():
7076 if p.isunstable():
7057 instabilities = (
7077 instabilities = (
7058 ui.label(instability, b'trouble.%s' % instability)
7078 ui.label(instability, b'trouble.%s' % instability)
7059 for instability in p.instabilities()
7079 for instability in p.instabilities()
7060 )
7080 )
7061 ui.write(b' (' + b', '.join(instabilities) + b')')
7081 ui.write(b' (' + b', '.join(instabilities) + b')')
7062 ui.write(b'\n')
7082 ui.write(b'\n')
7063 if p.description():
7083 if p.description():
7064 ui.status(
7084 ui.status(
7065 b' ' + p.description().splitlines()[0].strip() + b'\n',
7085 b' ' + p.description().splitlines()[0].strip() + b'\n',
7066 label=b'log.summary',
7086 label=b'log.summary',
7067 )
7087 )
7068
7088
7069 branch = ctx.branch()
7089 branch = ctx.branch()
7070 bheads = repo.branchheads(branch)
7090 bheads = repo.branchheads(branch)
7071 # i18n: column positioning for "hg summary"
7091 # i18n: column positioning for "hg summary"
7072 m = _(b'branch: %s\n') % branch
7092 m = _(b'branch: %s\n') % branch
7073 if branch != b'default':
7093 if branch != b'default':
7074 ui.write(m, label=b'log.branch')
7094 ui.write(m, label=b'log.branch')
7075 else:
7095 else:
7076 ui.status(m, label=b'log.branch')
7096 ui.status(m, label=b'log.branch')
7077
7097
7078 if marks:
7098 if marks:
7079 active = repo._activebookmark
7099 active = repo._activebookmark
7080 # i18n: column positioning for "hg summary"
7100 # i18n: column positioning for "hg summary"
7081 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7101 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7082 if active is not None:
7102 if active is not None:
7083 if active in marks:
7103 if active in marks:
7084 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7104 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7085 marks.remove(active)
7105 marks.remove(active)
7086 else:
7106 else:
7087 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7107 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7088 for m in marks:
7108 for m in marks:
7089 ui.write(b' ' + m, label=b'log.bookmark')
7109 ui.write(b' ' + m, label=b'log.bookmark')
7090 ui.write(b'\n', label=b'log.bookmark')
7110 ui.write(b'\n', label=b'log.bookmark')
7091
7111
7092 status = repo.status(unknown=True)
7112 status = repo.status(unknown=True)
7093
7113
7094 c = repo.dirstate.copies()
7114 c = repo.dirstate.copies()
7095 copied, renamed = [], []
7115 copied, renamed = [], []
7096 for d, s in c.items():
7116 for d, s in c.items():
7097 if s in status.removed:
7117 if s in status.removed:
7098 status.removed.remove(s)
7118 status.removed.remove(s)
7099 renamed.append(d)
7119 renamed.append(d)
7100 else:
7120 else:
7101 copied.append(d)
7121 copied.append(d)
7102 if d in status.added:
7122 if d in status.added:
7103 status.added.remove(d)
7123 status.added.remove(d)
7104
7124
7105 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7125 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7106
7126
7107 labels = [
7127 labels = [
7108 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7128 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7109 (ui.label(_(b'%d added'), b'status.added'), status.added),
7129 (ui.label(_(b'%d added'), b'status.added'), status.added),
7110 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7130 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7111 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7131 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7112 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7132 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7113 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7133 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7114 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7134 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7115 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7135 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7116 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7136 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7117 ]
7137 ]
7118 t = []
7138 t = []
7119 for l, s in labels:
7139 for l, s in labels:
7120 if s:
7140 if s:
7121 t.append(l % len(s))
7141 t.append(l % len(s))
7122
7142
7123 t = b', '.join(t)
7143 t = b', '.join(t)
7124 cleanworkdir = False
7144 cleanworkdir = False
7125
7145
7126 if repo.vfs.exists(b'graftstate'):
7146 if repo.vfs.exists(b'graftstate'):
7127 t += _(b' (graft in progress)')
7147 t += _(b' (graft in progress)')
7128 if repo.vfs.exists(b'updatestate'):
7148 if repo.vfs.exists(b'updatestate'):
7129 t += _(b' (interrupted update)')
7149 t += _(b' (interrupted update)')
7130 elif len(parents) > 1:
7150 elif len(parents) > 1:
7131 t += _(b' (merge)')
7151 t += _(b' (merge)')
7132 elif branch != parents[0].branch():
7152 elif branch != parents[0].branch():
7133 t += _(b' (new branch)')
7153 t += _(b' (new branch)')
7134 elif parents[0].closesbranch() and pnode in repo.branchheads(
7154 elif parents[0].closesbranch() and pnode in repo.branchheads(
7135 branch, closed=True
7155 branch, closed=True
7136 ):
7156 ):
7137 t += _(b' (head closed)')
7157 t += _(b' (head closed)')
7138 elif not (
7158 elif not (
7139 status.modified
7159 status.modified
7140 or status.added
7160 or status.added
7141 or status.removed
7161 or status.removed
7142 or renamed
7162 or renamed
7143 or copied
7163 or copied
7144 or subs
7164 or subs
7145 ):
7165 ):
7146 t += _(b' (clean)')
7166 t += _(b' (clean)')
7147 cleanworkdir = True
7167 cleanworkdir = True
7148 elif pnode not in bheads:
7168 elif pnode not in bheads:
7149 t += _(b' (new branch head)')
7169 t += _(b' (new branch head)')
7150
7170
7151 if parents:
7171 if parents:
7152 pendingphase = max(p.phase() for p in parents)
7172 pendingphase = max(p.phase() for p in parents)
7153 else:
7173 else:
7154 pendingphase = phases.public
7174 pendingphase = phases.public
7155
7175
7156 if pendingphase > phases.newcommitphase(ui):
7176 if pendingphase > phases.newcommitphase(ui):
7157 t += b' (%s)' % phases.phasenames[pendingphase]
7177 t += b' (%s)' % phases.phasenames[pendingphase]
7158
7178
7159 if cleanworkdir:
7179 if cleanworkdir:
7160 # i18n: column positioning for "hg summary"
7180 # i18n: column positioning for "hg summary"
7161 ui.status(_(b'commit: %s\n') % t.strip())
7181 ui.status(_(b'commit: %s\n') % t.strip())
7162 else:
7182 else:
7163 # i18n: column positioning for "hg summary"
7183 # i18n: column positioning for "hg summary"
7164 ui.write(_(b'commit: %s\n') % t.strip())
7184 ui.write(_(b'commit: %s\n') % t.strip())
7165
7185
7166 # all ancestors of branch heads - all ancestors of parent = new csets
7186 # all ancestors of branch heads - all ancestors of parent = new csets
7167 new = len(
7187 new = len(
7168 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7188 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7169 )
7189 )
7170
7190
7171 if new == 0:
7191 if new == 0:
7172 # i18n: column positioning for "hg summary"
7192 # i18n: column positioning for "hg summary"
7173 ui.status(_(b'update: (current)\n'))
7193 ui.status(_(b'update: (current)\n'))
7174 elif pnode not in bheads:
7194 elif pnode not in bheads:
7175 # i18n: column positioning for "hg summary"
7195 # i18n: column positioning for "hg summary"
7176 ui.write(_(b'update: %d new changesets (update)\n') % new)
7196 ui.write(_(b'update: %d new changesets (update)\n') % new)
7177 else:
7197 else:
7178 # i18n: column positioning for "hg summary"
7198 # i18n: column positioning for "hg summary"
7179 ui.write(
7199 ui.write(
7180 _(b'update: %d new changesets, %d branch heads (merge)\n')
7200 _(b'update: %d new changesets, %d branch heads (merge)\n')
7181 % (new, len(bheads))
7201 % (new, len(bheads))
7182 )
7202 )
7183
7203
7184 t = []
7204 t = []
7185 draft = len(repo.revs(b'draft()'))
7205 draft = len(repo.revs(b'draft()'))
7186 if draft:
7206 if draft:
7187 t.append(_(b'%d draft') % draft)
7207 t.append(_(b'%d draft') % draft)
7188 secret = len(repo.revs(b'secret()'))
7208 secret = len(repo.revs(b'secret()'))
7189 if secret:
7209 if secret:
7190 t.append(_(b'%d secret') % secret)
7210 t.append(_(b'%d secret') % secret)
7191
7211
7192 if draft or secret:
7212 if draft or secret:
7193 ui.status(_(b'phases: %s\n') % b', '.join(t))
7213 ui.status(_(b'phases: %s\n') % b', '.join(t))
7194
7214
7195 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7215 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7196 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7216 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7197 numtrouble = len(repo.revs(trouble + b"()"))
7217 numtrouble = len(repo.revs(trouble + b"()"))
7198 # We write all the possibilities to ease translation
7218 # We write all the possibilities to ease translation
7199 troublemsg = {
7219 troublemsg = {
7200 b"orphan": _(b"orphan: %d changesets"),
7220 b"orphan": _(b"orphan: %d changesets"),
7201 b"contentdivergent": _(b"content-divergent: %d changesets"),
7221 b"contentdivergent": _(b"content-divergent: %d changesets"),
7202 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7222 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7203 }
7223 }
7204 if numtrouble > 0:
7224 if numtrouble > 0:
7205 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7225 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7206
7226
7207 cmdutil.summaryhooks(ui, repo)
7227 cmdutil.summaryhooks(ui, repo)
7208
7228
7209 if opts.get(b'remote'):
7229 if opts.get(b'remote'):
7210 needsincoming, needsoutgoing = True, True
7230 needsincoming, needsoutgoing = True, True
7211 else:
7231 else:
7212 needsincoming, needsoutgoing = False, False
7232 needsincoming, needsoutgoing = False, False
7213 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7233 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7214 if i:
7234 if i:
7215 needsincoming = True
7235 needsincoming = True
7216 if o:
7236 if o:
7217 needsoutgoing = True
7237 needsoutgoing = True
7218 if not needsincoming and not needsoutgoing:
7238 if not needsincoming and not needsoutgoing:
7219 return
7239 return
7220
7240
7221 def getincoming():
7241 def getincoming():
7222 # XXX We should actually skip this if no default is specified, instead
7242 # XXX We should actually skip this if no default is specified, instead
7223 # of passing "default" which will resolve as "./default/" if no default
7243 # of passing "default" which will resolve as "./default/" if no default
7224 # path is defined.
7244 # path is defined.
7225 source, branches = urlutil.get_unique_pull_path(
7245 source, branches = urlutil.get_unique_pull_path(
7226 b'summary', repo, ui, b'default'
7246 b'summary', repo, ui, b'default'
7227 )
7247 )
7228 sbranch = branches[0]
7248 sbranch = branches[0]
7229 try:
7249 try:
7230 other = hg.peer(repo, {}, source)
7250 other = hg.peer(repo, {}, source)
7231 except error.RepoError:
7251 except error.RepoError:
7232 if opts.get(b'remote'):
7252 if opts.get(b'remote'):
7233 raise
7253 raise
7234 return source, sbranch, None, None, None
7254 return source, sbranch, None, None, None
7235 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7255 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7236 if revs:
7256 if revs:
7237 revs = [other.lookup(rev) for rev in revs]
7257 revs = [other.lookup(rev) for rev in revs]
7238 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(source))
7258 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(source))
7239 with repo.ui.silent():
7259 with repo.ui.silent():
7240 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7260 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7241 return source, sbranch, other, commoninc, commoninc[1]
7261 return source, sbranch, other, commoninc, commoninc[1]
7242
7262
7243 if needsincoming:
7263 if needsincoming:
7244 source, sbranch, sother, commoninc, incoming = getincoming()
7264 source, sbranch, sother, commoninc, incoming = getincoming()
7245 else:
7265 else:
7246 source = sbranch = sother = commoninc = incoming = None
7266 source = sbranch = sother = commoninc = incoming = None
7247
7267
7248 def getoutgoing():
7268 def getoutgoing():
7249 # XXX We should actually skip this if no default is specified, instead
7269 # XXX We should actually skip this if no default is specified, instead
7250 # of passing "default" which will resolve as "./default/" if no default
7270 # of passing "default" which will resolve as "./default/" if no default
7251 # path is defined.
7271 # path is defined.
7252 d = None
7272 d = None
7253 if b'default-push' in ui.paths:
7273 if b'default-push' in ui.paths:
7254 d = b'default-push'
7274 d = b'default-push'
7255 elif b'default' in ui.paths:
7275 elif b'default' in ui.paths:
7256 d = b'default'
7276 d = b'default'
7257 if d is not None:
7277 if d is not None:
7258 path = urlutil.get_unique_push_path(b'summary', repo, ui, d)
7278 path = urlutil.get_unique_push_path(b'summary', repo, ui, d)
7259 dest = path.pushloc or path.loc
7279 dest = path.pushloc or path.loc
7260 dbranch = path.branch
7280 dbranch = path.branch
7261 else:
7281 else:
7262 dest = b'default'
7282 dest = b'default'
7263 dbranch = None
7283 dbranch = None
7264 revs, checkout = hg.addbranchrevs(repo, repo, (dbranch, []), None)
7284 revs, checkout = hg.addbranchrevs(repo, repo, (dbranch, []), None)
7265 if source != dest:
7285 if source != dest:
7266 try:
7286 try:
7267 dother = hg.peer(repo, {}, dest)
7287 dother = hg.peer(repo, {}, dest)
7268 except error.RepoError:
7288 except error.RepoError:
7269 if opts.get(b'remote'):
7289 if opts.get(b'remote'):
7270 raise
7290 raise
7271 return dest, dbranch, None, None
7291 return dest, dbranch, None, None
7272 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(dest))
7292 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(dest))
7273 elif sother is None:
7293 elif sother is None:
7274 # there is no explicit destination peer, but source one is invalid
7294 # there is no explicit destination peer, but source one is invalid
7275 return dest, dbranch, None, None
7295 return dest, dbranch, None, None
7276 else:
7296 else:
7277 dother = sother
7297 dother = sother
7278 if source != dest or (sbranch is not None and sbranch != dbranch):
7298 if source != dest or (sbranch is not None and sbranch != dbranch):
7279 common = None
7299 common = None
7280 else:
7300 else:
7281 common = commoninc
7301 common = commoninc
7282 if revs:
7302 if revs:
7283 revs = [repo.lookup(rev) for rev in revs]
7303 revs = [repo.lookup(rev) for rev in revs]
7284 with repo.ui.silent():
7304 with repo.ui.silent():
7285 outgoing = discovery.findcommonoutgoing(
7305 outgoing = discovery.findcommonoutgoing(
7286 repo, dother, onlyheads=revs, commoninc=common
7306 repo, dother, onlyheads=revs, commoninc=common
7287 )
7307 )
7288 return dest, dbranch, dother, outgoing
7308 return dest, dbranch, dother, outgoing
7289
7309
7290 if needsoutgoing:
7310 if needsoutgoing:
7291 dest, dbranch, dother, outgoing = getoutgoing()
7311 dest, dbranch, dother, outgoing = getoutgoing()
7292 else:
7312 else:
7293 dest = dbranch = dother = outgoing = None
7313 dest = dbranch = dother = outgoing = None
7294
7314
7295 if opts.get(b'remote'):
7315 if opts.get(b'remote'):
7296 # Help pytype. --remote sets both `needsincoming` and `needsoutgoing`.
7316 # Help pytype. --remote sets both `needsincoming` and `needsoutgoing`.
7297 # The former always sets `sother` (or raises an exception if it can't);
7317 # The former always sets `sother` (or raises an exception if it can't);
7298 # the latter always sets `outgoing`.
7318 # the latter always sets `outgoing`.
7299 assert sother is not None
7319 assert sother is not None
7300 assert outgoing is not None
7320 assert outgoing is not None
7301
7321
7302 t = []
7322 t = []
7303 if incoming:
7323 if incoming:
7304 t.append(_(b'1 or more incoming'))
7324 t.append(_(b'1 or more incoming'))
7305 o = outgoing.missing
7325 o = outgoing.missing
7306 if o:
7326 if o:
7307 t.append(_(b'%d outgoing') % len(o))
7327 t.append(_(b'%d outgoing') % len(o))
7308 other = dother or sother
7328 other = dother or sother
7309 if b'bookmarks' in other.listkeys(b'namespaces'):
7329 if b'bookmarks' in other.listkeys(b'namespaces'):
7310 counts = bookmarks.summary(repo, other)
7330 counts = bookmarks.summary(repo, other)
7311 if counts[0] > 0:
7331 if counts[0] > 0:
7312 t.append(_(b'%d incoming bookmarks') % counts[0])
7332 t.append(_(b'%d incoming bookmarks') % counts[0])
7313 if counts[1] > 0:
7333 if counts[1] > 0:
7314 t.append(_(b'%d outgoing bookmarks') % counts[1])
7334 t.append(_(b'%d outgoing bookmarks') % counts[1])
7315
7335
7316 if t:
7336 if t:
7317 # i18n: column positioning for "hg summary"
7337 # i18n: column positioning for "hg summary"
7318 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7338 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7319 else:
7339 else:
7320 # i18n: column positioning for "hg summary"
7340 # i18n: column positioning for "hg summary"
7321 ui.status(_(b'remote: (synced)\n'))
7341 ui.status(_(b'remote: (synced)\n'))
7322
7342
7323 cmdutil.summaryremotehooks(
7343 cmdutil.summaryremotehooks(
7324 ui,
7344 ui,
7325 repo,
7345 repo,
7326 opts,
7346 opts,
7327 (
7347 (
7328 (source, sbranch, sother, commoninc),
7348 (source, sbranch, sother, commoninc),
7329 (dest, dbranch, dother, outgoing),
7349 (dest, dbranch, dother, outgoing),
7330 ),
7350 ),
7331 )
7351 )
7332
7352
7333
7353
7334 @command(
7354 @command(
7335 b'tag',
7355 b'tag',
7336 [
7356 [
7337 (b'f', b'force', None, _(b'force tag')),
7357 (b'f', b'force', None, _(b'force tag')),
7338 (b'l', b'local', None, _(b'make the tag local')),
7358 (b'l', b'local', None, _(b'make the tag local')),
7339 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7359 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7340 (b'', b'remove', None, _(b'remove a tag')),
7360 (b'', b'remove', None, _(b'remove a tag')),
7341 # -l/--local is already there, commitopts cannot be used
7361 # -l/--local is already there, commitopts cannot be used
7342 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7362 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7343 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7363 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7344 ]
7364 ]
7345 + commitopts2,
7365 + commitopts2,
7346 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7366 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7347 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7367 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7348 )
7368 )
7349 def tag(ui, repo, name1, *names, **opts):
7369 def tag(ui, repo, name1, *names, **opts):
7350 """add one or more tags for the current or given revision
7370 """add one or more tags for the current or given revision
7351
7371
7352 Name a particular revision using <name>.
7372 Name a particular revision using <name>.
7353
7373
7354 Tags are used to name particular revisions of the repository and are
7374 Tags are used to name particular revisions of the repository and are
7355 very useful to compare different revisions, to go back to significant
7375 very useful to compare different revisions, to go back to significant
7356 earlier versions or to mark branch points as releases, etc. Changing
7376 earlier versions or to mark branch points as releases, etc. Changing
7357 an existing tag is normally disallowed; use -f/--force to override.
7377 an existing tag is normally disallowed; use -f/--force to override.
7358
7378
7359 If no revision is given, the parent of the working directory is
7379 If no revision is given, the parent of the working directory is
7360 used.
7380 used.
7361
7381
7362 To facilitate version control, distribution, and merging of tags,
7382 To facilitate version control, distribution, and merging of tags,
7363 they are stored as a file named ".hgtags" which is managed similarly
7383 they are stored as a file named ".hgtags" which is managed similarly
7364 to other project files and can be hand-edited if necessary. This
7384 to other project files and can be hand-edited if necessary. This
7365 also means that tagging creates a new commit. The file
7385 also means that tagging creates a new commit. The file
7366 ".hg/localtags" is used for local tags (not shared among
7386 ".hg/localtags" is used for local tags (not shared among
7367 repositories).
7387 repositories).
7368
7388
7369 Tag commits are usually made at the head of a branch. If the parent
7389 Tag commits are usually made at the head of a branch. If the parent
7370 of the working directory is not a branch head, :hg:`tag` aborts; use
7390 of the working directory is not a branch head, :hg:`tag` aborts; use
7371 -f/--force to force the tag commit to be based on a non-head
7391 -f/--force to force the tag commit to be based on a non-head
7372 changeset.
7392 changeset.
7373
7393
7374 See :hg:`help dates` for a list of formats valid for -d/--date.
7394 See :hg:`help dates` for a list of formats valid for -d/--date.
7375
7395
7376 Since tag names have priority over branch names during revision
7396 Since tag names have priority over branch names during revision
7377 lookup, using an existing branch name as a tag name is discouraged.
7397 lookup, using an existing branch name as a tag name is discouraged.
7378
7398
7379 Returns 0 on success.
7399 Returns 0 on success.
7380 """
7400 """
7381 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7401 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7382 opts = pycompat.byteskwargs(opts)
7402 opts = pycompat.byteskwargs(opts)
7383 with repo.wlock(), repo.lock():
7403 with repo.wlock(), repo.lock():
7384 rev_ = b"."
7404 rev_ = b"."
7385 names = [t.strip() for t in (name1,) + names]
7405 names = [t.strip() for t in (name1,) + names]
7386 if len(names) != len(set(names)):
7406 if len(names) != len(set(names)):
7387 raise error.InputError(_(b'tag names must be unique'))
7407 raise error.InputError(_(b'tag names must be unique'))
7388 for n in names:
7408 for n in names:
7389 scmutil.checknewlabel(repo, n, b'tag')
7409 scmutil.checknewlabel(repo, n, b'tag')
7390 if not n:
7410 if not n:
7391 raise error.InputError(
7411 raise error.InputError(
7392 _(b'tag names cannot consist entirely of whitespace')
7412 _(b'tag names cannot consist entirely of whitespace')
7393 )
7413 )
7394 if opts.get(b'rev'):
7414 if opts.get(b'rev'):
7395 rev_ = opts[b'rev']
7415 rev_ = opts[b'rev']
7396 message = opts.get(b'message')
7416 message = opts.get(b'message')
7397 if opts.get(b'remove'):
7417 if opts.get(b'remove'):
7398 if opts.get(b'local'):
7418 if opts.get(b'local'):
7399 expectedtype = b'local'
7419 expectedtype = b'local'
7400 else:
7420 else:
7401 expectedtype = b'global'
7421 expectedtype = b'global'
7402
7422
7403 for n in names:
7423 for n in names:
7404 if repo.tagtype(n) == b'global':
7424 if repo.tagtype(n) == b'global':
7405 alltags = tagsmod.findglobaltags(ui, repo)
7425 alltags = tagsmod.findglobaltags(ui, repo)
7406 if alltags[n][0] == repo.nullid:
7426 if alltags[n][0] == repo.nullid:
7407 raise error.InputError(
7427 raise error.InputError(
7408 _(b"tag '%s' is already removed") % n
7428 _(b"tag '%s' is already removed") % n
7409 )
7429 )
7410 if not repo.tagtype(n):
7430 if not repo.tagtype(n):
7411 raise error.InputError(_(b"tag '%s' does not exist") % n)
7431 raise error.InputError(_(b"tag '%s' does not exist") % n)
7412 if repo.tagtype(n) != expectedtype:
7432 if repo.tagtype(n) != expectedtype:
7413 if expectedtype == b'global':
7433 if expectedtype == b'global':
7414 raise error.InputError(
7434 raise error.InputError(
7415 _(b"tag '%s' is not a global tag") % n
7435 _(b"tag '%s' is not a global tag") % n
7416 )
7436 )
7417 else:
7437 else:
7418 raise error.InputError(
7438 raise error.InputError(
7419 _(b"tag '%s' is not a local tag") % n
7439 _(b"tag '%s' is not a local tag") % n
7420 )
7440 )
7421 rev_ = b'null'
7441 rev_ = b'null'
7422 if not message:
7442 if not message:
7423 # we don't translate commit messages
7443 # we don't translate commit messages
7424 message = b'Removed tag %s' % b', '.join(names)
7444 message = b'Removed tag %s' % b', '.join(names)
7425 elif not opts.get(b'force'):
7445 elif not opts.get(b'force'):
7426 for n in names:
7446 for n in names:
7427 if n in repo.tags():
7447 if n in repo.tags():
7428 raise error.InputError(
7448 raise error.InputError(
7429 _(b"tag '%s' already exists (use -f to force)") % n
7449 _(b"tag '%s' already exists (use -f to force)") % n
7430 )
7450 )
7431 if not opts.get(b'local'):
7451 if not opts.get(b'local'):
7432 p1, p2 = repo.dirstate.parents()
7452 p1, p2 = repo.dirstate.parents()
7433 if p2 != repo.nullid:
7453 if p2 != repo.nullid:
7434 raise error.StateError(_(b'uncommitted merge'))
7454 raise error.StateError(_(b'uncommitted merge'))
7435 bheads = repo.branchheads()
7455 bheads = repo.branchheads()
7436 if not opts.get(b'force') and bheads and p1 not in bheads:
7456 if not opts.get(b'force') and bheads and p1 not in bheads:
7437 raise error.InputError(
7457 raise error.InputError(
7438 _(
7458 _(
7439 b'working directory is not at a branch head '
7459 b'working directory is not at a branch head '
7440 b'(use -f to force)'
7460 b'(use -f to force)'
7441 )
7461 )
7442 )
7462 )
7443 node = logcmdutil.revsingle(repo, rev_).node()
7463 node = logcmdutil.revsingle(repo, rev_).node()
7444
7464
7445 if not message:
7465 if not message:
7446 # we don't translate commit messages
7466 # we don't translate commit messages
7447 message = b'Added tag %s for changeset %s' % (
7467 message = b'Added tag %s for changeset %s' % (
7448 b', '.join(names),
7468 b', '.join(names),
7449 short(node),
7469 short(node),
7450 )
7470 )
7451
7471
7452 date = opts.get(b'date')
7472 date = opts.get(b'date')
7453 if date:
7473 if date:
7454 date = dateutil.parsedate(date)
7474 date = dateutil.parsedate(date)
7455
7475
7456 if opts.get(b'remove'):
7476 if opts.get(b'remove'):
7457 editform = b'tag.remove'
7477 editform = b'tag.remove'
7458 else:
7478 else:
7459 editform = b'tag.add'
7479 editform = b'tag.add'
7460 editor = cmdutil.getcommiteditor(
7480 editor = cmdutil.getcommiteditor(
7461 editform=editform, **pycompat.strkwargs(opts)
7481 editform=editform, **pycompat.strkwargs(opts)
7462 )
7482 )
7463
7483
7464 # don't allow tagging the null rev
7484 # don't allow tagging the null rev
7465 if (
7485 if (
7466 not opts.get(b'remove')
7486 not opts.get(b'remove')
7467 and logcmdutil.revsingle(repo, rev_).rev() == nullrev
7487 and logcmdutil.revsingle(repo, rev_).rev() == nullrev
7468 ):
7488 ):
7469 raise error.InputError(_(b"cannot tag null revision"))
7489 raise error.InputError(_(b"cannot tag null revision"))
7470
7490
7471 tagsmod.tag(
7491 tagsmod.tag(
7472 repo,
7492 repo,
7473 names,
7493 names,
7474 node,
7494 node,
7475 message,
7495 message,
7476 opts.get(b'local'),
7496 opts.get(b'local'),
7477 opts.get(b'user'),
7497 opts.get(b'user'),
7478 date,
7498 date,
7479 editor=editor,
7499 editor=editor,
7480 )
7500 )
7481
7501
7482
7502
7483 @command(
7503 @command(
7484 b'tags',
7504 b'tags',
7485 formatteropts,
7505 formatteropts,
7486 b'',
7506 b'',
7487 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7507 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7488 intents={INTENT_READONLY},
7508 intents={INTENT_READONLY},
7489 )
7509 )
7490 def tags(ui, repo, **opts):
7510 def tags(ui, repo, **opts):
7491 """list repository tags
7511 """list repository tags
7492
7512
7493 This lists both regular and local tags. When the -v/--verbose
7513 This lists both regular and local tags. When the -v/--verbose
7494 switch is used, a third column "local" is printed for local tags.
7514 switch is used, a third column "local" is printed for local tags.
7495 When the -q/--quiet switch is used, only the tag name is printed.
7515 When the -q/--quiet switch is used, only the tag name is printed.
7496
7516
7497 .. container:: verbose
7517 .. container:: verbose
7498
7518
7499 Template:
7519 Template:
7500
7520
7501 The following keywords are supported in addition to the common template
7521 The following keywords are supported in addition to the common template
7502 keywords and functions such as ``{tag}``. See also
7522 keywords and functions such as ``{tag}``. See also
7503 :hg:`help templates`.
7523 :hg:`help templates`.
7504
7524
7505 :type: String. ``local`` for local tags.
7525 :type: String. ``local`` for local tags.
7506
7526
7507 Returns 0 on success.
7527 Returns 0 on success.
7508 """
7528 """
7509
7529
7510 opts = pycompat.byteskwargs(opts)
7530 opts = pycompat.byteskwargs(opts)
7511 ui.pager(b'tags')
7531 ui.pager(b'tags')
7512 fm = ui.formatter(b'tags', opts)
7532 fm = ui.formatter(b'tags', opts)
7513 hexfunc = fm.hexfunc
7533 hexfunc = fm.hexfunc
7514
7534
7515 for t, n in reversed(repo.tagslist()):
7535 for t, n in reversed(repo.tagslist()):
7516 hn = hexfunc(n)
7536 hn = hexfunc(n)
7517 label = b'tags.normal'
7537 label = b'tags.normal'
7518 tagtype = repo.tagtype(t)
7538 tagtype = repo.tagtype(t)
7519 if not tagtype or tagtype == b'global':
7539 if not tagtype or tagtype == b'global':
7520 tagtype = b''
7540 tagtype = b''
7521 else:
7541 else:
7522 label = b'tags.' + tagtype
7542 label = b'tags.' + tagtype
7523
7543
7524 fm.startitem()
7544 fm.startitem()
7525 fm.context(repo=repo)
7545 fm.context(repo=repo)
7526 fm.write(b'tag', b'%s', t, label=label)
7546 fm.write(b'tag', b'%s', t, label=label)
7527 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7547 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7528 fm.condwrite(
7548 fm.condwrite(
7529 not ui.quiet,
7549 not ui.quiet,
7530 b'rev node',
7550 b'rev node',
7531 fmt,
7551 fmt,
7532 repo.changelog.rev(n),
7552 repo.changelog.rev(n),
7533 hn,
7553 hn,
7534 label=label,
7554 label=label,
7535 )
7555 )
7536 fm.condwrite(
7556 fm.condwrite(
7537 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7557 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7538 )
7558 )
7539 fm.plain(b'\n')
7559 fm.plain(b'\n')
7540 fm.end()
7560 fm.end()
7541
7561
7542
7562
7543 @command(
7563 @command(
7544 b'tip',
7564 b'tip',
7545 [
7565 [
7546 (b'p', b'patch', None, _(b'show patch')),
7566 (b'p', b'patch', None, _(b'show patch')),
7547 (b'g', b'git', None, _(b'use git extended diff format')),
7567 (b'g', b'git', None, _(b'use git extended diff format')),
7548 ]
7568 ]
7549 + templateopts,
7569 + templateopts,
7550 _(b'[-p] [-g]'),
7570 _(b'[-p] [-g]'),
7551 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7571 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7552 )
7572 )
7553 def tip(ui, repo, **opts):
7573 def tip(ui, repo, **opts):
7554 """show the tip revision (DEPRECATED)
7574 """show the tip revision (DEPRECATED)
7555
7575
7556 The tip revision (usually just called the tip) is the changeset
7576 The tip revision (usually just called the tip) is the changeset
7557 most recently added to the repository (and therefore the most
7577 most recently added to the repository (and therefore the most
7558 recently changed head).
7578 recently changed head).
7559
7579
7560 If you have just made a commit, that commit will be the tip. If
7580 If you have just made a commit, that commit will be the tip. If
7561 you have just pulled changes from another repository, the tip of
7581 you have just pulled changes from another repository, the tip of
7562 that repository becomes the current tip. The "tip" tag is special
7582 that repository becomes the current tip. The "tip" tag is special
7563 and cannot be renamed or assigned to a different changeset.
7583 and cannot be renamed or assigned to a different changeset.
7564
7584
7565 This command is deprecated, please use :hg:`heads` instead.
7585 This command is deprecated, please use :hg:`heads` instead.
7566
7586
7567 Returns 0 on success.
7587 Returns 0 on success.
7568 """
7588 """
7569 opts = pycompat.byteskwargs(opts)
7589 opts = pycompat.byteskwargs(opts)
7570 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7590 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7571 displayer.show(repo[b'tip'])
7591 displayer.show(repo[b'tip'])
7572 displayer.close()
7592 displayer.close()
7573
7593
7574
7594
7575 @command(
7595 @command(
7576 b'unbundle',
7596 b'unbundle',
7577 [
7597 [
7578 (
7598 (
7579 b'u',
7599 b'u',
7580 b'update',
7600 b'update',
7581 None,
7601 None,
7582 _(b'update to new branch head if changesets were unbundled'),
7602 _(b'update to new branch head if changesets were unbundled'),
7583 )
7603 )
7584 ],
7604 ],
7585 _(b'[-u] FILE...'),
7605 _(b'[-u] FILE...'),
7586 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7606 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7587 )
7607 )
7588 def unbundle(ui, repo, fname1, *fnames, **opts):
7608 def unbundle(ui, repo, fname1, *fnames, **opts):
7589 """apply one or more bundle files
7609 """apply one or more bundle files
7590
7610
7591 Apply one or more bundle files generated by :hg:`bundle`.
7611 Apply one or more bundle files generated by :hg:`bundle`.
7592
7612
7593 Returns 0 on success, 1 if an update has unresolved files.
7613 Returns 0 on success, 1 if an update has unresolved files.
7594 """
7614 """
7595 fnames = (fname1,) + fnames
7615 fnames = (fname1,) + fnames
7596
7616
7597 with repo.lock():
7617 with repo.lock():
7598 for fname in fnames:
7618 for fname in fnames:
7599 f = hg.openpath(ui, fname)
7619 f = hg.openpath(ui, fname)
7600 gen = exchange.readbundle(ui, f, fname)
7620 gen = exchange.readbundle(ui, f, fname)
7601 if isinstance(gen, streamclone.streamcloneapplier):
7621 if isinstance(gen, streamclone.streamcloneapplier):
7602 raise error.InputError(
7622 raise error.InputError(
7603 _(
7623 _(
7604 b'packed bundles cannot be applied with '
7624 b'packed bundles cannot be applied with '
7605 b'"hg unbundle"'
7625 b'"hg unbundle"'
7606 ),
7626 ),
7607 hint=_(b'use "hg debugapplystreamclonebundle"'),
7627 hint=_(b'use "hg debugapplystreamclonebundle"'),
7608 )
7628 )
7609 url = b'bundle:' + fname
7629 url = b'bundle:' + fname
7610 try:
7630 try:
7611 txnname = b'unbundle'
7631 txnname = b'unbundle'
7612 if not isinstance(gen, bundle2.unbundle20):
7632 if not isinstance(gen, bundle2.unbundle20):
7613 txnname = b'unbundle\n%s' % urlutil.hidepassword(url)
7633 txnname = b'unbundle\n%s' % urlutil.hidepassword(url)
7614 with repo.transaction(txnname) as tr:
7634 with repo.transaction(txnname) as tr:
7615 op = bundle2.applybundle(
7635 op = bundle2.applybundle(
7616 repo, gen, tr, source=b'unbundle', url=url
7636 repo, gen, tr, source=b'unbundle', url=url
7617 )
7637 )
7618 except error.BundleUnknownFeatureError as exc:
7638 except error.BundleUnknownFeatureError as exc:
7619 raise error.Abort(
7639 raise error.Abort(
7620 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7640 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7621 hint=_(
7641 hint=_(
7622 b"see https://mercurial-scm.org/"
7642 b"see https://mercurial-scm.org/"
7623 b"wiki/BundleFeature for more "
7643 b"wiki/BundleFeature for more "
7624 b"information"
7644 b"information"
7625 ),
7645 ),
7626 )
7646 )
7627 modheads = bundle2.combinechangegroupresults(op)
7647 modheads = bundle2.combinechangegroupresults(op)
7628
7648
7629 if postincoming(ui, repo, modheads, opts.get('update'), None, None):
7649 if postincoming(ui, repo, modheads, opts.get('update'), None, None):
7630 return 1
7650 return 1
7631 else:
7651 else:
7632 return 0
7652 return 0
7633
7653
7634
7654
7635 @command(
7655 @command(
7636 b'unshelve',
7656 b'unshelve',
7637 [
7657 [
7638 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7658 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7639 (
7659 (
7640 b'c',
7660 b'c',
7641 b'continue',
7661 b'continue',
7642 None,
7662 None,
7643 _(b'continue an incomplete unshelve operation'),
7663 _(b'continue an incomplete unshelve operation'),
7644 ),
7664 ),
7645 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7665 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7646 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7666 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7647 (
7667 (
7648 b'n',
7668 b'n',
7649 b'name',
7669 b'name',
7650 b'',
7670 b'',
7651 _(b'restore shelved change with given name'),
7671 _(b'restore shelved change with given name'),
7652 _(b'NAME'),
7672 _(b'NAME'),
7653 ),
7673 ),
7654 (b't', b'tool', b'', _(b'specify merge tool')),
7674 (b't', b'tool', b'', _(b'specify merge tool')),
7655 (
7675 (
7656 b'',
7676 b'',
7657 b'date',
7677 b'date',
7658 b'',
7678 b'',
7659 _(b'set date for temporary commits (DEPRECATED)'),
7679 _(b'set date for temporary commits (DEPRECATED)'),
7660 _(b'DATE'),
7680 _(b'DATE'),
7661 ),
7681 ),
7662 ],
7682 ],
7663 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7683 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7664 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7684 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7665 )
7685 )
7666 def unshelve(ui, repo, *shelved, **opts):
7686 def unshelve(ui, repo, *shelved, **opts):
7667 """restore a shelved change to the working directory
7687 """restore a shelved change to the working directory
7668
7688
7669 This command accepts an optional name of a shelved change to
7689 This command accepts an optional name of a shelved change to
7670 restore. If none is given, the most recent shelved change is used.
7690 restore. If none is given, the most recent shelved change is used.
7671
7691
7672 If a shelved change is applied successfully, the bundle that
7692 If a shelved change is applied successfully, the bundle that
7673 contains the shelved changes is moved to a backup location
7693 contains the shelved changes is moved to a backup location
7674 (.hg/shelve-backup).
7694 (.hg/shelve-backup).
7675
7695
7676 Since you can restore a shelved change on top of an arbitrary
7696 Since you can restore a shelved change on top of an arbitrary
7677 commit, it is possible that unshelving will result in a conflict
7697 commit, it is possible that unshelving will result in a conflict
7678 between your changes and the commits you are unshelving onto. If
7698 between your changes and the commits you are unshelving onto. If
7679 this occurs, you must resolve the conflict, then use
7699 this occurs, you must resolve the conflict, then use
7680 ``--continue`` to complete the unshelve operation. (The bundle
7700 ``--continue`` to complete the unshelve operation. (The bundle
7681 will not be moved until you successfully complete the unshelve.)
7701 will not be moved until you successfully complete the unshelve.)
7682
7702
7683 (Alternatively, you can use ``--abort`` to abandon an unshelve
7703 (Alternatively, you can use ``--abort`` to abandon an unshelve
7684 that causes a conflict. This reverts the unshelved changes, and
7704 that causes a conflict. This reverts the unshelved changes, and
7685 leaves the bundle in place.)
7705 leaves the bundle in place.)
7686
7706
7687 If bare shelved change (without interactive, include and exclude
7707 If bare shelved change (without interactive, include and exclude
7688 option) was done on newly created branch it would restore branch
7708 option) was done on newly created branch it would restore branch
7689 information to the working directory.
7709 information to the working directory.
7690
7710
7691 After a successful unshelve, the shelved changes are stored in a
7711 After a successful unshelve, the shelved changes are stored in a
7692 backup directory. Only the N most recent backups are kept. N
7712 backup directory. Only the N most recent backups are kept. N
7693 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7713 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7694 configuration option.
7714 configuration option.
7695
7715
7696 .. container:: verbose
7716 .. container:: verbose
7697
7717
7698 Timestamp in seconds is used to decide order of backups. More
7718 Timestamp in seconds is used to decide order of backups. More
7699 than ``maxbackups`` backups are kept, if same timestamp
7719 than ``maxbackups`` backups are kept, if same timestamp
7700 prevents from deciding exact order of them, for safety.
7720 prevents from deciding exact order of them, for safety.
7701
7721
7702 Selected changes can be unshelved with ``--interactive`` flag.
7722 Selected changes can be unshelved with ``--interactive`` flag.
7703 The working directory is updated with the selected changes, and
7723 The working directory is updated with the selected changes, and
7704 only the unselected changes remain shelved.
7724 only the unselected changes remain shelved.
7705 Note: The whole shelve is applied to working directory first before
7725 Note: The whole shelve is applied to working directory first before
7706 running interactively. So, this will bring up all the conflicts between
7726 running interactively. So, this will bring up all the conflicts between
7707 working directory and the shelve, irrespective of which changes will be
7727 working directory and the shelve, irrespective of which changes will be
7708 unshelved.
7728 unshelved.
7709 """
7729 """
7710 with repo.wlock():
7730 with repo.wlock():
7711 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7731 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7712
7732
7713
7733
7714 statemod.addunfinished(
7734 statemod.addunfinished(
7715 b'unshelve',
7735 b'unshelve',
7716 fname=b'shelvedstate',
7736 fname=b'shelvedstate',
7717 continueflag=True,
7737 continueflag=True,
7718 abortfunc=shelvemod.hgabortunshelve,
7738 abortfunc=shelvemod.hgabortunshelve,
7719 continuefunc=shelvemod.hgcontinueunshelve,
7739 continuefunc=shelvemod.hgcontinueunshelve,
7720 cmdmsg=_(b'unshelve already in progress'),
7740 cmdmsg=_(b'unshelve already in progress'),
7721 )
7741 )
7722
7742
7723
7743
7724 @command(
7744 @command(
7725 b'update|up|checkout|co',
7745 b'update|up|checkout|co',
7726 [
7746 [
7727 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7747 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7728 (b'c', b'check', None, _(b'require clean working directory')),
7748 (b'c', b'check', None, _(b'require clean working directory')),
7729 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7749 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7730 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7750 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7731 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7751 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7732 ]
7752 ]
7733 + mergetoolopts,
7753 + mergetoolopts,
7734 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7754 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7735 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7755 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7736 helpbasic=True,
7756 helpbasic=True,
7737 )
7757 )
7738 def update(ui, repo, node=None, **opts):
7758 def update(ui, repo, node=None, **opts):
7739 """update working directory (or switch revisions)
7759 """update working directory (or switch revisions)
7740
7760
7741 Update the repository's working directory to the specified
7761 Update the repository's working directory to the specified
7742 changeset. If no changeset is specified, update to the tip of the
7762 changeset. If no changeset is specified, update to the tip of the
7743 current named branch and move the active bookmark (see :hg:`help
7763 current named branch and move the active bookmark (see :hg:`help
7744 bookmarks`).
7764 bookmarks`).
7745
7765
7746 Update sets the working directory's parent revision to the specified
7766 Update sets the working directory's parent revision to the specified
7747 changeset (see :hg:`help parents`).
7767 changeset (see :hg:`help parents`).
7748
7768
7749 If the changeset is not a descendant or ancestor of the working
7769 If the changeset is not a descendant or ancestor of the working
7750 directory's parent and there are uncommitted changes, the update is
7770 directory's parent and there are uncommitted changes, the update is
7751 aborted. With the -c/--check option, the working directory is checked
7771 aborted. With the -c/--check option, the working directory is checked
7752 for uncommitted changes; if none are found, the working directory is
7772 for uncommitted changes; if none are found, the working directory is
7753 updated to the specified changeset.
7773 updated to the specified changeset.
7754
7774
7755 .. container:: verbose
7775 .. container:: verbose
7756
7776
7757 The -C/--clean, -c/--check, and -m/--merge options control what
7777 The -C/--clean, -c/--check, and -m/--merge options control what
7758 happens if the working directory contains uncommitted changes.
7778 happens if the working directory contains uncommitted changes.
7759 At most of one of them can be specified.
7779 At most of one of them can be specified.
7760
7780
7761 1. If no option is specified, and if
7781 1. If no option is specified, and if
7762 the requested changeset is an ancestor or descendant of
7782 the requested changeset is an ancestor or descendant of
7763 the working directory's parent, the uncommitted changes
7783 the working directory's parent, the uncommitted changes
7764 are merged into the requested changeset and the merged
7784 are merged into the requested changeset and the merged
7765 result is left uncommitted. If the requested changeset is
7785 result is left uncommitted. If the requested changeset is
7766 not an ancestor or descendant (that is, it is on another
7786 not an ancestor or descendant (that is, it is on another
7767 branch), the update is aborted and the uncommitted changes
7787 branch), the update is aborted and the uncommitted changes
7768 are preserved.
7788 are preserved.
7769
7789
7770 2. With the -m/--merge option, the update is allowed even if the
7790 2. With the -m/--merge option, the update is allowed even if the
7771 requested changeset is not an ancestor or descendant of
7791 requested changeset is not an ancestor or descendant of
7772 the working directory's parent.
7792 the working directory's parent.
7773
7793
7774 3. With the -c/--check option, the update is aborted and the
7794 3. With the -c/--check option, the update is aborted and the
7775 uncommitted changes are preserved.
7795 uncommitted changes are preserved.
7776
7796
7777 4. With the -C/--clean option, uncommitted changes are discarded and
7797 4. With the -C/--clean option, uncommitted changes are discarded and
7778 the working directory is updated to the requested changeset.
7798 the working directory is updated to the requested changeset.
7779
7799
7780 To cancel an uncommitted merge (and lose your changes), use
7800 To cancel an uncommitted merge (and lose your changes), use
7781 :hg:`merge --abort`.
7801 :hg:`merge --abort`.
7782
7802
7783 Use null as the changeset to remove the working directory (like
7803 Use null as the changeset to remove the working directory (like
7784 :hg:`clone -U`).
7804 :hg:`clone -U`).
7785
7805
7786 If you want to revert just one file to an older revision, use
7806 If you want to revert just one file to an older revision, use
7787 :hg:`revert [-r REV] NAME`.
7807 :hg:`revert [-r REV] NAME`.
7788
7808
7789 See :hg:`help dates` for a list of formats valid for -d/--date.
7809 See :hg:`help dates` for a list of formats valid for -d/--date.
7790
7810
7791 Returns 0 on success, 1 if there are unresolved files.
7811 Returns 0 on success, 1 if there are unresolved files.
7792 """
7812 """
7793 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7813 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7794 rev = opts.get('rev')
7814 rev = opts.get('rev')
7795 date = opts.get('date')
7815 date = opts.get('date')
7796 clean = opts.get('clean')
7816 clean = opts.get('clean')
7797 check = opts.get('check')
7817 check = opts.get('check')
7798 merge = opts.get('merge')
7818 merge = opts.get('merge')
7799 if rev and node:
7819 if rev and node:
7800 raise error.InputError(_(b"please specify just one revision"))
7820 raise error.InputError(_(b"please specify just one revision"))
7801
7821
7802 if ui.configbool(b'commands', b'update.requiredest'):
7822 if ui.configbool(b'commands', b'update.requiredest'):
7803 if not node and not rev and not date:
7823 if not node and not rev and not date:
7804 raise error.InputError(
7824 raise error.InputError(
7805 _(b'you must specify a destination'),
7825 _(b'you must specify a destination'),
7806 hint=_(b'for example: hg update ".::"'),
7826 hint=_(b'for example: hg update ".::"'),
7807 )
7827 )
7808
7828
7809 if rev is None or rev == b'':
7829 if rev is None or rev == b'':
7810 rev = node
7830 rev = node
7811
7831
7812 if date and rev is not None:
7832 if date and rev is not None:
7813 raise error.InputError(_(b"you can't specify a revision and a date"))
7833 raise error.InputError(_(b"you can't specify a revision and a date"))
7814
7834
7815 updatecheck = None
7835 updatecheck = None
7816 if check or merge is not None and not merge:
7836 if check or merge is not None and not merge:
7817 updatecheck = b'abort'
7837 updatecheck = b'abort'
7818 elif merge or check is not None and not check:
7838 elif merge or check is not None and not check:
7819 updatecheck = b'none'
7839 updatecheck = b'none'
7820
7840
7821 with repo.wlock():
7841 with repo.wlock():
7822 cmdutil.clearunfinished(repo)
7842 cmdutil.clearunfinished(repo)
7823 if date:
7843 if date:
7824 rev = cmdutil.finddate(ui, repo, date)
7844 rev = cmdutil.finddate(ui, repo, date)
7825
7845
7826 # if we defined a bookmark, we have to remember the original name
7846 # if we defined a bookmark, we have to remember the original name
7827 brev = rev
7847 brev = rev
7828 if rev:
7848 if rev:
7829 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7849 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7830 ctx = logcmdutil.revsingle(repo, rev, default=None)
7850 ctx = logcmdutil.revsingle(repo, rev, default=None)
7831 rev = ctx.rev()
7851 rev = ctx.rev()
7832 hidden = ctx.hidden()
7852 hidden = ctx.hidden()
7833 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7853 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7834 with ui.configoverride(overrides, b'update'):
7854 with ui.configoverride(overrides, b'update'):
7835 ret = hg.updatetotally(
7855 ret = hg.updatetotally(
7836 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7856 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7837 )
7857 )
7838 if hidden:
7858 if hidden:
7839 ctxstr = ctx.hex()[:12]
7859 ctxstr = ctx.hex()[:12]
7840 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7860 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7841
7861
7842 if ctx.obsolete():
7862 if ctx.obsolete():
7843 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7863 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7844 ui.warn(b"(%s)\n" % obsfatemsg)
7864 ui.warn(b"(%s)\n" % obsfatemsg)
7845 return ret
7865 return ret
7846
7866
7847
7867
7848 @command(
7868 @command(
7849 b'verify',
7869 b'verify',
7850 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7870 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7851 helpcategory=command.CATEGORY_MAINTENANCE,
7871 helpcategory=command.CATEGORY_MAINTENANCE,
7852 )
7872 )
7853 def verify(ui, repo, **opts):
7873 def verify(ui, repo, **opts):
7854 """verify the integrity of the repository
7874 """verify the integrity of the repository
7855
7875
7856 Verify the integrity of the current repository.
7876 Verify the integrity of the current repository.
7857
7877
7858 This will perform an extensive check of the repository's
7878 This will perform an extensive check of the repository's
7859 integrity, validating the hashes and checksums of each entry in
7879 integrity, validating the hashes and checksums of each entry in
7860 the changelog, manifest, and tracked files, as well as the
7880 the changelog, manifest, and tracked files, as well as the
7861 integrity of their crosslinks and indices.
7881 integrity of their crosslinks and indices.
7862
7882
7863 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7883 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7864 for more information about recovery from corruption of the
7884 for more information about recovery from corruption of the
7865 repository.
7885 repository.
7866
7886
7867 Returns 0 on success, 1 if errors are encountered.
7887 Returns 0 on success, 1 if errors are encountered.
7868 """
7888 """
7869 opts = pycompat.byteskwargs(opts)
7889 opts = pycompat.byteskwargs(opts)
7870
7890
7871 level = None
7891 level = None
7872 if opts[b'full']:
7892 if opts[b'full']:
7873 level = verifymod.VERIFY_FULL
7893 level = verifymod.VERIFY_FULL
7874 return hg.verify(repo, level)
7894 return hg.verify(repo, level)
7875
7895
7876
7896
7877 @command(
7897 @command(
7878 b'version',
7898 b'version',
7879 [] + formatteropts,
7899 [] + formatteropts,
7880 helpcategory=command.CATEGORY_HELP,
7900 helpcategory=command.CATEGORY_HELP,
7881 norepo=True,
7901 norepo=True,
7882 intents={INTENT_READONLY},
7902 intents={INTENT_READONLY},
7883 )
7903 )
7884 def version_(ui, **opts):
7904 def version_(ui, **opts):
7885 """output version and copyright information
7905 """output version and copyright information
7886
7906
7887 .. container:: verbose
7907 .. container:: verbose
7888
7908
7889 Template:
7909 Template:
7890
7910
7891 The following keywords are supported. See also :hg:`help templates`.
7911 The following keywords are supported. See also :hg:`help templates`.
7892
7912
7893 :extensions: List of extensions.
7913 :extensions: List of extensions.
7894 :ver: String. Version number.
7914 :ver: String. Version number.
7895
7915
7896 And each entry of ``{extensions}`` provides the following sub-keywords
7916 And each entry of ``{extensions}`` provides the following sub-keywords
7897 in addition to ``{ver}``.
7917 in addition to ``{ver}``.
7898
7918
7899 :bundled: Boolean. True if included in the release.
7919 :bundled: Boolean. True if included in the release.
7900 :name: String. Extension name.
7920 :name: String. Extension name.
7901 """
7921 """
7902 opts = pycompat.byteskwargs(opts)
7922 opts = pycompat.byteskwargs(opts)
7903 if ui.verbose:
7923 if ui.verbose:
7904 ui.pager(b'version')
7924 ui.pager(b'version')
7905 fm = ui.formatter(b"version", opts)
7925 fm = ui.formatter(b"version", opts)
7906 fm.startitem()
7926 fm.startitem()
7907 fm.write(
7927 fm.write(
7908 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7928 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7909 )
7929 )
7910 license = _(
7930 license = _(
7911 b"(see https://mercurial-scm.org for more information)\n"
7931 b"(see https://mercurial-scm.org for more information)\n"
7912 b"\nCopyright (C) 2005-2022 Olivia Mackall and others\n"
7932 b"\nCopyright (C) 2005-2022 Olivia Mackall and others\n"
7913 b"This is free software; see the source for copying conditions. "
7933 b"This is free software; see the source for copying conditions. "
7914 b"There is NO\nwarranty; "
7934 b"There is NO\nwarranty; "
7915 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7935 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7916 )
7936 )
7917 if not ui.quiet:
7937 if not ui.quiet:
7918 fm.plain(license)
7938 fm.plain(license)
7919
7939
7920 if ui.verbose:
7940 if ui.verbose:
7921 fm.plain(_(b"\nEnabled extensions:\n\n"))
7941 fm.plain(_(b"\nEnabled extensions:\n\n"))
7922 # format names and versions into columns
7942 # format names and versions into columns
7923 names = []
7943 names = []
7924 vers = []
7944 vers = []
7925 isinternals = []
7945 isinternals = []
7926 for name, module in sorted(extensions.extensions()):
7946 for name, module in sorted(extensions.extensions()):
7927 names.append(name)
7947 names.append(name)
7928 vers.append(extensions.moduleversion(module) or None)
7948 vers.append(extensions.moduleversion(module) or None)
7929 isinternals.append(extensions.ismoduleinternal(module))
7949 isinternals.append(extensions.ismoduleinternal(module))
7930 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7950 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7931 if names:
7951 if names:
7932 namefmt = b" %%-%ds " % max(len(n) for n in names)
7952 namefmt = b" %%-%ds " % max(len(n) for n in names)
7933 places = [_(b"external"), _(b"internal")]
7953 places = [_(b"external"), _(b"internal")]
7934 for n, v, p in zip(names, vers, isinternals):
7954 for n, v, p in zip(names, vers, isinternals):
7935 fn.startitem()
7955 fn.startitem()
7936 fn.condwrite(ui.verbose, b"name", namefmt, n)
7956 fn.condwrite(ui.verbose, b"name", namefmt, n)
7937 if ui.verbose:
7957 if ui.verbose:
7938 fn.plain(b"%s " % places[p])
7958 fn.plain(b"%s " % places[p])
7939 fn.data(bundled=p)
7959 fn.data(bundled=p)
7940 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7960 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7941 if ui.verbose:
7961 if ui.verbose:
7942 fn.plain(b"\n")
7962 fn.plain(b"\n")
7943 fn.end()
7963 fn.end()
7944 fm.end()
7964 fm.end()
7945
7965
7946
7966
7947 def loadcmdtable(ui, name, cmdtable):
7967 def loadcmdtable(ui, name, cmdtable):
7948 """Load command functions from specified cmdtable"""
7968 """Load command functions from specified cmdtable"""
7949 overrides = [cmd for cmd in cmdtable if cmd in table]
7969 overrides = [cmd for cmd in cmdtable if cmd in table]
7950 if overrides:
7970 if overrides:
7951 ui.warn(
7971 ui.warn(
7952 _(b"extension '%s' overrides commands: %s\n")
7972 _(b"extension '%s' overrides commands: %s\n")
7953 % (name, b" ".join(overrides))
7973 % (name, b" ".join(overrides))
7954 )
7974 )
7955 table.update(cmdtable)
7975 table.update(cmdtable)
@@ -1,1065 +1,1065 b''
1 Setting up test
1 Setting up test
2
2
3 $ hg init test
3 $ hg init test
4 $ cd test
4 $ cd test
5 $ echo 0 > afile
5 $ echo 0 > afile
6 $ hg add afile
6 $ hg add afile
7 $ hg commit -m "0.0"
7 $ hg commit -m "0.0"
8 $ echo 1 >> afile
8 $ echo 1 >> afile
9 $ hg commit -m "0.1"
9 $ hg commit -m "0.1"
10 $ echo 2 >> afile
10 $ echo 2 >> afile
11 $ hg commit -m "0.2"
11 $ hg commit -m "0.2"
12 $ echo 3 >> afile
12 $ echo 3 >> afile
13 $ hg commit -m "0.3"
13 $ hg commit -m "0.3"
14 $ hg update -C 0
14 $ hg update -C 0
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 $ echo 1 >> afile
16 $ echo 1 >> afile
17 $ hg commit -m "1.1"
17 $ hg commit -m "1.1"
18 created new head
18 created new head
19 $ echo 2 >> afile
19 $ echo 2 >> afile
20 $ hg commit -m "1.2"
20 $ hg commit -m "1.2"
21 $ echo "a line" > fred
21 $ echo "a line" > fred
22 $ echo 3 >> afile
22 $ echo 3 >> afile
23 $ hg add fred
23 $ hg add fred
24 $ hg commit -m "1.3"
24 $ hg commit -m "1.3"
25 $ hg mv afile adifferentfile
25 $ hg mv afile adifferentfile
26 $ hg commit -m "1.3m"
26 $ hg commit -m "1.3m"
27 $ hg update -C 3
27 $ hg update -C 3
28 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
28 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
29 $ hg mv afile anotherfile
29 $ hg mv afile anotherfile
30 $ hg commit -m "0.3m"
30 $ hg commit -m "0.3m"
31 $ hg verify
31 $ hg verify
32 checking changesets
32 checking changesets
33 checking manifests
33 checking manifests
34 crosschecking files in changesets and manifests
34 crosschecking files in changesets and manifests
35 checking files
35 checking files
36 checked 9 changesets with 7 changes to 4 files
36 checked 9 changesets with 7 changes to 4 files
37 $ cd ..
37 $ cd ..
38 $ hg init empty
38 $ hg init empty
39
39
40 Bundle and phase
40 Bundle and phase
41
41
42 $ hg -R test phase --force --secret 0
42 $ hg -R test phase --force --secret 0
43 $ hg -R test bundle phase.hg empty
43 $ hg -R test bundle phase.hg empty
44 searching for changes
44 searching for changes
45 no changes found (ignored 9 secret changesets)
45 no changes found (ignored 9 secret changesets)
46 [1]
46 [1]
47 $ hg -R test phase --draft -r 'head()'
47 $ hg -R test phase --draft -r 'head()'
48
48
49 Bundle --all
49 Bundle --all
50
50
51 $ hg -R test bundle --all all.hg
51 $ hg -R test bundle --all all.hg
52 9 changesets found
52 9 changesets found
53
53
54 Bundle test to full.hg
54 Bundle test to full.hg
55
55
56 $ hg -R test bundle full.hg empty
56 $ hg -R test bundle full.hg empty
57 searching for changes
57 searching for changes
58 9 changesets found
58 9 changesets found
59
59
60 Unbundle full.hg in test
60 Unbundle full.hg in test
61
61
62 $ hg -R test unbundle full.hg
62 $ hg -R test unbundle full.hg
63 adding changesets
63 adding changesets
64 adding manifests
64 adding manifests
65 adding file changes
65 adding file changes
66 added 0 changesets with 0 changes to 4 files
66 added 0 changesets with 0 changes to 4 files
67 (run 'hg update' to get a working copy)
67 (run 'hg update' to get a working copy)
68
68
69 Verify empty
69 Verify empty
70
70
71 $ hg -R empty heads
71 $ hg -R empty heads
72 [1]
72 [1]
73 $ hg -R empty verify
73 $ hg -R empty verify
74 checking changesets
74 checking changesets
75 checking manifests
75 checking manifests
76 crosschecking files in changesets and manifests
76 crosschecking files in changesets and manifests
77 checking files
77 checking files
78 checked 0 changesets with 0 changes to 0 files
78 checked 0 changesets with 0 changes to 0 files
79
79
80 #if repobundlerepo
80 #if repobundlerepo
81
81
82 Pull full.hg into test (using --cwd)
82 Pull full.hg into test (using --cwd)
83
83
84 $ hg --cwd test pull ../full.hg
84 $ hg --cwd test pull ../full.hg
85 pulling from ../full.hg
85 pulling from ../full.hg
86 searching for changes
86 searching for changes
87 no changes found
87 no changes found
88
88
89 Verify that there are no leaked temporary files after pull (issue2797)
89 Verify that there are no leaked temporary files after pull (issue2797)
90
90
91 $ ls test/.hg | grep .hg10un
91 $ ls test/.hg | grep .hg10un
92 [1]
92 [1]
93
93
94 Pull full.hg into empty (using --cwd)
94 Pull full.hg into empty (using --cwd)
95
95
96 $ hg --cwd empty pull ../full.hg
96 $ hg --cwd empty pull ../full.hg
97 pulling from ../full.hg
97 pulling from ../full.hg
98 requesting all changes
98 requesting all changes
99 adding changesets
99 adding changesets
100 adding manifests
100 adding manifests
101 adding file changes
101 adding file changes
102 added 9 changesets with 7 changes to 4 files (+1 heads)
102 added 9 changesets with 7 changes to 4 files (+1 heads)
103 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
103 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
104 (run 'hg heads' to see heads, 'hg merge' to merge)
104 (run 'hg heads' to see heads, 'hg merge' to merge)
105
105
106 Rollback empty
106 Rollback empty
107
107
108 $ hg -R empty rollback
108 $ hg -R empty rollback
109 repository tip rolled back to revision -1 (undo pull)
109 repository tip rolled back to revision -1 (undo pull)
110
110
111 Pull full.hg into empty again (using --cwd)
111 Pull full.hg into empty again (using --cwd)
112
112
113 $ hg --cwd empty pull ../full.hg
113 $ hg --cwd empty pull ../full.hg
114 pulling from ../full.hg
114 pulling from ../full.hg
115 requesting all changes
115 requesting all changes
116 adding changesets
116 adding changesets
117 adding manifests
117 adding manifests
118 adding file changes
118 adding file changes
119 added 9 changesets with 7 changes to 4 files (+1 heads)
119 added 9 changesets with 7 changes to 4 files (+1 heads)
120 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
120 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
121 (run 'hg heads' to see heads, 'hg merge' to merge)
121 (run 'hg heads' to see heads, 'hg merge' to merge)
122
122
123 Pull full.hg into test (using -R)
123 Pull full.hg into test (using -R)
124
124
125 $ hg -R test pull full.hg
125 $ hg -R test pull full.hg
126 pulling from full.hg
126 pulling from full.hg
127 searching for changes
127 searching for changes
128 no changes found
128 no changes found
129
129
130 Pull full.hg into empty (using -R)
130 Pull full.hg into empty (using -R)
131
131
132 $ hg -R empty pull full.hg
132 $ hg -R empty pull full.hg
133 pulling from full.hg
133 pulling from full.hg
134 searching for changes
134 searching for changes
135 no changes found
135 no changes found
136
136
137 Rollback empty
137 Rollback empty
138
138
139 $ hg -R empty rollback
139 $ hg -R empty rollback
140 repository tip rolled back to revision -1 (undo pull)
140 repository tip rolled back to revision -1 (undo pull)
141
141
142 Pull full.hg into empty again (using -R)
142 Pull full.hg into empty again (using -R)
143
143
144 $ hg -R empty pull full.hg
144 $ hg -R empty pull full.hg
145 pulling from full.hg
145 pulling from full.hg
146 requesting all changes
146 requesting all changes
147 adding changesets
147 adding changesets
148 adding manifests
148 adding manifests
149 adding file changes
149 adding file changes
150 added 9 changesets with 7 changes to 4 files (+1 heads)
150 added 9 changesets with 7 changes to 4 files (+1 heads)
151 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
151 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
152 (run 'hg heads' to see heads, 'hg merge' to merge)
152 (run 'hg heads' to see heads, 'hg merge' to merge)
153
153
154 Log -R full.hg in fresh empty
154 Log -R full.hg in fresh empty
155
155
156 $ rm -r empty
156 $ rm -r empty
157 $ hg init empty
157 $ hg init empty
158 $ cd empty
158 $ cd empty
159 $ hg -R bundle://../full.hg log
159 $ hg -R bundle://../full.hg log
160 changeset: 8:aa35859c02ea
160 changeset: 8:aa35859c02ea
161 tag: tip
161 tag: tip
162 parent: 3:eebf5a27f8ca
162 parent: 3:eebf5a27f8ca
163 user: test
163 user: test
164 date: Thu Jan 01 00:00:00 1970 +0000
164 date: Thu Jan 01 00:00:00 1970 +0000
165 summary: 0.3m
165 summary: 0.3m
166
166
167 changeset: 7:a6a34bfa0076
167 changeset: 7:a6a34bfa0076
168 user: test
168 user: test
169 date: Thu Jan 01 00:00:00 1970 +0000
169 date: Thu Jan 01 00:00:00 1970 +0000
170 summary: 1.3m
170 summary: 1.3m
171
171
172 changeset: 6:7373c1169842
172 changeset: 6:7373c1169842
173 user: test
173 user: test
174 date: Thu Jan 01 00:00:00 1970 +0000
174 date: Thu Jan 01 00:00:00 1970 +0000
175 summary: 1.3
175 summary: 1.3
176
176
177 changeset: 5:1bb50a9436a7
177 changeset: 5:1bb50a9436a7
178 user: test
178 user: test
179 date: Thu Jan 01 00:00:00 1970 +0000
179 date: Thu Jan 01 00:00:00 1970 +0000
180 summary: 1.2
180 summary: 1.2
181
181
182 changeset: 4:095197eb4973
182 changeset: 4:095197eb4973
183 parent: 0:f9ee2f85a263
183 parent: 0:f9ee2f85a263
184 user: test
184 user: test
185 date: Thu Jan 01 00:00:00 1970 +0000
185 date: Thu Jan 01 00:00:00 1970 +0000
186 summary: 1.1
186 summary: 1.1
187
187
188 changeset: 3:eebf5a27f8ca
188 changeset: 3:eebf5a27f8ca
189 user: test
189 user: test
190 date: Thu Jan 01 00:00:00 1970 +0000
190 date: Thu Jan 01 00:00:00 1970 +0000
191 summary: 0.3
191 summary: 0.3
192
192
193 changeset: 2:e38ba6f5b7e0
193 changeset: 2:e38ba6f5b7e0
194 user: test
194 user: test
195 date: Thu Jan 01 00:00:00 1970 +0000
195 date: Thu Jan 01 00:00:00 1970 +0000
196 summary: 0.2
196 summary: 0.2
197
197
198 changeset: 1:34c2bf6b0626
198 changeset: 1:34c2bf6b0626
199 user: test
199 user: test
200 date: Thu Jan 01 00:00:00 1970 +0000
200 date: Thu Jan 01 00:00:00 1970 +0000
201 summary: 0.1
201 summary: 0.1
202
202
203 changeset: 0:f9ee2f85a263
203 changeset: 0:f9ee2f85a263
204 user: test
204 user: test
205 date: Thu Jan 01 00:00:00 1970 +0000
205 date: Thu Jan 01 00:00:00 1970 +0000
206 summary: 0.0
206 summary: 0.0
207
207
208 Make sure bundlerepo doesn't leak tempfiles (issue2491)
208 Make sure bundlerepo doesn't leak tempfiles (issue2491)
209
209
210 $ ls .hg
210 $ ls .hg
211 00changelog.i
211 00changelog.i
212 cache
212 cache
213 requires
213 requires
214 store
214 store
215 wcache
215 wcache
216
216
217 Pull ../full.hg into empty (with hook)
217 Pull ../full.hg into empty (with hook)
218
218
219 $ cat >> .hg/hgrc <<EOF
219 $ cat >> .hg/hgrc <<EOF
220 > [hooks]
220 > [hooks]
221 > changegroup = sh -c "printenv.py --line changegroup"
221 > changegroup = sh -c "printenv.py --line changegroup"
222 > EOF
222 > EOF
223
223
224 doesn't work (yet ?)
224 doesn't work (yet ?)
225 NOTE: msys is mangling the URL below
225 NOTE: msys is mangling the URL below
226
226
227 hg -R bundle://../full.hg verify
227 hg -R bundle://../full.hg verify
228
228
229 $ hg pull bundle://../full.hg
229 $ hg pull bundle://../full.hg
230 pulling from bundle:../full.hg
230 pulling from bundle:../full.hg
231 requesting all changes
231 requesting all changes
232 adding changesets
232 adding changesets
233 adding manifests
233 adding manifests
234 adding file changes
234 adding file changes
235 added 9 changesets with 7 changes to 4 files (+1 heads)
235 added 9 changesets with 7 changes to 4 files (+1 heads)
236 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
236 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
237 changegroup hook: HG_HOOKNAME=changegroup
237 changegroup hook: HG_HOOKNAME=changegroup
238 HG_HOOKTYPE=changegroup
238 HG_HOOKTYPE=changegroup
239 HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735
239 HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735
240 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf
240 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf
241 HG_SOURCE=pull
241 HG_SOURCE=pull
242 HG_TXNID=TXN:$ID$
242 HG_TXNID=TXN:$ID$
243 HG_TXNNAME=pull
243 HG_TXNNAME=pull
244 bundle:../full.hg (no-msys !)
244 bundle:../full.hg (no-msys !)
245 bundle;../full.hg (msys !)
245 bundle;../full.hg (msys !)
246 HG_URL=bundle:../full.hg (no-msys !)
246 HG_URL=bundle:../full.hg (no-msys !)
247 HG_URL=bundle;../full.hg (msys !)
247 HG_URL=bundle;../full.hg (msys !)
248
248
249 (run 'hg heads' to see heads, 'hg merge' to merge)
249 (run 'hg heads' to see heads, 'hg merge' to merge)
250
250
251 Rollback empty
251 Rollback empty
252
252
253 $ hg rollback
253 $ hg rollback
254 repository tip rolled back to revision -1 (undo pull)
254 repository tip rolled back to revision -1 (undo pull)
255 $ cd ..
255 $ cd ..
256
256
257 Log -R bundle:empty+full.hg
257 Log -R bundle:empty+full.hg
258
258
259 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
259 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
260 8 7 6 5 4 3 2 1 0
260 8 7 6 5 4 3 2 1 0
261
261
262 Pull full.hg into empty again (using -R; with hook)
262 Pull full.hg into empty again (using -R; with hook)
263
263
264 $ hg -R empty pull full.hg
264 $ hg -R empty pull full.hg
265 pulling from full.hg
265 pulling from full.hg
266 requesting all changes
266 requesting all changes
267 adding changesets
267 adding changesets
268 adding manifests
268 adding manifests
269 adding file changes
269 adding file changes
270 added 9 changesets with 7 changes to 4 files (+1 heads)
270 added 9 changesets with 7 changes to 4 files (+1 heads)
271 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
271 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
272 changegroup hook: HG_HOOKNAME=changegroup
272 changegroup hook: HG_HOOKNAME=changegroup
273 HG_HOOKTYPE=changegroup
273 HG_HOOKTYPE=changegroup
274 HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735
274 HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735
275 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf
275 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf
276 HG_SOURCE=pull
276 HG_SOURCE=pull
277 HG_TXNID=TXN:$ID$
277 HG_TXNID=TXN:$ID$
278 HG_TXNNAME=pull
278 HG_TXNNAME=pull
279 bundle:empty+full.hg
279 bundle:empty+full.hg
280 HG_URL=bundle:empty+full.hg
280 HG_URL=bundle:empty+full.hg
281
281
282 (run 'hg heads' to see heads, 'hg merge' to merge)
282 (run 'hg heads' to see heads, 'hg merge' to merge)
283
283
284 #endif
284 #endif
285
285
286 Cannot produce streaming clone bundles with "hg bundle"
286 Cannot produce streaming clone bundles with "hg bundle"
287
287
288 $ hg -R test bundle -t packed1 packed.hg
288 $ hg -R test bundle -t packed1 packed.hg
289 abort: packed bundles cannot be produced by "hg bundle"
289 abort: packed bundles cannot be produced by "hg bundle"
290 (use 'hg debugcreatestreamclonebundle')
290 (use 'hg debugcreatestreamclonebundle')
291 [10]
291 [10]
292
292
293 packed1 is produced properly
293 packed1 is produced properly
294
294
295
295
296 #if reporevlogstore rust
296 #if reporevlogstore rust
297
297
298 $ hg -R test debugcreatestreamclonebundle packed.hg
298 $ hg -R test debugcreatestreamclonebundle packed.hg
299 writing 2665 bytes for 6 files
299 writing 2665 bytes for 6 files
300 bundle requirements: generaldelta, revlog-compression-zstd, revlogv1, sparserevlog
300 bundle requirements: generaldelta, revlog-compression-zstd, revlogv1, sparserevlog
301
301
302 $ f -B 64 --size --sha1 --hexdump packed.hg
302 $ f -B 64 --size --sha1 --hexdump packed.hg
303 packed.hg: size=2865, sha1=353d10311f4befa195d9a1ca4b8e26518115c702
303 packed.hg: size=2865, sha1=353d10311f4befa195d9a1ca4b8e26518115c702
304 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
304 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
305 0010: 00 00 00 00 0a 69 00 3b 67 65 6e 65 72 61 6c 64 |.....i.;generald|
305 0010: 00 00 00 00 0a 69 00 3b 67 65 6e 65 72 61 6c 64 |.....i.;generald|
306 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 2d 63 6f 6d 70 |elta,revlog-comp|
306 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 2d 63 6f 6d 70 |elta,revlog-comp|
307 0030: 72 65 73 73 69 6f 6e 2d 7a 73 74 64 2c 72 65 76 |ression-zstd,rev|
307 0030: 72 65 73 73 69 6f 6e 2d 7a 73 74 64 2c 72 65 76 |ression-zstd,rev|
308 $ hg debugbundle --spec packed.hg
308 $ hg debugbundle --spec packed.hg
309 none-packed1;requirements%3Dgeneraldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog
309 none-packed1;requirements%3Dgeneraldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog
310 #endif
310 #endif
311
311
312 #if reporevlogstore no-rust zstd
312 #if reporevlogstore no-rust zstd
313
313
314 $ hg -R test debugcreatestreamclonebundle packed.hg
314 $ hg -R test debugcreatestreamclonebundle packed.hg
315 writing 2665 bytes for 6 files
315 writing 2665 bytes for 6 files
316 bundle requirements: generaldelta, revlog-compression-zstd, revlogv1, sparserevlog
316 bundle requirements: generaldelta, revlog-compression-zstd, revlogv1, sparserevlog
317
317
318 $ f -B 64 --size --sha1 --hexdump packed.hg
318 $ f -B 64 --size --sha1 --hexdump packed.hg
319 packed.hg: size=2865, sha1=353d10311f4befa195d9a1ca4b8e26518115c702
319 packed.hg: size=2865, sha1=353d10311f4befa195d9a1ca4b8e26518115c702
320 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
320 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
321 0010: 00 00 00 00 0a 69 00 3b 67 65 6e 65 72 61 6c 64 |.....i.;generald|
321 0010: 00 00 00 00 0a 69 00 3b 67 65 6e 65 72 61 6c 64 |.....i.;generald|
322 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 2d 63 6f 6d 70 |elta,revlog-comp|
322 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 2d 63 6f 6d 70 |elta,revlog-comp|
323 0030: 72 65 73 73 69 6f 6e 2d 7a 73 74 64 2c 72 65 76 |ression-zstd,rev|
323 0030: 72 65 73 73 69 6f 6e 2d 7a 73 74 64 2c 72 65 76 |ression-zstd,rev|
324 $ hg debugbundle --spec packed.hg
324 $ hg debugbundle --spec packed.hg
325 none-packed1;requirements%3Dgeneraldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog
325 none-packed1;requirements%3Dgeneraldelta%2Crevlog-compression-zstd%2Crevlogv1%2Csparserevlog
326 #endif
326 #endif
327
327
328 #if reporevlogstore no-rust no-zstd
328 #if reporevlogstore no-rust no-zstd
329
329
330 $ hg -R test debugcreatestreamclonebundle packed.hg
330 $ hg -R test debugcreatestreamclonebundle packed.hg
331 writing 2664 bytes for 6 files
331 writing 2664 bytes for 6 files
332 bundle requirements: generaldelta, revlogv1, sparserevlog
332 bundle requirements: generaldelta, revlogv1, sparserevlog
333
333
334 $ f -B 64 --size --sha1 --hexdump packed.hg
334 $ f -B 64 --size --sha1 --hexdump packed.hg
335 packed.hg: size=2840, sha1=12bf3eee3eb8a04c503ce2d29b48f0135c7edff5
335 packed.hg: size=2840, sha1=12bf3eee3eb8a04c503ce2d29b48f0135c7edff5
336 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
336 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
337 0010: 00 00 00 00 0a 68 00 23 67 65 6e 65 72 61 6c 64 |.....h.#generald|
337 0010: 00 00 00 00 0a 68 00 23 67 65 6e 65 72 61 6c 64 |.....h.#generald|
338 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 76 31 2c 73 70 |elta,revlogv1,sp|
338 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 76 31 2c 73 70 |elta,revlogv1,sp|
339 0030: 61 72 73 65 72 65 76 6c 6f 67 00 64 61 74 61 2f |arserevlog.data/|
339 0030: 61 72 73 65 72 65 76 6c 6f 67 00 64 61 74 61 2f |arserevlog.data/|
340 $ hg debugbundle --spec packed.hg
340 $ hg debugbundle --spec packed.hg
341 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1%2Csparserevlog
341 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1%2Csparserevlog
342 #endif
342 #endif
343
343
344 #if reporevlogstore
344 #if reporevlogstore
345
345
346 generaldelta requirement is not listed in stream clone bundles unless used
346 generaldelta requirement is not listed in stream clone bundles unless used
347
347
348 $ hg --config format.usegeneraldelta=false init testnongd
348 $ hg --config format.usegeneraldelta=false init testnongd
349 $ cd testnongd
349 $ cd testnongd
350 $ touch foo
350 $ touch foo
351 $ hg -q commit -A -m initial
351 $ hg -q commit -A -m initial
352 $ cd ..
352 $ cd ..
353
353
354 #endif
354 #endif
355
355
356 #if reporevlogstore rust
356 #if reporevlogstore rust
357
357
358 $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg
358 $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg
359 writing 301 bytes for 3 files
359 writing 301 bytes for 3 files
360 bundle requirements: revlog-compression-zstd, revlogv1
360 bundle requirements: revlog-compression-zstd, revlogv1
361
361
362 $ f -B 64 --size --sha1 --hexdump packednongd.hg
362 $ f -B 64 --size --sha1 --hexdump packednongd.hg
363 packednongd.hg: size=407, sha1=0b8714422b785ba8eb98c916b41ffd5fb994c9b5
363 packednongd.hg: size=407, sha1=0b8714422b785ba8eb98c916b41ffd5fb994c9b5
364 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........|
364 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........|
365 0010: 00 00 00 00 01 2d 00 21 72 65 76 6c 6f 67 2d 63 |.....-.!revlog-c|
365 0010: 00 00 00 00 01 2d 00 21 72 65 76 6c 6f 67 2d 63 |.....-.!revlog-c|
366 0020: 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 2c |ompression-zstd,|
366 0020: 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 2c |ompression-zstd,|
367 0030: 72 65 76 6c 6f 67 76 31 00 64 61 74 61 2f 66 6f |revlogv1.data/fo|
367 0030: 72 65 76 6c 6f 67 76 31 00 64 61 74 61 2f 66 6f |revlogv1.data/fo|
368
368
369 $ hg debugbundle --spec packednongd.hg
369 $ hg debugbundle --spec packednongd.hg
370 none-packed1;requirements%3Drevlog-compression-zstd%2Crevlogv1
370 none-packed1;requirements%3Drevlog-compression-zstd%2Crevlogv1
371
371
372 #endif
372 #endif
373
373
374 #if reporevlogstore no-rust zstd
374 #if reporevlogstore no-rust zstd
375
375
376 $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg
376 $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg
377 writing 301 bytes for 3 files
377 writing 301 bytes for 3 files
378 bundle requirements: revlog-compression-zstd, revlogv1
378 bundle requirements: revlog-compression-zstd, revlogv1
379
379
380 $ f -B 64 --size --sha1 --hexdump packednongd.hg
380 $ f -B 64 --size --sha1 --hexdump packednongd.hg
381 packednongd.hg: size=407, sha1=0b8714422b785ba8eb98c916b41ffd5fb994c9b5
381 packednongd.hg: size=407, sha1=0b8714422b785ba8eb98c916b41ffd5fb994c9b5
382 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........|
382 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........|
383 0010: 00 00 00 00 01 2d 00 21 72 65 76 6c 6f 67 2d 63 |.....-.!revlog-c|
383 0010: 00 00 00 00 01 2d 00 21 72 65 76 6c 6f 67 2d 63 |.....-.!revlog-c|
384 0020: 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 2c |ompression-zstd,|
384 0020: 6f 6d 70 72 65 73 73 69 6f 6e 2d 7a 73 74 64 2c |ompression-zstd,|
385 0030: 72 65 76 6c 6f 67 76 31 00 64 61 74 61 2f 66 6f |revlogv1.data/fo|
385 0030: 72 65 76 6c 6f 67 76 31 00 64 61 74 61 2f 66 6f |revlogv1.data/fo|
386
386
387 $ hg debugbundle --spec packednongd.hg
387 $ hg debugbundle --spec packednongd.hg
388 none-packed1;requirements%3Drevlog-compression-zstd%2Crevlogv1
388 none-packed1;requirements%3Drevlog-compression-zstd%2Crevlogv1
389
389
390
390
391 #endif
391 #endif
392
392
393 #if reporevlogstore no-rust no-zstd
393 #if reporevlogstore no-rust no-zstd
394
394
395 $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg
395 $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg
396 writing 301 bytes for 3 files
396 writing 301 bytes for 3 files
397 bundle requirements: revlogv1
397 bundle requirements: revlogv1
398
398
399 $ f -B 64 --size --sha1 --hexdump packednongd.hg
399 $ f -B 64 --size --sha1 --hexdump packednongd.hg
400 packednongd.hg: size=383, sha1=1d9c230238edd5d38907100b729ba72b1831fe6f
400 packednongd.hg: size=383, sha1=1d9c230238edd5d38907100b729ba72b1831fe6f
401 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........|
401 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........|
402 0010: 00 00 00 00 01 2d 00 09 72 65 76 6c 6f 67 76 31 |.....-..revlogv1|
402 0010: 00 00 00 00 01 2d 00 09 72 65 76 6c 6f 67 76 31 |.....-..revlogv1|
403 0020: 00 64 61 74 61 2f 66 6f 6f 2e 69 00 36 34 0a 00 |.data/foo.i.64..|
403 0020: 00 64 61 74 61 2f 66 6f 6f 2e 69 00 36 34 0a 00 |.data/foo.i.64..|
404 0030: 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
404 0030: 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
405
405
406 $ hg debugbundle --spec packednongd.hg
406 $ hg debugbundle --spec packednongd.hg
407 none-packed1;requirements%3Drevlogv1
407 none-packed1;requirements%3Drevlogv1
408
408
409
409
410 #endif
410 #endif
411
411
412 #if reporevlogstore
412 #if reporevlogstore
413
413
414 Warning emitted when packed bundles contain secret changesets
414 Warning emitted when packed bundles contain secret changesets
415
415
416 $ hg init testsecret
416 $ hg init testsecret
417 $ cd testsecret
417 $ cd testsecret
418 $ touch foo
418 $ touch foo
419 $ hg -q commit -A -m initial
419 $ hg -q commit -A -m initial
420 $ hg phase --force --secret -r .
420 $ hg phase --force --secret -r .
421 $ cd ..
421 $ cd ..
422
422
423 #endif
423 #endif
424
424
425 #if reporevlogstore rust
425 #if reporevlogstore rust
426
426
427 $ hg -R testsecret debugcreatestreamclonebundle packedsecret.hg
427 $ hg -R testsecret debugcreatestreamclonebundle packedsecret.hg
428 (warning: stream clone bundle will contain secret revisions)
428 (warning: stream clone bundle will contain secret revisions)
429 writing 301 bytes for 3 files
429 writing 301 bytes for 3 files
430 bundle requirements: generaldelta, revlog-compression-zstd, revlogv1, sparserevlog
430 bundle requirements: generaldelta, revlog-compression-zstd, revlogv1, sparserevlog
431
431
432 #endif
432 #endif
433
433
434 #if reporevlogstore no-rust zstd
434 #if reporevlogstore no-rust zstd
435
435
436 $ hg -R testsecret debugcreatestreamclonebundle packedsecret.hg
436 $ hg -R testsecret debugcreatestreamclonebundle packedsecret.hg
437 (warning: stream clone bundle will contain secret revisions)
437 (warning: stream clone bundle will contain secret revisions)
438 writing 301 bytes for 3 files
438 writing 301 bytes for 3 files
439 bundle requirements: generaldelta, revlog-compression-zstd, revlogv1, sparserevlog
439 bundle requirements: generaldelta, revlog-compression-zstd, revlogv1, sparserevlog
440
440
441 #endif
441 #endif
442
442
443 #if reporevlogstore no-rust no-zstd
443 #if reporevlogstore no-rust no-zstd
444
444
445 $ hg -R testsecret debugcreatestreamclonebundle packedsecret.hg
445 $ hg -R testsecret debugcreatestreamclonebundle packedsecret.hg
446 (warning: stream clone bundle will contain secret revisions)
446 (warning: stream clone bundle will contain secret revisions)
447 writing 301 bytes for 3 files
447 writing 301 bytes for 3 files
448 bundle requirements: generaldelta, revlogv1, sparserevlog
448 bundle requirements: generaldelta, revlogv1, sparserevlog
449
449
450 #endif
450 #endif
451
451
452 #if reporevlogstore
452 #if reporevlogstore
453
453
454 Unpacking packed1 bundles with "hg unbundle" isn't allowed
454 Unpacking packed1 bundles with "hg unbundle" isn't allowed
455
455
456 $ hg init packed
456 $ hg init packed
457 $ hg -R packed unbundle packed.hg
457 $ hg -R packed unbundle packed.hg
458 abort: packed bundles cannot be applied with "hg unbundle"
458 abort: packed bundles cannot be applied with "hg unbundle"
459 (use "hg debugapplystreamclonebundle")
459 (use "hg debugapplystreamclonebundle")
460 [10]
460 [10]
461
461
462 packed1 can be consumed from debug command
462 packed1 can be consumed from debug command
463
463
464 (this also confirms that streamclone-ed changes are visible via
464 (this also confirms that streamclone-ed changes are visible via
465 @filecache properties to in-process procedures before closing
465 @filecache properties to in-process procedures before closing
466 transaction)
466 transaction)
467
467
468 $ cat > $TESTTMP/showtip.py <<EOF
468 $ cat > $TESTTMP/showtip.py <<EOF
469 >
469 >
470 > def showtip(ui, repo, hooktype, **kwargs):
470 > def showtip(ui, repo, hooktype, **kwargs):
471 > ui.warn(b'%s: %s\n' % (hooktype, repo[b'tip'].hex()[:12]))
471 > ui.warn(b'%s: %s\n' % (hooktype, repo[b'tip'].hex()[:12]))
472 >
472 >
473 > def reposetup(ui, repo):
473 > def reposetup(ui, repo):
474 > # this confirms (and ensures) that (empty) 00changelog.i
474 > # this confirms (and ensures) that (empty) 00changelog.i
475 > # before streamclone is already cached as repo.changelog
475 > # before streamclone is already cached as repo.changelog
476 > ui.setconfig(b'hooks', b'pretxnopen.showtip', showtip)
476 > ui.setconfig(b'hooks', b'pretxnopen.showtip', showtip)
477 >
477 >
478 > # this confirms that streamclone-ed changes are visible to
478 > # this confirms that streamclone-ed changes are visible to
479 > # in-process procedures before closing transaction
479 > # in-process procedures before closing transaction
480 > ui.setconfig(b'hooks', b'pretxnclose.showtip', showtip)
480 > ui.setconfig(b'hooks', b'pretxnclose.showtip', showtip)
481 >
481 >
482 > # this confirms that streamclone-ed changes are still visible
482 > # this confirms that streamclone-ed changes are still visible
483 > # after closing transaction
483 > # after closing transaction
484 > ui.setconfig(b'hooks', b'txnclose.showtip', showtip)
484 > ui.setconfig(b'hooks', b'txnclose.showtip', showtip)
485 > EOF
485 > EOF
486 $ cat >> $HGRCPATH <<EOF
486 $ cat >> $HGRCPATH <<EOF
487 > [extensions]
487 > [extensions]
488 > showtip = $TESTTMP/showtip.py
488 > showtip = $TESTTMP/showtip.py
489 > EOF
489 > EOF
490
490
491 $ hg -R packed debugapplystreamclonebundle packed.hg
491 $ hg -R packed debugapplystreamclonebundle packed.hg
492 6 files to transfer, 2.60 KB of data
492 6 files to transfer, 2.60 KB of data
493 pretxnopen: 000000000000
493 pretxnopen: 000000000000
494 pretxnclose: aa35859c02ea
494 pretxnclose: aa35859c02ea
495 transferred 2.60 KB in * seconds (* */sec) (glob)
495 transferred 2.60 KB in * seconds (* */sec) (glob)
496 txnclose: aa35859c02ea
496 txnclose: aa35859c02ea
497
497
498 (for safety, confirm visibility of streamclone-ed changes by another
498 (for safety, confirm visibility of streamclone-ed changes by another
499 process, too)
499 process, too)
500
500
501 $ hg -R packed tip -T "{node|short}\n"
501 $ hg -R packed tip -T "{node|short}\n"
502 aa35859c02ea
502 aa35859c02ea
503
503
504 $ cat >> $HGRCPATH <<EOF
504 $ cat >> $HGRCPATH <<EOF
505 > [extensions]
505 > [extensions]
506 > showtip = !
506 > showtip = !
507 > EOF
507 > EOF
508
508
509 Does not work on non-empty repo
509 Does not work on non-empty repo
510
510
511 $ hg -R packed debugapplystreamclonebundle packed.hg
511 $ hg -R packed debugapplystreamclonebundle packed.hg
512 abort: cannot apply stream clone bundle on non-empty repo
512 abort: cannot apply stream clone bundle on non-empty repo
513 [255]
513 [255]
514
514
515 #endif
515 #endif
516
516
517 Create partial clones
517 Create partial clones
518
518
519 $ rm -r empty
519 $ rm -r empty
520 $ hg init empty
520 $ hg init empty
521 $ hg clone -r 3 test partial
521 $ hg clone -r 3 test partial
522 adding changesets
522 adding changesets
523 adding manifests
523 adding manifests
524 adding file changes
524 adding file changes
525 added 4 changesets with 4 changes to 1 files
525 added 4 changesets with 4 changes to 1 files
526 new changesets f9ee2f85a263:eebf5a27f8ca
526 new changesets f9ee2f85a263:eebf5a27f8ca
527 updating to branch default
527 updating to branch default
528 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
528 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
529 $ hg clone partial partial2
529 $ hg clone partial partial2
530 updating to branch default
530 updating to branch default
531 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
531 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
532 $ cd partial
532 $ cd partial
533
533
534 #if repobundlerepo
534 #if repobundlerepo
535
535
536 Log -R full.hg in partial
536 Log -R full.hg in partial
537
537
538 $ hg -R bundle://../full.hg log -T phases
538 $ hg -R bundle://../full.hg log -T phases
539 changeset: 8:aa35859c02ea
539 changeset: 8:aa35859c02ea
540 tag: tip
540 tag: tip
541 phase: draft
541 phase: draft
542 parent: 3:eebf5a27f8ca
542 parent: 3:eebf5a27f8ca
543 user: test
543 user: test
544 date: Thu Jan 01 00:00:00 1970 +0000
544 date: Thu Jan 01 00:00:00 1970 +0000
545 summary: 0.3m
545 summary: 0.3m
546
546
547 changeset: 7:a6a34bfa0076
547 changeset: 7:a6a34bfa0076
548 phase: draft
548 phase: draft
549 user: test
549 user: test
550 date: Thu Jan 01 00:00:00 1970 +0000
550 date: Thu Jan 01 00:00:00 1970 +0000
551 summary: 1.3m
551 summary: 1.3m
552
552
553 changeset: 6:7373c1169842
553 changeset: 6:7373c1169842
554 phase: draft
554 phase: draft
555 user: test
555 user: test
556 date: Thu Jan 01 00:00:00 1970 +0000
556 date: Thu Jan 01 00:00:00 1970 +0000
557 summary: 1.3
557 summary: 1.3
558
558
559 changeset: 5:1bb50a9436a7
559 changeset: 5:1bb50a9436a7
560 phase: draft
560 phase: draft
561 user: test
561 user: test
562 date: Thu Jan 01 00:00:00 1970 +0000
562 date: Thu Jan 01 00:00:00 1970 +0000
563 summary: 1.2
563 summary: 1.2
564
564
565 changeset: 4:095197eb4973
565 changeset: 4:095197eb4973
566 phase: draft
566 phase: draft
567 parent: 0:f9ee2f85a263
567 parent: 0:f9ee2f85a263
568 user: test
568 user: test
569 date: Thu Jan 01 00:00:00 1970 +0000
569 date: Thu Jan 01 00:00:00 1970 +0000
570 summary: 1.1
570 summary: 1.1
571
571
572 changeset: 3:eebf5a27f8ca
572 changeset: 3:eebf5a27f8ca
573 phase: public
573 phase: public
574 user: test
574 user: test
575 date: Thu Jan 01 00:00:00 1970 +0000
575 date: Thu Jan 01 00:00:00 1970 +0000
576 summary: 0.3
576 summary: 0.3
577
577
578 changeset: 2:e38ba6f5b7e0
578 changeset: 2:e38ba6f5b7e0
579 phase: public
579 phase: public
580 user: test
580 user: test
581 date: Thu Jan 01 00:00:00 1970 +0000
581 date: Thu Jan 01 00:00:00 1970 +0000
582 summary: 0.2
582 summary: 0.2
583
583
584 changeset: 1:34c2bf6b0626
584 changeset: 1:34c2bf6b0626
585 phase: public
585 phase: public
586 user: test
586 user: test
587 date: Thu Jan 01 00:00:00 1970 +0000
587 date: Thu Jan 01 00:00:00 1970 +0000
588 summary: 0.1
588 summary: 0.1
589
589
590 changeset: 0:f9ee2f85a263
590 changeset: 0:f9ee2f85a263
591 phase: public
591 phase: public
592 user: test
592 user: test
593 date: Thu Jan 01 00:00:00 1970 +0000
593 date: Thu Jan 01 00:00:00 1970 +0000
594 summary: 0.0
594 summary: 0.0
595
595
596
596
597 Incoming full.hg in partial
597 Incoming full.hg in partial
598
598
599 $ hg incoming bundle://../full.hg
599 $ hg incoming bundle://../full.hg
600 comparing with bundle:../full.hg
600 comparing with bundle:../full.hg
601 searching for changes
601 searching for changes
602 changeset: 4:095197eb4973
602 changeset: 4:095197eb4973
603 parent: 0:f9ee2f85a263
603 parent: 0:f9ee2f85a263
604 user: test
604 user: test
605 date: Thu Jan 01 00:00:00 1970 +0000
605 date: Thu Jan 01 00:00:00 1970 +0000
606 summary: 1.1
606 summary: 1.1
607
607
608 changeset: 5:1bb50a9436a7
608 changeset: 5:1bb50a9436a7
609 user: test
609 user: test
610 date: Thu Jan 01 00:00:00 1970 +0000
610 date: Thu Jan 01 00:00:00 1970 +0000
611 summary: 1.2
611 summary: 1.2
612
612
613 changeset: 6:7373c1169842
613 changeset: 6:7373c1169842
614 user: test
614 user: test
615 date: Thu Jan 01 00:00:00 1970 +0000
615 date: Thu Jan 01 00:00:00 1970 +0000
616 summary: 1.3
616 summary: 1.3
617
617
618 changeset: 7:a6a34bfa0076
618 changeset: 7:a6a34bfa0076
619 user: test
619 user: test
620 date: Thu Jan 01 00:00:00 1970 +0000
620 date: Thu Jan 01 00:00:00 1970 +0000
621 summary: 1.3m
621 summary: 1.3m
622
622
623 changeset: 8:aa35859c02ea
623 changeset: 8:aa35859c02ea
624 tag: tip
624 tag: tip
625 parent: 3:eebf5a27f8ca
625 parent: 3:eebf5a27f8ca
626 user: test
626 user: test
627 date: Thu Jan 01 00:00:00 1970 +0000
627 date: Thu Jan 01 00:00:00 1970 +0000
628 summary: 0.3m
628 summary: 0.3m
629
629
630
630
631 Outgoing -R full.hg vs partial2 in partial
631 Outgoing -R full.hg vs partial2 in partial
632
632
633 $ hg -R bundle://../full.hg outgoing ../partial2
633 $ hg -R bundle://../full.hg outgoing ../partial2
634 comparing with ../partial2
634 comparing with ../partial2
635 searching for changes
635 searching for changes
636 changeset: 4:095197eb4973
636 changeset: 4:095197eb4973
637 parent: 0:f9ee2f85a263
637 parent: 0:f9ee2f85a263
638 user: test
638 user: test
639 date: Thu Jan 01 00:00:00 1970 +0000
639 date: Thu Jan 01 00:00:00 1970 +0000
640 summary: 1.1
640 summary: 1.1
641
641
642 changeset: 5:1bb50a9436a7
642 changeset: 5:1bb50a9436a7
643 user: test
643 user: test
644 date: Thu Jan 01 00:00:00 1970 +0000
644 date: Thu Jan 01 00:00:00 1970 +0000
645 summary: 1.2
645 summary: 1.2
646
646
647 changeset: 6:7373c1169842
647 changeset: 6:7373c1169842
648 user: test
648 user: test
649 date: Thu Jan 01 00:00:00 1970 +0000
649 date: Thu Jan 01 00:00:00 1970 +0000
650 summary: 1.3
650 summary: 1.3
651
651
652 changeset: 7:a6a34bfa0076
652 changeset: 7:a6a34bfa0076
653 user: test
653 user: test
654 date: Thu Jan 01 00:00:00 1970 +0000
654 date: Thu Jan 01 00:00:00 1970 +0000
655 summary: 1.3m
655 summary: 1.3m
656
656
657 changeset: 8:aa35859c02ea
657 changeset: 8:aa35859c02ea
658 tag: tip
658 tag: tip
659 parent: 3:eebf5a27f8ca
659 parent: 3:eebf5a27f8ca
660 user: test
660 user: test
661 date: Thu Jan 01 00:00:00 1970 +0000
661 date: Thu Jan 01 00:00:00 1970 +0000
662 summary: 0.3m
662 summary: 0.3m
663
663
664
664
665 Outgoing -R does-not-exist.hg vs partial2 in partial
665 Outgoing -R does-not-exist.hg vs partial2 in partial
666
666
667 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
667 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
668 abort: *../does-not-exist.hg* (glob)
668 abort: *../does-not-exist.hg* (glob)
669 [255]
669 [255]
670
670
671 #endif
671 #endif
672
672
673 $ cd ..
673 $ cd ..
674
674
675 hide outer repo
675 hide outer repo
676 $ hg init
676 $ hg init
677
677
678 Direct clone from bundle (all-history)
678 Direct clone from bundle (all-history)
679
679
680 #if repobundlerepo
680 #if repobundlerepo
681
681
682 $ hg clone full.hg full-clone
682 $ hg clone full.hg full-clone
683 requesting all changes
683 requesting all changes
684 adding changesets
684 adding changesets
685 adding manifests
685 adding manifests
686 adding file changes
686 adding file changes
687 added 9 changesets with 7 changes to 4 files (+1 heads)
687 added 9 changesets with 7 changes to 4 files (+1 heads)
688 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
688 new changesets f9ee2f85a263:aa35859c02ea (9 drafts)
689 updating to branch default
689 updating to branch default
690 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
690 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
691 $ hg -R full-clone heads
691 $ hg -R full-clone heads
692 changeset: 8:aa35859c02ea
692 changeset: 8:aa35859c02ea
693 tag: tip
693 tag: tip
694 parent: 3:eebf5a27f8ca
694 parent: 3:eebf5a27f8ca
695 user: test
695 user: test
696 date: Thu Jan 01 00:00:00 1970 +0000
696 date: Thu Jan 01 00:00:00 1970 +0000
697 summary: 0.3m
697 summary: 0.3m
698
698
699 changeset: 7:a6a34bfa0076
699 changeset: 7:a6a34bfa0076
700 user: test
700 user: test
701 date: Thu Jan 01 00:00:00 1970 +0000
701 date: Thu Jan 01 00:00:00 1970 +0000
702 summary: 1.3m
702 summary: 1.3m
703
703
704 $ rm -r full-clone
704 $ rm -r full-clone
705
705
706 When cloning from a non-copiable repository into '', do not
706 When cloning from a non-copiable repository into '', do not
707 recurse infinitely (issue2528)
707 recurse infinitely (issue2528)
708
708
709 $ hg clone full.hg ''
709 $ hg clone full.hg ''
710 abort: empty destination path is not valid
710 abort: empty destination path is not valid
711 [10]
711 [10]
712
712
713 test for https://bz.mercurial-scm.org/216
713 test for https://bz.mercurial-scm.org/216
714
714
715 Unbundle incremental bundles into fresh empty in one go
715 Unbundle incremental bundles into fresh empty in one go
716
716
717 $ rm -r empty
717 $ rm -r empty
718 $ hg init empty
718 $ hg init empty
719 $ hg -R test bundle --base null -r 0 ../0.hg
719 $ hg -R test bundle --base null -r 0 ../0.hg
720 1 changesets found
720 1 changesets found
721 $ hg -R test bundle --base 0 -r 1 ../1.hg
721 $ hg -R test bundle --exact -r 1 ../1.hg
722 1 changesets found
722 1 changesets found
723 $ hg -R empty unbundle -u ../0.hg ../1.hg
723 $ hg -R empty unbundle -u ../0.hg ../1.hg
724 adding changesets
724 adding changesets
725 adding manifests
725 adding manifests
726 adding file changes
726 adding file changes
727 added 1 changesets with 1 changes to 1 files
727 added 1 changesets with 1 changes to 1 files
728 new changesets f9ee2f85a263 (1 drafts)
728 new changesets f9ee2f85a263 (1 drafts)
729 adding changesets
729 adding changesets
730 adding manifests
730 adding manifests
731 adding file changes
731 adding file changes
732 added 1 changesets with 1 changes to 1 files
732 added 1 changesets with 1 changes to 1 files
733 new changesets 34c2bf6b0626 (1 drafts)
733 new changesets 34c2bf6b0626 (1 drafts)
734 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
734 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
735
735
736 View full contents of the bundle
736 View full contents of the bundle
737 $ hg -R test bundle --base null -r 3 ../partial.hg
737 $ hg -R test bundle --base null -r 3 ../partial.hg
738 4 changesets found
738 4 changesets found
739 $ cd test
739 $ cd test
740 $ hg -R ../../partial.hg log -r "bundle()"
740 $ hg -R ../../partial.hg log -r "bundle()"
741 changeset: 0:f9ee2f85a263
741 changeset: 0:f9ee2f85a263
742 user: test
742 user: test
743 date: Thu Jan 01 00:00:00 1970 +0000
743 date: Thu Jan 01 00:00:00 1970 +0000
744 summary: 0.0
744 summary: 0.0
745
745
746 changeset: 1:34c2bf6b0626
746 changeset: 1:34c2bf6b0626
747 user: test
747 user: test
748 date: Thu Jan 01 00:00:00 1970 +0000
748 date: Thu Jan 01 00:00:00 1970 +0000
749 summary: 0.1
749 summary: 0.1
750
750
751 changeset: 2:e38ba6f5b7e0
751 changeset: 2:e38ba6f5b7e0
752 user: test
752 user: test
753 date: Thu Jan 01 00:00:00 1970 +0000
753 date: Thu Jan 01 00:00:00 1970 +0000
754 summary: 0.2
754 summary: 0.2
755
755
756 changeset: 3:eebf5a27f8ca
756 changeset: 3:eebf5a27f8ca
757 user: test
757 user: test
758 date: Thu Jan 01 00:00:00 1970 +0000
758 date: Thu Jan 01 00:00:00 1970 +0000
759 summary: 0.3
759 summary: 0.3
760
760
761 $ cd ..
761 $ cd ..
762
762
763 #endif
763 #endif
764
764
765 test for 540d1059c802
765 test for 540d1059c802
766
766
767 $ hg init orig
767 $ hg init orig
768 $ cd orig
768 $ cd orig
769 $ echo foo > foo
769 $ echo foo > foo
770 $ hg add foo
770 $ hg add foo
771 $ hg ci -m 'add foo'
771 $ hg ci -m 'add foo'
772
772
773 $ hg clone . ../copy
773 $ hg clone . ../copy
774 updating to branch default
774 updating to branch default
775 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
775 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
776 $ hg tag foo
776 $ hg tag foo
777
777
778 $ cd ../copy
778 $ cd ../copy
779 $ echo >> foo
779 $ echo >> foo
780 $ hg ci -m 'change foo'
780 $ hg ci -m 'change foo'
781 $ hg bundle ../bundle.hg ../orig
781 $ hg bundle ../bundle.hg ../orig
782 searching for changes
782 searching for changes
783 1 changesets found
783 1 changesets found
784
784
785 $ cd ..
785 $ cd ..
786
786
787 #if repobundlerepo
787 #if repobundlerepo
788 $ cd orig
788 $ cd orig
789 $ hg incoming ../bundle.hg
789 $ hg incoming ../bundle.hg
790 comparing with ../bundle.hg
790 comparing with ../bundle.hg
791 searching for changes
791 searching for changes
792 changeset: 2:ed1b79f46b9a
792 changeset: 2:ed1b79f46b9a
793 tag: tip
793 tag: tip
794 parent: 0:bbd179dfa0a7
794 parent: 0:bbd179dfa0a7
795 user: test
795 user: test
796 date: Thu Jan 01 00:00:00 1970 +0000
796 date: Thu Jan 01 00:00:00 1970 +0000
797 summary: change foo
797 summary: change foo
798
798
799 $ cd ..
799 $ cd ..
800
800
801 test bundle with # in the filename (issue2154):
801 test bundle with # in the filename (issue2154):
802
802
803 $ cp bundle.hg 'test#bundle.hg'
803 $ cp bundle.hg 'test#bundle.hg'
804 $ cd orig
804 $ cd orig
805 $ hg incoming '../test#bundle.hg'
805 $ hg incoming '../test#bundle.hg'
806 comparing with ../test
806 comparing with ../test
807 abort: unknown revision 'bundle.hg'
807 abort: unknown revision 'bundle.hg'
808 [10]
808 [10]
809
809
810 note that percent encoding is not handled:
810 note that percent encoding is not handled:
811
811
812 $ hg incoming ../test%23bundle.hg
812 $ hg incoming ../test%23bundle.hg
813 abort: repository ../test%23bundle.hg not found
813 abort: repository ../test%23bundle.hg not found
814 [255]
814 [255]
815 $ cd ..
815 $ cd ..
816
816
817 #endif
817 #endif
818
818
819 test to bundle revisions on the newly created branch (issue3828):
819 test to bundle revisions on the newly created branch (issue3828):
820
820
821 $ hg -q clone -U test test-clone
821 $ hg -q clone -U test test-clone
822 $ cd test
822 $ cd test
823
823
824 $ hg -q branch foo
824 $ hg -q branch foo
825 $ hg commit -m "create foo branch"
825 $ hg commit -m "create foo branch"
826 $ hg -q outgoing ../test-clone
826 $ hg -q outgoing ../test-clone
827 9:b4f5acb1ee27
827 9:b4f5acb1ee27
828 $ hg -q bundle --branch foo foo.hg ../test-clone
828 $ hg -q bundle --branch foo foo.hg ../test-clone
829 #if repobundlerepo
829 #if repobundlerepo
830 $ hg -R foo.hg -q log -r "bundle()"
830 $ hg -R foo.hg -q log -r "bundle()"
831 9:b4f5acb1ee27
831 9:b4f5acb1ee27
832 #endif
832 #endif
833
833
834 $ cd ..
834 $ cd ..
835
835
836 test for https://bz.mercurial-scm.org/1144
836 test for https://bz.mercurial-scm.org/1144
837
837
838 test that verify bundle does not traceback
838 test that verify bundle does not traceback
839
839
840 partial history bundle, fails w/ unknown parent
840 partial history bundle, fails w/ unknown parent
841
841
842 $ hg -R bundle.hg verify
842 $ hg -R bundle.hg verify
843 abort: 00changelog@bbd179dfa0a71671c253b3ae0aa1513b60d199fa: unknown parent
843 abort: 00changelog@bbd179dfa0a71671c253b3ae0aa1513b60d199fa: unknown parent
844 [50]
844 [50]
845
845
846 full history bundle, refuses to verify non-local repo
846 full history bundle, refuses to verify non-local repo
847
847
848 #if repobundlerepo
848 #if repobundlerepo
849 $ hg -R all.hg verify
849 $ hg -R all.hg verify
850 abort: cannot verify bundle or remote repos
850 abort: cannot verify bundle or remote repos
851 [255]
851 [255]
852 #endif
852 #endif
853
853
854 but, regular verify must continue to work
854 but, regular verify must continue to work
855
855
856 $ hg -R orig verify
856 $ hg -R orig verify
857 checking changesets
857 checking changesets
858 checking manifests
858 checking manifests
859 crosschecking files in changesets and manifests
859 crosschecking files in changesets and manifests
860 checking files
860 checking files
861 checked 2 changesets with 2 changes to 2 files
861 checked 2 changesets with 2 changes to 2 files
862
862
863 #if repobundlerepo
863 #if repobundlerepo
864 diff against bundle
864 diff against bundle
865
865
866 $ hg init b
866 $ hg init b
867 $ cd b
867 $ cd b
868 $ hg -R ../all.hg diff -r tip
868 $ hg -R ../all.hg diff -r tip
869 diff -r aa35859c02ea anotherfile
869 diff -r aa35859c02ea anotherfile
870 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
870 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
871 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
871 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
872 @@ -1,4 +0,0 @@
872 @@ -1,4 +0,0 @@
873 -0
873 -0
874 -1
874 -1
875 -2
875 -2
876 -3
876 -3
877 $ cd ..
877 $ cd ..
878 #endif
878 #endif
879
879
880 bundle single branch
880 bundle single branch
881
881
882 $ hg init branchy
882 $ hg init branchy
883 $ cd branchy
883 $ cd branchy
884 $ echo a >a
884 $ echo a >a
885 $ echo x >x
885 $ echo x >x
886 $ hg ci -Ama
886 $ hg ci -Ama
887 adding a
887 adding a
888 adding x
888 adding x
889 $ echo c >c
889 $ echo c >c
890 $ echo xx >x
890 $ echo xx >x
891 $ hg ci -Amc
891 $ hg ci -Amc
892 adding c
892 adding c
893 $ echo c1 >c1
893 $ echo c1 >c1
894 $ hg ci -Amc1
894 $ hg ci -Amc1
895 adding c1
895 adding c1
896 $ hg up 0
896 $ hg up 0
897 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
897 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
898 $ echo b >b
898 $ echo b >b
899 $ hg ci -Amb
899 $ hg ci -Amb
900 adding b
900 adding b
901 created new head
901 created new head
902 $ echo b1 >b1
902 $ echo b1 >b1
903 $ echo xx >x
903 $ echo xx >x
904 $ hg ci -Amb1
904 $ hg ci -Amb1
905 adding b1
905 adding b1
906 $ hg clone -q -r2 . part
906 $ hg clone -q -r2 . part
907
907
908 == bundling via incoming
908 == bundling via incoming
909
909
910 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
910 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
911 comparing with .
911 comparing with .
912 searching for changes
912 searching for changes
913 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
913 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
914 057f4db07f61970e1c11e83be79e9d08adc4dc31
914 057f4db07f61970e1c11e83be79e9d08adc4dc31
915
915
916 == bundling
916 == bundling
917
917
918 $ hg bundle bundle.hg part --debug --config progress.debug=true
918 $ hg bundle bundle.hg part --debug --config progress.debug=true
919 query 1; heads
919 query 1; heads
920 searching for changes
920 searching for changes
921 all remote heads known locally
921 all remote heads known locally
922 2 changesets found
922 2 changesets found
923 list of changesets:
923 list of changesets:
924 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
924 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
925 057f4db07f61970e1c11e83be79e9d08adc4dc31
925 057f4db07f61970e1c11e83be79e9d08adc4dc31
926 bundle2-output-bundle: "HG20", (1 params) 2 parts total
926 bundle2-output-bundle: "HG20", (1 params) 2 parts total
927 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
927 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
928 changesets: 1/2 chunks (50.00%)
928 changesets: 1/2 chunks (50.00%)
929 changesets: 2/2 chunks (100.00%)
929 changesets: 2/2 chunks (100.00%)
930 manifests: 1/2 chunks (50.00%)
930 manifests: 1/2 chunks (50.00%)
931 manifests: 2/2 chunks (100.00%)
931 manifests: 2/2 chunks (100.00%)
932 files: b 1/3 files (33.33%)
932 files: b 1/3 files (33.33%)
933 files: b1 2/3 files (66.67%)
933 files: b1 2/3 files (66.67%)
934 files: x 3/3 files (100.00%)
934 files: x 3/3 files (100.00%)
935 bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
935 bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
936
936
937 #if repobundlerepo
937 #if repobundlerepo
938 == Test for issue3441
938 == Test for issue3441
939
939
940 $ hg clone -q -r0 . part2
940 $ hg clone -q -r0 . part2
941 $ hg -q -R part2 pull bundle.hg
941 $ hg -q -R part2 pull bundle.hg
942 $ hg -R part2 verify
942 $ hg -R part2 verify
943 checking changesets
943 checking changesets
944 checking manifests
944 checking manifests
945 crosschecking files in changesets and manifests
945 crosschecking files in changesets and manifests
946 checking files
946 checking files
947 checked 3 changesets with 5 changes to 4 files
947 checked 3 changesets with 5 changes to 4 files
948 #endif
948 #endif
949
949
950 == Test bundling no commits
950 == Test bundling no commits
951
951
952 $ hg bundle -r 'public()' no-output.hg
952 $ hg bundle -r 'public()' no-output.hg
953 abort: no commits to bundle
953 abort: no commits to bundle
954 [10]
954 [10]
955
955
956 $ cd ..
956 $ cd ..
957
957
958 When user merges to the revision existing only in the bundle,
958 When user merges to the revision existing only in the bundle,
959 it should show warning that second parent of the working
959 it should show warning that second parent of the working
960 directory does not exist
960 directory does not exist
961
961
962 $ hg init update2bundled
962 $ hg init update2bundled
963 $ cd update2bundled
963 $ cd update2bundled
964 $ cat <<EOF >> .hg/hgrc
964 $ cat <<EOF >> .hg/hgrc
965 > [extensions]
965 > [extensions]
966 > strip =
966 > strip =
967 > EOF
967 > EOF
968 $ echo "aaa" >> a
968 $ echo "aaa" >> a
969 $ hg commit -A -m 0
969 $ hg commit -A -m 0
970 adding a
970 adding a
971 $ echo "bbb" >> b
971 $ echo "bbb" >> b
972 $ hg commit -A -m 1
972 $ hg commit -A -m 1
973 adding b
973 adding b
974 $ echo "ccc" >> c
974 $ echo "ccc" >> c
975 $ hg commit -A -m 2
975 $ hg commit -A -m 2
976 adding c
976 adding c
977 $ hg update -r 1
977 $ hg update -r 1
978 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
978 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
979 $ echo "ddd" >> d
979 $ echo "ddd" >> d
980 $ hg commit -A -m 3
980 $ hg commit -A -m 3
981 adding d
981 adding d
982 created new head
982 created new head
983 $ hg update -r 2
983 $ hg update -r 2
984 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
984 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
985 $ hg log -G
985 $ hg log -G
986 o changeset: 3:8bd3e1f196af
986 o changeset: 3:8bd3e1f196af
987 | tag: tip
987 | tag: tip
988 | parent: 1:a01eca7af26d
988 | parent: 1:a01eca7af26d
989 | user: test
989 | user: test
990 | date: Thu Jan 01 00:00:00 1970 +0000
990 | date: Thu Jan 01 00:00:00 1970 +0000
991 | summary: 3
991 | summary: 3
992 |
992 |
993 | @ changeset: 2:4652c276ac4f
993 | @ changeset: 2:4652c276ac4f
994 |/ user: test
994 |/ user: test
995 | date: Thu Jan 01 00:00:00 1970 +0000
995 | date: Thu Jan 01 00:00:00 1970 +0000
996 | summary: 2
996 | summary: 2
997 |
997 |
998 o changeset: 1:a01eca7af26d
998 o changeset: 1:a01eca7af26d
999 | user: test
999 | user: test
1000 | date: Thu Jan 01 00:00:00 1970 +0000
1000 | date: Thu Jan 01 00:00:00 1970 +0000
1001 | summary: 1
1001 | summary: 1
1002 |
1002 |
1003 o changeset: 0:4fe08cd4693e
1003 o changeset: 0:4fe08cd4693e
1004 user: test
1004 user: test
1005 date: Thu Jan 01 00:00:00 1970 +0000
1005 date: Thu Jan 01 00:00:00 1970 +0000
1006 summary: 0
1006 summary: 0
1007
1007
1008
1008
1009 #if repobundlerepo
1009 #if repobundlerepo
1010 $ hg bundle --base 1 -r 3 ../update2bundled.hg
1010 $ hg bundle --base 1 -r 3 ../update2bundled.hg
1011 1 changesets found
1011 1 changesets found
1012 $ hg strip -r 3
1012 $ hg strip -r 3
1013 saved backup bundle to $TESTTMP/update2bundled/.hg/strip-backup/8bd3e1f196af-017e56d8-backup.hg
1013 saved backup bundle to $TESTTMP/update2bundled/.hg/strip-backup/8bd3e1f196af-017e56d8-backup.hg
1014 $ hg merge -R ../update2bundled.hg -r 3
1014 $ hg merge -R ../update2bundled.hg -r 3
1015 setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle
1015 setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle
1016 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1016 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1017 (branch merge, don't forget to commit)
1017 (branch merge, don't forget to commit)
1018
1018
1019 When user updates to the revision existing only in the bundle,
1019 When user updates to the revision existing only in the bundle,
1020 it should show warning
1020 it should show warning
1021
1021
1022 $ hg update -R ../update2bundled.hg --clean -r 3
1022 $ hg update -R ../update2bundled.hg --clean -r 3
1023 setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle
1023 setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle
1024 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1024 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1025
1025
1026 When user updates to the revision existing in the local repository
1026 When user updates to the revision existing in the local repository
1027 the warning shouldn't be emitted
1027 the warning shouldn't be emitted
1028
1028
1029 $ hg update -R ../update2bundled.hg -r 0
1029 $ hg update -R ../update2bundled.hg -r 0
1030 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1030 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1031 #endif
1031 #endif
1032
1032
1033 Test the option that create slim bundle
1033 Test the option that create slim bundle
1034
1034
1035 $ hg bundle -a --config devel.bundle.delta=p1 ./slim.hg
1035 $ hg bundle -a --config devel.bundle.delta=p1 ./slim.hg
1036 3 changesets found
1036 3 changesets found
1037
1037
1038 Test the option that create and no-delta's bundle
1038 Test the option that create and no-delta's bundle
1039 $ hg bundle -a --config devel.bundle.delta=full ./full.hg
1039 $ hg bundle -a --config devel.bundle.delta=full ./full.hg
1040 3 changesets found
1040 3 changesets found
1041
1041
1042 Test the debug output when applying delta
1042 Test the debug output when applying delta
1043 -----------------------------------------
1043 -----------------------------------------
1044
1044
1045 $ hg init foo
1045 $ hg init foo
1046 $ hg -R foo unbundle ./slim.hg \
1046 $ hg -R foo unbundle ./slim.hg \
1047 > --config debug.revlog.debug-delta=yes \
1047 > --config debug.revlog.debug-delta=yes \
1048 > --config storage.revlog.reuse-external-delta=no \
1048 > --config storage.revlog.reuse-external-delta=no \
1049 > --config storage.revlog.reuse-external-delta-parent=no
1049 > --config storage.revlog.reuse-external-delta-parent=no
1050 adding changesets
1050 adding changesets
1051 DBG-DELTAS: CHANGELOG: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1051 DBG-DELTAS: CHANGELOG: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1052 DBG-DELTAS: CHANGELOG: rev=1: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=0 p2-chain-length=-1 - duration=* (glob)
1052 DBG-DELTAS: CHANGELOG: rev=1: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=0 p2-chain-length=-1 - duration=* (glob)
1053 DBG-DELTAS: CHANGELOG: rev=2: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=0 p2-chain-length=-1 - duration=* (glob)
1053 DBG-DELTAS: CHANGELOG: rev=2: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=0 p2-chain-length=-1 - duration=* (glob)
1054 adding manifests
1054 adding manifests
1055 DBG-DELTAS: MANIFESTLOG: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1055 DBG-DELTAS: MANIFESTLOG: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1056 DBG-DELTAS: MANIFESTLOG: rev=1: search-rounds=1 try-count=1 - delta-type=delta snap-depth=0 - p1-chain-length=0 p2-chain-length=-1 - duration=* (glob)
1056 DBG-DELTAS: MANIFESTLOG: rev=1: search-rounds=1 try-count=1 - delta-type=delta snap-depth=0 - p1-chain-length=0 p2-chain-length=-1 - duration=* (glob)
1057 DBG-DELTAS: MANIFESTLOG: rev=2: search-rounds=1 try-count=1 - delta-type=delta snap-depth=0 - p1-chain-length=1 p2-chain-length=-1 - duration=* (glob)
1057 DBG-DELTAS: MANIFESTLOG: rev=2: search-rounds=1 try-count=1 - delta-type=delta snap-depth=0 - p1-chain-length=1 p2-chain-length=-1 - duration=* (glob)
1058 adding file changes
1058 adding file changes
1059 DBG-DELTAS: FILELOG:a: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1059 DBG-DELTAS: FILELOG:a: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1060 DBG-DELTAS: FILELOG:b: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1060 DBG-DELTAS: FILELOG:b: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1061 DBG-DELTAS: FILELOG:c: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1061 DBG-DELTAS: FILELOG:c: rev=0: search-rounds=0 try-count=0 - delta-type=full snap-depth=0 - p1-chain-length=-1 p2-chain-length=-1 - duration=* (glob)
1062 added 3 changesets with 3 changes to 3 files
1062 added 3 changesets with 3 changes to 3 files
1063 new changesets 4fe08cd4693e:4652c276ac4f (3 drafts)
1063 new changesets 4fe08cd4693e:4652c276ac4f (3 drafts)
1064 (run 'hg update' to get a working copy)
1064 (run 'hg update' to get a working copy)
1065
1065
@@ -1,449 +1,449 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 purge
41 purge
42 push
42 push
43 recover
43 recover
44 remove
44 remove
45 rename
45 rename
46 resolve
46 resolve
47 revert
47 revert
48 rollback
48 rollback
49 root
49 root
50 serve
50 serve
51 shelve
51 shelve
52 status
52 status
53 summary
53 summary
54 tag
54 tag
55 tags
55 tags
56 tip
56 tip
57 unbundle
57 unbundle
58 unshelve
58 unshelve
59 update
59 update
60 verify
60 verify
61 version
61 version
62
62
63 Show all commands that start with "a"
63 Show all commands that start with "a"
64 $ hg debugcomplete a
64 $ hg debugcomplete a
65 abort
65 abort
66 add
66 add
67 addremove
67 addremove
68 annotate
68 annotate
69 archive
69 archive
70
70
71 Do not show debug commands if there are other candidates
71 Do not show debug commands if there are other candidates
72 $ hg debugcomplete d
72 $ hg debugcomplete d
73 diff
73 diff
74
74
75 Show debug commands if there are no other candidates
75 Show debug commands if there are no other candidates
76 $ hg debugcomplete debug
76 $ hg debugcomplete debug
77 debug-delta-find
77 debug-delta-find
78 debug-repair-issue6528
78 debug-repair-issue6528
79 debug-revlog-index
79 debug-revlog-index
80 debugancestor
80 debugancestor
81 debugantivirusrunning
81 debugantivirusrunning
82 debugapplystreamclonebundle
82 debugapplystreamclonebundle
83 debugbackupbundle
83 debugbackupbundle
84 debugbuilddag
84 debugbuilddag
85 debugbundle
85 debugbundle
86 debugcapabilities
86 debugcapabilities
87 debugchangedfiles
87 debugchangedfiles
88 debugcheckstate
88 debugcheckstate
89 debugcolor
89 debugcolor
90 debugcommands
90 debugcommands
91 debugcomplete
91 debugcomplete
92 debugconfig
92 debugconfig
93 debugcreatestreamclonebundle
93 debugcreatestreamclonebundle
94 debugdag
94 debugdag
95 debugdata
95 debugdata
96 debugdate
96 debugdate
97 debugdeltachain
97 debugdeltachain
98 debugdirstate
98 debugdirstate
99 debugdirstateignorepatternshash
99 debugdirstateignorepatternshash
100 debugdiscovery
100 debugdiscovery
101 debugdownload
101 debugdownload
102 debugextensions
102 debugextensions
103 debugfileset
103 debugfileset
104 debugformat
104 debugformat
105 debugfsinfo
105 debugfsinfo
106 debuggetbundle
106 debuggetbundle
107 debugignore
107 debugignore
108 debugindexdot
108 debugindexdot
109 debugindexstats
109 debugindexstats
110 debuginstall
110 debuginstall
111 debugknown
111 debugknown
112 debuglabelcomplete
112 debuglabelcomplete
113 debuglocks
113 debuglocks
114 debugmanifestfulltextcache
114 debugmanifestfulltextcache
115 debugmergestate
115 debugmergestate
116 debugnamecomplete
116 debugnamecomplete
117 debugnodemap
117 debugnodemap
118 debugobsolete
118 debugobsolete
119 debugp1copies
119 debugp1copies
120 debugp2copies
120 debugp2copies
121 debugpathcomplete
121 debugpathcomplete
122 debugpathcopies
122 debugpathcopies
123 debugpeer
123 debugpeer
124 debugpickmergetool
124 debugpickmergetool
125 debugpushkey
125 debugpushkey
126 debugpvec
126 debugpvec
127 debugrebuilddirstate
127 debugrebuilddirstate
128 debugrebuildfncache
128 debugrebuildfncache
129 debugrename
129 debugrename
130 debugrequires
130 debugrequires
131 debugrevlog
131 debugrevlog
132 debugrevlogindex
132 debugrevlogindex
133 debugrevspec
133 debugrevspec
134 debugserve
134 debugserve
135 debugsetparents
135 debugsetparents
136 debugshell
136 debugshell
137 debugsidedata
137 debugsidedata
138 debugssl
138 debugssl
139 debugstrip
139 debugstrip
140 debugsub
140 debugsub
141 debugsuccessorssets
141 debugsuccessorssets
142 debugtagscache
142 debugtagscache
143 debugtemplate
143 debugtemplate
144 debuguigetpass
144 debuguigetpass
145 debuguiprompt
145 debuguiprompt
146 debugupdatecaches
146 debugupdatecaches
147 debugupgraderepo
147 debugupgraderepo
148 debugwalk
148 debugwalk
149 debugwhyunstable
149 debugwhyunstable
150 debugwireargs
150 debugwireargs
151 debugwireproto
151 debugwireproto
152
152
153 Do not show the alias of a debug command if there are other candidates
153 Do not show the alias of a debug command if there are other candidates
154 (this should hide rawcommit)
154 (this should hide rawcommit)
155 $ hg debugcomplete r
155 $ hg debugcomplete r
156 recover
156 recover
157 remove
157 remove
158 rename
158 rename
159 resolve
159 resolve
160 revert
160 revert
161 rollback
161 rollback
162 root
162 root
163 Show the alias of a debug command if there are no other candidates
163 Show the alias of a debug command if there are no other candidates
164 $ hg debugcomplete rawc
164 $ hg debugcomplete rawc
165
165
166
166
167 Show the global options
167 Show the global options
168 $ hg debugcomplete --options | sort
168 $ hg debugcomplete --options | sort
169 --color
169 --color
170 --config
170 --config
171 --cwd
171 --cwd
172 --debug
172 --debug
173 --debugger
173 --debugger
174 --encoding
174 --encoding
175 --encodingmode
175 --encodingmode
176 --help
176 --help
177 --hidden
177 --hidden
178 --noninteractive
178 --noninteractive
179 --pager
179 --pager
180 --profile
180 --profile
181 --quiet
181 --quiet
182 --repository
182 --repository
183 --time
183 --time
184 --traceback
184 --traceback
185 --verbose
185 --verbose
186 --version
186 --version
187 -R
187 -R
188 -h
188 -h
189 -q
189 -q
190 -v
190 -v
191 -y
191 -y
192
192
193 Show the options for the "serve" command
193 Show the options for the "serve" command
194 $ hg debugcomplete --options serve | sort
194 $ hg debugcomplete --options serve | sort
195 --accesslog
195 --accesslog
196 --address
196 --address
197 --certificate
197 --certificate
198 --cmdserver
198 --cmdserver
199 --color
199 --color
200 --config
200 --config
201 --cwd
201 --cwd
202 --daemon
202 --daemon
203 --daemon-postexec
203 --daemon-postexec
204 --debug
204 --debug
205 --debugger
205 --debugger
206 --encoding
206 --encoding
207 --encodingmode
207 --encodingmode
208 --errorlog
208 --errorlog
209 --help
209 --help
210 --hidden
210 --hidden
211 --ipv6
211 --ipv6
212 --name
212 --name
213 --noninteractive
213 --noninteractive
214 --pager
214 --pager
215 --pid-file
215 --pid-file
216 --port
216 --port
217 --prefix
217 --prefix
218 --print-url
218 --print-url
219 --profile
219 --profile
220 --quiet
220 --quiet
221 --repository
221 --repository
222 --stdio
222 --stdio
223 --style
223 --style
224 --subrepos
224 --subrepos
225 --templates
225 --templates
226 --time
226 --time
227 --traceback
227 --traceback
228 --verbose
228 --verbose
229 --version
229 --version
230 --web-conf
230 --web-conf
231 -6
231 -6
232 -A
232 -A
233 -E
233 -E
234 -R
234 -R
235 -S
235 -S
236 -a
236 -a
237 -d
237 -d
238 -h
238 -h
239 -n
239 -n
240 -p
240 -p
241 -q
241 -q
242 -t
242 -t
243 -v
243 -v
244 -y
244 -y
245
245
246 Show an error if we use --options with an ambiguous abbreviation
246 Show an error if we use --options with an ambiguous abbreviation
247 $ hg debugcomplete --options s
247 $ hg debugcomplete --options s
248 hg: command 's' is ambiguous:
248 hg: command 's' is ambiguous:
249 serve shelve showconfig status summary
249 serve shelve showconfig status summary
250 [10]
250 [10]
251
251
252 Show all commands + options
252 Show all commands + options
253 $ hg debugcommands
253 $ hg debugcommands
254 abort: dry-run
254 abort: dry-run
255 add: include, exclude, subrepos, dry-run
255 add: include, exclude, subrepos, dry-run
256 addremove: similarity, subrepos, include, exclude, dry-run
256 addremove: similarity, subrepos, include, exclude, dry-run
257 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
257 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
258 archive: no-decode, prefix, rev, type, subrepos, include, exclude
258 archive: no-decode, prefix, rev, type, subrepos, include, exclude
259 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
259 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
260 bisect: reset, good, bad, skip, extend, command, noupdate
260 bisect: reset, good, bad, skip, extend, command, noupdate
261 bookmarks: force, rev, delete, rename, inactive, list, template
261 bookmarks: force, rev, delete, rename, inactive, list, template
262 branch: force, clean, rev
262 branch: force, clean, rev
263 branches: active, closed, rev, template
263 branches: active, closed, rev, template
264 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
264 bundle: exact, force, rev, branch, base, all, type, ssh, remotecmd, insecure
265 cat: output, rev, decode, include, exclude, template
265 cat: output, rev, decode, include, exclude, template
266 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
266 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
267 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
267 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
268 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
268 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
269 continue: dry-run
269 continue: dry-run
270 copy: forget, after, at-rev, force, include, exclude, dry-run
270 copy: forget, after, at-rev, force, include, exclude, dry-run
271 debug-delta-find: changelog, manifest, dir, template
271 debug-delta-find: changelog, manifest, dir, template
272 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
272 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
273 debug-revlog-index: changelog, manifest, dir, template
273 debug-revlog-index: changelog, manifest, dir, template
274 debugancestor:
274 debugancestor:
275 debugantivirusrunning:
275 debugantivirusrunning:
276 debugapplystreamclonebundle:
276 debugapplystreamclonebundle:
277 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
277 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
278 debugbuilddag: mergeable-file, overwritten-file, new-file, from-existing
278 debugbuilddag: mergeable-file, overwritten-file, new-file, from-existing
279 debugbundle: all, part-type, spec
279 debugbundle: all, part-type, spec
280 debugcapabilities:
280 debugcapabilities:
281 debugchangedfiles: compute
281 debugchangedfiles: compute
282 debugcheckstate:
282 debugcheckstate:
283 debugcolor: style
283 debugcolor: style
284 debugcommands:
284 debugcommands:
285 debugcomplete: options
285 debugcomplete: options
286 debugcreatestreamclonebundle:
286 debugcreatestreamclonebundle:
287 debugdag: tags, branches, dots, spaces
287 debugdag: tags, branches, dots, spaces
288 debugdata: changelog, manifest, dir
288 debugdata: changelog, manifest, dir
289 debugdate: extended
289 debugdate: extended
290 debugdeltachain: changelog, manifest, dir, template
290 debugdeltachain: changelog, manifest, dir, template
291 debugdirstateignorepatternshash:
291 debugdirstateignorepatternshash:
292 debugdirstate: nodates, dates, datesort, docket, all
292 debugdirstate: nodates, dates, datesort, docket, all
293 debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template
293 debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template
294 debugdownload: output
294 debugdownload: output
295 debugextensions: template
295 debugextensions: template
296 debugfileset: rev, all-files, show-matcher, show-stage
296 debugfileset: rev, all-files, show-matcher, show-stage
297 debugformat: template
297 debugformat: template
298 debugfsinfo:
298 debugfsinfo:
299 debuggetbundle: head, common, type
299 debuggetbundle: head, common, type
300 debugignore:
300 debugignore:
301 debugindexdot: changelog, manifest, dir
301 debugindexdot: changelog, manifest, dir
302 debugindexstats:
302 debugindexstats:
303 debuginstall: template
303 debuginstall: template
304 debugknown:
304 debugknown:
305 debuglabelcomplete:
305 debuglabelcomplete:
306 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
306 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
307 debugmanifestfulltextcache: clear, add
307 debugmanifestfulltextcache: clear, add
308 debugmergestate: style, template
308 debugmergestate: style, template
309 debugnamecomplete:
309 debugnamecomplete:
310 debugnodemap: dump-new, dump-disk, check, metadata
310 debugnodemap: dump-new, dump-disk, check, metadata
311 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
311 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
312 debugp1copies: rev
312 debugp1copies: rev
313 debugp2copies: rev
313 debugp2copies: rev
314 debugpathcomplete: full, normal, added, removed
314 debugpathcomplete: full, normal, added, removed
315 debugpathcopies: include, exclude
315 debugpathcopies: include, exclude
316 debugpeer:
316 debugpeer:
317 debugpickmergetool: rev, changedelete, include, exclude, tool
317 debugpickmergetool: rev, changedelete, include, exclude, tool
318 debugpushkey:
318 debugpushkey:
319 debugpvec:
319 debugpvec:
320 debugrebuilddirstate: rev, minimal
320 debugrebuilddirstate: rev, minimal
321 debugrebuildfncache: only-data
321 debugrebuildfncache: only-data
322 debugrename: rev
322 debugrename: rev
323 debugrequires:
323 debugrequires:
324 debugrevlog: changelog, manifest, dir, dump
324 debugrevlog: changelog, manifest, dir, dump
325 debugrevlogindex: changelog, manifest, dir, format
325 debugrevlogindex: changelog, manifest, dir, format
326 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
326 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
327 debugserve: sshstdio, logiofd, logiofile
327 debugserve: sshstdio, logiofd, logiofile
328 debugsetparents:
328 debugsetparents:
329 debugshell:
329 debugshell:
330 debugsidedata: changelog, manifest, dir
330 debugsidedata: changelog, manifest, dir
331 debugssl:
331 debugssl:
332 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
332 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
333 debugsub: rev
333 debugsub: rev
334 debugsuccessorssets: closest
334 debugsuccessorssets: closest
335 debugtagscache:
335 debugtagscache:
336 debugtemplate: rev, define
336 debugtemplate: rev, define
337 debuguigetpass: prompt
337 debuguigetpass: prompt
338 debuguiprompt: prompt
338 debuguiprompt: prompt
339 debugupdatecaches:
339 debugupdatecaches:
340 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
340 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
341 debugwalk: include, exclude
341 debugwalk: include, exclude
342 debugwhyunstable:
342 debugwhyunstable:
343 debugwireargs: three, four, five, ssh, remotecmd, insecure
343 debugwireargs: three, four, five, ssh, remotecmd, insecure
344 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
344 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
345 diff: rev, from, to, 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
345 diff: rev, from, to, 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
346 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
346 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
347 files: rev, print0, include, exclude, template, subrepos
347 files: rev, print0, include, exclude, template, subrepos
348 forget: interactive, include, exclude, dry-run
348 forget: interactive, include, exclude, dry-run
349 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
349 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
350 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
350 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
351 heads: rev, topo, active, closed, style, template
351 heads: rev, topo, active, closed, style, template
352 help: extension, command, keyword, system
352 help: extension, command, keyword, system
353 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
353 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
354 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
354 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
355 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
355 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
356 init: ssh, remotecmd, insecure
356 init: ssh, remotecmd, insecure
357 locate: rev, print0, fullpath, include, exclude
357 locate: rev, print0, fullpath, include, exclude
358 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, bookmark, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
358 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, bookmark, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
359 manifest: rev, all, template
359 manifest: rev, all, template
360 merge: force, rev, preview, abort, tool
360 merge: force, rev, preview, abort, tool
361 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
361 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
362 parents: rev, style, template
362 parents: rev, style, template
363 paths: template
363 paths: template
364 phase: public, draft, secret, force, rev
364 phase: public, draft, secret, force, rev
365 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
365 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
366 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
366 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
367 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
367 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
368 recover: verify
368 recover: verify
369 remove: after, force, subrepos, include, exclude, dry-run
369 remove: after, force, subrepos, include, exclude, dry-run
370 rename: forget, after, at-rev, force, include, exclude, dry-run
370 rename: forget, after, at-rev, force, include, exclude, dry-run
371 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
371 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
372 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
372 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
373 rollback: dry-run, force
373 rollback: dry-run, force
374 root: template
374 root: template
375 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
375 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
376 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
376 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
377 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
377 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
378 summary: remote
378 summary: remote
379 tag: force, local, rev, remove, edit, message, date, user
379 tag: force, local, rev, remove, edit, message, date, user
380 tags: template
380 tags: template
381 tip: patch, git, style, template
381 tip: patch, git, style, template
382 unbundle: update
382 unbundle: update
383 unshelve: abort, continue, interactive, keep, name, tool, date
383 unshelve: abort, continue, interactive, keep, name, tool, date
384 update: clean, check, merge, date, rev, tool
384 update: clean, check, merge, date, rev, tool
385 verify: full
385 verify: full
386 version: template
386 version: template
387
387
388 $ hg init a
388 $ hg init a
389 $ cd a
389 $ cd a
390 $ echo fee > fee
390 $ echo fee > fee
391 $ hg ci -q -Amfee
391 $ hg ci -q -Amfee
392 $ hg tag fee
392 $ hg tag fee
393 $ mkdir fie
393 $ mkdir fie
394 $ echo dead > fie/dead
394 $ echo dead > fie/dead
395 $ echo live > fie/live
395 $ echo live > fie/live
396 $ hg bookmark fo
396 $ hg bookmark fo
397 $ hg branch -q fie
397 $ hg branch -q fie
398 $ hg ci -q -Amfie
398 $ hg ci -q -Amfie
399 $ echo fo > fo
399 $ echo fo > fo
400 $ hg branch -qf default
400 $ hg branch -qf default
401 $ hg ci -q -Amfo
401 $ hg ci -q -Amfo
402 $ echo Fum > Fum
402 $ echo Fum > Fum
403 $ hg ci -q -AmFum
403 $ hg ci -q -AmFum
404 $ hg bookmark Fum
404 $ hg bookmark Fum
405
405
406 Test debugpathcomplete
406 Test debugpathcomplete
407
407
408 $ hg debugpathcomplete f
408 $ hg debugpathcomplete f
409 fee
409 fee
410 fie
410 fie
411 fo
411 fo
412 $ hg debugpathcomplete -f f
412 $ hg debugpathcomplete -f f
413 fee
413 fee
414 fie/dead
414 fie/dead
415 fie/live
415 fie/live
416 fo
416 fo
417
417
418 $ hg rm Fum
418 $ hg rm Fum
419 $ hg debugpathcomplete -r F
419 $ hg debugpathcomplete -r F
420 Fum
420 Fum
421
421
422 Test debugnamecomplete
422 Test debugnamecomplete
423
423
424 $ hg debugnamecomplete
424 $ hg debugnamecomplete
425 Fum
425 Fum
426 default
426 default
427 fee
427 fee
428 fie
428 fie
429 fo
429 fo
430 tip
430 tip
431 $ hg debugnamecomplete f
431 $ hg debugnamecomplete f
432 fee
432 fee
433 fie
433 fie
434 fo
434 fo
435
435
436 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
436 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
437 used for completions in some shells.
437 used for completions in some shells.
438
438
439 $ hg debuglabelcomplete
439 $ hg debuglabelcomplete
440 Fum
440 Fum
441 default
441 default
442 fee
442 fee
443 fie
443 fie
444 fo
444 fo
445 tip
445 tip
446 $ hg debuglabelcomplete f
446 $ hg debuglabelcomplete f
447 fee
447 fee
448 fie
448 fie
449 fo
449 fo
General Comments 0
You need to be logged in to leave comments. Login now