##// END OF EJS Templates
debug: add a debug::unbundle command that simulate the unbundle from a push...
marmoute -
r52293:e2dfa403 default
parent child Browse files
Show More
@@ -1,8100 +1,8104 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 nullid,
16 nullid,
17 nullrev,
17 nullrev,
18 short,
18 short,
19 wdirrev,
19 wdirrev,
20 )
20 )
21 from . import (
21 from . import (
22 admin_commands as admin_commands_mod,
22 admin_commands as admin_commands_mod,
23 archival,
23 archival,
24 bookmarks,
24 bookmarks,
25 bundle2,
25 bundle2,
26 bundlecaches,
26 bundlecaches,
27 changegroup,
27 changegroup,
28 cmdutil,
28 cmdutil,
29 copies,
29 copies,
30 debugcommands as debugcommandsmod,
30 debugcommands as debugcommandsmod,
31 destutil,
31 destutil,
32 diffutil,
32 diffutil,
33 discovery,
33 discovery,
34 encoding,
34 encoding,
35 error,
35 error,
36 exchange,
36 exchange,
37 extensions,
37 extensions,
38 filemerge,
38 filemerge,
39 formatter,
39 formatter,
40 graphmod,
40 graphmod,
41 grep as grepmod,
41 grep as grepmod,
42 hbisect,
42 hbisect,
43 help,
43 help,
44 hg,
44 hg,
45 logcmdutil,
45 logcmdutil,
46 merge as mergemod,
46 merge as mergemod,
47 mergestate as mergestatemod,
47 mergestate as mergestatemod,
48 narrowspec,
48 narrowspec,
49 obsolete,
49 obsolete,
50 obsutil,
50 obsutil,
51 patch,
51 patch,
52 phases,
52 phases,
53 pycompat,
53 pycompat,
54 rcutil,
54 rcutil,
55 registrar,
55 registrar,
56 requirements,
56 requirements,
57 revsetlang,
57 revsetlang,
58 rewriteutil,
58 rewriteutil,
59 scmutil,
59 scmutil,
60 server,
60 server,
61 shelve as shelvemod,
61 shelve as shelvemod,
62 state as statemod,
62 state as statemod,
63 streamclone,
63 streamclone,
64 tags as tagsmod,
64 tags as tagsmod,
65 ui as uimod,
65 ui as uimod,
66 util,
66 util,
67 verify as verifymod,
67 verify as verifymod,
68 vfs as vfsmod,
68 vfs as vfsmod,
69 wireprotoserver,
69 wireprotoserver,
70 )
70 )
71 from .utils import (
71 from .utils import (
72 dateutil,
72 dateutil,
73 procutil,
73 procutil,
74 stringutil,
74 stringutil,
75 urlutil,
75 urlutil,
76 )
76 )
77
77
78 table = {}
78 table = {}
79 table.update(debugcommandsmod.command._table)
79 table.update(debugcommandsmod.command._table)
80 table.update(admin_commands_mod.command._table)
80 table.update(admin_commands_mod.command._table)
81
81
82 command = registrar.command(table)
82 command = registrar.command(table)
83 INTENT_READONLY = registrar.INTENT_READONLY
83 INTENT_READONLY = registrar.INTENT_READONLY
84
84
85 # common command options
85 # common command options
86
86
87 globalopts = [
87 globalopts = [
88 (
88 (
89 b'R',
89 b'R',
90 b'repository',
90 b'repository',
91 b'',
91 b'',
92 _(b'repository root directory or name of overlay bundle file'),
92 _(b'repository root directory or name of overlay bundle file'),
93 _(b'REPO'),
93 _(b'REPO'),
94 ),
94 ),
95 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
95 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
96 (
96 (
97 b'y',
97 b'y',
98 b'noninteractive',
98 b'noninteractive',
99 None,
99 None,
100 _(
100 _(
101 b'do not prompt, automatically pick the first choice for all prompts'
101 b'do not prompt, automatically pick the first choice for all prompts'
102 ),
102 ),
103 ),
103 ),
104 (b'q', b'quiet', None, _(b'suppress output')),
104 (b'q', b'quiet', None, _(b'suppress output')),
105 (b'v', b'verbose', None, _(b'enable additional output')),
105 (b'v', b'verbose', None, _(b'enable additional output')),
106 (
106 (
107 b'',
107 b'',
108 b'color',
108 b'color',
109 b'',
109 b'',
110 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
110 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
111 # and should not be translated
111 # and should not be translated
112 _(b"when to colorize (boolean, always, auto, never, or debug)"),
112 _(b"when to colorize (boolean, always, auto, never, or debug)"),
113 _(b'TYPE'),
113 _(b'TYPE'),
114 ),
114 ),
115 (
115 (
116 b'',
116 b'',
117 b'config',
117 b'config',
118 [],
118 [],
119 _(b'set/override config option (use \'section.name=value\')'),
119 _(b'set/override config option (use \'section.name=value\')'),
120 _(b'CONFIG'),
120 _(b'CONFIG'),
121 ),
121 ),
122 (b'', b'debug', None, _(b'enable debugging output')),
122 (b'', b'debug', None, _(b'enable debugging output')),
123 (b'', b'debugger', None, _(b'start debugger')),
123 (b'', b'debugger', None, _(b'start debugger')),
124 (
124 (
125 b'',
125 b'',
126 b'encoding',
126 b'encoding',
127 encoding.encoding,
127 encoding.encoding,
128 _(b'set the charset encoding'),
128 _(b'set the charset encoding'),
129 _(b'ENCODE'),
129 _(b'ENCODE'),
130 ),
130 ),
131 (
131 (
132 b'',
132 b'',
133 b'encodingmode',
133 b'encodingmode',
134 encoding.encodingmode,
134 encoding.encodingmode,
135 _(b'set the charset encoding mode'),
135 _(b'set the charset encoding mode'),
136 _(b'MODE'),
136 _(b'MODE'),
137 ),
137 ),
138 (b'', b'traceback', None, _(b'always print a traceback on exception')),
138 (b'', b'traceback', None, _(b'always print a traceback on exception')),
139 (b'', b'time', None, _(b'time how long the command takes')),
139 (b'', b'time', None, _(b'time how long the command takes')),
140 (b'', b'profile', None, _(b'print command execution profile')),
140 (b'', b'profile', None, _(b'print command execution profile')),
141 (b'', b'version', None, _(b'output version information and exit')),
141 (b'', b'version', None, _(b'output version information and exit')),
142 (b'h', b'help', None, _(b'display help and exit')),
142 (b'h', b'help', None, _(b'display help and exit')),
143 (b'', b'hidden', False, _(b'consider hidden changesets')),
143 (b'', b'hidden', False, _(b'consider hidden changesets')),
144 (
144 (
145 b'',
145 b'',
146 b'pager',
146 b'pager',
147 b'auto',
147 b'auto',
148 _(b"when to paginate (boolean, always, auto, or never)"),
148 _(b"when to paginate (boolean, always, auto, or never)"),
149 _(b'TYPE'),
149 _(b'TYPE'),
150 ),
150 ),
151 ]
151 ]
152
152
153 dryrunopts = cmdutil.dryrunopts
153 dryrunopts = cmdutil.dryrunopts
154 remoteopts = cmdutil.remoteopts
154 remoteopts = cmdutil.remoteopts
155 walkopts = cmdutil.walkopts
155 walkopts = cmdutil.walkopts
156 commitopts = cmdutil.commitopts
156 commitopts = cmdutil.commitopts
157 commitopts2 = cmdutil.commitopts2
157 commitopts2 = cmdutil.commitopts2
158 commitopts3 = cmdutil.commitopts3
158 commitopts3 = cmdutil.commitopts3
159 formatteropts = cmdutil.formatteropts
159 formatteropts = cmdutil.formatteropts
160 templateopts = cmdutil.templateopts
160 templateopts = cmdutil.templateopts
161 logopts = cmdutil.logopts
161 logopts = cmdutil.logopts
162 diffopts = cmdutil.diffopts
162 diffopts = cmdutil.diffopts
163 diffwsopts = cmdutil.diffwsopts
163 diffwsopts = cmdutil.diffwsopts
164 diffopts2 = cmdutil.diffopts2
164 diffopts2 = cmdutil.diffopts2
165 mergetoolopts = cmdutil.mergetoolopts
165 mergetoolopts = cmdutil.mergetoolopts
166 similarityopts = cmdutil.similarityopts
166 similarityopts = cmdutil.similarityopts
167 subrepoopts = cmdutil.subrepoopts
167 subrepoopts = cmdutil.subrepoopts
168 debugrevlogopts = cmdutil.debugrevlogopts
168 debugrevlogopts = cmdutil.debugrevlogopts
169
169
170 # Commands start here, listed alphabetically
170 # Commands start here, listed alphabetically
171
171
172
172
173 @command(
173 @command(
174 b'abort',
174 b'abort',
175 dryrunopts,
175 dryrunopts,
176 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
176 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
177 helpbasic=True,
177 helpbasic=True,
178 )
178 )
179 def abort(ui, repo, **opts):
179 def abort(ui, repo, **opts):
180 """abort an unfinished operation (EXPERIMENTAL)
180 """abort an unfinished operation (EXPERIMENTAL)
181
181
182 Aborts a multistep operation like graft, histedit, rebase, merge,
182 Aborts a multistep operation like graft, histedit, rebase, merge,
183 and unshelve if they are in an unfinished state.
183 and unshelve if they are in an unfinished state.
184
184
185 use --dry-run/-n to dry run the command.
185 use --dry-run/-n to dry run the command.
186 """
186 """
187 dryrun = opts.get('dry_run')
187 dryrun = opts.get('dry_run')
188 abortstate = cmdutil.getunfinishedstate(repo)
188 abortstate = cmdutil.getunfinishedstate(repo)
189 if not abortstate:
189 if not abortstate:
190 raise error.StateError(_(b'no operation in progress'))
190 raise error.StateError(_(b'no operation in progress'))
191 if not abortstate.abortfunc:
191 if not abortstate.abortfunc:
192 raise error.InputError(
192 raise error.InputError(
193 (
193 (
194 _(b"%s in progress but does not support 'hg abort'")
194 _(b"%s in progress but does not support 'hg abort'")
195 % (abortstate._opname)
195 % (abortstate._opname)
196 ),
196 ),
197 hint=abortstate.hint(),
197 hint=abortstate.hint(),
198 )
198 )
199 if dryrun:
199 if dryrun:
200 ui.status(
200 ui.status(
201 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
201 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
202 )
202 )
203 return
203 return
204 return abortstate.abortfunc(ui, repo)
204 return abortstate.abortfunc(ui, repo)
205
205
206
206
207 @command(
207 @command(
208 b'add',
208 b'add',
209 walkopts + subrepoopts + dryrunopts,
209 walkopts + subrepoopts + dryrunopts,
210 _(b'[OPTION]... [FILE]...'),
210 _(b'[OPTION]... [FILE]...'),
211 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
211 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
212 helpbasic=True,
212 helpbasic=True,
213 inferrepo=True,
213 inferrepo=True,
214 )
214 )
215 def add(ui, repo, *pats, **opts):
215 def add(ui, repo, *pats, **opts):
216 """add the specified files on the next commit
216 """add the specified files on the next commit
217
217
218 Schedule files to be version controlled and added to the
218 Schedule files to be version controlled and added to the
219 repository.
219 repository.
220
220
221 The files will be added to the repository at the next commit. To
221 The files will be added to the repository at the next commit. To
222 undo an add before that, see :hg:`forget`.
222 undo an add before that, see :hg:`forget`.
223
223
224 If no names are given, add all files to the repository (except
224 If no names are given, add all files to the repository (except
225 files matching ``.hgignore``).
225 files matching ``.hgignore``).
226
226
227 .. container:: verbose
227 .. container:: verbose
228
228
229 Examples:
229 Examples:
230
230
231 - New (unknown) files are added
231 - New (unknown) files are added
232 automatically by :hg:`add`::
232 automatically by :hg:`add`::
233
233
234 $ ls
234 $ ls
235 foo.c
235 foo.c
236 $ hg status
236 $ hg status
237 ? foo.c
237 ? foo.c
238 $ hg add
238 $ hg add
239 adding foo.c
239 adding foo.c
240 $ hg status
240 $ hg status
241 A foo.c
241 A foo.c
242
242
243 - Specific files to be added can be specified::
243 - Specific files to be added can be specified::
244
244
245 $ ls
245 $ ls
246 bar.c foo.c
246 bar.c foo.c
247 $ hg status
247 $ hg status
248 ? bar.c
248 ? bar.c
249 ? foo.c
249 ? foo.c
250 $ hg add bar.c
250 $ hg add bar.c
251 $ hg status
251 $ hg status
252 A bar.c
252 A bar.c
253 ? foo.c
253 ? foo.c
254
254
255 Returns 0 if all files are successfully added.
255 Returns 0 if all files are successfully added.
256 """
256 """
257
257
258 with repo.wlock(), repo.dirstate.changing_files(repo):
258 with repo.wlock(), repo.dirstate.changing_files(repo):
259 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
259 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
260 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
260 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
261 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
261 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
262 return rejected and 1 or 0
262 return rejected and 1 or 0
263
263
264
264
265 @command(
265 @command(
266 b'addremove',
266 b'addremove',
267 similarityopts + subrepoopts + walkopts + dryrunopts,
267 similarityopts + subrepoopts + walkopts + dryrunopts,
268 _(b'[OPTION]... [FILE]...'),
268 _(b'[OPTION]... [FILE]...'),
269 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
269 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
270 inferrepo=True,
270 inferrepo=True,
271 )
271 )
272 def addremove(ui, repo, *pats, **opts):
272 def addremove(ui, repo, *pats, **opts):
273 """add all new files, delete all missing files
273 """add all new files, delete all missing files
274
274
275 Add all new files and remove all missing files from the
275 Add all new files and remove all missing files from the
276 repository.
276 repository.
277
277
278 Unless names are given, new files are ignored if they match any of
278 Unless names are given, new files are ignored if they match any of
279 the patterns in ``.hgignore``. As with add, these changes take
279 the patterns in ``.hgignore``. As with add, these changes take
280 effect at the next commit.
280 effect at the next commit.
281
281
282 Use the -s/--similarity option to detect renamed files. This
282 Use the -s/--similarity option to detect renamed files. This
283 option takes a percentage between 0 (disabled) and 100 (files must
283 option takes a percentage between 0 (disabled) and 100 (files must
284 be identical) as its parameter. With a parameter greater than 0,
284 be identical) as its parameter. With a parameter greater than 0,
285 this compares every removed file with every added file and records
285 this compares every removed file with every added file and records
286 those similar enough as renames. Detecting renamed files this way
286 those similar enough as renames. Detecting renamed files this way
287 can be expensive. After using this option, :hg:`status -C` can be
287 can be expensive. After using this option, :hg:`status -C` can be
288 used to check which files were identified as moved or renamed. If
288 used to check which files were identified as moved or renamed. If
289 not specified, -s/--similarity defaults to 100 and only renames of
289 not specified, -s/--similarity defaults to 100 and only renames of
290 identical files are detected.
290 identical files are detected.
291
291
292 .. container:: verbose
292 .. container:: verbose
293
293
294 Examples:
294 Examples:
295
295
296 - A number of files (bar.c and foo.c) are new,
296 - A number of files (bar.c and foo.c) are new,
297 while foobar.c has been removed (without using :hg:`remove`)
297 while foobar.c has been removed (without using :hg:`remove`)
298 from the repository::
298 from the repository::
299
299
300 $ ls
300 $ ls
301 bar.c foo.c
301 bar.c foo.c
302 $ hg status
302 $ hg status
303 ! foobar.c
303 ! foobar.c
304 ? bar.c
304 ? bar.c
305 ? foo.c
305 ? foo.c
306 $ hg addremove
306 $ hg addremove
307 adding bar.c
307 adding bar.c
308 adding foo.c
308 adding foo.c
309 removing foobar.c
309 removing foobar.c
310 $ hg status
310 $ hg status
311 A bar.c
311 A bar.c
312 A foo.c
312 A foo.c
313 R foobar.c
313 R foobar.c
314
314
315 - A file foobar.c was moved to foo.c without using :hg:`rename`.
315 - A file foobar.c was moved to foo.c without using :hg:`rename`.
316 Afterwards, it was edited slightly::
316 Afterwards, it was edited slightly::
317
317
318 $ ls
318 $ ls
319 foo.c
319 foo.c
320 $ hg status
320 $ hg status
321 ! foobar.c
321 ! foobar.c
322 ? foo.c
322 ? foo.c
323 $ hg addremove --similarity 90
323 $ hg addremove --similarity 90
324 removing foobar.c
324 removing foobar.c
325 adding foo.c
325 adding foo.c
326 recording removal of foobar.c as rename to foo.c (94% similar)
326 recording removal of foobar.c as rename to foo.c (94% similar)
327 $ hg status -C
327 $ hg status -C
328 A foo.c
328 A foo.c
329 foobar.c
329 foobar.c
330 R foobar.c
330 R foobar.c
331
331
332 Returns 0 if all files are successfully added.
332 Returns 0 if all files are successfully added.
333 """
333 """
334 opts = pycompat.byteskwargs(opts)
334 opts = pycompat.byteskwargs(opts)
335 if not opts.get(b'similarity'):
335 if not opts.get(b'similarity'):
336 opts[b'similarity'] = b'100'
336 opts[b'similarity'] = b'100'
337 with repo.wlock(), repo.dirstate.changing_files(repo):
337 with repo.wlock(), repo.dirstate.changing_files(repo):
338 matcher = scmutil.match(repo[None], pats, opts)
338 matcher = scmutil.match(repo[None], pats, opts)
339 relative = scmutil.anypats(pats, opts)
339 relative = scmutil.anypats(pats, opts)
340 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
340 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
341 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
341 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
342
342
343
343
344 @command(
344 @command(
345 b'annotate|blame',
345 b'annotate|blame',
346 [
346 [
347 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
347 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
348 (
348 (
349 b'',
349 b'',
350 b'follow',
350 b'follow',
351 None,
351 None,
352 _(b'follow copies/renames and list the filename (DEPRECATED)'),
352 _(b'follow copies/renames and list the filename (DEPRECATED)'),
353 ),
353 ),
354 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
354 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
355 (b'a', b'text', None, _(b'treat all files as text')),
355 (b'a', b'text', None, _(b'treat all files as text')),
356 (b'u', b'user', None, _(b'list the author (long with -v)')),
356 (b'u', b'user', None, _(b'list the author (long with -v)')),
357 (b'f', b'file', None, _(b'list the filename')),
357 (b'f', b'file', None, _(b'list the filename')),
358 (b'd', b'date', None, _(b'list the date (short with -q)')),
358 (b'd', b'date', None, _(b'list the date (short with -q)')),
359 (b'n', b'number', None, _(b'list the revision number (default)')),
359 (b'n', b'number', None, _(b'list the revision number (default)')),
360 (b'c', b'changeset', None, _(b'list the changeset')),
360 (b'c', b'changeset', None, _(b'list the changeset')),
361 (
361 (
362 b'l',
362 b'l',
363 b'line-number',
363 b'line-number',
364 None,
364 None,
365 _(b'show line number at the first appearance'),
365 _(b'show line number at the first appearance'),
366 ),
366 ),
367 (
367 (
368 b'',
368 b'',
369 b'skip',
369 b'skip',
370 [],
370 [],
371 _(b'revset to not display (EXPERIMENTAL)'),
371 _(b'revset to not display (EXPERIMENTAL)'),
372 _(b'REV'),
372 _(b'REV'),
373 ),
373 ),
374 (
374 (
375 b'L',
375 b'L',
376 b'line-range',
376 b'line-range',
377 [],
377 [],
378 _(b'follow line range of specified file (EXPERIMENTAL)'),
378 _(b'follow line range of specified file (EXPERIMENTAL)'),
379 _(b'FILE,RANGE'),
379 _(b'FILE,RANGE'),
380 ),
380 ),
381 ]
381 ]
382 + diffwsopts
382 + diffwsopts
383 + walkopts
383 + walkopts
384 + formatteropts,
384 + formatteropts,
385 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
385 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
386 helpcategory=command.CATEGORY_FILE_CONTENTS,
386 helpcategory=command.CATEGORY_FILE_CONTENTS,
387 helpbasic=True,
387 helpbasic=True,
388 inferrepo=True,
388 inferrepo=True,
389 )
389 )
390 def annotate(ui, repo, *pats, **opts):
390 def annotate(ui, repo, *pats, **opts):
391 """show changeset information by line for each file
391 """show changeset information by line for each file
392
392
393 List changes in files, showing the revision id responsible for
393 List changes in files, showing the revision id responsible for
394 each line.
394 each line.
395
395
396 This command is useful for discovering when a change was made and
396 This command is useful for discovering when a change was made and
397 by whom.
397 by whom.
398
398
399 If you include --file, --user, or --date, the revision number is
399 If you include --file, --user, or --date, the revision number is
400 suppressed unless you also include --number.
400 suppressed unless you also include --number.
401
401
402 Without the -a/--text option, annotate will avoid processing files
402 Without the -a/--text option, annotate will avoid processing files
403 it detects as binary. With -a, annotate will annotate the file
403 it detects as binary. With -a, annotate will annotate the file
404 anyway, although the results will probably be neither useful
404 anyway, although the results will probably be neither useful
405 nor desirable.
405 nor desirable.
406
406
407 .. container:: verbose
407 .. container:: verbose
408
408
409 Use -L/--line-range FILE,M:N options to filter the output to the lines
409 Use -L/--line-range FILE,M:N options to filter the output to the lines
410 from M to N in FILE. This option is incompatible with --no-follow and
410 from M to N in FILE. This option is incompatible with --no-follow and
411 cannot be combined with file pattern arguments. When combined with --rev
411 cannot be combined with file pattern arguments. When combined with --rev
412 the line ranges refer to the state of the file at the requested revision.
412 the line ranges refer to the state of the file at the requested revision.
413
413
414 .. container:: verbose
414 .. container:: verbose
415
415
416 Template:
416 Template:
417
417
418 The following keywords are supported in addition to the common template
418 The following keywords are supported in addition to the common template
419 keywords and functions. See also :hg:`help templates`.
419 keywords and functions. See also :hg:`help templates`.
420
420
421 :lines: List of lines with annotation data.
421 :lines: List of lines with annotation data.
422 :path: String. Repository-absolute path of the specified file.
422 :path: String. Repository-absolute path of the specified file.
423
423
424 And each entry of ``{lines}`` provides the following sub-keywords in
424 And each entry of ``{lines}`` provides the following sub-keywords in
425 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
425 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
426
426
427 :line: String. Line content.
427 :line: String. Line content.
428 :lineno: Integer. Line number at that revision.
428 :lineno: Integer. Line number at that revision.
429 :path: String. Repository-absolute path of the file at that revision.
429 :path: String. Repository-absolute path of the file at that revision.
430
430
431 See :hg:`help templates.operators` for the list expansion syntax.
431 See :hg:`help templates.operators` for the list expansion syntax.
432
432
433 Returns 0 on success.
433 Returns 0 on success.
434 """
434 """
435 opts = pycompat.byteskwargs(opts)
435 opts = pycompat.byteskwargs(opts)
436
436
437 linerange = opts.get(b'line_range')
437 linerange = opts.get(b'line_range')
438
438
439 if linerange and opts.get(b'no_follow'):
439 if linerange and opts.get(b'no_follow'):
440 raise error.InputError(
440 raise error.InputError(
441 _(b'--line-range is incompatible with --no-follow')
441 _(b'--line-range is incompatible with --no-follow')
442 )
442 )
443
443
444 if pats and linerange:
444 if pats and linerange:
445 raise error.InputError(
445 raise error.InputError(
446 _(b'cannot combine filename or pattern and --line-range')
446 _(b'cannot combine filename or pattern and --line-range')
447 )
447 )
448
448
449 if not pats and not linerange:
449 if not pats and not linerange:
450 raise error.InputError(
450 raise error.InputError(
451 _(b'at least one filename or pattern is required')
451 _(b'at least one filename or pattern is required')
452 )
452 )
453
453
454 if opts.get(b'follow'):
454 if opts.get(b'follow'):
455 # --follow is deprecated and now just an alias for -f/--file
455 # --follow is deprecated and now just an alias for -f/--file
456 # to mimic the behavior of Mercurial before version 1.5
456 # to mimic the behavior of Mercurial before version 1.5
457 opts[b'file'] = True
457 opts[b'file'] = True
458
458
459 if (
459 if (
460 not opts.get(b'user')
460 not opts.get(b'user')
461 and not opts.get(b'changeset')
461 and not opts.get(b'changeset')
462 and not opts.get(b'date')
462 and not opts.get(b'date')
463 and not opts.get(b'file')
463 and not opts.get(b'file')
464 ):
464 ):
465 opts[b'number'] = True
465 opts[b'number'] = True
466
466
467 linenumber = opts.get(b'line_number') is not None
467 linenumber = opts.get(b'line_number') is not None
468 if (
468 if (
469 linenumber
469 linenumber
470 and (not opts.get(b'changeset'))
470 and (not opts.get(b'changeset'))
471 and (not opts.get(b'number'))
471 and (not opts.get(b'number'))
472 ):
472 ):
473 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
473 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
474
474
475 rev = opts.get(b'rev')
475 rev = opts.get(b'rev')
476 if rev:
476 if rev:
477 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
477 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
478 ctx = logcmdutil.revsingle(repo, rev)
478 ctx = logcmdutil.revsingle(repo, rev)
479
479
480 if not pats:
480 if not pats:
481 pats = [
481 pats = [
482 fname
482 fname
483 for fname, _ranges in logcmdutil._parselinerangeopt(repo, opts)
483 for fname, _ranges in logcmdutil._parselinerangeopt(repo, opts)
484 ]
484 ]
485
485
486 ui.pager(b'annotate')
486 ui.pager(b'annotate')
487 rootfm = ui.formatter(b'annotate', opts)
487 rootfm = ui.formatter(b'annotate', opts)
488 if ui.debugflag:
488 if ui.debugflag:
489 shorthex = pycompat.identity
489 shorthex = pycompat.identity
490 else:
490 else:
491
491
492 def shorthex(h):
492 def shorthex(h):
493 return h[:12]
493 return h[:12]
494
494
495 if ui.quiet:
495 if ui.quiet:
496 datefunc = dateutil.shortdate
496 datefunc = dateutil.shortdate
497 else:
497 else:
498 datefunc = dateutil.datestr
498 datefunc = dateutil.datestr
499 if ctx.rev() is None:
499 if ctx.rev() is None:
500 if opts.get(b'changeset'):
500 if opts.get(b'changeset'):
501 # omit "+" suffix which is appended to node hex
501 # omit "+" suffix which is appended to node hex
502 def formatrev(rev):
502 def formatrev(rev):
503 if rev == wdirrev:
503 if rev == wdirrev:
504 return b'%d' % ctx.p1().rev()
504 return b'%d' % ctx.p1().rev()
505 else:
505 else:
506 return b'%d' % rev
506 return b'%d' % rev
507
507
508 else:
508 else:
509
509
510 def formatrev(rev):
510 def formatrev(rev):
511 if rev == wdirrev:
511 if rev == wdirrev:
512 return b'%d+' % ctx.p1().rev()
512 return b'%d+' % ctx.p1().rev()
513 else:
513 else:
514 return b'%d ' % rev
514 return b'%d ' % rev
515
515
516 def formathex(h):
516 def formathex(h):
517 if h == repo.nodeconstants.wdirhex:
517 if h == repo.nodeconstants.wdirhex:
518 return b'%s+' % shorthex(hex(ctx.p1().node()))
518 return b'%s+' % shorthex(hex(ctx.p1().node()))
519 else:
519 else:
520 return b'%s ' % shorthex(h)
520 return b'%s ' % shorthex(h)
521
521
522 else:
522 else:
523 formatrev = b'%d'.__mod__
523 formatrev = b'%d'.__mod__
524 formathex = shorthex
524 formathex = shorthex
525
525
526 opmap = [
526 opmap = [
527 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
527 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
528 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
528 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
529 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
529 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
530 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
530 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
531 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
531 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
532 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
532 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
533 ]
533 ]
534 opnamemap = {
534 opnamemap = {
535 b'rev': b'number',
535 b'rev': b'number',
536 b'node': b'changeset',
536 b'node': b'changeset',
537 b'path': b'file',
537 b'path': b'file',
538 b'lineno': b'line_number',
538 b'lineno': b'line_number',
539 }
539 }
540
540
541 if rootfm.isplain():
541 if rootfm.isplain():
542
542
543 def makefunc(get, fmt):
543 def makefunc(get, fmt):
544 return lambda x: fmt(get(x))
544 return lambda x: fmt(get(x))
545
545
546 else:
546 else:
547
547
548 def makefunc(get, fmt):
548 def makefunc(get, fmt):
549 return get
549 return get
550
550
551 datahint = rootfm.datahint()
551 datahint = rootfm.datahint()
552 funcmap = [
552 funcmap = [
553 (makefunc(get, fmt), sep)
553 (makefunc(get, fmt), sep)
554 for fn, sep, get, fmt in opmap
554 for fn, sep, get, fmt in opmap
555 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
555 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
556 ]
556 ]
557 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
557 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
558 fields = b' '.join(
558 fields = b' '.join(
559 fn
559 fn
560 for fn, sep, get, fmt in opmap
560 for fn, sep, get, fmt in opmap
561 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
561 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
562 )
562 )
563
563
564 def bad(x, y):
564 def bad(x, y):
565 raise error.InputError(b"%s: %s" % (x, y))
565 raise error.InputError(b"%s: %s" % (x, y))
566
566
567 m = scmutil.match(ctx, pats, opts, badfn=bad)
567 m = scmutil.match(ctx, pats, opts, badfn=bad)
568
568
569 follow = not opts.get(b'no_follow')
569 follow = not opts.get(b'no_follow')
570 diffopts = patch.difffeatureopts(
570 diffopts = patch.difffeatureopts(
571 ui, opts, section=b'annotate', whitespace=True
571 ui, opts, section=b'annotate', whitespace=True
572 )
572 )
573 skiprevs = opts.get(b'skip')
573 skiprevs = opts.get(b'skip')
574 if skiprevs:
574 if skiprevs:
575 skiprevs = logcmdutil.revrange(repo, skiprevs)
575 skiprevs = logcmdutil.revrange(repo, skiprevs)
576
576
577 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
577 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
578 for abs in ctx.walk(m):
578 for abs in ctx.walk(m):
579 fctx = ctx[abs]
579 fctx = ctx[abs]
580 rootfm.startitem()
580 rootfm.startitem()
581 rootfm.data(path=abs)
581 rootfm.data(path=abs)
582 if not opts.get(b'text') and fctx.isbinary():
582 if not opts.get(b'text') and fctx.isbinary():
583 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
583 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
584 continue
584 continue
585
585
586 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
586 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
587 lines = fctx.annotate(
587 lines = fctx.annotate(
588 follow=follow, skiprevs=skiprevs, diffopts=diffopts
588 follow=follow, skiprevs=skiprevs, diffopts=diffopts
589 )
589 )
590 if linerange:
590 if linerange:
591 _fname, (line_start, line_end) = list(
591 _fname, (line_start, line_end) = list(
592 logcmdutil._parselinerangeopt(repo, opts)
592 logcmdutil._parselinerangeopt(repo, opts)
593 )[0]
593 )[0]
594 lines = [
594 lines = [
595 line
595 line
596 for no, line in enumerate(lines)
596 for no, line in enumerate(lines)
597 if line_start <= no < line_end
597 if line_start <= no < line_end
598 ]
598 ]
599
599
600 if not lines:
600 if not lines:
601 fm.end()
601 fm.end()
602 continue
602 continue
603 formats = []
603 formats = []
604 pieces = []
604 pieces = []
605
605
606 for f, sep in funcmap:
606 for f, sep in funcmap:
607 l = [f(n) for n in lines]
607 l = [f(n) for n in lines]
608 if fm.isplain():
608 if fm.isplain():
609 sizes = [encoding.colwidth(x) for x in l]
609 sizes = [encoding.colwidth(x) for x in l]
610 ml = max(sizes)
610 ml = max(sizes)
611 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
611 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
612 else:
612 else:
613 formats.append([b'%s'] * len(l))
613 formats.append([b'%s'] * len(l))
614 pieces.append(l)
614 pieces.append(l)
615
615
616 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
616 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
617 fm.startitem()
617 fm.startitem()
618 fm.context(fctx=n.fctx)
618 fm.context(fctx=n.fctx)
619 fm.write(fields, b"".join(f), *p)
619 fm.write(fields, b"".join(f), *p)
620 if n.skip:
620 if n.skip:
621 fmt = b"* %s"
621 fmt = b"* %s"
622 else:
622 else:
623 fmt = b": %s"
623 fmt = b": %s"
624 fm.write(b'line', fmt, n.text)
624 fm.write(b'line', fmt, n.text)
625
625
626 if not lines[-1].text.endswith(b'\n'):
626 if not lines[-1].text.endswith(b'\n'):
627 fm.plain(b'\n')
627 fm.plain(b'\n')
628 fm.end()
628 fm.end()
629
629
630 rootfm.end()
630 rootfm.end()
631
631
632
632
633 @command(
633 @command(
634 b'archive',
634 b'archive',
635 [
635 [
636 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
636 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
637 (
637 (
638 b'p',
638 b'p',
639 b'prefix',
639 b'prefix',
640 b'',
640 b'',
641 _(b'directory prefix for files in archive'),
641 _(b'directory prefix for files in archive'),
642 _(b'PREFIX'),
642 _(b'PREFIX'),
643 ),
643 ),
644 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
644 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
645 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
645 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
646 ]
646 ]
647 + subrepoopts
647 + subrepoopts
648 + walkopts,
648 + walkopts,
649 _(b'[OPTION]... DEST'),
649 _(b'[OPTION]... DEST'),
650 helpcategory=command.CATEGORY_IMPORT_EXPORT,
650 helpcategory=command.CATEGORY_IMPORT_EXPORT,
651 )
651 )
652 def archive(ui, repo, dest, **opts):
652 def archive(ui, repo, dest, **opts):
653 """create an unversioned archive of a repository revision
653 """create an unversioned archive of a repository revision
654
654
655 By default, the revision used is the parent of the working
655 By default, the revision used is the parent of the working
656 directory; use -r/--rev to specify a different revision.
656 directory; use -r/--rev to specify a different revision.
657
657
658 The archive type is automatically detected based on file
658 The archive type is automatically detected based on file
659 extension (to override, use -t/--type).
659 extension (to override, use -t/--type).
660
660
661 .. container:: verbose
661 .. container:: verbose
662
662
663 Examples:
663 Examples:
664
664
665 - create a zip file containing the 1.0 release::
665 - create a zip file containing the 1.0 release::
666
666
667 hg archive -r 1.0 project-1.0.zip
667 hg archive -r 1.0 project-1.0.zip
668
668
669 - create a tarball excluding .hg files::
669 - create a tarball excluding .hg files::
670
670
671 hg archive project.tar.gz -X ".hg*"
671 hg archive project.tar.gz -X ".hg*"
672
672
673 Valid types are:
673 Valid types are:
674
674
675 :``files``: a directory full of files (default)
675 :``files``: a directory full of files (default)
676 :``tar``: tar archive, uncompressed
676 :``tar``: tar archive, uncompressed
677 :``tbz2``: tar archive, compressed using bzip2
677 :``tbz2``: tar archive, compressed using bzip2
678 :``tgz``: tar archive, compressed using gzip
678 :``tgz``: tar archive, compressed using gzip
679 :``txz``: tar archive, compressed using lzma (only in Python 3)
679 :``txz``: tar archive, compressed using lzma (only in Python 3)
680 :``uzip``: zip archive, uncompressed
680 :``uzip``: zip archive, uncompressed
681 :``zip``: zip archive, compressed using deflate
681 :``zip``: zip archive, compressed using deflate
682
682
683 The exact name of the destination archive or directory is given
683 The exact name of the destination archive or directory is given
684 using a format string; see :hg:`help export` for details.
684 using a format string; see :hg:`help export` for details.
685
685
686 Each member added to an archive file has a directory prefix
686 Each member added to an archive file has a directory prefix
687 prepended. Use -p/--prefix to specify a format string for the
687 prepended. Use -p/--prefix to specify a format string for the
688 prefix. The default is the basename of the archive, with suffixes
688 prefix. The default is the basename of the archive, with suffixes
689 removed.
689 removed.
690
690
691 Returns 0 on success.
691 Returns 0 on success.
692 """
692 """
693
693
694 rev = opts.get('rev')
694 rev = opts.get('rev')
695 if rev:
695 if rev:
696 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
696 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
697 ctx = logcmdutil.revsingle(repo, rev)
697 ctx = logcmdutil.revsingle(repo, rev)
698 if not ctx:
698 if not ctx:
699 raise error.InputError(
699 raise error.InputError(
700 _(b'no working directory: please specify a revision')
700 _(b'no working directory: please specify a revision')
701 )
701 )
702 node = ctx.node()
702 node = ctx.node()
703 dest = cmdutil.makefilename(ctx, dest)
703 dest = cmdutil.makefilename(ctx, dest)
704 if os.path.realpath(dest) == repo.root:
704 if os.path.realpath(dest) == repo.root:
705 raise error.InputError(_(b'repository root cannot be destination'))
705 raise error.InputError(_(b'repository root cannot be destination'))
706
706
707 kind = opts.get('type') or archival.guesskind(dest) or b'files'
707 kind = opts.get('type') or archival.guesskind(dest) or b'files'
708 prefix = opts.get('prefix')
708 prefix = opts.get('prefix')
709
709
710 if dest == b'-':
710 if dest == b'-':
711 if kind == b'files':
711 if kind == b'files':
712 raise error.InputError(_(b'cannot archive plain files to stdout'))
712 raise error.InputError(_(b'cannot archive plain files to stdout'))
713 dest = cmdutil.makefileobj(ctx, dest)
713 dest = cmdutil.makefileobj(ctx, dest)
714 if not prefix:
714 if not prefix:
715 prefix = os.path.basename(repo.root) + b'-%h'
715 prefix = os.path.basename(repo.root) + b'-%h'
716
716
717 prefix = cmdutil.makefilename(ctx, prefix)
717 prefix = cmdutil.makefilename(ctx, prefix)
718 match = scmutil.match(ctx, [], pycompat.byteskwargs(opts))
718 match = scmutil.match(ctx, [], pycompat.byteskwargs(opts))
719 archival.archive(
719 archival.archive(
720 repo,
720 repo,
721 dest,
721 dest,
722 node,
722 node,
723 kind,
723 kind,
724 not opts.get('no_decode'),
724 not opts.get('no_decode'),
725 match,
725 match,
726 prefix,
726 prefix,
727 subrepos=opts.get('subrepos'),
727 subrepos=opts.get('subrepos'),
728 )
728 )
729
729
730
730
731 @command(
731 @command(
732 b'backout',
732 b'backout',
733 [
733 [
734 (
734 (
735 b'',
735 b'',
736 b'merge',
736 b'merge',
737 None,
737 None,
738 _(b'merge with old dirstate parent after backout'),
738 _(b'merge with old dirstate parent after backout'),
739 ),
739 ),
740 (
740 (
741 b'',
741 b'',
742 b'commit',
742 b'commit',
743 None,
743 None,
744 _(b'commit if no conflicts were encountered (DEPRECATED)'),
744 _(b'commit if no conflicts were encountered (DEPRECATED)'),
745 ),
745 ),
746 (b'', b'no-commit', None, _(b'do not commit')),
746 (b'', b'no-commit', None, _(b'do not commit')),
747 (
747 (
748 b'',
748 b'',
749 b'parent',
749 b'parent',
750 b'',
750 b'',
751 _(b'parent to choose when backing out merge (DEPRECATED)'),
751 _(b'parent to choose when backing out merge (DEPRECATED)'),
752 _(b'REV'),
752 _(b'REV'),
753 ),
753 ),
754 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
754 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
755 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
755 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
756 ]
756 ]
757 + mergetoolopts
757 + mergetoolopts
758 + walkopts
758 + walkopts
759 + commitopts
759 + commitopts
760 + commitopts2,
760 + commitopts2,
761 _(b'[OPTION]... [-r] REV'),
761 _(b'[OPTION]... [-r] REV'),
762 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
762 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
763 )
763 )
764 def backout(ui, repo, node=None, rev=None, **opts):
764 def backout(ui, repo, node=None, rev=None, **opts):
765 """reverse effect of earlier changeset
765 """reverse effect of earlier changeset
766
766
767 Prepare a new changeset with the effect of REV undone in the
767 Prepare a new changeset with the effect of REV undone in the
768 current working directory. If no conflicts were encountered,
768 current working directory. If no conflicts were encountered,
769 it will be committed immediately.
769 it will be committed immediately.
770
770
771 If REV is the parent of the working directory, then this new changeset
771 If REV is the parent of the working directory, then this new changeset
772 is committed automatically (unless --no-commit is specified).
772 is committed automatically (unless --no-commit is specified).
773
773
774 .. note::
774 .. note::
775
775
776 :hg:`backout` cannot be used to fix either an unwanted or
776 :hg:`backout` cannot be used to fix either an unwanted or
777 incorrect merge.
777 incorrect merge.
778
778
779 .. container:: verbose
779 .. container:: verbose
780
780
781 Examples:
781 Examples:
782
782
783 - Reverse the effect of the parent of the working directory.
783 - Reverse the effect of the parent of the working directory.
784 This backout will be committed immediately::
784 This backout will be committed immediately::
785
785
786 hg backout -r .
786 hg backout -r .
787
787
788 - Reverse the effect of previous bad revision 23::
788 - Reverse the effect of previous bad revision 23::
789
789
790 hg backout -r 23
790 hg backout -r 23
791
791
792 - Reverse the effect of previous bad revision 23 and
792 - Reverse the effect of previous bad revision 23 and
793 leave changes uncommitted::
793 leave changes uncommitted::
794
794
795 hg backout -r 23 --no-commit
795 hg backout -r 23 --no-commit
796 hg commit -m "Backout revision 23"
796 hg commit -m "Backout revision 23"
797
797
798 By default, the pending changeset will have one parent,
798 By default, the pending changeset will have one parent,
799 maintaining a linear history. With --merge, the pending
799 maintaining a linear history. With --merge, the pending
800 changeset will instead have two parents: the old parent of the
800 changeset will instead have two parents: the old parent of the
801 working directory and a new child of REV that simply undoes REV.
801 working directory and a new child of REV that simply undoes REV.
802
802
803 Before version 1.7, the behavior without --merge was equivalent
803 Before version 1.7, the behavior without --merge was equivalent
804 to specifying --merge followed by :hg:`update --clean .` to
804 to specifying --merge followed by :hg:`update --clean .` to
805 cancel the merge and leave the child of REV as a head to be
805 cancel the merge and leave the child of REV as a head to be
806 merged separately.
806 merged separately.
807
807
808 See :hg:`help dates` for a list of formats valid for -d/--date.
808 See :hg:`help dates` for a list of formats valid for -d/--date.
809
809
810 See :hg:`help revert` for a way to restore files to the state
810 See :hg:`help revert` for a way to restore files to the state
811 of another revision.
811 of another revision.
812
812
813 Returns 0 on success, 1 if nothing to backout or there are unresolved
813 Returns 0 on success, 1 if nothing to backout or there are unresolved
814 files.
814 files.
815 """
815 """
816 with repo.wlock(), repo.lock():
816 with repo.wlock(), repo.lock():
817 return _dobackout(ui, repo, node, rev, **opts)
817 return _dobackout(ui, repo, node, rev, **opts)
818
818
819
819
820 def _dobackout(ui, repo, node=None, rev=None, **opts):
820 def _dobackout(ui, repo, node=None, rev=None, **opts):
821 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
821 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
822
822
823 if rev and node:
823 if rev and node:
824 raise error.InputError(_(b"please specify just one revision"))
824 raise error.InputError(_(b"please specify just one revision"))
825
825
826 if not rev:
826 if not rev:
827 rev = node
827 rev = node
828
828
829 if not rev:
829 if not rev:
830 raise error.InputError(_(b"please specify a revision to backout"))
830 raise error.InputError(_(b"please specify a revision to backout"))
831
831
832 date = opts.get('date')
832 date = opts.get('date')
833 if date:
833 if date:
834 opts['date'] = dateutil.parsedate(date)
834 opts['date'] = dateutil.parsedate(date)
835
835
836 cmdutil.checkunfinished(repo)
836 cmdutil.checkunfinished(repo)
837 cmdutil.bailifchanged(repo)
837 cmdutil.bailifchanged(repo)
838 ctx = logcmdutil.revsingle(repo, rev)
838 ctx = logcmdutil.revsingle(repo, rev)
839 node = ctx.node()
839 node = ctx.node()
840
840
841 op1, op2 = repo.dirstate.parents()
841 op1, op2 = repo.dirstate.parents()
842 if not repo.changelog.isancestor(node, op1):
842 if not repo.changelog.isancestor(node, op1):
843 raise error.InputError(
843 raise error.InputError(
844 _(b'cannot backout change that is not an ancestor')
844 _(b'cannot backout change that is not an ancestor')
845 )
845 )
846
846
847 p1, p2 = repo.changelog.parents(node)
847 p1, p2 = repo.changelog.parents(node)
848 if p1 == repo.nullid:
848 if p1 == repo.nullid:
849 raise error.InputError(_(b'cannot backout a change with no parents'))
849 raise error.InputError(_(b'cannot backout a change with no parents'))
850 if p2 != repo.nullid:
850 if p2 != repo.nullid:
851 if not opts.get('parent'):
851 if not opts.get('parent'):
852 raise error.InputError(_(b'cannot backout a merge changeset'))
852 raise error.InputError(_(b'cannot backout a merge changeset'))
853 p = repo.lookup(opts['parent'])
853 p = repo.lookup(opts['parent'])
854 if p not in (p1, p2):
854 if p not in (p1, p2):
855 raise error.InputError(
855 raise error.InputError(
856 _(b'%s is not a parent of %s') % (short(p), short(node))
856 _(b'%s is not a parent of %s') % (short(p), short(node))
857 )
857 )
858 parent = p
858 parent = p
859 else:
859 else:
860 if opts.get('parent'):
860 if opts.get('parent'):
861 raise error.InputError(
861 raise error.InputError(
862 _(b'cannot use --parent on non-merge changeset')
862 _(b'cannot use --parent on non-merge changeset')
863 )
863 )
864 parent = p1
864 parent = p1
865
865
866 # the backout should appear on the same branch
866 # the backout should appear on the same branch
867 branch = repo.dirstate.branch()
867 branch = repo.dirstate.branch()
868 bheads = repo.branchheads(branch)
868 bheads = repo.branchheads(branch)
869 rctx = scmutil.revsingle(repo, hex(parent))
869 rctx = scmutil.revsingle(repo, hex(parent))
870 if not opts.get('merge') and op1 != node:
870 if not opts.get('merge') and op1 != node:
871 with repo.transaction(b"backout"):
871 with repo.transaction(b"backout"):
872 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
872 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
873 with ui.configoverride(overrides, b'backout'):
873 with ui.configoverride(overrides, b'backout'):
874 stats = mergemod.back_out(ctx, parent=repo[parent])
874 stats = mergemod.back_out(ctx, parent=repo[parent])
875 repo.setparents(op1, op2)
875 repo.setparents(op1, op2)
876 hg._showstats(repo, stats)
876 hg._showstats(repo, stats)
877 if stats.unresolvedcount:
877 if stats.unresolvedcount:
878 repo.ui.status(
878 repo.ui.status(
879 _(b"use 'hg resolve' to retry unresolved file merges\n")
879 _(b"use 'hg resolve' to retry unresolved file merges\n")
880 )
880 )
881 return 1
881 return 1
882 else:
882 else:
883 hg.clean(repo, node, show_stats=False)
883 hg.clean(repo, node, show_stats=False)
884 repo.dirstate.setbranch(branch, repo.currenttransaction())
884 repo.dirstate.setbranch(branch, repo.currenttransaction())
885 cmdutil.revert(ui, repo, rctx)
885 cmdutil.revert(ui, repo, rctx)
886
886
887 if opts.get('no_commit'):
887 if opts.get('no_commit'):
888 msg = _(b"changeset %s backed out, don't forget to commit.\n")
888 msg = _(b"changeset %s backed out, don't forget to commit.\n")
889 ui.status(msg % short(node))
889 ui.status(msg % short(node))
890 return 0
890 return 0
891
891
892 def commitfunc(ui, repo, message, match, opts):
892 def commitfunc(ui, repo, message, match, opts):
893 editform = b'backout'
893 editform = b'backout'
894 e = cmdutil.getcommiteditor(
894 e = cmdutil.getcommiteditor(
895 editform=editform, **pycompat.strkwargs(opts)
895 editform=editform, **pycompat.strkwargs(opts)
896 )
896 )
897 if not message:
897 if not message:
898 # we don't translate commit messages
898 # we don't translate commit messages
899 message = b"Backed out changeset %s" % short(node)
899 message = b"Backed out changeset %s" % short(node)
900 e = cmdutil.getcommiteditor(edit=True, editform=editform)
900 e = cmdutil.getcommiteditor(edit=True, editform=editform)
901 return repo.commit(
901 return repo.commit(
902 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
902 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
903 )
903 )
904
904
905 # save to detect changes
905 # save to detect changes
906 tip = repo.changelog.tip()
906 tip = repo.changelog.tip()
907
907
908 newnode = cmdutil.commit(
908 newnode = cmdutil.commit(
909 ui, repo, commitfunc, [], pycompat.byteskwargs(opts)
909 ui, repo, commitfunc, [], pycompat.byteskwargs(opts)
910 )
910 )
911 if not newnode:
911 if not newnode:
912 ui.status(_(b"nothing changed\n"))
912 ui.status(_(b"nothing changed\n"))
913 return 1
913 return 1
914 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
914 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
915
915
916 def nice(node):
916 def nice(node):
917 return b'%d:%s' % (repo.changelog.rev(node), short(node))
917 return b'%d:%s' % (repo.changelog.rev(node), short(node))
918
918
919 ui.status(
919 ui.status(
920 _(b'changeset %s backs out changeset %s\n')
920 _(b'changeset %s backs out changeset %s\n')
921 % (nice(newnode), nice(node))
921 % (nice(newnode), nice(node))
922 )
922 )
923 if opts.get('merge') and op1 != node:
923 if opts.get('merge') and op1 != node:
924 hg.clean(repo, op1, show_stats=False)
924 hg.clean(repo, op1, show_stats=False)
925 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
925 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
926 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
926 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
927 with ui.configoverride(overrides, b'backout'):
927 with ui.configoverride(overrides, b'backout'):
928 return hg.merge(repo[b'tip'])
928 return hg.merge(repo[b'tip'])
929 return 0
929 return 0
930
930
931
931
932 @command(
932 @command(
933 b'bisect',
933 b'bisect',
934 [
934 [
935 (b'r', b'reset', False, _(b'reset bisect state')),
935 (b'r', b'reset', False, _(b'reset bisect state')),
936 (b'g', b'good', False, _(b'mark changeset good')),
936 (b'g', b'good', False, _(b'mark changeset good')),
937 (b'b', b'bad', False, _(b'mark changeset bad')),
937 (b'b', b'bad', False, _(b'mark changeset bad')),
938 (b's', b'skip', False, _(b'skip testing changeset')),
938 (b's', b'skip', False, _(b'skip testing changeset')),
939 (b'e', b'extend', False, _(b'extend the bisect range')),
939 (b'e', b'extend', False, _(b'extend the bisect range')),
940 (
940 (
941 b'c',
941 b'c',
942 b'command',
942 b'command',
943 b'',
943 b'',
944 _(b'use command to check changeset state'),
944 _(b'use command to check changeset state'),
945 _(b'CMD'),
945 _(b'CMD'),
946 ),
946 ),
947 (b'U', b'noupdate', False, _(b'do not update to target')),
947 (b'U', b'noupdate', False, _(b'do not update to target')),
948 ],
948 ],
949 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
949 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
950 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
950 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
951 )
951 )
952 def bisect(
952 def bisect(
953 ui,
953 ui,
954 repo,
954 repo,
955 positional_1=None,
955 positional_1=None,
956 positional_2=None,
956 positional_2=None,
957 command=None,
957 command=None,
958 reset=None,
958 reset=None,
959 good=None,
959 good=None,
960 bad=None,
960 bad=None,
961 skip=None,
961 skip=None,
962 extend=None,
962 extend=None,
963 noupdate=None,
963 noupdate=None,
964 ):
964 ):
965 """subdivision search of changesets
965 """subdivision search of changesets
966
966
967 This command helps to find changesets which introduce problems. To
967 This command helps to find changesets which introduce problems. To
968 use, mark the earliest changeset you know exhibits the problem as
968 use, mark the earliest changeset you know exhibits the problem as
969 bad, then mark the latest changeset which is free from the problem
969 bad, then mark the latest changeset which is free from the problem
970 as good. Bisect will update your working directory to a revision
970 as good. Bisect will update your working directory to a revision
971 for testing (unless the -U/--noupdate option is specified). Once
971 for testing (unless the -U/--noupdate option is specified). Once
972 you have performed tests, mark the working directory as good or
972 you have performed tests, mark the working directory as good or
973 bad, and bisect will either update to another candidate changeset
973 bad, and bisect will either update to another candidate changeset
974 or announce that it has found the bad revision.
974 or announce that it has found the bad revision.
975
975
976 As a shortcut, you can also use the revision argument to mark a
976 As a shortcut, you can also use the revision argument to mark a
977 revision as good or bad without checking it out first.
977 revision as good or bad without checking it out first.
978
978
979 If you supply a command, it will be used for automatic bisection.
979 If you supply a command, it will be used for automatic bisection.
980 The environment variable HG_NODE will contain the ID of the
980 The environment variable HG_NODE will contain the ID of the
981 changeset being tested. The exit status of the command will be
981 changeset being tested. The exit status of the command will be
982 used to mark revisions as good or bad: status 0 means good, 125
982 used to mark revisions as good or bad: status 0 means good, 125
983 means to skip the revision, 127 (command not found) will abort the
983 means to skip the revision, 127 (command not found) will abort the
984 bisection, and any other non-zero exit status means the revision
984 bisection, and any other non-zero exit status means the revision
985 is bad.
985 is bad.
986
986
987 .. container:: verbose
987 .. container:: verbose
988
988
989 Some examples:
989 Some examples:
990
990
991 - start a bisection with known bad revision 34, and good revision 12::
991 - start a bisection with known bad revision 34, and good revision 12::
992
992
993 hg bisect --bad 34
993 hg bisect --bad 34
994 hg bisect --good 12
994 hg bisect --good 12
995
995
996 - advance the current bisection by marking current revision as good or
996 - advance the current bisection by marking current revision as good or
997 bad::
997 bad::
998
998
999 hg bisect --good
999 hg bisect --good
1000 hg bisect --bad
1000 hg bisect --bad
1001
1001
1002 - mark the current revision, or a known revision, to be skipped (e.g. if
1002 - mark the current revision, or a known revision, to be skipped (e.g. if
1003 that revision is not usable because of another issue)::
1003 that revision is not usable because of another issue)::
1004
1004
1005 hg bisect --skip
1005 hg bisect --skip
1006 hg bisect --skip 23
1006 hg bisect --skip 23
1007
1007
1008 - skip all revisions that do not touch directories ``foo`` or ``bar``::
1008 - skip all revisions that do not touch directories ``foo`` or ``bar``::
1009
1009
1010 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
1010 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
1011
1011
1012 - forget the current bisection::
1012 - forget the current bisection::
1013
1013
1014 hg bisect --reset
1014 hg bisect --reset
1015
1015
1016 - use 'make && make tests' to automatically find the first broken
1016 - use 'make && make tests' to automatically find the first broken
1017 revision::
1017 revision::
1018
1018
1019 hg bisect --reset
1019 hg bisect --reset
1020 hg bisect --bad 34
1020 hg bisect --bad 34
1021 hg bisect --good 12
1021 hg bisect --good 12
1022 hg bisect --command "make && make tests"
1022 hg bisect --command "make && make tests"
1023
1023
1024 - see all changesets whose states are already known in the current
1024 - see all changesets whose states are already known in the current
1025 bisection::
1025 bisection::
1026
1026
1027 hg log -r "bisect(pruned)"
1027 hg log -r "bisect(pruned)"
1028
1028
1029 - see the changeset currently being bisected (especially useful
1029 - see the changeset currently being bisected (especially useful
1030 if running with -U/--noupdate)::
1030 if running with -U/--noupdate)::
1031
1031
1032 hg log -r "bisect(current)"
1032 hg log -r "bisect(current)"
1033
1033
1034 - see all changesets that took part in the current bisection::
1034 - see all changesets that took part in the current bisection::
1035
1035
1036 hg log -r "bisect(range)"
1036 hg log -r "bisect(range)"
1037
1037
1038 - you can even get a nice graph::
1038 - you can even get a nice graph::
1039
1039
1040 hg log --graph -r "bisect(range)"
1040 hg log --graph -r "bisect(range)"
1041
1041
1042 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
1042 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
1043
1043
1044 Returns 0 on success.
1044 Returns 0 on success.
1045 """
1045 """
1046 rev = []
1046 rev = []
1047 # backward compatibility
1047 # backward compatibility
1048 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1048 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1049 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1049 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1050 cmd = positional_1
1050 cmd = positional_1
1051 rev.append(positional_2)
1051 rev.append(positional_2)
1052 if cmd == b"good":
1052 if cmd == b"good":
1053 good = True
1053 good = True
1054 elif cmd == b"bad":
1054 elif cmd == b"bad":
1055 bad = True
1055 bad = True
1056 else:
1056 else:
1057 reset = True
1057 reset = True
1058 elif positional_2:
1058 elif positional_2:
1059 raise error.InputError(_(b'incompatible arguments'))
1059 raise error.InputError(_(b'incompatible arguments'))
1060 elif positional_1 is not None:
1060 elif positional_1 is not None:
1061 rev.append(positional_1)
1061 rev.append(positional_1)
1062
1062
1063 incompatibles = {
1063 incompatibles = {
1064 b'--bad': bad,
1064 b'--bad': bad,
1065 b'--command': bool(command),
1065 b'--command': bool(command),
1066 b'--extend': extend,
1066 b'--extend': extend,
1067 b'--good': good,
1067 b'--good': good,
1068 b'--reset': reset,
1068 b'--reset': reset,
1069 b'--skip': skip,
1069 b'--skip': skip,
1070 }
1070 }
1071
1071
1072 enabled = [x for x in incompatibles if incompatibles[x]]
1072 enabled = [x for x in incompatibles if incompatibles[x]]
1073
1073
1074 if len(enabled) > 1:
1074 if len(enabled) > 1:
1075 raise error.InputError(
1075 raise error.InputError(
1076 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1076 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1077 )
1077 )
1078
1078
1079 if reset:
1079 if reset:
1080 hbisect.resetstate(repo)
1080 hbisect.resetstate(repo)
1081 return
1081 return
1082
1082
1083 state = hbisect.load_state(repo)
1083 state = hbisect.load_state(repo)
1084
1084
1085 if rev:
1085 if rev:
1086 revs = logcmdutil.revrange(repo, rev)
1086 revs = logcmdutil.revrange(repo, rev)
1087 goodnodes = state[b'good']
1087 goodnodes = state[b'good']
1088 badnodes = state[b'bad']
1088 badnodes = state[b'bad']
1089 if goodnodes and badnodes:
1089 if goodnodes and badnodes:
1090 candidates = repo.revs(b'(%ln)::(%ln)', goodnodes, badnodes)
1090 candidates = repo.revs(b'(%ln)::(%ln)', goodnodes, badnodes)
1091 candidates += repo.revs(b'(%ln)::(%ln)', badnodes, goodnodes)
1091 candidates += repo.revs(b'(%ln)::(%ln)', badnodes, goodnodes)
1092 revs = candidates & revs
1092 revs = candidates & revs
1093 nodes = [repo.changelog.node(i) for i in revs]
1093 nodes = [repo.changelog.node(i) for i in revs]
1094 else:
1094 else:
1095 nodes = [repo.lookup(b'.')]
1095 nodes = [repo.lookup(b'.')]
1096
1096
1097 # update state
1097 # update state
1098 if good or bad or skip:
1098 if good or bad or skip:
1099 if good:
1099 if good:
1100 state[b'good'] += nodes
1100 state[b'good'] += nodes
1101 elif bad:
1101 elif bad:
1102 state[b'bad'] += nodes
1102 state[b'bad'] += nodes
1103 elif skip:
1103 elif skip:
1104 state[b'skip'] += nodes
1104 state[b'skip'] += nodes
1105 hbisect.save_state(repo, state)
1105 hbisect.save_state(repo, state)
1106 if not (state[b'good'] and state[b'bad']):
1106 if not (state[b'good'] and state[b'bad']):
1107 return
1107 return
1108
1108
1109 def mayupdate(repo, node, show_stats=True):
1109 def mayupdate(repo, node, show_stats=True):
1110 """common used update sequence"""
1110 """common used update sequence"""
1111 if noupdate:
1111 if noupdate:
1112 return
1112 return
1113 cmdutil.checkunfinished(repo)
1113 cmdutil.checkunfinished(repo)
1114 cmdutil.bailifchanged(repo)
1114 cmdutil.bailifchanged(repo)
1115 return hg.clean(repo, node, show_stats=show_stats)
1115 return hg.clean(repo, node, show_stats=show_stats)
1116
1116
1117 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1117 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1118
1118
1119 if command:
1119 if command:
1120 changesets = 1
1120 changesets = 1
1121 if noupdate:
1121 if noupdate:
1122 try:
1122 try:
1123 node = state[b'current'][0]
1123 node = state[b'current'][0]
1124 except LookupError:
1124 except LookupError:
1125 raise error.StateError(
1125 raise error.StateError(
1126 _(
1126 _(
1127 b'current bisect revision is unknown - '
1127 b'current bisect revision is unknown - '
1128 b'start a new bisect to fix'
1128 b'start a new bisect to fix'
1129 )
1129 )
1130 )
1130 )
1131 else:
1131 else:
1132 node, p2 = repo.dirstate.parents()
1132 node, p2 = repo.dirstate.parents()
1133 if p2 != repo.nullid:
1133 if p2 != repo.nullid:
1134 raise error.StateError(_(b'current bisect revision is a merge'))
1134 raise error.StateError(_(b'current bisect revision is a merge'))
1135 if rev:
1135 if rev:
1136 if not nodes:
1136 if not nodes:
1137 raise error.InputError(_(b'empty revision set'))
1137 raise error.InputError(_(b'empty revision set'))
1138 node = repo[nodes[-1]].node()
1138 node = repo[nodes[-1]].node()
1139 with hbisect.restore_state(repo, state, node):
1139 with hbisect.restore_state(repo, state, node):
1140 while changesets:
1140 while changesets:
1141 # update state
1141 # update state
1142 state[b'current'] = [node]
1142 state[b'current'] = [node]
1143 hbisect.save_state(repo, state)
1143 hbisect.save_state(repo, state)
1144 status = ui.system(
1144 status = ui.system(
1145 command,
1145 command,
1146 environ={b'HG_NODE': hex(node)},
1146 environ={b'HG_NODE': hex(node)},
1147 blockedtag=b'bisect_check',
1147 blockedtag=b'bisect_check',
1148 )
1148 )
1149 if status == 125:
1149 if status == 125:
1150 transition = b"skip"
1150 transition = b"skip"
1151 elif status == 0:
1151 elif status == 0:
1152 transition = b"good"
1152 transition = b"good"
1153 # status < 0 means process was killed
1153 # status < 0 means process was killed
1154 elif status == 127:
1154 elif status == 127:
1155 raise error.Abort(_(b"failed to execute %s") % command)
1155 raise error.Abort(_(b"failed to execute %s") % command)
1156 elif status < 0:
1156 elif status < 0:
1157 raise error.Abort(_(b"%s killed") % command)
1157 raise error.Abort(_(b"%s killed") % command)
1158 else:
1158 else:
1159 transition = b"bad"
1159 transition = b"bad"
1160 state[transition].append(node)
1160 state[transition].append(node)
1161 ctx = repo[node]
1161 ctx = repo[node]
1162 summary = cmdutil.format_changeset_summary(ui, ctx, b'bisect')
1162 summary = cmdutil.format_changeset_summary(ui, ctx, b'bisect')
1163 ui.status(_(b'changeset %s: %s\n') % (summary, transition))
1163 ui.status(_(b'changeset %s: %s\n') % (summary, transition))
1164 hbisect.checkstate(state)
1164 hbisect.checkstate(state)
1165 # bisect
1165 # bisect
1166 nodes, changesets, bgood = hbisect.bisect(repo, state)
1166 nodes, changesets, bgood = hbisect.bisect(repo, state)
1167 # update to next check
1167 # update to next check
1168 node = nodes[0]
1168 node = nodes[0]
1169 mayupdate(repo, node, show_stats=False)
1169 mayupdate(repo, node, show_stats=False)
1170 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1170 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1171 return
1171 return
1172
1172
1173 hbisect.checkstate(state)
1173 hbisect.checkstate(state)
1174
1174
1175 # actually bisect
1175 # actually bisect
1176 nodes, changesets, good = hbisect.bisect(repo, state)
1176 nodes, changesets, good = hbisect.bisect(repo, state)
1177 if extend:
1177 if extend:
1178 if not changesets:
1178 if not changesets:
1179 extendctx = hbisect.extendrange(repo, state, nodes, good)
1179 extendctx = hbisect.extendrange(repo, state, nodes, good)
1180 if extendctx is not None:
1180 if extendctx is not None:
1181 ui.write(
1181 ui.write(
1182 _(b"Extending search to changeset %s\n")
1182 _(b"Extending search to changeset %s\n")
1183 % cmdutil.format_changeset_summary(ui, extendctx, b'bisect')
1183 % cmdutil.format_changeset_summary(ui, extendctx, b'bisect')
1184 )
1184 )
1185 state[b'current'] = [extendctx.node()]
1185 state[b'current'] = [extendctx.node()]
1186 hbisect.save_state(repo, state)
1186 hbisect.save_state(repo, state)
1187 return mayupdate(repo, extendctx.node())
1187 return mayupdate(repo, extendctx.node())
1188 raise error.StateError(_(b"nothing to extend"))
1188 raise error.StateError(_(b"nothing to extend"))
1189
1189
1190 if changesets == 0:
1190 if changesets == 0:
1191 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1191 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1192 else:
1192 else:
1193 assert len(nodes) == 1 # only a single node can be tested next
1193 assert len(nodes) == 1 # only a single node can be tested next
1194 node = nodes[0]
1194 node = nodes[0]
1195 # compute the approximate number of remaining tests
1195 # compute the approximate number of remaining tests
1196 tests, size = 0, 2
1196 tests, size = 0, 2
1197 while size <= changesets:
1197 while size <= changesets:
1198 tests, size = tests + 1, size * 2
1198 tests, size = tests + 1, size * 2
1199 rev = repo.changelog.rev(node)
1199 rev = repo.changelog.rev(node)
1200 summary = cmdutil.format_changeset_summary(ui, repo[rev], b'bisect')
1200 summary = cmdutil.format_changeset_summary(ui, repo[rev], b'bisect')
1201 ui.write(
1201 ui.write(
1202 _(
1202 _(
1203 b"Testing changeset %s "
1203 b"Testing changeset %s "
1204 b"(%d changesets remaining, ~%d tests)\n"
1204 b"(%d changesets remaining, ~%d tests)\n"
1205 )
1205 )
1206 % (summary, changesets, tests)
1206 % (summary, changesets, tests)
1207 )
1207 )
1208 state[b'current'] = [node]
1208 state[b'current'] = [node]
1209 hbisect.save_state(repo, state)
1209 hbisect.save_state(repo, state)
1210 return mayupdate(repo, node)
1210 return mayupdate(repo, node)
1211
1211
1212
1212
1213 @command(
1213 @command(
1214 b'bookmarks|bookmark',
1214 b'bookmarks|bookmark',
1215 [
1215 [
1216 (b'f', b'force', False, _(b'force')),
1216 (b'f', b'force', False, _(b'force')),
1217 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1217 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1218 (b'd', b'delete', False, _(b'delete a given bookmark')),
1218 (b'd', b'delete', False, _(b'delete a given bookmark')),
1219 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1219 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1220 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1220 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1221 (b'l', b'list', False, _(b'list existing bookmarks')),
1221 (b'l', b'list', False, _(b'list existing bookmarks')),
1222 ]
1222 ]
1223 + formatteropts,
1223 + formatteropts,
1224 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1224 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1225 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1225 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1226 )
1226 )
1227 def bookmark(ui, repo, *names, **opts):
1227 def bookmark(ui, repo, *names, **opts):
1228 """create a new bookmark or list existing bookmarks
1228 """create a new bookmark or list existing bookmarks
1229
1229
1230 Bookmarks are labels on changesets to help track lines of development.
1230 Bookmarks are labels on changesets to help track lines of development.
1231 Bookmarks are unversioned and can be moved, renamed and deleted.
1231 Bookmarks are unversioned and can be moved, renamed and deleted.
1232 Deleting or moving a bookmark has no effect on the associated changesets.
1232 Deleting or moving a bookmark has no effect on the associated changesets.
1233
1233
1234 Creating or updating to a bookmark causes it to be marked as 'active'.
1234 Creating or updating to a bookmark causes it to be marked as 'active'.
1235 The active bookmark is indicated with a '*'.
1235 The active bookmark is indicated with a '*'.
1236 When a commit is made, the active bookmark will advance to the new commit.
1236 When a commit is made, the active bookmark will advance to the new commit.
1237 A plain :hg:`update` will also advance an active bookmark, if possible.
1237 A plain :hg:`update` will also advance an active bookmark, if possible.
1238 Updating away from a bookmark will cause it to be deactivated.
1238 Updating away from a bookmark will cause it to be deactivated.
1239
1239
1240 Bookmarks can be pushed and pulled between repositories (see
1240 Bookmarks can be pushed and pulled between repositories (see
1241 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1241 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1242 diverged, a new 'divergent bookmark' of the form 'name@path' will
1242 diverged, a new 'divergent bookmark' of the form 'name@path' will
1243 be created. Using :hg:`merge` will resolve the divergence.
1243 be created. Using :hg:`merge` will resolve the divergence.
1244
1244
1245 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1245 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1246 the active bookmark's name.
1246 the active bookmark's name.
1247
1247
1248 A bookmark named '@' has the special property that :hg:`clone` will
1248 A bookmark named '@' has the special property that :hg:`clone` will
1249 check it out by default if it exists.
1249 check it out by default if it exists.
1250
1250
1251 .. container:: verbose
1251 .. container:: verbose
1252
1252
1253 Template:
1253 Template:
1254
1254
1255 The following keywords are supported in addition to the common template
1255 The following keywords are supported in addition to the common template
1256 keywords and functions such as ``{bookmark}``. See also
1256 keywords and functions such as ``{bookmark}``. See also
1257 :hg:`help templates`.
1257 :hg:`help templates`.
1258
1258
1259 :active: Boolean. True if the bookmark is active.
1259 :active: Boolean. True if the bookmark is active.
1260
1260
1261 Examples:
1261 Examples:
1262
1262
1263 - create an active bookmark for a new line of development::
1263 - create an active bookmark for a new line of development::
1264
1264
1265 hg book new-feature
1265 hg book new-feature
1266
1266
1267 - create an inactive bookmark as a place marker::
1267 - create an inactive bookmark as a place marker::
1268
1268
1269 hg book -i reviewed
1269 hg book -i reviewed
1270
1270
1271 - create an inactive bookmark on another changeset::
1271 - create an inactive bookmark on another changeset::
1272
1272
1273 hg book -r .^ tested
1273 hg book -r .^ tested
1274
1274
1275 - rename bookmark turkey to dinner::
1275 - rename bookmark turkey to dinner::
1276
1276
1277 hg book -m turkey dinner
1277 hg book -m turkey dinner
1278
1278
1279 - move the '@' bookmark from another branch::
1279 - move the '@' bookmark from another branch::
1280
1280
1281 hg book -f @
1281 hg book -f @
1282
1282
1283 - print only the active bookmark name::
1283 - print only the active bookmark name::
1284
1284
1285 hg book -ql .
1285 hg book -ql .
1286 """
1286 """
1287 force = opts.get('force')
1287 force = opts.get('force')
1288 rev = opts.get('rev')
1288 rev = opts.get('rev')
1289 inactive = opts.get('inactive') # meaning add/rename to inactive bookmark
1289 inactive = opts.get('inactive') # meaning add/rename to inactive bookmark
1290
1290
1291 action = cmdutil.check_at_most_one_arg(opts, 'delete', 'rename', 'list')
1291 action = cmdutil.check_at_most_one_arg(opts, 'delete', 'rename', 'list')
1292 if action:
1292 if action:
1293 cmdutil.check_incompatible_arguments(opts, action, ['rev'])
1293 cmdutil.check_incompatible_arguments(opts, action, ['rev'])
1294 elif names or rev:
1294 elif names or rev:
1295 action = 'add'
1295 action = 'add'
1296 elif inactive:
1296 elif inactive:
1297 action = 'inactive' # meaning deactivate
1297 action = 'inactive' # meaning deactivate
1298 else:
1298 else:
1299 action = 'list'
1299 action = 'list'
1300
1300
1301 cmdutil.check_incompatible_arguments(opts, 'inactive', ['delete', 'list'])
1301 cmdutil.check_incompatible_arguments(opts, 'inactive', ['delete', 'list'])
1302 if not names and action in {'add', 'delete'}:
1302 if not names and action in {'add', 'delete'}:
1303 raise error.InputError(_(b"bookmark name required"))
1303 raise error.InputError(_(b"bookmark name required"))
1304
1304
1305 if action in {'add', 'delete', 'rename', 'inactive'}:
1305 if action in {'add', 'delete', 'rename', 'inactive'}:
1306 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1306 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1307 if action == 'delete':
1307 if action == 'delete':
1308 names = pycompat.maplist(repo._bookmarks.expandname, names)
1308 names = pycompat.maplist(repo._bookmarks.expandname, names)
1309 bookmarks.delete(repo, tr, names)
1309 bookmarks.delete(repo, tr, names)
1310 elif action == 'rename':
1310 elif action == 'rename':
1311 if not names:
1311 if not names:
1312 raise error.InputError(_(b"new bookmark name required"))
1312 raise error.InputError(_(b"new bookmark name required"))
1313 elif len(names) > 1:
1313 elif len(names) > 1:
1314 raise error.InputError(
1314 raise error.InputError(
1315 _(b"only one new bookmark name allowed")
1315 _(b"only one new bookmark name allowed")
1316 )
1316 )
1317 oldname = repo._bookmarks.expandname(opts['rename'])
1317 oldname = repo._bookmarks.expandname(opts['rename'])
1318 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1318 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1319 elif action == 'add':
1319 elif action == 'add':
1320 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1320 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1321 elif action == 'inactive':
1321 elif action == 'inactive':
1322 if len(repo._bookmarks) == 0:
1322 if len(repo._bookmarks) == 0:
1323 ui.status(_(b"no bookmarks set\n"))
1323 ui.status(_(b"no bookmarks set\n"))
1324 elif not repo._activebookmark:
1324 elif not repo._activebookmark:
1325 ui.status(_(b"no active bookmark\n"))
1325 ui.status(_(b"no active bookmark\n"))
1326 else:
1326 else:
1327 bookmarks.deactivate(repo)
1327 bookmarks.deactivate(repo)
1328 elif action == 'list':
1328 elif action == 'list':
1329 names = pycompat.maplist(repo._bookmarks.expandname, names)
1329 names = pycompat.maplist(repo._bookmarks.expandname, names)
1330 with ui.formatter(b'bookmarks', pycompat.byteskwargs(opts)) as fm:
1330 with ui.formatter(b'bookmarks', pycompat.byteskwargs(opts)) as fm:
1331 bookmarks.printbookmarks(ui, repo, fm, names)
1331 bookmarks.printbookmarks(ui, repo, fm, names)
1332 else:
1332 else:
1333 raise error.ProgrammingError(
1333 raise error.ProgrammingError(
1334 b'invalid action: %s' % pycompat.sysbytes(action)
1334 b'invalid action: %s' % pycompat.sysbytes(action)
1335 )
1335 )
1336
1336
1337
1337
1338 @command(
1338 @command(
1339 b'branch',
1339 b'branch',
1340 [
1340 [
1341 (
1341 (
1342 b'f',
1342 b'f',
1343 b'force',
1343 b'force',
1344 None,
1344 None,
1345 _(b'set branch name even if it shadows an existing branch'),
1345 _(b'set branch name even if it shadows an existing branch'),
1346 ),
1346 ),
1347 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1347 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1348 (
1348 (
1349 b'r',
1349 b'r',
1350 b'rev',
1350 b'rev',
1351 [],
1351 [],
1352 _(b'change branches of the given revs (EXPERIMENTAL)'),
1352 _(b'change branches of the given revs (EXPERIMENTAL)'),
1353 ),
1353 ),
1354 ],
1354 ],
1355 _(b'[-fC] [NAME]'),
1355 _(b'[-fC] [NAME]'),
1356 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1356 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1357 )
1357 )
1358 def branch(ui, repo, label=None, **opts):
1358 def branch(ui, repo, label=None, **opts):
1359 """set or show the current branch name
1359 """set or show the current branch name
1360
1360
1361 .. note::
1361 .. note::
1362
1362
1363 Branch names are permanent and global. Use :hg:`bookmark` to create a
1363 Branch names are permanent and global. Use :hg:`bookmark` to create a
1364 light-weight bookmark instead. See :hg:`help glossary` for more
1364 light-weight bookmark instead. See :hg:`help glossary` for more
1365 information about named branches and bookmarks.
1365 information about named branches and bookmarks.
1366
1366
1367 With no argument, show the current branch name. With one argument,
1367 With no argument, show the current branch name. With one argument,
1368 set the working directory branch name (the branch will not exist
1368 set the working directory branch name (the branch will not exist
1369 in the repository until the next commit). Standard practice
1369 in the repository until the next commit). Standard practice
1370 recommends that primary development take place on the 'default'
1370 recommends that primary development take place on the 'default'
1371 branch.
1371 branch.
1372
1372
1373 Unless -f/--force is specified, branch will not let you set a
1373 Unless -f/--force is specified, branch will not let you set a
1374 branch name that already exists.
1374 branch name that already exists.
1375
1375
1376 Use -C/--clean to reset the working directory branch to that of
1376 Use -C/--clean to reset the working directory branch to that of
1377 the parent of the working directory, negating a previous branch
1377 the parent of the working directory, negating a previous branch
1378 change.
1378 change.
1379
1379
1380 Use the command :hg:`update` to switch to an existing branch. Use
1380 Use the command :hg:`update` to switch to an existing branch. Use
1381 :hg:`commit --close-branch` to mark this branch head as closed.
1381 :hg:`commit --close-branch` to mark this branch head as closed.
1382 When all heads of a branch are closed, the branch will be
1382 When all heads of a branch are closed, the branch will be
1383 considered closed.
1383 considered closed.
1384
1384
1385 Returns 0 on success.
1385 Returns 0 on success.
1386 """
1386 """
1387 revs = opts.get('rev')
1387 revs = opts.get('rev')
1388 if label:
1388 if label:
1389 label = label.strip()
1389 label = label.strip()
1390
1390
1391 if not opts.get('clean') and not label:
1391 if not opts.get('clean') and not label:
1392 if revs:
1392 if revs:
1393 raise error.InputError(
1393 raise error.InputError(
1394 _(b"no branch name specified for the revisions")
1394 _(b"no branch name specified for the revisions")
1395 )
1395 )
1396 ui.write(b"%s\n" % repo.dirstate.branch())
1396 ui.write(b"%s\n" % repo.dirstate.branch())
1397 return
1397 return
1398
1398
1399 with repo.wlock():
1399 with repo.wlock():
1400 if opts.get('clean'):
1400 if opts.get('clean'):
1401 label = repo[b'.'].branch()
1401 label = repo[b'.'].branch()
1402 repo.dirstate.setbranch(label, repo.currenttransaction())
1402 repo.dirstate.setbranch(label, repo.currenttransaction())
1403 ui.status(_(b'reset working directory to branch %s\n') % label)
1403 ui.status(_(b'reset working directory to branch %s\n') % label)
1404 elif label:
1404 elif label:
1405 scmutil.checknewlabel(repo, label, b'branch')
1405 scmutil.checknewlabel(repo, label, b'branch')
1406 if revs:
1406 if revs:
1407 return cmdutil.changebranch(ui, repo, revs, label, **opts)
1407 return cmdutil.changebranch(ui, repo, revs, label, **opts)
1408
1408
1409 if not opts.get('force') and label in repo.branchmap():
1409 if not opts.get('force') and label in repo.branchmap():
1410 if label not in [p.branch() for p in repo[None].parents()]:
1410 if label not in [p.branch() for p in repo[None].parents()]:
1411 raise error.InputError(
1411 raise error.InputError(
1412 _(b'a branch of the same name already exists'),
1412 _(b'a branch of the same name already exists'),
1413 # i18n: "it" refers to an existing branch
1413 # i18n: "it" refers to an existing branch
1414 hint=_(b"use 'hg update' to switch to it"),
1414 hint=_(b"use 'hg update' to switch to it"),
1415 )
1415 )
1416
1416
1417 repo.dirstate.setbranch(label, repo.currenttransaction())
1417 repo.dirstate.setbranch(label, repo.currenttransaction())
1418 ui.status(_(b'marked working directory as branch %s\n') % label)
1418 ui.status(_(b'marked working directory as branch %s\n') % label)
1419
1419
1420 # find any open named branches aside from default
1420 # find any open named branches aside from default
1421 for n, h, t, c in repo.branchmap().iterbranches():
1421 for n, h, t, c in repo.branchmap().iterbranches():
1422 if n != b"default" and not c:
1422 if n != b"default" and not c:
1423 return 0
1423 return 0
1424 ui.status(
1424 ui.status(
1425 _(
1425 _(
1426 b'(branches are permanent and global, '
1426 b'(branches are permanent and global, '
1427 b'did you want a bookmark?)\n'
1427 b'did you want a bookmark?)\n'
1428 )
1428 )
1429 )
1429 )
1430
1430
1431
1431
1432 @command(
1432 @command(
1433 b'branches',
1433 b'branches',
1434 [
1434 [
1435 (
1435 (
1436 b'a',
1436 b'a',
1437 b'active',
1437 b'active',
1438 False,
1438 False,
1439 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1439 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1440 ),
1440 ),
1441 (b'c', b'closed', False, _(b'show normal and closed branches')),
1441 (b'c', b'closed', False, _(b'show normal and closed branches')),
1442 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1442 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1443 ]
1443 ]
1444 + formatteropts,
1444 + formatteropts,
1445 _(b'[-c]'),
1445 _(b'[-c]'),
1446 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1446 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1447 intents={INTENT_READONLY},
1447 intents={INTENT_READONLY},
1448 )
1448 )
1449 def branches(ui, repo, active=False, closed=False, **opts):
1449 def branches(ui, repo, active=False, closed=False, **opts):
1450 """list repository named branches
1450 """list repository named branches
1451
1451
1452 List the repository's named branches, indicating which ones are
1452 List the repository's named branches, indicating which ones are
1453 inactive. If -c/--closed is specified, also list branches which have
1453 inactive. If -c/--closed is specified, also list branches which have
1454 been marked closed (see :hg:`commit --close-branch`).
1454 been marked closed (see :hg:`commit --close-branch`).
1455
1455
1456 Use the command :hg:`update` to switch to an existing branch.
1456 Use the command :hg:`update` to switch to an existing branch.
1457
1457
1458 .. container:: verbose
1458 .. container:: verbose
1459
1459
1460 Template:
1460 Template:
1461
1461
1462 The following keywords are supported in addition to the common template
1462 The following keywords are supported in addition to the common template
1463 keywords and functions such as ``{branch}``. See also
1463 keywords and functions such as ``{branch}``. See also
1464 :hg:`help templates`.
1464 :hg:`help templates`.
1465
1465
1466 :active: Boolean. True if the branch is active.
1466 :active: Boolean. True if the branch is active.
1467 :closed: Boolean. True if the branch is closed.
1467 :closed: Boolean. True if the branch is closed.
1468 :current: Boolean. True if it is the current branch.
1468 :current: Boolean. True if it is the current branch.
1469
1469
1470 Returns 0.
1470 Returns 0.
1471 """
1471 """
1472
1472
1473 revs = opts.get('rev')
1473 revs = opts.get('rev')
1474 selectedbranches = None
1474 selectedbranches = None
1475 if revs:
1475 if revs:
1476 revs = logcmdutil.revrange(repo, revs)
1476 revs = logcmdutil.revrange(repo, revs)
1477 getbi = repo.revbranchcache().branchinfo
1477 getbi = repo.revbranchcache().branchinfo
1478 selectedbranches = {getbi(r)[0] for r in revs}
1478 selectedbranches = {getbi(r)[0] for r in revs}
1479
1479
1480 ui.pager(b'branches')
1480 ui.pager(b'branches')
1481 fm = ui.formatter(b'branches', pycompat.byteskwargs(opts))
1481 fm = ui.formatter(b'branches', pycompat.byteskwargs(opts))
1482 hexfunc = fm.hexfunc
1482 hexfunc = fm.hexfunc
1483
1483
1484 allheads = set(repo.heads())
1484 allheads = set(repo.heads())
1485 branches = []
1485 branches = []
1486 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1486 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1487 if selectedbranches is not None and tag not in selectedbranches:
1487 if selectedbranches is not None and tag not in selectedbranches:
1488 continue
1488 continue
1489 isactive = False
1489 isactive = False
1490 if not isclosed:
1490 if not isclosed:
1491 openheads = set(repo.branchmap().iteropen(heads))
1491 openheads = set(repo.branchmap().iteropen(heads))
1492 isactive = bool(openheads & allheads)
1492 isactive = bool(openheads & allheads)
1493 branches.append((tag, repo[tip], isactive, not isclosed))
1493 branches.append((tag, repo[tip], isactive, not isclosed))
1494 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1494 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1495
1495
1496 for tag, ctx, isactive, isopen in branches:
1496 for tag, ctx, isactive, isopen in branches:
1497 if active and not isactive:
1497 if active and not isactive:
1498 continue
1498 continue
1499 if isactive:
1499 if isactive:
1500 label = b'branches.active'
1500 label = b'branches.active'
1501 notice = b''
1501 notice = b''
1502 elif not isopen:
1502 elif not isopen:
1503 if not closed:
1503 if not closed:
1504 continue
1504 continue
1505 label = b'branches.closed'
1505 label = b'branches.closed'
1506 notice = _(b' (closed)')
1506 notice = _(b' (closed)')
1507 else:
1507 else:
1508 label = b'branches.inactive'
1508 label = b'branches.inactive'
1509 notice = _(b' (inactive)')
1509 notice = _(b' (inactive)')
1510 current = tag == repo.dirstate.branch()
1510 current = tag == repo.dirstate.branch()
1511 if current:
1511 if current:
1512 label = b'branches.current'
1512 label = b'branches.current'
1513
1513
1514 fm.startitem()
1514 fm.startitem()
1515 fm.write(b'branch', b'%s', tag, label=label)
1515 fm.write(b'branch', b'%s', tag, label=label)
1516 rev = ctx.rev()
1516 rev = ctx.rev()
1517 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1517 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1518 fmt = b' ' * padsize + b' %d:%s'
1518 fmt = b' ' * padsize + b' %d:%s'
1519 fm.condwrite(
1519 fm.condwrite(
1520 not ui.quiet,
1520 not ui.quiet,
1521 b'rev node',
1521 b'rev node',
1522 fmt,
1522 fmt,
1523 rev,
1523 rev,
1524 hexfunc(ctx.node()),
1524 hexfunc(ctx.node()),
1525 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1525 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1526 )
1526 )
1527 fm.context(ctx=ctx)
1527 fm.context(ctx=ctx)
1528 fm.data(active=isactive, closed=not isopen, current=current)
1528 fm.data(active=isactive, closed=not isopen, current=current)
1529 if not ui.quiet:
1529 if not ui.quiet:
1530 fm.plain(notice)
1530 fm.plain(notice)
1531 fm.plain(b'\n')
1531 fm.plain(b'\n')
1532 fm.end()
1532 fm.end()
1533
1533
1534
1534
1535 @command(
1535 @command(
1536 b'bundle',
1536 b'bundle',
1537 [
1537 [
1538 (
1538 (
1539 b'',
1539 b'',
1540 b'exact',
1540 b'exact',
1541 None,
1541 None,
1542 _(b'compute the base from the revision specified'),
1542 _(b'compute the base from the revision specified'),
1543 ),
1543 ),
1544 (
1544 (
1545 b'f',
1545 b'f',
1546 b'force',
1546 b'force',
1547 None,
1547 None,
1548 _(b'run even when the destination is unrelated'),
1548 _(b'run even when the destination is unrelated'),
1549 ),
1549 ),
1550 (
1550 (
1551 b'r',
1551 b'r',
1552 b'rev',
1552 b'rev',
1553 [],
1553 [],
1554 _(b'a changeset intended to be added to the destination'),
1554 _(b'a changeset intended to be added to the destination'),
1555 _(b'REV'),
1555 _(b'REV'),
1556 ),
1556 ),
1557 (
1557 (
1558 b'b',
1558 b'b',
1559 b'branch',
1559 b'branch',
1560 [],
1560 [],
1561 _(b'a specific branch you would like to bundle'),
1561 _(b'a specific branch you would like to bundle'),
1562 _(b'BRANCH'),
1562 _(b'BRANCH'),
1563 ),
1563 ),
1564 (
1564 (
1565 b'',
1565 b'',
1566 b'base',
1566 b'base',
1567 [],
1567 [],
1568 _(b'a base changeset assumed to be available at the destination'),
1568 _(b'a base changeset assumed to be available at the destination'),
1569 _(b'REV'),
1569 _(b'REV'),
1570 ),
1570 ),
1571 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1571 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1572 (
1572 (
1573 b't',
1573 b't',
1574 b'type',
1574 b'type',
1575 b'bzip2',
1575 b'bzip2',
1576 _(b'bundle compression type to use'),
1576 _(b'bundle compression type to use'),
1577 _(b'TYPE'),
1577 _(b'TYPE'),
1578 ),
1578 ),
1579 ]
1579 ]
1580 + remoteopts,
1580 + remoteopts,
1581 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]...'),
1581 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]...'),
1582 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1582 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1583 )
1583 )
1584 def bundle(ui, repo, fname, *dests, **opts):
1584 def bundle(ui, repo, fname, *dests, **opts):
1585 """create a bundle file
1585 """create a bundle file
1586
1586
1587 Generate a bundle file containing data to be transferred to another
1587 Generate a bundle file containing data to be transferred to another
1588 repository.
1588 repository.
1589
1589
1590 To create a bundle containing all changesets, use -a/--all
1590 To create a bundle containing all changesets, use -a/--all
1591 (or --base null). Otherwise, hg assumes the destination will have
1591 (or --base null). Otherwise, hg assumes the destination will have
1592 all the nodes you specify with --base parameters. Otherwise, hg
1592 all the nodes you specify with --base parameters. Otherwise, hg
1593 will assume the repository has all the nodes in destination, or
1593 will assume the repository has all the nodes in destination, or
1594 default-push/default if no destination is specified, where destination
1594 default-push/default if no destination is specified, where destination
1595 is the repositories you provide through DEST option.
1595 is the repositories you provide through DEST option.
1596
1596
1597 You can change bundle format with the -t/--type option. See
1597 You can change bundle format with the -t/--type option. See
1598 :hg:`help bundlespec` for documentation on this format. By default,
1598 :hg:`help bundlespec` for documentation on this format. By default,
1599 the most appropriate format is used and compression defaults to
1599 the most appropriate format is used and compression defaults to
1600 bzip2.
1600 bzip2.
1601
1601
1602 The bundle file can then be transferred using conventional means
1602 The bundle file can then be transferred using conventional means
1603 and applied to another repository with the unbundle or pull
1603 and applied to another repository with the unbundle or pull
1604 command. This is useful when direct push and pull are not
1604 command. This is useful when direct push and pull are not
1605 available or when exporting an entire repository is undesirable.
1605 available or when exporting an entire repository is undesirable.
1606
1606
1607 Applying bundles preserves all changeset contents including
1607 Applying bundles preserves all changeset contents including
1608 permissions, copy/rename information, and revision history.
1608 permissions, copy/rename information, and revision history.
1609
1609
1610 Returns 0 on success, 1 if no changes found.
1610 Returns 0 on success, 1 if no changes found.
1611 """
1611 """
1612
1612
1613 revs = None
1613 revs = None
1614 if 'rev' in opts:
1614 if 'rev' in opts:
1615 revstrings = opts['rev']
1615 revstrings = opts['rev']
1616 revs = logcmdutil.revrange(repo, revstrings)
1616 revs = logcmdutil.revrange(repo, revstrings)
1617 if revstrings and not revs:
1617 if revstrings and not revs:
1618 raise error.InputError(_(b'no commits to bundle'))
1618 raise error.InputError(_(b'no commits to bundle'))
1619
1619
1620 bundletype = opts.get('type', b'bzip2').lower()
1620 bundletype = opts.get('type', b'bzip2').lower()
1621 try:
1621 try:
1622 bundlespec = bundlecaches.parsebundlespec(
1622 bundlespec = bundlecaches.parsebundlespec(
1623 repo, bundletype, strict=False
1623 repo, bundletype, strict=False
1624 )
1624 )
1625 except error.UnsupportedBundleSpecification as e:
1625 except error.UnsupportedBundleSpecification as e:
1626 raise error.InputError(
1626 raise error.InputError(
1627 pycompat.bytestr(e),
1627 pycompat.bytestr(e),
1628 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1628 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1629 )
1629 )
1630 cgversion = bundlespec.params[b"cg.version"]
1630 cgversion = bundlespec.params[b"cg.version"]
1631
1631
1632 # Packed bundles are a pseudo bundle format for now.
1632 # Packed bundles are a pseudo bundle format for now.
1633 if cgversion == b's1':
1633 if cgversion == b's1':
1634 raise error.InputError(
1634 raise error.InputError(
1635 _(b'packed bundles cannot be produced by "hg bundle"'),
1635 _(b'packed bundles cannot be produced by "hg bundle"'),
1636 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1636 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1637 )
1637 )
1638 base_opt = opts.get('base')
1638 base_opt = opts.get('base')
1639 if opts.get('all'):
1639 if opts.get('all'):
1640 if dests:
1640 if dests:
1641 raise error.InputError(
1641 raise error.InputError(
1642 _(b"--all is incompatible with specifying destinations")
1642 _(b"--all is incompatible with specifying destinations")
1643 )
1643 )
1644 if base_opt:
1644 if base_opt:
1645 ui.warn(_(b"ignoring --base because --all was specified\n"))
1645 ui.warn(_(b"ignoring --base because --all was specified\n"))
1646 if opts.get('exact'):
1646 if opts.get('exact'):
1647 ui.warn(_(b"ignoring --exact because --all was specified\n"))
1647 ui.warn(_(b"ignoring --exact because --all was specified\n"))
1648 base = [nullrev]
1648 base = [nullrev]
1649 elif opts.get('exact'):
1649 elif opts.get('exact'):
1650 if dests:
1650 if dests:
1651 raise error.InputError(
1651 raise error.InputError(
1652 _(b"--exact is incompatible with specifying destinations")
1652 _(b"--exact is incompatible with specifying destinations")
1653 )
1653 )
1654 if base_opt:
1654 if base_opt:
1655 ui.warn(_(b"ignoring --base because --exact was specified\n"))
1655 ui.warn(_(b"ignoring --base because --exact was specified\n"))
1656 base = repo.revs(b'parents(%ld) - %ld', revs, revs)
1656 base = repo.revs(b'parents(%ld) - %ld', revs, revs)
1657 if not base:
1657 if not base:
1658 base = [nullrev]
1658 base = [nullrev]
1659 elif base_opt:
1659 elif base_opt:
1660 base = logcmdutil.revrange(repo, base_opt)
1660 base = logcmdutil.revrange(repo, base_opt)
1661 if not base:
1661 if not base:
1662 # base specified, but nothing was selected
1662 # base specified, but nothing was selected
1663 base = [nullrev]
1663 base = [nullrev]
1664 else:
1664 else:
1665 base = None
1665 base = None
1666 if cgversion not in changegroup.supportedoutgoingversions(repo):
1666 if cgversion not in changegroup.supportedoutgoingversions(repo):
1667 raise error.Abort(
1667 raise error.Abort(
1668 _(b"repository does not support bundle version %s") % cgversion
1668 _(b"repository does not support bundle version %s") % cgversion
1669 )
1669 )
1670
1670
1671 if base is not None:
1671 if base is not None:
1672 if dests:
1672 if dests:
1673 raise error.InputError(
1673 raise error.InputError(
1674 _(b"--base is incompatible with specifying destinations")
1674 _(b"--base is incompatible with specifying destinations")
1675 )
1675 )
1676 cl = repo.changelog
1676 cl = repo.changelog
1677 common = [cl.node(rev) for rev in base]
1677 common = [cl.node(rev) for rev in base]
1678 heads = [cl.node(r) for r in revs] if revs else None
1678 heads = [cl.node(r) for r in revs] if revs else None
1679 outgoing = discovery.outgoing(repo, common, heads)
1679 outgoing = discovery.outgoing(repo, common, heads)
1680 missing = outgoing.missing
1680 missing = outgoing.missing
1681 excluded = outgoing.excluded
1681 excluded = outgoing.excluded
1682 else:
1682 else:
1683 missing = set()
1683 missing = set()
1684 excluded = set()
1684 excluded = set()
1685 for path in urlutil.get_push_paths(repo, ui, dests):
1685 for path in urlutil.get_push_paths(repo, ui, dests):
1686 other = hg.peer(repo, pycompat.byteskwargs(opts), path)
1686 other = hg.peer(repo, pycompat.byteskwargs(opts), path)
1687 if revs is not None:
1687 if revs is not None:
1688 hex_revs = [repo[r].hex() for r in revs]
1688 hex_revs = [repo[r].hex() for r in revs]
1689 else:
1689 else:
1690 hex_revs = None
1690 hex_revs = None
1691 branches = (path.branch, [])
1691 branches = (path.branch, [])
1692 head_revs, checkout = hg.addbranchrevs(
1692 head_revs, checkout = hg.addbranchrevs(
1693 repo, repo, branches, hex_revs
1693 repo, repo, branches, hex_revs
1694 )
1694 )
1695 heads = (
1695 heads = (
1696 head_revs
1696 head_revs
1697 and pycompat.maplist(repo.lookup, head_revs)
1697 and pycompat.maplist(repo.lookup, head_revs)
1698 or head_revs
1698 or head_revs
1699 )
1699 )
1700 outgoing = discovery.findcommonoutgoing(
1700 outgoing = discovery.findcommonoutgoing(
1701 repo,
1701 repo,
1702 other,
1702 other,
1703 onlyheads=heads,
1703 onlyheads=heads,
1704 force=opts.get('force'),
1704 force=opts.get('force'),
1705 portable=True,
1705 portable=True,
1706 )
1706 )
1707 missing.update(outgoing.missing)
1707 missing.update(outgoing.missing)
1708 excluded.update(outgoing.excluded)
1708 excluded.update(outgoing.excluded)
1709
1709
1710 if not missing:
1710 if not missing:
1711 scmutil.nochangesfound(ui, repo, not base and excluded)
1711 scmutil.nochangesfound(ui, repo, not base and excluded)
1712 return 1
1712 return 1
1713
1713
1714 # internal changeset are internal implementation details that should not
1714 # internal changeset are internal implementation details that should not
1715 # leave the repository. Bundling with `hg bundle` create such risk.
1715 # leave the repository. Bundling with `hg bundle` create such risk.
1716 bundled_internal = repo.revs(b"%ln and _internal()", missing)
1716 bundled_internal = repo.revs(b"%ln and _internal()", missing)
1717 if bundled_internal:
1717 if bundled_internal:
1718 msg = _(b"cannot bundle internal changesets")
1718 msg = _(b"cannot bundle internal changesets")
1719 hint = _(b"%d internal changesets selected") % len(bundled_internal)
1719 hint = _(b"%d internal changesets selected") % len(bundled_internal)
1720 raise error.Abort(msg, hint=hint)
1720 raise error.Abort(msg, hint=hint)
1721
1721
1722 if heads:
1722 if heads:
1723 outgoing = discovery.outgoing(
1723 outgoing = discovery.outgoing(
1724 repo, missingroots=missing, ancestorsof=heads
1724 repo, missingroots=missing, ancestorsof=heads
1725 )
1725 )
1726 else:
1726 else:
1727 outgoing = discovery.outgoing(repo, missingroots=missing)
1727 outgoing = discovery.outgoing(repo, missingroots=missing)
1728 outgoing.excluded = sorted(excluded)
1728 outgoing.excluded = sorted(excluded)
1729
1729
1730 if cgversion == b'01': # bundle1
1730 if cgversion == b'01': # bundle1
1731 bversion = b'HG10' + bundlespec.wirecompression
1731 bversion = b'HG10' + bundlespec.wirecompression
1732 bcompression = None
1732 bcompression = None
1733 elif cgversion in (b'02', b'03'):
1733 elif cgversion in (b'02', b'03'):
1734 bversion = b'HG20'
1734 bversion = b'HG20'
1735 bcompression = bundlespec.wirecompression
1735 bcompression = bundlespec.wirecompression
1736 else:
1736 else:
1737 raise error.ProgrammingError(
1737 raise error.ProgrammingError(
1738 b'bundle: unexpected changegroup version %s' % cgversion
1738 b'bundle: unexpected changegroup version %s' % cgversion
1739 )
1739 )
1740
1740
1741 # TODO compression options should be derived from bundlespec parsing.
1741 # TODO compression options should be derived from bundlespec parsing.
1742 # This is a temporary hack to allow adjusting bundle compression
1742 # This is a temporary hack to allow adjusting bundle compression
1743 # level without a) formalizing the bundlespec changes to declare it
1743 # level without a) formalizing the bundlespec changes to declare it
1744 # b) introducing a command flag.
1744 # b) introducing a command flag.
1745 compopts = {}
1745 compopts = {}
1746 complevel = ui.configint(
1746 complevel = ui.configint(
1747 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1747 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1748 )
1748 )
1749 if complevel is None:
1749 if complevel is None:
1750 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1750 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1751 if complevel is not None:
1751 if complevel is not None:
1752 compopts[b'level'] = complevel
1752 compopts[b'level'] = complevel
1753
1753
1754 compthreads = ui.configint(
1754 compthreads = ui.configint(
1755 b'experimental', b'bundlecompthreads.' + bundlespec.compression
1755 b'experimental', b'bundlecompthreads.' + bundlespec.compression
1756 )
1756 )
1757 if compthreads is None:
1757 if compthreads is None:
1758 compthreads = ui.configint(b'experimental', b'bundlecompthreads')
1758 compthreads = ui.configint(b'experimental', b'bundlecompthreads')
1759 if compthreads is not None:
1759 if compthreads is not None:
1760 compopts[b'threads'] = compthreads
1760 compopts[b'threads'] = compthreads
1761
1761
1762 # Bundling of obsmarker and phases is optional as not all clients
1762 # Bundling of obsmarker and phases is optional as not all clients
1763 # support the necessary features.
1763 # support the necessary features.
1764 cfg = ui.configbool
1764 cfg = ui.configbool
1765 obsolescence_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker')
1765 obsolescence_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker')
1766 bundlespec.set_param(b'obsolescence', obsolescence_cfg, overwrite=False)
1766 bundlespec.set_param(b'obsolescence', obsolescence_cfg, overwrite=False)
1767 obs_mand_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker:mandatory')
1767 obs_mand_cfg = cfg(b'experimental', b'evolution.bundle-obsmarker:mandatory')
1768 bundlespec.set_param(
1768 bundlespec.set_param(
1769 b'obsolescence-mandatory', obs_mand_cfg, overwrite=False
1769 b'obsolescence-mandatory', obs_mand_cfg, overwrite=False
1770 )
1770 )
1771 if not bundlespec.params.get(b'phases', False):
1771 if not bundlespec.params.get(b'phases', False):
1772 phases_cfg = cfg(b'experimental', b'bundle-phases')
1772 phases_cfg = cfg(b'experimental', b'bundle-phases')
1773 bundlespec.set_param(b'phases', phases_cfg, overwrite=False)
1773 bundlespec.set_param(b'phases', phases_cfg, overwrite=False)
1774
1774
1775 bundle2.writenewbundle(
1775 bundle2.writenewbundle(
1776 ui,
1776 ui,
1777 repo,
1777 repo,
1778 b'bundle',
1778 b'bundle',
1779 fname,
1779 fname,
1780 bversion,
1780 bversion,
1781 outgoing,
1781 outgoing,
1782 bundlespec.params,
1782 bundlespec.params,
1783 compression=bcompression,
1783 compression=bcompression,
1784 compopts=compopts,
1784 compopts=compopts,
1785 )
1785 )
1786
1786
1787
1787
1788 @command(
1788 @command(
1789 b'cat',
1789 b'cat',
1790 [
1790 [
1791 (
1791 (
1792 b'o',
1792 b'o',
1793 b'output',
1793 b'output',
1794 b'',
1794 b'',
1795 _(b'print output to file with formatted name'),
1795 _(b'print output to file with formatted name'),
1796 _(b'FORMAT'),
1796 _(b'FORMAT'),
1797 ),
1797 ),
1798 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1798 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1799 (b'', b'decode', None, _(b'apply any matching decode filter')),
1799 (b'', b'decode', None, _(b'apply any matching decode filter')),
1800 ]
1800 ]
1801 + walkopts
1801 + walkopts
1802 + formatteropts,
1802 + formatteropts,
1803 _(b'[OPTION]... FILE...'),
1803 _(b'[OPTION]... FILE...'),
1804 helpcategory=command.CATEGORY_FILE_CONTENTS,
1804 helpcategory=command.CATEGORY_FILE_CONTENTS,
1805 inferrepo=True,
1805 inferrepo=True,
1806 intents={INTENT_READONLY},
1806 intents={INTENT_READONLY},
1807 )
1807 )
1808 def cat(ui, repo, file1, *pats, **opts):
1808 def cat(ui, repo, file1, *pats, **opts):
1809 """output the current or given revision of files
1809 """output the current or given revision of files
1810
1810
1811 Print the specified files as they were at the given revision. If
1811 Print the specified files as they were at the given revision. If
1812 no revision is given, the parent of the working directory is used.
1812 no revision is given, the parent of the working directory is used.
1813
1813
1814 Output may be to a file, in which case the name of the file is
1814 Output may be to a file, in which case the name of the file is
1815 given using a template string. See :hg:`help templates`. In addition
1815 given using a template string. See :hg:`help templates`. In addition
1816 to the common template keywords, the following formatting rules are
1816 to the common template keywords, the following formatting rules are
1817 supported:
1817 supported:
1818
1818
1819 :``%%``: literal "%" character
1819 :``%%``: literal "%" character
1820 :``%s``: basename of file being printed
1820 :``%s``: basename of file being printed
1821 :``%d``: dirname of file being printed, or '.' if in repository root
1821 :``%d``: dirname of file being printed, or '.' if in repository root
1822 :``%p``: root-relative path name of file being printed
1822 :``%p``: root-relative path name of file being printed
1823 :``%H``: changeset hash (40 hexadecimal digits)
1823 :``%H``: changeset hash (40 hexadecimal digits)
1824 :``%R``: changeset revision number
1824 :``%R``: changeset revision number
1825 :``%h``: short-form changeset hash (12 hexadecimal digits)
1825 :``%h``: short-form changeset hash (12 hexadecimal digits)
1826 :``%r``: zero-padded changeset revision number
1826 :``%r``: zero-padded changeset revision number
1827 :``%b``: basename of the exporting repository
1827 :``%b``: basename of the exporting repository
1828 :``\\``: literal "\\" character
1828 :``\\``: literal "\\" character
1829
1829
1830 .. container:: verbose
1830 .. container:: verbose
1831
1831
1832 Template:
1832 Template:
1833
1833
1834 The following keywords are supported in addition to the common template
1834 The following keywords are supported in addition to the common template
1835 keywords and functions. See also :hg:`help templates`.
1835 keywords and functions. See also :hg:`help templates`.
1836
1836
1837 :data: String. File content.
1837 :data: String. File content.
1838 :path: String. Repository-absolute path of the file.
1838 :path: String. Repository-absolute path of the file.
1839
1839
1840 Returns 0 on success.
1840 Returns 0 on success.
1841 """
1841 """
1842 rev = opts.get('rev')
1842 rev = opts.get('rev')
1843 if rev:
1843 if rev:
1844 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1844 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1845 ctx = logcmdutil.revsingle(repo, rev)
1845 ctx = logcmdutil.revsingle(repo, rev)
1846 m = scmutil.match(ctx, (file1,) + pats, pycompat.byteskwargs(opts))
1846 m = scmutil.match(ctx, (file1,) + pats, pycompat.byteskwargs(opts))
1847 fntemplate = opts.pop('output', b'')
1847 fntemplate = opts.pop('output', b'')
1848 if cmdutil.isstdiofilename(fntemplate):
1848 if cmdutil.isstdiofilename(fntemplate):
1849 fntemplate = b''
1849 fntemplate = b''
1850
1850
1851 if fntemplate:
1851 if fntemplate:
1852 fm = formatter.nullformatter(ui, b'cat', pycompat.byteskwargs(opts))
1852 fm = formatter.nullformatter(ui, b'cat', pycompat.byteskwargs(opts))
1853 else:
1853 else:
1854 ui.pager(b'cat')
1854 ui.pager(b'cat')
1855 fm = ui.formatter(b'cat', pycompat.byteskwargs(opts))
1855 fm = ui.formatter(b'cat', pycompat.byteskwargs(opts))
1856 with fm:
1856 with fm:
1857 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, b'', **opts)
1857 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, b'', **opts)
1858
1858
1859
1859
1860 @command(
1860 @command(
1861 b'clone',
1861 b'clone',
1862 [
1862 [
1863 (
1863 (
1864 b'U',
1864 b'U',
1865 b'noupdate',
1865 b'noupdate',
1866 None,
1866 None,
1867 _(
1867 _(
1868 b'the clone will include an empty working '
1868 b'the clone will include an empty working '
1869 b'directory (only a repository)'
1869 b'directory (only a repository)'
1870 ),
1870 ),
1871 ),
1871 ),
1872 (
1872 (
1873 b'u',
1873 b'u',
1874 b'updaterev',
1874 b'updaterev',
1875 b'',
1875 b'',
1876 _(b'revision, tag, or branch to check out'),
1876 _(b'revision, tag, or branch to check out'),
1877 _(b'REV'),
1877 _(b'REV'),
1878 ),
1878 ),
1879 (
1879 (
1880 b'r',
1880 b'r',
1881 b'rev',
1881 b'rev',
1882 [],
1882 [],
1883 _(
1883 _(
1884 b'do not clone everything, but include this changeset'
1884 b'do not clone everything, but include this changeset'
1885 b' and its ancestors'
1885 b' and its ancestors'
1886 ),
1886 ),
1887 _(b'REV'),
1887 _(b'REV'),
1888 ),
1888 ),
1889 (
1889 (
1890 b'b',
1890 b'b',
1891 b'branch',
1891 b'branch',
1892 [],
1892 [],
1893 _(
1893 _(
1894 b'do not clone everything, but include this branch\'s'
1894 b'do not clone everything, but include this branch\'s'
1895 b' changesets and their ancestors'
1895 b' changesets and their ancestors'
1896 ),
1896 ),
1897 _(b'BRANCH'),
1897 _(b'BRANCH'),
1898 ),
1898 ),
1899 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1899 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1900 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1900 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1901 (b'', b'stream', None, _(b'clone with minimal data processing')),
1901 (b'', b'stream', None, _(b'clone with minimal data processing')),
1902 ]
1902 ]
1903 + remoteopts,
1903 + remoteopts,
1904 _(b'[OPTION]... SOURCE [DEST]'),
1904 _(b'[OPTION]... SOURCE [DEST]'),
1905 helpcategory=command.CATEGORY_REPO_CREATION,
1905 helpcategory=command.CATEGORY_REPO_CREATION,
1906 helpbasic=True,
1906 helpbasic=True,
1907 norepo=True,
1907 norepo=True,
1908 )
1908 )
1909 def clone(ui, source, dest=None, **opts):
1909 def clone(ui, source, dest=None, **opts):
1910 """make a copy of an existing repository
1910 """make a copy of an existing repository
1911
1911
1912 Create a copy of an existing repository in a new directory.
1912 Create a copy of an existing repository in a new directory.
1913
1913
1914 If no destination directory name is specified, it defaults to the
1914 If no destination directory name is specified, it defaults to the
1915 basename of the source.
1915 basename of the source.
1916
1916
1917 The location of the source is added to the new repository's
1917 The location of the source is added to the new repository's
1918 ``.hg/hgrc`` file, as the default to be used for future pulls.
1918 ``.hg/hgrc`` file, as the default to be used for future pulls.
1919
1919
1920 Only local paths and ``ssh://`` URLs are supported as
1920 Only local paths and ``ssh://`` URLs are supported as
1921 destinations. For ``ssh://`` destinations, no working directory or
1921 destinations. For ``ssh://`` destinations, no working directory or
1922 ``.hg/hgrc`` will be created on the remote side.
1922 ``.hg/hgrc`` will be created on the remote side.
1923
1923
1924 If the source repository has a bookmark called '@' set, that
1924 If the source repository has a bookmark called '@' set, that
1925 revision will be checked out in the new repository by default.
1925 revision will be checked out in the new repository by default.
1926
1926
1927 To check out a particular version, use -u/--update, or
1927 To check out a particular version, use -u/--update, or
1928 -U/--noupdate to create a clone with no working directory.
1928 -U/--noupdate to create a clone with no working directory.
1929
1929
1930 To pull only a subset of changesets, specify one or more revisions
1930 To pull only a subset of changesets, specify one or more revisions
1931 identifiers with -r/--rev or branches with -b/--branch. The
1931 identifiers with -r/--rev or branches with -b/--branch. The
1932 resulting clone will contain only the specified changesets and
1932 resulting clone will contain only the specified changesets and
1933 their ancestors. These options (or 'clone src#rev dest') imply
1933 their ancestors. These options (or 'clone src#rev dest') imply
1934 --pull, even for local source repositories.
1934 --pull, even for local source repositories.
1935
1935
1936 In normal clone mode, the remote normalizes repository data into a common
1936 In normal clone mode, the remote normalizes repository data into a common
1937 exchange format and the receiving end translates this data into its local
1937 exchange format and the receiving end translates this data into its local
1938 storage format. --stream activates a different clone mode that essentially
1938 storage format. --stream activates a different clone mode that essentially
1939 copies repository files from the remote with minimal data processing. This
1939 copies repository files from the remote with minimal data processing. This
1940 significantly reduces the CPU cost of a clone both remotely and locally.
1940 significantly reduces the CPU cost of a clone both remotely and locally.
1941 However, it often increases the transferred data size by 30-40%. This can
1941 However, it often increases the transferred data size by 30-40%. This can
1942 result in substantially faster clones where I/O throughput is plentiful,
1942 result in substantially faster clones where I/O throughput is plentiful,
1943 especially for larger repositories. A side-effect of --stream clones is
1943 especially for larger repositories. A side-effect of --stream clones is
1944 that storage settings and requirements on the remote are applied locally:
1944 that storage settings and requirements on the remote are applied locally:
1945 a modern client may inherit legacy or inefficient storage used by the
1945 a modern client may inherit legacy or inefficient storage used by the
1946 remote or a legacy Mercurial client may not be able to clone from a
1946 remote or a legacy Mercurial client may not be able to clone from a
1947 modern Mercurial remote.
1947 modern Mercurial remote.
1948
1948
1949 .. note::
1949 .. note::
1950
1950
1951 Specifying a tag will include the tagged changeset but not the
1951 Specifying a tag will include the tagged changeset but not the
1952 changeset containing the tag.
1952 changeset containing the tag.
1953
1953
1954 .. container:: verbose
1954 .. container:: verbose
1955
1955
1956 For efficiency, hardlinks are used for cloning whenever the
1956 For efficiency, hardlinks are used for cloning whenever the
1957 source and destination are on the same filesystem (note this
1957 source and destination are on the same filesystem (note this
1958 applies only to the repository data, not to the working
1958 applies only to the repository data, not to the working
1959 directory). Some filesystems, such as AFS, implement hardlinking
1959 directory). Some filesystems, such as AFS, implement hardlinking
1960 incorrectly, but do not report errors. In these cases, use the
1960 incorrectly, but do not report errors. In these cases, use the
1961 --pull option to avoid hardlinking.
1961 --pull option to avoid hardlinking.
1962
1962
1963 Mercurial will update the working directory to the first applicable
1963 Mercurial will update the working directory to the first applicable
1964 revision from this list:
1964 revision from this list:
1965
1965
1966 a) null if -U or the source repository has no changesets
1966 a) null if -U or the source repository has no changesets
1967 b) if -u . and the source repository is local, the first parent of
1967 b) if -u . and the source repository is local, the first parent of
1968 the source repository's working directory
1968 the source repository's working directory
1969 c) the changeset specified with -u (if a branch name, this means the
1969 c) the changeset specified with -u (if a branch name, this means the
1970 latest head of that branch)
1970 latest head of that branch)
1971 d) the changeset specified with -r
1971 d) the changeset specified with -r
1972 e) the tipmost head specified with -b
1972 e) the tipmost head specified with -b
1973 f) the tipmost head specified with the url#branch source syntax
1973 f) the tipmost head specified with the url#branch source syntax
1974 g) the revision marked with the '@' bookmark, if present
1974 g) the revision marked with the '@' bookmark, if present
1975 h) the tipmost head of the default branch
1975 h) the tipmost head of the default branch
1976 i) tip
1976 i) tip
1977
1977
1978 When cloning from servers that support it, Mercurial may fetch
1978 When cloning from servers that support it, Mercurial may fetch
1979 pre-generated data from a server-advertised URL or inline from the
1979 pre-generated data from a server-advertised URL or inline from the
1980 same stream. When this is done, hooks operating on incoming changesets
1980 same stream. When this is done, hooks operating on incoming changesets
1981 and changegroups may fire more than once, once for each pre-generated
1981 and changegroups may fire more than once, once for each pre-generated
1982 bundle and as well as for any additional remaining data. In addition,
1982 bundle and as well as for any additional remaining data. In addition,
1983 if an error occurs, the repository may be rolled back to a partial
1983 if an error occurs, the repository may be rolled back to a partial
1984 clone. This behavior may change in future releases.
1984 clone. This behavior may change in future releases.
1985 See :hg:`help -e clonebundles` for more.
1985 See :hg:`help -e clonebundles` for more.
1986
1986
1987 Examples:
1987 Examples:
1988
1988
1989 - clone a remote repository to a new directory named hg/::
1989 - clone a remote repository to a new directory named hg/::
1990
1990
1991 hg clone https://www.mercurial-scm.org/repo/hg/
1991 hg clone https://www.mercurial-scm.org/repo/hg/
1992
1992
1993 - create a lightweight local clone::
1993 - create a lightweight local clone::
1994
1994
1995 hg clone project/ project-feature/
1995 hg clone project/ project-feature/
1996
1996
1997 - clone from an absolute path on an ssh server (note double-slash)::
1997 - clone from an absolute path on an ssh server (note double-slash)::
1998
1998
1999 hg clone ssh://user@server//home/projects/alpha/
1999 hg clone ssh://user@server//home/projects/alpha/
2000
2000
2001 - do a streaming clone while checking out a specified version::
2001 - do a streaming clone while checking out a specified version::
2002
2002
2003 hg clone --stream http://server/repo -u 1.5
2003 hg clone --stream http://server/repo -u 1.5
2004
2004
2005 - create a repository without changesets after a particular revision::
2005 - create a repository without changesets after a particular revision::
2006
2006
2007 hg clone -r 04e544 experimental/ good/
2007 hg clone -r 04e544 experimental/ good/
2008
2008
2009 - clone (and track) a particular named branch::
2009 - clone (and track) a particular named branch::
2010
2010
2011 hg clone https://www.mercurial-scm.org/repo/hg/#stable
2011 hg clone https://www.mercurial-scm.org/repo/hg/#stable
2012
2012
2013 See :hg:`help urls` for details on specifying URLs.
2013 See :hg:`help urls` for details on specifying URLs.
2014
2014
2015 Returns 0 on success.
2015 Returns 0 on success.
2016 """
2016 """
2017 cmdutil.check_at_most_one_arg(opts, 'noupdate', 'updaterev')
2017 cmdutil.check_at_most_one_arg(opts, 'noupdate', 'updaterev')
2018
2018
2019 # --include/--exclude can come from narrow or sparse.
2019 # --include/--exclude can come from narrow or sparse.
2020 includepats, excludepats = None, None
2020 includepats, excludepats = None, None
2021
2021
2022 # hg.clone() differentiates between None and an empty set. So make sure
2022 # hg.clone() differentiates between None and an empty set. So make sure
2023 # patterns are sets if narrow is requested without patterns.
2023 # patterns are sets if narrow is requested without patterns.
2024 if opts.get('narrow'):
2024 if opts.get('narrow'):
2025 includepats = set()
2025 includepats = set()
2026 excludepats = set()
2026 excludepats = set()
2027
2027
2028 if opts.get('include'):
2028 if opts.get('include'):
2029 includepats = narrowspec.parsepatterns(opts.get('include'))
2029 includepats = narrowspec.parsepatterns(opts.get('include'))
2030 if opts.get('exclude'):
2030 if opts.get('exclude'):
2031 excludepats = narrowspec.parsepatterns(opts.get('exclude'))
2031 excludepats = narrowspec.parsepatterns(opts.get('exclude'))
2032
2032
2033 r = hg.clone(
2033 r = hg.clone(
2034 ui,
2034 ui,
2035 pycompat.byteskwargs(opts),
2035 pycompat.byteskwargs(opts),
2036 source,
2036 source,
2037 dest,
2037 dest,
2038 pull=opts.get('pull'),
2038 pull=opts.get('pull'),
2039 stream=opts.get('stream') or opts.get('uncompressed'),
2039 stream=opts.get('stream') or opts.get('uncompressed'),
2040 revs=opts.get('rev'),
2040 revs=opts.get('rev'),
2041 update=opts.get('updaterev') or not opts.get('noupdate'),
2041 update=opts.get('updaterev') or not opts.get('noupdate'),
2042 branch=opts.get('branch'),
2042 branch=opts.get('branch'),
2043 shareopts=opts.get('shareopts'),
2043 shareopts=opts.get('shareopts'),
2044 storeincludepats=includepats,
2044 storeincludepats=includepats,
2045 storeexcludepats=excludepats,
2045 storeexcludepats=excludepats,
2046 depth=opts.get('depth') or None,
2046 depth=opts.get('depth') or None,
2047 )
2047 )
2048
2048
2049 return r is None
2049 return r is None
2050
2050
2051
2051
2052 @command(
2052 @command(
2053 b'commit|ci',
2053 b'commit|ci',
2054 [
2054 [
2055 (
2055 (
2056 b'A',
2056 b'A',
2057 b'addremove',
2057 b'addremove',
2058 None,
2058 None,
2059 _(b'mark new/missing files as added/removed before committing'),
2059 _(b'mark new/missing files as added/removed before committing'),
2060 ),
2060 ),
2061 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
2061 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
2062 (b'', b'amend', None, _(b'amend the parent of the working directory')),
2062 (b'', b'amend', None, _(b'amend the parent of the working directory')),
2063 (b's', b'secret', None, _(b'use the secret phase for committing')),
2063 (b's', b'secret', None, _(b'use the secret phase for committing')),
2064 (b'', b'draft', None, _(b'use the draft phase for committing')),
2064 (b'', b'draft', None, _(b'use the draft phase for committing')),
2065 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
2065 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
2066 (
2066 (
2067 b'',
2067 b'',
2068 b'force-close-branch',
2068 b'force-close-branch',
2069 None,
2069 None,
2070 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
2070 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
2071 ),
2071 ),
2072 (b'i', b'interactive', None, _(b'use interactive mode')),
2072 (b'i', b'interactive', None, _(b'use interactive mode')),
2073 ]
2073 ]
2074 + walkopts
2074 + walkopts
2075 + commitopts
2075 + commitopts
2076 + commitopts2
2076 + commitopts2
2077 + subrepoopts,
2077 + subrepoopts,
2078 _(b'[OPTION]... [FILE]...'),
2078 _(b'[OPTION]... [FILE]...'),
2079 helpcategory=command.CATEGORY_COMMITTING,
2079 helpcategory=command.CATEGORY_COMMITTING,
2080 helpbasic=True,
2080 helpbasic=True,
2081 inferrepo=True,
2081 inferrepo=True,
2082 )
2082 )
2083 def commit(ui, repo, *pats, **opts):
2083 def commit(ui, repo, *pats, **opts):
2084 """commit the specified files or all outstanding changes
2084 """commit the specified files or all outstanding changes
2085
2085
2086 Commit changes to the given files into the repository. Unlike a
2086 Commit changes to the given files into the repository. Unlike a
2087 centralized SCM, this operation is a local operation. See
2087 centralized SCM, this operation is a local operation. See
2088 :hg:`push` for a way to actively distribute your changes.
2088 :hg:`push` for a way to actively distribute your changes.
2089
2089
2090 If a list of files is omitted, all changes reported by :hg:`status`
2090 If a list of files is omitted, all changes reported by :hg:`status`
2091 will be committed.
2091 will be committed.
2092
2092
2093 If you are committing the result of a merge, do not provide any
2093 If you are committing the result of a merge, do not provide any
2094 filenames or -I/-X filters.
2094 filenames or -I/-X filters.
2095
2095
2096 If no commit message is specified, Mercurial starts your
2096 If no commit message is specified, Mercurial starts your
2097 configured editor where you can enter a message. In case your
2097 configured editor where you can enter a message. In case your
2098 commit fails, you will find a backup of your message in
2098 commit fails, you will find a backup of your message in
2099 ``.hg/last-message.txt``.
2099 ``.hg/last-message.txt``.
2100
2100
2101 The --close-branch flag can be used to mark the current branch
2101 The --close-branch flag can be used to mark the current branch
2102 head closed. When all heads of a branch are closed, the branch
2102 head closed. When all heads of a branch are closed, the branch
2103 will be considered closed and no longer listed.
2103 will be considered closed and no longer listed.
2104
2104
2105 The --amend flag can be used to amend the parent of the
2105 The --amend flag can be used to amend the parent of the
2106 working directory with a new commit that contains the changes
2106 working directory with a new commit that contains the changes
2107 in the parent in addition to those currently reported by :hg:`status`,
2107 in the parent in addition to those currently reported by :hg:`status`,
2108 if there are any. The old commit is stored in a backup bundle in
2108 if there are any. The old commit is stored in a backup bundle in
2109 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2109 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2110 on how to restore it).
2110 on how to restore it).
2111
2111
2112 Message, user and date are taken from the amended commit unless
2112 Message, user and date are taken from the amended commit unless
2113 specified. When a message isn't specified on the command line,
2113 specified. When a message isn't specified on the command line,
2114 the editor will open with the message of the amended commit.
2114 the editor will open with the message of the amended commit.
2115
2115
2116 It is not possible to amend public changesets (see :hg:`help phases`)
2116 It is not possible to amend public changesets (see :hg:`help phases`)
2117 or changesets that have children.
2117 or changesets that have children.
2118
2118
2119 See :hg:`help dates` for a list of formats valid for -d/--date.
2119 See :hg:`help dates` for a list of formats valid for -d/--date.
2120
2120
2121 Returns 0 on success, 1 if nothing changed.
2121 Returns 0 on success, 1 if nothing changed.
2122
2122
2123 .. container:: verbose
2123 .. container:: verbose
2124
2124
2125 Examples:
2125 Examples:
2126
2126
2127 - commit all files ending in .py::
2127 - commit all files ending in .py::
2128
2128
2129 hg commit --include "set:**.py"
2129 hg commit --include "set:**.py"
2130
2130
2131 - commit all non-binary files::
2131 - commit all non-binary files::
2132
2132
2133 hg commit --exclude "set:binary()"
2133 hg commit --exclude "set:binary()"
2134
2134
2135 - amend the current commit and set the date to now::
2135 - amend the current commit and set the date to now::
2136
2136
2137 hg commit --amend --date now
2137 hg commit --amend --date now
2138 """
2138 """
2139 cmdutil.check_at_most_one_arg(opts, 'draft', 'secret')
2139 cmdutil.check_at_most_one_arg(opts, 'draft', 'secret')
2140 cmdutil.check_incompatible_arguments(opts, 'subrepos', ['amend'])
2140 cmdutil.check_incompatible_arguments(opts, 'subrepos', ['amend'])
2141 with repo.wlock(), repo.lock():
2141 with repo.wlock(), repo.lock():
2142 return _docommit(ui, repo, *pats, **opts)
2142 return _docommit(ui, repo, *pats, **opts)
2143
2143
2144
2144
2145 def _docommit(ui, repo, *pats, **opts):
2145 def _docommit(ui, repo, *pats, **opts):
2146 if opts.get('interactive'):
2146 if opts.get('interactive'):
2147 opts.pop('interactive')
2147 opts.pop('interactive')
2148 ret = cmdutil.dorecord(
2148 ret = cmdutil.dorecord(
2149 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2149 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2150 )
2150 )
2151 # ret can be 0 (no changes to record) or the value returned by
2151 # ret can be 0 (no changes to record) or the value returned by
2152 # commit(), 1 if nothing changed or None on success.
2152 # commit(), 1 if nothing changed or None on success.
2153 return 1 if ret == 0 else ret
2153 return 1 if ret == 0 else ret
2154
2154
2155 if opts.get('subrepos'):
2155 if opts.get('subrepos'):
2156 # Let --subrepos on the command line override config setting.
2156 # Let --subrepos on the command line override config setting.
2157 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2157 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2158
2158
2159 cmdutil.checkunfinished(repo, commit=True)
2159 cmdutil.checkunfinished(repo, commit=True)
2160
2160
2161 branch = repo[None].branch()
2161 branch = repo[None].branch()
2162 bheads = repo.branchheads(branch)
2162 bheads = repo.branchheads(branch)
2163 tip = repo.changelog.tip()
2163 tip = repo.changelog.tip()
2164
2164
2165 extra = {}
2165 extra = {}
2166 if opts.get('close_branch') or opts.get('force_close_branch'):
2166 if opts.get('close_branch') or opts.get('force_close_branch'):
2167 extra[b'close'] = b'1'
2167 extra[b'close'] = b'1'
2168
2168
2169 if repo[b'.'].closesbranch():
2169 if repo[b'.'].closesbranch():
2170 # Not ideal, but let us do an extra status early to prevent early
2170 # Not ideal, but let us do an extra status early to prevent early
2171 # bail out.
2171 # bail out.
2172 matcher = scmutil.match(
2172 matcher = scmutil.match(
2173 repo[None], pats, pycompat.byteskwargs(opts)
2173 repo[None], pats, pycompat.byteskwargs(opts)
2174 )
2174 )
2175 s = repo.status(match=matcher)
2175 s = repo.status(match=matcher)
2176 if s.modified or s.added or s.removed:
2176 if s.modified or s.added or s.removed:
2177 bheads = repo.branchheads(branch, closed=True)
2177 bheads = repo.branchheads(branch, closed=True)
2178 else:
2178 else:
2179 msg = _(b'current revision is already a branch closing head')
2179 msg = _(b'current revision is already a branch closing head')
2180 raise error.InputError(msg)
2180 raise error.InputError(msg)
2181
2181
2182 if not bheads:
2182 if not bheads:
2183 raise error.InputError(
2183 raise error.InputError(
2184 _(b'branch "%s" has no heads to close') % branch
2184 _(b'branch "%s" has no heads to close') % branch
2185 )
2185 )
2186 elif (
2186 elif (
2187 branch == repo[b'.'].branch()
2187 branch == repo[b'.'].branch()
2188 and repo[b'.'].node() not in bheads
2188 and repo[b'.'].node() not in bheads
2189 and not opts.get('force_close_branch')
2189 and not opts.get('force_close_branch')
2190 ):
2190 ):
2191 hint = _(
2191 hint = _(
2192 b'use --force-close-branch to close branch from a non-head'
2192 b'use --force-close-branch to close branch from a non-head'
2193 b' changeset'
2193 b' changeset'
2194 )
2194 )
2195 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2195 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2196 elif opts.get('amend'):
2196 elif opts.get('amend'):
2197 if (
2197 if (
2198 repo[b'.'].p1().branch() != branch
2198 repo[b'.'].p1().branch() != branch
2199 and repo[b'.'].p2().branch() != branch
2199 and repo[b'.'].p2().branch() != branch
2200 ):
2200 ):
2201 raise error.InputError(_(b'can only close branch heads'))
2201 raise error.InputError(_(b'can only close branch heads'))
2202
2202
2203 if opts.get('amend'):
2203 if opts.get('amend'):
2204 if ui.configbool(b'ui', b'commitsubrepos'):
2204 if ui.configbool(b'ui', b'commitsubrepos'):
2205 raise error.InputError(
2205 raise error.InputError(
2206 _(b'cannot amend with ui.commitsubrepos enabled')
2206 _(b'cannot amend with ui.commitsubrepos enabled')
2207 )
2207 )
2208
2208
2209 old = repo[b'.']
2209 old = repo[b'.']
2210 rewriteutil.precheck(repo, [old.rev()], b'amend')
2210 rewriteutil.precheck(repo, [old.rev()], b'amend')
2211
2211
2212 # Currently histedit gets confused if an amend happens while histedit
2212 # Currently histedit gets confused if an amend happens while histedit
2213 # is in progress. Since we have a checkunfinished command, we are
2213 # is in progress. Since we have a checkunfinished command, we are
2214 # temporarily honoring it.
2214 # temporarily honoring it.
2215 #
2215 #
2216 # Note: eventually this guard will be removed. Please do not expect
2216 # Note: eventually this guard will be removed. Please do not expect
2217 # this behavior to remain.
2217 # this behavior to remain.
2218 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2218 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2219 cmdutil.checkunfinished(repo)
2219 cmdutil.checkunfinished(repo)
2220
2220
2221 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2221 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2222 if node == old.node():
2222 if node == old.node():
2223 ui.status(_(b"nothing changed\n"))
2223 ui.status(_(b"nothing changed\n"))
2224 return 1
2224 return 1
2225 else:
2225 else:
2226
2226
2227 def commitfunc(ui, repo, message, match, opts):
2227 def commitfunc(ui, repo, message, match, opts):
2228 overrides = {}
2228 overrides = {}
2229 if opts.get(b'secret'):
2229 if opts.get(b'secret'):
2230 overrides[(b'phases', b'new-commit')] = b'secret'
2230 overrides[(b'phases', b'new-commit')] = b'secret'
2231 elif opts.get(b'draft'):
2231 elif opts.get(b'draft'):
2232 overrides[(b'phases', b'new-commit')] = b'draft'
2232 overrides[(b'phases', b'new-commit')] = b'draft'
2233
2233
2234 baseui = repo.baseui
2234 baseui = repo.baseui
2235 with baseui.configoverride(overrides, b'commit'):
2235 with baseui.configoverride(overrides, b'commit'):
2236 with ui.configoverride(overrides, b'commit'):
2236 with ui.configoverride(overrides, b'commit'):
2237 editform = cmdutil.mergeeditform(
2237 editform = cmdutil.mergeeditform(
2238 repo[None], b'commit.normal'
2238 repo[None], b'commit.normal'
2239 )
2239 )
2240 editor = cmdutil.getcommiteditor(
2240 editor = cmdutil.getcommiteditor(
2241 editform=editform, **pycompat.strkwargs(opts)
2241 editform=editform, **pycompat.strkwargs(opts)
2242 )
2242 )
2243 return repo.commit(
2243 return repo.commit(
2244 message,
2244 message,
2245 opts.get(b'user'),
2245 opts.get(b'user'),
2246 opts.get(b'date'),
2246 opts.get(b'date'),
2247 match,
2247 match,
2248 editor=editor,
2248 editor=editor,
2249 extra=extra,
2249 extra=extra,
2250 )
2250 )
2251
2251
2252 node = cmdutil.commit(
2252 node = cmdutil.commit(
2253 ui, repo, commitfunc, pats, pycompat.byteskwargs(opts)
2253 ui, repo, commitfunc, pats, pycompat.byteskwargs(opts)
2254 )
2254 )
2255
2255
2256 if not node:
2256 if not node:
2257 stat = cmdutil.postcommitstatus(
2257 stat = cmdutil.postcommitstatus(
2258 repo, pats, pycompat.byteskwargs(opts)
2258 repo, pats, pycompat.byteskwargs(opts)
2259 )
2259 )
2260 if stat.deleted:
2260 if stat.deleted:
2261 ui.status(
2261 ui.status(
2262 _(
2262 _(
2263 b"nothing changed (%d missing files, see "
2263 b"nothing changed (%d missing files, see "
2264 b"'hg status')\n"
2264 b"'hg status')\n"
2265 )
2265 )
2266 % len(stat.deleted)
2266 % len(stat.deleted)
2267 )
2267 )
2268 else:
2268 else:
2269 ui.status(_(b"nothing changed\n"))
2269 ui.status(_(b"nothing changed\n"))
2270 return 1
2270 return 1
2271
2271
2272 cmdutil.commitstatus(repo, node, branch, bheads, tip, **opts)
2272 cmdutil.commitstatus(repo, node, branch, bheads, tip, **opts)
2273
2273
2274 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2274 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2275 status(
2275 status(
2276 ui,
2276 ui,
2277 repo,
2277 repo,
2278 modified=True,
2278 modified=True,
2279 added=True,
2279 added=True,
2280 removed=True,
2280 removed=True,
2281 deleted=True,
2281 deleted=True,
2282 unknown=True,
2282 unknown=True,
2283 subrepos=opts.get('subrepos'),
2283 subrepos=opts.get('subrepos'),
2284 )
2284 )
2285
2285
2286
2286
2287 @command(
2287 @command(
2288 b'config|showconfig|debugconfig',
2288 b'config|showconfig|debugconfig',
2289 [
2289 [
2290 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2290 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2291 # This is experimental because we need
2291 # This is experimental because we need
2292 # * reasonable behavior around aliases,
2292 # * reasonable behavior around aliases,
2293 # * decide if we display [debug] [experimental] and [devel] section par
2293 # * decide if we display [debug] [experimental] and [devel] section par
2294 # default
2294 # default
2295 # * some way to display "generic" config entry (the one matching
2295 # * some way to display "generic" config entry (the one matching
2296 # regexp,
2296 # regexp,
2297 # * proper display of the different value type
2297 # * proper display of the different value type
2298 # * a better way to handle <DYNAMIC> values (and variable types),
2298 # * a better way to handle <DYNAMIC> values (and variable types),
2299 # * maybe some type information ?
2299 # * maybe some type information ?
2300 (
2300 (
2301 b'',
2301 b'',
2302 b'exp-all-known',
2302 b'exp-all-known',
2303 None,
2303 None,
2304 _(b'show all known config option (EXPERIMENTAL)'),
2304 _(b'show all known config option (EXPERIMENTAL)'),
2305 ),
2305 ),
2306 (b'e', b'edit', None, _(b'edit user config')),
2306 (b'e', b'edit', None, _(b'edit user config')),
2307 (b'l', b'local', None, _(b'edit repository config')),
2307 (b'l', b'local', None, _(b'edit repository config')),
2308 (b'', b'source', None, _(b'show source of configuration value')),
2308 (b'', b'source', None, _(b'show source of configuration value')),
2309 (
2309 (
2310 b'',
2310 b'',
2311 b'shared',
2311 b'shared',
2312 None,
2312 None,
2313 _(b'edit shared source repository config (EXPERIMENTAL)'),
2313 _(b'edit shared source repository config (EXPERIMENTAL)'),
2314 ),
2314 ),
2315 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2315 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2316 (b'g', b'global', None, _(b'edit global config')),
2316 (b'g', b'global', None, _(b'edit global config')),
2317 ]
2317 ]
2318 + formatteropts,
2318 + formatteropts,
2319 _(b'[-u] [NAME]...'),
2319 _(b'[-u] [NAME]...'),
2320 helpcategory=command.CATEGORY_HELP,
2320 helpcategory=command.CATEGORY_HELP,
2321 optionalrepo=True,
2321 optionalrepo=True,
2322 intents={INTENT_READONLY},
2322 intents={INTENT_READONLY},
2323 )
2323 )
2324 def config(ui, repo, *values, **opts):
2324 def config(ui, repo, *values, **opts):
2325 """show combined config settings from all hgrc files
2325 """show combined config settings from all hgrc files
2326
2326
2327 With no arguments, print names and values of all config items.
2327 With no arguments, print names and values of all config items.
2328
2328
2329 With one argument of the form section.name, print just the value
2329 With one argument of the form section.name, print just the value
2330 of that config item.
2330 of that config item.
2331
2331
2332 With multiple arguments, print names and values of all config
2332 With multiple arguments, print names and values of all config
2333 items with matching section names or section.names.
2333 items with matching section names or section.names.
2334
2334
2335 With --edit, start an editor on the user-level config file. With
2335 With --edit, start an editor on the user-level config file. With
2336 --global, edit the system-wide config file. With --local, edit the
2336 --global, edit the system-wide config file. With --local, edit the
2337 repository-level config file.
2337 repository-level config file.
2338
2338
2339 With --source, the source (filename and line number) is printed
2339 With --source, the source (filename and line number) is printed
2340 for each config item.
2340 for each config item.
2341
2341
2342 See :hg:`help config` for more information about config files.
2342 See :hg:`help config` for more information about config files.
2343
2343
2344 .. container:: verbose
2344 .. container:: verbose
2345
2345
2346 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2346 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2347 This file is not shared across shares when in share-safe mode.
2347 This file is not shared across shares when in share-safe mode.
2348
2348
2349 Template:
2349 Template:
2350
2350
2351 The following keywords are supported. See also :hg:`help templates`.
2351 The following keywords are supported. See also :hg:`help templates`.
2352
2352
2353 :name: String. Config name.
2353 :name: String. Config name.
2354 :source: String. Filename and line number where the item is defined.
2354 :source: String. Filename and line number where the item is defined.
2355 :value: String. Config value.
2355 :value: String. Config value.
2356
2356
2357 The --shared flag can be used to edit the config file of shared source
2357 The --shared flag can be used to edit the config file of shared source
2358 repository. It only works when you have shared using the experimental
2358 repository. It only works when you have shared using the experimental
2359 share safe feature.
2359 share safe feature.
2360
2360
2361 Returns 0 on success, 1 if NAME does not exist.
2361 Returns 0 on success, 1 if NAME does not exist.
2362
2362
2363 """
2363 """
2364
2364
2365 editopts = ('edit', 'local', 'global', 'shared', 'non_shared')
2365 editopts = ('edit', 'local', 'global', 'shared', 'non_shared')
2366 if any(opts.get(o) for o in editopts):
2366 if any(opts.get(o) for o in editopts):
2367 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2367 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2368 if opts.get('local'):
2368 if opts.get('local'):
2369 if not repo:
2369 if not repo:
2370 raise error.InputError(
2370 raise error.InputError(
2371 _(b"can't use --local outside a repository")
2371 _(b"can't use --local outside a repository")
2372 )
2372 )
2373 paths = [repo.vfs.join(b'hgrc')]
2373 paths = [repo.vfs.join(b'hgrc')]
2374 elif opts.get('global'):
2374 elif opts.get('global'):
2375 paths = rcutil.systemrcpath()
2375 paths = rcutil.systemrcpath()
2376 elif opts.get('shared'):
2376 elif opts.get('shared'):
2377 if not repo.shared():
2377 if not repo.shared():
2378 raise error.InputError(
2378 raise error.InputError(
2379 _(b"repository is not shared; can't use --shared")
2379 _(b"repository is not shared; can't use --shared")
2380 )
2380 )
2381 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2381 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2382 raise error.InputError(
2382 raise error.InputError(
2383 _(
2383 _(
2384 b"share safe feature not enabled; "
2384 b"share safe feature not enabled; "
2385 b"unable to edit shared source repository config"
2385 b"unable to edit shared source repository config"
2386 )
2386 )
2387 )
2387 )
2388 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2388 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2389 elif opts.get('non_shared'):
2389 elif opts.get('non_shared'):
2390 paths = [repo.vfs.join(b'hgrc-not-shared')]
2390 paths = [repo.vfs.join(b'hgrc-not-shared')]
2391 else:
2391 else:
2392 paths = rcutil.userrcpath()
2392 paths = rcutil.userrcpath()
2393
2393
2394 for f in paths:
2394 for f in paths:
2395 if os.path.exists(f):
2395 if os.path.exists(f):
2396 break
2396 break
2397 else:
2397 else:
2398 if opts.get('global'):
2398 if opts.get('global'):
2399 samplehgrc = uimod.samplehgrcs[b'global']
2399 samplehgrc = uimod.samplehgrcs[b'global']
2400 elif opts.get('local'):
2400 elif opts.get('local'):
2401 samplehgrc = uimod.samplehgrcs[b'local']
2401 samplehgrc = uimod.samplehgrcs[b'local']
2402 else:
2402 else:
2403 samplehgrc = uimod.samplehgrcs[b'user']
2403 samplehgrc = uimod.samplehgrcs[b'user']
2404
2404
2405 f = paths[0]
2405 f = paths[0]
2406 util.writefile(f, util.tonativeeol(samplehgrc))
2406 util.writefile(f, util.tonativeeol(samplehgrc))
2407
2407
2408 editor = ui.geteditor()
2408 editor = ui.geteditor()
2409 ui.system(
2409 ui.system(
2410 b"%s \"%s\"" % (editor, f),
2410 b"%s \"%s\"" % (editor, f),
2411 onerr=error.InputError,
2411 onerr=error.InputError,
2412 errprefix=_(b"edit failed"),
2412 errprefix=_(b"edit failed"),
2413 blockedtag=b'config_edit',
2413 blockedtag=b'config_edit',
2414 )
2414 )
2415 return
2415 return
2416 ui.pager(b'config')
2416 ui.pager(b'config')
2417 fm = ui.formatter(b'config', pycompat.byteskwargs(opts))
2417 fm = ui.formatter(b'config', pycompat.byteskwargs(opts))
2418 for t, f in rcutil.rccomponents():
2418 for t, f in rcutil.rccomponents():
2419 if t == b'path':
2419 if t == b'path':
2420 ui.debug(b'read config from: %s\n' % f)
2420 ui.debug(b'read config from: %s\n' % f)
2421 elif t == b'resource':
2421 elif t == b'resource':
2422 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2422 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2423 elif t == b'items':
2423 elif t == b'items':
2424 # Don't print anything for 'items'.
2424 # Don't print anything for 'items'.
2425 pass
2425 pass
2426 else:
2426 else:
2427 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2427 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2428 untrusted = bool(opts.get('untrusted'))
2428 untrusted = bool(opts.get('untrusted'))
2429
2429
2430 selsections = selentries = []
2430 selsections = selentries = []
2431 if values:
2431 if values:
2432 selsections = [v for v in values if b'.' not in v]
2432 selsections = [v for v in values if b'.' not in v]
2433 selentries = [v for v in values if b'.' in v]
2433 selentries = [v for v in values if b'.' in v]
2434 uniquesel = len(selentries) == 1 and not selsections
2434 uniquesel = len(selentries) == 1 and not selsections
2435 selsections = set(selsections)
2435 selsections = set(selsections)
2436 selentries = set(selentries)
2436 selentries = set(selentries)
2437
2437
2438 matched = False
2438 matched = False
2439 all_known = opts['exp_all_known']
2439 all_known = opts['exp_all_known']
2440 show_source = ui.debugflag or opts.get('source')
2440 show_source = ui.debugflag or opts.get('source')
2441 entries = ui.walkconfig(untrusted=untrusted, all_known=all_known)
2441 entries = ui.walkconfig(untrusted=untrusted, all_known=all_known)
2442 for section, name, value in entries:
2442 for section, name, value in entries:
2443 source = ui.configsource(section, name, untrusted)
2443 source = ui.configsource(section, name, untrusted)
2444 value = pycompat.bytestr(value)
2444 value = pycompat.bytestr(value)
2445 defaultvalue = ui.configdefault(section, name)
2445 defaultvalue = ui.configdefault(section, name)
2446 if fm.isplain():
2446 if fm.isplain():
2447 source = source or b'none'
2447 source = source or b'none'
2448 value = value.replace(b'\n', b'\\n')
2448 value = value.replace(b'\n', b'\\n')
2449 entryname = section + b'.' + name
2449 entryname = section + b'.' + name
2450 if values and not (section in selsections or entryname in selentries):
2450 if values and not (section in selsections or entryname in selentries):
2451 continue
2451 continue
2452 fm.startitem()
2452 fm.startitem()
2453 fm.condwrite(show_source, b'source', b'%s: ', source)
2453 fm.condwrite(show_source, b'source', b'%s: ', source)
2454 if uniquesel:
2454 if uniquesel:
2455 fm.data(name=entryname)
2455 fm.data(name=entryname)
2456 fm.write(b'value', b'%s\n', value)
2456 fm.write(b'value', b'%s\n', value)
2457 else:
2457 else:
2458 fm.write(b'name value', b'%s=%s\n', entryname, value)
2458 fm.write(b'name value', b'%s=%s\n', entryname, value)
2459 if formatter.isprintable(defaultvalue):
2459 if formatter.isprintable(defaultvalue):
2460 fm.data(defaultvalue=defaultvalue)
2460 fm.data(defaultvalue=defaultvalue)
2461 elif isinstance(defaultvalue, list) and all(
2461 elif isinstance(defaultvalue, list) and all(
2462 formatter.isprintable(e) for e in defaultvalue
2462 formatter.isprintable(e) for e in defaultvalue
2463 ):
2463 ):
2464 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2464 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2465 # TODO: no idea how to process unsupported defaultvalue types
2465 # TODO: no idea how to process unsupported defaultvalue types
2466 matched = True
2466 matched = True
2467 fm.end()
2467 fm.end()
2468 if matched:
2468 if matched:
2469 return 0
2469 return 0
2470 return 1
2470 return 1
2471
2471
2472
2472
2473 @command(
2473 @command(
2474 b'continue',
2474 b'continue',
2475 dryrunopts,
2475 dryrunopts,
2476 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2476 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2477 helpbasic=True,
2477 helpbasic=True,
2478 )
2478 )
2479 def continuecmd(ui, repo, **opts):
2479 def continuecmd(ui, repo, **opts):
2480 """resumes an interrupted operation (EXPERIMENTAL)
2480 """resumes an interrupted operation (EXPERIMENTAL)
2481
2481
2482 Finishes a multistep operation like graft, histedit, rebase, merge,
2482 Finishes a multistep operation like graft, histedit, rebase, merge,
2483 and unshelve if they are in an interrupted state.
2483 and unshelve if they are in an interrupted state.
2484
2484
2485 use --dry-run/-n to dry run the command.
2485 use --dry-run/-n to dry run the command.
2486 """
2486 """
2487 dryrun = opts.get('dry_run')
2487 dryrun = opts.get('dry_run')
2488 contstate = cmdutil.getunfinishedstate(repo)
2488 contstate = cmdutil.getunfinishedstate(repo)
2489 if not contstate:
2489 if not contstate:
2490 raise error.StateError(_(b'no operation in progress'))
2490 raise error.StateError(_(b'no operation in progress'))
2491 if not contstate.continuefunc:
2491 if not contstate.continuefunc:
2492 raise error.StateError(
2492 raise error.StateError(
2493 (
2493 (
2494 _(b"%s in progress but does not support 'hg continue'")
2494 _(b"%s in progress but does not support 'hg continue'")
2495 % (contstate._opname)
2495 % (contstate._opname)
2496 ),
2496 ),
2497 hint=contstate.continuemsg(),
2497 hint=contstate.continuemsg(),
2498 )
2498 )
2499 if dryrun:
2499 if dryrun:
2500 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2500 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2501 return
2501 return
2502 return contstate.continuefunc(ui, repo)
2502 return contstate.continuefunc(ui, repo)
2503
2503
2504
2504
2505 @command(
2505 @command(
2506 b'copy|cp',
2506 b'copy|cp',
2507 [
2507 [
2508 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2508 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2509 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2509 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2510 (
2510 (
2511 b'',
2511 b'',
2512 b'at-rev',
2512 b'at-rev',
2513 b'',
2513 b'',
2514 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2514 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2515 _(b'REV'),
2515 _(b'REV'),
2516 ),
2516 ),
2517 (
2517 (
2518 b'f',
2518 b'f',
2519 b'force',
2519 b'force',
2520 None,
2520 None,
2521 _(b'forcibly copy over an existing managed file'),
2521 _(b'forcibly copy over an existing managed file'),
2522 ),
2522 ),
2523 ]
2523 ]
2524 + walkopts
2524 + walkopts
2525 + dryrunopts,
2525 + dryrunopts,
2526 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2526 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2527 helpcategory=command.CATEGORY_FILE_CONTENTS,
2527 helpcategory=command.CATEGORY_FILE_CONTENTS,
2528 )
2528 )
2529 def copy(ui, repo, *pats, **opts):
2529 def copy(ui, repo, *pats, **opts):
2530 """mark files as copied for the next commit
2530 """mark files as copied for the next commit
2531
2531
2532 Mark dest as having copies of source files. If dest is a
2532 Mark dest as having copies of source files. If dest is a
2533 directory, copies are put in that directory. If dest is a file,
2533 directory, copies are put in that directory. If dest is a file,
2534 the source must be a single file.
2534 the source must be a single file.
2535
2535
2536 By default, this command copies the contents of files as they
2536 By default, this command copies the contents of files as they
2537 exist in the working directory. If invoked with -A/--after, the
2537 exist in the working directory. If invoked with -A/--after, the
2538 operation is recorded, but no copying is performed.
2538 operation is recorded, but no copying is performed.
2539
2539
2540 To undo marking a destination file as copied, use --forget. With that
2540 To undo marking a destination file as copied, use --forget. With that
2541 option, all given (positional) arguments are unmarked as copies. The
2541 option, all given (positional) arguments are unmarked as copies. The
2542 destination file(s) will be left in place (still tracked). Note that
2542 destination file(s) will be left in place (still tracked). Note that
2543 :hg:`copy --forget` behaves the same way as :hg:`rename --forget`.
2543 :hg:`copy --forget` behaves the same way as :hg:`rename --forget`.
2544
2544
2545 This command takes effect with the next commit by default.
2545 This command takes effect with the next commit by default.
2546
2546
2547 Returns 0 on success, 1 if errors are encountered.
2547 Returns 0 on success, 1 if errors are encountered.
2548 """
2548 """
2549
2549
2550 context = lambda repo: repo.dirstate.changing_files(repo)
2550 context = lambda repo: repo.dirstate.changing_files(repo)
2551 rev = opts.get('at_rev')
2551 rev = opts.get('at_rev')
2552
2552
2553 if rev:
2553 if rev:
2554 ctx = logcmdutil.revsingle(repo, rev)
2554 ctx = logcmdutil.revsingle(repo, rev)
2555 if ctx.rev() is not None:
2555 if ctx.rev() is not None:
2556
2556
2557 def context(repo):
2557 def context(repo):
2558 return util.nullcontextmanager()
2558 return util.nullcontextmanager()
2559
2559
2560 opts['at_rev'] = ctx.rev()
2560 opts['at_rev'] = ctx.rev()
2561 with repo.wlock(), context(repo):
2561 with repo.wlock(), context(repo):
2562 return cmdutil.copy(ui, repo, pats, pycompat.byteskwargs(opts))
2562 return cmdutil.copy(ui, repo, pats, pycompat.byteskwargs(opts))
2563
2563
2564
2564
2565 @command(
2565 @command(
2566 b'debugcommands',
2566 b'debugcommands',
2567 [],
2567 [],
2568 _(b'[COMMAND]'),
2568 _(b'[COMMAND]'),
2569 helpcategory=command.CATEGORY_HELP,
2569 helpcategory=command.CATEGORY_HELP,
2570 norepo=True,
2570 norepo=True,
2571 )
2571 )
2572 def debugcommands(ui, cmd=b'', *args):
2572 def debugcommands(ui, cmd=b'', *args):
2573 """list all available commands and options"""
2573 """list all available commands and options"""
2574 for cmd, vals in sorted(table.items()):
2574 for cmd, vals in sorted(table.items()):
2575 cmd = cmd.split(b'|')[0]
2575 cmd = cmd.split(b'|')[0]
2576 opts = b', '.join([i[1] for i in vals[1]])
2576 opts = b', '.join([i[1] for i in vals[1]])
2577 ui.write(b'%s: %s\n' % (cmd, opts))
2577 ui.write(b'%s: %s\n' % (cmd, opts))
2578
2578
2579
2579
2580 @command(
2580 @command(
2581 b'debugcomplete',
2581 b'debugcomplete',
2582 [(b'o', b'options', None, _(b'show the command options'))],
2582 [(b'o', b'options', None, _(b'show the command options'))],
2583 _(b'[-o] CMD'),
2583 _(b'[-o] CMD'),
2584 helpcategory=command.CATEGORY_HELP,
2584 helpcategory=command.CATEGORY_HELP,
2585 norepo=True,
2585 norepo=True,
2586 )
2586 )
2587 def debugcomplete(ui, cmd=b'', **opts):
2587 def debugcomplete(ui, cmd=b'', **opts):
2588 """returns the completion list associated with the given command"""
2588 """returns the completion list associated with the given command"""
2589
2589
2590 if opts.get('options'):
2590 if opts.get('options'):
2591 options = []
2591 options = []
2592 otables = [globalopts]
2592 otables = [globalopts]
2593 if cmd:
2593 if cmd:
2594 aliases, entry = cmdutil.findcmd(cmd, table, False)
2594 aliases, entry = cmdutil.findcmd(cmd, table, False)
2595 otables.append(entry[1])
2595 otables.append(entry[1])
2596 for t in otables:
2596 for t in otables:
2597 for o in t:
2597 for o in t:
2598 if b"(DEPRECATED)" in o[3]:
2598 if b"(DEPRECATED)" in o[3]:
2599 continue
2599 continue
2600 if o[0]:
2600 if o[0]:
2601 options.append(b'-%s' % o[0])
2601 options.append(b'-%s' % o[0])
2602 options.append(b'--%s' % o[1])
2602 options.append(b'--%s' % o[1])
2603 ui.write(b"%s\n" % b"\n".join(options))
2603 ui.write(b"%s\n" % b"\n".join(options))
2604 return
2604 return
2605
2605
2606 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2606 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2607 if ui.verbose:
2607 if ui.verbose:
2608 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2608 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2609 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2609 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2610
2610
2611
2611
2612 @command(
2612 @command(
2613 b'diff',
2613 b'diff',
2614 [
2614 [
2615 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2615 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2616 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2616 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2617 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2617 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2618 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2618 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2619 ]
2619 ]
2620 + diffopts
2620 + diffopts
2621 + diffopts2
2621 + diffopts2
2622 + walkopts
2622 + walkopts
2623 + subrepoopts,
2623 + subrepoopts,
2624 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2624 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2625 helpcategory=command.CATEGORY_FILE_CONTENTS,
2625 helpcategory=command.CATEGORY_FILE_CONTENTS,
2626 helpbasic=True,
2626 helpbasic=True,
2627 inferrepo=True,
2627 inferrepo=True,
2628 intents={INTENT_READONLY},
2628 intents={INTENT_READONLY},
2629 )
2629 )
2630 def diff(ui, repo, *pats, **opts):
2630 def diff(ui, repo, *pats, **opts):
2631 """diff repository (or selected files)
2631 """diff repository (or selected files)
2632
2632
2633 Show differences between revisions for the specified files.
2633 Show differences between revisions for the specified files.
2634
2634
2635 Differences between files are shown using the unified diff format.
2635 Differences between files are shown using the unified diff format.
2636
2636
2637 .. note::
2637 .. note::
2638
2638
2639 :hg:`diff` may generate unexpected results for merges, as it will
2639 :hg:`diff` may generate unexpected results for merges, as it will
2640 default to comparing against the working directory's first
2640 default to comparing against the working directory's first
2641 parent changeset if no revisions are specified. To diff against the
2641 parent changeset if no revisions are specified. To diff against the
2642 conflict regions, you can use `--config diff.merge=yes`.
2642 conflict regions, you can use `--config diff.merge=yes`.
2643
2643
2644 By default, the working directory files are compared to its first parent. To
2644 By default, the working directory files are compared to its first parent. To
2645 see the differences from another revision, use --from. To see the difference
2645 see the differences from another revision, use --from. To see the difference
2646 to another revision, use --to. For example, :hg:`diff --from .^` will show
2646 to another revision, use --to. For example, :hg:`diff --from .^` will show
2647 the differences from the working copy's grandparent to the working copy,
2647 the differences from the working copy's grandparent to the working copy,
2648 :hg:`diff --to .` will show the diff from the working copy to its parent
2648 :hg:`diff --to .` will show the diff from the working copy to its parent
2649 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2649 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2650 show the diff between those two revisions.
2650 show the diff between those two revisions.
2651
2651
2652 Alternatively you can specify -c/--change with a revision to see the changes
2652 Alternatively you can specify -c/--change with a revision to see the changes
2653 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2653 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2654 equivalent to :hg:`diff --from 42^ --to 42`)
2654 equivalent to :hg:`diff --from 42^ --to 42`)
2655
2655
2656 Without the -a/--text option, diff will avoid generating diffs of
2656 Without the -a/--text option, diff will avoid generating diffs of
2657 files it detects as binary. With -a, diff will generate a diff
2657 files it detects as binary. With -a, diff will generate a diff
2658 anyway, probably with undesirable results.
2658 anyway, probably with undesirable results.
2659
2659
2660 Use the -g/--git option to generate diffs in the git extended diff
2660 Use the -g/--git option to generate diffs in the git extended diff
2661 format. For more information, read :hg:`help diffs`.
2661 format. For more information, read :hg:`help diffs`.
2662
2662
2663 .. container:: verbose
2663 .. container:: verbose
2664
2664
2665 Examples:
2665 Examples:
2666
2666
2667 - compare a file in the current working directory to its parent::
2667 - compare a file in the current working directory to its parent::
2668
2668
2669 hg diff foo.c
2669 hg diff foo.c
2670
2670
2671 - compare two historical versions of a directory, with rename info::
2671 - compare two historical versions of a directory, with rename info::
2672
2672
2673 hg diff --git --from 1.0 --to 1.2 lib/
2673 hg diff --git --from 1.0 --to 1.2 lib/
2674
2674
2675 - get change stats relative to the last change on some date::
2675 - get change stats relative to the last change on some date::
2676
2676
2677 hg diff --stat --from "date('may 2')"
2677 hg diff --stat --from "date('may 2')"
2678
2678
2679 - diff all newly-added files that contain a keyword::
2679 - diff all newly-added files that contain a keyword::
2680
2680
2681 hg diff "set:added() and grep(GNU)"
2681 hg diff "set:added() and grep(GNU)"
2682
2682
2683 - compare a revision and its parents::
2683 - compare a revision and its parents::
2684
2684
2685 hg diff -c 9353 # compare against first parent
2685 hg diff -c 9353 # compare against first parent
2686 hg diff --from 9353^ --to 9353 # same using revset syntax
2686 hg diff --from 9353^ --to 9353 # same using revset syntax
2687 hg diff --from 9353^2 --to 9353 # compare against the second parent
2687 hg diff --from 9353^2 --to 9353 # compare against the second parent
2688
2688
2689 Returns 0 on success.
2689 Returns 0 on success.
2690 """
2690 """
2691
2691
2692 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2692 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2693 opts = pycompat.byteskwargs(opts)
2693 opts = pycompat.byteskwargs(opts)
2694 revs = opts.get(b'rev')
2694 revs = opts.get(b'rev')
2695 change = opts.get(b'change')
2695 change = opts.get(b'change')
2696 from_rev = opts.get(b'from')
2696 from_rev = opts.get(b'from')
2697 to_rev = opts.get(b'to')
2697 to_rev = opts.get(b'to')
2698 stat = opts.get(b'stat')
2698 stat = opts.get(b'stat')
2699 reverse = opts.get(b'reverse')
2699 reverse = opts.get(b'reverse')
2700
2700
2701 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2701 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2702 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2702 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2703 if change:
2703 if change:
2704 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2704 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2705 ctx2 = logcmdutil.revsingle(repo, change, None)
2705 ctx2 = logcmdutil.revsingle(repo, change, None)
2706 ctx1 = diffutil.diff_parent(ctx2)
2706 ctx1 = diffutil.diff_parent(ctx2)
2707 elif from_rev or to_rev:
2707 elif from_rev or to_rev:
2708 repo = scmutil.unhidehashlikerevs(
2708 repo = scmutil.unhidehashlikerevs(
2709 repo, [from_rev] + [to_rev], b'nowarn'
2709 repo, [from_rev] + [to_rev], b'nowarn'
2710 )
2710 )
2711 ctx1 = logcmdutil.revsingle(repo, from_rev, None)
2711 ctx1 = logcmdutil.revsingle(repo, from_rev, None)
2712 ctx2 = logcmdutil.revsingle(repo, to_rev, None)
2712 ctx2 = logcmdutil.revsingle(repo, to_rev, None)
2713 else:
2713 else:
2714 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2714 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2715 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
2715 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
2716
2716
2717 if reverse:
2717 if reverse:
2718 ctxleft = ctx2
2718 ctxleft = ctx2
2719 ctxright = ctx1
2719 ctxright = ctx1
2720 else:
2720 else:
2721 ctxleft = ctx1
2721 ctxleft = ctx1
2722 ctxright = ctx2
2722 ctxright = ctx2
2723
2723
2724 diffopts = patch.diffallopts(ui, opts)
2724 diffopts = patch.diffallopts(ui, opts)
2725 m = scmutil.match(ctx2, pats, opts)
2725 m = scmutil.match(ctx2, pats, opts)
2726 m = repo.narrowmatch(m)
2726 m = repo.narrowmatch(m)
2727 ui.pager(b'diff')
2727 ui.pager(b'diff')
2728 logcmdutil.diffordiffstat(
2728 logcmdutil.diffordiffstat(
2729 ui,
2729 ui,
2730 repo,
2730 repo,
2731 diffopts,
2731 diffopts,
2732 ctxleft,
2732 ctxleft,
2733 ctxright,
2733 ctxright,
2734 m,
2734 m,
2735 stat=stat,
2735 stat=stat,
2736 listsubrepos=opts.get(b'subrepos'),
2736 listsubrepos=opts.get(b'subrepos'),
2737 root=opts.get(b'root'),
2737 root=opts.get(b'root'),
2738 )
2738 )
2739
2739
2740
2740
2741 @command(
2741 @command(
2742 b'export',
2742 b'export',
2743 [
2743 [
2744 (
2744 (
2745 b'B',
2745 b'B',
2746 b'bookmark',
2746 b'bookmark',
2747 b'',
2747 b'',
2748 _(b'export changes only reachable by given bookmark'),
2748 _(b'export changes only reachable by given bookmark'),
2749 _(b'BOOKMARK'),
2749 _(b'BOOKMARK'),
2750 ),
2750 ),
2751 (
2751 (
2752 b'o',
2752 b'o',
2753 b'output',
2753 b'output',
2754 b'',
2754 b'',
2755 _(b'print output to file with formatted name'),
2755 _(b'print output to file with formatted name'),
2756 _(b'FORMAT'),
2756 _(b'FORMAT'),
2757 ),
2757 ),
2758 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2758 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2759 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2759 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2760 ]
2760 ]
2761 + diffopts
2761 + diffopts
2762 + formatteropts,
2762 + formatteropts,
2763 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2763 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2764 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2764 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2765 helpbasic=True,
2765 helpbasic=True,
2766 intents={INTENT_READONLY},
2766 intents={INTENT_READONLY},
2767 )
2767 )
2768 def export(ui, repo, *changesets, **opts):
2768 def export(ui, repo, *changesets, **opts):
2769 """dump the header and diffs for one or more changesets
2769 """dump the header and diffs for one or more changesets
2770
2770
2771 Print the changeset header and diffs for one or more revisions.
2771 Print the changeset header and diffs for one or more revisions.
2772 If no revision is given, the parent of the working directory is used.
2772 If no revision is given, the parent of the working directory is used.
2773
2773
2774 The information shown in the changeset header is: author, date,
2774 The information shown in the changeset header is: author, date,
2775 branch name (if non-default), changeset hash, parent(s) and commit
2775 branch name (if non-default), changeset hash, parent(s) and commit
2776 comment.
2776 comment.
2777
2777
2778 .. note::
2778 .. note::
2779
2779
2780 :hg:`export` may generate unexpected diff output for merge
2780 :hg:`export` may generate unexpected diff output for merge
2781 changesets, as it will compare the merge changeset against its
2781 changesets, as it will compare the merge changeset against its
2782 first parent only.
2782 first parent only.
2783
2783
2784 Output may be to a file, in which case the name of the file is
2784 Output may be to a file, in which case the name of the file is
2785 given using a template string. See :hg:`help templates`. In addition
2785 given using a template string. See :hg:`help templates`. In addition
2786 to the common template keywords, the following formatting rules are
2786 to the common template keywords, the following formatting rules are
2787 supported:
2787 supported:
2788
2788
2789 :``%%``: literal "%" character
2789 :``%%``: literal "%" character
2790 :``%H``: changeset hash (40 hexadecimal digits)
2790 :``%H``: changeset hash (40 hexadecimal digits)
2791 :``%N``: number of patches being generated
2791 :``%N``: number of patches being generated
2792 :``%R``: changeset revision number
2792 :``%R``: changeset revision number
2793 :``%b``: basename of the exporting repository
2793 :``%b``: basename of the exporting repository
2794 :``%h``: short-form changeset hash (12 hexadecimal digits)
2794 :``%h``: short-form changeset hash (12 hexadecimal digits)
2795 :``%m``: first line of the commit message (only alphanumeric characters)
2795 :``%m``: first line of the commit message (only alphanumeric characters)
2796 :``%n``: zero-padded sequence number, starting at 1
2796 :``%n``: zero-padded sequence number, starting at 1
2797 :``%r``: zero-padded changeset revision number
2797 :``%r``: zero-padded changeset revision number
2798 :``\\``: literal "\\" character
2798 :``\\``: literal "\\" character
2799
2799
2800 Without the -a/--text option, export will avoid generating diffs
2800 Without the -a/--text option, export will avoid generating diffs
2801 of files it detects as binary. With -a, export will generate a
2801 of files it detects as binary. With -a, export will generate a
2802 diff anyway, probably with undesirable results.
2802 diff anyway, probably with undesirable results.
2803
2803
2804 With -B/--bookmark changesets reachable by the given bookmark are
2804 With -B/--bookmark changesets reachable by the given bookmark are
2805 selected.
2805 selected.
2806
2806
2807 Use the -g/--git option to generate diffs in the git extended diff
2807 Use the -g/--git option to generate diffs in the git extended diff
2808 format. See :hg:`help diffs` for more information.
2808 format. See :hg:`help diffs` for more information.
2809
2809
2810 With the --switch-parent option, the diff will be against the
2810 With the --switch-parent option, the diff will be against the
2811 second parent. It can be useful to review a merge.
2811 second parent. It can be useful to review a merge.
2812
2812
2813 .. container:: verbose
2813 .. container:: verbose
2814
2814
2815 Template:
2815 Template:
2816
2816
2817 The following keywords are supported in addition to the common template
2817 The following keywords are supported in addition to the common template
2818 keywords and functions. See also :hg:`help templates`.
2818 keywords and functions. See also :hg:`help templates`.
2819
2819
2820 :diff: String. Diff content.
2820 :diff: String. Diff content.
2821 :parents: List of strings. Parent nodes of the changeset.
2821 :parents: List of strings. Parent nodes of the changeset.
2822
2822
2823 Examples:
2823 Examples:
2824
2824
2825 - use export and import to transplant a bugfix to the current
2825 - use export and import to transplant a bugfix to the current
2826 branch::
2826 branch::
2827
2827
2828 hg export -r 9353 | hg import -
2828 hg export -r 9353 | hg import -
2829
2829
2830 - export all the changesets between two revisions to a file with
2830 - export all the changesets between two revisions to a file with
2831 rename information::
2831 rename information::
2832
2832
2833 hg export --git -r 123:150 > changes.txt
2833 hg export --git -r 123:150 > changes.txt
2834
2834
2835 - split outgoing changes into a series of patches with
2835 - split outgoing changes into a series of patches with
2836 descriptive names::
2836 descriptive names::
2837
2837
2838 hg export -r "outgoing()" -o "%n-%m.patch"
2838 hg export -r "outgoing()" -o "%n-%m.patch"
2839
2839
2840 Returns 0 on success.
2840 Returns 0 on success.
2841 """
2841 """
2842 opts = pycompat.byteskwargs(opts)
2842 opts = pycompat.byteskwargs(opts)
2843 bookmark = opts.get(b'bookmark')
2843 bookmark = opts.get(b'bookmark')
2844 changesets += tuple(opts.get(b'rev', []))
2844 changesets += tuple(opts.get(b'rev', []))
2845
2845
2846 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2846 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2847
2847
2848 if bookmark:
2848 if bookmark:
2849 if bookmark not in repo._bookmarks:
2849 if bookmark not in repo._bookmarks:
2850 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2850 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2851
2851
2852 revs = scmutil.bookmarkrevs(repo, bookmark)
2852 revs = scmutil.bookmarkrevs(repo, bookmark)
2853 else:
2853 else:
2854 if not changesets:
2854 if not changesets:
2855 changesets = [b'.']
2855 changesets = [b'.']
2856
2856
2857 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2857 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2858 revs = logcmdutil.revrange(repo, changesets)
2858 revs = logcmdutil.revrange(repo, changesets)
2859
2859
2860 if not revs:
2860 if not revs:
2861 raise error.InputError(_(b"export requires at least one changeset"))
2861 raise error.InputError(_(b"export requires at least one changeset"))
2862 if len(revs) > 1:
2862 if len(revs) > 1:
2863 ui.note(_(b'exporting patches:\n'))
2863 ui.note(_(b'exporting patches:\n'))
2864 else:
2864 else:
2865 ui.note(_(b'exporting patch:\n'))
2865 ui.note(_(b'exporting patch:\n'))
2866
2866
2867 fntemplate = opts.get(b'output')
2867 fntemplate = opts.get(b'output')
2868 if cmdutil.isstdiofilename(fntemplate):
2868 if cmdutil.isstdiofilename(fntemplate):
2869 fntemplate = b''
2869 fntemplate = b''
2870
2870
2871 if fntemplate:
2871 if fntemplate:
2872 fm = formatter.nullformatter(ui, b'export', opts)
2872 fm = formatter.nullformatter(ui, b'export', opts)
2873 else:
2873 else:
2874 ui.pager(b'export')
2874 ui.pager(b'export')
2875 fm = ui.formatter(b'export', opts)
2875 fm = ui.formatter(b'export', opts)
2876 with fm:
2876 with fm:
2877 cmdutil.export(
2877 cmdutil.export(
2878 repo,
2878 repo,
2879 revs,
2879 revs,
2880 fm,
2880 fm,
2881 fntemplate=fntemplate,
2881 fntemplate=fntemplate,
2882 switch_parent=opts.get(b'switch_parent'),
2882 switch_parent=opts.get(b'switch_parent'),
2883 opts=patch.diffallopts(ui, opts),
2883 opts=patch.diffallopts(ui, opts),
2884 )
2884 )
2885
2885
2886
2886
2887 @command(
2887 @command(
2888 b'files',
2888 b'files',
2889 [
2889 [
2890 (
2890 (
2891 b'r',
2891 b'r',
2892 b'rev',
2892 b'rev',
2893 b'',
2893 b'',
2894 _(b'search the repository as it is in REV'),
2894 _(b'search the repository as it is in REV'),
2895 _(b'REV'),
2895 _(b'REV'),
2896 ),
2896 ),
2897 (
2897 (
2898 b'0',
2898 b'0',
2899 b'print0',
2899 b'print0',
2900 None,
2900 None,
2901 _(b'end filenames with NUL, for use with xargs'),
2901 _(b'end filenames with NUL, for use with xargs'),
2902 ),
2902 ),
2903 ]
2903 ]
2904 + walkopts
2904 + walkopts
2905 + formatteropts
2905 + formatteropts
2906 + subrepoopts,
2906 + subrepoopts,
2907 _(b'[OPTION]... [FILE]...'),
2907 _(b'[OPTION]... [FILE]...'),
2908 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2908 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2909 intents={INTENT_READONLY},
2909 intents={INTENT_READONLY},
2910 )
2910 )
2911 def files(ui, repo, *pats, **opts):
2911 def files(ui, repo, *pats, **opts):
2912 """list tracked files
2912 """list tracked files
2913
2913
2914 Print files under Mercurial control in the working directory or
2914 Print files under Mercurial control in the working directory or
2915 specified revision for given files (excluding removed files).
2915 specified revision for given files (excluding removed files).
2916 Files can be specified as filenames or filesets.
2916 Files can be specified as filenames or filesets.
2917
2917
2918 If no files are given to match, this command prints the names
2918 If no files are given to match, this command prints the names
2919 of all files under Mercurial control.
2919 of all files under Mercurial control.
2920
2920
2921 .. container:: verbose
2921 .. container:: verbose
2922
2922
2923 Template:
2923 Template:
2924
2924
2925 The following keywords are supported in addition to the common template
2925 The following keywords are supported in addition to the common template
2926 keywords and functions. See also :hg:`help templates`.
2926 keywords and functions. See also :hg:`help templates`.
2927
2927
2928 :flags: String. Character denoting file's symlink and executable bits.
2928 :flags: String. Character denoting file's symlink and executable bits.
2929 :path: String. Repository-absolute path of the file.
2929 :path: String. Repository-absolute path of the file.
2930 :size: Integer. Size of the file in bytes.
2930 :size: Integer. Size of the file in bytes.
2931
2931
2932 Examples:
2932 Examples:
2933
2933
2934 - list all files under the current directory::
2934 - list all files under the current directory::
2935
2935
2936 hg files .
2936 hg files .
2937
2937
2938 - shows sizes and flags for current revision::
2938 - shows sizes and flags for current revision::
2939
2939
2940 hg files -vr .
2940 hg files -vr .
2941
2941
2942 - list all files named README::
2942 - list all files named README::
2943
2943
2944 hg files -I "**/README"
2944 hg files -I "**/README"
2945
2945
2946 - list all binary files::
2946 - list all binary files::
2947
2947
2948 hg files "set:binary()"
2948 hg files "set:binary()"
2949
2949
2950 - find files containing a regular expression::
2950 - find files containing a regular expression::
2951
2951
2952 hg files "set:grep('bob')"
2952 hg files "set:grep('bob')"
2953
2953
2954 - search tracked file contents with xargs and grep::
2954 - search tracked file contents with xargs and grep::
2955
2955
2956 hg files -0 | xargs -0 grep foo
2956 hg files -0 | xargs -0 grep foo
2957
2957
2958 See :hg:`help patterns` and :hg:`help filesets` for more information
2958 See :hg:`help patterns` and :hg:`help filesets` for more information
2959 on specifying file patterns.
2959 on specifying file patterns.
2960
2960
2961 Returns 0 if a match is found, 1 otherwise.
2961 Returns 0 if a match is found, 1 otherwise.
2962
2962
2963 """
2963 """
2964
2964
2965 opts = pycompat.byteskwargs(opts)
2965 opts = pycompat.byteskwargs(opts)
2966 rev = opts.get(b'rev')
2966 rev = opts.get(b'rev')
2967 if rev:
2967 if rev:
2968 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2968 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2969 ctx = logcmdutil.revsingle(repo, rev, None)
2969 ctx = logcmdutil.revsingle(repo, rev, None)
2970
2970
2971 end = b'\n'
2971 end = b'\n'
2972 if opts.get(b'print0'):
2972 if opts.get(b'print0'):
2973 end = b'\0'
2973 end = b'\0'
2974 fmt = b'%s' + end
2974 fmt = b'%s' + end
2975
2975
2976 m = scmutil.match(ctx, pats, opts)
2976 m = scmutil.match(ctx, pats, opts)
2977 ui.pager(b'files')
2977 ui.pager(b'files')
2978 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2978 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2979 with ui.formatter(b'files', opts) as fm:
2979 with ui.formatter(b'files', opts) as fm:
2980 return cmdutil.files(
2980 return cmdutil.files(
2981 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2981 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2982 )
2982 )
2983
2983
2984
2984
2985 @command(
2985 @command(
2986 b'forget',
2986 b'forget',
2987 [
2987 [
2988 (b'i', b'interactive', None, _(b'use interactive mode')),
2988 (b'i', b'interactive', None, _(b'use interactive mode')),
2989 ]
2989 ]
2990 + walkopts
2990 + walkopts
2991 + dryrunopts,
2991 + dryrunopts,
2992 _(b'[OPTION]... FILE...'),
2992 _(b'[OPTION]... FILE...'),
2993 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2993 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2994 helpbasic=True,
2994 helpbasic=True,
2995 inferrepo=True,
2995 inferrepo=True,
2996 )
2996 )
2997 def forget(ui, repo, *pats, **opts):
2997 def forget(ui, repo, *pats, **opts):
2998 """forget the specified files on the next commit
2998 """forget the specified files on the next commit
2999
2999
3000 Mark the specified files so they will no longer be tracked
3000 Mark the specified files so they will no longer be tracked
3001 after the next commit.
3001 after the next commit.
3002
3002
3003 This only removes files from the current branch, not from the
3003 This only removes files from the current branch, not from the
3004 entire project history, and it does not delete them from the
3004 entire project history, and it does not delete them from the
3005 working directory.
3005 working directory.
3006
3006
3007 To delete the file from the working directory, see :hg:`remove`.
3007 To delete the file from the working directory, see :hg:`remove`.
3008
3008
3009 To undo a forget before the next commit, see :hg:`add`.
3009 To undo a forget before the next commit, see :hg:`add`.
3010
3010
3011 .. container:: verbose
3011 .. container:: verbose
3012
3012
3013 Examples:
3013 Examples:
3014
3014
3015 - forget newly-added binary files::
3015 - forget newly-added binary files::
3016
3016
3017 hg forget "set:added() and binary()"
3017 hg forget "set:added() and binary()"
3018
3018
3019 - forget files that would be excluded by .hgignore::
3019 - forget files that would be excluded by .hgignore::
3020
3020
3021 hg forget "set:hgignore()"
3021 hg forget "set:hgignore()"
3022
3022
3023 Returns 0 on success.
3023 Returns 0 on success.
3024 """
3024 """
3025
3025
3026 if not pats:
3026 if not pats:
3027 raise error.InputError(_(b'no files specified'))
3027 raise error.InputError(_(b'no files specified'))
3028
3028
3029 with repo.wlock(), repo.dirstate.changing_files(repo):
3029 with repo.wlock(), repo.dirstate.changing_files(repo):
3030 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
3030 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
3031 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
3031 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
3032 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
3032 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
3033 rejected = cmdutil.forget(
3033 rejected = cmdutil.forget(
3034 ui,
3034 ui,
3035 repo,
3035 repo,
3036 m,
3036 m,
3037 prefix=b"",
3037 prefix=b"",
3038 uipathfn=uipathfn,
3038 uipathfn=uipathfn,
3039 explicitonly=False,
3039 explicitonly=False,
3040 dryrun=dryrun,
3040 dryrun=dryrun,
3041 interactive=interactive,
3041 interactive=interactive,
3042 )[0]
3042 )[0]
3043 return rejected and 1 or 0
3043 return rejected and 1 or 0
3044
3044
3045
3045
3046 @command(
3046 @command(
3047 b'graft',
3047 b'graft',
3048 [
3048 [
3049 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
3049 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
3050 (
3050 (
3051 b'',
3051 b'',
3052 b'base',
3052 b'base',
3053 b'',
3053 b'',
3054 _(b'base revision when doing the graft merge (ADVANCED)'),
3054 _(b'base revision when doing the graft merge (ADVANCED)'),
3055 _(b'REV'),
3055 _(b'REV'),
3056 ),
3056 ),
3057 (b'c', b'continue', False, _(b'resume interrupted graft')),
3057 (b'c', b'continue', False, _(b'resume interrupted graft')),
3058 (b'', b'stop', False, _(b'stop interrupted graft')),
3058 (b'', b'stop', False, _(b'stop interrupted graft')),
3059 (b'', b'abort', False, _(b'abort interrupted graft')),
3059 (b'', b'abort', False, _(b'abort interrupted graft')),
3060 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3060 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3061 (b'', b'log', None, _(b'append graft info to log message')),
3061 (b'', b'log', None, _(b'append graft info to log message')),
3062 (
3062 (
3063 b'',
3063 b'',
3064 b'no-commit',
3064 b'no-commit',
3065 None,
3065 None,
3066 _(b"don't commit, just apply the changes in working directory"),
3066 _(b"don't commit, just apply the changes in working directory"),
3067 ),
3067 ),
3068 (b'f', b'force', False, _(b'force graft')),
3068 (b'f', b'force', False, _(b'force graft')),
3069 (
3069 (
3070 b'D',
3070 b'D',
3071 b'currentdate',
3071 b'currentdate',
3072 False,
3072 False,
3073 _(b'record the current date as commit date'),
3073 _(b'record the current date as commit date'),
3074 ),
3074 ),
3075 (
3075 (
3076 b'U',
3076 b'U',
3077 b'currentuser',
3077 b'currentuser',
3078 False,
3078 False,
3079 _(b'record the current user as committer'),
3079 _(b'record the current user as committer'),
3080 ),
3080 ),
3081 ]
3081 ]
3082 + commitopts2
3082 + commitopts2
3083 + mergetoolopts
3083 + mergetoolopts
3084 + dryrunopts,
3084 + dryrunopts,
3085 _(b'[OPTION]... [-r REV]... REV...'),
3085 _(b'[OPTION]... [-r REV]... REV...'),
3086 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
3086 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
3087 )
3087 )
3088 def graft(ui, repo, *revs, **opts):
3088 def graft(ui, repo, *revs, **opts):
3089 """copy changes from other branches onto the current branch
3089 """copy changes from other branches onto the current branch
3090
3090
3091 This command uses Mercurial's merge logic to copy individual
3091 This command uses Mercurial's merge logic to copy individual
3092 changes from other branches without merging branches in the
3092 changes from other branches without merging branches in the
3093 history graph. This is sometimes known as 'backporting' or
3093 history graph. This is sometimes known as 'backporting' or
3094 'cherry-picking'. By default, graft will copy user, date, and
3094 'cherry-picking'. By default, graft will copy user, date, and
3095 description from the source changesets.
3095 description from the source changesets.
3096
3096
3097 Changesets that are ancestors of the current revision, that have
3097 Changesets that are ancestors of the current revision, that have
3098 already been grafted, or that are merges will be skipped.
3098 already been grafted, or that are merges will be skipped.
3099
3099
3100 If --log is specified, log messages will have a comment appended
3100 If --log is specified, log messages will have a comment appended
3101 of the form::
3101 of the form::
3102
3102
3103 (grafted from CHANGESETHASH)
3103 (grafted from CHANGESETHASH)
3104
3104
3105 If --force is specified, revisions will be grafted even if they
3105 If --force is specified, revisions will be grafted even if they
3106 are already ancestors of, or have been grafted to, the destination.
3106 are already ancestors of, or have been grafted to, the destination.
3107 This is useful when the revisions have since been backed out.
3107 This is useful when the revisions have since been backed out.
3108
3108
3109 If a graft merge results in conflicts, the graft process is
3109 If a graft merge results in conflicts, the graft process is
3110 interrupted so that the current merge can be manually resolved.
3110 interrupted so that the current merge can be manually resolved.
3111 Once all conflicts are addressed, the graft process can be
3111 Once all conflicts are addressed, the graft process can be
3112 continued with the -c/--continue option.
3112 continued with the -c/--continue option.
3113
3113
3114 The -c/--continue option reapplies all the earlier options.
3114 The -c/--continue option reapplies all the earlier options.
3115
3115
3116 .. container:: verbose
3116 .. container:: verbose
3117
3117
3118 The --base option exposes more of how graft internally uses merge with a
3118 The --base option exposes more of how graft internally uses merge with a
3119 custom base revision. --base can be used to specify another ancestor than
3119 custom base revision. --base can be used to specify another ancestor than
3120 the first and only parent.
3120 the first and only parent.
3121
3121
3122 The command::
3122 The command::
3123
3123
3124 hg graft -r 345 --base 234
3124 hg graft -r 345 --base 234
3125
3125
3126 is thus pretty much the same as::
3126 is thus pretty much the same as::
3127
3127
3128 hg diff --from 234 --to 345 | hg import
3128 hg diff --from 234 --to 345 | hg import
3129
3129
3130 but using merge to resolve conflicts and track moved files.
3130 but using merge to resolve conflicts and track moved files.
3131
3131
3132 The result of a merge can thus be backported as a single commit by
3132 The result of a merge can thus be backported as a single commit by
3133 specifying one of the merge parents as base, and thus effectively
3133 specifying one of the merge parents as base, and thus effectively
3134 grafting the changes from the other side.
3134 grafting the changes from the other side.
3135
3135
3136 It is also possible to collapse multiple changesets and clean up history
3136 It is also possible to collapse multiple changesets and clean up history
3137 by specifying another ancestor as base, much like rebase --collapse
3137 by specifying another ancestor as base, much like rebase --collapse
3138 --keep.
3138 --keep.
3139
3139
3140 The commit message can be tweaked after the fact using commit --amend .
3140 The commit message can be tweaked after the fact using commit --amend .
3141
3141
3142 For using non-ancestors as the base to backout changes, see the backout
3142 For using non-ancestors as the base to backout changes, see the backout
3143 command and the hidden --parent option.
3143 command and the hidden --parent option.
3144
3144
3145 .. container:: verbose
3145 .. container:: verbose
3146
3146
3147 Examples:
3147 Examples:
3148
3148
3149 - copy a single change to the stable branch and edit its description::
3149 - copy a single change to the stable branch and edit its description::
3150
3150
3151 hg update stable
3151 hg update stable
3152 hg graft --edit 9393
3152 hg graft --edit 9393
3153
3153
3154 - graft a range of changesets with one exception, updating dates::
3154 - graft a range of changesets with one exception, updating dates::
3155
3155
3156 hg graft -D "2085::2093 and not 2091"
3156 hg graft -D "2085::2093 and not 2091"
3157
3157
3158 - continue a graft after resolving conflicts::
3158 - continue a graft after resolving conflicts::
3159
3159
3160 hg graft -c
3160 hg graft -c
3161
3161
3162 - show the source of a grafted changeset::
3162 - show the source of a grafted changeset::
3163
3163
3164 hg log --debug -r .
3164 hg log --debug -r .
3165
3165
3166 - show revisions sorted by date::
3166 - show revisions sorted by date::
3167
3167
3168 hg log -r "sort(all(), date)"
3168 hg log -r "sort(all(), date)"
3169
3169
3170 - backport the result of a merge as a single commit::
3170 - backport the result of a merge as a single commit::
3171
3171
3172 hg graft -r 123 --base 123^
3172 hg graft -r 123 --base 123^
3173
3173
3174 - land a feature branch as one changeset::
3174 - land a feature branch as one changeset::
3175
3175
3176 hg up -cr default
3176 hg up -cr default
3177 hg graft -r featureX --base "ancestor('featureX', 'default')"
3177 hg graft -r featureX --base "ancestor('featureX', 'default')"
3178
3178
3179 See :hg:`help revisions` for more about specifying revisions.
3179 See :hg:`help revisions` for more about specifying revisions.
3180
3180
3181 Returns 0 on successful completion, 1 if there are unresolved files.
3181 Returns 0 on successful completion, 1 if there are unresolved files.
3182 """
3182 """
3183 with repo.wlock():
3183 with repo.wlock():
3184 return _dograft(ui, repo, *revs, **opts)
3184 return _dograft(ui, repo, *revs, **opts)
3185
3185
3186
3186
3187 def _dograft(ui, repo, *revs, **opts):
3187 def _dograft(ui, repo, *revs, **opts):
3188 if revs and opts.get('rev'):
3188 if revs and opts.get('rev'):
3189 ui.warn(
3189 ui.warn(
3190 _(
3190 _(
3191 b'warning: inconsistent use of --rev might give unexpected '
3191 b'warning: inconsistent use of --rev might give unexpected '
3192 b'revision ordering!\n'
3192 b'revision ordering!\n'
3193 )
3193 )
3194 )
3194 )
3195
3195
3196 revs = list(revs)
3196 revs = list(revs)
3197 revs.extend(opts.get('rev'))
3197 revs.extend(opts.get('rev'))
3198 # a dict of data to be stored in state file
3198 # a dict of data to be stored in state file
3199 statedata = {}
3199 statedata = {}
3200 # list of new nodes created by ongoing graft
3200 # list of new nodes created by ongoing graft
3201 statedata[b'newnodes'] = []
3201 statedata[b'newnodes'] = []
3202
3202
3203 cmdutil.resolve_commit_options(ui, opts)
3203 cmdutil.resolve_commit_options(ui, opts)
3204
3204
3205 editor = cmdutil.getcommiteditor(editform=b'graft', **opts)
3205 editor = cmdutil.getcommiteditor(editform=b'graft', **opts)
3206
3206
3207 cmdutil.check_at_most_one_arg(opts, 'abort', 'stop', 'continue')
3207 cmdutil.check_at_most_one_arg(opts, 'abort', 'stop', 'continue')
3208
3208
3209 cont = False
3209 cont = False
3210 if opts.get('no_commit'):
3210 if opts.get('no_commit'):
3211 cmdutil.check_incompatible_arguments(
3211 cmdutil.check_incompatible_arguments(
3212 opts,
3212 opts,
3213 'no_commit',
3213 'no_commit',
3214 ['edit', 'currentuser', 'currentdate', 'log'],
3214 ['edit', 'currentuser', 'currentdate', 'log'],
3215 )
3215 )
3216
3216
3217 graftstate = statemod.cmdstate(repo, b'graftstate')
3217 graftstate = statemod.cmdstate(repo, b'graftstate')
3218
3218
3219 if opts.get('stop'):
3219 if opts.get('stop'):
3220 cmdutil.check_incompatible_arguments(
3220 cmdutil.check_incompatible_arguments(
3221 opts,
3221 opts,
3222 'stop',
3222 'stop',
3223 [
3223 [
3224 'edit',
3224 'edit',
3225 'log',
3225 'log',
3226 'user',
3226 'user',
3227 'date',
3227 'date',
3228 'currentdate',
3228 'currentdate',
3229 'currentuser',
3229 'currentuser',
3230 'rev',
3230 'rev',
3231 ],
3231 ],
3232 )
3232 )
3233 return _stopgraft(ui, repo, graftstate)
3233 return _stopgraft(ui, repo, graftstate)
3234 elif opts.get('abort'):
3234 elif opts.get('abort'):
3235 cmdutil.check_incompatible_arguments(
3235 cmdutil.check_incompatible_arguments(
3236 opts,
3236 opts,
3237 'abort',
3237 'abort',
3238 [
3238 [
3239 'edit',
3239 'edit',
3240 'log',
3240 'log',
3241 'user',
3241 'user',
3242 'date',
3242 'date',
3243 'currentdate',
3243 'currentdate',
3244 'currentuser',
3244 'currentuser',
3245 'rev',
3245 'rev',
3246 ],
3246 ],
3247 )
3247 )
3248 return cmdutil.abortgraft(ui, repo, graftstate)
3248 return cmdutil.abortgraft(ui, repo, graftstate)
3249 elif opts.get('continue'):
3249 elif opts.get('continue'):
3250 cont = True
3250 cont = True
3251 if revs:
3251 if revs:
3252 raise error.InputError(_(b"can't specify --continue and revisions"))
3252 raise error.InputError(_(b"can't specify --continue and revisions"))
3253 # read in unfinished revisions
3253 # read in unfinished revisions
3254 if graftstate.exists():
3254 if graftstate.exists():
3255 statedata = cmdutil.readgraftstate(repo, graftstate)
3255 statedata = cmdutil.readgraftstate(repo, graftstate)
3256 if statedata.get(b'date'):
3256 if statedata.get(b'date'):
3257 opts['date'] = statedata[b'date']
3257 opts['date'] = statedata[b'date']
3258 if statedata.get(b'user'):
3258 if statedata.get(b'user'):
3259 opts['user'] = statedata[b'user']
3259 opts['user'] = statedata[b'user']
3260 if statedata.get(b'log'):
3260 if statedata.get(b'log'):
3261 opts['log'] = True
3261 opts['log'] = True
3262 if statedata.get(b'no_commit'):
3262 if statedata.get(b'no_commit'):
3263 opts['no_commit'] = statedata.get(b'no_commit')
3263 opts['no_commit'] = statedata.get(b'no_commit')
3264 if statedata.get(b'base'):
3264 if statedata.get(b'base'):
3265 opts['base'] = statedata.get(b'base')
3265 opts['base'] = statedata.get(b'base')
3266 nodes = statedata[b'nodes']
3266 nodes = statedata[b'nodes']
3267 revs = [repo[node].rev() for node in nodes]
3267 revs = [repo[node].rev() for node in nodes]
3268 else:
3268 else:
3269 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3269 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3270 else:
3270 else:
3271 if not revs:
3271 if not revs:
3272 raise error.InputError(_(b'no revisions specified'))
3272 raise error.InputError(_(b'no revisions specified'))
3273 cmdutil.checkunfinished(repo)
3273 cmdutil.checkunfinished(repo)
3274 cmdutil.bailifchanged(repo)
3274 cmdutil.bailifchanged(repo)
3275 revs = logcmdutil.revrange(repo, revs)
3275 revs = logcmdutil.revrange(repo, revs)
3276
3276
3277 skipped = set()
3277 skipped = set()
3278 basectx = None
3278 basectx = None
3279 if opts.get('base'):
3279 if opts.get('base'):
3280 basectx = logcmdutil.revsingle(repo, opts['base'], None)
3280 basectx = logcmdutil.revsingle(repo, opts['base'], None)
3281 if basectx is None:
3281 if basectx is None:
3282 # check for merges
3282 # check for merges
3283 for rev in repo.revs(b'%ld and merge()', revs):
3283 for rev in repo.revs(b'%ld and merge()', revs):
3284 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3284 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3285 skipped.add(rev)
3285 skipped.add(rev)
3286 revs = [r for r in revs if r not in skipped]
3286 revs = [r for r in revs if r not in skipped]
3287 if not revs:
3287 if not revs:
3288 return -1
3288 return -1
3289 if basectx is not None and len(revs) != 1:
3289 if basectx is not None and len(revs) != 1:
3290 raise error.InputError(_(b'only one revision allowed with --base '))
3290 raise error.InputError(_(b'only one revision allowed with --base '))
3291
3291
3292 # Don't check in the --continue case, in effect retaining --force across
3292 # Don't check in the --continue case, in effect retaining --force across
3293 # --continues. That's because without --force, any revisions we decided to
3293 # --continues. That's because without --force, any revisions we decided to
3294 # skip would have been filtered out here, so they wouldn't have made their
3294 # skip would have been filtered out here, so they wouldn't have made their
3295 # way to the graftstate. With --force, any revisions we would have otherwise
3295 # way to the graftstate. With --force, any revisions we would have otherwise
3296 # skipped would not have been filtered out, and if they hadn't been applied
3296 # skipped would not have been filtered out, and if they hadn't been applied
3297 # already, they'd have been in the graftstate.
3297 # already, they'd have been in the graftstate.
3298 if not (cont or opts.get('force')) and basectx is None:
3298 if not (cont or opts.get('force')) and basectx is None:
3299 # check for ancestors of dest branch
3299 # check for ancestors of dest branch
3300 ancestors = repo.revs(b'%ld & (::.)', revs)
3300 ancestors = repo.revs(b'%ld & (::.)', revs)
3301 for rev in ancestors:
3301 for rev in ancestors:
3302 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3302 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3303
3303
3304 revs = [r for r in revs if r not in ancestors]
3304 revs = [r for r in revs if r not in ancestors]
3305
3305
3306 if not revs:
3306 if not revs:
3307 return -1
3307 return -1
3308
3308
3309 # analyze revs for earlier grafts
3309 # analyze revs for earlier grafts
3310 ids = {}
3310 ids = {}
3311 for ctx in repo.set(b"%ld", revs):
3311 for ctx in repo.set(b"%ld", revs):
3312 ids[ctx.hex()] = ctx.rev()
3312 ids[ctx.hex()] = ctx.rev()
3313 n = ctx.extra().get(b'source')
3313 n = ctx.extra().get(b'source')
3314 if n:
3314 if n:
3315 ids[n] = ctx.rev()
3315 ids[n] = ctx.rev()
3316
3316
3317 # check ancestors for earlier grafts
3317 # check ancestors for earlier grafts
3318 ui.debug(b'scanning for duplicate grafts\n')
3318 ui.debug(b'scanning for duplicate grafts\n')
3319
3319
3320 # The only changesets we can be sure doesn't contain grafts of any
3320 # The only changesets we can be sure doesn't contain grafts of any
3321 # revs, are the ones that are common ancestors of *all* revs:
3321 # revs, are the ones that are common ancestors of *all* revs:
3322 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3322 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3323 ctx = repo[rev]
3323 ctx = repo[rev]
3324 n = ctx.extra().get(b'source')
3324 n = ctx.extra().get(b'source')
3325 if n in ids:
3325 if n in ids:
3326 try:
3326 try:
3327 r = repo[n].rev()
3327 r = repo[n].rev()
3328 except error.RepoLookupError:
3328 except error.RepoLookupError:
3329 r = None
3329 r = None
3330 if r in revs:
3330 if r in revs:
3331 ui.warn(
3331 ui.warn(
3332 _(
3332 _(
3333 b'skipping revision %d:%s '
3333 b'skipping revision %d:%s '
3334 b'(already grafted to %d:%s)\n'
3334 b'(already grafted to %d:%s)\n'
3335 )
3335 )
3336 % (r, repo[r], rev, ctx)
3336 % (r, repo[r], rev, ctx)
3337 )
3337 )
3338 revs.remove(r)
3338 revs.remove(r)
3339 elif ids[n] in revs:
3339 elif ids[n] in revs:
3340 if r is None:
3340 if r is None:
3341 ui.warn(
3341 ui.warn(
3342 _(
3342 _(
3343 b'skipping already grafted revision %d:%s '
3343 b'skipping already grafted revision %d:%s '
3344 b'(%d:%s also has unknown origin %s)\n'
3344 b'(%d:%s also has unknown origin %s)\n'
3345 )
3345 )
3346 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3346 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3347 )
3347 )
3348 else:
3348 else:
3349 ui.warn(
3349 ui.warn(
3350 _(
3350 _(
3351 b'skipping already grafted revision %d:%s '
3351 b'skipping already grafted revision %d:%s '
3352 b'(%d:%s also has origin %d:%s)\n'
3352 b'(%d:%s also has origin %d:%s)\n'
3353 )
3353 )
3354 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3354 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3355 )
3355 )
3356 revs.remove(ids[n])
3356 revs.remove(ids[n])
3357 elif ctx.hex() in ids:
3357 elif ctx.hex() in ids:
3358 r = ids[ctx.hex()]
3358 r = ids[ctx.hex()]
3359 if r in revs:
3359 if r in revs:
3360 ui.warn(
3360 ui.warn(
3361 _(
3361 _(
3362 b'skipping already grafted revision %d:%s '
3362 b'skipping already grafted revision %d:%s '
3363 b'(was grafted from %d:%s)\n'
3363 b'(was grafted from %d:%s)\n'
3364 )
3364 )
3365 % (r, repo[r], rev, ctx)
3365 % (r, repo[r], rev, ctx)
3366 )
3366 )
3367 revs.remove(r)
3367 revs.remove(r)
3368 if not revs:
3368 if not revs:
3369 return -1
3369 return -1
3370
3370
3371 if opts.get('no_commit'):
3371 if opts.get('no_commit'):
3372 statedata[b'no_commit'] = True
3372 statedata[b'no_commit'] = True
3373 if opts.get('base'):
3373 if opts.get('base'):
3374 statedata[b'base'] = opts['base']
3374 statedata[b'base'] = opts['base']
3375 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3375 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3376 desc = b'%d:%s "%s"' % (
3376 desc = b'%d:%s "%s"' % (
3377 ctx.rev(),
3377 ctx.rev(),
3378 ctx,
3378 ctx,
3379 ctx.description().split(b'\n', 1)[0],
3379 ctx.description().split(b'\n', 1)[0],
3380 )
3380 )
3381 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3381 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3382 if names:
3382 if names:
3383 desc += b' (%s)' % b' '.join(names)
3383 desc += b' (%s)' % b' '.join(names)
3384 ui.status(_(b'grafting %s\n') % desc)
3384 ui.status(_(b'grafting %s\n') % desc)
3385 if opts.get('dry_run'):
3385 if opts.get('dry_run'):
3386 continue
3386 continue
3387
3387
3388 source = ctx.extra().get(b'source')
3388 source = ctx.extra().get(b'source')
3389 extra = {}
3389 extra = {}
3390 if source:
3390 if source:
3391 extra[b'source'] = source
3391 extra[b'source'] = source
3392 extra[b'intermediate-source'] = ctx.hex()
3392 extra[b'intermediate-source'] = ctx.hex()
3393 else:
3393 else:
3394 extra[b'source'] = ctx.hex()
3394 extra[b'source'] = ctx.hex()
3395 user = ctx.user()
3395 user = ctx.user()
3396 if opts.get('user'):
3396 if opts.get('user'):
3397 user = opts['user']
3397 user = opts['user']
3398 statedata[b'user'] = user
3398 statedata[b'user'] = user
3399 date = ctx.date()
3399 date = ctx.date()
3400 if opts.get('date'):
3400 if opts.get('date'):
3401 date = opts['date']
3401 date = opts['date']
3402 statedata[b'date'] = date
3402 statedata[b'date'] = date
3403 message = ctx.description()
3403 message = ctx.description()
3404 if opts.get('log'):
3404 if opts.get('log'):
3405 message += b'\n(grafted from %s)' % ctx.hex()
3405 message += b'\n(grafted from %s)' % ctx.hex()
3406 statedata[b'log'] = True
3406 statedata[b'log'] = True
3407
3407
3408 # we don't merge the first commit when continuing
3408 # we don't merge the first commit when continuing
3409 if not cont:
3409 if not cont:
3410 # perform the graft merge with p1(rev) as 'ancestor'
3410 # perform the graft merge with p1(rev) as 'ancestor'
3411 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
3411 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
3412 base = ctx.p1() if basectx is None else basectx
3412 base = ctx.p1() if basectx is None else basectx
3413 with ui.configoverride(overrides, b'graft'):
3413 with ui.configoverride(overrides, b'graft'):
3414 stats = mergemod.graft(
3414 stats = mergemod.graft(
3415 repo, ctx, base, [b'local', b'graft', b'parent of graft']
3415 repo, ctx, base, [b'local', b'graft', b'parent of graft']
3416 )
3416 )
3417 # report any conflicts
3417 # report any conflicts
3418 if stats.unresolvedcount > 0:
3418 if stats.unresolvedcount > 0:
3419 # write out state for --continue
3419 # write out state for --continue
3420 nodes = [repo[rev].hex() for rev in revs[pos:]]
3420 nodes = [repo[rev].hex() for rev in revs[pos:]]
3421 statedata[b'nodes'] = nodes
3421 statedata[b'nodes'] = nodes
3422 stateversion = 1
3422 stateversion = 1
3423 graftstate.save(stateversion, statedata)
3423 graftstate.save(stateversion, statedata)
3424 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3424 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3425 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3425 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3426 return 1
3426 return 1
3427 else:
3427 else:
3428 cont = False
3428 cont = False
3429
3429
3430 # commit if --no-commit is false
3430 # commit if --no-commit is false
3431 if not opts.get('no_commit'):
3431 if not opts.get('no_commit'):
3432 node = repo.commit(
3432 node = repo.commit(
3433 text=message, user=user, date=date, extra=extra, editor=editor
3433 text=message, user=user, date=date, extra=extra, editor=editor
3434 )
3434 )
3435 if node is None:
3435 if node is None:
3436 ui.warn(
3436 ui.warn(
3437 _(b'note: graft of %d:%s created no changes to commit\n')
3437 _(b'note: graft of %d:%s created no changes to commit\n')
3438 % (ctx.rev(), ctx)
3438 % (ctx.rev(), ctx)
3439 )
3439 )
3440 # checking that newnodes exist because old state files won't have it
3440 # checking that newnodes exist because old state files won't have it
3441 elif statedata.get(b'newnodes') is not None:
3441 elif statedata.get(b'newnodes') is not None:
3442 nn = statedata[b'newnodes']
3442 nn = statedata[b'newnodes']
3443 assert isinstance(nn, list) # list of bytes
3443 assert isinstance(nn, list) # list of bytes
3444 nn.append(node)
3444 nn.append(node)
3445
3445
3446 # remove state when we complete successfully
3446 # remove state when we complete successfully
3447 if not opts.get('dry_run'):
3447 if not opts.get('dry_run'):
3448 graftstate.delete()
3448 graftstate.delete()
3449
3449
3450 return 0
3450 return 0
3451
3451
3452
3452
3453 def _stopgraft(ui, repo, graftstate):
3453 def _stopgraft(ui, repo, graftstate):
3454 """stop the interrupted graft"""
3454 """stop the interrupted graft"""
3455 if not graftstate.exists():
3455 if not graftstate.exists():
3456 raise error.StateError(_(b"no interrupted graft found"))
3456 raise error.StateError(_(b"no interrupted graft found"))
3457 pctx = repo[b'.']
3457 pctx = repo[b'.']
3458 mergemod.clean_update(pctx)
3458 mergemod.clean_update(pctx)
3459 graftstate.delete()
3459 graftstate.delete()
3460 ui.status(_(b"stopped the interrupted graft\n"))
3460 ui.status(_(b"stopped the interrupted graft\n"))
3461 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3461 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3462 return 0
3462 return 0
3463
3463
3464
3464
3465 statemod.addunfinished(
3465 statemod.addunfinished(
3466 b'graft',
3466 b'graft',
3467 fname=b'graftstate',
3467 fname=b'graftstate',
3468 clearable=True,
3468 clearable=True,
3469 stopflag=True,
3469 stopflag=True,
3470 continueflag=True,
3470 continueflag=True,
3471 abortfunc=cmdutil.hgabortgraft,
3471 abortfunc=cmdutil.hgabortgraft,
3472 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3472 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3473 )
3473 )
3474
3474
3475
3475
3476 @command(
3476 @command(
3477 b'grep',
3477 b'grep',
3478 [
3478 [
3479 (b'0', b'print0', None, _(b'end fields with NUL')),
3479 (b'0', b'print0', None, _(b'end fields with NUL')),
3480 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3480 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3481 (
3481 (
3482 b'',
3482 b'',
3483 b'diff',
3483 b'diff',
3484 None,
3484 None,
3485 _(
3485 _(
3486 b'search revision differences for when the pattern was added '
3486 b'search revision differences for when the pattern was added '
3487 b'or removed'
3487 b'or removed'
3488 ),
3488 ),
3489 ),
3489 ),
3490 (b'a', b'text', None, _(b'treat all files as text')),
3490 (b'a', b'text', None, _(b'treat all files as text')),
3491 (
3491 (
3492 b'f',
3492 b'f',
3493 b'follow',
3493 b'follow',
3494 None,
3494 None,
3495 _(
3495 _(
3496 b'follow changeset history,'
3496 b'follow changeset history,'
3497 b' or file history across copies and renames'
3497 b' or file history across copies and renames'
3498 ),
3498 ),
3499 ),
3499 ),
3500 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3500 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3501 (
3501 (
3502 b'l',
3502 b'l',
3503 b'files-with-matches',
3503 b'files-with-matches',
3504 None,
3504 None,
3505 _(b'print only filenames and revisions that match'),
3505 _(b'print only filenames and revisions that match'),
3506 ),
3506 ),
3507 (b'n', b'line-number', None, _(b'print matching line numbers')),
3507 (b'n', b'line-number', None, _(b'print matching line numbers')),
3508 (
3508 (
3509 b'r',
3509 b'r',
3510 b'rev',
3510 b'rev',
3511 [],
3511 [],
3512 _(b'search files changed within revision range'),
3512 _(b'search files changed within revision range'),
3513 _(b'REV'),
3513 _(b'REV'),
3514 ),
3514 ),
3515 (
3515 (
3516 b'',
3516 b'',
3517 b'all-files',
3517 b'all-files',
3518 None,
3518 None,
3519 _(
3519 _(
3520 b'include all files in the changeset while grepping (DEPRECATED)'
3520 b'include all files in the changeset while grepping (DEPRECATED)'
3521 ),
3521 ),
3522 ),
3522 ),
3523 (b'u', b'user', None, _(b'list the author (long with -v)')),
3523 (b'u', b'user', None, _(b'list the author (long with -v)')),
3524 (b'd', b'date', None, _(b'list the date (short with -q)')),
3524 (b'd', b'date', None, _(b'list the date (short with -q)')),
3525 ]
3525 ]
3526 + formatteropts
3526 + formatteropts
3527 + walkopts,
3527 + walkopts,
3528 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3528 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3529 helpcategory=command.CATEGORY_FILE_CONTENTS,
3529 helpcategory=command.CATEGORY_FILE_CONTENTS,
3530 inferrepo=True,
3530 inferrepo=True,
3531 intents={INTENT_READONLY},
3531 intents={INTENT_READONLY},
3532 )
3532 )
3533 def grep(ui, repo, pattern, *pats, **opts):
3533 def grep(ui, repo, pattern, *pats, **opts):
3534 """search for a pattern in specified files
3534 """search for a pattern in specified files
3535
3535
3536 Search the working directory or revision history for a regular
3536 Search the working directory or revision history for a regular
3537 expression in the specified files for the entire repository.
3537 expression in the specified files for the entire repository.
3538
3538
3539 By default, grep searches the repository files in the working
3539 By default, grep searches the repository files in the working
3540 directory and prints the files where it finds a match. To specify
3540 directory and prints the files where it finds a match. To specify
3541 historical revisions instead of the working directory, use the
3541 historical revisions instead of the working directory, use the
3542 --rev flag.
3542 --rev flag.
3543
3543
3544 To search instead historical revision differences that contains a
3544 To search instead historical revision differences that contains a
3545 change in match status ("-" for a match that becomes a non-match,
3545 change in match status ("-" for a match that becomes a non-match,
3546 or "+" for a non-match that becomes a match), use the --diff flag.
3546 or "+" for a non-match that becomes a match), use the --diff flag.
3547
3547
3548 PATTERN can be any Python (roughly Perl-compatible) regular
3548 PATTERN can be any Python (roughly Perl-compatible) regular
3549 expression.
3549 expression.
3550
3550
3551 If no FILEs are specified and the --rev flag isn't supplied, all
3551 If no FILEs are specified and the --rev flag isn't supplied, all
3552 files in the working directory are searched. When using the --rev
3552 files in the working directory are searched. When using the --rev
3553 flag and specifying FILEs, use the --follow argument to also
3553 flag and specifying FILEs, use the --follow argument to also
3554 follow the specified FILEs across renames and copies.
3554 follow the specified FILEs across renames and copies.
3555
3555
3556 .. container:: verbose
3556 .. container:: verbose
3557
3557
3558 Template:
3558 Template:
3559
3559
3560 The following keywords are supported in addition to the common template
3560 The following keywords are supported in addition to the common template
3561 keywords and functions. See also :hg:`help templates`.
3561 keywords and functions. See also :hg:`help templates`.
3562
3562
3563 :change: String. Character denoting insertion ``+`` or removal ``-``.
3563 :change: String. Character denoting insertion ``+`` or removal ``-``.
3564 Available if ``--diff`` is specified.
3564 Available if ``--diff`` is specified.
3565 :lineno: Integer. Line number of the match.
3565 :lineno: Integer. Line number of the match.
3566 :path: String. Repository-absolute path of the file.
3566 :path: String. Repository-absolute path of the file.
3567 :texts: List of text chunks.
3567 :texts: List of text chunks.
3568
3568
3569 And each entry of ``{texts}`` provides the following sub-keywords.
3569 And each entry of ``{texts}`` provides the following sub-keywords.
3570
3570
3571 :matched: Boolean. True if the chunk matches the specified pattern.
3571 :matched: Boolean. True if the chunk matches the specified pattern.
3572 :text: String. Chunk content.
3572 :text: String. Chunk content.
3573
3573
3574 See :hg:`help templates.operators` for the list expansion syntax.
3574 See :hg:`help templates.operators` for the list expansion syntax.
3575
3575
3576 Returns 0 if a match is found, 1 otherwise.
3576 Returns 0 if a match is found, 1 otherwise.
3577
3577
3578 """
3578 """
3579 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3579 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3580
3580
3581 diff = opts.get('all') or opts.get('diff')
3581 diff = opts.get('all') or opts.get('diff')
3582 follow = opts.get('follow')
3582 follow = opts.get('follow')
3583 if opts.get('all_files') is None and not diff:
3583 if opts.get('all_files') is None and not diff:
3584 opts['all_files'] = True
3584 opts['all_files'] = True
3585 plaingrep = (
3585 plaingrep = (
3586 opts.get('all_files') and not opts.get('rev') and not opts.get('follow')
3586 opts.get('all_files') and not opts.get('rev') and not opts.get('follow')
3587 )
3587 )
3588 all_files = opts.get('all_files')
3588 all_files = opts.get('all_files')
3589 if plaingrep:
3589 if plaingrep:
3590 opts['rev'] = [b'wdir()']
3590 opts['rev'] = [b'wdir()']
3591
3591
3592 reflags = re.M
3592 reflags = re.M
3593 if opts.get('ignore_case'):
3593 if opts.get('ignore_case'):
3594 reflags |= re.I
3594 reflags |= re.I
3595 try:
3595 try:
3596 regexp = util.re.compile(pattern, reflags)
3596 regexp = util.re.compile(pattern, reflags)
3597 except re.error as inst:
3597 except re.error as inst:
3598 ui.warn(
3598 ui.warn(
3599 _(b"grep: invalid match pattern: %s\n")
3599 _(b"grep: invalid match pattern: %s\n")
3600 % stringutil.forcebytestr(inst)
3600 % stringutil.forcebytestr(inst)
3601 )
3601 )
3602 return 1
3602 return 1
3603 sep, eol = b':', b'\n'
3603 sep, eol = b':', b'\n'
3604 if opts.get('print0'):
3604 if opts.get('print0'):
3605 sep = eol = b'\0'
3605 sep = eol = b'\0'
3606
3606
3607 searcher = grepmod.grepsearcher(
3607 searcher = grepmod.grepsearcher(
3608 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3608 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3609 )
3609 )
3610
3610
3611 getfile = searcher._getfile
3611 getfile = searcher._getfile
3612
3612
3613 uipathfn = scmutil.getuipathfn(repo)
3613 uipathfn = scmutil.getuipathfn(repo)
3614
3614
3615 def display(fm, fn, ctx, pstates, states):
3615 def display(fm, fn, ctx, pstates, states):
3616 rev = scmutil.intrev(ctx)
3616 rev = scmutil.intrev(ctx)
3617 if fm.isplain():
3617 if fm.isplain():
3618 formatuser = ui.shortuser
3618 formatuser = ui.shortuser
3619 else:
3619 else:
3620 formatuser = pycompat.bytestr
3620 formatuser = pycompat.bytestr
3621 if ui.quiet:
3621 if ui.quiet:
3622 datefmt = b'%Y-%m-%d'
3622 datefmt = b'%Y-%m-%d'
3623 else:
3623 else:
3624 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3624 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3625 found = False
3625 found = False
3626
3626
3627 @util.cachefunc
3627 @util.cachefunc
3628 def binary():
3628 def binary():
3629 flog = getfile(fn)
3629 flog = getfile(fn)
3630 try:
3630 try:
3631 return stringutil.binary(flog.read(ctx.filenode(fn)))
3631 return stringutil.binary(flog.read(ctx.filenode(fn)))
3632 except error.WdirUnsupported:
3632 except error.WdirUnsupported:
3633 return ctx[fn].isbinary()
3633 return ctx[fn].isbinary()
3634
3634
3635 fieldnamemap = {b'linenumber': b'lineno'}
3635 fieldnamemap = {b'linenumber': b'lineno'}
3636 if diff:
3636 if diff:
3637 iter = grepmod.difflinestates(pstates, states)
3637 iter = grepmod.difflinestates(pstates, states)
3638 else:
3638 else:
3639 iter = [(b'', l) for l in states]
3639 iter = [(b'', l) for l in states]
3640 for change, l in iter:
3640 for change, l in iter:
3641 fm.startitem()
3641 fm.startitem()
3642 fm.context(ctx=ctx)
3642 fm.context(ctx=ctx)
3643 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3643 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3644 fm.plain(uipathfn(fn), label=b'grep.filename')
3644 fm.plain(uipathfn(fn), label=b'grep.filename')
3645
3645
3646 cols = [
3646 cols = [
3647 (b'rev', b'%d', rev, not plaingrep, b''),
3647 (b'rev', b'%d', rev, not plaingrep, b''),
3648 (
3648 (
3649 b'linenumber',
3649 b'linenumber',
3650 b'%d',
3650 b'%d',
3651 l.linenum,
3651 l.linenum,
3652 opts.get('line_number'),
3652 opts.get('line_number'),
3653 b'',
3653 b'',
3654 ),
3654 ),
3655 ]
3655 ]
3656 if diff:
3656 if diff:
3657 cols.append(
3657 cols.append(
3658 (
3658 (
3659 b'change',
3659 b'change',
3660 b'%s',
3660 b'%s',
3661 change,
3661 change,
3662 True,
3662 True,
3663 b'grep.inserted '
3663 b'grep.inserted '
3664 if change == b'+'
3664 if change == b'+'
3665 else b'grep.deleted ',
3665 else b'grep.deleted ',
3666 )
3666 )
3667 )
3667 )
3668 cols.extend(
3668 cols.extend(
3669 [
3669 [
3670 (
3670 (
3671 b'user',
3671 b'user',
3672 b'%s',
3672 b'%s',
3673 formatuser(ctx.user()),
3673 formatuser(ctx.user()),
3674 opts.get('user'),
3674 opts.get('user'),
3675 b'',
3675 b'',
3676 ),
3676 ),
3677 (
3677 (
3678 b'date',
3678 b'date',
3679 b'%s',
3679 b'%s',
3680 fm.formatdate(ctx.date(), datefmt),
3680 fm.formatdate(ctx.date(), datefmt),
3681 opts.get('date'),
3681 opts.get('date'),
3682 b'',
3682 b'',
3683 ),
3683 ),
3684 ]
3684 ]
3685 )
3685 )
3686 for name, fmt, data, cond, extra_label in cols:
3686 for name, fmt, data, cond, extra_label in cols:
3687 if cond:
3687 if cond:
3688 fm.plain(sep, label=b'grep.sep')
3688 fm.plain(sep, label=b'grep.sep')
3689 field = fieldnamemap.get(name, name)
3689 field = fieldnamemap.get(name, name)
3690 label = extra_label + (b'grep.%s' % name)
3690 label = extra_label + (b'grep.%s' % name)
3691 fm.condwrite(cond, field, fmt, data, label=label)
3691 fm.condwrite(cond, field, fmt, data, label=label)
3692 if not opts.get('files_with_matches'):
3692 if not opts.get('files_with_matches'):
3693 fm.plain(sep, label=b'grep.sep')
3693 fm.plain(sep, label=b'grep.sep')
3694 if not opts.get('text') and binary():
3694 if not opts.get('text') and binary():
3695 fm.plain(_(b" Binary file matches"))
3695 fm.plain(_(b" Binary file matches"))
3696 else:
3696 else:
3697 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3697 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3698 fm.plain(eol)
3698 fm.plain(eol)
3699 found = True
3699 found = True
3700 if opts.get('files_with_matches'):
3700 if opts.get('files_with_matches'):
3701 break
3701 break
3702 return found
3702 return found
3703
3703
3704 def displaymatches(fm, l):
3704 def displaymatches(fm, l):
3705 p = 0
3705 p = 0
3706 for s, e in l.findpos(regexp):
3706 for s, e in l.findpos(regexp):
3707 if p < s:
3707 if p < s:
3708 fm.startitem()
3708 fm.startitem()
3709 fm.write(b'text', b'%s', l.line[p:s])
3709 fm.write(b'text', b'%s', l.line[p:s])
3710 fm.data(matched=False)
3710 fm.data(matched=False)
3711 fm.startitem()
3711 fm.startitem()
3712 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3712 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3713 fm.data(matched=True)
3713 fm.data(matched=True)
3714 p = e
3714 p = e
3715 if p < len(l.line):
3715 if p < len(l.line):
3716 fm.startitem()
3716 fm.startitem()
3717 fm.write(b'text', b'%s', l.line[p:])
3717 fm.write(b'text', b'%s', l.line[p:])
3718 fm.data(matched=False)
3718 fm.data(matched=False)
3719 fm.end()
3719 fm.end()
3720
3720
3721 found = False
3721 found = False
3722
3722
3723 wopts = logcmdutil.walkopts(
3723 wopts = logcmdutil.walkopts(
3724 pats=pats,
3724 pats=pats,
3725 opts=pycompat.byteskwargs(opts),
3725 opts=pycompat.byteskwargs(opts),
3726 revspec=opts['rev'],
3726 revspec=opts['rev'],
3727 include_pats=opts['include'],
3727 include_pats=opts['include'],
3728 exclude_pats=opts['exclude'],
3728 exclude_pats=opts['exclude'],
3729 follow=follow,
3729 follow=follow,
3730 force_changelog_traversal=all_files,
3730 force_changelog_traversal=all_files,
3731 filter_revisions_by_pats=not all_files,
3731 filter_revisions_by_pats=not all_files,
3732 )
3732 )
3733 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3733 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3734
3734
3735 ui.pager(b'grep')
3735 ui.pager(b'grep')
3736 fm = ui.formatter(b'grep', pycompat.byteskwargs(opts))
3736 fm = ui.formatter(b'grep', pycompat.byteskwargs(opts))
3737 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3737 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3738 r = display(fm, fn, ctx, pstates, states)
3738 r = display(fm, fn, ctx, pstates, states)
3739 found = found or r
3739 found = found or r
3740 if r and not diff and not all_files:
3740 if r and not diff and not all_files:
3741 searcher.skipfile(fn, ctx.rev())
3741 searcher.skipfile(fn, ctx.rev())
3742 fm.end()
3742 fm.end()
3743
3743
3744 return not found
3744 return not found
3745
3745
3746
3746
3747 @command(
3747 @command(
3748 b'heads',
3748 b'heads',
3749 [
3749 [
3750 (
3750 (
3751 b'r',
3751 b'r',
3752 b'rev',
3752 b'rev',
3753 b'',
3753 b'',
3754 _(b'show only heads which are descendants of STARTREV'),
3754 _(b'show only heads which are descendants of STARTREV'),
3755 _(b'STARTREV'),
3755 _(b'STARTREV'),
3756 ),
3756 ),
3757 (b't', b'topo', False, _(b'show topological heads only')),
3757 (b't', b'topo', False, _(b'show topological heads only')),
3758 (
3758 (
3759 b'a',
3759 b'a',
3760 b'active',
3760 b'active',
3761 False,
3761 False,
3762 _(b'show active branchheads only (DEPRECATED)'),
3762 _(b'show active branchheads only (DEPRECATED)'),
3763 ),
3763 ),
3764 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3764 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3765 ]
3765 ]
3766 + templateopts,
3766 + templateopts,
3767 _(b'[-ct] [-r STARTREV] [REV]...'),
3767 _(b'[-ct] [-r STARTREV] [REV]...'),
3768 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3768 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3769 intents={INTENT_READONLY},
3769 intents={INTENT_READONLY},
3770 )
3770 )
3771 def heads(ui, repo, *branchrevs, **opts):
3771 def heads(ui, repo, *branchrevs, **opts):
3772 """show branch heads
3772 """show branch heads
3773
3773
3774 With no arguments, show all open branch heads in the repository.
3774 With no arguments, show all open branch heads in the repository.
3775 Branch heads are changesets that have no descendants on the
3775 Branch heads are changesets that have no descendants on the
3776 same branch. They are where development generally takes place and
3776 same branch. They are where development generally takes place and
3777 are the usual targets for update and merge operations.
3777 are the usual targets for update and merge operations.
3778
3778
3779 If one or more REVs are given, only open branch heads on the
3779 If one or more REVs are given, only open branch heads on the
3780 branches associated with the specified changesets are shown. This
3780 branches associated with the specified changesets are shown. This
3781 means that you can use :hg:`heads .` to see the heads on the
3781 means that you can use :hg:`heads .` to see the heads on the
3782 currently checked-out branch.
3782 currently checked-out branch.
3783
3783
3784 If -c/--closed is specified, also show branch heads marked closed
3784 If -c/--closed is specified, also show branch heads marked closed
3785 (see :hg:`commit --close-branch`).
3785 (see :hg:`commit --close-branch`).
3786
3786
3787 If STARTREV is specified, only those heads that are descendants of
3787 If STARTREV is specified, only those heads that are descendants of
3788 STARTREV will be displayed.
3788 STARTREV will be displayed.
3789
3789
3790 If -t/--topo is specified, named branch mechanics will be ignored and only
3790 If -t/--topo is specified, named branch mechanics will be ignored and only
3791 topological heads (changesets with no children) will be shown.
3791 topological heads (changesets with no children) will be shown.
3792
3792
3793 Returns 0 if matching heads are found, 1 if not.
3793 Returns 0 if matching heads are found, 1 if not.
3794 """
3794 """
3795
3795
3796 start = None
3796 start = None
3797 rev = opts.get('rev')
3797 rev = opts.get('rev')
3798 if rev:
3798 if rev:
3799 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3799 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3800 start = logcmdutil.revsingle(repo, rev, None).node()
3800 start = logcmdutil.revsingle(repo, rev, None).node()
3801
3801
3802 if opts.get('topo'):
3802 if opts.get('topo'):
3803 heads = [repo[h] for h in repo.heads(start)]
3803 heads = [repo[h] for h in repo.heads(start)]
3804 else:
3804 else:
3805 heads = []
3805 heads = []
3806 for branch in repo.branchmap():
3806 for branch in repo.branchmap():
3807 heads += repo.branchheads(branch, start, opts.get('closed'))
3807 heads += repo.branchheads(branch, start, opts.get('closed'))
3808 heads = [repo[h] for h in heads]
3808 heads = [repo[h] for h in heads]
3809
3809
3810 if branchrevs:
3810 if branchrevs:
3811 branches = {
3811 branches = {
3812 repo[r].branch() for r in logcmdutil.revrange(repo, branchrevs)
3812 repo[r].branch() for r in logcmdutil.revrange(repo, branchrevs)
3813 }
3813 }
3814 heads = [h for h in heads if h.branch() in branches]
3814 heads = [h for h in heads if h.branch() in branches]
3815
3815
3816 if opts.get('active') and branchrevs:
3816 if opts.get('active') and branchrevs:
3817 dagheads = repo.heads(start)
3817 dagheads = repo.heads(start)
3818 heads = [h for h in heads if h.node() in dagheads]
3818 heads = [h for h in heads if h.node() in dagheads]
3819
3819
3820 if branchrevs:
3820 if branchrevs:
3821 haveheads = {h.branch() for h in heads}
3821 haveheads = {h.branch() for h in heads}
3822 if branches - haveheads:
3822 if branches - haveheads:
3823 headless = b', '.join(b for b in branches - haveheads)
3823 headless = b', '.join(b for b in branches - haveheads)
3824 msg = _(b'no open branch heads found on branches %s')
3824 msg = _(b'no open branch heads found on branches %s')
3825 if opts.get('rev'):
3825 if opts.get('rev'):
3826 msg += _(b' (started at %s)') % opts['rev']
3826 msg += _(b' (started at %s)') % opts['rev']
3827 ui.warn((msg + b'\n') % headless)
3827 ui.warn((msg + b'\n') % headless)
3828
3828
3829 if not heads:
3829 if not heads:
3830 return 1
3830 return 1
3831
3831
3832 ui.pager(b'heads')
3832 ui.pager(b'heads')
3833 heads = sorted(heads, key=lambda x: -(x.rev()))
3833 heads = sorted(heads, key=lambda x: -(x.rev()))
3834 displayer = logcmdutil.changesetdisplayer(
3834 displayer = logcmdutil.changesetdisplayer(
3835 ui, repo, pycompat.byteskwargs(opts)
3835 ui, repo, pycompat.byteskwargs(opts)
3836 )
3836 )
3837 for ctx in heads:
3837 for ctx in heads:
3838 displayer.show(ctx)
3838 displayer.show(ctx)
3839 displayer.close()
3839 displayer.close()
3840
3840
3841
3841
3842 @command(
3842 @command(
3843 b'help',
3843 b'help',
3844 [
3844 [
3845 (b'e', b'extension', None, _(b'show only help for extensions')),
3845 (b'e', b'extension', None, _(b'show only help for extensions')),
3846 (b'c', b'command', None, _(b'show only help for commands')),
3846 (b'c', b'command', None, _(b'show only help for commands')),
3847 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3847 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3848 (
3848 (
3849 b's',
3849 b's',
3850 b'system',
3850 b'system',
3851 [],
3851 [],
3852 _(b'show help for specific platform(s)'),
3852 _(b'show help for specific platform(s)'),
3853 _(b'PLATFORM'),
3853 _(b'PLATFORM'),
3854 ),
3854 ),
3855 ],
3855 ],
3856 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3856 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3857 helpcategory=command.CATEGORY_HELP,
3857 helpcategory=command.CATEGORY_HELP,
3858 norepo=True,
3858 norepo=True,
3859 intents={INTENT_READONLY},
3859 intents={INTENT_READONLY},
3860 )
3860 )
3861 def help_(ui, name=None, **opts):
3861 def help_(ui, name=None, **opts):
3862 """show help for a given topic or a help overview
3862 """show help for a given topic or a help overview
3863
3863
3864 With no arguments, print a list of commands with short help messages.
3864 With no arguments, print a list of commands with short help messages.
3865
3865
3866 Given a topic, extension, or command name, print help for that
3866 Given a topic, extension, or command name, print help for that
3867 topic.
3867 topic.
3868
3868
3869 Returns 0 if successful.
3869 Returns 0 if successful.
3870 """
3870 """
3871
3871
3872 keep = opts.get('system') or []
3872 keep = opts.get('system') or []
3873 if len(keep) == 0:
3873 if len(keep) == 0:
3874 if pycompat.sysplatform.startswith(b'win'):
3874 if pycompat.sysplatform.startswith(b'win'):
3875 keep.append(b'windows')
3875 keep.append(b'windows')
3876 elif pycompat.sysplatform == b'OpenVMS':
3876 elif pycompat.sysplatform == b'OpenVMS':
3877 keep.append(b'vms')
3877 keep.append(b'vms')
3878 elif pycompat.sysplatform == b'plan9':
3878 elif pycompat.sysplatform == b'plan9':
3879 keep.append(b'plan9')
3879 keep.append(b'plan9')
3880 else:
3880 else:
3881 keep.append(b'unix')
3881 keep.append(b'unix')
3882 keep.append(pycompat.sysplatform.lower())
3882 keep.append(pycompat.sysplatform.lower())
3883 if ui.verbose:
3883 if ui.verbose:
3884 keep.append(b'verbose')
3884 keep.append(b'verbose')
3885
3885
3886 commands = sys.modules[__name__]
3886 commands = sys.modules[__name__]
3887 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3887 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3888 ui.pager(b'help')
3888 ui.pager(b'help')
3889 ui.write(formatted)
3889 ui.write(formatted)
3890
3890
3891
3891
3892 @command(
3892 @command(
3893 b'identify|id',
3893 b'identify|id',
3894 [
3894 [
3895 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3895 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3896 (b'n', b'num', None, _(b'show local revision number')),
3896 (b'n', b'num', None, _(b'show local revision number')),
3897 (b'i', b'id', None, _(b'show global revision id')),
3897 (b'i', b'id', None, _(b'show global revision id')),
3898 (b'b', b'branch', None, _(b'show branch')),
3898 (b'b', b'branch', None, _(b'show branch')),
3899 (b't', b'tags', None, _(b'show tags')),
3899 (b't', b'tags', None, _(b'show tags')),
3900 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3900 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3901 ]
3901 ]
3902 + remoteopts
3902 + remoteopts
3903 + formatteropts,
3903 + formatteropts,
3904 _(b'[-nibtB] [-r REV] [SOURCE]'),
3904 _(b'[-nibtB] [-r REV] [SOURCE]'),
3905 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3905 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3906 optionalrepo=True,
3906 optionalrepo=True,
3907 intents={INTENT_READONLY},
3907 intents={INTENT_READONLY},
3908 )
3908 )
3909 def identify(
3909 def identify(
3910 ui,
3910 ui,
3911 repo,
3911 repo,
3912 source=None,
3912 source=None,
3913 rev=None,
3913 rev=None,
3914 num=None,
3914 num=None,
3915 id=None,
3915 id=None,
3916 branch=None,
3916 branch=None,
3917 tags=None,
3917 tags=None,
3918 bookmarks=None,
3918 bookmarks=None,
3919 **opts
3919 **opts
3920 ):
3920 ):
3921 """identify the working directory or specified revision
3921 """identify the working directory or specified revision
3922
3922
3923 Print a summary identifying the repository state at REV using one or
3923 Print a summary identifying the repository state at REV using one or
3924 two parent hash identifiers, followed by a "+" if the working
3924 two parent hash identifiers, followed by a "+" if the working
3925 directory has uncommitted changes, the branch name (if not default),
3925 directory has uncommitted changes, the branch name (if not default),
3926 a list of tags, and a list of bookmarks.
3926 a list of tags, and a list of bookmarks.
3927
3927
3928 When REV is not given, print a summary of the current state of the
3928 When REV is not given, print a summary of the current state of the
3929 repository including the working directory. Specify -r. to get information
3929 repository including the working directory. Specify -r. to get information
3930 of the working directory parent without scanning uncommitted changes.
3930 of the working directory parent without scanning uncommitted changes.
3931
3931
3932 Specifying a path to a repository root or Mercurial bundle will
3932 Specifying a path to a repository root or Mercurial bundle will
3933 cause lookup to operate on that repository/bundle.
3933 cause lookup to operate on that repository/bundle.
3934
3934
3935 .. container:: verbose
3935 .. container:: verbose
3936
3936
3937 Template:
3937 Template:
3938
3938
3939 The following keywords are supported in addition to the common template
3939 The following keywords are supported in addition to the common template
3940 keywords and functions. See also :hg:`help templates`.
3940 keywords and functions. See also :hg:`help templates`.
3941
3941
3942 :dirty: String. Character ``+`` denoting if the working directory has
3942 :dirty: String. Character ``+`` denoting if the working directory has
3943 uncommitted changes.
3943 uncommitted changes.
3944 :id: String. One or two nodes, optionally followed by ``+``.
3944 :id: String. One or two nodes, optionally followed by ``+``.
3945 :parents: List of strings. Parent nodes of the changeset.
3945 :parents: List of strings. Parent nodes of the changeset.
3946
3946
3947 Examples:
3947 Examples:
3948
3948
3949 - generate a build identifier for the working directory::
3949 - generate a build identifier for the working directory::
3950
3950
3951 hg id --id > build-id.dat
3951 hg id --id > build-id.dat
3952
3952
3953 - find the revision corresponding to a tag::
3953 - find the revision corresponding to a tag::
3954
3954
3955 hg id -n -r 1.3
3955 hg id -n -r 1.3
3956
3956
3957 - check the most recent revision of a remote repository::
3957 - check the most recent revision of a remote repository::
3958
3958
3959 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3959 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3960
3960
3961 See :hg:`log` for generating more information about specific revisions,
3961 See :hg:`log` for generating more information about specific revisions,
3962 including full hash identifiers.
3962 including full hash identifiers.
3963
3963
3964 Returns 0 if successful.
3964 Returns 0 if successful.
3965 """
3965 """
3966
3966
3967 opts = pycompat.byteskwargs(opts)
3967 opts = pycompat.byteskwargs(opts)
3968 if not repo and not source:
3968 if not repo and not source:
3969 raise error.InputError(
3969 raise error.InputError(
3970 _(b"there is no Mercurial repository here (.hg not found)")
3970 _(b"there is no Mercurial repository here (.hg not found)")
3971 )
3971 )
3972
3972
3973 default = not (num or id or branch or tags or bookmarks)
3973 default = not (num or id or branch or tags or bookmarks)
3974 output = []
3974 output = []
3975 revs = []
3975 revs = []
3976
3976
3977 peer = None
3977 peer = None
3978 try:
3978 try:
3979 if source:
3979 if source:
3980 path = urlutil.get_unique_pull_path_obj(b'identify', ui, source)
3980 path = urlutil.get_unique_pull_path_obj(b'identify', ui, source)
3981 # only pass ui when no repo
3981 # only pass ui when no repo
3982 peer = hg.peer(repo or ui, opts, path)
3982 peer = hg.peer(repo or ui, opts, path)
3983 repo = peer.local()
3983 repo = peer.local()
3984 branches = (path.branch, [])
3984 branches = (path.branch, [])
3985 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3985 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3986
3986
3987 fm = ui.formatter(b'identify', opts)
3987 fm = ui.formatter(b'identify', opts)
3988 fm.startitem()
3988 fm.startitem()
3989
3989
3990 if not repo:
3990 if not repo:
3991 if num or branch or tags:
3991 if num or branch or tags:
3992 raise error.InputError(
3992 raise error.InputError(
3993 _(b"can't query remote revision number, branch, or tags")
3993 _(b"can't query remote revision number, branch, or tags")
3994 )
3994 )
3995 if not rev and revs:
3995 if not rev and revs:
3996 rev = revs[0]
3996 rev = revs[0]
3997 if not rev:
3997 if not rev:
3998 rev = b"tip"
3998 rev = b"tip"
3999
3999
4000 remoterev = peer.lookup(rev)
4000 remoterev = peer.lookup(rev)
4001 hexrev = fm.hexfunc(remoterev)
4001 hexrev = fm.hexfunc(remoterev)
4002 if default or id:
4002 if default or id:
4003 output = [hexrev]
4003 output = [hexrev]
4004 fm.data(id=hexrev)
4004 fm.data(id=hexrev)
4005
4005
4006 @util.cachefunc
4006 @util.cachefunc
4007 def getbms():
4007 def getbms():
4008 bms = []
4008 bms = []
4009
4009
4010 if b'bookmarks' in peer.listkeys(b'namespaces'):
4010 if b'bookmarks' in peer.listkeys(b'namespaces'):
4011 hexremoterev = hex(remoterev)
4011 hexremoterev = hex(remoterev)
4012 bms = [
4012 bms = [
4013 bm
4013 bm
4014 for bm, bmr in peer.listkeys(b'bookmarks').items()
4014 for bm, bmr in peer.listkeys(b'bookmarks').items()
4015 if bmr == hexremoterev
4015 if bmr == hexremoterev
4016 ]
4016 ]
4017
4017
4018 return sorted(bms)
4018 return sorted(bms)
4019
4019
4020 if fm.isplain():
4020 if fm.isplain():
4021 if bookmarks:
4021 if bookmarks:
4022 output.extend(getbms())
4022 output.extend(getbms())
4023 elif default and not ui.quiet:
4023 elif default and not ui.quiet:
4024 # multiple bookmarks for a single parent separated by '/'
4024 # multiple bookmarks for a single parent separated by '/'
4025 bm = b'/'.join(getbms())
4025 bm = b'/'.join(getbms())
4026 if bm:
4026 if bm:
4027 output.append(bm)
4027 output.append(bm)
4028 else:
4028 else:
4029 fm.data(node=hex(remoterev))
4029 fm.data(node=hex(remoterev))
4030 if bookmarks or b'bookmarks' in fm.datahint():
4030 if bookmarks or b'bookmarks' in fm.datahint():
4031 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
4031 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
4032 else:
4032 else:
4033 if rev:
4033 if rev:
4034 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
4034 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
4035 ctx = logcmdutil.revsingle(repo, rev, None)
4035 ctx = logcmdutil.revsingle(repo, rev, None)
4036
4036
4037 if ctx.rev() is None:
4037 if ctx.rev() is None:
4038 ctx = repo[None]
4038 ctx = repo[None]
4039 parents = ctx.parents()
4039 parents = ctx.parents()
4040 taglist = []
4040 taglist = []
4041 for p in parents:
4041 for p in parents:
4042 taglist.extend(p.tags())
4042 taglist.extend(p.tags())
4043
4043
4044 dirty = b""
4044 dirty = b""
4045 if ctx.dirty(missing=True, merge=False, branch=False):
4045 if ctx.dirty(missing=True, merge=False, branch=False):
4046 dirty = b'+'
4046 dirty = b'+'
4047 fm.data(dirty=dirty)
4047 fm.data(dirty=dirty)
4048
4048
4049 hexoutput = [fm.hexfunc(p.node()) for p in parents]
4049 hexoutput = [fm.hexfunc(p.node()) for p in parents]
4050 if default or id:
4050 if default or id:
4051 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
4051 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
4052 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
4052 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
4053
4053
4054 if num:
4054 if num:
4055 numoutput = [b"%d" % p.rev() for p in parents]
4055 numoutput = [b"%d" % p.rev() for p in parents]
4056 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
4056 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
4057
4057
4058 fm.data(
4058 fm.data(
4059 parents=fm.formatlist(
4059 parents=fm.formatlist(
4060 [fm.hexfunc(p.node()) for p in parents], name=b'node'
4060 [fm.hexfunc(p.node()) for p in parents], name=b'node'
4061 )
4061 )
4062 )
4062 )
4063 else:
4063 else:
4064 hexoutput = fm.hexfunc(ctx.node())
4064 hexoutput = fm.hexfunc(ctx.node())
4065 if default or id:
4065 if default or id:
4066 output = [hexoutput]
4066 output = [hexoutput]
4067 fm.data(id=hexoutput)
4067 fm.data(id=hexoutput)
4068
4068
4069 if num:
4069 if num:
4070 output.append(pycompat.bytestr(ctx.rev()))
4070 output.append(pycompat.bytestr(ctx.rev()))
4071 taglist = ctx.tags()
4071 taglist = ctx.tags()
4072
4072
4073 if default and not ui.quiet:
4073 if default and not ui.quiet:
4074 b = ctx.branch()
4074 b = ctx.branch()
4075 if b != b'default':
4075 if b != b'default':
4076 output.append(b"(%s)" % b)
4076 output.append(b"(%s)" % b)
4077
4077
4078 # multiple tags for a single parent separated by '/'
4078 # multiple tags for a single parent separated by '/'
4079 t = b'/'.join(taglist)
4079 t = b'/'.join(taglist)
4080 if t:
4080 if t:
4081 output.append(t)
4081 output.append(t)
4082
4082
4083 # multiple bookmarks for a single parent separated by '/'
4083 # multiple bookmarks for a single parent separated by '/'
4084 bm = b'/'.join(ctx.bookmarks())
4084 bm = b'/'.join(ctx.bookmarks())
4085 if bm:
4085 if bm:
4086 output.append(bm)
4086 output.append(bm)
4087 else:
4087 else:
4088 if branch:
4088 if branch:
4089 output.append(ctx.branch())
4089 output.append(ctx.branch())
4090
4090
4091 if tags:
4091 if tags:
4092 output.extend(taglist)
4092 output.extend(taglist)
4093
4093
4094 if bookmarks:
4094 if bookmarks:
4095 output.extend(ctx.bookmarks())
4095 output.extend(ctx.bookmarks())
4096
4096
4097 fm.data(node=ctx.hex())
4097 fm.data(node=ctx.hex())
4098 fm.data(branch=ctx.branch())
4098 fm.data(branch=ctx.branch())
4099 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4099 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4100 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4100 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4101 fm.context(ctx=ctx)
4101 fm.context(ctx=ctx)
4102
4102
4103 fm.plain(b"%s\n" % b' '.join(output))
4103 fm.plain(b"%s\n" % b' '.join(output))
4104 fm.end()
4104 fm.end()
4105 finally:
4105 finally:
4106 if peer:
4106 if peer:
4107 peer.close()
4107 peer.close()
4108
4108
4109
4109
4110 @command(
4110 @command(
4111 b'import|patch',
4111 b'import|patch',
4112 [
4112 [
4113 (
4113 (
4114 b'p',
4114 b'p',
4115 b'strip',
4115 b'strip',
4116 1,
4116 1,
4117 _(
4117 _(
4118 b'directory strip option for patch. This has the same '
4118 b'directory strip option for patch. This has the same '
4119 b'meaning as the corresponding patch option'
4119 b'meaning as the corresponding patch option'
4120 ),
4120 ),
4121 _(b'NUM'),
4121 _(b'NUM'),
4122 ),
4122 ),
4123 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4123 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4124 (b'', b'secret', None, _(b'use the secret phase for committing')),
4124 (b'', b'secret', None, _(b'use the secret phase for committing')),
4125 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4125 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4126 (
4126 (
4127 b'f',
4127 b'f',
4128 b'force',
4128 b'force',
4129 None,
4129 None,
4130 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4130 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4131 ),
4131 ),
4132 (
4132 (
4133 b'',
4133 b'',
4134 b'no-commit',
4134 b'no-commit',
4135 None,
4135 None,
4136 _(b"don't commit, just update the working directory"),
4136 _(b"don't commit, just update the working directory"),
4137 ),
4137 ),
4138 (
4138 (
4139 b'',
4139 b'',
4140 b'bypass',
4140 b'bypass',
4141 None,
4141 None,
4142 _(b"apply patch without touching the working directory"),
4142 _(b"apply patch without touching the working directory"),
4143 ),
4143 ),
4144 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4144 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4145 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4145 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4146 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4146 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4147 (
4147 (
4148 b'',
4148 b'',
4149 b'import-branch',
4149 b'import-branch',
4150 None,
4150 None,
4151 _(b'use any branch information in patch (implied by --exact)'),
4151 _(b'use any branch information in patch (implied by --exact)'),
4152 ),
4152 ),
4153 ]
4153 ]
4154 + commitopts
4154 + commitopts
4155 + commitopts2
4155 + commitopts2
4156 + similarityopts,
4156 + similarityopts,
4157 _(b'[OPTION]... PATCH...'),
4157 _(b'[OPTION]... PATCH...'),
4158 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4158 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4159 )
4159 )
4160 def import_(ui, repo, patch1=None, *patches, **opts):
4160 def import_(ui, repo, patch1=None, *patches, **opts):
4161 """import an ordered set of patches
4161 """import an ordered set of patches
4162
4162
4163 Import a list of patches and commit them individually (unless
4163 Import a list of patches and commit them individually (unless
4164 --no-commit is specified).
4164 --no-commit is specified).
4165
4165
4166 To read a patch from standard input (stdin), use "-" as the patch
4166 To read a patch from standard input (stdin), use "-" as the patch
4167 name. If a URL is specified, the patch will be downloaded from
4167 name. If a URL is specified, the patch will be downloaded from
4168 there.
4168 there.
4169
4169
4170 Import first applies changes to the working directory (unless
4170 Import first applies changes to the working directory (unless
4171 --bypass is specified), import will abort if there are outstanding
4171 --bypass is specified), import will abort if there are outstanding
4172 changes.
4172 changes.
4173
4173
4174 Use --bypass to apply and commit patches directly to the
4174 Use --bypass to apply and commit patches directly to the
4175 repository, without affecting the working directory. Without
4175 repository, without affecting the working directory. Without
4176 --exact, patches will be applied on top of the working directory
4176 --exact, patches will be applied on top of the working directory
4177 parent revision.
4177 parent revision.
4178
4178
4179 You can import a patch straight from a mail message. Even patches
4179 You can import a patch straight from a mail message. Even patches
4180 as attachments work (to use the body part, it must have type
4180 as attachments work (to use the body part, it must have type
4181 text/plain or text/x-patch). From and Subject headers of email
4181 text/plain or text/x-patch). From and Subject headers of email
4182 message are used as default committer and commit message. All
4182 message are used as default committer and commit message. All
4183 text/plain body parts before first diff are added to the commit
4183 text/plain body parts before first diff are added to the commit
4184 message.
4184 message.
4185
4185
4186 If the imported patch was generated by :hg:`export`, user and
4186 If the imported patch was generated by :hg:`export`, user and
4187 description from patch override values from message headers and
4187 description from patch override values from message headers and
4188 body. Values given on command line with -m/--message and -u/--user
4188 body. Values given on command line with -m/--message and -u/--user
4189 override these.
4189 override these.
4190
4190
4191 If --exact is specified, import will set the working directory to
4191 If --exact is specified, import will set the working directory to
4192 the parent of each patch before applying it, and will abort if the
4192 the parent of each patch before applying it, and will abort if the
4193 resulting changeset has a different ID than the one recorded in
4193 resulting changeset has a different ID than the one recorded in
4194 the patch. This will guard against various ways that portable
4194 the patch. This will guard against various ways that portable
4195 patch formats and mail systems might fail to transfer Mercurial
4195 patch formats and mail systems might fail to transfer Mercurial
4196 data or metadata. See :hg:`bundle` for lossless transmission.
4196 data or metadata. See :hg:`bundle` for lossless transmission.
4197
4197
4198 Use --partial to ensure a changeset will be created from the patch
4198 Use --partial to ensure a changeset will be created from the patch
4199 even if some hunks fail to apply. Hunks that fail to apply will be
4199 even if some hunks fail to apply. Hunks that fail to apply will be
4200 written to a <target-file>.rej file. Conflicts can then be resolved
4200 written to a <target-file>.rej file. Conflicts can then be resolved
4201 by hand before :hg:`commit --amend` is run to update the created
4201 by hand before :hg:`commit --amend` is run to update the created
4202 changeset. This flag exists to let people import patches that
4202 changeset. This flag exists to let people import patches that
4203 partially apply without losing the associated metadata (author,
4203 partially apply without losing the associated metadata (author,
4204 date, description, ...).
4204 date, description, ...).
4205
4205
4206 .. note::
4206 .. note::
4207
4207
4208 When no hunks apply cleanly, :hg:`import --partial` will create
4208 When no hunks apply cleanly, :hg:`import --partial` will create
4209 an empty changeset, importing only the patch metadata.
4209 an empty changeset, importing only the patch metadata.
4210
4210
4211 With -s/--similarity, hg will attempt to discover renames and
4211 With -s/--similarity, hg will attempt to discover renames and
4212 copies in the patch in the same way as :hg:`addremove`.
4212 copies in the patch in the same way as :hg:`addremove`.
4213
4213
4214 It is possible to use external patch programs to perform the patch
4214 It is possible to use external patch programs to perform the patch
4215 by setting the ``ui.patch`` configuration option. For the default
4215 by setting the ``ui.patch`` configuration option. For the default
4216 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4216 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4217 See :hg:`help config` for more information about configuration
4217 See :hg:`help config` for more information about configuration
4218 files and how to use these options.
4218 files and how to use these options.
4219
4219
4220 See :hg:`help dates` for a list of formats valid for -d/--date.
4220 See :hg:`help dates` for a list of formats valid for -d/--date.
4221
4221
4222 .. container:: verbose
4222 .. container:: verbose
4223
4223
4224 Examples:
4224 Examples:
4225
4225
4226 - import a traditional patch from a website and detect renames::
4226 - import a traditional patch from a website and detect renames::
4227
4227
4228 hg import -s 80 http://example.com/bugfix.patch
4228 hg import -s 80 http://example.com/bugfix.patch
4229
4229
4230 - import a changeset from an hgweb server::
4230 - import a changeset from an hgweb server::
4231
4231
4232 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4232 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4233
4233
4234 - import all the patches in an Unix-style mbox::
4234 - import all the patches in an Unix-style mbox::
4235
4235
4236 hg import incoming-patches.mbox
4236 hg import incoming-patches.mbox
4237
4237
4238 - import patches from stdin::
4238 - import patches from stdin::
4239
4239
4240 hg import -
4240 hg import -
4241
4241
4242 - attempt to exactly restore an exported changeset (not always
4242 - attempt to exactly restore an exported changeset (not always
4243 possible)::
4243 possible)::
4244
4244
4245 hg import --exact proposed-fix.patch
4245 hg import --exact proposed-fix.patch
4246
4246
4247 - use an external tool to apply a patch which is too fuzzy for
4247 - use an external tool to apply a patch which is too fuzzy for
4248 the default internal tool.
4248 the default internal tool.
4249
4249
4250 hg import --config ui.patch="patch --merge" fuzzy.patch
4250 hg import --config ui.patch="patch --merge" fuzzy.patch
4251
4251
4252 - change the default fuzzing from 2 to a less strict 7
4252 - change the default fuzzing from 2 to a less strict 7
4253
4253
4254 hg import --config ui.fuzz=7 fuzz.patch
4254 hg import --config ui.fuzz=7 fuzz.patch
4255
4255
4256 Returns 0 on success, 1 on partial success (see --partial).
4256 Returns 0 on success, 1 on partial success (see --partial).
4257 """
4257 """
4258
4258
4259 cmdutil.check_incompatible_arguments(
4259 cmdutil.check_incompatible_arguments(
4260 opts, 'no_commit', ['bypass', 'secret']
4260 opts, 'no_commit', ['bypass', 'secret']
4261 )
4261 )
4262 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4262 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4263
4263
4264 if not patch1:
4264 if not patch1:
4265 raise error.InputError(_(b'need at least one patch to import'))
4265 raise error.InputError(_(b'need at least one patch to import'))
4266
4266
4267 patches = (patch1,) + patches
4267 patches = (patch1,) + patches
4268
4268
4269 date = opts.get('date')
4269 date = opts.get('date')
4270 if date:
4270 if date:
4271 opts['date'] = dateutil.parsedate(date)
4271 opts['date'] = dateutil.parsedate(date)
4272
4272
4273 exact = opts.get('exact')
4273 exact = opts.get('exact')
4274 update = not opts.get('bypass')
4274 update = not opts.get('bypass')
4275 try:
4275 try:
4276 sim = float(opts.get('similarity') or 0)
4276 sim = float(opts.get('similarity') or 0)
4277 except ValueError:
4277 except ValueError:
4278 raise error.InputError(_(b'similarity must be a number'))
4278 raise error.InputError(_(b'similarity must be a number'))
4279 if sim < 0 or sim > 100:
4279 if sim < 0 or sim > 100:
4280 raise error.InputError(_(b'similarity must be between 0 and 100'))
4280 raise error.InputError(_(b'similarity must be between 0 and 100'))
4281 if sim and not update:
4281 if sim and not update:
4282 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4282 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4283
4283
4284 base = opts["base"]
4284 base = opts["base"]
4285 msgs = []
4285 msgs = []
4286 ret = 0
4286 ret = 0
4287
4287
4288 with repo.wlock():
4288 with repo.wlock():
4289 if update:
4289 if update:
4290 cmdutil.checkunfinished(repo)
4290 cmdutil.checkunfinished(repo)
4291 if exact or not opts.get('force'):
4291 if exact or not opts.get('force'):
4292 cmdutil.bailifchanged(repo)
4292 cmdutil.bailifchanged(repo)
4293
4293
4294 if not opts.get('no_commit'):
4294 if not opts.get('no_commit'):
4295 lock = repo.lock
4295 lock = repo.lock
4296 tr = lambda: repo.transaction(b'import')
4296 tr = lambda: repo.transaction(b'import')
4297 else:
4297 else:
4298 lock = util.nullcontextmanager
4298 lock = util.nullcontextmanager
4299 tr = util.nullcontextmanager
4299 tr = util.nullcontextmanager
4300 with lock(), tr():
4300 with lock(), tr():
4301 parents = repo[None].parents()
4301 parents = repo[None].parents()
4302 for patchurl in patches:
4302 for patchurl in patches:
4303 if patchurl == b'-':
4303 if patchurl == b'-':
4304 ui.status(_(b'applying patch from stdin\n'))
4304 ui.status(_(b'applying patch from stdin\n'))
4305 patchfile = ui.fin
4305 patchfile = ui.fin
4306 patchurl = b'stdin' # for error message
4306 patchurl = b'stdin' # for error message
4307 else:
4307 else:
4308 patchurl = os.path.join(base, patchurl)
4308 patchurl = os.path.join(base, patchurl)
4309 ui.status(_(b'applying %s\n') % patchurl)
4309 ui.status(_(b'applying %s\n') % patchurl)
4310 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4310 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4311
4311
4312 haspatch = False
4312 haspatch = False
4313 for hunk in patch.split(patchfile):
4313 for hunk in patch.split(patchfile):
4314 with patch.extract(ui, hunk) as patchdata:
4314 with patch.extract(ui, hunk) as patchdata:
4315 msg, node, rej = cmdutil.tryimportone(
4315 msg, node, rej = cmdutil.tryimportone(
4316 ui,
4316 ui,
4317 repo,
4317 repo,
4318 patchdata,
4318 patchdata,
4319 parents,
4319 parents,
4320 pycompat.byteskwargs(opts),
4320 pycompat.byteskwargs(opts),
4321 msgs,
4321 msgs,
4322 hg.clean,
4322 hg.clean,
4323 )
4323 )
4324 if msg:
4324 if msg:
4325 haspatch = True
4325 haspatch = True
4326 ui.note(msg + b'\n')
4326 ui.note(msg + b'\n')
4327 if update or exact:
4327 if update or exact:
4328 parents = repo[None].parents()
4328 parents = repo[None].parents()
4329 else:
4329 else:
4330 parents = [repo[node]]
4330 parents = [repo[node]]
4331 if rej:
4331 if rej:
4332 ui.write_err(_(b"patch applied partially\n"))
4332 ui.write_err(_(b"patch applied partially\n"))
4333 ui.write_err(
4333 ui.write_err(
4334 _(
4334 _(
4335 b"(fix the .rej files and run "
4335 b"(fix the .rej files and run "
4336 b"`hg commit --amend`)\n"
4336 b"`hg commit --amend`)\n"
4337 )
4337 )
4338 )
4338 )
4339 ret = 1
4339 ret = 1
4340 break
4340 break
4341
4341
4342 if not haspatch:
4342 if not haspatch:
4343 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4343 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4344
4344
4345 if msgs:
4345 if msgs:
4346 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4346 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4347 return ret
4347 return ret
4348
4348
4349
4349
4350 @command(
4350 @command(
4351 b'incoming|in',
4351 b'incoming|in',
4352 [
4352 [
4353 (
4353 (
4354 b'f',
4354 b'f',
4355 b'force',
4355 b'force',
4356 None,
4356 None,
4357 _(b'run even if remote repository is unrelated'),
4357 _(b'run even if remote repository is unrelated'),
4358 ),
4358 ),
4359 (b'n', b'newest-first', None, _(b'show newest record first')),
4359 (b'n', b'newest-first', None, _(b'show newest record first')),
4360 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4360 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4361 (
4361 (
4362 b'r',
4362 b'r',
4363 b'rev',
4363 b'rev',
4364 [],
4364 [],
4365 _(b'a remote changeset intended to be added'),
4365 _(b'a remote changeset intended to be added'),
4366 _(b'REV'),
4366 _(b'REV'),
4367 ),
4367 ),
4368 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4368 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4369 (
4369 (
4370 b'b',
4370 b'b',
4371 b'branch',
4371 b'branch',
4372 [],
4372 [],
4373 _(b'a specific branch you would like to pull'),
4373 _(b'a specific branch you would like to pull'),
4374 _(b'BRANCH'),
4374 _(b'BRANCH'),
4375 ),
4375 ),
4376 ]
4376 ]
4377 + logopts
4377 + logopts
4378 + remoteopts
4378 + remoteopts
4379 + subrepoopts,
4379 + subrepoopts,
4380 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4380 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4381 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4381 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4382 )
4382 )
4383 def incoming(ui, repo, source=b"default", **opts):
4383 def incoming(ui, repo, source=b"default", **opts):
4384 """show new changesets found in source
4384 """show new changesets found in source
4385
4385
4386 Show new changesets found in the specified path/URL or the default
4386 Show new changesets found in the specified path/URL or the default
4387 pull location. These are the changesets that would have been pulled
4387 pull location. These are the changesets that would have been pulled
4388 by :hg:`pull` at the time you issued this command.
4388 by :hg:`pull` at the time you issued this command.
4389
4389
4390 See pull for valid source format details.
4390 See pull for valid source format details.
4391
4391
4392 .. container:: verbose
4392 .. container:: verbose
4393
4393
4394 With -B/--bookmarks, the result of bookmark comparison between
4394 With -B/--bookmarks, the result of bookmark comparison between
4395 local and remote repositories is displayed. With -v/--verbose,
4395 local and remote repositories is displayed. With -v/--verbose,
4396 status is also displayed for each bookmark like below::
4396 status is also displayed for each bookmark like below::
4397
4397
4398 BM1 01234567890a added
4398 BM1 01234567890a added
4399 BM2 1234567890ab advanced
4399 BM2 1234567890ab advanced
4400 BM3 234567890abc diverged
4400 BM3 234567890abc diverged
4401 BM4 34567890abcd changed
4401 BM4 34567890abcd changed
4402
4402
4403 The action taken locally when pulling depends on the
4403 The action taken locally when pulling depends on the
4404 status of each bookmark:
4404 status of each bookmark:
4405
4405
4406 :``added``: pull will create it
4406 :``added``: pull will create it
4407 :``advanced``: pull will update it
4407 :``advanced``: pull will update it
4408 :``diverged``: pull will create a divergent bookmark
4408 :``diverged``: pull will create a divergent bookmark
4409 :``changed``: result depends on remote changesets
4409 :``changed``: result depends on remote changesets
4410
4410
4411 From the point of view of pulling behavior, bookmark
4411 From the point of view of pulling behavior, bookmark
4412 existing only in the remote repository are treated as ``added``,
4412 existing only in the remote repository are treated as ``added``,
4413 even if it is in fact locally deleted.
4413 even if it is in fact locally deleted.
4414
4414
4415 .. container:: verbose
4415 .. container:: verbose
4416
4416
4417 For remote repository, using --bundle avoids downloading the
4417 For remote repository, using --bundle avoids downloading the
4418 changesets twice if the incoming is followed by a pull.
4418 changesets twice if the incoming is followed by a pull.
4419
4419
4420 Examples:
4420 Examples:
4421
4421
4422 - show incoming changes with patches and full description::
4422 - show incoming changes with patches and full description::
4423
4423
4424 hg incoming -vp
4424 hg incoming -vp
4425
4425
4426 - show incoming changes excluding merges, store a bundle::
4426 - show incoming changes excluding merges, store a bundle::
4427
4427
4428 hg in -vpM --bundle incoming.hg
4428 hg in -vpM --bundle incoming.hg
4429 hg pull incoming.hg
4429 hg pull incoming.hg
4430
4430
4431 - briefly list changes inside a bundle::
4431 - briefly list changes inside a bundle::
4432
4432
4433 hg in changes.hg -T "{desc|firstline}\\n"
4433 hg in changes.hg -T "{desc|firstline}\\n"
4434
4434
4435 Returns 0 if there are incoming changes, 1 otherwise.
4435 Returns 0 if there are incoming changes, 1 otherwise.
4436 """
4436 """
4437 opts = pycompat.byteskwargs(opts)
4437 opts = pycompat.byteskwargs(opts)
4438 if opts.get(b'graph'):
4438 if opts.get(b'graph'):
4439 logcmdutil.checkunsupportedgraphflags([], opts)
4439 logcmdutil.checkunsupportedgraphflags([], opts)
4440
4440
4441 def display(other, chlist, displayer):
4441 def display(other, chlist, displayer):
4442 revdag = logcmdutil.graphrevs(other, chlist, opts)
4442 revdag = logcmdutil.graphrevs(other, chlist, opts)
4443 logcmdutil.displaygraph(
4443 logcmdutil.displaygraph(
4444 ui, repo, revdag, displayer, graphmod.asciiedges
4444 ui, repo, revdag, displayer, graphmod.asciiedges
4445 )
4445 )
4446
4446
4447 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4447 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4448 return 0
4448 return 0
4449
4449
4450 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4450 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4451
4451
4452 if opts.get(b'bookmarks'):
4452 if opts.get(b'bookmarks'):
4453 srcs = urlutil.get_pull_paths(repo, ui, [source])
4453 srcs = urlutil.get_pull_paths(repo, ui, [source])
4454 for path in srcs:
4454 for path in srcs:
4455 # XXX the "branches" options are not used. Should it be used?
4455 # XXX the "branches" options are not used. Should it be used?
4456 other = hg.peer(repo, opts, path)
4456 other = hg.peer(repo, opts, path)
4457 try:
4457 try:
4458 if b'bookmarks' not in other.listkeys(b'namespaces'):
4458 if b'bookmarks' not in other.listkeys(b'namespaces'):
4459 ui.warn(_(b"remote doesn't support bookmarks\n"))
4459 ui.warn(_(b"remote doesn't support bookmarks\n"))
4460 return 0
4460 return 0
4461 ui.pager(b'incoming')
4461 ui.pager(b'incoming')
4462 ui.status(
4462 ui.status(
4463 _(b'comparing with %s\n') % urlutil.hidepassword(path.loc)
4463 _(b'comparing with %s\n') % urlutil.hidepassword(path.loc)
4464 )
4464 )
4465 return bookmarks.incoming(
4465 return bookmarks.incoming(
4466 ui, repo, other, mode=path.bookmarks_mode
4466 ui, repo, other, mode=path.bookmarks_mode
4467 )
4467 )
4468 finally:
4468 finally:
4469 other.close()
4469 other.close()
4470
4470
4471 return hg.incoming(ui, repo, source, opts)
4471 return hg.incoming(ui, repo, source, opts)
4472
4472
4473
4473
4474 @command(
4474 @command(
4475 b'init',
4475 b'init',
4476 remoteopts,
4476 remoteopts,
4477 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4477 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4478 helpcategory=command.CATEGORY_REPO_CREATION,
4478 helpcategory=command.CATEGORY_REPO_CREATION,
4479 helpbasic=True,
4479 helpbasic=True,
4480 norepo=True,
4480 norepo=True,
4481 )
4481 )
4482 def init(ui, dest=b".", **opts):
4482 def init(ui, dest=b".", **opts):
4483 """create a new repository in the given directory
4483 """create a new repository in the given directory
4484
4484
4485 Initialize a new repository in the given directory. If the given
4485 Initialize a new repository in the given directory. If the given
4486 directory does not exist, it will be created.
4486 directory does not exist, it will be created.
4487
4487
4488 If no directory is given, the current directory is used.
4488 If no directory is given, the current directory is used.
4489
4489
4490 It is possible to specify an ``ssh://`` URL as the destination.
4490 It is possible to specify an ``ssh://`` URL as the destination.
4491 See :hg:`help urls` for more information.
4491 See :hg:`help urls` for more information.
4492
4492
4493 Returns 0 on success.
4493 Returns 0 on success.
4494 """
4494 """
4495 opts = pycompat.byteskwargs(opts)
4495 opts = pycompat.byteskwargs(opts)
4496 path = urlutil.get_clone_path_obj(ui, dest)
4496 path = urlutil.get_clone_path_obj(ui, dest)
4497 peer = hg.peer(ui, opts, path, create=True)
4497 peer = hg.peer(ui, opts, path, create=True)
4498 peer.close()
4498 peer.close()
4499
4499
4500
4500
4501 @command(
4501 @command(
4502 b'locate',
4502 b'locate',
4503 [
4503 [
4504 (
4504 (
4505 b'r',
4505 b'r',
4506 b'rev',
4506 b'rev',
4507 b'',
4507 b'',
4508 _(b'search the repository as it is in REV'),
4508 _(b'search the repository as it is in REV'),
4509 _(b'REV'),
4509 _(b'REV'),
4510 ),
4510 ),
4511 (
4511 (
4512 b'0',
4512 b'0',
4513 b'print0',
4513 b'print0',
4514 None,
4514 None,
4515 _(b'end filenames with NUL, for use with xargs'),
4515 _(b'end filenames with NUL, for use with xargs'),
4516 ),
4516 ),
4517 (
4517 (
4518 b'f',
4518 b'f',
4519 b'fullpath',
4519 b'fullpath',
4520 None,
4520 None,
4521 _(b'print complete paths from the filesystem root'),
4521 _(b'print complete paths from the filesystem root'),
4522 ),
4522 ),
4523 ]
4523 ]
4524 + walkopts,
4524 + walkopts,
4525 _(b'[OPTION]... [PATTERN]...'),
4525 _(b'[OPTION]... [PATTERN]...'),
4526 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4526 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4527 )
4527 )
4528 def locate(ui, repo, *pats, **opts):
4528 def locate(ui, repo, *pats, **opts):
4529 """locate files matching specific patterns (DEPRECATED)
4529 """locate files matching specific patterns (DEPRECATED)
4530
4530
4531 Print files under Mercurial control in the working directory whose
4531 Print files under Mercurial control in the working directory whose
4532 names match the given patterns.
4532 names match the given patterns.
4533
4533
4534 By default, this command searches all directories in the working
4534 By default, this command searches all directories in the working
4535 directory. To search just the current directory and its
4535 directory. To search just the current directory and its
4536 subdirectories, use "--include .".
4536 subdirectories, use "--include .".
4537
4537
4538 If no patterns are given to match, this command prints the names
4538 If no patterns are given to match, this command prints the names
4539 of all files under Mercurial control in the working directory.
4539 of all files under Mercurial control in the working directory.
4540
4540
4541 If you want to feed the output of this command into the "xargs"
4541 If you want to feed the output of this command into the "xargs"
4542 command, use the -0 option to both this command and "xargs". This
4542 command, use the -0 option to both this command and "xargs". This
4543 will avoid the problem of "xargs" treating single filenames that
4543 will avoid the problem of "xargs" treating single filenames that
4544 contain whitespace as multiple filenames.
4544 contain whitespace as multiple filenames.
4545
4545
4546 See :hg:`help files` for a more versatile command.
4546 See :hg:`help files` for a more versatile command.
4547
4547
4548 Returns 0 if a match is found, 1 otherwise.
4548 Returns 0 if a match is found, 1 otherwise.
4549 """
4549 """
4550 if opts.get('print0'):
4550 if opts.get('print0'):
4551 end = b'\0'
4551 end = b'\0'
4552 else:
4552 else:
4553 end = b'\n'
4553 end = b'\n'
4554 ctx = logcmdutil.revsingle(repo, opts.get('rev'), None)
4554 ctx = logcmdutil.revsingle(repo, opts.get('rev'), None)
4555
4555
4556 ret = 1
4556 ret = 1
4557 m = scmutil.match(
4557 m = scmutil.match(
4558 ctx,
4558 ctx,
4559 pats,
4559 pats,
4560 pycompat.byteskwargs(opts),
4560 pycompat.byteskwargs(opts),
4561 default=b'relglob',
4561 default=b'relglob',
4562 badfn=lambda x, y: False,
4562 badfn=lambda x, y: False,
4563 )
4563 )
4564
4564
4565 ui.pager(b'locate')
4565 ui.pager(b'locate')
4566 if ctx.rev() is None:
4566 if ctx.rev() is None:
4567 # When run on the working copy, "locate" includes removed files, so
4567 # When run on the working copy, "locate" includes removed files, so
4568 # we get the list of files from the dirstate.
4568 # we get the list of files from the dirstate.
4569 filesgen = sorted(repo.dirstate.matches(m))
4569 filesgen = sorted(repo.dirstate.matches(m))
4570 else:
4570 else:
4571 filesgen = ctx.matches(m)
4571 filesgen = ctx.matches(m)
4572 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4572 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4573 for abs in filesgen:
4573 for abs in filesgen:
4574 if opts.get('fullpath'):
4574 if opts.get('fullpath'):
4575 ui.write(repo.wjoin(abs), end)
4575 ui.write(repo.wjoin(abs), end)
4576 else:
4576 else:
4577 ui.write(uipathfn(abs), end)
4577 ui.write(uipathfn(abs), end)
4578 ret = 0
4578 ret = 0
4579
4579
4580 return ret
4580 return ret
4581
4581
4582
4582
4583 @command(
4583 @command(
4584 b'log|history',
4584 b'log|history',
4585 [
4585 [
4586 (
4586 (
4587 b'f',
4587 b'f',
4588 b'follow',
4588 b'follow',
4589 None,
4589 None,
4590 _(
4590 _(
4591 b'follow changeset history, or file history across copies and renames'
4591 b'follow changeset history, or file history across copies and renames'
4592 ),
4592 ),
4593 ),
4593 ),
4594 (
4594 (
4595 b'',
4595 b'',
4596 b'follow-first',
4596 b'follow-first',
4597 None,
4597 None,
4598 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4598 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4599 ),
4599 ),
4600 (
4600 (
4601 b'd',
4601 b'd',
4602 b'date',
4602 b'date',
4603 b'',
4603 b'',
4604 _(b'show revisions matching date spec'),
4604 _(b'show revisions matching date spec'),
4605 _(b'DATE'),
4605 _(b'DATE'),
4606 ),
4606 ),
4607 (b'C', b'copies', None, _(b'show copied files')),
4607 (b'C', b'copies', None, _(b'show copied files')),
4608 (
4608 (
4609 b'k',
4609 b'k',
4610 b'keyword',
4610 b'keyword',
4611 [],
4611 [],
4612 _(b'do case-insensitive search for a given text'),
4612 _(b'do case-insensitive search for a given text'),
4613 _(b'TEXT'),
4613 _(b'TEXT'),
4614 ),
4614 ),
4615 (
4615 (
4616 b'r',
4616 b'r',
4617 b'rev',
4617 b'rev',
4618 [],
4618 [],
4619 _(b'revisions to select or follow from'),
4619 _(b'revisions to select or follow from'),
4620 _(b'REV'),
4620 _(b'REV'),
4621 ),
4621 ),
4622 (
4622 (
4623 b'L',
4623 b'L',
4624 b'line-range',
4624 b'line-range',
4625 [],
4625 [],
4626 _(b'follow line range of specified file (EXPERIMENTAL)'),
4626 _(b'follow line range of specified file (EXPERIMENTAL)'),
4627 _(b'FILE,RANGE'),
4627 _(b'FILE,RANGE'),
4628 ),
4628 ),
4629 (
4629 (
4630 b'',
4630 b'',
4631 b'removed',
4631 b'removed',
4632 None,
4632 None,
4633 _(b'include revisions where files were removed'),
4633 _(b'include revisions where files were removed'),
4634 ),
4634 ),
4635 (
4635 (
4636 b'm',
4636 b'm',
4637 b'only-merges',
4637 b'only-merges',
4638 None,
4638 None,
4639 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4639 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4640 ),
4640 ),
4641 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4641 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4642 (
4642 (
4643 b'',
4643 b'',
4644 b'only-branch',
4644 b'only-branch',
4645 [],
4645 [],
4646 _(
4646 _(
4647 b'show only changesets within the given named branch (DEPRECATED)'
4647 b'show only changesets within the given named branch (DEPRECATED)'
4648 ),
4648 ),
4649 _(b'BRANCH'),
4649 _(b'BRANCH'),
4650 ),
4650 ),
4651 (
4651 (
4652 b'b',
4652 b'b',
4653 b'branch',
4653 b'branch',
4654 [],
4654 [],
4655 _(b'show changesets within the given named branch'),
4655 _(b'show changesets within the given named branch'),
4656 _(b'BRANCH'),
4656 _(b'BRANCH'),
4657 ),
4657 ),
4658 (
4658 (
4659 b'B',
4659 b'B',
4660 b'bookmark',
4660 b'bookmark',
4661 [],
4661 [],
4662 _(b"show changesets within the given bookmark"),
4662 _(b"show changesets within the given bookmark"),
4663 _(b'BOOKMARK'),
4663 _(b'BOOKMARK'),
4664 ),
4664 ),
4665 (
4665 (
4666 b'P',
4666 b'P',
4667 b'prune',
4667 b'prune',
4668 [],
4668 [],
4669 _(b'do not display revision or any of its ancestors'),
4669 _(b'do not display revision or any of its ancestors'),
4670 _(b'REV'),
4670 _(b'REV'),
4671 ),
4671 ),
4672 ]
4672 ]
4673 + logopts
4673 + logopts
4674 + walkopts,
4674 + walkopts,
4675 _(b'[OPTION]... [FILE]'),
4675 _(b'[OPTION]... [FILE]'),
4676 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4676 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4677 helpbasic=True,
4677 helpbasic=True,
4678 inferrepo=True,
4678 inferrepo=True,
4679 intents={INTENT_READONLY},
4679 intents={INTENT_READONLY},
4680 )
4680 )
4681 def log(ui, repo, *pats, **opts):
4681 def log(ui, repo, *pats, **opts):
4682 """show revision history of entire repository or files
4682 """show revision history of entire repository or files
4683
4683
4684 Print the revision history of the specified files or the entire
4684 Print the revision history of the specified files or the entire
4685 project.
4685 project.
4686
4686
4687 If no revision range is specified, the default is ``tip:0`` unless
4687 If no revision range is specified, the default is ``tip:0`` unless
4688 --follow is set.
4688 --follow is set.
4689
4689
4690 File history is shown without following rename or copy history of
4690 File history is shown without following rename or copy history of
4691 files. Use -f/--follow with a filename to follow history across
4691 files. Use -f/--follow with a filename to follow history across
4692 renames and copies. --follow without a filename will only show
4692 renames and copies. --follow without a filename will only show
4693 ancestors of the starting revisions. The starting revisions can be
4693 ancestors of the starting revisions. The starting revisions can be
4694 specified by -r/--rev, which default to the working directory parent.
4694 specified by -r/--rev, which default to the working directory parent.
4695
4695
4696 By default this command prints revision number and changeset id,
4696 By default this command prints revision number and changeset id,
4697 tags, non-trivial parents, user, date and time, and a summary for
4697 tags, non-trivial parents, user, date and time, and a summary for
4698 each commit. When the -v/--verbose switch is used, the list of
4698 each commit. When the -v/--verbose switch is used, the list of
4699 changed files and full commit message are shown.
4699 changed files and full commit message are shown.
4700
4700
4701 With --graph the revisions are shown as an ASCII art DAG with the most
4701 With --graph the revisions are shown as an ASCII art DAG with the most
4702 recent changeset at the top.
4702 recent changeset at the top.
4703 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4703 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4704 involved in an unresolved merge conflict, '_' closes a branch,
4704 involved in an unresolved merge conflict, '_' closes a branch,
4705 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4705 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4706 changeset from the lines below is a parent of the 'o' merge on the same
4706 changeset from the lines below is a parent of the 'o' merge on the same
4707 line.
4707 line.
4708 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4708 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4709 of a '|' indicates one or more revisions in a path are omitted.
4709 of a '|' indicates one or more revisions in a path are omitted.
4710
4710
4711 .. container:: verbose
4711 .. container:: verbose
4712
4712
4713 Use -L/--line-range FILE,M:N options to follow the history of lines
4713 Use -L/--line-range FILE,M:N options to follow the history of lines
4714 from M to N in FILE. With -p/--patch only diff hunks affecting
4714 from M to N in FILE. With -p/--patch only diff hunks affecting
4715 specified line range will be shown. This option requires --follow;
4715 specified line range will be shown. This option requires --follow;
4716 it can be specified multiple times. Currently, this option is not
4716 it can be specified multiple times. Currently, this option is not
4717 compatible with --graph. This option is experimental.
4717 compatible with --graph. This option is experimental.
4718
4718
4719 .. note::
4719 .. note::
4720
4720
4721 :hg:`log --patch` may generate unexpected diff output for merge
4721 :hg:`log --patch` may generate unexpected diff output for merge
4722 changesets, as it will only compare the merge changeset against
4722 changesets, as it will only compare the merge changeset against
4723 its first parent. Also, only files different from BOTH parents
4723 its first parent. Also, only files different from BOTH parents
4724 will appear in files:.
4724 will appear in files:.
4725
4725
4726 .. note::
4726 .. note::
4727
4727
4728 For performance reasons, :hg:`log FILE` may omit duplicate changes
4728 For performance reasons, :hg:`log FILE` may omit duplicate changes
4729 made on branches and will not show removals or mode changes. To
4729 made on branches and will not show removals or mode changes. To
4730 see all such changes, use the --removed switch.
4730 see all such changes, use the --removed switch.
4731
4731
4732 .. container:: verbose
4732 .. container:: verbose
4733
4733
4734 .. note::
4734 .. note::
4735
4735
4736 The history resulting from -L/--line-range options depends on diff
4736 The history resulting from -L/--line-range options depends on diff
4737 options; for instance if white-spaces are ignored, respective changes
4737 options; for instance if white-spaces are ignored, respective changes
4738 with only white-spaces in specified line range will not be listed.
4738 with only white-spaces in specified line range will not be listed.
4739
4739
4740 .. container:: verbose
4740 .. container:: verbose
4741
4741
4742 Some examples:
4742 Some examples:
4743
4743
4744 - changesets with full descriptions and file lists::
4744 - changesets with full descriptions and file lists::
4745
4745
4746 hg log -v
4746 hg log -v
4747
4747
4748 - changesets ancestral to the working directory::
4748 - changesets ancestral to the working directory::
4749
4749
4750 hg log -f
4750 hg log -f
4751
4751
4752 - last 10 commits on the current branch::
4752 - last 10 commits on the current branch::
4753
4753
4754 hg log -l 10 -b .
4754 hg log -l 10 -b .
4755
4755
4756 - changesets showing all modifications of a file, including removals::
4756 - changesets showing all modifications of a file, including removals::
4757
4757
4758 hg log --removed file.c
4758 hg log --removed file.c
4759
4759
4760 - all changesets that touch a directory, with diffs, excluding merges::
4760 - all changesets that touch a directory, with diffs, excluding merges::
4761
4761
4762 hg log -Mp lib/
4762 hg log -Mp lib/
4763
4763
4764 - all revision numbers that match a keyword::
4764 - all revision numbers that match a keyword::
4765
4765
4766 hg log -k bug --template "{rev}\\n"
4766 hg log -k bug --template "{rev}\\n"
4767
4767
4768 - the full hash identifier of the working directory parent::
4768 - the full hash identifier of the working directory parent::
4769
4769
4770 hg log -r . --template "{node}\\n"
4770 hg log -r . --template "{node}\\n"
4771
4771
4772 - list available log templates::
4772 - list available log templates::
4773
4773
4774 hg log -T list
4774 hg log -T list
4775
4775
4776 - check if a given changeset is included in a tagged release::
4776 - check if a given changeset is included in a tagged release::
4777
4777
4778 hg log -r "a21ccf and ancestor(1.9)"
4778 hg log -r "a21ccf and ancestor(1.9)"
4779
4779
4780 - find all changesets by some user in a date range::
4780 - find all changesets by some user in a date range::
4781
4781
4782 hg log -k alice -d "may 2008 to jul 2008"
4782 hg log -k alice -d "may 2008 to jul 2008"
4783
4783
4784 - summary of all changesets after the last tag::
4784 - summary of all changesets after the last tag::
4785
4785
4786 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4786 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4787
4787
4788 - changesets touching lines 13 to 23 for file.c::
4788 - changesets touching lines 13 to 23 for file.c::
4789
4789
4790 hg log -L file.c,13:23
4790 hg log -L file.c,13:23
4791
4791
4792 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4792 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4793 main.c with patch::
4793 main.c with patch::
4794
4794
4795 hg log -L file.c,13:23 -L main.c,2:6 -p
4795 hg log -L file.c,13:23 -L main.c,2:6 -p
4796
4796
4797 See :hg:`help dates` for a list of formats valid for -d/--date.
4797 See :hg:`help dates` for a list of formats valid for -d/--date.
4798
4798
4799 See :hg:`help revisions` for more about specifying and ordering
4799 See :hg:`help revisions` for more about specifying and ordering
4800 revisions.
4800 revisions.
4801
4801
4802 See :hg:`help templates` for more about pre-packaged styles and
4802 See :hg:`help templates` for more about pre-packaged styles and
4803 specifying custom templates. The default template used by the log
4803 specifying custom templates. The default template used by the log
4804 command can be customized via the ``command-templates.log`` configuration
4804 command can be customized via the ``command-templates.log`` configuration
4805 setting.
4805 setting.
4806
4806
4807 Returns 0 on success.
4807 Returns 0 on success.
4808
4808
4809 """
4809 """
4810 opts = pycompat.byteskwargs(opts)
4810 opts = pycompat.byteskwargs(opts)
4811 linerange = opts.get(b'line_range')
4811 linerange = opts.get(b'line_range')
4812
4812
4813 if linerange and not opts.get(b'follow'):
4813 if linerange and not opts.get(b'follow'):
4814 raise error.InputError(_(b'--line-range requires --follow'))
4814 raise error.InputError(_(b'--line-range requires --follow'))
4815
4815
4816 if linerange and pats:
4816 if linerange and pats:
4817 # TODO: take pats as patterns with no line-range filter
4817 # TODO: take pats as patterns with no line-range filter
4818 raise error.InputError(
4818 raise error.InputError(
4819 _(b'FILE arguments are not compatible with --line-range option')
4819 _(b'FILE arguments are not compatible with --line-range option')
4820 )
4820 )
4821
4821
4822 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4822 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4823 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4823 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4824 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4824 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4825 if linerange:
4825 if linerange:
4826 # TODO: should follow file history from logcmdutil._initialrevs(),
4826 # TODO: should follow file history from logcmdutil._initialrevs(),
4827 # then filter the result by logcmdutil._makerevset() and --limit
4827 # then filter the result by logcmdutil._makerevset() and --limit
4828 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4828 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4829
4829
4830 getcopies = None
4830 getcopies = None
4831 if opts.get(b'copies'):
4831 if opts.get(b'copies'):
4832 endrev = None
4832 endrev = None
4833 if revs:
4833 if revs:
4834 endrev = revs.max() + 1
4834 endrev = revs.max() + 1
4835 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4835 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4836
4836
4837 ui.pager(b'log')
4837 ui.pager(b'log')
4838 displayer = logcmdutil.changesetdisplayer(
4838 displayer = logcmdutil.changesetdisplayer(
4839 ui, repo, opts, differ, buffered=True
4839 ui, repo, opts, differ, buffered=True
4840 )
4840 )
4841 if opts.get(b'graph'):
4841 if opts.get(b'graph'):
4842 displayfn = logcmdutil.displaygraphrevs
4842 displayfn = logcmdutil.displaygraphrevs
4843 else:
4843 else:
4844 displayfn = logcmdutil.displayrevs
4844 displayfn = logcmdutil.displayrevs
4845 displayfn(ui, repo, revs, displayer, getcopies)
4845 displayfn(ui, repo, revs, displayer, getcopies)
4846
4846
4847
4847
4848 @command(
4848 @command(
4849 b'manifest',
4849 b'manifest',
4850 [
4850 [
4851 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4851 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4852 (b'', b'all', False, _(b"list files from all revisions")),
4852 (b'', b'all', False, _(b"list files from all revisions")),
4853 ]
4853 ]
4854 + formatteropts,
4854 + formatteropts,
4855 _(b'[-r REV]'),
4855 _(b'[-r REV]'),
4856 helpcategory=command.CATEGORY_MAINTENANCE,
4856 helpcategory=command.CATEGORY_MAINTENANCE,
4857 intents={INTENT_READONLY},
4857 intents={INTENT_READONLY},
4858 )
4858 )
4859 def manifest(ui, repo, node=None, rev=None, **opts):
4859 def manifest(ui, repo, node=None, rev=None, **opts):
4860 """output the current or given revision of the project manifest
4860 """output the current or given revision of the project manifest
4861
4861
4862 Print a list of version controlled files for the given revision.
4862 Print a list of version controlled files for the given revision.
4863 If no revision is given, the first parent of the working directory
4863 If no revision is given, the first parent of the working directory
4864 is used, or the null revision if no revision is checked out.
4864 is used, or the null revision if no revision is checked out.
4865
4865
4866 With -v, print file permissions, symlink and executable bits.
4866 With -v, print file permissions, symlink and executable bits.
4867 With --debug, print file revision hashes.
4867 With --debug, print file revision hashes.
4868
4868
4869 If option --all is specified, the list of all files from all revisions
4869 If option --all is specified, the list of all files from all revisions
4870 is printed. This includes deleted and renamed files.
4870 is printed. This includes deleted and renamed files.
4871
4871
4872 Returns 0 on success.
4872 Returns 0 on success.
4873 """
4873 """
4874 fm = ui.formatter(b'manifest', pycompat.byteskwargs(opts))
4874 fm = ui.formatter(b'manifest', pycompat.byteskwargs(opts))
4875
4875
4876 if opts.get('all'):
4876 if opts.get('all'):
4877 if rev or node:
4877 if rev or node:
4878 raise error.InputError(_(b"can't specify a revision with --all"))
4878 raise error.InputError(_(b"can't specify a revision with --all"))
4879
4879
4880 res = set()
4880 res = set()
4881 for rev in repo:
4881 for rev in repo:
4882 ctx = repo[rev]
4882 ctx = repo[rev]
4883 res |= set(ctx.files())
4883 res |= set(ctx.files())
4884
4884
4885 ui.pager(b'manifest')
4885 ui.pager(b'manifest')
4886 for f in sorted(res):
4886 for f in sorted(res):
4887 fm.startitem()
4887 fm.startitem()
4888 fm.write(b"path", b'%s\n', f)
4888 fm.write(b"path", b'%s\n', f)
4889 fm.end()
4889 fm.end()
4890 return
4890 return
4891
4891
4892 if rev and node:
4892 if rev and node:
4893 raise error.InputError(_(b"please specify just one revision"))
4893 raise error.InputError(_(b"please specify just one revision"))
4894
4894
4895 if not node:
4895 if not node:
4896 node = rev
4896 node = rev
4897
4897
4898 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4898 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4899 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4899 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4900 if node:
4900 if node:
4901 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4901 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4902 ctx = logcmdutil.revsingle(repo, node)
4902 ctx = logcmdutil.revsingle(repo, node)
4903 mf = ctx.manifest()
4903 mf = ctx.manifest()
4904 ui.pager(b'manifest')
4904 ui.pager(b'manifest')
4905 for f in ctx:
4905 for f in ctx:
4906 fm.startitem()
4906 fm.startitem()
4907 fm.context(ctx=ctx)
4907 fm.context(ctx=ctx)
4908 fl = ctx[f].flags()
4908 fl = ctx[f].flags()
4909 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4909 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4910 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4910 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4911 fm.write(b'path', b'%s\n', f)
4911 fm.write(b'path', b'%s\n', f)
4912 fm.end()
4912 fm.end()
4913
4913
4914
4914
4915 @command(
4915 @command(
4916 b'merge',
4916 b'merge',
4917 [
4917 [
4918 (
4918 (
4919 b'f',
4919 b'f',
4920 b'force',
4920 b'force',
4921 None,
4921 None,
4922 _(b'force a merge including outstanding changes (DEPRECATED)'),
4922 _(b'force a merge including outstanding changes (DEPRECATED)'),
4923 ),
4923 ),
4924 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4924 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4925 (
4925 (
4926 b'P',
4926 b'P',
4927 b'preview',
4927 b'preview',
4928 None,
4928 None,
4929 _(b'review revisions to merge (no merge is performed)'),
4929 _(b'review revisions to merge (no merge is performed)'),
4930 ),
4930 ),
4931 (b'', b'abort', None, _(b'abort the ongoing merge')),
4931 (b'', b'abort', None, _(b'abort the ongoing merge')),
4932 ]
4932 ]
4933 + mergetoolopts,
4933 + mergetoolopts,
4934 _(b'[-P] [[-r] REV]'),
4934 _(b'[-P] [[-r] REV]'),
4935 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4935 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4936 helpbasic=True,
4936 helpbasic=True,
4937 )
4937 )
4938 def merge(ui, repo, node=None, **opts):
4938 def merge(ui, repo, node=None, **opts):
4939 """merge another revision into working directory
4939 """merge another revision into working directory
4940
4940
4941 The current working directory is updated with all changes made in
4941 The current working directory is updated with all changes made in
4942 the requested revision since the last common predecessor revision.
4942 the requested revision since the last common predecessor revision.
4943
4943
4944 Files that changed between either parent are marked as changed for
4944 Files that changed between either parent are marked as changed for
4945 the next commit and a commit must be performed before any further
4945 the next commit and a commit must be performed before any further
4946 updates to the repository are allowed. The next commit will have
4946 updates to the repository are allowed. The next commit will have
4947 two parents.
4947 two parents.
4948
4948
4949 ``--tool`` can be used to specify the merge tool used for file
4949 ``--tool`` can be used to specify the merge tool used for file
4950 merges. It overrides the HGMERGE environment variable and your
4950 merges. It overrides the HGMERGE environment variable and your
4951 configuration files. See :hg:`help merge-tools` for options.
4951 configuration files. See :hg:`help merge-tools` for options.
4952
4952
4953 If no revision is specified, the working directory's parent is a
4953 If no revision is specified, the working directory's parent is a
4954 head revision, and the current branch contains exactly one other
4954 head revision, and the current branch contains exactly one other
4955 head, the other head is merged with by default. Otherwise, an
4955 head, the other head is merged with by default. Otherwise, an
4956 explicit revision with which to merge must be provided.
4956 explicit revision with which to merge must be provided.
4957
4957
4958 See :hg:`help resolve` for information on handling file conflicts.
4958 See :hg:`help resolve` for information on handling file conflicts.
4959
4959
4960 To undo an uncommitted merge, use :hg:`merge --abort` which
4960 To undo an uncommitted merge, use :hg:`merge --abort` which
4961 will check out a clean copy of the original merge parent, losing
4961 will check out a clean copy of the original merge parent, losing
4962 all changes.
4962 all changes.
4963
4963
4964 Returns 0 on success, 1 if there are unresolved files.
4964 Returns 0 on success, 1 if there are unresolved files.
4965 """
4965 """
4966
4966
4967 abort = opts.get('abort')
4967 abort = opts.get('abort')
4968 if abort and repo.dirstate.p2() == repo.nullid:
4968 if abort and repo.dirstate.p2() == repo.nullid:
4969 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4969 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4970 cmdutil.check_incompatible_arguments(opts, 'abort', ['rev', 'preview'])
4970 cmdutil.check_incompatible_arguments(opts, 'abort', ['rev', 'preview'])
4971 if abort:
4971 if abort:
4972 state = cmdutil.getunfinishedstate(repo)
4972 state = cmdutil.getunfinishedstate(repo)
4973 if state and state._opname != b'merge':
4973 if state and state._opname != b'merge':
4974 raise error.StateError(
4974 raise error.StateError(
4975 _(b'cannot abort merge with %s in progress') % (state._opname),
4975 _(b'cannot abort merge with %s in progress') % (state._opname),
4976 hint=state.hint(),
4976 hint=state.hint(),
4977 )
4977 )
4978 if node:
4978 if node:
4979 raise error.InputError(_(b"cannot specify a node with --abort"))
4979 raise error.InputError(_(b"cannot specify a node with --abort"))
4980 return hg.abortmerge(repo.ui, repo)
4980 return hg.abortmerge(repo.ui, repo)
4981
4981
4982 if opts.get('rev') and node:
4982 if opts.get('rev') and node:
4983 raise error.InputError(_(b"please specify just one revision"))
4983 raise error.InputError(_(b"please specify just one revision"))
4984 if not node:
4984 if not node:
4985 node = opts.get('rev')
4985 node = opts.get('rev')
4986
4986
4987 if node:
4987 if node:
4988 ctx = logcmdutil.revsingle(repo, node)
4988 ctx = logcmdutil.revsingle(repo, node)
4989 else:
4989 else:
4990 if ui.configbool(b'commands', b'merge.require-rev'):
4990 if ui.configbool(b'commands', b'merge.require-rev'):
4991 raise error.InputError(
4991 raise error.InputError(
4992 _(
4992 _(
4993 b'configuration requires specifying revision to merge '
4993 b'configuration requires specifying revision to merge '
4994 b'with'
4994 b'with'
4995 )
4995 )
4996 )
4996 )
4997 ctx = repo[destutil.destmerge(repo)]
4997 ctx = repo[destutil.destmerge(repo)]
4998
4998
4999 if ctx.node() is None:
4999 if ctx.node() is None:
5000 raise error.InputError(
5000 raise error.InputError(
5001 _(b'merging with the working copy has no effect')
5001 _(b'merging with the working copy has no effect')
5002 )
5002 )
5003
5003
5004 if opts.get('preview'):
5004 if opts.get('preview'):
5005 # find nodes that are ancestors of p2 but not of p1
5005 # find nodes that are ancestors of p2 but not of p1
5006 p1 = repo[b'.'].node()
5006 p1 = repo[b'.'].node()
5007 p2 = ctx.node()
5007 p2 = ctx.node()
5008 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5008 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5009
5009
5010 displayer = logcmdutil.changesetdisplayer(
5010 displayer = logcmdutil.changesetdisplayer(
5011 ui, repo, pycompat.byteskwargs(opts)
5011 ui, repo, pycompat.byteskwargs(opts)
5012 )
5012 )
5013 for node in nodes:
5013 for node in nodes:
5014 displayer.show(repo[node])
5014 displayer.show(repo[node])
5015 displayer.close()
5015 displayer.close()
5016 return 0
5016 return 0
5017
5017
5018 # ui.forcemerge is an internal variable, do not document
5018 # ui.forcemerge is an internal variable, do not document
5019 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
5019 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
5020 with ui.configoverride(overrides, b'merge'):
5020 with ui.configoverride(overrides, b'merge'):
5021 force = opts.get('force')
5021 force = opts.get('force')
5022 labels = [b'working copy', b'merge rev', b'common ancestor']
5022 labels = [b'working copy', b'merge rev', b'common ancestor']
5023 return hg.merge(ctx, force=force, labels=labels)
5023 return hg.merge(ctx, force=force, labels=labels)
5024
5024
5025
5025
5026 statemod.addunfinished(
5026 statemod.addunfinished(
5027 b'merge',
5027 b'merge',
5028 fname=None,
5028 fname=None,
5029 clearable=True,
5029 clearable=True,
5030 allowcommit=True,
5030 allowcommit=True,
5031 cmdmsg=_(b'outstanding uncommitted merge'),
5031 cmdmsg=_(b'outstanding uncommitted merge'),
5032 abortfunc=hg.abortmerge,
5032 abortfunc=hg.abortmerge,
5033 statushint=_(
5033 statushint=_(
5034 b'To continue: hg commit\nTo abort: hg merge --abort'
5034 b'To continue: hg commit\nTo abort: hg merge --abort'
5035 ),
5035 ),
5036 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
5036 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
5037 )
5037 )
5038
5038
5039
5039
5040 @command(
5040 @command(
5041 b'outgoing|out',
5041 b'outgoing|out',
5042 [
5042 [
5043 (
5043 (
5044 b'f',
5044 b'f',
5045 b'force',
5045 b'force',
5046 None,
5046 None,
5047 _(b'run even when the destination is unrelated'),
5047 _(b'run even when the destination is unrelated'),
5048 ),
5048 ),
5049 (
5049 (
5050 b'r',
5050 b'r',
5051 b'rev',
5051 b'rev',
5052 [],
5052 [],
5053 _(b'a changeset intended to be included in the destination'),
5053 _(b'a changeset intended to be included in the destination'),
5054 _(b'REV'),
5054 _(b'REV'),
5055 ),
5055 ),
5056 (b'n', b'newest-first', None, _(b'show newest record first')),
5056 (b'n', b'newest-first', None, _(b'show newest record first')),
5057 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
5057 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
5058 (
5058 (
5059 b'b',
5059 b'b',
5060 b'branch',
5060 b'branch',
5061 [],
5061 [],
5062 _(b'a specific branch you would like to push'),
5062 _(b'a specific branch you would like to push'),
5063 _(b'BRANCH'),
5063 _(b'BRANCH'),
5064 ),
5064 ),
5065 ]
5065 ]
5066 + logopts
5066 + logopts
5067 + remoteopts
5067 + remoteopts
5068 + subrepoopts,
5068 + subrepoopts,
5069 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]...'),
5069 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]...'),
5070 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5070 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5071 )
5071 )
5072 def outgoing(ui, repo, *dests, **opts):
5072 def outgoing(ui, repo, *dests, **opts):
5073 """show changesets not found in the destination
5073 """show changesets not found in the destination
5074
5074
5075 Show changesets not found in the specified destination repository
5075 Show changesets not found in the specified destination repository
5076 or the default push location. These are the changesets that would
5076 or the default push location. These are the changesets that would
5077 be pushed if a push was requested.
5077 be pushed if a push was requested.
5078
5078
5079 See pull for details of valid destination formats.
5079 See pull for details of valid destination formats.
5080
5080
5081 .. container:: verbose
5081 .. container:: verbose
5082
5082
5083 With -B/--bookmarks, the result of bookmark comparison between
5083 With -B/--bookmarks, the result of bookmark comparison between
5084 local and remote repositories is displayed. With -v/--verbose,
5084 local and remote repositories is displayed. With -v/--verbose,
5085 status is also displayed for each bookmark like below::
5085 status is also displayed for each bookmark like below::
5086
5086
5087 BM1 01234567890a added
5087 BM1 01234567890a added
5088 BM2 deleted
5088 BM2 deleted
5089 BM3 234567890abc advanced
5089 BM3 234567890abc advanced
5090 BM4 34567890abcd diverged
5090 BM4 34567890abcd diverged
5091 BM5 4567890abcde changed
5091 BM5 4567890abcde changed
5092
5092
5093 The action taken when pushing depends on the
5093 The action taken when pushing depends on the
5094 status of each bookmark:
5094 status of each bookmark:
5095
5095
5096 :``added``: push with ``-B`` will create it
5096 :``added``: push with ``-B`` will create it
5097 :``deleted``: push with ``-B`` will delete it
5097 :``deleted``: push with ``-B`` will delete it
5098 :``advanced``: push will update it
5098 :``advanced``: push will update it
5099 :``diverged``: push with ``-B`` will update it
5099 :``diverged``: push with ``-B`` will update it
5100 :``changed``: push with ``-B`` will update it
5100 :``changed``: push with ``-B`` will update it
5101
5101
5102 From the point of view of pushing behavior, bookmarks
5102 From the point of view of pushing behavior, bookmarks
5103 existing only in the remote repository are treated as
5103 existing only in the remote repository are treated as
5104 ``deleted``, even if it is in fact added remotely.
5104 ``deleted``, even if it is in fact added remotely.
5105
5105
5106 Returns 0 if there are outgoing changes, 1 otherwise.
5106 Returns 0 if there are outgoing changes, 1 otherwise.
5107 """
5107 """
5108 opts = pycompat.byteskwargs(opts)
5108 opts = pycompat.byteskwargs(opts)
5109 if opts.get(b'bookmarks'):
5109 if opts.get(b'bookmarks'):
5110 for path in urlutil.get_push_paths(repo, ui, dests):
5110 for path in urlutil.get_push_paths(repo, ui, dests):
5111 other = hg.peer(repo, opts, path)
5111 other = hg.peer(repo, opts, path)
5112 try:
5112 try:
5113 if b'bookmarks' not in other.listkeys(b'namespaces'):
5113 if b'bookmarks' not in other.listkeys(b'namespaces'):
5114 ui.warn(_(b"remote doesn't support bookmarks\n"))
5114 ui.warn(_(b"remote doesn't support bookmarks\n"))
5115 return 0
5115 return 0
5116 ui.status(
5116 ui.status(
5117 _(b'comparing with %s\n') % urlutil.hidepassword(path.loc)
5117 _(b'comparing with %s\n') % urlutil.hidepassword(path.loc)
5118 )
5118 )
5119 ui.pager(b'outgoing')
5119 ui.pager(b'outgoing')
5120 return bookmarks.outgoing(ui, repo, other)
5120 return bookmarks.outgoing(ui, repo, other)
5121 finally:
5121 finally:
5122 other.close()
5122 other.close()
5123
5123
5124 return hg.outgoing(ui, repo, dests, opts)
5124 return hg.outgoing(ui, repo, dests, opts)
5125
5125
5126
5126
5127 @command(
5127 @command(
5128 b'parents',
5128 b'parents',
5129 [
5129 [
5130 (
5130 (
5131 b'r',
5131 b'r',
5132 b'rev',
5132 b'rev',
5133 b'',
5133 b'',
5134 _(b'show parents of the specified revision'),
5134 _(b'show parents of the specified revision'),
5135 _(b'REV'),
5135 _(b'REV'),
5136 ),
5136 ),
5137 ]
5137 ]
5138 + templateopts,
5138 + templateopts,
5139 _(b'[-r REV] [FILE]'),
5139 _(b'[-r REV] [FILE]'),
5140 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5140 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5141 inferrepo=True,
5141 inferrepo=True,
5142 )
5142 )
5143 def parents(ui, repo, file_=None, **opts):
5143 def parents(ui, repo, file_=None, **opts):
5144 """show the parents of the working directory or revision (DEPRECATED)
5144 """show the parents of the working directory or revision (DEPRECATED)
5145
5145
5146 Print the working directory's parent revisions. If a revision is
5146 Print the working directory's parent revisions. If a revision is
5147 given via -r/--rev, the parent of that revision will be printed.
5147 given via -r/--rev, the parent of that revision will be printed.
5148 If a file argument is given, the revision in which the file was
5148 If a file argument is given, the revision in which the file was
5149 last changed (before the working directory revision or the
5149 last changed (before the working directory revision or the
5150 argument to --rev if given) is printed.
5150 argument to --rev if given) is printed.
5151
5151
5152 This command is equivalent to::
5152 This command is equivalent to::
5153
5153
5154 hg log -r "p1()+p2()" or
5154 hg log -r "p1()+p2()" or
5155 hg log -r "p1(REV)+p2(REV)" or
5155 hg log -r "p1(REV)+p2(REV)" or
5156 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5156 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5157 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5157 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5158
5158
5159 See :hg:`summary` and :hg:`help revsets` for related information.
5159 See :hg:`summary` and :hg:`help revsets` for related information.
5160
5160
5161 Returns 0 on success.
5161 Returns 0 on success.
5162 """
5162 """
5163
5163
5164 opts = pycompat.byteskwargs(opts)
5164 opts = pycompat.byteskwargs(opts)
5165 rev = opts.get(b'rev')
5165 rev = opts.get(b'rev')
5166 if rev:
5166 if rev:
5167 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5167 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5168 ctx = logcmdutil.revsingle(repo, rev, None)
5168 ctx = logcmdutil.revsingle(repo, rev, None)
5169
5169
5170 if file_:
5170 if file_:
5171 m = scmutil.match(ctx, (file_,), opts)
5171 m = scmutil.match(ctx, (file_,), opts)
5172 if m.anypats() or len(m.files()) != 1:
5172 if m.anypats() or len(m.files()) != 1:
5173 raise error.InputError(_(b'can only specify an explicit filename'))
5173 raise error.InputError(_(b'can only specify an explicit filename'))
5174 file_ = m.files()[0]
5174 file_ = m.files()[0]
5175 filenodes = []
5175 filenodes = []
5176 for cp in ctx.parents():
5176 for cp in ctx.parents():
5177 if not cp:
5177 if not cp:
5178 continue
5178 continue
5179 try:
5179 try:
5180 filenodes.append(cp.filenode(file_))
5180 filenodes.append(cp.filenode(file_))
5181 except error.LookupError:
5181 except error.LookupError:
5182 pass
5182 pass
5183 if not filenodes:
5183 if not filenodes:
5184 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5184 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5185 p = []
5185 p = []
5186 for fn in filenodes:
5186 for fn in filenodes:
5187 fctx = repo.filectx(file_, fileid=fn)
5187 fctx = repo.filectx(file_, fileid=fn)
5188 p.append(fctx.node())
5188 p.append(fctx.node())
5189 else:
5189 else:
5190 p = [cp.node() for cp in ctx.parents()]
5190 p = [cp.node() for cp in ctx.parents()]
5191
5191
5192 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5192 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5193 for n in p:
5193 for n in p:
5194 if n != repo.nullid:
5194 if n != repo.nullid:
5195 displayer.show(repo[n])
5195 displayer.show(repo[n])
5196 displayer.close()
5196 displayer.close()
5197
5197
5198
5198
5199 @command(
5199 @command(
5200 b'paths',
5200 b'paths',
5201 formatteropts,
5201 formatteropts,
5202 _(b'[NAME]'),
5202 _(b'[NAME]'),
5203 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5203 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5204 optionalrepo=True,
5204 optionalrepo=True,
5205 intents={INTENT_READONLY},
5205 intents={INTENT_READONLY},
5206 )
5206 )
5207 def paths(ui, repo, search=None, **opts):
5207 def paths(ui, repo, search=None, **opts):
5208 """show aliases for remote repositories
5208 """show aliases for remote repositories
5209
5209
5210 Show definition of symbolic path name NAME. If no name is given,
5210 Show definition of symbolic path name NAME. If no name is given,
5211 show definition of all available names.
5211 show definition of all available names.
5212
5212
5213 Option -q/--quiet suppresses all output when searching for NAME
5213 Option -q/--quiet suppresses all output when searching for NAME
5214 and shows only the path names when listing all definitions.
5214 and shows only the path names when listing all definitions.
5215
5215
5216 Path names are defined in the [paths] section of your
5216 Path names are defined in the [paths] section of your
5217 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5217 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5218 repository, ``.hg/hgrc`` is used, too.
5218 repository, ``.hg/hgrc`` is used, too.
5219
5219
5220 The path names ``default`` and ``default-push`` have a special
5220 The path names ``default`` and ``default-push`` have a special
5221 meaning. When performing a push or pull operation, they are used
5221 meaning. When performing a push or pull operation, they are used
5222 as fallbacks if no location is specified on the command-line.
5222 as fallbacks if no location is specified on the command-line.
5223 When ``default-push`` is set, it will be used for push and
5223 When ``default-push`` is set, it will be used for push and
5224 ``default`` will be used for pull; otherwise ``default`` is used
5224 ``default`` will be used for pull; otherwise ``default`` is used
5225 as the fallback for both. When cloning a repository, the clone
5225 as the fallback for both. When cloning a repository, the clone
5226 source is written as ``default`` in ``.hg/hgrc``.
5226 source is written as ``default`` in ``.hg/hgrc``.
5227
5227
5228 .. note::
5228 .. note::
5229
5229
5230 ``default`` and ``default-push`` apply to all inbound (e.g.
5230 ``default`` and ``default-push`` apply to all inbound (e.g.
5231 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5231 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5232 and :hg:`bundle`) operations.
5232 and :hg:`bundle`) operations.
5233
5233
5234 See :hg:`help urls` for more information.
5234 See :hg:`help urls` for more information.
5235
5235
5236 .. container:: verbose
5236 .. container:: verbose
5237
5237
5238 Template:
5238 Template:
5239
5239
5240 The following keywords are supported. See also :hg:`help templates`.
5240 The following keywords are supported. See also :hg:`help templates`.
5241
5241
5242 :name: String. Symbolic name of the path alias.
5242 :name: String. Symbolic name of the path alias.
5243 :pushurl: String. URL for push operations.
5243 :pushurl: String. URL for push operations.
5244 :url: String. URL or directory path for the other operations.
5244 :url: String. URL or directory path for the other operations.
5245
5245
5246 Returns 0 on success.
5246 Returns 0 on success.
5247 """
5247 """
5248
5248
5249 pathitems = urlutil.list_paths(ui, search)
5249 pathitems = urlutil.list_paths(ui, search)
5250 ui.pager(b'paths')
5250 ui.pager(b'paths')
5251
5251
5252 fm = ui.formatter(b'paths', pycompat.byteskwargs(opts))
5252 fm = ui.formatter(b'paths', pycompat.byteskwargs(opts))
5253 if fm.isplain():
5253 if fm.isplain():
5254 hidepassword = urlutil.hidepassword
5254 hidepassword = urlutil.hidepassword
5255 else:
5255 else:
5256 hidepassword = bytes
5256 hidepassword = bytes
5257 if ui.quiet:
5257 if ui.quiet:
5258 namefmt = b'%s\n'
5258 namefmt = b'%s\n'
5259 else:
5259 else:
5260 namefmt = b'%s = '
5260 namefmt = b'%s = '
5261 showsubopts = not search and not ui.quiet
5261 showsubopts = not search and not ui.quiet
5262
5262
5263 for name, path in pathitems:
5263 for name, path in pathitems:
5264 fm.startitem()
5264 fm.startitem()
5265 fm.condwrite(not search, b'name', namefmt, name)
5265 fm.condwrite(not search, b'name', namefmt, name)
5266 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5266 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5267 for subopt, value in sorted(path.suboptions.items()):
5267 for subopt, value in sorted(path.suboptions.items()):
5268 assert subopt not in (b'name', b'url')
5268 assert subopt not in (b'name', b'url')
5269 if showsubopts:
5269 if showsubopts:
5270 fm.plain(b'%s:%s = ' % (name, subopt))
5270 fm.plain(b'%s:%s = ' % (name, subopt))
5271 display = urlutil.path_suboptions_display[subopt]
5271 display = urlutil.path_suboptions_display[subopt]
5272 value = display(value)
5272 value = display(value)
5273 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5273 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5274
5274
5275 fm.end()
5275 fm.end()
5276
5276
5277 if search and not pathitems:
5277 if search and not pathitems:
5278 if not ui.quiet:
5278 if not ui.quiet:
5279 ui.warn(_(b"not found!\n"))
5279 ui.warn(_(b"not found!\n"))
5280 return 1
5280 return 1
5281 else:
5281 else:
5282 return 0
5282 return 0
5283
5283
5284
5284
5285 @command(
5285 @command(
5286 b'phase',
5286 b'phase',
5287 [
5287 [
5288 (b'p', b'public', False, _(b'set changeset phase to public')),
5288 (b'p', b'public', False, _(b'set changeset phase to public')),
5289 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5289 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5290 (b's', b'secret', False, _(b'set changeset phase to secret')),
5290 (b's', b'secret', False, _(b'set changeset phase to secret')),
5291 (b'f', b'force', False, _(b'allow to move boundary backward')),
5291 (b'f', b'force', False, _(b'allow to move boundary backward')),
5292 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5292 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5293 ],
5293 ],
5294 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5294 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5295 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5295 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5296 )
5296 )
5297 def phase(ui, repo, *revs, **opts):
5297 def phase(ui, repo, *revs, **opts):
5298 """set or show the current phase name
5298 """set or show the current phase name
5299
5299
5300 With no argument, show the phase name of the current revision(s).
5300 With no argument, show the phase name of the current revision(s).
5301
5301
5302 With one of -p/--public, -d/--draft or -s/--secret, change the
5302 With one of -p/--public, -d/--draft or -s/--secret, change the
5303 phase value of the specified revisions.
5303 phase value of the specified revisions.
5304
5304
5305 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5305 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5306 lower phase to a higher phase. Phases are ordered as follows::
5306 lower phase to a higher phase. Phases are ordered as follows::
5307
5307
5308 public < draft < secret
5308 public < draft < secret
5309
5309
5310 Returns 0 on success, 1 if some phases could not be changed.
5310 Returns 0 on success, 1 if some phases could not be changed.
5311
5311
5312 (For more information about the phases concept, see :hg:`help phases`.)
5312 (For more information about the phases concept, see :hg:`help phases`.)
5313 """
5313 """
5314 opts = pycompat.byteskwargs(opts)
5314 opts = pycompat.byteskwargs(opts)
5315 # search for a unique phase argument
5315 # search for a unique phase argument
5316 targetphase = None
5316 targetphase = None
5317 for idx, name in enumerate(phases.cmdphasenames):
5317 for idx, name in enumerate(phases.cmdphasenames):
5318 if opts[name]:
5318 if opts[name]:
5319 if targetphase is not None:
5319 if targetphase is not None:
5320 raise error.InputError(_(b'only one phase can be specified'))
5320 raise error.InputError(_(b'only one phase can be specified'))
5321 targetphase = idx
5321 targetphase = idx
5322
5322
5323 # look for specified revision
5323 # look for specified revision
5324 revs = list(revs)
5324 revs = list(revs)
5325 revs.extend(opts[b'rev'])
5325 revs.extend(opts[b'rev'])
5326 if revs:
5326 if revs:
5327 revs = logcmdutil.revrange(repo, revs)
5327 revs = logcmdutil.revrange(repo, revs)
5328 else:
5328 else:
5329 # display both parents as the second parent phase can influence
5329 # display both parents as the second parent phase can influence
5330 # the phase of a merge commit
5330 # the phase of a merge commit
5331 revs = [c.rev() for c in repo[None].parents()]
5331 revs = [c.rev() for c in repo[None].parents()]
5332
5332
5333 ret = 0
5333 ret = 0
5334 if targetphase is None:
5334 if targetphase is None:
5335 # display
5335 # display
5336 for r in revs:
5336 for r in revs:
5337 ctx = repo[r]
5337 ctx = repo[r]
5338 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5338 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5339 else:
5339 else:
5340 with repo.lock(), repo.transaction(b"phase") as tr:
5340 with repo.lock(), repo.transaction(b"phase") as tr:
5341 # set phase
5341 # set phase
5342 if not revs:
5342 if not revs:
5343 raise error.InputError(_(b'empty revision set'))
5343 raise error.InputError(_(b'empty revision set'))
5344 nodes = [repo[r].node() for r in revs]
5344 nodes = [repo[r].node() for r in revs]
5345 # moving revision from public to draft may hide them
5345 # moving revision from public to draft may hide them
5346 # We have to check result on an unfiltered repository
5346 # We have to check result on an unfiltered repository
5347 unfi = repo.unfiltered()
5347 unfi = repo.unfiltered()
5348 getphase = unfi._phasecache.phase
5348 getphase = unfi._phasecache.phase
5349 olddata = [getphase(unfi, r) for r in unfi]
5349 olddata = [getphase(unfi, r) for r in unfi]
5350 phases.advanceboundary(repo, tr, targetphase, nodes)
5350 phases.advanceboundary(repo, tr, targetphase, nodes)
5351 if opts[b'force']:
5351 if opts[b'force']:
5352 phases.retractboundary(repo, tr, targetphase, nodes)
5352 phases.retractboundary(repo, tr, targetphase, nodes)
5353 getphase = unfi._phasecache.phase
5353 getphase = unfi._phasecache.phase
5354 newdata = [getphase(unfi, r) for r in unfi]
5354 newdata = [getphase(unfi, r) for r in unfi]
5355 changes = sum(newdata[r] != olddata[r] for r in unfi)
5355 changes = sum(newdata[r] != olddata[r] for r in unfi)
5356 cl = unfi.changelog
5356 cl = unfi.changelog
5357 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5357 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5358 if rejected:
5358 if rejected:
5359 ui.warn(
5359 ui.warn(
5360 _(
5360 _(
5361 b'cannot move %i changesets to a higher '
5361 b'cannot move %i changesets to a higher '
5362 b'phase, use --force\n'
5362 b'phase, use --force\n'
5363 )
5363 )
5364 % len(rejected)
5364 % len(rejected)
5365 )
5365 )
5366 ret = 1
5366 ret = 1
5367 if changes:
5367 if changes:
5368 msg = _(b'phase changed for %i changesets\n') % changes
5368 msg = _(b'phase changed for %i changesets\n') % changes
5369 if ret:
5369 if ret:
5370 ui.status(msg)
5370 ui.status(msg)
5371 else:
5371 else:
5372 ui.note(msg)
5372 ui.note(msg)
5373 else:
5373 else:
5374 ui.warn(_(b'no phases changed\n'))
5374 ui.warn(_(b'no phases changed\n'))
5375 return ret
5375 return ret
5376
5376
5377
5377
5378 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5378 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5379 """Run after a changegroup has been added via pull/unbundle
5379 """Run after a changegroup has been added via pull/unbundle
5380
5380
5381 This takes arguments below:
5381 This takes arguments below:
5382
5382
5383 :modheads: change of heads by pull/unbundle
5383 :modheads: change of heads by pull/unbundle
5384 :optupdate: updating working directory is needed or not
5384 :optupdate: updating working directory is needed or not
5385 :checkout: update destination revision (or None to default destination)
5385 :checkout: update destination revision (or None to default destination)
5386 :brev: a name, which might be a bookmark to be activated after updating
5386 :brev: a name, which might be a bookmark to be activated after updating
5387
5387
5388 return True if update raise any conflict, False otherwise.
5388 return True if update raise any conflict, False otherwise.
5389 """
5389 """
5390 if modheads == 0:
5390 if modheads == 0:
5391 return False
5391 return False
5392 if optupdate:
5392 if optupdate:
5393 try:
5393 try:
5394 return hg.updatetotally(ui, repo, checkout, brev)
5394 return hg.updatetotally(ui, repo, checkout, brev)
5395 except error.UpdateAbort as inst:
5395 except error.UpdateAbort as inst:
5396 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5396 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5397 hint = inst.hint
5397 hint = inst.hint
5398 raise error.UpdateAbort(msg, hint=hint)
5398 raise error.UpdateAbort(msg, hint=hint)
5399 if modheads is not None and modheads > 1:
5399 if modheads is not None and modheads > 1:
5400 currentbranchheads = len(repo.branchheads())
5400 currentbranchheads = len(repo.branchheads())
5401 if currentbranchheads == modheads:
5401 if currentbranchheads == modheads:
5402 ui.status(
5402 ui.status(
5403 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5403 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5404 )
5404 )
5405 elif currentbranchheads > 1:
5405 elif currentbranchheads > 1:
5406 ui.status(
5406 ui.status(
5407 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5407 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5408 )
5408 )
5409 else:
5409 else:
5410 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5410 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5411 elif not ui.configbool(b'commands', b'update.requiredest'):
5411 elif not ui.configbool(b'commands', b'update.requiredest'):
5412 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5412 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5413 return False
5413 return False
5414
5414
5415
5415
5416 @command(
5416 @command(
5417 b'pull',
5417 b'pull',
5418 [
5418 [
5419 (
5419 (
5420 b'u',
5420 b'u',
5421 b'update',
5421 b'update',
5422 None,
5422 None,
5423 _(b'update to new branch head if new descendants were pulled'),
5423 _(b'update to new branch head if new descendants were pulled'),
5424 ),
5424 ),
5425 (
5425 (
5426 b'f',
5426 b'f',
5427 b'force',
5427 b'force',
5428 None,
5428 None,
5429 _(b'run even when remote repository is unrelated'),
5429 _(b'run even when remote repository is unrelated'),
5430 ),
5430 ),
5431 (
5431 (
5432 b'',
5432 b'',
5433 b'confirm',
5433 b'confirm',
5434 None,
5434 None,
5435 _(b'confirm pull before applying changes'),
5435 _(b'confirm pull before applying changes'),
5436 ),
5436 ),
5437 (
5437 (
5438 b'r',
5438 b'r',
5439 b'rev',
5439 b'rev',
5440 [],
5440 [],
5441 _(b'a remote changeset intended to be added'),
5441 _(b'a remote changeset intended to be added'),
5442 _(b'REV'),
5442 _(b'REV'),
5443 ),
5443 ),
5444 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5444 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5445 (
5445 (
5446 b'b',
5446 b'b',
5447 b'branch',
5447 b'branch',
5448 [],
5448 [],
5449 _(b'a specific branch you would like to pull'),
5449 _(b'a specific branch you would like to pull'),
5450 _(b'BRANCH'),
5450 _(b'BRANCH'),
5451 ),
5451 ),
5452 (
5452 (
5453 b'',
5453 b'',
5454 b'remote-hidden',
5454 b'remote-hidden',
5455 False,
5455 False,
5456 _(b"include changesets hidden on the remote (EXPERIMENTAL)"),
5456 _(b"include changesets hidden on the remote (EXPERIMENTAL)"),
5457 ),
5457 ),
5458 ]
5458 ]
5459 + remoteopts,
5459 + remoteopts,
5460 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]...'),
5460 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]...'),
5461 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5461 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5462 helpbasic=True,
5462 helpbasic=True,
5463 )
5463 )
5464 def pull(ui, repo, *sources, **opts):
5464 def pull(ui, repo, *sources, **opts):
5465 """pull changes from the specified source
5465 """pull changes from the specified source
5466
5466
5467 Pull changes from a remote repository to a local one.
5467 Pull changes from a remote repository to a local one.
5468
5468
5469 This finds all changes from the repository at the specified path
5469 This finds all changes from the repository at the specified path
5470 or URL and adds them to a local repository (the current one unless
5470 or URL and adds them to a local repository (the current one unless
5471 -R is specified). By default, this does not update the copy of the
5471 -R is specified). By default, this does not update the copy of the
5472 project in the working directory.
5472 project in the working directory.
5473
5473
5474 When cloning from servers that support it, Mercurial may fetch
5474 When cloning from servers that support it, Mercurial may fetch
5475 pre-generated data. When this is done, hooks operating on incoming
5475 pre-generated data. When this is done, hooks operating on incoming
5476 changesets and changegroups may fire more than once, once for each
5476 changesets and changegroups may fire more than once, once for each
5477 pre-generated bundle and as well as for any additional remaining
5477 pre-generated bundle and as well as for any additional remaining
5478 data. See :hg:`help -e clonebundles` for more.
5478 data. See :hg:`help -e clonebundles` for more.
5479
5479
5480 Use :hg:`incoming` if you want to see what would have been added
5480 Use :hg:`incoming` if you want to see what would have been added
5481 by a pull at the time you issued this command. If you then decide
5481 by a pull at the time you issued this command. If you then decide
5482 to add those changes to the repository, you should use :hg:`pull
5482 to add those changes to the repository, you should use :hg:`pull
5483 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5483 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5484
5484
5485 If SOURCE is omitted, the 'default' path will be used.
5485 If SOURCE is omitted, the 'default' path will be used.
5486 See :hg:`help urls` for more information.
5486 See :hg:`help urls` for more information.
5487
5487
5488 If multiple sources are specified, they will be pulled sequentially as if
5488 If multiple sources are specified, they will be pulled sequentially as if
5489 the command was run multiple time. If --update is specify and the command
5489 the command was run multiple time. If --update is specify and the command
5490 will stop at the first failed --update.
5490 will stop at the first failed --update.
5491
5491
5492 Specifying bookmark as ``.`` is equivalent to specifying the active
5492 Specifying bookmark as ``.`` is equivalent to specifying the active
5493 bookmark's name.
5493 bookmark's name.
5494
5494
5495 .. container:: verbose
5495 .. container:: verbose
5496
5496
5497 One can use the `--remote-hidden` flag to pull changesets
5497 One can use the `--remote-hidden` flag to pull changesets
5498 hidden on the remote. This flag is "best effort", and will only
5498 hidden on the remote. This flag is "best effort", and will only
5499 work if the server supports the feature and is configured to
5499 work if the server supports the feature and is configured to
5500 allow the user to access hidden changesets. This option is
5500 allow the user to access hidden changesets. This option is
5501 experimental and backwards compatibility is not garanteed.
5501 experimental and backwards compatibility is not garanteed.
5502
5502
5503 Returns 0 on success, 1 if an update had unresolved files.
5503 Returns 0 on success, 1 if an update had unresolved files.
5504 """
5504 """
5505
5505
5506 if ui.configbool(b'commands', b'update.requiredest') and opts.get('update'):
5506 if ui.configbool(b'commands', b'update.requiredest') and opts.get('update'):
5507 msg = _(b'update destination required by configuration')
5507 msg = _(b'update destination required by configuration')
5508 hint = _(b'use hg pull followed by hg update DEST')
5508 hint = _(b'use hg pull followed by hg update DEST')
5509 raise error.InputError(msg, hint=hint)
5509 raise error.InputError(msg, hint=hint)
5510
5510
5511 update_conflict = None
5511 update_conflict = None
5512
5512
5513 for path in urlutil.get_pull_paths(repo, ui, sources):
5513 for path in urlutil.get_pull_paths(repo, ui, sources):
5514 ui.status(_(b'pulling from %s\n') % urlutil.hidepassword(path.loc))
5514 ui.status(_(b'pulling from %s\n') % urlutil.hidepassword(path.loc))
5515 ui.flush()
5515 ui.flush()
5516 other = hg.peer(
5516 other = hg.peer(
5517 repo,
5517 repo,
5518 pycompat.byteskwargs(opts),
5518 pycompat.byteskwargs(opts),
5519 path,
5519 path,
5520 remotehidden=opts['remote_hidden'],
5520 remotehidden=opts['remote_hidden'],
5521 )
5521 )
5522 update_conflict = None
5522 update_conflict = None
5523 try:
5523 try:
5524 branches = (path.branch, opts.get('branch', []))
5524 branches = (path.branch, opts.get('branch', []))
5525 revs, checkout = hg.addbranchrevs(
5525 revs, checkout = hg.addbranchrevs(
5526 repo,
5526 repo,
5527 other,
5527 other,
5528 branches,
5528 branches,
5529 opts.get('rev'),
5529 opts.get('rev'),
5530 remotehidden=opts['remote_hidden'],
5530 remotehidden=opts['remote_hidden'],
5531 )
5531 )
5532
5532
5533 pullopargs = {}
5533 pullopargs = {}
5534
5534
5535 nodes = None
5535 nodes = None
5536 if opts.get('bookmark') or revs:
5536 if opts.get('bookmark') or revs:
5537 # The list of bookmark used here is the same used to actually update
5537 # The list of bookmark used here is the same used to actually update
5538 # the bookmark names, to avoid the race from issue 4689 and we do
5538 # the bookmark names, to avoid the race from issue 4689 and we do
5539 # all lookup and bookmark queries in one go so they see the same
5539 # all lookup and bookmark queries in one go so they see the same
5540 # version of the server state (issue 4700).
5540 # version of the server state (issue 4700).
5541 nodes = []
5541 nodes = []
5542 fnodes = []
5542 fnodes = []
5543 revs = revs or []
5543 revs = revs or []
5544 if revs and not other.capable(b'lookup'):
5544 if revs and not other.capable(b'lookup'):
5545 err = _(
5545 err = _(
5546 b"other repository doesn't support revision lookup, "
5546 b"other repository doesn't support revision lookup, "
5547 b"so a rev cannot be specified."
5547 b"so a rev cannot be specified."
5548 )
5548 )
5549 raise error.Abort(err)
5549 raise error.Abort(err)
5550 with other.commandexecutor() as e:
5550 with other.commandexecutor() as e:
5551 fremotebookmarks = e.callcommand(
5551 fremotebookmarks = e.callcommand(
5552 b'listkeys', {b'namespace': b'bookmarks'}
5552 b'listkeys', {b'namespace': b'bookmarks'}
5553 )
5553 )
5554 for r in revs:
5554 for r in revs:
5555 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5555 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5556 remotebookmarks = fremotebookmarks.result()
5556 remotebookmarks = fremotebookmarks.result()
5557 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5557 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5558 pullopargs[b'remotebookmarks'] = remotebookmarks
5558 pullopargs[b'remotebookmarks'] = remotebookmarks
5559 for b in opts.get('bookmark', []):
5559 for b in opts.get('bookmark', []):
5560 b = repo._bookmarks.expandname(b)
5560 b = repo._bookmarks.expandname(b)
5561 if b not in remotebookmarks:
5561 if b not in remotebookmarks:
5562 raise error.InputError(
5562 raise error.InputError(
5563 _(b'remote bookmark %s not found!') % b
5563 _(b'remote bookmark %s not found!') % b
5564 )
5564 )
5565 nodes.append(remotebookmarks[b])
5565 nodes.append(remotebookmarks[b])
5566 for i, rev in enumerate(revs):
5566 for i, rev in enumerate(revs):
5567 node = fnodes[i].result()
5567 node = fnodes[i].result()
5568 nodes.append(node)
5568 nodes.append(node)
5569 if rev == checkout:
5569 if rev == checkout:
5570 checkout = node
5570 checkout = node
5571
5571
5572 wlock = util.nullcontextmanager()
5572 wlock = util.nullcontextmanager()
5573 if opts.get('update'):
5573 if opts.get('update'):
5574 wlock = repo.wlock()
5574 wlock = repo.wlock()
5575 with wlock:
5575 with wlock:
5576 pullopargs.update(opts.get('opargs', {}))
5576 pullopargs.update(opts.get('opargs', {}))
5577 modheads = exchange.pull(
5577 modheads = exchange.pull(
5578 repo,
5578 repo,
5579 other,
5579 other,
5580 path=path,
5580 path=path,
5581 heads=nodes,
5581 heads=nodes,
5582 force=opts.get('force'),
5582 force=opts.get('force'),
5583 bookmarks=opts.get('bookmark', ()),
5583 bookmarks=opts.get('bookmark', ()),
5584 opargs=pullopargs,
5584 opargs=pullopargs,
5585 confirm=opts.get('confirm'),
5585 confirm=opts.get('confirm'),
5586 ).cgresult
5586 ).cgresult
5587
5587
5588 # brev is a name, which might be a bookmark to be activated at
5588 # brev is a name, which might be a bookmark to be activated at
5589 # the end of the update. In other words, it is an explicit
5589 # the end of the update. In other words, it is an explicit
5590 # destination of the update
5590 # destination of the update
5591 brev = None
5591 brev = None
5592
5592
5593 if checkout:
5593 if checkout:
5594 checkout = repo.unfiltered().changelog.rev(checkout)
5594 checkout = repo.unfiltered().changelog.rev(checkout)
5595
5595
5596 # order below depends on implementation of
5596 # order below depends on implementation of
5597 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5597 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5598 # because 'checkout' is determined without it.
5598 # because 'checkout' is determined without it.
5599 if opts.get('rev'):
5599 if opts.get('rev'):
5600 brev = opts['rev'][0]
5600 brev = opts['rev'][0]
5601 elif opts.get('branch'):
5601 elif opts.get('branch'):
5602 brev = opts['branch'][0]
5602 brev = opts['branch'][0]
5603 else:
5603 else:
5604 brev = path.branch
5604 brev = path.branch
5605
5605
5606 # XXX path: we are losing the `path` object here. Keeping it
5606 # XXX path: we are losing the `path` object here. Keeping it
5607 # would be valuable. For example as a "variant" as we do
5607 # would be valuable. For example as a "variant" as we do
5608 # for pushes.
5608 # for pushes.
5609 repo._subtoppath = path.loc
5609 repo._subtoppath = path.loc
5610 try:
5610 try:
5611 update_conflict = postincoming(
5611 update_conflict = postincoming(
5612 ui, repo, modheads, opts.get('update'), checkout, brev
5612 ui, repo, modheads, opts.get('update'), checkout, brev
5613 )
5613 )
5614 except error.FilteredRepoLookupError as exc:
5614 except error.FilteredRepoLookupError as exc:
5615 msg = _(b'cannot update to target: %s') % exc.args[0]
5615 msg = _(b'cannot update to target: %s') % exc.args[0]
5616 exc.args = (msg,) + exc.args[1:]
5616 exc.args = (msg,) + exc.args[1:]
5617 raise
5617 raise
5618 finally:
5618 finally:
5619 del repo._subtoppath
5619 del repo._subtoppath
5620
5620
5621 finally:
5621 finally:
5622 other.close()
5622 other.close()
5623 # skip the remaining pull source if they are some conflict.
5623 # skip the remaining pull source if they are some conflict.
5624 if update_conflict:
5624 if update_conflict:
5625 break
5625 break
5626 if update_conflict:
5626 if update_conflict:
5627 return 1
5627 return 1
5628 else:
5628 else:
5629 return 0
5629 return 0
5630
5630
5631
5631
5632 @command(
5632 @command(
5633 b'purge|clean',
5633 b'purge|clean',
5634 [
5634 [
5635 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5635 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5636 (b'', b'all', None, _(b'purge ignored files too')),
5636 (b'', b'all', None, _(b'purge ignored files too')),
5637 (b'i', b'ignored', None, _(b'purge only ignored files')),
5637 (b'i', b'ignored', None, _(b'purge only ignored files')),
5638 (b'', b'dirs', None, _(b'purge empty directories')),
5638 (b'', b'dirs', None, _(b'purge empty directories')),
5639 (b'', b'files', None, _(b'purge files')),
5639 (b'', b'files', None, _(b'purge files')),
5640 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5640 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5641 (
5641 (
5642 b'0',
5642 b'0',
5643 b'print0',
5643 b'print0',
5644 None,
5644 None,
5645 _(
5645 _(
5646 b'end filenames with NUL, for use with xargs'
5646 b'end filenames with NUL, for use with xargs'
5647 b' (implies -p/--print)'
5647 b' (implies -p/--print)'
5648 ),
5648 ),
5649 ),
5649 ),
5650 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5650 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5651 ]
5651 ]
5652 + cmdutil.walkopts,
5652 + cmdutil.walkopts,
5653 _(b'hg purge [OPTION]... [DIR]...'),
5653 _(b'hg purge [OPTION]... [DIR]...'),
5654 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5654 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5655 )
5655 )
5656 def purge(ui, repo, *dirs, **opts):
5656 def purge(ui, repo, *dirs, **opts):
5657 """removes files not tracked by Mercurial
5657 """removes files not tracked by Mercurial
5658
5658
5659 Delete files not known to Mercurial. This is useful to test local
5659 Delete files not known to Mercurial. This is useful to test local
5660 and uncommitted changes in an otherwise-clean source tree.
5660 and uncommitted changes in an otherwise-clean source tree.
5661
5661
5662 This means that purge will delete the following by default:
5662 This means that purge will delete the following by default:
5663
5663
5664 - Unknown files: files marked with "?" by :hg:`status`
5664 - Unknown files: files marked with "?" by :hg:`status`
5665 - Empty directories: in fact Mercurial ignores directories unless
5665 - Empty directories: in fact Mercurial ignores directories unless
5666 they contain files under source control management
5666 they contain files under source control management
5667
5667
5668 But it will leave untouched:
5668 But it will leave untouched:
5669
5669
5670 - Modified and unmodified tracked files
5670 - Modified and unmodified tracked files
5671 - Ignored files (unless -i or --all is specified)
5671 - Ignored files (unless -i or --all is specified)
5672 - New files added to the repository (with :hg:`add`)
5672 - New files added to the repository (with :hg:`add`)
5673
5673
5674 The --files and --dirs options can be used to direct purge to delete
5674 The --files and --dirs options can be used to direct purge to delete
5675 only files, only directories, or both. If neither option is given,
5675 only files, only directories, or both. If neither option is given,
5676 both will be deleted.
5676 both will be deleted.
5677
5677
5678 If directories are given on the command line, only files in these
5678 If directories are given on the command line, only files in these
5679 directories are considered.
5679 directories are considered.
5680
5680
5681 Be careful with purge, as you could irreversibly delete some files
5681 Be careful with purge, as you could irreversibly delete some files
5682 you forgot to add to the repository. If you only want to print the
5682 you forgot to add to the repository. If you only want to print the
5683 list of files that this program would delete, use the --print
5683 list of files that this program would delete, use the --print
5684 option.
5684 option.
5685 """
5685 """
5686 cmdutil.check_at_most_one_arg(opts, 'all', 'ignored')
5686 cmdutil.check_at_most_one_arg(opts, 'all', 'ignored')
5687
5687
5688 act = not opts.get('print')
5688 act = not opts.get('print')
5689 eol = b'\n'
5689 eol = b'\n'
5690 if opts.get('print0'):
5690 if opts.get('print0'):
5691 eol = b'\0'
5691 eol = b'\0'
5692 act = False # --print0 implies --print
5692 act = False # --print0 implies --print
5693 if opts.get('all', False):
5693 if opts.get('all', False):
5694 ignored = True
5694 ignored = True
5695 unknown = True
5695 unknown = True
5696 else:
5696 else:
5697 ignored = opts.get('ignored', False)
5697 ignored = opts.get('ignored', False)
5698 unknown = not ignored
5698 unknown = not ignored
5699
5699
5700 removefiles = opts.get('files')
5700 removefiles = opts.get('files')
5701 removedirs = opts.get('dirs')
5701 removedirs = opts.get('dirs')
5702 confirm = opts.get('confirm')
5702 confirm = opts.get('confirm')
5703 if confirm is None:
5703 if confirm is None:
5704 try:
5704 try:
5705 extensions.find(b'purge')
5705 extensions.find(b'purge')
5706 confirm = False
5706 confirm = False
5707 except KeyError:
5707 except KeyError:
5708 confirm = True
5708 confirm = True
5709
5709
5710 if not removefiles and not removedirs:
5710 if not removefiles and not removedirs:
5711 removefiles = True
5711 removefiles = True
5712 removedirs = True
5712 removedirs = True
5713
5713
5714 match = scmutil.match(repo[None], dirs, pycompat.byteskwargs(opts))
5714 match = scmutil.match(repo[None], dirs, pycompat.byteskwargs(opts))
5715
5715
5716 paths = mergemod.purge(
5716 paths = mergemod.purge(
5717 repo,
5717 repo,
5718 match,
5718 match,
5719 unknown=unknown,
5719 unknown=unknown,
5720 ignored=ignored,
5720 ignored=ignored,
5721 removeemptydirs=removedirs,
5721 removeemptydirs=removedirs,
5722 removefiles=removefiles,
5722 removefiles=removefiles,
5723 abortonerror=opts.get('abort_on_err'),
5723 abortonerror=opts.get('abort_on_err'),
5724 noop=not act,
5724 noop=not act,
5725 confirm=confirm,
5725 confirm=confirm,
5726 )
5726 )
5727
5727
5728 for path in paths:
5728 for path in paths:
5729 if not act:
5729 if not act:
5730 ui.write(b'%s%s' % (path, eol))
5730 ui.write(b'%s%s' % (path, eol))
5731
5731
5732
5732
5733 @command(
5733 @command(
5734 b'push',
5734 b'push',
5735 [
5735 [
5736 (b'f', b'force', None, _(b'force push')),
5736 (b'f', b'force', None, _(b'force push')),
5737 (
5737 (
5738 b'r',
5738 b'r',
5739 b'rev',
5739 b'rev',
5740 [],
5740 [],
5741 _(b'a changeset intended to be included in the destination'),
5741 _(b'a changeset intended to be included in the destination'),
5742 _(b'REV'),
5742 _(b'REV'),
5743 ),
5743 ),
5744 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5744 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5745 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5745 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5746 (
5746 (
5747 b'b',
5747 b'b',
5748 b'branch',
5748 b'branch',
5749 [],
5749 [],
5750 _(b'a specific branch you would like to push'),
5750 _(b'a specific branch you would like to push'),
5751 _(b'BRANCH'),
5751 _(b'BRANCH'),
5752 ),
5752 ),
5753 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5753 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5754 (
5754 (
5755 b'',
5755 b'',
5756 b'pushvars',
5756 b'pushvars',
5757 [],
5757 [],
5758 _(b'variables that can be sent to server (ADVANCED)'),
5758 _(b'variables that can be sent to server (ADVANCED)'),
5759 ),
5759 ),
5760 (
5760 (
5761 b'',
5761 b'',
5762 b'publish',
5762 b'publish',
5763 False,
5763 False,
5764 _(b'push the changeset as public (EXPERIMENTAL)'),
5764 _(b'push the changeset as public (EXPERIMENTAL)'),
5765 ),
5765 ),
5766 ]
5766 ]
5767 + remoteopts,
5767 + remoteopts,
5768 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]...'),
5768 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]...'),
5769 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5769 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5770 helpbasic=True,
5770 helpbasic=True,
5771 )
5771 )
5772 def push(ui, repo, *dests, **opts):
5772 def push(ui, repo, *dests, **opts):
5773 """push changes to the specified destination
5773 """push changes to the specified destination
5774
5774
5775 Push changesets from the local repository to the specified
5775 Push changesets from the local repository to the specified
5776 destination.
5776 destination.
5777
5777
5778 This operation is symmetrical to pull: it is identical to a pull
5778 This operation is symmetrical to pull: it is identical to a pull
5779 in the destination repository from the current one.
5779 in the destination repository from the current one.
5780
5780
5781 By default, push will not allow creation of new heads at the
5781 By default, push will not allow creation of new heads at the
5782 destination, since multiple heads would make it unclear which head
5782 destination, since multiple heads would make it unclear which head
5783 to use. In this situation, it is recommended to pull and merge
5783 to use. In this situation, it is recommended to pull and merge
5784 before pushing.
5784 before pushing.
5785
5785
5786 Use --new-branch if you want to allow push to create a new named
5786 Use --new-branch if you want to allow push to create a new named
5787 branch that is not present at the destination. This allows you to
5787 branch that is not present at the destination. This allows you to
5788 only create a new branch without forcing other changes.
5788 only create a new branch without forcing other changes.
5789
5789
5790 .. note::
5790 .. note::
5791
5791
5792 Extra care should be taken with the -f/--force option,
5792 Extra care should be taken with the -f/--force option,
5793 which will push all new heads on all branches, an action which will
5793 which will push all new heads on all branches, an action which will
5794 almost always cause confusion for collaborators.
5794 almost always cause confusion for collaborators.
5795
5795
5796 If -r/--rev is used, the specified revision and all its ancestors
5796 If -r/--rev is used, the specified revision and all its ancestors
5797 will be pushed to the remote repository.
5797 will be pushed to the remote repository.
5798
5798
5799 If -B/--bookmark is used, the specified bookmarked revision, its
5799 If -B/--bookmark is used, the specified bookmarked revision, its
5800 ancestors, and the bookmark will be pushed to the remote
5800 ancestors, and the bookmark will be pushed to the remote
5801 repository. Specifying ``.`` is equivalent to specifying the active
5801 repository. Specifying ``.`` is equivalent to specifying the active
5802 bookmark's name. Use the --all-bookmarks option for pushing all
5802 bookmark's name. Use the --all-bookmarks option for pushing all
5803 current bookmarks.
5803 current bookmarks.
5804
5804
5805 Please see :hg:`help urls` for important details about ``ssh://``
5805 Please see :hg:`help urls` for important details about ``ssh://``
5806 URLs. If DESTINATION is omitted, a default path will be used.
5806 URLs. If DESTINATION is omitted, a default path will be used.
5807
5807
5808 When passed multiple destinations, push will process them one after the
5808 When passed multiple destinations, push will process them one after the
5809 other, but stop should an error occur.
5809 other, but stop should an error occur.
5810
5810
5811 .. container:: verbose
5811 .. container:: verbose
5812
5812
5813 The --pushvars option sends strings to the server that become
5813 The --pushvars option sends strings to the server that become
5814 environment variables prepended with ``HG_USERVAR_``. For example,
5814 environment variables prepended with ``HG_USERVAR_``. For example,
5815 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5815 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5816 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5816 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5817
5817
5818 pushvars can provide for user-overridable hooks as well as set debug
5818 pushvars can provide for user-overridable hooks as well as set debug
5819 levels. One example is having a hook that blocks commits containing
5819 levels. One example is having a hook that blocks commits containing
5820 conflict markers, but enables the user to override the hook if the file
5820 conflict markers, but enables the user to override the hook if the file
5821 is using conflict markers for testing purposes or the file format has
5821 is using conflict markers for testing purposes or the file format has
5822 strings that look like conflict markers.
5822 strings that look like conflict markers.
5823
5823
5824 By default, servers will ignore `--pushvars`. To enable it add the
5824 By default, servers will ignore `--pushvars`. To enable it add the
5825 following to your configuration file::
5825 following to your configuration file::
5826
5826
5827 [push]
5827 [push]
5828 pushvars.server = true
5828 pushvars.server = true
5829
5829
5830 Returns 0 if push was successful, 1 if nothing to push.
5830 Returns 0 if push was successful, 1 if nothing to push.
5831 """
5831 """
5832
5832
5833 opts = pycompat.byteskwargs(opts)
5833 opts = pycompat.byteskwargs(opts)
5834
5834
5835 if opts.get(b'all_bookmarks'):
5835 if opts.get(b'all_bookmarks'):
5836 cmdutil.check_incompatible_arguments(
5836 cmdutil.check_incompatible_arguments(
5837 opts,
5837 opts,
5838 b'all_bookmarks',
5838 b'all_bookmarks',
5839 [b'bookmark', b'rev'],
5839 [b'bookmark', b'rev'],
5840 )
5840 )
5841 opts[b'bookmark'] = list(repo._bookmarks)
5841 opts[b'bookmark'] = list(repo._bookmarks)
5842
5842
5843 if opts.get(b'bookmark'):
5843 if opts.get(b'bookmark'):
5844 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5844 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5845 for b in opts[b'bookmark']:
5845 for b in opts[b'bookmark']:
5846 # translate -B options to -r so changesets get pushed
5846 # translate -B options to -r so changesets get pushed
5847 b = repo._bookmarks.expandname(b)
5847 b = repo._bookmarks.expandname(b)
5848 if b in repo._bookmarks:
5848 if b in repo._bookmarks:
5849 opts.setdefault(b'rev', []).append(b)
5849 opts.setdefault(b'rev', []).append(b)
5850 else:
5850 else:
5851 # if we try to push a deleted bookmark, translate it to null
5851 # if we try to push a deleted bookmark, translate it to null
5852 # this lets simultaneous -r, -b options continue working
5852 # this lets simultaneous -r, -b options continue working
5853 opts.setdefault(b'rev', []).append(b"null")
5853 opts.setdefault(b'rev', []).append(b"null")
5854
5854
5855 some_pushed = False
5855 some_pushed = False
5856 result = 0
5856 result = 0
5857 for path in urlutil.get_push_paths(repo, ui, dests):
5857 for path in urlutil.get_push_paths(repo, ui, dests):
5858 dest = path.loc
5858 dest = path.loc
5859 branches = (path.branch, opts.get(b'branch') or [])
5859 branches = (path.branch, opts.get(b'branch') or [])
5860 ui.status(_(b'pushing to %s\n') % urlutil.hidepassword(dest))
5860 ui.status(_(b'pushing to %s\n') % urlutil.hidepassword(dest))
5861 revs, checkout = hg.addbranchrevs(
5861 revs, checkout = hg.addbranchrevs(
5862 repo, repo, branches, opts.get(b'rev')
5862 repo, repo, branches, opts.get(b'rev')
5863 )
5863 )
5864 other = hg.peer(repo, opts, dest)
5864 other = hg.peer(repo, opts, dest)
5865
5865
5866 try:
5866 try:
5867 if revs:
5867 if revs:
5868 revs = [repo[r].node() for r in logcmdutil.revrange(repo, revs)]
5868 revs = [repo[r].node() for r in logcmdutil.revrange(repo, revs)]
5869 if not revs:
5869 if not revs:
5870 raise error.InputError(
5870 raise error.InputError(
5871 _(b"specified revisions evaluate to an empty set"),
5871 _(b"specified revisions evaluate to an empty set"),
5872 hint=_(b"use different revision arguments"),
5872 hint=_(b"use different revision arguments"),
5873 )
5873 )
5874 elif path.pushrev:
5874 elif path.pushrev:
5875 # It doesn't make any sense to specify ancestor revisions. So limit
5875 # It doesn't make any sense to specify ancestor revisions. So limit
5876 # to DAG heads to make discovery simpler.
5876 # to DAG heads to make discovery simpler.
5877 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5877 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5878 revs = scmutil.revrange(repo, [expr])
5878 revs = scmutil.revrange(repo, [expr])
5879 revs = [repo[rev].node() for rev in revs]
5879 revs = [repo[rev].node() for rev in revs]
5880 if not revs:
5880 if not revs:
5881 raise error.InputError(
5881 raise error.InputError(
5882 _(
5882 _(
5883 b'default push revset for path evaluates to an empty set'
5883 b'default push revset for path evaluates to an empty set'
5884 )
5884 )
5885 )
5885 )
5886 elif ui.configbool(b'commands', b'push.require-revs'):
5886 elif ui.configbool(b'commands', b'push.require-revs'):
5887 raise error.InputError(
5887 raise error.InputError(
5888 _(b'no revisions specified to push'),
5888 _(b'no revisions specified to push'),
5889 hint=_(b'did you mean "hg push -r ."?'),
5889 hint=_(b'did you mean "hg push -r ."?'),
5890 )
5890 )
5891
5891
5892 repo._subtoppath = dest
5892 repo._subtoppath = dest
5893 try:
5893 try:
5894 # push subrepos depth-first for coherent ordering
5894 # push subrepos depth-first for coherent ordering
5895 c = repo[b'.']
5895 c = repo[b'.']
5896 subs = c.substate # only repos that are committed
5896 subs = c.substate # only repos that are committed
5897 for s in sorted(subs):
5897 for s in sorted(subs):
5898 sub_result = c.sub(s).push(opts)
5898 sub_result = c.sub(s).push(opts)
5899 if sub_result == 0:
5899 if sub_result == 0:
5900 return 1
5900 return 1
5901 finally:
5901 finally:
5902 del repo._subtoppath
5902 del repo._subtoppath
5903
5903
5904 opargs = dict(
5904 opargs = dict(
5905 opts.get(b'opargs', {})
5905 opts.get(b'opargs', {})
5906 ) # copy opargs since we may mutate it
5906 ) # copy opargs since we may mutate it
5907 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5907 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5908
5908
5909 pushop = exchange.push(
5909 pushop = exchange.push(
5910 repo,
5910 repo,
5911 other,
5911 other,
5912 opts.get(b'force'),
5912 opts.get(b'force'),
5913 revs=revs,
5913 revs=revs,
5914 newbranch=opts.get(b'new_branch'),
5914 newbranch=opts.get(b'new_branch'),
5915 bookmarks=opts.get(b'bookmark', ()),
5915 bookmarks=opts.get(b'bookmark', ()),
5916 publish=opts.get(b'publish'),
5916 publish=opts.get(b'publish'),
5917 opargs=opargs,
5917 opargs=opargs,
5918 )
5918 )
5919
5919
5920 if pushop.cgresult == 0:
5920 if pushop.cgresult == 0:
5921 result = 1
5921 result = 1
5922 elif pushop.cgresult is not None:
5922 elif pushop.cgresult is not None:
5923 some_pushed = True
5923 some_pushed = True
5924
5924
5925 if pushop.bkresult is not None:
5925 if pushop.bkresult is not None:
5926 if pushop.bkresult == 2:
5926 if pushop.bkresult == 2:
5927 result = 2
5927 result = 2
5928 elif not result and pushop.bkresult:
5928 elif not result and pushop.bkresult:
5929 result = 2
5929 result = 2
5930
5930
5931 if result:
5931 if result:
5932 break
5932 break
5933
5933
5934 finally:
5934 finally:
5935 other.close()
5935 other.close()
5936 if result == 0 and not some_pushed:
5936 if result == 0 and not some_pushed:
5937 result = 1
5937 result = 1
5938 return result
5938 return result
5939
5939
5940
5940
5941 @command(
5941 @command(
5942 b'recover',
5942 b'recover',
5943 [
5943 [
5944 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5944 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5945 ],
5945 ],
5946 helpcategory=command.CATEGORY_MAINTENANCE,
5946 helpcategory=command.CATEGORY_MAINTENANCE,
5947 )
5947 )
5948 def recover(ui, repo, **opts):
5948 def recover(ui, repo, **opts):
5949 """roll back an interrupted transaction
5949 """roll back an interrupted transaction
5950
5950
5951 Recover from an interrupted commit or pull.
5951 Recover from an interrupted commit or pull.
5952
5952
5953 This command tries to fix the repository status after an
5953 This command tries to fix the repository status after an
5954 interrupted operation. It should only be necessary when Mercurial
5954 interrupted operation. It should only be necessary when Mercurial
5955 suggests it.
5955 suggests it.
5956
5956
5957 Returns 0 if successful, 1 if nothing to recover or verify fails.
5957 Returns 0 if successful, 1 if nothing to recover or verify fails.
5958 """
5958 """
5959 ret = repo.recover()
5959 ret = repo.recover()
5960 if ret:
5960 if ret:
5961 if opts['verify']:
5961 if opts['verify']:
5962 return hg.verify(repo)
5962 return hg.verify(repo)
5963 else:
5963 else:
5964 msg = _(
5964 msg = _(
5965 b"(verify step skipped, run `hg verify` to check your "
5965 b"(verify step skipped, run `hg verify` to check your "
5966 b"repository content)\n"
5966 b"repository content)\n"
5967 )
5967 )
5968 ui.warn(msg)
5968 ui.warn(msg)
5969 return 0
5969 return 0
5970 return 1
5970 return 1
5971
5971
5972
5972
5973 @command(
5973 @command(
5974 b'remove|rm',
5974 b'remove|rm',
5975 [
5975 [
5976 (b'A', b'after', None, _(b'record delete for missing files')),
5976 (b'A', b'after', None, _(b'record delete for missing files')),
5977 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5977 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5978 ]
5978 ]
5979 + subrepoopts
5979 + subrepoopts
5980 + walkopts
5980 + walkopts
5981 + dryrunopts,
5981 + dryrunopts,
5982 _(b'[OPTION]... FILE...'),
5982 _(b'[OPTION]... FILE...'),
5983 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5983 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5984 helpbasic=True,
5984 helpbasic=True,
5985 inferrepo=True,
5985 inferrepo=True,
5986 )
5986 )
5987 def remove(ui, repo, *pats, **opts):
5987 def remove(ui, repo, *pats, **opts):
5988 """remove the specified files on the next commit
5988 """remove the specified files on the next commit
5989
5989
5990 Schedule the indicated files for removal from the current branch.
5990 Schedule the indicated files for removal from the current branch.
5991
5991
5992 This command schedules the files to be removed at the next commit.
5992 This command schedules the files to be removed at the next commit.
5993 To undo a remove before that, see :hg:`revert`. To undo added
5993 To undo a remove before that, see :hg:`revert`. To undo added
5994 files, see :hg:`forget`.
5994 files, see :hg:`forget`.
5995
5995
5996 .. container:: verbose
5996 .. container:: verbose
5997
5997
5998 -A/--after can be used to remove only files that have already
5998 -A/--after can be used to remove only files that have already
5999 been deleted, -f/--force can be used to force deletion, and -Af
5999 been deleted, -f/--force can be used to force deletion, and -Af
6000 can be used to remove files from the next revision without
6000 can be used to remove files from the next revision without
6001 deleting them from the working directory.
6001 deleting them from the working directory.
6002
6002
6003 The following table details the behavior of remove for different
6003 The following table details the behavior of remove for different
6004 file states (columns) and option combinations (rows). The file
6004 file states (columns) and option combinations (rows). The file
6005 states are Added [A], Clean [C], Modified [M] and Missing [!]
6005 states are Added [A], Clean [C], Modified [M] and Missing [!]
6006 (as reported by :hg:`status`). The actions are Warn, Remove
6006 (as reported by :hg:`status`). The actions are Warn, Remove
6007 (from branch) and Delete (from disk):
6007 (from branch) and Delete (from disk):
6008
6008
6009 ========= == == == ==
6009 ========= == == == ==
6010 opt/state A C M !
6010 opt/state A C M !
6011 ========= == == == ==
6011 ========= == == == ==
6012 none W RD W R
6012 none W RD W R
6013 -f R RD RD R
6013 -f R RD RD R
6014 -A W W W R
6014 -A W W W R
6015 -Af R R R R
6015 -Af R R R R
6016 ========= == == == ==
6016 ========= == == == ==
6017
6017
6018 .. note::
6018 .. note::
6019
6019
6020 :hg:`remove` never deletes files in Added [A] state from the
6020 :hg:`remove` never deletes files in Added [A] state from the
6021 working directory, not even if ``--force`` is specified.
6021 working directory, not even if ``--force`` is specified.
6022
6022
6023 Returns 0 on success, 1 if any warnings encountered.
6023 Returns 0 on success, 1 if any warnings encountered.
6024 """
6024 """
6025
6025
6026 after, force = opts.get('after'), opts.get('force')
6026 after, force = opts.get('after'), opts.get('force')
6027 dryrun = opts.get('dry_run')
6027 dryrun = opts.get('dry_run')
6028 if not pats and not after:
6028 if not pats and not after:
6029 raise error.InputError(_(b'no files specified'))
6029 raise error.InputError(_(b'no files specified'))
6030
6030
6031 with repo.wlock(), repo.dirstate.changing_files(repo):
6031 with repo.wlock(), repo.dirstate.changing_files(repo):
6032 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
6032 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
6033 subrepos = opts.get('subrepos')
6033 subrepos = opts.get('subrepos')
6034 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
6034 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
6035 return cmdutil.remove(
6035 return cmdutil.remove(
6036 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
6036 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
6037 )
6037 )
6038
6038
6039
6039
6040 @command(
6040 @command(
6041 b'rename|move|mv',
6041 b'rename|move|mv',
6042 [
6042 [
6043 (b'', b'forget', None, _(b'unmark a destination file as renamed')),
6043 (b'', b'forget', None, _(b'unmark a destination file as renamed')),
6044 (b'A', b'after', None, _(b'record a rename that has already occurred')),
6044 (b'A', b'after', None, _(b'record a rename that has already occurred')),
6045 (
6045 (
6046 b'',
6046 b'',
6047 b'at-rev',
6047 b'at-rev',
6048 b'',
6048 b'',
6049 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
6049 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
6050 _(b'REV'),
6050 _(b'REV'),
6051 ),
6051 ),
6052 (
6052 (
6053 b'f',
6053 b'f',
6054 b'force',
6054 b'force',
6055 None,
6055 None,
6056 _(b'forcibly move over an existing managed file'),
6056 _(b'forcibly move over an existing managed file'),
6057 ),
6057 ),
6058 ]
6058 ]
6059 + walkopts
6059 + walkopts
6060 + dryrunopts,
6060 + dryrunopts,
6061 _(b'[OPTION]... SOURCE... DEST'),
6061 _(b'[OPTION]... SOURCE... DEST'),
6062 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6062 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6063 )
6063 )
6064 def rename(ui, repo, *pats, **opts):
6064 def rename(ui, repo, *pats, **opts):
6065 """rename files; equivalent of copy + remove
6065 """rename files; equivalent of copy + remove
6066
6066
6067 Mark dest as copies of sources; mark sources for deletion. If dest
6067 Mark dest as copies of sources; mark sources for deletion. If dest
6068 is a directory, copies are put in that directory. If dest is a
6068 is a directory, copies are put in that directory. If dest is a
6069 file, there can only be one source.
6069 file, there can only be one source.
6070
6070
6071 By default, this command copies the contents of files as they
6071 By default, this command copies the contents of files as they
6072 exist in the working directory. If invoked with -A/--after, the
6072 exist in the working directory. If invoked with -A/--after, the
6073 operation is recorded, but no copying is performed.
6073 operation is recorded, but no copying is performed.
6074
6074
6075 To undo marking a destination file as renamed, use --forget. With that
6075 To undo marking a destination file as renamed, use --forget. With that
6076 option, all given (positional) arguments are unmarked as renames. The
6076 option, all given (positional) arguments are unmarked as renames. The
6077 destination file(s) will be left in place (still tracked). The source
6077 destination file(s) will be left in place (still tracked). The source
6078 file(s) will not be restored. Note that :hg:`rename --forget` behaves
6078 file(s) will not be restored. Note that :hg:`rename --forget` behaves
6079 the same way as :hg:`copy --forget`.
6079 the same way as :hg:`copy --forget`.
6080
6080
6081 This command takes effect with the next commit by default.
6081 This command takes effect with the next commit by default.
6082
6082
6083 Returns 0 on success, 1 if errors are encountered.
6083 Returns 0 on success, 1 if errors are encountered.
6084 """
6084 """
6085 context = lambda repo: repo.dirstate.changing_files(repo)
6085 context = lambda repo: repo.dirstate.changing_files(repo)
6086 rev = opts.get('at_rev')
6086 rev = opts.get('at_rev')
6087
6087
6088 if rev:
6088 if rev:
6089 ctx = logcmdutil.revsingle(repo, rev)
6089 ctx = logcmdutil.revsingle(repo, rev)
6090 if ctx.rev() is not None:
6090 if ctx.rev() is not None:
6091
6091
6092 def context(repo):
6092 def context(repo):
6093 return util.nullcontextmanager()
6093 return util.nullcontextmanager()
6094
6094
6095 opts['at_rev'] = ctx.rev()
6095 opts['at_rev'] = ctx.rev()
6096 with repo.wlock(), context(repo):
6096 with repo.wlock(), context(repo):
6097 return cmdutil.copy(
6097 return cmdutil.copy(
6098 ui, repo, pats, pycompat.byteskwargs(opts), rename=True
6098 ui, repo, pats, pycompat.byteskwargs(opts), rename=True
6099 )
6099 )
6100
6100
6101
6101
6102 @command(
6102 @command(
6103 b'resolve',
6103 b'resolve',
6104 [
6104 [
6105 (b'a', b'all', None, _(b'select all unresolved files')),
6105 (b'a', b'all', None, _(b'select all unresolved files')),
6106 (b'l', b'list', None, _(b'list state of files needing merge')),
6106 (b'l', b'list', None, _(b'list state of files needing merge')),
6107 (b'm', b'mark', None, _(b'mark files as resolved')),
6107 (b'm', b'mark', None, _(b'mark files as resolved')),
6108 (b'u', b'unmark', None, _(b'mark files as unresolved')),
6108 (b'u', b'unmark', None, _(b'mark files as unresolved')),
6109 (b'n', b'no-status', None, _(b'hide status prefix')),
6109 (b'n', b'no-status', None, _(b'hide status prefix')),
6110 (b'', b're-merge', None, _(b're-merge files')),
6110 (b'', b're-merge', None, _(b're-merge files')),
6111 ]
6111 ]
6112 + mergetoolopts
6112 + mergetoolopts
6113 + walkopts
6113 + walkopts
6114 + formatteropts,
6114 + formatteropts,
6115 _(b'[OPTION]... [FILE]...'),
6115 _(b'[OPTION]... [FILE]...'),
6116 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6116 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6117 inferrepo=True,
6117 inferrepo=True,
6118 )
6118 )
6119 def resolve(ui, repo, *pats, **opts):
6119 def resolve(ui, repo, *pats, **opts):
6120 """redo merges or set/view the merge status of files
6120 """redo merges or set/view the merge status of files
6121
6121
6122 Merges with unresolved conflicts are often the result of
6122 Merges with unresolved conflicts are often the result of
6123 non-interactive merging using the ``internal:merge`` configuration
6123 non-interactive merging using the ``internal:merge`` configuration
6124 setting, or a command-line merge tool like ``diff3``. The resolve
6124 setting, or a command-line merge tool like ``diff3``. The resolve
6125 command is used to manage the files involved in a merge, after
6125 command is used to manage the files involved in a merge, after
6126 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6126 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
6127 working directory must have two parents). See :hg:`help
6127 working directory must have two parents). See :hg:`help
6128 merge-tools` for information on configuring merge tools.
6128 merge-tools` for information on configuring merge tools.
6129
6129
6130 The resolve command can be used in the following ways:
6130 The resolve command can be used in the following ways:
6131
6131
6132 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
6132 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
6133 the specified files, discarding any previous merge attempts. Re-merging
6133 the specified files, discarding any previous merge attempts. Re-merging
6134 is not performed for files already marked as resolved. Use ``--all/-a``
6134 is not performed for files already marked as resolved. Use ``--all/-a``
6135 to select all unresolved files. ``--tool`` can be used to specify
6135 to select all unresolved files. ``--tool`` can be used to specify
6136 the merge tool used for the given files. It overrides the HGMERGE
6136 the merge tool used for the given files. It overrides the HGMERGE
6137 environment variable and your configuration files. Previous file
6137 environment variable and your configuration files. Previous file
6138 contents are saved with a ``.orig`` suffix.
6138 contents are saved with a ``.orig`` suffix.
6139
6139
6140 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6140 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
6141 (e.g. after having manually fixed-up the files). The default is
6141 (e.g. after having manually fixed-up the files). The default is
6142 to mark all unresolved files.
6142 to mark all unresolved files.
6143
6143
6144 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6144 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
6145 default is to mark all resolved files.
6145 default is to mark all resolved files.
6146
6146
6147 - :hg:`resolve -l`: list files which had or still have conflicts.
6147 - :hg:`resolve -l`: list files which had or still have conflicts.
6148 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6148 In the printed list, ``U`` = unresolved and ``R`` = resolved.
6149 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
6149 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
6150 the list. See :hg:`help filesets` for details.
6150 the list. See :hg:`help filesets` for details.
6151
6151
6152 .. note::
6152 .. note::
6153
6153
6154 Mercurial will not let you commit files with unresolved merge
6154 Mercurial will not let you commit files with unresolved merge
6155 conflicts. You must use :hg:`resolve -m ...` before you can
6155 conflicts. You must use :hg:`resolve -m ...` before you can
6156 commit after a conflicting merge.
6156 commit after a conflicting merge.
6157
6157
6158 .. container:: verbose
6158 .. container:: verbose
6159
6159
6160 Template:
6160 Template:
6161
6161
6162 The following keywords are supported in addition to the common template
6162 The following keywords are supported in addition to the common template
6163 keywords and functions. See also :hg:`help templates`.
6163 keywords and functions. See also :hg:`help templates`.
6164
6164
6165 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
6165 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
6166 :path: String. Repository-absolute path of the file.
6166 :path: String. Repository-absolute path of the file.
6167
6167
6168 Returns 0 on success, 1 if any files fail a resolve attempt.
6168 Returns 0 on success, 1 if any files fail a resolve attempt.
6169 """
6169 """
6170
6170
6171 opts = pycompat.byteskwargs(opts)
6171 opts = pycompat.byteskwargs(opts)
6172 confirm = ui.configbool(b'commands', b'resolve.confirm')
6172 confirm = ui.configbool(b'commands', b'resolve.confirm')
6173 flaglist = b'all mark unmark list no_status re_merge'.split()
6173 flaglist = b'all mark unmark list no_status re_merge'.split()
6174 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
6174 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
6175
6175
6176 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
6176 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
6177 if actioncount > 1:
6177 if actioncount > 1:
6178 raise error.InputError(_(b"too many actions specified"))
6178 raise error.InputError(_(b"too many actions specified"))
6179 elif actioncount == 0 and ui.configbool(
6179 elif actioncount == 0 and ui.configbool(
6180 b'commands', b'resolve.explicit-re-merge'
6180 b'commands', b'resolve.explicit-re-merge'
6181 ):
6181 ):
6182 hint = _(b'use --mark, --unmark, --list or --re-merge')
6182 hint = _(b'use --mark, --unmark, --list or --re-merge')
6183 raise error.InputError(_(b'no action specified'), hint=hint)
6183 raise error.InputError(_(b'no action specified'), hint=hint)
6184 if pats and all:
6184 if pats and all:
6185 raise error.InputError(_(b"can't specify --all and patterns"))
6185 raise error.InputError(_(b"can't specify --all and patterns"))
6186 if not (all or pats or show or mark or unmark):
6186 if not (all or pats or show or mark or unmark):
6187 raise error.InputError(
6187 raise error.InputError(
6188 _(b'no files or directories specified'),
6188 _(b'no files or directories specified'),
6189 hint=b'use --all to re-merge all unresolved files',
6189 hint=b'use --all to re-merge all unresolved files',
6190 )
6190 )
6191
6191
6192 if confirm:
6192 if confirm:
6193 if all:
6193 if all:
6194 if ui.promptchoice(
6194 if ui.promptchoice(
6195 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
6195 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
6196 ):
6196 ):
6197 raise error.CanceledError(_(b'user quit'))
6197 raise error.CanceledError(_(b'user quit'))
6198 if mark and not pats:
6198 if mark and not pats:
6199 if ui.promptchoice(
6199 if ui.promptchoice(
6200 _(
6200 _(
6201 b'mark all unresolved files as resolved (yn)?'
6201 b'mark all unresolved files as resolved (yn)?'
6202 b'$$ &Yes $$ &No'
6202 b'$$ &Yes $$ &No'
6203 )
6203 )
6204 ):
6204 ):
6205 raise error.CanceledError(_(b'user quit'))
6205 raise error.CanceledError(_(b'user quit'))
6206 if unmark and not pats:
6206 if unmark and not pats:
6207 if ui.promptchoice(
6207 if ui.promptchoice(
6208 _(
6208 _(
6209 b'mark all resolved files as unresolved (yn)?'
6209 b'mark all resolved files as unresolved (yn)?'
6210 b'$$ &Yes $$ &No'
6210 b'$$ &Yes $$ &No'
6211 )
6211 )
6212 ):
6212 ):
6213 raise error.CanceledError(_(b'user quit'))
6213 raise error.CanceledError(_(b'user quit'))
6214
6214
6215 uipathfn = scmutil.getuipathfn(repo)
6215 uipathfn = scmutil.getuipathfn(repo)
6216
6216
6217 if show:
6217 if show:
6218 ui.pager(b'resolve')
6218 ui.pager(b'resolve')
6219 fm = ui.formatter(b'resolve', opts)
6219 fm = ui.formatter(b'resolve', opts)
6220 ms = mergestatemod.mergestate.read(repo)
6220 ms = mergestatemod.mergestate.read(repo)
6221 wctx = repo[None]
6221 wctx = repo[None]
6222 m = scmutil.match(wctx, pats, opts)
6222 m = scmutil.match(wctx, pats, opts)
6223
6223
6224 # Labels and keys based on merge state. Unresolved path conflicts show
6224 # Labels and keys based on merge state. Unresolved path conflicts show
6225 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6225 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6226 # resolved conflicts.
6226 # resolved conflicts.
6227 mergestateinfo = {
6227 mergestateinfo = {
6228 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6228 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6229 b'resolve.unresolved',
6229 b'resolve.unresolved',
6230 b'U',
6230 b'U',
6231 ),
6231 ),
6232 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6232 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6233 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6233 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6234 b'resolve.unresolved',
6234 b'resolve.unresolved',
6235 b'P',
6235 b'P',
6236 ),
6236 ),
6237 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6237 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6238 b'resolve.resolved',
6238 b'resolve.resolved',
6239 b'R',
6239 b'R',
6240 ),
6240 ),
6241 }
6241 }
6242
6242
6243 for f in ms:
6243 for f in ms:
6244 if not m(f):
6244 if not m(f):
6245 continue
6245 continue
6246
6246
6247 label, key = mergestateinfo[ms[f]]
6247 label, key = mergestateinfo[ms[f]]
6248 fm.startitem()
6248 fm.startitem()
6249 fm.context(ctx=wctx)
6249 fm.context(ctx=wctx)
6250 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6250 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6251 fm.data(path=f)
6251 fm.data(path=f)
6252 fm.plain(b'%s\n' % uipathfn(f), label=label)
6252 fm.plain(b'%s\n' % uipathfn(f), label=label)
6253 fm.end()
6253 fm.end()
6254 return 0
6254 return 0
6255
6255
6256 with repo.wlock():
6256 with repo.wlock():
6257 ms = mergestatemod.mergestate.read(repo)
6257 ms = mergestatemod.mergestate.read(repo)
6258
6258
6259 if not (ms.active() or repo.dirstate.p2() != repo.nullid):
6259 if not (ms.active() or repo.dirstate.p2() != repo.nullid):
6260 raise error.StateError(
6260 raise error.StateError(
6261 _(b'resolve command not applicable when not merging')
6261 _(b'resolve command not applicable when not merging')
6262 )
6262 )
6263
6263
6264 wctx = repo[None]
6264 wctx = repo[None]
6265 m = scmutil.match(wctx, pats, opts)
6265 m = scmutil.match(wctx, pats, opts)
6266 ret = 0
6266 ret = 0
6267 didwork = False
6267 didwork = False
6268
6268
6269 hasconflictmarkers = []
6269 hasconflictmarkers = []
6270 if mark:
6270 if mark:
6271 markcheck = ui.config(b'commands', b'resolve.mark-check')
6271 markcheck = ui.config(b'commands', b'resolve.mark-check')
6272 if markcheck not in [b'warn', b'abort']:
6272 if markcheck not in [b'warn', b'abort']:
6273 # Treat all invalid / unrecognized values as 'none'.
6273 # Treat all invalid / unrecognized values as 'none'.
6274 markcheck = False
6274 markcheck = False
6275 for f in ms:
6275 for f in ms:
6276 if not m(f):
6276 if not m(f):
6277 continue
6277 continue
6278
6278
6279 didwork = True
6279 didwork = True
6280
6280
6281 # path conflicts must be resolved manually
6281 # path conflicts must be resolved manually
6282 if ms[f] in (
6282 if ms[f] in (
6283 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6283 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6284 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6284 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6285 ):
6285 ):
6286 if mark:
6286 if mark:
6287 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6287 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6288 elif unmark:
6288 elif unmark:
6289 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6289 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6290 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6290 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6291 ui.warn(
6291 ui.warn(
6292 _(b'%s: path conflict must be resolved manually\n')
6292 _(b'%s: path conflict must be resolved manually\n')
6293 % uipathfn(f)
6293 % uipathfn(f)
6294 )
6294 )
6295 continue
6295 continue
6296
6296
6297 if mark:
6297 if mark:
6298 if markcheck:
6298 if markcheck:
6299 fdata = repo.wvfs.tryread(f)
6299 fdata = repo.wvfs.tryread(f)
6300 if (
6300 if (
6301 filemerge.hasconflictmarkers(fdata)
6301 filemerge.hasconflictmarkers(fdata)
6302 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6302 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6303 ):
6303 ):
6304 hasconflictmarkers.append(f)
6304 hasconflictmarkers.append(f)
6305 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6305 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6306 elif unmark:
6306 elif unmark:
6307 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6307 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6308 else:
6308 else:
6309 # backup pre-resolve (merge uses .orig for its own purposes)
6309 # backup pre-resolve (merge uses .orig for its own purposes)
6310 a = repo.wjoin(f)
6310 a = repo.wjoin(f)
6311 try:
6311 try:
6312 util.copyfile(a, a + b".resolve")
6312 util.copyfile(a, a + b".resolve")
6313 except FileNotFoundError:
6313 except FileNotFoundError:
6314 pass
6314 pass
6315
6315
6316 try:
6316 try:
6317 # preresolve file
6317 # preresolve file
6318 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6318 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6319 with ui.configoverride(overrides, b'resolve'):
6319 with ui.configoverride(overrides, b'resolve'):
6320 r = ms.resolve(f, wctx)
6320 r = ms.resolve(f, wctx)
6321 if r:
6321 if r:
6322 ret = 1
6322 ret = 1
6323 finally:
6323 finally:
6324 ms.commit()
6324 ms.commit()
6325
6325
6326 # replace filemerge's .orig file with our resolve file
6326 # replace filemerge's .orig file with our resolve file
6327 try:
6327 try:
6328 util.rename(
6328 util.rename(
6329 a + b".resolve", scmutil.backuppath(ui, repo, f)
6329 a + b".resolve", scmutil.backuppath(ui, repo, f)
6330 )
6330 )
6331 except FileNotFoundError:
6331 except FileNotFoundError:
6332 pass
6332 pass
6333
6333
6334 if hasconflictmarkers:
6334 if hasconflictmarkers:
6335 ui.warn(
6335 ui.warn(
6336 _(
6336 _(
6337 b'warning: the following files still have conflict '
6337 b'warning: the following files still have conflict '
6338 b'markers:\n'
6338 b'markers:\n'
6339 )
6339 )
6340 + b''.join(
6340 + b''.join(
6341 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6341 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6342 )
6342 )
6343 )
6343 )
6344 if markcheck == b'abort' and not all and not pats:
6344 if markcheck == b'abort' and not all and not pats:
6345 raise error.StateError(
6345 raise error.StateError(
6346 _(b'conflict markers detected'),
6346 _(b'conflict markers detected'),
6347 hint=_(b'use --all to mark anyway'),
6347 hint=_(b'use --all to mark anyway'),
6348 )
6348 )
6349
6349
6350 ms.commit()
6350 ms.commit()
6351 branchmerge = repo.dirstate.p2() != repo.nullid
6351 branchmerge = repo.dirstate.p2() != repo.nullid
6352 # resolve is not doing a parent change here, however, `record updates`
6352 # resolve is not doing a parent change here, however, `record updates`
6353 # will call some dirstate API that at intended for parent changes call.
6353 # will call some dirstate API that at intended for parent changes call.
6354 # Ideally we would not need this and could implement a lighter version
6354 # Ideally we would not need this and could implement a lighter version
6355 # of the recordupdateslogic that will not have to deal with the part
6355 # of the recordupdateslogic that will not have to deal with the part
6356 # related to parent changes. However this would requires that:
6356 # related to parent changes. However this would requires that:
6357 # - we are sure we passed around enough information at update/merge
6357 # - we are sure we passed around enough information at update/merge
6358 # time to no longer needs it at `hg resolve time`
6358 # time to no longer needs it at `hg resolve time`
6359 # - we are sure we store that information well enough to be able to reuse it
6359 # - we are sure we store that information well enough to be able to reuse it
6360 # - we are the necessary logic to reuse it right.
6360 # - we are the necessary logic to reuse it right.
6361 #
6361 #
6362 # All this should eventually happens, but in the mean time, we use this
6362 # All this should eventually happens, but in the mean time, we use this
6363 # context manager slightly out of the context it should be.
6363 # context manager slightly out of the context it should be.
6364 with repo.dirstate.changing_parents(repo):
6364 with repo.dirstate.changing_parents(repo):
6365 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6365 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6366
6366
6367 if not didwork and pats:
6367 if not didwork and pats:
6368 hint = None
6368 hint = None
6369 if not any([p for p in pats if p.find(b':') >= 0]):
6369 if not any([p for p in pats if p.find(b':') >= 0]):
6370 pats = [b'path:%s' % p for p in pats]
6370 pats = [b'path:%s' % p for p in pats]
6371 m = scmutil.match(wctx, pats, opts)
6371 m = scmutil.match(wctx, pats, opts)
6372 for f in ms:
6372 for f in ms:
6373 if not m(f):
6373 if not m(f):
6374 continue
6374 continue
6375
6375
6376 def flag(o):
6376 def flag(o):
6377 if o == b're_merge':
6377 if o == b're_merge':
6378 return b'--re-merge '
6378 return b'--re-merge '
6379 return b'-%s ' % o[0:1]
6379 return b'-%s ' % o[0:1]
6380
6380
6381 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6381 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6382 hint = _(b"(try: hg resolve %s%s)\n") % (
6382 hint = _(b"(try: hg resolve %s%s)\n") % (
6383 flags,
6383 flags,
6384 b' '.join(pats),
6384 b' '.join(pats),
6385 )
6385 )
6386 break
6386 break
6387 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6387 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6388 if hint:
6388 if hint:
6389 ui.warn(hint)
6389 ui.warn(hint)
6390
6390
6391 unresolvedf = ms.unresolvedcount()
6391 unresolvedf = ms.unresolvedcount()
6392 if not unresolvedf:
6392 if not unresolvedf:
6393 ui.status(_(b'(no more unresolved files)\n'))
6393 ui.status(_(b'(no more unresolved files)\n'))
6394 cmdutil.checkafterresolved(repo)
6394 cmdutil.checkafterresolved(repo)
6395
6395
6396 return ret
6396 return ret
6397
6397
6398
6398
6399 @command(
6399 @command(
6400 b'revert',
6400 b'revert',
6401 [
6401 [
6402 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6402 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6403 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6403 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6404 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6404 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6405 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6405 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6406 (b'i', b'interactive', None, _(b'interactively select the changes')),
6406 (b'i', b'interactive', None, _(b'interactively select the changes')),
6407 ]
6407 ]
6408 + walkopts
6408 + walkopts
6409 + dryrunopts,
6409 + dryrunopts,
6410 _(b'[OPTION]... [-r REV] [NAME]...'),
6410 _(b'[OPTION]... [-r REV] [NAME]...'),
6411 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6411 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6412 )
6412 )
6413 def revert(ui, repo, *pats, **opts):
6413 def revert(ui, repo, *pats, **opts):
6414 """restore files to their checkout state
6414 """restore files to their checkout state
6415
6415
6416 .. note::
6416 .. note::
6417
6417
6418 To check out earlier revisions, you should use :hg:`update REV`.
6418 To check out earlier revisions, you should use :hg:`update REV`.
6419 To cancel an uncommitted merge (and lose your changes),
6419 To cancel an uncommitted merge (and lose your changes),
6420 use :hg:`merge --abort`.
6420 use :hg:`merge --abort`.
6421
6421
6422 With no revision specified, revert the specified files or directories
6422 With no revision specified, revert the specified files or directories
6423 to the contents they had in the parent of the working directory.
6423 to the contents they had in the parent of the working directory.
6424 This restores the contents of files to an unmodified
6424 This restores the contents of files to an unmodified
6425 state and unschedules adds, removes, copies, and renames. If the
6425 state and unschedules adds, removes, copies, and renames. If the
6426 working directory has two parents, you must explicitly specify a
6426 working directory has two parents, you must explicitly specify a
6427 revision.
6427 revision.
6428
6428
6429 Using the -r/--rev or -d/--date options, revert the given files or
6429 Using the -r/--rev or -d/--date options, revert the given files or
6430 directories to their states as of a specific revision. Because
6430 directories to their states as of a specific revision. Because
6431 revert does not change the working directory parents, this will
6431 revert does not change the working directory parents, this will
6432 cause these files to appear modified. This can be helpful to "back
6432 cause these files to appear modified. This can be helpful to "back
6433 out" some or all of an earlier change. See :hg:`backout` for a
6433 out" some or all of an earlier change. See :hg:`backout` for a
6434 related method.
6434 related method.
6435
6435
6436 Modified files are saved with a .orig suffix before reverting.
6436 Modified files are saved with a .orig suffix before reverting.
6437 To disable these backups, use --no-backup. It is possible to store
6437 To disable these backups, use --no-backup. It is possible to store
6438 the backup files in a custom directory relative to the root of the
6438 the backup files in a custom directory relative to the root of the
6439 repository by setting the ``ui.origbackuppath`` configuration
6439 repository by setting the ``ui.origbackuppath`` configuration
6440 option.
6440 option.
6441
6441
6442 See :hg:`help dates` for a list of formats valid for -d/--date.
6442 See :hg:`help dates` for a list of formats valid for -d/--date.
6443
6443
6444 See :hg:`help backout` for a way to reverse the effect of an
6444 See :hg:`help backout` for a way to reverse the effect of an
6445 earlier changeset.
6445 earlier changeset.
6446
6446
6447 Returns 0 on success.
6447 Returns 0 on success.
6448 """
6448 """
6449
6449
6450 if opts.get("date"):
6450 if opts.get("date"):
6451 cmdutil.check_incompatible_arguments(opts, 'date', ['rev'])
6451 cmdutil.check_incompatible_arguments(opts, 'date', ['rev'])
6452 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6452 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6453
6453
6454 parent, p2 = repo.dirstate.parents()
6454 parent, p2 = repo.dirstate.parents()
6455 if not opts.get('rev') and p2 != repo.nullid:
6455 if not opts.get('rev') and p2 != repo.nullid:
6456 # revert after merge is a trap for new users (issue2915)
6456 # revert after merge is a trap for new users (issue2915)
6457 raise error.InputError(
6457 raise error.InputError(
6458 _(b'uncommitted merge with no revision specified'),
6458 _(b'uncommitted merge with no revision specified'),
6459 hint=_(b"use 'hg update' or see 'hg help revert'"),
6459 hint=_(b"use 'hg update' or see 'hg help revert'"),
6460 )
6460 )
6461
6461
6462 rev = opts.get('rev')
6462 rev = opts.get('rev')
6463 if rev:
6463 if rev:
6464 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6464 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6465 ctx = logcmdutil.revsingle(repo, rev)
6465 ctx = logcmdutil.revsingle(repo, rev)
6466
6466
6467 if not (
6467 if not (
6468 pats
6468 pats
6469 or opts.get('include')
6469 or opts.get('include')
6470 or opts.get('exclude')
6470 or opts.get('exclude')
6471 or opts.get('all')
6471 or opts.get('all')
6472 or opts.get('interactive')
6472 or opts.get('interactive')
6473 ):
6473 ):
6474 msg = _(b"no files or directories specified")
6474 msg = _(b"no files or directories specified")
6475 if p2 != repo.nullid:
6475 if p2 != repo.nullid:
6476 hint = _(
6476 hint = _(
6477 b"uncommitted merge, use --all to discard all changes,"
6477 b"uncommitted merge, use --all to discard all changes,"
6478 b" or 'hg update -C .' to abort the merge"
6478 b" or 'hg update -C .' to abort the merge"
6479 )
6479 )
6480 raise error.InputError(msg, hint=hint)
6480 raise error.InputError(msg, hint=hint)
6481 dirty = any(repo.status())
6481 dirty = any(repo.status())
6482 node = ctx.node()
6482 node = ctx.node()
6483 if node != parent:
6483 if node != parent:
6484 if dirty:
6484 if dirty:
6485 hint = (
6485 hint = (
6486 _(
6486 _(
6487 b"uncommitted changes, use --all to discard all"
6487 b"uncommitted changes, use --all to discard all"
6488 b" changes, or 'hg update %d' to update"
6488 b" changes, or 'hg update %d' to update"
6489 )
6489 )
6490 % ctx.rev()
6490 % ctx.rev()
6491 )
6491 )
6492 else:
6492 else:
6493 hint = (
6493 hint = (
6494 _(
6494 _(
6495 b"use --all to revert all files,"
6495 b"use --all to revert all files,"
6496 b" or 'hg update %d' to update"
6496 b" or 'hg update %d' to update"
6497 )
6497 )
6498 % ctx.rev()
6498 % ctx.rev()
6499 )
6499 )
6500 elif dirty:
6500 elif dirty:
6501 hint = _(b"uncommitted changes, use --all to discard all changes")
6501 hint = _(b"uncommitted changes, use --all to discard all changes")
6502 else:
6502 else:
6503 hint = _(b"use --all to revert all files")
6503 hint = _(b"use --all to revert all files")
6504 raise error.InputError(msg, hint=hint)
6504 raise error.InputError(msg, hint=hint)
6505
6505
6506 return cmdutil.revert(ui, repo, ctx, *pats, **opts)
6506 return cmdutil.revert(ui, repo, ctx, *pats, **opts)
6507
6507
6508
6508
6509 @command(
6509 @command(
6510 b'rollback',
6510 b'rollback',
6511 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6511 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6512 helpcategory=command.CATEGORY_MAINTENANCE,
6512 helpcategory=command.CATEGORY_MAINTENANCE,
6513 )
6513 )
6514 def rollback(ui, repo, **opts):
6514 def rollback(ui, repo, **opts):
6515 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6515 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6516
6516
6517 Please use :hg:`commit --amend` instead of rollback to correct
6517 Please use :hg:`commit --amend` instead of rollback to correct
6518 mistakes in the last commit.
6518 mistakes in the last commit.
6519
6519
6520 This command should be used with care. There is only one level of
6520 This command should be used with care. There is only one level of
6521 rollback, and there is no way to undo a rollback. It will also
6521 rollback, and there is no way to undo a rollback. It will also
6522 restore the dirstate at the time of the last transaction, losing
6522 restore the dirstate at the time of the last transaction, losing
6523 any dirstate changes since that time. This command does not alter
6523 any dirstate changes since that time. This command does not alter
6524 the working directory.
6524 the working directory.
6525
6525
6526 Transactions are used to encapsulate the effects of all commands
6526 Transactions are used to encapsulate the effects of all commands
6527 that create new changesets or propagate existing changesets into a
6527 that create new changesets or propagate existing changesets into a
6528 repository.
6528 repository.
6529
6529
6530 .. container:: verbose
6530 .. container:: verbose
6531
6531
6532 For example, the following commands are transactional, and their
6532 For example, the following commands are transactional, and their
6533 effects can be rolled back:
6533 effects can be rolled back:
6534
6534
6535 - commit
6535 - commit
6536 - import
6536 - import
6537 - pull
6537 - pull
6538 - push (with this repository as the destination)
6538 - push (with this repository as the destination)
6539 - unbundle
6539 - unbundle
6540
6540
6541 To avoid permanent data loss, rollback will refuse to rollback a
6541 To avoid permanent data loss, rollback will refuse to rollback a
6542 commit transaction if it isn't checked out. Use --force to
6542 commit transaction if it isn't checked out. Use --force to
6543 override this protection.
6543 override this protection.
6544
6544
6545 The rollback command can be entirely disabled by setting the
6545 The rollback command can be entirely disabled by setting the
6546 ``ui.rollback`` configuration setting to false. If you're here
6546 ``ui.rollback`` configuration setting to false. If you're here
6547 because you want to use rollback and it's disabled, you can
6547 because you want to use rollback and it's disabled, you can
6548 re-enable the command by setting ``ui.rollback`` to true.
6548 re-enable the command by setting ``ui.rollback`` to true.
6549
6549
6550 This command is not intended for use on public repositories. Once
6550 This command is not intended for use on public repositories. Once
6551 changes are visible for pull by other users, rolling a transaction
6551 changes are visible for pull by other users, rolling a transaction
6552 back locally is ineffective (someone else may already have pulled
6552 back locally is ineffective (someone else may already have pulled
6553 the changes). Furthermore, a race is possible with readers of the
6553 the changes). Furthermore, a race is possible with readers of the
6554 repository; for example an in-progress pull from the repository
6554 repository; for example an in-progress pull from the repository
6555 may fail if a rollback is performed.
6555 may fail if a rollback is performed.
6556
6556
6557 Returns 0 on success, 1 if no rollback data is available.
6557 Returns 0 on success, 1 if no rollback data is available.
6558 """
6558 """
6559 if not ui.configbool(b'ui', b'rollback'):
6559 if not ui.configbool(b'ui', b'rollback'):
6560 raise error.Abort(
6560 raise error.Abort(
6561 _(b'rollback is disabled because it is unsafe'),
6561 _(b'rollback is disabled because it is unsafe'),
6562 hint=b'see `hg help -v rollback` for information',
6562 hint=b'see `hg help -v rollback` for information',
6563 )
6563 )
6564 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6564 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6565
6565
6566
6566
6567 @command(
6567 @command(
6568 b'root',
6568 b'root',
6569 [] + formatteropts,
6569 [] + formatteropts,
6570 intents={INTENT_READONLY},
6570 intents={INTENT_READONLY},
6571 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6571 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6572 )
6572 )
6573 def root(ui, repo, **opts):
6573 def root(ui, repo, **opts):
6574 """print the root (top) of the current working directory
6574 """print the root (top) of the current working directory
6575
6575
6576 Print the root directory of the current repository.
6576 Print the root directory of the current repository.
6577
6577
6578 .. container:: verbose
6578 .. container:: verbose
6579
6579
6580 Template:
6580 Template:
6581
6581
6582 The following keywords are supported in addition to the common template
6582 The following keywords are supported in addition to the common template
6583 keywords and functions. See also :hg:`help templates`.
6583 keywords and functions. See also :hg:`help templates`.
6584
6584
6585 :hgpath: String. Path to the .hg directory.
6585 :hgpath: String. Path to the .hg directory.
6586 :storepath: String. Path to the directory holding versioned data.
6586 :storepath: String. Path to the directory holding versioned data.
6587
6587
6588 Returns 0 on success.
6588 Returns 0 on success.
6589 """
6589 """
6590 opts = pycompat.byteskwargs(opts)
6590 opts = pycompat.byteskwargs(opts)
6591 with ui.formatter(b'root', opts) as fm:
6591 with ui.formatter(b'root', opts) as fm:
6592 fm.startitem()
6592 fm.startitem()
6593 fm.write(b'reporoot', b'%s\n', repo.root)
6593 fm.write(b'reporoot', b'%s\n', repo.root)
6594 fm.data(hgpath=repo.path, storepath=repo.spath)
6594 fm.data(hgpath=repo.path, storepath=repo.spath)
6595
6595
6596
6596
6597 @command(
6597 @command(
6598 b'serve',
6598 b'serve',
6599 [
6599 [
6600 (
6600 (
6601 b'A',
6601 b'A',
6602 b'accesslog',
6602 b'accesslog',
6603 b'',
6603 b'',
6604 _(b'name of access log file to write to'),
6604 _(b'name of access log file to write to'),
6605 _(b'FILE'),
6605 _(b'FILE'),
6606 ),
6606 ),
6607 (b'd', b'daemon', None, _(b'run server in background')),
6607 (b'd', b'daemon', None, _(b'run server in background')),
6608 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6608 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6609 (
6609 (
6610 b'E',
6610 b'E',
6611 b'errorlog',
6611 b'errorlog',
6612 b'',
6612 b'',
6613 _(b'name of error log file to write to'),
6613 _(b'name of error log file to write to'),
6614 _(b'FILE'),
6614 _(b'FILE'),
6615 ),
6615 ),
6616 # use string type, then we can check if something was passed
6616 # use string type, then we can check if something was passed
6617 (
6617 (
6618 b'p',
6618 b'p',
6619 b'port',
6619 b'port',
6620 b'',
6620 b'',
6621 _(b'port to listen on (default: 8000)'),
6621 _(b'port to listen on (default: 8000)'),
6622 _(b'PORT'),
6622 _(b'PORT'),
6623 ),
6623 ),
6624 (
6624 (
6625 b'a',
6625 b'a',
6626 b'address',
6626 b'address',
6627 b'',
6627 b'',
6628 _(b'address to listen on (default: all interfaces)'),
6628 _(b'address to listen on (default: all interfaces)'),
6629 _(b'ADDR'),
6629 _(b'ADDR'),
6630 ),
6630 ),
6631 (
6631 (
6632 b'',
6632 b'',
6633 b'prefix',
6633 b'prefix',
6634 b'',
6634 b'',
6635 _(b'prefix path to serve from (default: server root)'),
6635 _(b'prefix path to serve from (default: server root)'),
6636 _(b'PREFIX'),
6636 _(b'PREFIX'),
6637 ),
6637 ),
6638 (
6638 (
6639 b'n',
6639 b'n',
6640 b'name',
6640 b'name',
6641 b'',
6641 b'',
6642 _(b'name to show in web pages (default: working directory)'),
6642 _(b'name to show in web pages (default: working directory)'),
6643 _(b'NAME'),
6643 _(b'NAME'),
6644 ),
6644 ),
6645 (
6645 (
6646 b'',
6646 b'',
6647 b'web-conf',
6647 b'web-conf',
6648 b'',
6648 b'',
6649 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6649 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6650 _(b'FILE'),
6650 _(b'FILE'),
6651 ),
6651 ),
6652 (
6652 (
6653 b'',
6653 b'',
6654 b'webdir-conf',
6654 b'webdir-conf',
6655 b'',
6655 b'',
6656 _(b'name of the hgweb config file (DEPRECATED)'),
6656 _(b'name of the hgweb config file (DEPRECATED)'),
6657 _(b'FILE'),
6657 _(b'FILE'),
6658 ),
6658 ),
6659 (
6659 (
6660 b'',
6660 b'',
6661 b'pid-file',
6661 b'pid-file',
6662 b'',
6662 b'',
6663 _(b'name of file to write process ID to'),
6663 _(b'name of file to write process ID to'),
6664 _(b'FILE'),
6664 _(b'FILE'),
6665 ),
6665 ),
6666 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6666 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6667 (
6667 (
6668 b'',
6668 b'',
6669 b'cmdserver',
6669 b'cmdserver',
6670 b'',
6670 b'',
6671 _(b'for remote clients (ADVANCED)'),
6671 _(b'for remote clients (ADVANCED)'),
6672 _(b'MODE'),
6672 _(b'MODE'),
6673 ),
6673 ),
6674 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6674 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6675 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6675 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6676 (b'6', b'ipv6', None, _(b'use IPv6 instead of IPv4')),
6676 (b'6', b'ipv6', None, _(b'use IPv6 instead of IPv4')),
6677 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6677 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6678 (b'', b'print-url', None, _(b'start and print only the URL')),
6678 (b'', b'print-url', None, _(b'start and print only the URL')),
6679 ]
6679 ]
6680 + subrepoopts,
6680 + subrepoopts,
6681 _(b'[OPTION]...'),
6681 _(b'[OPTION]...'),
6682 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6682 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6683 helpbasic=True,
6683 helpbasic=True,
6684 optionalrepo=True,
6684 optionalrepo=True,
6685 )
6685 )
6686 def serve(ui, repo, **opts):
6686 def serve(ui, repo, **opts):
6687 """start stand-alone webserver
6687 """start stand-alone webserver
6688
6688
6689 Start a local HTTP repository browser and pull server. You can use
6689 Start a local HTTP repository browser and pull server. You can use
6690 this for ad-hoc sharing and browsing of repositories. It is
6690 this for ad-hoc sharing and browsing of repositories. It is
6691 recommended to use a real web server to serve a repository for
6691 recommended to use a real web server to serve a repository for
6692 longer periods of time.
6692 longer periods of time.
6693
6693
6694 Please note that the server does not implement access control.
6694 Please note that the server does not implement access control.
6695 This means that, by default, anybody can read from the server and
6695 This means that, by default, anybody can read from the server and
6696 nobody can write to it by default. Set the ``web.allow-push``
6696 nobody can write to it by default. Set the ``web.allow-push``
6697 option to ``*`` to allow everybody to push to the server. You
6697 option to ``*`` to allow everybody to push to the server. You
6698 should use a real web server if you need to authenticate users.
6698 should use a real web server if you need to authenticate users.
6699
6699
6700 By default, the server logs accesses to stdout and errors to
6700 By default, the server logs accesses to stdout and errors to
6701 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6701 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6702 files.
6702 files.
6703
6703
6704 To have the server choose a free port number to listen on, specify
6704 To have the server choose a free port number to listen on, specify
6705 a port number of 0; in this case, the server will print the port
6705 a port number of 0; in this case, the server will print the port
6706 number it uses.
6706 number it uses.
6707
6707
6708 Returns 0 on success.
6708 Returns 0 on success.
6709 """
6709 """
6710
6710
6711 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6711 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6712 opts = pycompat.byteskwargs(opts)
6712 opts = pycompat.byteskwargs(opts)
6713 if opts[b"print_url"] and ui.verbose:
6713 if opts[b"print_url"] and ui.verbose:
6714 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6714 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6715
6715
6716 if opts[b"stdio"]:
6716 if opts[b"stdio"]:
6717 if repo is None:
6717 if repo is None:
6718 raise error.RepoError(
6718 raise error.RepoError(
6719 _(b"there is no Mercurial repository here (.hg not found)")
6719 _(b"there is no Mercurial repository here (.hg not found)")
6720 )
6720 )
6721 accesshidden = False
6721 accesshidden = False
6722 if repo.filtername is None:
6722 if repo.filtername is None:
6723 allow = ui.configlist(
6723 allow = ui.configlist(
6724 b'experimental', b'server.allow-hidden-access'
6724 b'experimental', b'server.allow-hidden-access'
6725 )
6725 )
6726 user = procutil.getuser()
6726 user = procutil.getuser()
6727 if allow and scmutil.ismember(ui, user, allow):
6727 if allow and scmutil.ismember(ui, user, allow):
6728 accesshidden = True
6728 accesshidden = True
6729 else:
6729 else:
6730 msg = (
6730 msg = (
6731 _(
6731 _(
6732 b'ignoring request to access hidden changeset by '
6732 b'ignoring request to access hidden changeset by '
6733 b'unauthorized user: %s\n'
6733 b'unauthorized user: %s\n'
6734 )
6734 )
6735 % user
6735 % user
6736 )
6736 )
6737 ui.warn(msg)
6737 ui.warn(msg)
6738
6738
6739 s = wireprotoserver.sshserver(ui, repo, accesshidden=accesshidden)
6739 s = wireprotoserver.sshserver(ui, repo, accesshidden=accesshidden)
6740 s.serve_forever()
6740 s.serve_forever()
6741 return
6741 return
6742
6742
6743 service = server.createservice(ui, repo, opts)
6743 service = server.createservice(ui, repo, opts)
6744 return server.runservice(opts, initfn=service.init, runfn=service.run)
6744 return server.runservice(opts, initfn=service.init, runfn=service.run)
6745
6745
6746
6746
6747 @command(
6747 @command(
6748 b'shelve',
6748 b'shelve',
6749 [
6749 [
6750 (
6750 (
6751 b'A',
6751 b'A',
6752 b'addremove',
6752 b'addremove',
6753 None,
6753 None,
6754 _(b'mark new/missing files as added/removed before shelving'),
6754 _(b'mark new/missing files as added/removed before shelving'),
6755 ),
6755 ),
6756 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6756 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6757 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6757 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6758 (
6758 (
6759 b'',
6759 b'',
6760 b'date',
6760 b'date',
6761 b'',
6761 b'',
6762 _(b'shelve with the specified commit date'),
6762 _(b'shelve with the specified commit date'),
6763 _(b'DATE'),
6763 _(b'DATE'),
6764 ),
6764 ),
6765 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6765 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6766 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6766 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6767 (
6767 (
6768 b'k',
6768 b'k',
6769 b'keep',
6769 b'keep',
6770 False,
6770 False,
6771 _(b'shelve, but keep changes in the working directory'),
6771 _(b'shelve, but keep changes in the working directory'),
6772 ),
6772 ),
6773 (b'l', b'list', None, _(b'list current shelves')),
6773 (b'l', b'list', None, _(b'list current shelves')),
6774 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6774 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6775 (
6775 (
6776 b'n',
6776 b'n',
6777 b'name',
6777 b'name',
6778 b'',
6778 b'',
6779 _(b'use the given name for the shelved commit'),
6779 _(b'use the given name for the shelved commit'),
6780 _(b'NAME'),
6780 _(b'NAME'),
6781 ),
6781 ),
6782 (
6782 (
6783 b'p',
6783 b'p',
6784 b'patch',
6784 b'patch',
6785 None,
6785 None,
6786 _(
6786 _(
6787 b'output patches for changes (provide the names of the shelved '
6787 b'output patches for changes (provide the names of the shelved '
6788 b'changes as positional arguments)'
6788 b'changes as positional arguments)'
6789 ),
6789 ),
6790 ),
6790 ),
6791 (b'i', b'interactive', None, _(b'interactive mode')),
6791 (b'i', b'interactive', None, _(b'interactive mode')),
6792 (
6792 (
6793 b'',
6793 b'',
6794 b'stat',
6794 b'stat',
6795 None,
6795 None,
6796 _(
6796 _(
6797 b'output diffstat-style summary of changes (provide the names of '
6797 b'output diffstat-style summary of changes (provide the names of '
6798 b'the shelved changes as positional arguments)'
6798 b'the shelved changes as positional arguments)'
6799 ),
6799 ),
6800 ),
6800 ),
6801 ]
6801 ]
6802 + cmdutil.walkopts,
6802 + cmdutil.walkopts,
6803 _(b'hg shelve [OPTION]... [FILE]...'),
6803 _(b'hg shelve [OPTION]... [FILE]...'),
6804 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6804 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6805 )
6805 )
6806 def shelve(ui, repo, *pats, **opts):
6806 def shelve(ui, repo, *pats, **opts):
6807 """save and set aside changes from the working directory
6807 """save and set aside changes from the working directory
6808
6808
6809 Shelving takes files that "hg status" reports as not clean, saves
6809 Shelving takes files that "hg status" reports as not clean, saves
6810 the modifications to a bundle (a shelved change), and reverts the
6810 the modifications to a bundle (a shelved change), and reverts the
6811 files so that their state in the working directory becomes clean.
6811 files so that their state in the working directory becomes clean.
6812
6812
6813 To restore these changes to the working directory, using "hg
6813 To restore these changes to the working directory, using "hg
6814 unshelve"; this will work even if you switch to a different
6814 unshelve"; this will work even if you switch to a different
6815 commit.
6815 commit.
6816
6816
6817 When no files are specified, "hg shelve" saves all not-clean
6817 When no files are specified, "hg shelve" saves all not-clean
6818 files. If specific files or directories are named, only changes to
6818 files. If specific files or directories are named, only changes to
6819 those files are shelved.
6819 those files are shelved.
6820
6820
6821 In bare shelve (when no files are specified, without interactive,
6821 In bare shelve (when no files are specified, without interactive,
6822 include and exclude option), shelving remembers information if the
6822 include and exclude option), shelving remembers information if the
6823 working directory was on newly created branch, in other words working
6823 working directory was on newly created branch, in other words working
6824 directory was on different branch than its first parent. In this
6824 directory was on different branch than its first parent. In this
6825 situation unshelving restores branch information to the working directory.
6825 situation unshelving restores branch information to the working directory.
6826
6826
6827 Each shelved change has a name that makes it easier to find later.
6827 Each shelved change has a name that makes it easier to find later.
6828 The name of a shelved change defaults to being based on the active
6828 The name of a shelved change defaults to being based on the active
6829 bookmark, or if there is no active bookmark, the current named
6829 bookmark, or if there is no active bookmark, the current named
6830 branch. To specify a different name, use ``--name``.
6830 branch. To specify a different name, use ``--name``.
6831
6831
6832 To see a list of existing shelved changes, use the ``--list``
6832 To see a list of existing shelved changes, use the ``--list``
6833 option. For each shelved change, this will print its name, age,
6833 option. For each shelved change, this will print its name, age,
6834 and description; use ``--patch`` or ``--stat`` for more details.
6834 and description; use ``--patch`` or ``--stat`` for more details.
6835
6835
6836 To delete specific shelved changes, use ``--delete``. To delete
6836 To delete specific shelved changes, use ``--delete``. To delete
6837 all shelved changes, use ``--cleanup``.
6837 all shelved changes, use ``--cleanup``.
6838 """
6838 """
6839 opts = pycompat.byteskwargs(opts)
6839 opts = pycompat.byteskwargs(opts)
6840 allowables = [
6840 allowables = [
6841 (b'addremove', {b'create'}), # 'create' is pseudo action
6841 (b'addremove', {b'create'}), # 'create' is pseudo action
6842 (b'unknown', {b'create'}),
6842 (b'unknown', {b'create'}),
6843 (b'cleanup', {b'cleanup'}),
6843 (b'cleanup', {b'cleanup'}),
6844 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6844 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6845 (b'delete', {b'delete'}),
6845 (b'delete', {b'delete'}),
6846 (b'edit', {b'create'}),
6846 (b'edit', {b'create'}),
6847 (b'keep', {b'create'}),
6847 (b'keep', {b'create'}),
6848 (b'list', {b'list'}),
6848 (b'list', {b'list'}),
6849 (b'message', {b'create'}),
6849 (b'message', {b'create'}),
6850 (b'name', {b'create'}),
6850 (b'name', {b'create'}),
6851 (b'patch', {b'patch', b'list'}),
6851 (b'patch', {b'patch', b'list'}),
6852 (b'stat', {b'stat', b'list'}),
6852 (b'stat', {b'stat', b'list'}),
6853 ]
6853 ]
6854
6854
6855 def checkopt(opt):
6855 def checkopt(opt):
6856 if opts.get(opt):
6856 if opts.get(opt):
6857 for i, allowable in allowables:
6857 for i, allowable in allowables:
6858 if opts[i] and opt not in allowable:
6858 if opts[i] and opt not in allowable:
6859 raise error.InputError(
6859 raise error.InputError(
6860 _(
6860 _(
6861 b"options '--%s' and '--%s' may not be "
6861 b"options '--%s' and '--%s' may not be "
6862 b"used together"
6862 b"used together"
6863 )
6863 )
6864 % (opt, i)
6864 % (opt, i)
6865 )
6865 )
6866 return True
6866 return True
6867
6867
6868 if checkopt(b'cleanup'):
6868 if checkopt(b'cleanup'):
6869 if pats:
6869 if pats:
6870 raise error.InputError(
6870 raise error.InputError(
6871 _(b"cannot specify names when using '--cleanup'")
6871 _(b"cannot specify names when using '--cleanup'")
6872 )
6872 )
6873 return shelvemod.cleanupcmd(ui, repo)
6873 return shelvemod.cleanupcmd(ui, repo)
6874 elif checkopt(b'delete'):
6874 elif checkopt(b'delete'):
6875 return shelvemod.deletecmd(ui, repo, pats)
6875 return shelvemod.deletecmd(ui, repo, pats)
6876 elif checkopt(b'list'):
6876 elif checkopt(b'list'):
6877 return shelvemod.listcmd(ui, repo, pats, opts)
6877 return shelvemod.listcmd(ui, repo, pats, opts)
6878 elif checkopt(b'patch') or checkopt(b'stat'):
6878 elif checkopt(b'patch') or checkopt(b'stat'):
6879 return shelvemod.patchcmds(ui, repo, pats, opts)
6879 return shelvemod.patchcmds(ui, repo, pats, opts)
6880 else:
6880 else:
6881 return shelvemod.createcmd(ui, repo, pats, opts)
6881 return shelvemod.createcmd(ui, repo, pats, opts)
6882
6882
6883
6883
6884 _NOTTERSE = b'nothing'
6884 _NOTTERSE = b'nothing'
6885
6885
6886
6886
6887 @command(
6887 @command(
6888 b'status|st',
6888 b'status|st',
6889 [
6889 [
6890 (b'A', b'all', None, _(b'show status of all files')),
6890 (b'A', b'all', None, _(b'show status of all files')),
6891 (b'm', b'modified', None, _(b'show only modified files')),
6891 (b'm', b'modified', None, _(b'show only modified files')),
6892 (b'a', b'added', None, _(b'show only added files')),
6892 (b'a', b'added', None, _(b'show only added files')),
6893 (b'r', b'removed', None, _(b'show only removed files')),
6893 (b'r', b'removed', None, _(b'show only removed files')),
6894 (b'd', b'deleted', None, _(b'show only missing files')),
6894 (b'd', b'deleted', None, _(b'show only missing files')),
6895 (b'c', b'clean', None, _(b'show only files without changes')),
6895 (b'c', b'clean', None, _(b'show only files without changes')),
6896 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6896 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6897 (b'i', b'ignored', None, _(b'show only ignored files')),
6897 (b'i', b'ignored', None, _(b'show only ignored files')),
6898 (b'n', b'no-status', None, _(b'hide status prefix')),
6898 (b'n', b'no-status', None, _(b'hide status prefix')),
6899 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6899 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6900 (
6900 (
6901 b'C',
6901 b'C',
6902 b'copies',
6902 b'copies',
6903 None,
6903 None,
6904 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6904 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6905 ),
6905 ),
6906 (
6906 (
6907 b'0',
6907 b'0',
6908 b'print0',
6908 b'print0',
6909 None,
6909 None,
6910 _(b'end filenames with NUL, for use with xargs'),
6910 _(b'end filenames with NUL, for use with xargs'),
6911 ),
6911 ),
6912 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6912 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6913 (
6913 (
6914 b'',
6914 b'',
6915 b'change',
6915 b'change',
6916 b'',
6916 b'',
6917 _(b'list the changed files of a revision'),
6917 _(b'list the changed files of a revision'),
6918 _(b'REV'),
6918 _(b'REV'),
6919 ),
6919 ),
6920 ]
6920 ]
6921 + walkopts
6921 + walkopts
6922 + subrepoopts
6922 + subrepoopts
6923 + formatteropts,
6923 + formatteropts,
6924 _(b'[OPTION]... [FILE]...'),
6924 _(b'[OPTION]... [FILE]...'),
6925 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6925 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6926 helpbasic=True,
6926 helpbasic=True,
6927 inferrepo=True,
6927 inferrepo=True,
6928 intents={INTENT_READONLY},
6928 intents={INTENT_READONLY},
6929 )
6929 )
6930 def status(ui, repo, *pats, **opts):
6930 def status(ui, repo, *pats, **opts):
6931 """show changed files in the working directory
6931 """show changed files in the working directory
6932
6932
6933 Show status of files in the repository. If names are given, only
6933 Show status of files in the repository. If names are given, only
6934 files that match are shown. Files that are clean or ignored or
6934 files that match are shown. Files that are clean or ignored or
6935 the source of a copy/move operation, are not listed unless
6935 the source of a copy/move operation, are not listed unless
6936 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6936 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6937 Unless options described with "show only ..." are given, the
6937 Unless options described with "show only ..." are given, the
6938 options -mardu are used.
6938 options -mardu are used.
6939
6939
6940 Option -q/--quiet hides untracked (unknown and ignored) files
6940 Option -q/--quiet hides untracked (unknown and ignored) files
6941 unless explicitly requested with -u/--unknown or -i/--ignored.
6941 unless explicitly requested with -u/--unknown or -i/--ignored.
6942
6942
6943 .. note::
6943 .. note::
6944
6944
6945 :hg:`status` may appear to disagree with diff if permissions have
6945 :hg:`status` may appear to disagree with diff if permissions have
6946 changed or a merge has occurred. The standard diff format does
6946 changed or a merge has occurred. The standard diff format does
6947 not report permission changes and diff only reports changes
6947 not report permission changes and diff only reports changes
6948 relative to one merge parent.
6948 relative to one merge parent.
6949
6949
6950 If one revision is given, it is used as the base revision.
6950 If one revision is given, it is used as the base revision.
6951 If two revisions are given, the differences between them are
6951 If two revisions are given, the differences between them are
6952 shown. The --change option can also be used as a shortcut to list
6952 shown. The --change option can also be used as a shortcut to list
6953 the changed files of a revision from its first parent.
6953 the changed files of a revision from its first parent.
6954
6954
6955 The codes used to show the status of files are::
6955 The codes used to show the status of files are::
6956
6956
6957 M = modified
6957 M = modified
6958 A = added
6958 A = added
6959 R = removed
6959 R = removed
6960 C = clean
6960 C = clean
6961 ! = missing (deleted by non-hg command, but still tracked)
6961 ! = missing (deleted by non-hg command, but still tracked)
6962 ? = not tracked
6962 ? = not tracked
6963 I = ignored
6963 I = ignored
6964 = origin of the previous file (with --copies)
6964 = origin of the previous file (with --copies)
6965
6965
6966 .. container:: verbose
6966 .. container:: verbose
6967
6967
6968 The -t/--terse option abbreviates the output by showing only the directory
6968 The -t/--terse option abbreviates the output by showing only the directory
6969 name if all the files in it share the same status. The option takes an
6969 name if all the files in it share the same status. The option takes an
6970 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6970 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6971 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6971 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6972 for 'ignored' and 'c' for clean.
6972 for 'ignored' and 'c' for clean.
6973
6973
6974 It abbreviates only those statuses which are passed. Note that clean and
6974 It abbreviates only those statuses which are passed. Note that clean and
6975 ignored files are not displayed with '--terse ic' unless the -c/--clean
6975 ignored files are not displayed with '--terse ic' unless the -c/--clean
6976 and -i/--ignored options are also used.
6976 and -i/--ignored options are also used.
6977
6977
6978 The -v/--verbose option shows information when the repository is in an
6978 The -v/--verbose option shows information when the repository is in an
6979 unfinished merge, shelve, rebase state etc. You can have this behavior
6979 unfinished merge, shelve, rebase state etc. You can have this behavior
6980 turned on by default by enabling the ``commands.status.verbose`` option.
6980 turned on by default by enabling the ``commands.status.verbose`` option.
6981
6981
6982 You can skip displaying some of these states by setting
6982 You can skip displaying some of these states by setting
6983 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6983 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6984 'histedit', 'merge', 'rebase', or 'unshelve'.
6984 'histedit', 'merge', 'rebase', or 'unshelve'.
6985
6985
6986 Template:
6986 Template:
6987
6987
6988 The following keywords are supported in addition to the common template
6988 The following keywords are supported in addition to the common template
6989 keywords and functions. See also :hg:`help templates`.
6989 keywords and functions. See also :hg:`help templates`.
6990
6990
6991 :path: String. Repository-absolute path of the file.
6991 :path: String. Repository-absolute path of the file.
6992 :source: String. Repository-absolute path of the file originated from.
6992 :source: String. Repository-absolute path of the file originated from.
6993 Available if ``--copies`` is specified.
6993 Available if ``--copies`` is specified.
6994 :status: String. Character denoting file's status.
6994 :status: String. Character denoting file's status.
6995
6995
6996 Examples:
6996 Examples:
6997
6997
6998 - show changes in the working directory relative to a
6998 - show changes in the working directory relative to a
6999 changeset::
6999 changeset::
7000
7000
7001 hg status --rev 9353
7001 hg status --rev 9353
7002
7002
7003 - show changes in the working directory relative to the
7003 - show changes in the working directory relative to the
7004 current directory (see :hg:`help patterns` for more information)::
7004 current directory (see :hg:`help patterns` for more information)::
7005
7005
7006 hg status re:
7006 hg status re:
7007
7007
7008 - show all changes including copies in an existing changeset::
7008 - show all changes including copies in an existing changeset::
7009
7009
7010 hg status --copies --change 9353
7010 hg status --copies --change 9353
7011
7011
7012 - get a NUL separated list of added files, suitable for xargs::
7012 - get a NUL separated list of added files, suitable for xargs::
7013
7013
7014 hg status -an0
7014 hg status -an0
7015
7015
7016 - show more information about the repository status, abbreviating
7016 - show more information about the repository status, abbreviating
7017 added, removed, modified, deleted, and untracked paths::
7017 added, removed, modified, deleted, and untracked paths::
7018
7018
7019 hg status -v -t mardu
7019 hg status -v -t mardu
7020
7020
7021 Returns 0 on success.
7021 Returns 0 on success.
7022
7022
7023 """
7023 """
7024
7024
7025 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
7025 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
7026 opts = pycompat.byteskwargs(opts)
7026 opts = pycompat.byteskwargs(opts)
7027 revs = opts.get(b'rev', [])
7027 revs = opts.get(b'rev', [])
7028 change = opts.get(b'change', b'')
7028 change = opts.get(b'change', b'')
7029 terse = opts.get(b'terse', _NOTTERSE)
7029 terse = opts.get(b'terse', _NOTTERSE)
7030 if terse is _NOTTERSE:
7030 if terse is _NOTTERSE:
7031 if revs:
7031 if revs:
7032 terse = b''
7032 terse = b''
7033 else:
7033 else:
7034 terse = ui.config(b'commands', b'status.terse')
7034 terse = ui.config(b'commands', b'status.terse')
7035
7035
7036 if revs and terse:
7036 if revs and terse:
7037 msg = _(b'cannot use --terse with --rev')
7037 msg = _(b'cannot use --terse with --rev')
7038 raise error.InputError(msg)
7038 raise error.InputError(msg)
7039 elif change:
7039 elif change:
7040 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
7040 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
7041 ctx2 = logcmdutil.revsingle(repo, change, None)
7041 ctx2 = logcmdutil.revsingle(repo, change, None)
7042 ctx1 = ctx2.p1()
7042 ctx1 = ctx2.p1()
7043 else:
7043 else:
7044 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
7044 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
7045 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
7045 ctx1, ctx2 = logcmdutil.revpair(repo, revs)
7046
7046
7047 forcerelativevalue = None
7047 forcerelativevalue = None
7048 if ui.hasconfig(b'commands', b'status.relative'):
7048 if ui.hasconfig(b'commands', b'status.relative'):
7049 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
7049 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
7050 uipathfn = scmutil.getuipathfn(
7050 uipathfn = scmutil.getuipathfn(
7051 repo,
7051 repo,
7052 legacyrelativevalue=bool(pats),
7052 legacyrelativevalue=bool(pats),
7053 forcerelativevalue=forcerelativevalue,
7053 forcerelativevalue=forcerelativevalue,
7054 )
7054 )
7055
7055
7056 if opts.get(b'print0'):
7056 if opts.get(b'print0'):
7057 end = b'\0'
7057 end = b'\0'
7058 else:
7058 else:
7059 end = b'\n'
7059 end = b'\n'
7060 states = b'modified added removed deleted unknown ignored clean'.split()
7060 states = b'modified added removed deleted unknown ignored clean'.split()
7061 show = [k for k in states if opts.get(k)]
7061 show = [k for k in states if opts.get(k)]
7062 if opts.get(b'all'):
7062 if opts.get(b'all'):
7063 show += ui.quiet and (states[:4] + [b'clean']) or states
7063 show += ui.quiet and (states[:4] + [b'clean']) or states
7064
7064
7065 if not show:
7065 if not show:
7066 if ui.quiet:
7066 if ui.quiet:
7067 show = states[:4]
7067 show = states[:4]
7068 else:
7068 else:
7069 show = states[:5]
7069 show = states[:5]
7070
7070
7071 m = scmutil.match(ctx2, pats, opts)
7071 m = scmutil.match(ctx2, pats, opts)
7072 if terse:
7072 if terse:
7073 # we need to compute clean and unknown to terse
7073 # we need to compute clean and unknown to terse
7074 stat = repo.status(
7074 stat = repo.status(
7075 ctx1.node(),
7075 ctx1.node(),
7076 ctx2.node(),
7076 ctx2.node(),
7077 m,
7077 m,
7078 b'ignored' in show or b'i' in terse,
7078 b'ignored' in show or b'i' in terse,
7079 clean=True,
7079 clean=True,
7080 unknown=True,
7080 unknown=True,
7081 listsubrepos=opts.get(b'subrepos'),
7081 listsubrepos=opts.get(b'subrepos'),
7082 )
7082 )
7083
7083
7084 stat = cmdutil.tersedir(stat, terse)
7084 stat = cmdutil.tersedir(stat, terse)
7085 else:
7085 else:
7086 stat = repo.status(
7086 stat = repo.status(
7087 ctx1.node(),
7087 ctx1.node(),
7088 ctx2.node(),
7088 ctx2.node(),
7089 m,
7089 m,
7090 b'ignored' in show,
7090 b'ignored' in show,
7091 b'clean' in show,
7091 b'clean' in show,
7092 b'unknown' in show,
7092 b'unknown' in show,
7093 opts.get(b'subrepos'),
7093 opts.get(b'subrepos'),
7094 )
7094 )
7095
7095
7096 changestates = zip(
7096 changestates = zip(
7097 states,
7097 states,
7098 pycompat.iterbytestr(b'MAR!?IC'),
7098 pycompat.iterbytestr(b'MAR!?IC'),
7099 [getattr(stat, s.decode('utf8')) for s in states],
7099 [getattr(stat, s.decode('utf8')) for s in states],
7100 )
7100 )
7101
7101
7102 copy = {}
7102 copy = {}
7103 show_copies = ui.configbool(b'ui', b'statuscopies')
7103 show_copies = ui.configbool(b'ui', b'statuscopies')
7104 if opts.get(b'copies') is not None:
7104 if opts.get(b'copies') is not None:
7105 show_copies = opts.get(b'copies')
7105 show_copies = opts.get(b'copies')
7106 show_copies = (show_copies or opts.get(b'all')) and not opts.get(
7106 show_copies = (show_copies or opts.get(b'all')) and not opts.get(
7107 b'no_status'
7107 b'no_status'
7108 )
7108 )
7109 if show_copies:
7109 if show_copies:
7110 copy = copies.pathcopies(ctx1, ctx2, m)
7110 copy = copies.pathcopies(ctx1, ctx2, m)
7111
7111
7112 morestatus = None
7112 morestatus = None
7113 if (
7113 if (
7114 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
7114 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
7115 and not ui.plain()
7115 and not ui.plain()
7116 and not opts.get(b'print0')
7116 and not opts.get(b'print0')
7117 ):
7117 ):
7118 morestatus = cmdutil.readmorestatus(repo)
7118 morestatus = cmdutil.readmorestatus(repo)
7119
7119
7120 ui.pager(b'status')
7120 ui.pager(b'status')
7121 fm = ui.formatter(b'status', opts)
7121 fm = ui.formatter(b'status', opts)
7122 fmt = b'%s' + end
7122 fmt = b'%s' + end
7123 showchar = not opts.get(b'no_status')
7123 showchar = not opts.get(b'no_status')
7124
7124
7125 for state, char, files in changestates:
7125 for state, char, files in changestates:
7126 if state in show:
7126 if state in show:
7127 label = b'status.' + state
7127 label = b'status.' + state
7128 for f in files:
7128 for f in files:
7129 fm.startitem()
7129 fm.startitem()
7130 fm.context(ctx=ctx2)
7130 fm.context(ctx=ctx2)
7131 fm.data(itemtype=b'file', path=f)
7131 fm.data(itemtype=b'file', path=f)
7132 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
7132 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
7133 fm.plain(fmt % uipathfn(f), label=label)
7133 fm.plain(fmt % uipathfn(f), label=label)
7134 if f in copy:
7134 if f in copy:
7135 fm.data(source=copy[f])
7135 fm.data(source=copy[f])
7136 fm.plain(
7136 fm.plain(
7137 (b' %s' + end) % uipathfn(copy[f]),
7137 (b' %s' + end) % uipathfn(copy[f]),
7138 label=b'status.copied',
7138 label=b'status.copied',
7139 )
7139 )
7140 if morestatus:
7140 if morestatus:
7141 morestatus.formatfile(f, fm)
7141 morestatus.formatfile(f, fm)
7142
7142
7143 if morestatus:
7143 if morestatus:
7144 morestatus.formatfooter(fm)
7144 morestatus.formatfooter(fm)
7145 fm.end()
7145 fm.end()
7146
7146
7147
7147
7148 @command(
7148 @command(
7149 b'summary|sum',
7149 b'summary|sum',
7150 [(b'', b'remote', None, _(b'check for push and pull'))],
7150 [(b'', b'remote', None, _(b'check for push and pull'))],
7151 b'[--remote]',
7151 b'[--remote]',
7152 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7152 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7153 helpbasic=True,
7153 helpbasic=True,
7154 intents={INTENT_READONLY},
7154 intents={INTENT_READONLY},
7155 )
7155 )
7156 def summary(ui, repo, **opts):
7156 def summary(ui, repo, **opts):
7157 """summarize working directory state
7157 """summarize working directory state
7158
7158
7159 This generates a brief summary of the working directory state,
7159 This generates a brief summary of the working directory state,
7160 including parents, branch, commit status, phase and available updates.
7160 including parents, branch, commit status, phase and available updates.
7161
7161
7162 With the --remote option, this will check the default paths for
7162 With the --remote option, this will check the default paths for
7163 incoming and outgoing changes. This can be time-consuming.
7163 incoming and outgoing changes. This can be time-consuming.
7164
7164
7165 Returns 0 on success.
7165 Returns 0 on success.
7166 """
7166 """
7167
7167
7168 ui.pager(b'summary')
7168 ui.pager(b'summary')
7169 ctx = repo[None]
7169 ctx = repo[None]
7170 parents = ctx.parents()
7170 parents = ctx.parents()
7171 pnode = parents[0].node()
7171 pnode = parents[0].node()
7172 marks = []
7172 marks = []
7173
7173
7174 try:
7174 try:
7175 ms = mergestatemod.mergestate.read(repo)
7175 ms = mergestatemod.mergestate.read(repo)
7176 except error.UnsupportedMergeRecords as e:
7176 except error.UnsupportedMergeRecords as e:
7177 s = b' '.join(e.recordtypes)
7177 s = b' '.join(e.recordtypes)
7178 ui.warn(
7178 ui.warn(
7179 _(b'warning: merge state has unsupported record types: %s\n') % s
7179 _(b'warning: merge state has unsupported record types: %s\n') % s
7180 )
7180 )
7181 unresolved = []
7181 unresolved = []
7182 else:
7182 else:
7183 unresolved = list(ms.unresolved())
7183 unresolved = list(ms.unresolved())
7184
7184
7185 for p in parents:
7185 for p in parents:
7186 # label with log.changeset (instead of log.parent) since this
7186 # label with log.changeset (instead of log.parent) since this
7187 # shows a working directory parent *changeset*:
7187 # shows a working directory parent *changeset*:
7188 # i18n: column positioning for "hg summary"
7188 # i18n: column positioning for "hg summary"
7189 ui.write(
7189 ui.write(
7190 _(b'parent: %d:%s ') % (p.rev(), p),
7190 _(b'parent: %d:%s ') % (p.rev(), p),
7191 label=logcmdutil.changesetlabels(p),
7191 label=logcmdutil.changesetlabels(p),
7192 )
7192 )
7193 ui.write(b' '.join(p.tags()), label=b'log.tag')
7193 ui.write(b' '.join(p.tags()), label=b'log.tag')
7194 if p.bookmarks():
7194 if p.bookmarks():
7195 marks.extend(p.bookmarks())
7195 marks.extend(p.bookmarks())
7196 if p.rev() == -1:
7196 if p.rev() == -1:
7197 if not len(repo):
7197 if not len(repo):
7198 ui.write(_(b' (empty repository)'))
7198 ui.write(_(b' (empty repository)'))
7199 else:
7199 else:
7200 ui.write(_(b' (no revision checked out)'))
7200 ui.write(_(b' (no revision checked out)'))
7201 if p.obsolete():
7201 if p.obsolete():
7202 ui.write(_(b' (obsolete)'))
7202 ui.write(_(b' (obsolete)'))
7203 if p.isunstable():
7203 if p.isunstable():
7204 instabilities = (
7204 instabilities = (
7205 ui.label(instability, b'trouble.%s' % instability)
7205 ui.label(instability, b'trouble.%s' % instability)
7206 for instability in p.instabilities()
7206 for instability in p.instabilities()
7207 )
7207 )
7208 ui.write(b' (' + b', '.join(instabilities) + b')')
7208 ui.write(b' (' + b', '.join(instabilities) + b')')
7209 ui.write(b'\n')
7209 ui.write(b'\n')
7210 if p.description():
7210 if p.description():
7211 ui.status(
7211 ui.status(
7212 b' ' + p.description().splitlines()[0].strip() + b'\n',
7212 b' ' + p.description().splitlines()[0].strip() + b'\n',
7213 label=b'log.summary',
7213 label=b'log.summary',
7214 )
7214 )
7215
7215
7216 branch = ctx.branch()
7216 branch = ctx.branch()
7217 bheads = repo.branchheads(branch)
7217 bheads = repo.branchheads(branch)
7218 # i18n: column positioning for "hg summary"
7218 # i18n: column positioning for "hg summary"
7219 m = _(b'branch: %s\n') % branch
7219 m = _(b'branch: %s\n') % branch
7220 if branch != b'default':
7220 if branch != b'default':
7221 ui.write(m, label=b'log.branch')
7221 ui.write(m, label=b'log.branch')
7222 else:
7222 else:
7223 ui.status(m, label=b'log.branch')
7223 ui.status(m, label=b'log.branch')
7224
7224
7225 if marks:
7225 if marks:
7226 active = repo._activebookmark
7226 active = repo._activebookmark
7227 # i18n: column positioning for "hg summary"
7227 # i18n: column positioning for "hg summary"
7228 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7228 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7229 if active is not None:
7229 if active is not None:
7230 if active in marks:
7230 if active in marks:
7231 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7231 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7232 marks.remove(active)
7232 marks.remove(active)
7233 else:
7233 else:
7234 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7234 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7235 for m in marks:
7235 for m in marks:
7236 ui.write(b' ' + m, label=b'log.bookmark')
7236 ui.write(b' ' + m, label=b'log.bookmark')
7237 ui.write(b'\n', label=b'log.bookmark')
7237 ui.write(b'\n', label=b'log.bookmark')
7238
7238
7239 status = repo.status(unknown=True)
7239 status = repo.status(unknown=True)
7240
7240
7241 c = repo.dirstate.copies()
7241 c = repo.dirstate.copies()
7242 copied, renamed = [], []
7242 copied, renamed = [], []
7243 for d, s in c.items():
7243 for d, s in c.items():
7244 if s in status.removed:
7244 if s in status.removed:
7245 status.removed.remove(s)
7245 status.removed.remove(s)
7246 renamed.append(d)
7246 renamed.append(d)
7247 else:
7247 else:
7248 copied.append(d)
7248 copied.append(d)
7249 if d in status.added:
7249 if d in status.added:
7250 status.added.remove(d)
7250 status.added.remove(d)
7251
7251
7252 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7252 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7253
7253
7254 labels = [
7254 labels = [
7255 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7255 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7256 (ui.label(_(b'%d added'), b'status.added'), status.added),
7256 (ui.label(_(b'%d added'), b'status.added'), status.added),
7257 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7257 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7258 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7258 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7259 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7259 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7260 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7260 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7261 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7261 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7262 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7262 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7263 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7263 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7264 ]
7264 ]
7265 t = []
7265 t = []
7266 for l, s in labels:
7266 for l, s in labels:
7267 if s:
7267 if s:
7268 t.append(l % len(s))
7268 t.append(l % len(s))
7269
7269
7270 t = b', '.join(t)
7270 t = b', '.join(t)
7271 cleanworkdir = False
7271 cleanworkdir = False
7272
7272
7273 if repo.vfs.exists(b'graftstate'):
7273 if repo.vfs.exists(b'graftstate'):
7274 t += _(b' (graft in progress)')
7274 t += _(b' (graft in progress)')
7275 if repo.vfs.exists(b'updatestate'):
7275 if repo.vfs.exists(b'updatestate'):
7276 t += _(b' (interrupted update)')
7276 t += _(b' (interrupted update)')
7277 elif len(parents) > 1:
7277 elif len(parents) > 1:
7278 t += _(b' (merge)')
7278 t += _(b' (merge)')
7279 elif branch != parents[0].branch():
7279 elif branch != parents[0].branch():
7280 t += _(b' (new branch)')
7280 t += _(b' (new branch)')
7281 elif parents[0].closesbranch() and pnode in repo.branchheads(
7281 elif parents[0].closesbranch() and pnode in repo.branchheads(
7282 branch, closed=True
7282 branch, closed=True
7283 ):
7283 ):
7284 t += _(b' (head closed)')
7284 t += _(b' (head closed)')
7285 elif not (
7285 elif not (
7286 status.modified
7286 status.modified
7287 or status.added
7287 or status.added
7288 or status.removed
7288 or status.removed
7289 or renamed
7289 or renamed
7290 or copied
7290 or copied
7291 or subs
7291 or subs
7292 ):
7292 ):
7293 t += _(b' (clean)')
7293 t += _(b' (clean)')
7294 cleanworkdir = True
7294 cleanworkdir = True
7295 elif pnode not in bheads:
7295 elif pnode not in bheads:
7296 t += _(b' (new branch head)')
7296 t += _(b' (new branch head)')
7297
7297
7298 if parents:
7298 if parents:
7299 pendingphase = max(p.phase() for p in parents)
7299 pendingphase = max(p.phase() for p in parents)
7300 else:
7300 else:
7301 pendingphase = phases.public
7301 pendingphase = phases.public
7302
7302
7303 if pendingphase > phases.newcommitphase(ui):
7303 if pendingphase > phases.newcommitphase(ui):
7304 t += b' (%s)' % phases.phasenames[pendingphase]
7304 t += b' (%s)' % phases.phasenames[pendingphase]
7305
7305
7306 if cleanworkdir:
7306 if cleanworkdir:
7307 # i18n: column positioning for "hg summary"
7307 # i18n: column positioning for "hg summary"
7308 ui.status(_(b'commit: %s\n') % t.strip())
7308 ui.status(_(b'commit: %s\n') % t.strip())
7309 else:
7309 else:
7310 # i18n: column positioning for "hg summary"
7310 # i18n: column positioning for "hg summary"
7311 ui.write(_(b'commit: %s\n') % t.strip())
7311 ui.write(_(b'commit: %s\n') % t.strip())
7312
7312
7313 # all ancestors of branch heads - all ancestors of parent = new csets
7313 # all ancestors of branch heads - all ancestors of parent = new csets
7314 new = len(
7314 new = len(
7315 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7315 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7316 )
7316 )
7317
7317
7318 if new == 0:
7318 if new == 0:
7319 # i18n: column positioning for "hg summary"
7319 # i18n: column positioning for "hg summary"
7320 ui.status(_(b'update: (current)\n'))
7320 ui.status(_(b'update: (current)\n'))
7321 elif pnode not in bheads:
7321 elif pnode not in bheads:
7322 # i18n: column positioning for "hg summary"
7322 # i18n: column positioning for "hg summary"
7323 ui.write(_(b'update: %d new changesets (update)\n') % new)
7323 ui.write(_(b'update: %d new changesets (update)\n') % new)
7324 else:
7324 else:
7325 # i18n: column positioning for "hg summary"
7325 # i18n: column positioning for "hg summary"
7326 ui.write(
7326 ui.write(
7327 _(b'update: %d new changesets, %d branch heads (merge)\n')
7327 _(b'update: %d new changesets, %d branch heads (merge)\n')
7328 % (new, len(bheads))
7328 % (new, len(bheads))
7329 )
7329 )
7330
7330
7331 t = []
7331 t = []
7332 draft = len(repo.revs(b'draft()'))
7332 draft = len(repo.revs(b'draft()'))
7333 if draft:
7333 if draft:
7334 t.append(_(b'%d draft') % draft)
7334 t.append(_(b'%d draft') % draft)
7335 secret = len(repo.revs(b'secret()'))
7335 secret = len(repo.revs(b'secret()'))
7336 if secret:
7336 if secret:
7337 t.append(_(b'%d secret') % secret)
7337 t.append(_(b'%d secret') % secret)
7338
7338
7339 if draft or secret:
7339 if draft or secret:
7340 ui.status(_(b'phases: %s\n') % b', '.join(t))
7340 ui.status(_(b'phases: %s\n') % b', '.join(t))
7341
7341
7342 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7342 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7343 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7343 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7344 numtrouble = len(repo.revs(trouble + b"()"))
7344 numtrouble = len(repo.revs(trouble + b"()"))
7345 # We write all the possibilities to ease translation
7345 # We write all the possibilities to ease translation
7346 troublemsg = {
7346 troublemsg = {
7347 b"orphan": _(b"orphan: %d changesets"),
7347 b"orphan": _(b"orphan: %d changesets"),
7348 b"contentdivergent": _(b"content-divergent: %d changesets"),
7348 b"contentdivergent": _(b"content-divergent: %d changesets"),
7349 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7349 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7350 }
7350 }
7351 if numtrouble > 0:
7351 if numtrouble > 0:
7352 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7352 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7353
7353
7354 cmdutil.summaryhooks(ui, repo)
7354 cmdutil.summaryhooks(ui, repo)
7355
7355
7356 if opts.get('remote'):
7356 if opts.get('remote'):
7357 needsincoming, needsoutgoing = True, True
7357 needsincoming, needsoutgoing = True, True
7358 else:
7358 else:
7359 needsincoming, needsoutgoing = False, False
7359 needsincoming, needsoutgoing = False, False
7360 for i, o in cmdutil.summaryremotehooks(
7360 for i, o in cmdutil.summaryremotehooks(
7361 ui, repo, pycompat.byteskwargs(opts), None
7361 ui, repo, pycompat.byteskwargs(opts), None
7362 ):
7362 ):
7363 if i:
7363 if i:
7364 needsincoming = True
7364 needsincoming = True
7365 if o:
7365 if o:
7366 needsoutgoing = True
7366 needsoutgoing = True
7367 if not needsincoming and not needsoutgoing:
7367 if not needsincoming and not needsoutgoing:
7368 return
7368 return
7369
7369
7370 def getincoming():
7370 def getincoming():
7371 # XXX We should actually skip this if no default is specified, instead
7371 # XXX We should actually skip this if no default is specified, instead
7372 # of passing "default" which will resolve as "./default/" if no default
7372 # of passing "default" which will resolve as "./default/" if no default
7373 # path is defined.
7373 # path is defined.
7374 path = urlutil.get_unique_pull_path_obj(b'summary', ui, b'default')
7374 path = urlutil.get_unique_pull_path_obj(b'summary', ui, b'default')
7375 sbranch = path.branch
7375 sbranch = path.branch
7376 try:
7376 try:
7377 other = hg.peer(repo, {}, path)
7377 other = hg.peer(repo, {}, path)
7378 except error.RepoError:
7378 except error.RepoError:
7379 if opts.get('remote'):
7379 if opts.get('remote'):
7380 raise
7380 raise
7381 return path.loc, sbranch, None, None, None
7381 return path.loc, sbranch, None, None, None
7382 branches = (path.branch, [])
7382 branches = (path.branch, [])
7383 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7383 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7384 if revs:
7384 if revs:
7385 revs = [other.lookup(rev) for rev in revs]
7385 revs = [other.lookup(rev) for rev in revs]
7386 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(path.loc))
7386 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(path.loc))
7387 with repo.ui.silent():
7387 with repo.ui.silent():
7388 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7388 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7389 return path.loc, sbranch, other, commoninc, commoninc[1]
7389 return path.loc, sbranch, other, commoninc, commoninc[1]
7390
7390
7391 if needsincoming:
7391 if needsincoming:
7392 source, sbranch, sother, commoninc, incoming = getincoming()
7392 source, sbranch, sother, commoninc, incoming = getincoming()
7393 else:
7393 else:
7394 source = sbranch = sother = commoninc = incoming = None
7394 source = sbranch = sother = commoninc = incoming = None
7395
7395
7396 def getoutgoing():
7396 def getoutgoing():
7397 # XXX We should actually skip this if no default is specified, instead
7397 # XXX We should actually skip this if no default is specified, instead
7398 # of passing "default" which will resolve as "./default/" if no default
7398 # of passing "default" which will resolve as "./default/" if no default
7399 # path is defined.
7399 # path is defined.
7400 d = None
7400 d = None
7401 if b'default-push' in ui.paths:
7401 if b'default-push' in ui.paths:
7402 d = b'default-push'
7402 d = b'default-push'
7403 elif b'default' in ui.paths:
7403 elif b'default' in ui.paths:
7404 d = b'default'
7404 d = b'default'
7405 path = None
7405 path = None
7406 if d is not None:
7406 if d is not None:
7407 path = urlutil.get_unique_push_path(b'summary', repo, ui, d)
7407 path = urlutil.get_unique_push_path(b'summary', repo, ui, d)
7408 dest = path.loc
7408 dest = path.loc
7409 dbranch = path.branch
7409 dbranch = path.branch
7410 else:
7410 else:
7411 dest = b'default'
7411 dest = b'default'
7412 dbranch = None
7412 dbranch = None
7413 revs, checkout = hg.addbranchrevs(repo, repo, (dbranch, []), None)
7413 revs, checkout = hg.addbranchrevs(repo, repo, (dbranch, []), None)
7414 if source != dest:
7414 if source != dest:
7415 try:
7415 try:
7416 dother = hg.peer(repo, {}, path if path is not None else dest)
7416 dother = hg.peer(repo, {}, path if path is not None else dest)
7417 except error.RepoError:
7417 except error.RepoError:
7418 if opts.get('remote'):
7418 if opts.get('remote'):
7419 raise
7419 raise
7420 return dest, dbranch, None, None
7420 return dest, dbranch, None, None
7421 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(dest))
7421 ui.debug(b'comparing with %s\n' % urlutil.hidepassword(dest))
7422 elif sother is None:
7422 elif sother is None:
7423 # there is no explicit destination peer, but source one is invalid
7423 # there is no explicit destination peer, but source one is invalid
7424 return dest, dbranch, None, None
7424 return dest, dbranch, None, None
7425 else:
7425 else:
7426 dother = sother
7426 dother = sother
7427 if source != dest or (sbranch is not None and sbranch != dbranch):
7427 if source != dest or (sbranch is not None and sbranch != dbranch):
7428 common = None
7428 common = None
7429 else:
7429 else:
7430 common = commoninc
7430 common = commoninc
7431 if revs:
7431 if revs:
7432 revs = [repo.lookup(rev) for rev in revs]
7432 revs = [repo.lookup(rev) for rev in revs]
7433 with repo.ui.silent():
7433 with repo.ui.silent():
7434 outgoing = discovery.findcommonoutgoing(
7434 outgoing = discovery.findcommonoutgoing(
7435 repo, dother, onlyheads=revs, commoninc=common
7435 repo, dother, onlyheads=revs, commoninc=common
7436 )
7436 )
7437 return dest, dbranch, dother, outgoing
7437 return dest, dbranch, dother, outgoing
7438
7438
7439 if needsoutgoing:
7439 if needsoutgoing:
7440 dest, dbranch, dother, outgoing = getoutgoing()
7440 dest, dbranch, dother, outgoing = getoutgoing()
7441 else:
7441 else:
7442 dest = dbranch = dother = outgoing = None
7442 dest = dbranch = dother = outgoing = None
7443
7443
7444 if opts.get('remote'):
7444 if opts.get('remote'):
7445 # Help pytype. --remote sets both `needsincoming` and `needsoutgoing`.
7445 # Help pytype. --remote sets both `needsincoming` and `needsoutgoing`.
7446 # The former always sets `sother` (or raises an exception if it can't);
7446 # The former always sets `sother` (or raises an exception if it can't);
7447 # the latter always sets `outgoing`.
7447 # the latter always sets `outgoing`.
7448 assert sother is not None
7448 assert sother is not None
7449 assert outgoing is not None
7449 assert outgoing is not None
7450
7450
7451 t = []
7451 t = []
7452 if incoming:
7452 if incoming:
7453 t.append(_(b'1 or more incoming'))
7453 t.append(_(b'1 or more incoming'))
7454 o = outgoing.missing
7454 o = outgoing.missing
7455 if o:
7455 if o:
7456 t.append(_(b'%d outgoing') % len(o))
7456 t.append(_(b'%d outgoing') % len(o))
7457 other = dother or sother
7457 other = dother or sother
7458 if b'bookmarks' in other.listkeys(b'namespaces'):
7458 if b'bookmarks' in other.listkeys(b'namespaces'):
7459 counts = bookmarks.summary(repo, other)
7459 counts = bookmarks.summary(repo, other)
7460 if counts[0] > 0:
7460 if counts[0] > 0:
7461 t.append(_(b'%d incoming bookmarks') % counts[0])
7461 t.append(_(b'%d incoming bookmarks') % counts[0])
7462 if counts[1] > 0:
7462 if counts[1] > 0:
7463 t.append(_(b'%d outgoing bookmarks') % counts[1])
7463 t.append(_(b'%d outgoing bookmarks') % counts[1])
7464
7464
7465 if t:
7465 if t:
7466 # i18n: column positioning for "hg summary"
7466 # i18n: column positioning for "hg summary"
7467 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7467 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7468 else:
7468 else:
7469 # i18n: column positioning for "hg summary"
7469 # i18n: column positioning for "hg summary"
7470 ui.status(_(b'remote: (synced)\n'))
7470 ui.status(_(b'remote: (synced)\n'))
7471
7471
7472 cmdutil.summaryremotehooks(
7472 cmdutil.summaryremotehooks(
7473 ui,
7473 ui,
7474 repo,
7474 repo,
7475 pycompat.byteskwargs(opts),
7475 pycompat.byteskwargs(opts),
7476 (
7476 (
7477 (source, sbranch, sother, commoninc),
7477 (source, sbranch, sother, commoninc),
7478 (dest, dbranch, dother, outgoing),
7478 (dest, dbranch, dother, outgoing),
7479 ),
7479 ),
7480 )
7480 )
7481
7481
7482
7482
7483 @command(
7483 @command(
7484 b'tag',
7484 b'tag',
7485 [
7485 [
7486 (b'f', b'force', None, _(b'force tag')),
7486 (b'f', b'force', None, _(b'force tag')),
7487 (b'l', b'local', None, _(b'make the tag local')),
7487 (b'l', b'local', None, _(b'make the tag local')),
7488 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7488 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7489 (b'', b'remove', None, _(b'remove a tag')),
7489 (b'', b'remove', None, _(b'remove a tag')),
7490 # -l/--local is already there, commitopts cannot be used
7490 # -l/--local is already there, commitopts cannot be used
7491 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7491 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7492 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7492 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7493 ]
7493 ]
7494 + commitopts2,
7494 + commitopts2,
7495 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7495 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7496 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7496 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7497 )
7497 )
7498 def tag(ui, repo, name1, *names, **opts):
7498 def tag(ui, repo, name1, *names, **opts):
7499 """add one or more tags for the current or given revision
7499 """add one or more tags for the current or given revision
7500
7500
7501 Name a particular revision using <name>.
7501 Name a particular revision using <name>.
7502
7502
7503 Tags are used to name particular revisions of the repository and are
7503 Tags are used to name particular revisions of the repository and are
7504 very useful to compare different revisions, to go back to significant
7504 very useful to compare different revisions, to go back to significant
7505 earlier versions or to mark branch points as releases, etc. Changing
7505 earlier versions or to mark branch points as releases, etc. Changing
7506 an existing tag is normally disallowed; use -f/--force to override.
7506 an existing tag is normally disallowed; use -f/--force to override.
7507
7507
7508 If no revision is given, the parent of the working directory is
7508 If no revision is given, the parent of the working directory is
7509 used.
7509 used.
7510
7510
7511 To facilitate version control, distribution, and merging of tags,
7511 To facilitate version control, distribution, and merging of tags,
7512 they are stored as a file named ".hgtags" which is managed similarly
7512 they are stored as a file named ".hgtags" which is managed similarly
7513 to other project files and can be hand-edited if necessary. This
7513 to other project files and can be hand-edited if necessary. This
7514 also means that tagging creates a new commit. The file
7514 also means that tagging creates a new commit. The file
7515 ".hg/localtags" is used for local tags (not shared among
7515 ".hg/localtags" is used for local tags (not shared among
7516 repositories).
7516 repositories).
7517
7517
7518 Tag commits are usually made at the head of a branch. If the parent
7518 Tag commits are usually made at the head of a branch. If the parent
7519 of the working directory is not a branch head, :hg:`tag` aborts; use
7519 of the working directory is not a branch head, :hg:`tag` aborts; use
7520 -f/--force to force the tag commit to be based on a non-head
7520 -f/--force to force the tag commit to be based on a non-head
7521 changeset.
7521 changeset.
7522
7522
7523 See :hg:`help dates` for a list of formats valid for -d/--date.
7523 See :hg:`help dates` for a list of formats valid for -d/--date.
7524
7524
7525 Since tag names have priority over branch names during revision
7525 Since tag names have priority over branch names during revision
7526 lookup, using an existing branch name as a tag name is discouraged.
7526 lookup, using an existing branch name as a tag name is discouraged.
7527
7527
7528 Returns 0 on success.
7528 Returns 0 on success.
7529 """
7529 """
7530 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7530 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7531
7531
7532 with repo.wlock(), repo.lock():
7532 with repo.wlock(), repo.lock():
7533 rev_ = b"."
7533 rev_ = b"."
7534 names = [t.strip() for t in (name1,) + names]
7534 names = [t.strip() for t in (name1,) + names]
7535 if len(names) != len(set(names)):
7535 if len(names) != len(set(names)):
7536 raise error.InputError(_(b'tag names must be unique'))
7536 raise error.InputError(_(b'tag names must be unique'))
7537 for n in names:
7537 for n in names:
7538 scmutil.checknewlabel(repo, n, b'tag')
7538 scmutil.checknewlabel(repo, n, b'tag')
7539 if not n:
7539 if not n:
7540 raise error.InputError(
7540 raise error.InputError(
7541 _(b'tag names cannot consist entirely of whitespace')
7541 _(b'tag names cannot consist entirely of whitespace')
7542 )
7542 )
7543 if opts.get('rev'):
7543 if opts.get('rev'):
7544 rev_ = opts['rev']
7544 rev_ = opts['rev']
7545 message = opts.get('message')
7545 message = opts.get('message')
7546 if opts.get('remove'):
7546 if opts.get('remove'):
7547 if opts.get('local'):
7547 if opts.get('local'):
7548 expectedtype = b'local'
7548 expectedtype = b'local'
7549 else:
7549 else:
7550 expectedtype = b'global'
7550 expectedtype = b'global'
7551
7551
7552 for n in names:
7552 for n in names:
7553 if repo.tagtype(n) == b'global':
7553 if repo.tagtype(n) == b'global':
7554 alltags = tagsmod.findglobaltags(ui, repo)
7554 alltags = tagsmod.findglobaltags(ui, repo)
7555 if alltags[n][0] == repo.nullid:
7555 if alltags[n][0] == repo.nullid:
7556 raise error.InputError(
7556 raise error.InputError(
7557 _(b"tag '%s' is already removed") % n
7557 _(b"tag '%s' is already removed") % n
7558 )
7558 )
7559 if not repo.tagtype(n):
7559 if not repo.tagtype(n):
7560 raise error.InputError(_(b"tag '%s' does not exist") % n)
7560 raise error.InputError(_(b"tag '%s' does not exist") % n)
7561 if repo.tagtype(n) != expectedtype:
7561 if repo.tagtype(n) != expectedtype:
7562 if expectedtype == b'global':
7562 if expectedtype == b'global':
7563 raise error.InputError(
7563 raise error.InputError(
7564 _(b"tag '%s' is not a global tag") % n
7564 _(b"tag '%s' is not a global tag") % n
7565 )
7565 )
7566 else:
7566 else:
7567 raise error.InputError(
7567 raise error.InputError(
7568 _(b"tag '%s' is not a local tag") % n
7568 _(b"tag '%s' is not a local tag") % n
7569 )
7569 )
7570 rev_ = b'null'
7570 rev_ = b'null'
7571 if not message:
7571 if not message:
7572 # we don't translate commit messages
7572 # we don't translate commit messages
7573 message = b'Removed tag %s' % b', '.join(names)
7573 message = b'Removed tag %s' % b', '.join(names)
7574 elif not opts.get('force'):
7574 elif not opts.get('force'):
7575 for n in names:
7575 for n in names:
7576 if n in repo.tags():
7576 if n in repo.tags():
7577 raise error.InputError(
7577 raise error.InputError(
7578 _(b"tag '%s' already exists (use -f to force)") % n
7578 _(b"tag '%s' already exists (use -f to force)") % n
7579 )
7579 )
7580 if not opts.get('local'):
7580 if not opts.get('local'):
7581 p1, p2 = repo.dirstate.parents()
7581 p1, p2 = repo.dirstate.parents()
7582 if p2 != repo.nullid:
7582 if p2 != repo.nullid:
7583 raise error.StateError(_(b'uncommitted merge'))
7583 raise error.StateError(_(b'uncommitted merge'))
7584 bheads = repo.branchheads()
7584 bheads = repo.branchheads()
7585 if not opts.get('force') and bheads and p1 not in bheads:
7585 if not opts.get('force') and bheads and p1 not in bheads:
7586 raise error.InputError(
7586 raise error.InputError(
7587 _(
7587 _(
7588 b'working directory is not at a branch head '
7588 b'working directory is not at a branch head '
7589 b'(use -f to force)'
7589 b'(use -f to force)'
7590 )
7590 )
7591 )
7591 )
7592 node = logcmdutil.revsingle(repo, rev_).node()
7592 node = logcmdutil.revsingle(repo, rev_).node()
7593
7593
7594 # don't allow tagging the null rev or the working directory
7594 # don't allow tagging the null rev or the working directory
7595 if node is None:
7595 if node is None:
7596 raise error.InputError(_(b"cannot tag working directory"))
7596 raise error.InputError(_(b"cannot tag working directory"))
7597 elif not opts.get('remove') and node == nullid:
7597 elif not opts.get('remove') and node == nullid:
7598 raise error.InputError(_(b"cannot tag null revision"))
7598 raise error.InputError(_(b"cannot tag null revision"))
7599
7599
7600 if not message:
7600 if not message:
7601 # we don't translate commit messages
7601 # we don't translate commit messages
7602 message = b'Added tag %s for changeset %s' % (
7602 message = b'Added tag %s for changeset %s' % (
7603 b', '.join(names),
7603 b', '.join(names),
7604 short(node),
7604 short(node),
7605 )
7605 )
7606
7606
7607 date = opts.get('date')
7607 date = opts.get('date')
7608 if date:
7608 if date:
7609 date = dateutil.parsedate(date)
7609 date = dateutil.parsedate(date)
7610
7610
7611 if opts.get('remove'):
7611 if opts.get('remove'):
7612 editform = b'tag.remove'
7612 editform = b'tag.remove'
7613 else:
7613 else:
7614 editform = b'tag.add'
7614 editform = b'tag.add'
7615 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7615 editor = cmdutil.getcommiteditor(editform=editform, **opts)
7616
7616
7617 tagsmod.tag(
7617 tagsmod.tag(
7618 repo,
7618 repo,
7619 names,
7619 names,
7620 node,
7620 node,
7621 message,
7621 message,
7622 opts.get('local'),
7622 opts.get('local'),
7623 opts.get('user'),
7623 opts.get('user'),
7624 date,
7624 date,
7625 editor=editor,
7625 editor=editor,
7626 )
7626 )
7627
7627
7628
7628
7629 @command(
7629 @command(
7630 b'tags',
7630 b'tags',
7631 formatteropts,
7631 formatteropts,
7632 b'',
7632 b'',
7633 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7633 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7634 intents={INTENT_READONLY},
7634 intents={INTENT_READONLY},
7635 )
7635 )
7636 def tags(ui, repo, **opts):
7636 def tags(ui, repo, **opts):
7637 """list repository tags
7637 """list repository tags
7638
7638
7639 This lists both regular and local tags. When the -v/--verbose
7639 This lists both regular and local tags. When the -v/--verbose
7640 switch is used, a third column "local" is printed for local tags.
7640 switch is used, a third column "local" is printed for local tags.
7641 When the -q/--quiet switch is used, only the tag name is printed.
7641 When the -q/--quiet switch is used, only the tag name is printed.
7642
7642
7643 .. container:: verbose
7643 .. container:: verbose
7644
7644
7645 Template:
7645 Template:
7646
7646
7647 The following keywords are supported in addition to the common template
7647 The following keywords are supported in addition to the common template
7648 keywords and functions such as ``{tag}``. See also
7648 keywords and functions such as ``{tag}``. See also
7649 :hg:`help templates`.
7649 :hg:`help templates`.
7650
7650
7651 :type: String. ``local`` for local tags.
7651 :type: String. ``local`` for local tags.
7652
7652
7653 Returns 0 on success.
7653 Returns 0 on success.
7654 """
7654 """
7655
7655
7656 ui.pager(b'tags')
7656 ui.pager(b'tags')
7657 fm = ui.formatter(b'tags', pycompat.byteskwargs(opts))
7657 fm = ui.formatter(b'tags', pycompat.byteskwargs(opts))
7658 hexfunc = fm.hexfunc
7658 hexfunc = fm.hexfunc
7659
7659
7660 for t, n in reversed(repo.tagslist()):
7660 for t, n in reversed(repo.tagslist()):
7661 hn = hexfunc(n)
7661 hn = hexfunc(n)
7662 label = b'tags.normal'
7662 label = b'tags.normal'
7663 tagtype = repo.tagtype(t)
7663 tagtype = repo.tagtype(t)
7664 if not tagtype or tagtype == b'global':
7664 if not tagtype or tagtype == b'global':
7665 tagtype = b''
7665 tagtype = b''
7666 else:
7666 else:
7667 label = b'tags.' + tagtype
7667 label = b'tags.' + tagtype
7668
7668
7669 fm.startitem()
7669 fm.startitem()
7670 fm.context(repo=repo)
7670 fm.context(repo=repo)
7671 fm.write(b'tag', b'%s', t, label=label)
7671 fm.write(b'tag', b'%s', t, label=label)
7672 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7672 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7673 fm.condwrite(
7673 fm.condwrite(
7674 not ui.quiet,
7674 not ui.quiet,
7675 b'rev node',
7675 b'rev node',
7676 fmt,
7676 fmt,
7677 repo.changelog.rev(n),
7677 repo.changelog.rev(n),
7678 hn,
7678 hn,
7679 label=label,
7679 label=label,
7680 )
7680 )
7681 fm.condwrite(
7681 fm.condwrite(
7682 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7682 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7683 )
7683 )
7684 fm.plain(b'\n')
7684 fm.plain(b'\n')
7685 fm.end()
7685 fm.end()
7686
7686
7687
7687
7688 @command(
7688 @command(
7689 b'tip',
7689 b'tip',
7690 [
7690 [
7691 (b'p', b'patch', None, _(b'show patch')),
7691 (b'p', b'patch', None, _(b'show patch')),
7692 (b'g', b'git', None, _(b'use git extended diff format')),
7692 (b'g', b'git', None, _(b'use git extended diff format')),
7693 ]
7693 ]
7694 + templateopts,
7694 + templateopts,
7695 _(b'[-p] [-g]'),
7695 _(b'[-p] [-g]'),
7696 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7696 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7697 )
7697 )
7698 def tip(ui, repo, **opts):
7698 def tip(ui, repo, **opts):
7699 """show the tip revision (DEPRECATED)
7699 """show the tip revision (DEPRECATED)
7700
7700
7701 The tip revision (usually just called the tip) is the changeset
7701 The tip revision (usually just called the tip) is the changeset
7702 most recently added to the repository (and therefore the most
7702 most recently added to the repository (and therefore the most
7703 recently changed head).
7703 recently changed head).
7704
7704
7705 If you have just made a commit, that commit will be the tip. If
7705 If you have just made a commit, that commit will be the tip. If
7706 you have just pulled changes from another repository, the tip of
7706 you have just pulled changes from another repository, the tip of
7707 that repository becomes the current tip. The "tip" tag is special
7707 that repository becomes the current tip. The "tip" tag is special
7708 and cannot be renamed or assigned to a different changeset.
7708 and cannot be renamed or assigned to a different changeset.
7709
7709
7710 This command is deprecated, please use :hg:`heads` instead.
7710 This command is deprecated, please use :hg:`heads` instead.
7711
7711
7712 Returns 0 on success.
7712 Returns 0 on success.
7713 """
7713 """
7714 opts = pycompat.byteskwargs(opts)
7714 opts = pycompat.byteskwargs(opts)
7715 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7715 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7716 displayer.show(repo[b'tip'])
7716 displayer.show(repo[b'tip'])
7717 displayer.close()
7717 displayer.close()
7718
7718
7719
7719
7720 @command(
7720 @command(
7721 b'unbundle',
7721 b'unbundle',
7722 [
7722 [
7723 (
7723 (
7724 b'u',
7724 b'u',
7725 b'update',
7725 b'update',
7726 None,
7726 None,
7727 _(b'update to new branch head if changesets were unbundled'),
7727 _(b'update to new branch head if changesets were unbundled'),
7728 )
7728 )
7729 ],
7729 ],
7730 _(b'[-u] FILE...'),
7730 _(b'[-u] FILE...'),
7731 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7731 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7732 )
7732 )
7733 def unbundle(ui, repo, fname1, *fnames, **opts):
7733 def unbundle(ui, repo, fname1, *fnames, _unbundle_source=b'unbundle', **opts):
7734 """apply one or more bundle files
7734 """apply one or more bundle files
7735
7735
7736 Apply one or more bundle files generated by :hg:`bundle`.
7736 Apply one or more bundle files generated by :hg:`bundle`.
7737
7737
7738 Returns 0 on success, 1 if an update has unresolved files.
7738 Returns 0 on success, 1 if an update has unresolved files.
7739 """
7739 """
7740 fnames = (fname1,) + fnames
7740 fnames = (fname1,) + fnames
7741
7741
7742 with repo.lock():
7742 with repo.lock():
7743 for fname in fnames:
7743 for fname in fnames:
7744 f = hg.openpath(ui, fname)
7744 f = hg.openpath(ui, fname)
7745 gen = exchange.readbundle(ui, f, fname)
7745 gen = exchange.readbundle(ui, f, fname)
7746 if isinstance(gen, streamclone.streamcloneapplier):
7746 if isinstance(gen, streamclone.streamcloneapplier):
7747 raise error.InputError(
7747 raise error.InputError(
7748 _(
7748 _(
7749 b'packed bundles cannot be applied with '
7749 b'packed bundles cannot be applied with '
7750 b'"hg unbundle"'
7750 b'"hg unbundle"'
7751 ),
7751 ),
7752 hint=_(b'use "hg debugapplystreamclonebundle"'),
7752 hint=_(b'use "hg debugapplystreamclonebundle"'),
7753 )
7753 )
7754 url = b'bundle:' + fname
7754 url = b'bundle:' + fname
7755 try:
7755 try:
7756 txnname = b'unbundle'
7756 txnname = b'unbundle'
7757 if not isinstance(gen, bundle2.unbundle20):
7757 if not isinstance(gen, bundle2.unbundle20):
7758 txnname = b'unbundle\n%s' % urlutil.hidepassword(url)
7758 txnname = b'unbundle\n%s' % urlutil.hidepassword(url)
7759 with repo.transaction(txnname) as tr:
7759 with repo.transaction(txnname) as tr:
7760 op = bundle2.applybundle(
7760 op = bundle2.applybundle(
7761 repo, gen, tr, source=b'unbundle', url=url
7761 repo,
7762 gen,
7763 tr,
7764 source=_unbundle_source, # used by debug::unbundle
7765 url=url,
7762 )
7766 )
7763 except error.BundleUnknownFeatureError as exc:
7767 except error.BundleUnknownFeatureError as exc:
7764 raise error.Abort(
7768 raise error.Abort(
7765 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7769 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7766 hint=_(
7770 hint=_(
7767 b"see https://mercurial-scm.org/"
7771 b"see https://mercurial-scm.org/"
7768 b"wiki/BundleFeature for more "
7772 b"wiki/BundleFeature for more "
7769 b"information"
7773 b"information"
7770 ),
7774 ),
7771 )
7775 )
7772 modheads = bundle2.combinechangegroupresults(op)
7776 modheads = bundle2.combinechangegroupresults(op)
7773
7777
7774 if postincoming(ui, repo, modheads, opts.get('update'), None, None):
7778 if postincoming(ui, repo, modheads, opts.get('update'), None, None):
7775 return 1
7779 return 1
7776 else:
7780 else:
7777 return 0
7781 return 0
7778
7782
7779
7783
7780 @command(
7784 @command(
7781 b'unshelve',
7785 b'unshelve',
7782 [
7786 [
7783 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7787 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7784 (
7788 (
7785 b'c',
7789 b'c',
7786 b'continue',
7790 b'continue',
7787 None,
7791 None,
7788 _(b'continue an incomplete unshelve operation'),
7792 _(b'continue an incomplete unshelve operation'),
7789 ),
7793 ),
7790 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7794 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7791 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7795 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7792 (
7796 (
7793 b'n',
7797 b'n',
7794 b'name',
7798 b'name',
7795 b'',
7799 b'',
7796 _(b'restore shelved change with given name'),
7800 _(b'restore shelved change with given name'),
7797 _(b'NAME'),
7801 _(b'NAME'),
7798 ),
7802 ),
7799 (b't', b'tool', b'', _(b'specify merge tool')),
7803 (b't', b'tool', b'', _(b'specify merge tool')),
7800 (
7804 (
7801 b'',
7805 b'',
7802 b'date',
7806 b'date',
7803 b'',
7807 b'',
7804 _(b'set date for temporary commits (DEPRECATED)'),
7808 _(b'set date for temporary commits (DEPRECATED)'),
7805 _(b'DATE'),
7809 _(b'DATE'),
7806 ),
7810 ),
7807 ],
7811 ],
7808 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7812 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7809 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7813 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7810 )
7814 )
7811 def unshelve(ui, repo, *shelved, **opts):
7815 def unshelve(ui, repo, *shelved, **opts):
7812 """restore a shelved change to the working directory
7816 """restore a shelved change to the working directory
7813
7817
7814 This command accepts an optional name of a shelved change to
7818 This command accepts an optional name of a shelved change to
7815 restore. If none is given, the most recent shelved change is used.
7819 restore. If none is given, the most recent shelved change is used.
7816
7820
7817 If a shelved change is applied successfully, the bundle that
7821 If a shelved change is applied successfully, the bundle that
7818 contains the shelved changes is moved to a backup location
7822 contains the shelved changes is moved to a backup location
7819 (.hg/shelve-backup).
7823 (.hg/shelve-backup).
7820
7824
7821 Since you can restore a shelved change on top of an arbitrary
7825 Since you can restore a shelved change on top of an arbitrary
7822 commit, it is possible that unshelving will result in a conflict
7826 commit, it is possible that unshelving will result in a conflict
7823 between your changes and the commits you are unshelving onto. If
7827 between your changes and the commits you are unshelving onto. If
7824 this occurs, you must resolve the conflict, then use
7828 this occurs, you must resolve the conflict, then use
7825 ``--continue`` to complete the unshelve operation. (The bundle
7829 ``--continue`` to complete the unshelve operation. (The bundle
7826 will not be moved until you successfully complete the unshelve.)
7830 will not be moved until you successfully complete the unshelve.)
7827
7831
7828 (Alternatively, you can use ``--abort`` to abandon an unshelve
7832 (Alternatively, you can use ``--abort`` to abandon an unshelve
7829 that causes a conflict. This reverts the unshelved changes, and
7833 that causes a conflict. This reverts the unshelved changes, and
7830 leaves the bundle in place.)
7834 leaves the bundle in place.)
7831
7835
7832 If bare shelved change (without interactive, include and exclude
7836 If bare shelved change (without interactive, include and exclude
7833 option) was done on newly created branch it would restore branch
7837 option) was done on newly created branch it would restore branch
7834 information to the working directory.
7838 information to the working directory.
7835
7839
7836 After a successful unshelve, the shelved changes are stored in a
7840 After a successful unshelve, the shelved changes are stored in a
7837 backup directory. Only the N most recent backups are kept. N
7841 backup directory. Only the N most recent backups are kept. N
7838 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7842 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7839 configuration option.
7843 configuration option.
7840
7844
7841 .. container:: verbose
7845 .. container:: verbose
7842
7846
7843 Timestamp in seconds is used to decide order of backups. More
7847 Timestamp in seconds is used to decide order of backups. More
7844 than ``maxbackups`` backups are kept, if same timestamp
7848 than ``maxbackups`` backups are kept, if same timestamp
7845 prevents from deciding exact order of them, for safety.
7849 prevents from deciding exact order of them, for safety.
7846
7850
7847 Selected changes can be unshelved with ``--interactive`` flag.
7851 Selected changes can be unshelved with ``--interactive`` flag.
7848 The working directory is updated with the selected changes, and
7852 The working directory is updated with the selected changes, and
7849 only the unselected changes remain shelved.
7853 only the unselected changes remain shelved.
7850 Note: The whole shelve is applied to working directory first before
7854 Note: The whole shelve is applied to working directory first before
7851 running interactively. So, this will bring up all the conflicts between
7855 running interactively. So, this will bring up all the conflicts between
7852 working directory and the shelve, irrespective of which changes will be
7856 working directory and the shelve, irrespective of which changes will be
7853 unshelved.
7857 unshelved.
7854 """
7858 """
7855 with repo.wlock():
7859 with repo.wlock():
7856 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7860 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7857
7861
7858
7862
7859 statemod.addunfinished(
7863 statemod.addunfinished(
7860 b'unshelve',
7864 b'unshelve',
7861 fname=b'shelvedstate',
7865 fname=b'shelvedstate',
7862 continueflag=True,
7866 continueflag=True,
7863 abortfunc=shelvemod.hgabortunshelve,
7867 abortfunc=shelvemod.hgabortunshelve,
7864 continuefunc=shelvemod.hgcontinueunshelve,
7868 continuefunc=shelvemod.hgcontinueunshelve,
7865 cmdmsg=_(b'unshelve already in progress'),
7869 cmdmsg=_(b'unshelve already in progress'),
7866 )
7870 )
7867
7871
7868
7872
7869 @command(
7873 @command(
7870 b'update|up|checkout|co',
7874 b'update|up|checkout|co',
7871 [
7875 [
7872 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7876 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7873 (b'c', b'check', None, _(b'require clean working directory')),
7877 (b'c', b'check', None, _(b'require clean working directory')),
7874 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7878 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7875 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7879 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7876 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7880 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7877 ]
7881 ]
7878 + mergetoolopts,
7882 + mergetoolopts,
7879 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7883 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7880 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7884 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7881 helpbasic=True,
7885 helpbasic=True,
7882 )
7886 )
7883 def update(ui, repo, node=None, **opts):
7887 def update(ui, repo, node=None, **opts):
7884 """update working directory (or switch revisions)
7888 """update working directory (or switch revisions)
7885
7889
7886 Update the repository's working directory to the specified
7890 Update the repository's working directory to the specified
7887 changeset. If no changeset is specified, update to the tip of the
7891 changeset. If no changeset is specified, update to the tip of the
7888 current named branch and move the active bookmark (see :hg:`help
7892 current named branch and move the active bookmark (see :hg:`help
7889 bookmarks`).
7893 bookmarks`).
7890
7894
7891 Update sets the working directory's parent revision to the specified
7895 Update sets the working directory's parent revision to the specified
7892 changeset (see :hg:`help parents`).
7896 changeset (see :hg:`help parents`).
7893
7897
7894 If the changeset is not a descendant or ancestor of the working
7898 If the changeset is not a descendant or ancestor of the working
7895 directory's parent and there are uncommitted changes, the update is
7899 directory's parent and there are uncommitted changes, the update is
7896 aborted. With the -c/--check option, the working directory is checked
7900 aborted. With the -c/--check option, the working directory is checked
7897 for uncommitted changes; if none are found, the working directory is
7901 for uncommitted changes; if none are found, the working directory is
7898 updated to the specified changeset.
7902 updated to the specified changeset.
7899
7903
7900 .. container:: verbose
7904 .. container:: verbose
7901
7905
7902 The -C/--clean, -c/--check, and -m/--merge options control what
7906 The -C/--clean, -c/--check, and -m/--merge options control what
7903 happens if the working directory contains uncommitted changes.
7907 happens if the working directory contains uncommitted changes.
7904 At most of one of them can be specified.
7908 At most of one of them can be specified.
7905
7909
7906 1. If no option is specified, and if
7910 1. If no option is specified, and if
7907 the requested changeset is an ancestor or descendant of
7911 the requested changeset is an ancestor or descendant of
7908 the working directory's parent, the uncommitted changes
7912 the working directory's parent, the uncommitted changes
7909 are merged into the requested changeset and the merged
7913 are merged into the requested changeset and the merged
7910 result is left uncommitted. If the requested changeset is
7914 result is left uncommitted. If the requested changeset is
7911 not an ancestor or descendant (that is, it is on another
7915 not an ancestor or descendant (that is, it is on another
7912 branch), the update is aborted and the uncommitted changes
7916 branch), the update is aborted and the uncommitted changes
7913 are preserved.
7917 are preserved.
7914
7918
7915 2. With the -m/--merge option, the update is allowed even if the
7919 2. With the -m/--merge option, the update is allowed even if the
7916 requested changeset is not an ancestor or descendant of
7920 requested changeset is not an ancestor or descendant of
7917 the working directory's parent.
7921 the working directory's parent.
7918
7922
7919 3. With the -c/--check option, the update is aborted and the
7923 3. With the -c/--check option, the update is aborted and the
7920 uncommitted changes are preserved.
7924 uncommitted changes are preserved.
7921
7925
7922 4. With the -C/--clean option, uncommitted changes are discarded and
7926 4. With the -C/--clean option, uncommitted changes are discarded and
7923 the working directory is updated to the requested changeset.
7927 the working directory is updated to the requested changeset.
7924
7928
7925 To cancel an uncommitted merge (and lose your changes), use
7929 To cancel an uncommitted merge (and lose your changes), use
7926 :hg:`merge --abort`.
7930 :hg:`merge --abort`.
7927
7931
7928 Use null as the changeset to remove the working directory (like
7932 Use null as the changeset to remove the working directory (like
7929 :hg:`clone -U`).
7933 :hg:`clone -U`).
7930
7934
7931 If you want to revert just one file to an older revision, use
7935 If you want to revert just one file to an older revision, use
7932 :hg:`revert [-r REV] NAME`.
7936 :hg:`revert [-r REV] NAME`.
7933
7937
7934 See :hg:`help dates` for a list of formats valid for -d/--date.
7938 See :hg:`help dates` for a list of formats valid for -d/--date.
7935
7939
7936 Returns 0 on success, 1 if there are unresolved files.
7940 Returns 0 on success, 1 if there are unresolved files.
7937 """
7941 """
7938 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7942 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7939 rev = opts.get('rev')
7943 rev = opts.get('rev')
7940 date = opts.get('date')
7944 date = opts.get('date')
7941 clean = opts.get('clean')
7945 clean = opts.get('clean')
7942 check = opts.get('check')
7946 check = opts.get('check')
7943 merge = opts.get('merge')
7947 merge = opts.get('merge')
7944 if rev and node:
7948 if rev and node:
7945 raise error.InputError(_(b"please specify just one revision"))
7949 raise error.InputError(_(b"please specify just one revision"))
7946
7950
7947 if ui.configbool(b'commands', b'update.requiredest'):
7951 if ui.configbool(b'commands', b'update.requiredest'):
7948 if not node and not rev and not date:
7952 if not node and not rev and not date:
7949 raise error.InputError(
7953 raise error.InputError(
7950 _(b'you must specify a destination'),
7954 _(b'you must specify a destination'),
7951 hint=_(b'for example: hg update ".::"'),
7955 hint=_(b'for example: hg update ".::"'),
7952 )
7956 )
7953
7957
7954 if rev is None or rev == b'':
7958 if rev is None or rev == b'':
7955 rev = node
7959 rev = node
7956
7960
7957 if date and rev is not None:
7961 if date and rev is not None:
7958 raise error.InputError(_(b"you can't specify a revision and a date"))
7962 raise error.InputError(_(b"you can't specify a revision and a date"))
7959
7963
7960 updatecheck = None
7964 updatecheck = None
7961 if check or merge is not None and not merge:
7965 if check or merge is not None and not merge:
7962 updatecheck = b'abort'
7966 updatecheck = b'abort'
7963 elif merge or check is not None and not check:
7967 elif merge or check is not None and not check:
7964 updatecheck = b'none'
7968 updatecheck = b'none'
7965
7969
7966 with repo.wlock():
7970 with repo.wlock():
7967 cmdutil.clearunfinished(repo)
7971 cmdutil.clearunfinished(repo)
7968 if date:
7972 if date:
7969 rev = cmdutil.finddate(ui, repo, date)
7973 rev = cmdutil.finddate(ui, repo, date)
7970
7974
7971 # if we defined a bookmark, we have to remember the original name
7975 # if we defined a bookmark, we have to remember the original name
7972 brev = rev
7976 brev = rev
7973 if rev:
7977 if rev:
7974 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7978 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7975 ctx = logcmdutil.revsingle(repo, rev, default=None)
7979 ctx = logcmdutil.revsingle(repo, rev, default=None)
7976 rev = ctx.rev()
7980 rev = ctx.rev()
7977 hidden = ctx.hidden()
7981 hidden = ctx.hidden()
7978 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7982 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7979 with ui.configoverride(overrides, b'update'):
7983 with ui.configoverride(overrides, b'update'):
7980 ret = hg.updatetotally(
7984 ret = hg.updatetotally(
7981 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7985 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7982 )
7986 )
7983 if hidden:
7987 if hidden:
7984 ctxstr = ctx.hex()[:12]
7988 ctxstr = ctx.hex()[:12]
7985 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7989 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7986
7990
7987 if ctx.obsolete():
7991 if ctx.obsolete():
7988 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7992 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7989 ui.warn(b"(%s)\n" % obsfatemsg)
7993 ui.warn(b"(%s)\n" % obsfatemsg)
7990 return ret
7994 return ret
7991
7995
7992
7996
7993 @command(
7997 @command(
7994 b'verify',
7998 b'verify',
7995 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7999 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7996 helpcategory=command.CATEGORY_MAINTENANCE,
8000 helpcategory=command.CATEGORY_MAINTENANCE,
7997 )
8001 )
7998 def verify(ui, repo, **opts):
8002 def verify(ui, repo, **opts):
7999 """verify the integrity of the repository
8003 """verify the integrity of the repository
8000
8004
8001 Verify the integrity of the current repository.
8005 Verify the integrity of the current repository.
8002
8006
8003 This will perform an extensive check of the repository's
8007 This will perform an extensive check of the repository's
8004 integrity, validating the hashes and checksums of each entry in
8008 integrity, validating the hashes and checksums of each entry in
8005 the changelog, manifest, and tracked files, as well as the
8009 the changelog, manifest, and tracked files, as well as the
8006 integrity of their crosslinks and indices.
8010 integrity of their crosslinks and indices.
8007
8011
8008 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
8012 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
8009 for more information about recovery from corruption of the
8013 for more information about recovery from corruption of the
8010 repository.
8014 repository.
8011
8015
8012 For an alternative UI with a lot more control over the verification
8016 For an alternative UI with a lot more control over the verification
8013 process and better error reporting, try `hg help admin::verify`.
8017 process and better error reporting, try `hg help admin::verify`.
8014
8018
8015 Returns 0 on success, 1 if errors are encountered.
8019 Returns 0 on success, 1 if errors are encountered.
8016 """
8020 """
8017 level = None
8021 level = None
8018 if opts['full']:
8022 if opts['full']:
8019 level = verifymod.VERIFY_FULL
8023 level = verifymod.VERIFY_FULL
8020 return hg.verify(repo, level)
8024 return hg.verify(repo, level)
8021
8025
8022
8026
8023 @command(
8027 @command(
8024 b'version',
8028 b'version',
8025 [] + formatteropts,
8029 [] + formatteropts,
8026 helpcategory=command.CATEGORY_HELP,
8030 helpcategory=command.CATEGORY_HELP,
8027 norepo=True,
8031 norepo=True,
8028 intents={INTENT_READONLY},
8032 intents={INTENT_READONLY},
8029 )
8033 )
8030 def version_(ui, **opts):
8034 def version_(ui, **opts):
8031 """output version and copyright information
8035 """output version and copyright information
8032
8036
8033 .. container:: verbose
8037 .. container:: verbose
8034
8038
8035 Template:
8039 Template:
8036
8040
8037 The following keywords are supported. See also :hg:`help templates`.
8041 The following keywords are supported. See also :hg:`help templates`.
8038
8042
8039 :extensions: List of extensions.
8043 :extensions: List of extensions.
8040 :ver: String. Version number.
8044 :ver: String. Version number.
8041
8045
8042 And each entry of ``{extensions}`` provides the following sub-keywords
8046 And each entry of ``{extensions}`` provides the following sub-keywords
8043 in addition to ``{ver}``.
8047 in addition to ``{ver}``.
8044
8048
8045 :bundled: Boolean. True if included in the release.
8049 :bundled: Boolean. True if included in the release.
8046 :name: String. Extension name.
8050 :name: String. Extension name.
8047 """
8051 """
8048 if ui.verbose:
8052 if ui.verbose:
8049 ui.pager(b'version')
8053 ui.pager(b'version')
8050 fm = ui.formatter(b"version", pycompat.byteskwargs(opts))
8054 fm = ui.formatter(b"version", pycompat.byteskwargs(opts))
8051 fm.startitem()
8055 fm.startitem()
8052 fm.write(
8056 fm.write(
8053 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
8057 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
8054 )
8058 )
8055 license = _(
8059 license = _(
8056 b"(see https://mercurial-scm.org for more information)\n"
8060 b"(see https://mercurial-scm.org for more information)\n"
8057 b"\nCopyright (C) 2005-2023 Olivia Mackall and others\n"
8061 b"\nCopyright (C) 2005-2023 Olivia Mackall and others\n"
8058 b"This is free software; see the source for copying conditions. "
8062 b"This is free software; see the source for copying conditions. "
8059 b"There is NO\nwarranty; "
8063 b"There is NO\nwarranty; "
8060 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
8064 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
8061 )
8065 )
8062 if not ui.quiet:
8066 if not ui.quiet:
8063 fm.plain(license)
8067 fm.plain(license)
8064
8068
8065 if ui.verbose:
8069 if ui.verbose:
8066 fm.plain(_(b"\nEnabled extensions:\n\n"))
8070 fm.plain(_(b"\nEnabled extensions:\n\n"))
8067 # format names and versions into columns
8071 # format names and versions into columns
8068 names = []
8072 names = []
8069 vers = []
8073 vers = []
8070 isinternals = []
8074 isinternals = []
8071 for name, module in sorted(extensions.extensions()):
8075 for name, module in sorted(extensions.extensions()):
8072 names.append(name)
8076 names.append(name)
8073 vers.append(extensions.moduleversion(module) or None)
8077 vers.append(extensions.moduleversion(module) or None)
8074 isinternals.append(extensions.ismoduleinternal(module))
8078 isinternals.append(extensions.ismoduleinternal(module))
8075 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
8079 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
8076 if names:
8080 if names:
8077 namefmt = b" %%-%ds " % max(len(n) for n in names)
8081 namefmt = b" %%-%ds " % max(len(n) for n in names)
8078 places = [_(b"external"), _(b"internal")]
8082 places = [_(b"external"), _(b"internal")]
8079 for n, v, p in zip(names, vers, isinternals):
8083 for n, v, p in zip(names, vers, isinternals):
8080 fn.startitem()
8084 fn.startitem()
8081 fn.condwrite(ui.verbose, b"name", namefmt, n)
8085 fn.condwrite(ui.verbose, b"name", namefmt, n)
8082 if ui.verbose:
8086 if ui.verbose:
8083 fn.plain(b"%s " % places[p])
8087 fn.plain(b"%s " % places[p])
8084 fn.data(bundled=p)
8088 fn.data(bundled=p)
8085 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
8089 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
8086 if ui.verbose:
8090 if ui.verbose:
8087 fn.plain(b"\n")
8091 fn.plain(b"\n")
8088 fn.end()
8092 fn.end()
8089 fm.end()
8093 fm.end()
8090
8094
8091
8095
8092 def loadcmdtable(ui, name, cmdtable):
8096 def loadcmdtable(ui, name, cmdtable):
8093 """Load command functions from specified cmdtable"""
8097 """Load command functions from specified cmdtable"""
8094 overrides = [cmd for cmd in cmdtable if cmd in table]
8098 overrides = [cmd for cmd in cmdtable if cmd in table]
8095 if overrides:
8099 if overrides:
8096 ui.warn(
8100 ui.warn(
8097 _(b"extension '%s' overrides commands: %s\n")
8101 _(b"extension '%s' overrides commands: %s\n")
8098 % (name, b" ".join(overrides))
8102 % (name, b" ".join(overrides))
8099 )
8103 )
8100 table.update(cmdtable)
8104 table.update(cmdtable)
@@ -1,4751 +1,4775 b''
1 # debugcommands.py - command processing for debug* commands
1 # debugcommands.py - command processing for debug* commands
2 #
2 #
3 # Copyright 2005-2016 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2016 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 binascii
9 import binascii
10 import codecs
10 import codecs
11 import collections
11 import collections
12 import contextlib
12 import contextlib
13 import difflib
13 import difflib
14 import errno
14 import errno
15 import glob
15 import glob
16 import operator
16 import operator
17 import os
17 import os
18 import platform
18 import platform
19 import random
19 import random
20 import re
20 import re
21 import socket
21 import socket
22 import ssl
22 import ssl
23 import stat
23 import stat
24 import subprocess
24 import subprocess
25 import sys
25 import sys
26 import time
26 import time
27
27
28 from .i18n import _
28 from .i18n import _
29 from .node import (
29 from .node import (
30 bin,
30 bin,
31 hex,
31 hex,
32 nullrev,
32 nullrev,
33 short,
33 short,
34 )
34 )
35 from .pycompat import (
35 from .pycompat import (
36 open,
36 open,
37 )
37 )
38 from . import (
38 from . import (
39 bundle2,
39 bundle2,
40 bundlerepo,
40 bundlerepo,
41 changegroup,
41 changegroup,
42 cmdutil,
42 cmdutil,
43 color,
43 color,
44 context,
44 context,
45 copies,
45 copies,
46 dagparser,
46 dagparser,
47 dirstateutils,
47 dirstateutils,
48 encoding,
48 encoding,
49 error,
49 error,
50 exchange,
50 exchange,
51 extensions,
51 extensions,
52 filelog,
52 filelog,
53 filemerge,
53 filemerge,
54 filesetlang,
54 filesetlang,
55 formatter,
55 formatter,
56 hg,
56 hg,
57 httppeer,
57 httppeer,
58 localrepo,
58 localrepo,
59 lock as lockmod,
59 lock as lockmod,
60 logcmdutil,
60 logcmdutil,
61 manifest,
61 manifest,
62 mergestate as mergestatemod,
62 mergestate as mergestatemod,
63 metadata,
63 metadata,
64 obsolete,
64 obsolete,
65 obsutil,
65 obsutil,
66 pathutil,
66 pathutil,
67 phases,
67 phases,
68 policy,
68 policy,
69 pvec,
69 pvec,
70 pycompat,
70 pycompat,
71 registrar,
71 registrar,
72 repair,
72 repair,
73 repoview,
73 repoview,
74 requirements,
74 requirements,
75 revlog,
75 revlog,
76 revset,
76 revset,
77 revsetlang,
77 revsetlang,
78 scmutil,
78 scmutil,
79 setdiscovery,
79 setdiscovery,
80 simplemerge,
80 simplemerge,
81 sshpeer,
81 sshpeer,
82 sslutil,
82 sslutil,
83 streamclone,
83 streamclone,
84 strip,
84 strip,
85 tags as tagsmod,
85 tags as tagsmod,
86 templater,
86 templater,
87 treediscovery,
87 treediscovery,
88 upgrade,
88 upgrade,
89 url as urlmod,
89 url as urlmod,
90 util,
90 util,
91 verify,
91 verify,
92 vfs as vfsmod,
92 vfs as vfsmod,
93 wireprotoframing,
93 wireprotoframing,
94 wireprotoserver,
94 wireprotoserver,
95 )
95 )
96 from .interfaces import repository
96 from .interfaces import repository
97 from .stabletailgraph import stabletailsort
97 from .stabletailgraph import stabletailsort
98 from .utils import (
98 from .utils import (
99 cborutil,
99 cborutil,
100 compression,
100 compression,
101 dateutil,
101 dateutil,
102 procutil,
102 procutil,
103 stringutil,
103 stringutil,
104 urlutil,
104 urlutil,
105 )
105 )
106
106
107 from .revlogutils import (
107 from .revlogutils import (
108 debug as revlog_debug,
108 debug as revlog_debug,
109 nodemap,
109 nodemap,
110 rewrite,
110 rewrite,
111 sidedata,
111 sidedata,
112 )
112 )
113
113
114 release = lockmod.release
114 release = lockmod.release
115
115
116 table = {}
116 table = {}
117 table.update(strip.command._table)
117 table.update(strip.command._table)
118 command = registrar.command(table)
118 command = registrar.command(table)
119
119
120
120
121 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
121 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
122 def debugancestor(ui, repo, *args):
122 def debugancestor(ui, repo, *args):
123 """find the ancestor revision of two revisions in a given index"""
123 """find the ancestor revision of two revisions in a given index"""
124 if len(args) == 3:
124 if len(args) == 3:
125 index, rev1, rev2 = args
125 index, rev1, rev2 = args
126 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
126 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
127 lookup = r.lookup
127 lookup = r.lookup
128 elif len(args) == 2:
128 elif len(args) == 2:
129 if not repo:
129 if not repo:
130 raise error.Abort(
130 raise error.Abort(
131 _(b'there is no Mercurial repository here (.hg not found)')
131 _(b'there is no Mercurial repository here (.hg not found)')
132 )
132 )
133 rev1, rev2 = args
133 rev1, rev2 = args
134 r = repo.changelog
134 r = repo.changelog
135 lookup = repo.lookup
135 lookup = repo.lookup
136 else:
136 else:
137 raise error.Abort(_(b'either two or three arguments required'))
137 raise error.Abort(_(b'either two or three arguments required'))
138 a = r.ancestor(lookup(rev1), lookup(rev2))
138 a = r.ancestor(lookup(rev1), lookup(rev2))
139 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
139 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
140
140
141
141
142 @command(b'debugantivirusrunning', [])
142 @command(b'debugantivirusrunning', [])
143 def debugantivirusrunning(ui, repo):
143 def debugantivirusrunning(ui, repo):
144 """attempt to trigger an antivirus scanner to see if one is active"""
144 """attempt to trigger an antivirus scanner to see if one is active"""
145 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
145 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
146 f.write(
146 f.write(
147 util.b85decode(
147 util.b85decode(
148 # This is a base85-armored version of the EICAR test file. See
148 # This is a base85-armored version of the EICAR test file. See
149 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
149 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
150 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
150 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
151 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
151 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
152 )
152 )
153 )
153 )
154 # Give an AV engine time to scan the file.
154 # Give an AV engine time to scan the file.
155 time.sleep(2)
155 time.sleep(2)
156 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
156 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
157
157
158
158
159 @command(b'debugapplystreamclonebundle', [], b'FILE')
159 @command(b'debugapplystreamclonebundle', [], b'FILE')
160 def debugapplystreamclonebundle(ui, repo, fname):
160 def debugapplystreamclonebundle(ui, repo, fname):
161 """apply a stream clone bundle file"""
161 """apply a stream clone bundle file"""
162 f = hg.openpath(ui, fname)
162 f = hg.openpath(ui, fname)
163 gen = exchange.readbundle(ui, f, fname)
163 gen = exchange.readbundle(ui, f, fname)
164 gen.apply(repo)
164 gen.apply(repo)
165
165
166
166
167 @command(
167 @command(
168 b'debugbuilddag',
168 b'debugbuilddag',
169 [
169 [
170 (
170 (
171 b'm',
171 b'm',
172 b'mergeable-file',
172 b'mergeable-file',
173 None,
173 None,
174 _(b'add single file mergeable changes'),
174 _(b'add single file mergeable changes'),
175 ),
175 ),
176 (
176 (
177 b'o',
177 b'o',
178 b'overwritten-file',
178 b'overwritten-file',
179 None,
179 None,
180 _(b'add single file all revs overwrite'),
180 _(b'add single file all revs overwrite'),
181 ),
181 ),
182 (b'n', b'new-file', None, _(b'add new file at each rev')),
182 (b'n', b'new-file', None, _(b'add new file at each rev')),
183 (
183 (
184 b'',
184 b'',
185 b'from-existing',
185 b'from-existing',
186 None,
186 None,
187 _(b'continue from a non-empty repository'),
187 _(b'continue from a non-empty repository'),
188 ),
188 ),
189 ],
189 ],
190 _(b'[OPTION]... [TEXT]'),
190 _(b'[OPTION]... [TEXT]'),
191 )
191 )
192 def debugbuilddag(
192 def debugbuilddag(
193 ui,
193 ui,
194 repo,
194 repo,
195 text=None,
195 text=None,
196 mergeable_file=False,
196 mergeable_file=False,
197 overwritten_file=False,
197 overwritten_file=False,
198 new_file=False,
198 new_file=False,
199 from_existing=False,
199 from_existing=False,
200 ):
200 ):
201 """builds a repo with a given DAG from scratch in the current empty repo
201 """builds a repo with a given DAG from scratch in the current empty repo
202
202
203 The description of the DAG is read from stdin if not given on the
203 The description of the DAG is read from stdin if not given on the
204 command line.
204 command line.
205
205
206 Elements:
206 Elements:
207
207
208 - "+n" is a linear run of n nodes based on the current default parent
208 - "+n" is a linear run of n nodes based on the current default parent
209 - "." is a single node based on the current default parent
209 - "." is a single node based on the current default parent
210 - "$" resets the default parent to null (implied at the start);
210 - "$" resets the default parent to null (implied at the start);
211 otherwise the default parent is always the last node created
211 otherwise the default parent is always the last node created
212 - "<p" sets the default parent to the backref p
212 - "<p" sets the default parent to the backref p
213 - "*p" is a fork at parent p, which is a backref
213 - "*p" is a fork at parent p, which is a backref
214 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
214 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
215 - "/p2" is a merge of the preceding node and p2
215 - "/p2" is a merge of the preceding node and p2
216 - ":tag" defines a local tag for the preceding node
216 - ":tag" defines a local tag for the preceding node
217 - "@branch" sets the named branch for subsequent nodes
217 - "@branch" sets the named branch for subsequent nodes
218 - "#...\\n" is a comment up to the end of the line
218 - "#...\\n" is a comment up to the end of the line
219
219
220 Whitespace between the above elements is ignored.
220 Whitespace between the above elements is ignored.
221
221
222 A backref is either
222 A backref is either
223
223
224 - a number n, which references the node curr-n, where curr is the current
224 - a number n, which references the node curr-n, where curr is the current
225 node, or
225 node, or
226 - the name of a local tag you placed earlier using ":tag", or
226 - the name of a local tag you placed earlier using ":tag", or
227 - empty to denote the default parent.
227 - empty to denote the default parent.
228
228
229 All string valued-elements are either strictly alphanumeric, or must
229 All string valued-elements are either strictly alphanumeric, or must
230 be enclosed in double quotes ("..."), with "\\" as escape character.
230 be enclosed in double quotes ("..."), with "\\" as escape character.
231 """
231 """
232
232
233 if text is None:
233 if text is None:
234 ui.status(_(b"reading DAG from stdin\n"))
234 ui.status(_(b"reading DAG from stdin\n"))
235 text = ui.fin.read()
235 text = ui.fin.read()
236
236
237 cl = repo.changelog
237 cl = repo.changelog
238 if len(cl) > 0 and not from_existing:
238 if len(cl) > 0 and not from_existing:
239 raise error.Abort(_(b'repository is not empty'))
239 raise error.Abort(_(b'repository is not empty'))
240
240
241 # determine number of revs in DAG
241 # determine number of revs in DAG
242 total = 0
242 total = 0
243 for type, data in dagparser.parsedag(text):
243 for type, data in dagparser.parsedag(text):
244 if type == b'n':
244 if type == b'n':
245 total += 1
245 total += 1
246
246
247 if mergeable_file:
247 if mergeable_file:
248 linesperrev = 2
248 linesperrev = 2
249 # make a file with k lines per rev
249 # make a file with k lines per rev
250 initialmergedlines = [b'%d' % i for i in range(0, total * linesperrev)]
250 initialmergedlines = [b'%d' % i for i in range(0, total * linesperrev)]
251 initialmergedlines.append(b"")
251 initialmergedlines.append(b"")
252
252
253 tags = []
253 tags = []
254 progress = ui.makeprogress(
254 progress = ui.makeprogress(
255 _(b'building'), unit=_(b'revisions'), total=total
255 _(b'building'), unit=_(b'revisions'), total=total
256 )
256 )
257 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
257 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
258 at = -1
258 at = -1
259 atbranch = b'default'
259 atbranch = b'default'
260 nodeids = []
260 nodeids = []
261 id = 0
261 id = 0
262 progress.update(id)
262 progress.update(id)
263 for type, data in dagparser.parsedag(text):
263 for type, data in dagparser.parsedag(text):
264 if type == b'n':
264 if type == b'n':
265 ui.note((b'node %s\n' % pycompat.bytestr(data)))
265 ui.note((b'node %s\n' % pycompat.bytestr(data)))
266 id, ps = data
266 id, ps = data
267
267
268 files = []
268 files = []
269 filecontent = {}
269 filecontent = {}
270
270
271 p2 = None
271 p2 = None
272 if mergeable_file:
272 if mergeable_file:
273 fn = b"mf"
273 fn = b"mf"
274 p1 = repo[ps[0]]
274 p1 = repo[ps[0]]
275 if len(ps) > 1:
275 if len(ps) > 1:
276 p2 = repo[ps[1]]
276 p2 = repo[ps[1]]
277 pa = p1.ancestor(p2)
277 pa = p1.ancestor(p2)
278 base, local, other = [
278 base, local, other = [
279 x[fn].data() for x in (pa, p1, p2)
279 x[fn].data() for x in (pa, p1, p2)
280 ]
280 ]
281 m3 = simplemerge.Merge3Text(base, local, other)
281 m3 = simplemerge.Merge3Text(base, local, other)
282 ml = [
282 ml = [
283 l.strip()
283 l.strip()
284 for l in simplemerge.render_minimized(m3)[0]
284 for l in simplemerge.render_minimized(m3)[0]
285 ]
285 ]
286 ml.append(b"")
286 ml.append(b"")
287 elif at > 0:
287 elif at > 0:
288 ml = p1[fn].data().split(b"\n")
288 ml = p1[fn].data().split(b"\n")
289 else:
289 else:
290 ml = initialmergedlines
290 ml = initialmergedlines
291 ml[id * linesperrev] += b" r%i" % id
291 ml[id * linesperrev] += b" r%i" % id
292 mergedtext = b"\n".join(ml)
292 mergedtext = b"\n".join(ml)
293 files.append(fn)
293 files.append(fn)
294 filecontent[fn] = mergedtext
294 filecontent[fn] = mergedtext
295
295
296 if overwritten_file:
296 if overwritten_file:
297 fn = b"of"
297 fn = b"of"
298 files.append(fn)
298 files.append(fn)
299 filecontent[fn] = b"r%i\n" % id
299 filecontent[fn] = b"r%i\n" % id
300
300
301 if new_file:
301 if new_file:
302 fn = b"nf%i" % id
302 fn = b"nf%i" % id
303 files.append(fn)
303 files.append(fn)
304 filecontent[fn] = b"r%i\n" % id
304 filecontent[fn] = b"r%i\n" % id
305 if len(ps) > 1:
305 if len(ps) > 1:
306 if not p2:
306 if not p2:
307 p2 = repo[ps[1]]
307 p2 = repo[ps[1]]
308 for fn in p2:
308 for fn in p2:
309 if fn.startswith(b"nf"):
309 if fn.startswith(b"nf"):
310 files.append(fn)
310 files.append(fn)
311 filecontent[fn] = p2[fn].data()
311 filecontent[fn] = p2[fn].data()
312
312
313 def fctxfn(repo, cx, path):
313 def fctxfn(repo, cx, path):
314 if path in filecontent:
314 if path in filecontent:
315 return context.memfilectx(
315 return context.memfilectx(
316 repo, cx, path, filecontent[path]
316 repo, cx, path, filecontent[path]
317 )
317 )
318 return None
318 return None
319
319
320 if len(ps) == 0 or ps[0] < 0:
320 if len(ps) == 0 or ps[0] < 0:
321 pars = [None, None]
321 pars = [None, None]
322 elif len(ps) == 1:
322 elif len(ps) == 1:
323 pars = [nodeids[ps[0]], None]
323 pars = [nodeids[ps[0]], None]
324 else:
324 else:
325 pars = [nodeids[p] for p in ps]
325 pars = [nodeids[p] for p in ps]
326 cx = context.memctx(
326 cx = context.memctx(
327 repo,
327 repo,
328 pars,
328 pars,
329 b"r%i" % id,
329 b"r%i" % id,
330 files,
330 files,
331 fctxfn,
331 fctxfn,
332 date=(id, 0),
332 date=(id, 0),
333 user=b"debugbuilddag",
333 user=b"debugbuilddag",
334 extra={b'branch': atbranch},
334 extra={b'branch': atbranch},
335 )
335 )
336 nodeid = repo.commitctx(cx)
336 nodeid = repo.commitctx(cx)
337 nodeids.append(nodeid)
337 nodeids.append(nodeid)
338 at = id
338 at = id
339 elif type == b'l':
339 elif type == b'l':
340 id, name = data
340 id, name = data
341 ui.note((b'tag %s\n' % name))
341 ui.note((b'tag %s\n' % name))
342 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
342 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
343 elif type == b'a':
343 elif type == b'a':
344 ui.note((b'branch %s\n' % data))
344 ui.note((b'branch %s\n' % data))
345 atbranch = data
345 atbranch = data
346 progress.update(id)
346 progress.update(id)
347
347
348 if tags:
348 if tags:
349 repo.vfs.write(b"localtags", b"".join(tags))
349 repo.vfs.write(b"localtags", b"".join(tags))
350
350
351
351
352 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
352 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
353 indent_string = b' ' * indent
353 indent_string = b' ' * indent
354 if all:
354 if all:
355 ui.writenoi18n(
355 ui.writenoi18n(
356 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
356 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
357 % indent_string
357 % indent_string
358 )
358 )
359
359
360 def showchunks(named):
360 def showchunks(named):
361 ui.write(b"\n%s%s\n" % (indent_string, named))
361 ui.write(b"\n%s%s\n" % (indent_string, named))
362 for deltadata in gen.deltaiter():
362 for deltadata in gen.deltaiter():
363 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
363 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
364 ui.write(
364 ui.write(
365 b"%s%s %s %s %s %s %d\n"
365 b"%s%s %s %s %s %s %d\n"
366 % (
366 % (
367 indent_string,
367 indent_string,
368 hex(node),
368 hex(node),
369 hex(p1),
369 hex(p1),
370 hex(p2),
370 hex(p2),
371 hex(cs),
371 hex(cs),
372 hex(deltabase),
372 hex(deltabase),
373 len(delta),
373 len(delta),
374 )
374 )
375 )
375 )
376
376
377 gen.changelogheader()
377 gen.changelogheader()
378 showchunks(b"changelog")
378 showchunks(b"changelog")
379 gen.manifestheader()
379 gen.manifestheader()
380 showchunks(b"manifest")
380 showchunks(b"manifest")
381 for chunkdata in iter(gen.filelogheader, {}):
381 for chunkdata in iter(gen.filelogheader, {}):
382 fname = chunkdata[b'filename']
382 fname = chunkdata[b'filename']
383 showchunks(fname)
383 showchunks(fname)
384 else:
384 else:
385 if isinstance(gen, bundle2.unbundle20):
385 if isinstance(gen, bundle2.unbundle20):
386 raise error.Abort(_(b'use debugbundle2 for this file'))
386 raise error.Abort(_(b'use debugbundle2 for this file'))
387 gen.changelogheader()
387 gen.changelogheader()
388 for deltadata in gen.deltaiter():
388 for deltadata in gen.deltaiter():
389 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
389 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
390 ui.write(b"%s%s\n" % (indent_string, hex(node)))
390 ui.write(b"%s%s\n" % (indent_string, hex(node)))
391
391
392
392
393 def _debugobsmarkers(ui, part, indent=0, **opts):
393 def _debugobsmarkers(ui, part, indent=0, **opts):
394 """display version and markers contained in 'data'"""
394 """display version and markers contained in 'data'"""
395 data = part.read()
395 data = part.read()
396 indent_string = b' ' * indent
396 indent_string = b' ' * indent
397 try:
397 try:
398 version, markers = obsolete._readmarkers(data)
398 version, markers = obsolete._readmarkers(data)
399 except error.UnknownVersion as exc:
399 except error.UnknownVersion as exc:
400 msg = b"%sunsupported version: %s (%d bytes)\n"
400 msg = b"%sunsupported version: %s (%d bytes)\n"
401 msg %= indent_string, exc.version, len(data)
401 msg %= indent_string, exc.version, len(data)
402 ui.write(msg)
402 ui.write(msg)
403 else:
403 else:
404 msg = b"%sversion: %d (%d bytes)\n"
404 msg = b"%sversion: %d (%d bytes)\n"
405 msg %= indent_string, version, len(data)
405 msg %= indent_string, version, len(data)
406 ui.write(msg)
406 ui.write(msg)
407 fm = ui.formatter(b'debugobsolete', pycompat.byteskwargs(opts))
407 fm = ui.formatter(b'debugobsolete', pycompat.byteskwargs(opts))
408 for rawmarker in sorted(markers):
408 for rawmarker in sorted(markers):
409 m = obsutil.marker(None, rawmarker)
409 m = obsutil.marker(None, rawmarker)
410 fm.startitem()
410 fm.startitem()
411 fm.plain(indent_string)
411 fm.plain(indent_string)
412 cmdutil.showmarker(fm, m)
412 cmdutil.showmarker(fm, m)
413 fm.end()
413 fm.end()
414
414
415
415
416 def _debugphaseheads(ui, data, indent=0):
416 def _debugphaseheads(ui, data, indent=0):
417 """display version and markers contained in 'data'"""
417 """display version and markers contained in 'data'"""
418 indent_string = b' ' * indent
418 indent_string = b' ' * indent
419 headsbyphase = phases.binarydecode(data)
419 headsbyphase = phases.binarydecode(data)
420 for phase in phases.allphases:
420 for phase in phases.allphases:
421 for head in headsbyphase[phase]:
421 for head in headsbyphase[phase]:
422 ui.write(indent_string)
422 ui.write(indent_string)
423 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
423 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
424
424
425
425
426 def _quasirepr(thing):
426 def _quasirepr(thing):
427 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
427 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
428 return b'{%s}' % (
428 return b'{%s}' % (
429 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
429 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
430 )
430 )
431 return pycompat.bytestr(repr(thing))
431 return pycompat.bytestr(repr(thing))
432
432
433
433
434 def _debugbundle2(ui, gen, all=None, **opts):
434 def _debugbundle2(ui, gen, all=None, **opts):
435 """lists the contents of a bundle2"""
435 """lists the contents of a bundle2"""
436 if not isinstance(gen, bundle2.unbundle20):
436 if not isinstance(gen, bundle2.unbundle20):
437 raise error.Abort(_(b'not a bundle2 file'))
437 raise error.Abort(_(b'not a bundle2 file'))
438 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
438 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
439 parttypes = opts.get('part_type', [])
439 parttypes = opts.get('part_type', [])
440 for part in gen.iterparts():
440 for part in gen.iterparts():
441 if parttypes and part.type not in parttypes:
441 if parttypes and part.type not in parttypes:
442 continue
442 continue
443 msg = b'%s -- %s (mandatory: %r)\n'
443 msg = b'%s -- %s (mandatory: %r)\n'
444 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
444 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
445 if part.type == b'changegroup':
445 if part.type == b'changegroup':
446 version = part.params.get(b'version', b'01')
446 version = part.params.get(b'version', b'01')
447 cg = changegroup.getunbundler(version, part, b'UN')
447 cg = changegroup.getunbundler(version, part, b'UN')
448 if not ui.quiet:
448 if not ui.quiet:
449 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
449 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
450 if part.type == b'obsmarkers':
450 if part.type == b'obsmarkers':
451 if not ui.quiet:
451 if not ui.quiet:
452 _debugobsmarkers(ui, part, indent=4, **opts)
452 _debugobsmarkers(ui, part, indent=4, **opts)
453 if part.type == b'phase-heads':
453 if part.type == b'phase-heads':
454 if not ui.quiet:
454 if not ui.quiet:
455 _debugphaseheads(ui, part, indent=4)
455 _debugphaseheads(ui, part, indent=4)
456
456
457
457
458 @command(
458 @command(
459 b'debugbundle',
459 b'debugbundle',
460 [
460 [
461 (b'a', b'all', None, _(b'show all details')),
461 (b'a', b'all', None, _(b'show all details')),
462 (b'', b'part-type', [], _(b'show only the named part type')),
462 (b'', b'part-type', [], _(b'show only the named part type')),
463 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
463 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
464 ],
464 ],
465 _(b'FILE'),
465 _(b'FILE'),
466 norepo=True,
466 norepo=True,
467 )
467 )
468 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
468 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
469 """lists the contents of a bundle"""
469 """lists the contents of a bundle"""
470 with hg.openpath(ui, bundlepath) as f:
470 with hg.openpath(ui, bundlepath) as f:
471 if spec:
471 if spec:
472 spec = exchange.getbundlespec(ui, f)
472 spec = exchange.getbundlespec(ui, f)
473 ui.write(b'%s\n' % spec)
473 ui.write(b'%s\n' % spec)
474 return
474 return
475
475
476 gen = exchange.readbundle(ui, f, bundlepath)
476 gen = exchange.readbundle(ui, f, bundlepath)
477 if isinstance(gen, bundle2.unbundle20):
477 if isinstance(gen, bundle2.unbundle20):
478 return _debugbundle2(ui, gen, all=all, **opts)
478 return _debugbundle2(ui, gen, all=all, **opts)
479 _debugchangegroup(ui, gen, all=all, **opts)
479 _debugchangegroup(ui, gen, all=all, **opts)
480
480
481
481
482 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
482 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
483 def debugcapabilities(ui, path, **opts):
483 def debugcapabilities(ui, path, **opts):
484 """lists the capabilities of a remote peer"""
484 """lists the capabilities of a remote peer"""
485 peer = hg.peer(ui, pycompat.byteskwargs(opts), path)
485 peer = hg.peer(ui, pycompat.byteskwargs(opts), path)
486 try:
486 try:
487 caps = peer.capabilities()
487 caps = peer.capabilities()
488 ui.writenoi18n(b'Main capabilities:\n')
488 ui.writenoi18n(b'Main capabilities:\n')
489 for c in sorted(caps):
489 for c in sorted(caps):
490 ui.write(b' %s\n' % c)
490 ui.write(b' %s\n' % c)
491 b2caps = bundle2.bundle2caps(peer)
491 b2caps = bundle2.bundle2caps(peer)
492 if b2caps:
492 if b2caps:
493 ui.writenoi18n(b'Bundle2 capabilities:\n')
493 ui.writenoi18n(b'Bundle2 capabilities:\n')
494 for key, values in sorted(b2caps.items()):
494 for key, values in sorted(b2caps.items()):
495 ui.write(b' %s\n' % key)
495 ui.write(b' %s\n' % key)
496 for v in values:
496 for v in values:
497 ui.write(b' %s\n' % v)
497 ui.write(b' %s\n' % v)
498 finally:
498 finally:
499 peer.close()
499 peer.close()
500
500
501
501
502 @command(
502 @command(
503 b'debugchangedfiles',
503 b'debugchangedfiles',
504 [
504 [
505 (
505 (
506 b'',
506 b'',
507 b'compute',
507 b'compute',
508 False,
508 False,
509 b"compute information instead of reading it from storage",
509 b"compute information instead of reading it from storage",
510 ),
510 ),
511 ],
511 ],
512 b'REV',
512 b'REV',
513 )
513 )
514 def debugchangedfiles(ui, repo, rev, **opts):
514 def debugchangedfiles(ui, repo, rev, **opts):
515 """list the stored files changes for a revision"""
515 """list the stored files changes for a revision"""
516 ctx = logcmdutil.revsingle(repo, rev, None)
516 ctx = logcmdutil.revsingle(repo, rev, None)
517 files = None
517 files = None
518
518
519 if opts['compute']:
519 if opts['compute']:
520 files = metadata.compute_all_files_changes(ctx)
520 files = metadata.compute_all_files_changes(ctx)
521 else:
521 else:
522 sd = repo.changelog.sidedata(ctx.rev())
522 sd = repo.changelog.sidedata(ctx.rev())
523 files_block = sd.get(sidedata.SD_FILES)
523 files_block = sd.get(sidedata.SD_FILES)
524 if files_block is not None:
524 if files_block is not None:
525 files = metadata.decode_files_sidedata(sd)
525 files = metadata.decode_files_sidedata(sd)
526 if files is not None:
526 if files is not None:
527 for f in sorted(files.touched):
527 for f in sorted(files.touched):
528 if f in files.added:
528 if f in files.added:
529 action = b"added"
529 action = b"added"
530 elif f in files.removed:
530 elif f in files.removed:
531 action = b"removed"
531 action = b"removed"
532 elif f in files.merged:
532 elif f in files.merged:
533 action = b"merged"
533 action = b"merged"
534 elif f in files.salvaged:
534 elif f in files.salvaged:
535 action = b"salvaged"
535 action = b"salvaged"
536 else:
536 else:
537 action = b"touched"
537 action = b"touched"
538
538
539 copy_parent = b""
539 copy_parent = b""
540 copy_source = b""
540 copy_source = b""
541 if f in files.copied_from_p1:
541 if f in files.copied_from_p1:
542 copy_parent = b"p1"
542 copy_parent = b"p1"
543 copy_source = files.copied_from_p1[f]
543 copy_source = files.copied_from_p1[f]
544 elif f in files.copied_from_p2:
544 elif f in files.copied_from_p2:
545 copy_parent = b"p2"
545 copy_parent = b"p2"
546 copy_source = files.copied_from_p2[f]
546 copy_source = files.copied_from_p2[f]
547
547
548 data = (action, copy_parent, f, copy_source)
548 data = (action, copy_parent, f, copy_source)
549 template = b"%-8s %2s: %s, %s;\n"
549 template = b"%-8s %2s: %s, %s;\n"
550 ui.write(template % data)
550 ui.write(template % data)
551
551
552
552
553 @command(b'debugcheckstate', [], b'')
553 @command(b'debugcheckstate', [], b'')
554 def debugcheckstate(ui, repo):
554 def debugcheckstate(ui, repo):
555 """validate the correctness of the current dirstate"""
555 """validate the correctness of the current dirstate"""
556 errors = verify.verifier(repo)._verify_dirstate()
556 errors = verify.verifier(repo)._verify_dirstate()
557 if errors:
557 if errors:
558 errstr = _(b"dirstate inconsistent with current parent's manifest")
558 errstr = _(b"dirstate inconsistent with current parent's manifest")
559 raise error.Abort(errstr)
559 raise error.Abort(errstr)
560
560
561
561
562 @command(
562 @command(
563 b'debugcolor',
563 b'debugcolor',
564 [(b'', b'style', None, _(b'show all configured styles'))],
564 [(b'', b'style', None, _(b'show all configured styles'))],
565 b'hg debugcolor',
565 b'hg debugcolor',
566 )
566 )
567 def debugcolor(ui, repo, **opts):
567 def debugcolor(ui, repo, **opts):
568 """show available color, effects or style"""
568 """show available color, effects or style"""
569 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
569 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
570 if opts.get('style'):
570 if opts.get('style'):
571 return _debugdisplaystyle(ui)
571 return _debugdisplaystyle(ui)
572 else:
572 else:
573 return _debugdisplaycolor(ui)
573 return _debugdisplaycolor(ui)
574
574
575
575
576 def _debugdisplaycolor(ui):
576 def _debugdisplaycolor(ui):
577 ui = ui.copy()
577 ui = ui.copy()
578 ui._styles.clear()
578 ui._styles.clear()
579 for effect in color._activeeffects(ui).keys():
579 for effect in color._activeeffects(ui).keys():
580 ui._styles[effect] = effect
580 ui._styles[effect] = effect
581 if ui._terminfoparams:
581 if ui._terminfoparams:
582 for k, v in ui.configitems(b'color'):
582 for k, v in ui.configitems(b'color'):
583 if k.startswith(b'color.'):
583 if k.startswith(b'color.'):
584 ui._styles[k] = k[6:]
584 ui._styles[k] = k[6:]
585 elif k.startswith(b'terminfo.'):
585 elif k.startswith(b'terminfo.'):
586 ui._styles[k] = k[9:]
586 ui._styles[k] = k[9:]
587 ui.write(_(b'available colors:\n'))
587 ui.write(_(b'available colors:\n'))
588 # sort label with a '_' after the other to group '_background' entry.
588 # sort label with a '_' after the other to group '_background' entry.
589 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
589 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
590 for colorname, label in items:
590 for colorname, label in items:
591 ui.write(b'%s\n' % colorname, label=label)
591 ui.write(b'%s\n' % colorname, label=label)
592
592
593
593
594 def _debugdisplaystyle(ui):
594 def _debugdisplaystyle(ui):
595 ui.write(_(b'available style:\n'))
595 ui.write(_(b'available style:\n'))
596 if not ui._styles:
596 if not ui._styles:
597 return
597 return
598 width = max(len(s) for s in ui._styles)
598 width = max(len(s) for s in ui._styles)
599 for label, effects in sorted(ui._styles.items()):
599 for label, effects in sorted(ui._styles.items()):
600 ui.write(b'%s' % label, label=label)
600 ui.write(b'%s' % label, label=label)
601 if effects:
601 if effects:
602 # 50
602 # 50
603 ui.write(b': ')
603 ui.write(b': ')
604 ui.write(b' ' * (max(0, width - len(label))))
604 ui.write(b' ' * (max(0, width - len(label))))
605 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
605 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
606 ui.write(b'\n')
606 ui.write(b'\n')
607
607
608
608
609 @command(b'debugcreatestreamclonebundle', [], b'FILE')
609 @command(b'debugcreatestreamclonebundle', [], b'FILE')
610 def debugcreatestreamclonebundle(ui, repo, fname):
610 def debugcreatestreamclonebundle(ui, repo, fname):
611 """create a stream clone bundle file
611 """create a stream clone bundle file
612
612
613 Stream bundles are special bundles that are essentially archives of
613 Stream bundles are special bundles that are essentially archives of
614 revlog files. They are commonly used for cloning very quickly.
614 revlog files. They are commonly used for cloning very quickly.
615
615
616 This command creates a "version 1" stream clone, which is deprecated in
616 This command creates a "version 1" stream clone, which is deprecated in
617 favor of newer versions of the stream protocol. Bundles using such newer
617 favor of newer versions of the stream protocol. Bundles using such newer
618 versions can be generated using the `hg bundle` command.
618 versions can be generated using the `hg bundle` command.
619 """
619 """
620 # TODO we may want to turn this into an abort when this functionality
620 # TODO we may want to turn this into an abort when this functionality
621 # is moved into `hg bundle`.
621 # is moved into `hg bundle`.
622 if phases.hassecret(repo):
622 if phases.hassecret(repo):
623 ui.warn(
623 ui.warn(
624 _(
624 _(
625 b'(warning: stream clone bundle will contain secret '
625 b'(warning: stream clone bundle will contain secret '
626 b'revisions)\n'
626 b'revisions)\n'
627 )
627 )
628 )
628 )
629
629
630 requirements, gen = streamclone.generatebundlev1(repo)
630 requirements, gen = streamclone.generatebundlev1(repo)
631 changegroup.writechunks(ui, gen, fname)
631 changegroup.writechunks(ui, gen, fname)
632
632
633 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
633 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
634
634
635
635
636 @command(
636 @command(
637 b'debugdag',
637 b'debugdag',
638 [
638 [
639 (b't', b'tags', None, _(b'use tags as labels')),
639 (b't', b'tags', None, _(b'use tags as labels')),
640 (b'b', b'branches', None, _(b'annotate with branch names')),
640 (b'b', b'branches', None, _(b'annotate with branch names')),
641 (b'', b'dots', None, _(b'use dots for runs')),
641 (b'', b'dots', None, _(b'use dots for runs')),
642 (b's', b'spaces', None, _(b'separate elements by spaces')),
642 (b's', b'spaces', None, _(b'separate elements by spaces')),
643 ],
643 ],
644 _(b'[OPTION]... [FILE [REV]...]'),
644 _(b'[OPTION]... [FILE [REV]...]'),
645 optionalrepo=True,
645 optionalrepo=True,
646 )
646 )
647 def debugdag(ui, repo, file_=None, *revs, **opts):
647 def debugdag(ui, repo, file_=None, *revs, **opts):
648 """format the changelog or an index DAG as a concise textual description
648 """format the changelog or an index DAG as a concise textual description
649
649
650 If you pass a revlog index, the revlog's DAG is emitted. If you list
650 If you pass a revlog index, the revlog's DAG is emitted. If you list
651 revision numbers, they get labeled in the output as rN.
651 revision numbers, they get labeled in the output as rN.
652
652
653 Otherwise, the changelog DAG of the current repo is emitted.
653 Otherwise, the changelog DAG of the current repo is emitted.
654 """
654 """
655 spaces = opts.get('spaces')
655 spaces = opts.get('spaces')
656 dots = opts.get('dots')
656 dots = opts.get('dots')
657 if file_:
657 if file_:
658 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
658 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
659 revs = {int(r) for r in revs}
659 revs = {int(r) for r in revs}
660
660
661 def events():
661 def events():
662 for r in rlog:
662 for r in rlog:
663 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
663 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
664 if r in revs:
664 if r in revs:
665 yield b'l', (r, b"r%i" % r)
665 yield b'l', (r, b"r%i" % r)
666
666
667 elif repo:
667 elif repo:
668 cl = repo.changelog
668 cl = repo.changelog
669 tags = opts.get('tags')
669 tags = opts.get('tags')
670 branches = opts.get('branches')
670 branches = opts.get('branches')
671 if tags:
671 if tags:
672 labels = {}
672 labels = {}
673 for l, n in repo.tags().items():
673 for l, n in repo.tags().items():
674 labels.setdefault(cl.rev(n), []).append(l)
674 labels.setdefault(cl.rev(n), []).append(l)
675
675
676 def events():
676 def events():
677 b = b"default"
677 b = b"default"
678 for r in cl:
678 for r in cl:
679 if branches:
679 if branches:
680 newb = cl.read(cl.node(r))[5][b'branch']
680 newb = cl.read(cl.node(r))[5][b'branch']
681 if newb != b:
681 if newb != b:
682 yield b'a', newb
682 yield b'a', newb
683 b = newb
683 b = newb
684 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
684 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
685 if tags:
685 if tags:
686 ls = labels.get(r)
686 ls = labels.get(r)
687 if ls:
687 if ls:
688 for l in ls:
688 for l in ls:
689 yield b'l', (r, l)
689 yield b'l', (r, l)
690
690
691 else:
691 else:
692 raise error.Abort(_(b'need repo for changelog dag'))
692 raise error.Abort(_(b'need repo for changelog dag'))
693
693
694 for line in dagparser.dagtextlines(
694 for line in dagparser.dagtextlines(
695 events(),
695 events(),
696 addspaces=spaces,
696 addspaces=spaces,
697 wraplabels=True,
697 wraplabels=True,
698 wrapannotations=True,
698 wrapannotations=True,
699 wrapnonlinear=dots,
699 wrapnonlinear=dots,
700 usedots=dots,
700 usedots=dots,
701 maxlinewidth=70,
701 maxlinewidth=70,
702 ):
702 ):
703 ui.write(line)
703 ui.write(line)
704 ui.write(b"\n")
704 ui.write(b"\n")
705
705
706
706
707 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
707 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
708 def debugdata(ui, repo, file_, rev=None, **opts):
708 def debugdata(ui, repo, file_, rev=None, **opts):
709 """dump the contents of a data file revision"""
709 """dump the contents of a data file revision"""
710 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
710 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
711 if rev is not None:
711 if rev is not None:
712 raise error.InputError(
712 raise error.InputError(
713 _(b'cannot specify a revision with other arguments')
713 _(b'cannot specify a revision with other arguments')
714 )
714 )
715 file_, rev = None, file_
715 file_, rev = None, file_
716 elif rev is None:
716 elif rev is None:
717 raise error.InputError(_(b'please specify a revision'))
717 raise error.InputError(_(b'please specify a revision'))
718 r = cmdutil.openstorage(
718 r = cmdutil.openstorage(
719 repo, b'debugdata', file_, pycompat.byteskwargs(opts)
719 repo, b'debugdata', file_, pycompat.byteskwargs(opts)
720 )
720 )
721 try:
721 try:
722 ui.write(r.rawdata(r.lookup(rev)))
722 ui.write(r.rawdata(r.lookup(rev)))
723 except KeyError:
723 except KeyError:
724 raise error.Abort(_(b'invalid revision identifier %s') % rev)
724 raise error.Abort(_(b'invalid revision identifier %s') % rev)
725
725
726
726
727 @command(
727 @command(
728 b'debugdate',
728 b'debugdate',
729 [(b'e', b'extended', None, _(b'try extended date formats'))],
729 [(b'e', b'extended', None, _(b'try extended date formats'))],
730 _(b'[-e] DATE [RANGE]'),
730 _(b'[-e] DATE [RANGE]'),
731 norepo=True,
731 norepo=True,
732 optionalrepo=True,
732 optionalrepo=True,
733 )
733 )
734 def debugdate(ui, date, range=None, **opts):
734 def debugdate(ui, date, range=None, **opts):
735 """parse and display a date"""
735 """parse and display a date"""
736 if opts["extended"]:
736 if opts["extended"]:
737 d = dateutil.parsedate(date, dateutil.extendeddateformats)
737 d = dateutil.parsedate(date, dateutil.extendeddateformats)
738 else:
738 else:
739 d = dateutil.parsedate(date)
739 d = dateutil.parsedate(date)
740 ui.writenoi18n(b"internal: %d %d\n" % d)
740 ui.writenoi18n(b"internal: %d %d\n" % d)
741 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
741 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
742 if range:
742 if range:
743 m = dateutil.matchdate(range)
743 m = dateutil.matchdate(range)
744 ui.writenoi18n(b"match: %s\n" % m(d[0]))
744 ui.writenoi18n(b"match: %s\n" % m(d[0]))
745
745
746
746
747 @command(
747 @command(
748 b'debugdeltachain',
748 b'debugdeltachain',
749 [
749 [
750 (
750 (
751 b'r',
751 b'r',
752 b'rev',
752 b'rev',
753 [],
753 [],
754 _('restrict processing to these revlog revisions'),
754 _('restrict processing to these revlog revisions'),
755 ),
755 ),
756 (
756 (
757 b'',
757 b'',
758 b'all-info',
758 b'all-info',
759 False,
759 False,
760 _('compute all information unless specified otherwise'),
760 _('compute all information unless specified otherwise'),
761 ),
761 ),
762 (
762 (
763 b'',
763 b'',
764 b'size-info',
764 b'size-info',
765 None,
765 None,
766 _('compute information related to deltas size'),
766 _('compute information related to deltas size'),
767 ),
767 ),
768 (
768 (
769 b'',
769 b'',
770 b'dist-info',
770 b'dist-info',
771 None,
771 None,
772 _('compute information related to base distance'),
772 _('compute information related to base distance'),
773 ),
773 ),
774 (
774 (
775 b'',
775 b'',
776 b'sparse-info',
776 b'sparse-info',
777 None,
777 None,
778 _('compute information related to sparse read'),
778 _('compute information related to sparse read'),
779 ),
779 ),
780 ]
780 ]
781 + cmdutil.debugrevlogopts
781 + cmdutil.debugrevlogopts
782 + cmdutil.formatteropts,
782 + cmdutil.formatteropts,
783 _(b'-c|-m|FILE'),
783 _(b'-c|-m|FILE'),
784 optionalrepo=True,
784 optionalrepo=True,
785 )
785 )
786 def debugdeltachain(ui, repo, file_=None, **opts):
786 def debugdeltachain(ui, repo, file_=None, **opts):
787 """dump information about delta chains in a revlog
787 """dump information about delta chains in a revlog
788
788
789 Output can be templatized. Available template keywords are:
789 Output can be templatized. Available template keywords are:
790
790
791 :``rev``: revision number
791 :``rev``: revision number
792 :``p1``: parent 1 revision number (for reference)
792 :``p1``: parent 1 revision number (for reference)
793 :``p2``: parent 2 revision number (for reference)
793 :``p2``: parent 2 revision number (for reference)
794
794
795 :``chainid``: delta chain identifier (numbered by unique base)
795 :``chainid``: delta chain identifier (numbered by unique base)
796 :``chainlen``: delta chain length to this revision
796 :``chainlen``: delta chain length to this revision
797
797
798 :``prevrev``: previous revision in delta chain
798 :``prevrev``: previous revision in delta chain
799 :``deltatype``: role of delta / how it was computed
799 :``deltatype``: role of delta / how it was computed
800 - base: a full snapshot
800 - base: a full snapshot
801 - snap: an intermediate snapshot
801 - snap: an intermediate snapshot
802 - p1: a delta against the first parent
802 - p1: a delta against the first parent
803 - p2: a delta against the second parent
803 - p2: a delta against the second parent
804 - skip1: a delta against the same base as p1
804 - skip1: a delta against the same base as p1
805 (when p1 has empty delta
805 (when p1 has empty delta
806 - skip2: a delta against the same base as p2
806 - skip2: a delta against the same base as p2
807 (when p2 has empty delta
807 (when p2 has empty delta
808 - prev: a delta against the previous revision
808 - prev: a delta against the previous revision
809 - other: a delta against an arbitrary revision
809 - other: a delta against an arbitrary revision
810
810
811 :``compsize``: compressed size of revision
811 :``compsize``: compressed size of revision
812 :``uncompsize``: uncompressed size of revision
812 :``uncompsize``: uncompressed size of revision
813 :``chainsize``: total size of compressed revisions in chain
813 :``chainsize``: total size of compressed revisions in chain
814 :``chainratio``: total chain size divided by uncompressed revision size
814 :``chainratio``: total chain size divided by uncompressed revision size
815 (new delta chains typically start at ratio 2.00)
815 (new delta chains typically start at ratio 2.00)
816
816
817 :``lindist``: linear distance from base revision in delta chain to end
817 :``lindist``: linear distance from base revision in delta chain to end
818 of this revision
818 of this revision
819 :``extradist``: total size of revisions not part of this delta chain from
819 :``extradist``: total size of revisions not part of this delta chain from
820 base of delta chain to end of this revision; a measurement
820 base of delta chain to end of this revision; a measurement
821 of how much extra data we need to read/seek across to read
821 of how much extra data we need to read/seek across to read
822 the delta chain for this revision
822 the delta chain for this revision
823 :``extraratio``: extradist divided by chainsize; another representation of
823 :``extraratio``: extradist divided by chainsize; another representation of
824 how much unrelated data is needed to load this delta chain
824 how much unrelated data is needed to load this delta chain
825
825
826 If the repository is configured to use the sparse read, additional keywords
826 If the repository is configured to use the sparse read, additional keywords
827 are available:
827 are available:
828
828
829 :``readsize``: total size of data read from the disk for a revision
829 :``readsize``: total size of data read from the disk for a revision
830 (sum of the sizes of all the blocks)
830 (sum of the sizes of all the blocks)
831 :``largestblock``: size of the largest block of data read from the disk
831 :``largestblock``: size of the largest block of data read from the disk
832 :``readdensity``: density of useful bytes in the data read from the disk
832 :``readdensity``: density of useful bytes in the data read from the disk
833 :``srchunks``: in how many data hunks the whole revision would be read
833 :``srchunks``: in how many data hunks the whole revision would be read
834
834
835 It is possible to select the information to be computed, this can provide a
835 It is possible to select the information to be computed, this can provide a
836 noticeable speedup to the command in some cases.
836 noticeable speedup to the command in some cases.
837
837
838 Always computed:
838 Always computed:
839
839
840 - ``rev``
840 - ``rev``
841 - ``p1``
841 - ``p1``
842 - ``p2``
842 - ``p2``
843 - ``chainid``
843 - ``chainid``
844 - ``chainlen``
844 - ``chainlen``
845 - ``prevrev``
845 - ``prevrev``
846 - ``deltatype``
846 - ``deltatype``
847
847
848 Computed with --no-size-info
848 Computed with --no-size-info
849
849
850 - ``compsize``
850 - ``compsize``
851 - ``uncompsize``
851 - ``uncompsize``
852 - ``chainsize``
852 - ``chainsize``
853 - ``chainratio``
853 - ``chainratio``
854
854
855 Computed with --no-dist-info
855 Computed with --no-dist-info
856
856
857 - ``lindist``
857 - ``lindist``
858 - ``extradist``
858 - ``extradist``
859 - ``extraratio``
859 - ``extraratio``
860
860
861 Skipped with --no-sparse-info
861 Skipped with --no-sparse-info
862
862
863 - ``readsize``
863 - ``readsize``
864 - ``largestblock``
864 - ``largestblock``
865 - ``readdensity``
865 - ``readdensity``
866 - ``srchunks``
866 - ``srchunks``
867
867
868 --
868 --
869
869
870 The sparse read can be enabled with experimental.sparse-read = True
870 The sparse read can be enabled with experimental.sparse-read = True
871 """
871 """
872 revs = None
872 revs = None
873 revs_opt = opts.pop('rev', [])
873 revs_opt = opts.pop('rev', [])
874 if revs_opt:
874 if revs_opt:
875 revs = [int(r) for r in revs_opt]
875 revs = [int(r) for r in revs_opt]
876
876
877 all_info = opts.pop('all_info', False)
877 all_info = opts.pop('all_info', False)
878 size_info = opts.pop('size_info', None)
878 size_info = opts.pop('size_info', None)
879 if size_info is None:
879 if size_info is None:
880 size_info = all_info
880 size_info = all_info
881 dist_info = opts.pop('dist_info', None)
881 dist_info = opts.pop('dist_info', None)
882 if dist_info is None:
882 if dist_info is None:
883 dist_info = all_info
883 dist_info = all_info
884 sparse_info = opts.pop('sparse_info', None)
884 sparse_info = opts.pop('sparse_info', None)
885 if sparse_info is None:
885 if sparse_info is None:
886 sparse_info = all_info
886 sparse_info = all_info
887
887
888 revlog = cmdutil.openrevlog(
888 revlog = cmdutil.openrevlog(
889 repo, b'debugdeltachain', file_, pycompat.byteskwargs(opts)
889 repo, b'debugdeltachain', file_, pycompat.byteskwargs(opts)
890 )
890 )
891 fm = ui.formatter(b'debugdeltachain', pycompat.byteskwargs(opts))
891 fm = ui.formatter(b'debugdeltachain', pycompat.byteskwargs(opts))
892
892
893 lines = revlog_debug.debug_delta_chain(
893 lines = revlog_debug.debug_delta_chain(
894 revlog,
894 revlog,
895 revs=revs,
895 revs=revs,
896 size_info=size_info,
896 size_info=size_info,
897 dist_info=dist_info,
897 dist_info=dist_info,
898 sparse_info=sparse_info,
898 sparse_info=sparse_info,
899 )
899 )
900 # first entry is the header
900 # first entry is the header
901 header = next(lines)
901 header = next(lines)
902 fm.plain(header)
902 fm.plain(header)
903 for entry in lines:
903 for entry in lines:
904 label = b' '.join(e[0] for e in entry)
904 label = b' '.join(e[0] for e in entry)
905 format = b' '.join(e[1] for e in entry)
905 format = b' '.join(e[1] for e in entry)
906 values = [e[3] for e in entry]
906 values = [e[3] for e in entry]
907 data = dict((e[2], e[3]) for e in entry)
907 data = dict((e[2], e[3]) for e in entry)
908 fm.startitem()
908 fm.startitem()
909 fm.write(label, format, *values, **data)
909 fm.write(label, format, *values, **data)
910 fm.plain(b'\n')
910 fm.plain(b'\n')
911 fm.end()
911 fm.end()
912
912
913
913
914 @command(
914 @command(
915 b'debug-delta-find',
915 b'debug-delta-find',
916 cmdutil.debugrevlogopts
916 cmdutil.debugrevlogopts
917 + cmdutil.formatteropts
917 + cmdutil.formatteropts
918 + [
918 + [
919 (
919 (
920 b'',
920 b'',
921 b'source',
921 b'source',
922 b'full',
922 b'full',
923 _(b'input data feed to the process (full, storage, p1, p2, prev)'),
923 _(b'input data feed to the process (full, storage, p1, p2, prev)'),
924 ),
924 ),
925 ],
925 ],
926 _(b'-c|-m|FILE REV'),
926 _(b'-c|-m|FILE REV'),
927 optionalrepo=True,
927 optionalrepo=True,
928 )
928 )
929 def debugdeltafind(ui, repo, arg_1, arg_2=None, source=b'full', **opts):
929 def debugdeltafind(ui, repo, arg_1, arg_2=None, source=b'full', **opts):
930 """display the computation to get to a valid delta for storing REV
930 """display the computation to get to a valid delta for storing REV
931
931
932 This command will replay the process used to find the "best" delta to store
932 This command will replay the process used to find the "best" delta to store
933 a revision and display information about all the steps used to get to that
933 a revision and display information about all the steps used to get to that
934 result.
934 result.
935
935
936 By default, the process is fed with a the full-text for the revision. This
936 By default, the process is fed with a the full-text for the revision. This
937 can be controlled with the --source flag.
937 can be controlled with the --source flag.
938
938
939 The revision use the revision number of the target storage (not changelog
939 The revision use the revision number of the target storage (not changelog
940 revision number).
940 revision number).
941
941
942 note: the process is initiated from a full text of the revision to store.
942 note: the process is initiated from a full text of the revision to store.
943 """
943 """
944 if arg_2 is None:
944 if arg_2 is None:
945 file_ = None
945 file_ = None
946 rev = arg_1
946 rev = arg_1
947 else:
947 else:
948 file_ = arg_1
948 file_ = arg_1
949 rev = arg_2
949 rev = arg_2
950
950
951 rev = int(rev)
951 rev = int(rev)
952
952
953 revlog = cmdutil.openrevlog(
953 revlog = cmdutil.openrevlog(
954 repo, b'debugdeltachain', file_, pycompat.byteskwargs(opts)
954 repo, b'debugdeltachain', file_, pycompat.byteskwargs(opts)
955 )
955 )
956 p1r, p2r = revlog.parentrevs(rev)
956 p1r, p2r = revlog.parentrevs(rev)
957
957
958 if source == b'full':
958 if source == b'full':
959 base_rev = nullrev
959 base_rev = nullrev
960 elif source == b'storage':
960 elif source == b'storage':
961 base_rev = revlog.deltaparent(rev)
961 base_rev = revlog.deltaparent(rev)
962 elif source == b'p1':
962 elif source == b'p1':
963 base_rev = p1r
963 base_rev = p1r
964 elif source == b'p2':
964 elif source == b'p2':
965 base_rev = p2r
965 base_rev = p2r
966 elif source == b'prev':
966 elif source == b'prev':
967 base_rev = rev - 1
967 base_rev = rev - 1
968 else:
968 else:
969 raise error.InputError(b"invalid --source value: %s" % source)
969 raise error.InputError(b"invalid --source value: %s" % source)
970
970
971 revlog_debug.debug_delta_find(ui, revlog, rev, base_rev=base_rev)
971 revlog_debug.debug_delta_find(ui, revlog, rev, base_rev=base_rev)
972
972
973
973
974 @command(
974 @command(
975 b'debugdirstate|debugstate',
975 b'debugdirstate|debugstate',
976 [
976 [
977 (
977 (
978 b'',
978 b'',
979 b'nodates',
979 b'nodates',
980 None,
980 None,
981 _(b'do not display the saved mtime (DEPRECATED)'),
981 _(b'do not display the saved mtime (DEPRECATED)'),
982 ),
982 ),
983 (b'', b'dates', True, _(b'display the saved mtime')),
983 (b'', b'dates', True, _(b'display the saved mtime')),
984 (b'', b'datesort', None, _(b'sort by saved mtime')),
984 (b'', b'datesort', None, _(b'sort by saved mtime')),
985 (
985 (
986 b'',
986 b'',
987 b'docket',
987 b'docket',
988 False,
988 False,
989 _(b'display the docket (metadata file) instead'),
989 _(b'display the docket (metadata file) instead'),
990 ),
990 ),
991 (
991 (
992 b'',
992 b'',
993 b'all',
993 b'all',
994 False,
994 False,
995 _(b'display dirstate-v2 tree nodes that would not exist in v1'),
995 _(b'display dirstate-v2 tree nodes that would not exist in v1'),
996 ),
996 ),
997 ],
997 ],
998 _(b'[OPTION]...'),
998 _(b'[OPTION]...'),
999 )
999 )
1000 def debugstate(ui, repo, **opts):
1000 def debugstate(ui, repo, **opts):
1001 """show the contents of the current dirstate"""
1001 """show the contents of the current dirstate"""
1002
1002
1003 if opts.get("docket"):
1003 if opts.get("docket"):
1004 if not repo.dirstate._use_dirstate_v2:
1004 if not repo.dirstate._use_dirstate_v2:
1005 raise error.Abort(_(b'dirstate v1 does not have a docket'))
1005 raise error.Abort(_(b'dirstate v1 does not have a docket'))
1006
1006
1007 docket = repo.dirstate._map.docket
1007 docket = repo.dirstate._map.docket
1008 (
1008 (
1009 start_offset,
1009 start_offset,
1010 root_nodes,
1010 root_nodes,
1011 nodes_with_entry,
1011 nodes_with_entry,
1012 nodes_with_copy,
1012 nodes_with_copy,
1013 unused_bytes,
1013 unused_bytes,
1014 _unused,
1014 _unused,
1015 ignore_pattern,
1015 ignore_pattern,
1016 ) = dirstateutils.v2.TREE_METADATA.unpack(docket.tree_metadata)
1016 ) = dirstateutils.v2.TREE_METADATA.unpack(docket.tree_metadata)
1017
1017
1018 ui.write(_(b"size of dirstate data: %d\n") % docket.data_size)
1018 ui.write(_(b"size of dirstate data: %d\n") % docket.data_size)
1019 ui.write(_(b"data file uuid: %s\n") % docket.uuid)
1019 ui.write(_(b"data file uuid: %s\n") % docket.uuid)
1020 ui.write(_(b"start offset of root nodes: %d\n") % start_offset)
1020 ui.write(_(b"start offset of root nodes: %d\n") % start_offset)
1021 ui.write(_(b"number of root nodes: %d\n") % root_nodes)
1021 ui.write(_(b"number of root nodes: %d\n") % root_nodes)
1022 ui.write(_(b"nodes with entries: %d\n") % nodes_with_entry)
1022 ui.write(_(b"nodes with entries: %d\n") % nodes_with_entry)
1023 ui.write(_(b"nodes with copies: %d\n") % nodes_with_copy)
1023 ui.write(_(b"nodes with copies: %d\n") % nodes_with_copy)
1024 ui.write(_(b"number of unused bytes: %d\n") % unused_bytes)
1024 ui.write(_(b"number of unused bytes: %d\n") % unused_bytes)
1025 ui.write(
1025 ui.write(
1026 _(b"ignore pattern hash: %s\n") % binascii.hexlify(ignore_pattern)
1026 _(b"ignore pattern hash: %s\n") % binascii.hexlify(ignore_pattern)
1027 )
1027 )
1028 return
1028 return
1029
1029
1030 nodates = not opts['dates']
1030 nodates = not opts['dates']
1031 if opts.get('nodates') is not None:
1031 if opts.get('nodates') is not None:
1032 nodates = True
1032 nodates = True
1033 datesort = opts.get('datesort')
1033 datesort = opts.get('datesort')
1034
1034
1035 if datesort:
1035 if datesort:
1036
1036
1037 def keyfunc(entry):
1037 def keyfunc(entry):
1038 filename, _state, _mode, _size, mtime = entry
1038 filename, _state, _mode, _size, mtime = entry
1039 return (mtime, filename)
1039 return (mtime, filename)
1040
1040
1041 else:
1041 else:
1042 keyfunc = None # sort by filename
1042 keyfunc = None # sort by filename
1043 entries = list(repo.dirstate._map.debug_iter(all=opts['all']))
1043 entries = list(repo.dirstate._map.debug_iter(all=opts['all']))
1044 entries.sort(key=keyfunc)
1044 entries.sort(key=keyfunc)
1045 for entry in entries:
1045 for entry in entries:
1046 filename, state, mode, size, mtime = entry
1046 filename, state, mode, size, mtime = entry
1047 if mtime == -1:
1047 if mtime == -1:
1048 timestr = b'unset '
1048 timestr = b'unset '
1049 elif nodates:
1049 elif nodates:
1050 timestr = b'set '
1050 timestr = b'set '
1051 else:
1051 else:
1052 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(mtime))
1052 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(mtime))
1053 timestr = encoding.strtolocal(timestr)
1053 timestr = encoding.strtolocal(timestr)
1054 if mode & 0o20000:
1054 if mode & 0o20000:
1055 mode = b'lnk'
1055 mode = b'lnk'
1056 else:
1056 else:
1057 mode = b'%3o' % (mode & 0o777 & ~util.umask)
1057 mode = b'%3o' % (mode & 0o777 & ~util.umask)
1058 ui.write(b"%c %s %10d %s%s\n" % (state, mode, size, timestr, filename))
1058 ui.write(b"%c %s %10d %s%s\n" % (state, mode, size, timestr, filename))
1059 for f in repo.dirstate.copies():
1059 for f in repo.dirstate.copies():
1060 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1060 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1061
1061
1062
1062
1063 @command(
1063 @command(
1064 b'debugdirstateignorepatternshash',
1064 b'debugdirstateignorepatternshash',
1065 [],
1065 [],
1066 _(b''),
1066 _(b''),
1067 )
1067 )
1068 def debugdirstateignorepatternshash(ui, repo, **opts):
1068 def debugdirstateignorepatternshash(ui, repo, **opts):
1069 """show the hash of ignore patterns stored in dirstate if v2,
1069 """show the hash of ignore patterns stored in dirstate if v2,
1070 or nothing for dirstate-v2
1070 or nothing for dirstate-v2
1071 """
1071 """
1072 if repo.dirstate._use_dirstate_v2:
1072 if repo.dirstate._use_dirstate_v2:
1073 docket = repo.dirstate._map.docket
1073 docket = repo.dirstate._map.docket
1074 hash_len = 20 # 160 bits for SHA-1
1074 hash_len = 20 # 160 bits for SHA-1
1075 hash_bytes = docket.tree_metadata[-hash_len:]
1075 hash_bytes = docket.tree_metadata[-hash_len:]
1076 ui.write(binascii.hexlify(hash_bytes) + b'\n')
1076 ui.write(binascii.hexlify(hash_bytes) + b'\n')
1077
1077
1078
1078
1079 @command(
1079 @command(
1080 b'debugdiscovery',
1080 b'debugdiscovery',
1081 [
1081 [
1082 (b'', b'old', None, _(b'use old-style discovery')),
1082 (b'', b'old', None, _(b'use old-style discovery')),
1083 (
1083 (
1084 b'',
1084 b'',
1085 b'nonheads',
1085 b'nonheads',
1086 None,
1086 None,
1087 _(b'use old-style discovery with non-heads included'),
1087 _(b'use old-style discovery with non-heads included'),
1088 ),
1088 ),
1089 (b'', b'rev', [], b'restrict discovery to this set of revs'),
1089 (b'', b'rev', [], b'restrict discovery to this set of revs'),
1090 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
1090 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
1091 (
1091 (
1092 b'',
1092 b'',
1093 b'local-as-revs',
1093 b'local-as-revs',
1094 b"",
1094 b"",
1095 b'treat local has having these revisions only',
1095 b'treat local has having these revisions only',
1096 ),
1096 ),
1097 (
1097 (
1098 b'',
1098 b'',
1099 b'remote-as-revs',
1099 b'remote-as-revs',
1100 b"",
1100 b"",
1101 b'use local as remote, with only these revisions',
1101 b'use local as remote, with only these revisions',
1102 ),
1102 ),
1103 ]
1103 ]
1104 + cmdutil.remoteopts
1104 + cmdutil.remoteopts
1105 + cmdutil.formatteropts,
1105 + cmdutil.formatteropts,
1106 _(b'[--rev REV] [OTHER]'),
1106 _(b'[--rev REV] [OTHER]'),
1107 )
1107 )
1108 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
1108 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
1109 """runs the changeset discovery protocol in isolation
1109 """runs the changeset discovery protocol in isolation
1110
1110
1111 The local peer can be "replaced" by a subset of the local repository by
1111 The local peer can be "replaced" by a subset of the local repository by
1112 using the `--local-as-revs` flag. In the same way, the usual `remote` peer
1112 using the `--local-as-revs` flag. In the same way, the usual `remote` peer
1113 can be "replaced" by a subset of the local repository using the
1113 can be "replaced" by a subset of the local repository using the
1114 `--remote-as-revs` flag. This is useful to efficiently debug pathological
1114 `--remote-as-revs` flag. This is useful to efficiently debug pathological
1115 discovery situations.
1115 discovery situations.
1116
1116
1117 The following developer oriented config are relevant for people playing with this command:
1117 The following developer oriented config are relevant for people playing with this command:
1118
1118
1119 * devel.discovery.exchange-heads=True
1119 * devel.discovery.exchange-heads=True
1120
1120
1121 If False, the discovery will not start with
1121 If False, the discovery will not start with
1122 remote head fetching and local head querying.
1122 remote head fetching and local head querying.
1123
1123
1124 * devel.discovery.grow-sample=True
1124 * devel.discovery.grow-sample=True
1125
1125
1126 If False, the sample size used in set discovery will not be increased
1126 If False, the sample size used in set discovery will not be increased
1127 through the process
1127 through the process
1128
1128
1129 * devel.discovery.grow-sample.dynamic=True
1129 * devel.discovery.grow-sample.dynamic=True
1130
1130
1131 When discovery.grow-sample.dynamic is True, the default, the sample size is
1131 When discovery.grow-sample.dynamic is True, the default, the sample size is
1132 adapted to the shape of the undecided set (it is set to the max of:
1132 adapted to the shape of the undecided set (it is set to the max of:
1133 <target-size>, len(roots(undecided)), len(heads(undecided)
1133 <target-size>, len(roots(undecided)), len(heads(undecided)
1134
1134
1135 * devel.discovery.grow-sample.rate=1.05
1135 * devel.discovery.grow-sample.rate=1.05
1136
1136
1137 the rate at which the sample grow
1137 the rate at which the sample grow
1138
1138
1139 * devel.discovery.randomize=True
1139 * devel.discovery.randomize=True
1140
1140
1141 If andom sampling during discovery are deterministic. It is meant for
1141 If andom sampling during discovery are deterministic. It is meant for
1142 integration tests.
1142 integration tests.
1143
1143
1144 * devel.discovery.sample-size=200
1144 * devel.discovery.sample-size=200
1145
1145
1146 Control the initial size of the discovery sample
1146 Control the initial size of the discovery sample
1147
1147
1148 * devel.discovery.sample-size.initial=100
1148 * devel.discovery.sample-size.initial=100
1149
1149
1150 Control the initial size of the discovery for initial change
1150 Control the initial size of the discovery for initial change
1151 """
1151 """
1152 unfi = repo.unfiltered()
1152 unfi = repo.unfiltered()
1153
1153
1154 # setup potential extra filtering
1154 # setup potential extra filtering
1155 local_revs = opts["local_as_revs"]
1155 local_revs = opts["local_as_revs"]
1156 remote_revs = opts["remote_as_revs"]
1156 remote_revs = opts["remote_as_revs"]
1157
1157
1158 # make sure tests are repeatable
1158 # make sure tests are repeatable
1159 random.seed(int(opts['seed']))
1159 random.seed(int(opts['seed']))
1160
1160
1161 if not remote_revs:
1161 if not remote_revs:
1162 path = urlutil.get_unique_pull_path_obj(
1162 path = urlutil.get_unique_pull_path_obj(
1163 b'debugdiscovery', ui, remoteurl
1163 b'debugdiscovery', ui, remoteurl
1164 )
1164 )
1165 branches = (path.branch, [])
1165 branches = (path.branch, [])
1166 remote = hg.peer(repo, pycompat.byteskwargs(opts), path)
1166 remote = hg.peer(repo, pycompat.byteskwargs(opts), path)
1167 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(path.loc))
1167 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(path.loc))
1168 else:
1168 else:
1169 branches = (None, [])
1169 branches = (None, [])
1170 remote_filtered_revs = logcmdutil.revrange(
1170 remote_filtered_revs = logcmdutil.revrange(
1171 unfi, [b"not (::(%s))" % remote_revs]
1171 unfi, [b"not (::(%s))" % remote_revs]
1172 )
1172 )
1173 remote_filtered_revs = frozenset(remote_filtered_revs)
1173 remote_filtered_revs = frozenset(remote_filtered_revs)
1174
1174
1175 def remote_func(x):
1175 def remote_func(x):
1176 return remote_filtered_revs
1176 return remote_filtered_revs
1177
1177
1178 repoview.filtertable[b'debug-discovery-remote-filter'] = remote_func
1178 repoview.filtertable[b'debug-discovery-remote-filter'] = remote_func
1179
1179
1180 remote = repo.peer()
1180 remote = repo.peer()
1181 remote._repo = remote._repo.filtered(b'debug-discovery-remote-filter')
1181 remote._repo = remote._repo.filtered(b'debug-discovery-remote-filter')
1182
1182
1183 if local_revs:
1183 if local_revs:
1184 local_filtered_revs = logcmdutil.revrange(
1184 local_filtered_revs = logcmdutil.revrange(
1185 unfi, [b"not (::(%s))" % local_revs]
1185 unfi, [b"not (::(%s))" % local_revs]
1186 )
1186 )
1187 local_filtered_revs = frozenset(local_filtered_revs)
1187 local_filtered_revs = frozenset(local_filtered_revs)
1188
1188
1189 def local_func(x):
1189 def local_func(x):
1190 return local_filtered_revs
1190 return local_filtered_revs
1191
1191
1192 repoview.filtertable[b'debug-discovery-local-filter'] = local_func
1192 repoview.filtertable[b'debug-discovery-local-filter'] = local_func
1193 repo = repo.filtered(b'debug-discovery-local-filter')
1193 repo = repo.filtered(b'debug-discovery-local-filter')
1194
1194
1195 data = {}
1195 data = {}
1196 if opts.get('old'):
1196 if opts.get('old'):
1197
1197
1198 def doit(pushedrevs, remoteheads, remote=remote):
1198 def doit(pushedrevs, remoteheads, remote=remote):
1199 if not hasattr(remote, 'branches'):
1199 if not hasattr(remote, 'branches'):
1200 # enable in-client legacy support
1200 # enable in-client legacy support
1201 remote = localrepo.locallegacypeer(remote.local())
1201 remote = localrepo.locallegacypeer(remote.local())
1202 if remote_revs:
1202 if remote_revs:
1203 r = remote._repo.filtered(b'debug-discovery-remote-filter')
1203 r = remote._repo.filtered(b'debug-discovery-remote-filter')
1204 remote._repo = r
1204 remote._repo = r
1205 common, _in, hds = treediscovery.findcommonincoming(
1205 common, _in, hds = treediscovery.findcommonincoming(
1206 repo, remote, force=True, audit=data
1206 repo, remote, force=True, audit=data
1207 )
1207 )
1208 common = set(common)
1208 common = set(common)
1209 if not opts.get('nonheads'):
1209 if not opts.get('nonheads'):
1210 ui.writenoi18n(
1210 ui.writenoi18n(
1211 b"unpruned common: %s\n"
1211 b"unpruned common: %s\n"
1212 % b" ".join(sorted(short(n) for n in common))
1212 % b" ".join(sorted(short(n) for n in common))
1213 )
1213 )
1214
1214
1215 clnode = repo.changelog.node
1215 clnode = repo.changelog.node
1216 common = repo.revs(b'heads(::%ln)', common)
1216 common = repo.revs(b'heads(::%ln)', common)
1217 common = {clnode(r) for r in common}
1217 common = {clnode(r) for r in common}
1218 return common, hds
1218 return common, hds
1219
1219
1220 else:
1220 else:
1221
1221
1222 def doit(pushedrevs, remoteheads, remote=remote):
1222 def doit(pushedrevs, remoteheads, remote=remote):
1223 nodes = None
1223 nodes = None
1224 if pushedrevs:
1224 if pushedrevs:
1225 revs = logcmdutil.revrange(repo, pushedrevs)
1225 revs = logcmdutil.revrange(repo, pushedrevs)
1226 nodes = [repo[r].node() for r in revs]
1226 nodes = [repo[r].node() for r in revs]
1227 common, any, hds = setdiscovery.findcommonheads(
1227 common, any, hds = setdiscovery.findcommonheads(
1228 ui,
1228 ui,
1229 repo,
1229 repo,
1230 remote,
1230 remote,
1231 ancestorsof=nodes,
1231 ancestorsof=nodes,
1232 audit=data,
1232 audit=data,
1233 abortwhenunrelated=False,
1233 abortwhenunrelated=False,
1234 )
1234 )
1235 return common, hds
1235 return common, hds
1236
1236
1237 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1237 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1238 localrevs = opts['rev']
1238 localrevs = opts['rev']
1239
1239
1240 fm = ui.formatter(b'debugdiscovery', pycompat.byteskwargs(opts))
1240 fm = ui.formatter(b'debugdiscovery', pycompat.byteskwargs(opts))
1241 if fm.strict_format:
1241 if fm.strict_format:
1242
1242
1243 @contextlib.contextmanager
1243 @contextlib.contextmanager
1244 def may_capture_output():
1244 def may_capture_output():
1245 ui.pushbuffer()
1245 ui.pushbuffer()
1246 yield
1246 yield
1247 data[b'output'] = ui.popbuffer()
1247 data[b'output'] = ui.popbuffer()
1248
1248
1249 else:
1249 else:
1250 may_capture_output = util.nullcontextmanager
1250 may_capture_output = util.nullcontextmanager
1251 with may_capture_output():
1251 with may_capture_output():
1252 with util.timedcm('debug-discovery') as t:
1252 with util.timedcm('debug-discovery') as t:
1253 common, hds = doit(localrevs, remoterevs)
1253 common, hds = doit(localrevs, remoterevs)
1254
1254
1255 # compute all statistics
1255 # compute all statistics
1256 if len(common) == 1 and repo.nullid in common:
1256 if len(common) == 1 and repo.nullid in common:
1257 common = set()
1257 common = set()
1258 heads_common = set(common)
1258 heads_common = set(common)
1259 heads_remote = set(hds)
1259 heads_remote = set(hds)
1260 heads_local = set(repo.heads())
1260 heads_local = set(repo.heads())
1261 # note: they cannot be a local or remote head that is in common and not
1261 # note: they cannot be a local or remote head that is in common and not
1262 # itself a head of common.
1262 # itself a head of common.
1263 heads_common_local = heads_common & heads_local
1263 heads_common_local = heads_common & heads_local
1264 heads_common_remote = heads_common & heads_remote
1264 heads_common_remote = heads_common & heads_remote
1265 heads_common_both = heads_common & heads_remote & heads_local
1265 heads_common_both = heads_common & heads_remote & heads_local
1266
1266
1267 all = repo.revs(b'all()')
1267 all = repo.revs(b'all()')
1268 common = repo.revs(b'::%ln', common)
1268 common = repo.revs(b'::%ln', common)
1269 roots_common = repo.revs(b'roots(::%ld)', common)
1269 roots_common = repo.revs(b'roots(::%ld)', common)
1270 missing = repo.revs(b'not ::%ld', common)
1270 missing = repo.revs(b'not ::%ld', common)
1271 heads_missing = repo.revs(b'heads(%ld)', missing)
1271 heads_missing = repo.revs(b'heads(%ld)', missing)
1272 roots_missing = repo.revs(b'roots(%ld)', missing)
1272 roots_missing = repo.revs(b'roots(%ld)', missing)
1273 assert len(common) + len(missing) == len(all)
1273 assert len(common) + len(missing) == len(all)
1274
1274
1275 initial_undecided = repo.revs(
1275 initial_undecided = repo.revs(
1276 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1276 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1277 )
1277 )
1278 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1278 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1279 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1279 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1280 common_initial_undecided = initial_undecided & common
1280 common_initial_undecided = initial_undecided & common
1281 missing_initial_undecided = initial_undecided & missing
1281 missing_initial_undecided = initial_undecided & missing
1282
1282
1283 data[b'elapsed'] = t.elapsed
1283 data[b'elapsed'] = t.elapsed
1284 data[b'nb-common-heads'] = len(heads_common)
1284 data[b'nb-common-heads'] = len(heads_common)
1285 data[b'nb-common-heads-local'] = len(heads_common_local)
1285 data[b'nb-common-heads-local'] = len(heads_common_local)
1286 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1286 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1287 data[b'nb-common-heads-both'] = len(heads_common_both)
1287 data[b'nb-common-heads-both'] = len(heads_common_both)
1288 data[b'nb-common-roots'] = len(roots_common)
1288 data[b'nb-common-roots'] = len(roots_common)
1289 data[b'nb-head-local'] = len(heads_local)
1289 data[b'nb-head-local'] = len(heads_local)
1290 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1290 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1291 data[b'nb-head-remote'] = len(heads_remote)
1291 data[b'nb-head-remote'] = len(heads_remote)
1292 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1292 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1293 heads_common_remote
1293 heads_common_remote
1294 )
1294 )
1295 data[b'nb-revs'] = len(all)
1295 data[b'nb-revs'] = len(all)
1296 data[b'nb-revs-common'] = len(common)
1296 data[b'nb-revs-common'] = len(common)
1297 data[b'nb-revs-missing'] = len(missing)
1297 data[b'nb-revs-missing'] = len(missing)
1298 data[b'nb-missing-heads'] = len(heads_missing)
1298 data[b'nb-missing-heads'] = len(heads_missing)
1299 data[b'nb-missing-roots'] = len(roots_missing)
1299 data[b'nb-missing-roots'] = len(roots_missing)
1300 data[b'nb-ini_und'] = len(initial_undecided)
1300 data[b'nb-ini_und'] = len(initial_undecided)
1301 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1301 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1302 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1302 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1303 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1303 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1304 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1304 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1305
1305
1306 fm.startitem()
1306 fm.startitem()
1307 fm.data(**pycompat.strkwargs(data))
1307 fm.data(**pycompat.strkwargs(data))
1308 # display discovery summary
1308 # display discovery summary
1309 fm.plain(b"elapsed time: %(elapsed)f seconds\n" % data)
1309 fm.plain(b"elapsed time: %(elapsed)f seconds\n" % data)
1310 fm.plain(b"round-trips: %(total-roundtrips)9d\n" % data)
1310 fm.plain(b"round-trips: %(total-roundtrips)9d\n" % data)
1311 if b'total-round-trips-heads' in data:
1311 if b'total-round-trips-heads' in data:
1312 fm.plain(
1312 fm.plain(
1313 b" round-trips-heads: %(total-round-trips-heads)9d\n" % data
1313 b" round-trips-heads: %(total-round-trips-heads)9d\n" % data
1314 )
1314 )
1315 if b'total-round-trips-branches' in data:
1315 if b'total-round-trips-branches' in data:
1316 fm.plain(
1316 fm.plain(
1317 b" round-trips-branches: %(total-round-trips-branches)9d\n"
1317 b" round-trips-branches: %(total-round-trips-branches)9d\n"
1318 % data
1318 % data
1319 )
1319 )
1320 if b'total-round-trips-between' in data:
1320 if b'total-round-trips-between' in data:
1321 fm.plain(
1321 fm.plain(
1322 b" round-trips-between: %(total-round-trips-between)9d\n" % data
1322 b" round-trips-between: %(total-round-trips-between)9d\n" % data
1323 )
1323 )
1324 fm.plain(b"queries: %(total-queries)9d\n" % data)
1324 fm.plain(b"queries: %(total-queries)9d\n" % data)
1325 if b'total-queries-branches' in data:
1325 if b'total-queries-branches' in data:
1326 fm.plain(b" queries-branches: %(total-queries-branches)9d\n" % data)
1326 fm.plain(b" queries-branches: %(total-queries-branches)9d\n" % data)
1327 if b'total-queries-between' in data:
1327 if b'total-queries-between' in data:
1328 fm.plain(b" queries-between: %(total-queries-between)9d\n" % data)
1328 fm.plain(b" queries-between: %(total-queries-between)9d\n" % data)
1329 fm.plain(b"heads summary:\n")
1329 fm.plain(b"heads summary:\n")
1330 fm.plain(b" total common heads: %(nb-common-heads)9d\n" % data)
1330 fm.plain(b" total common heads: %(nb-common-heads)9d\n" % data)
1331 fm.plain(b" also local heads: %(nb-common-heads-local)9d\n" % data)
1331 fm.plain(b" also local heads: %(nb-common-heads-local)9d\n" % data)
1332 fm.plain(b" also remote heads: %(nb-common-heads-remote)9d\n" % data)
1332 fm.plain(b" also remote heads: %(nb-common-heads-remote)9d\n" % data)
1333 fm.plain(b" both: %(nb-common-heads-both)9d\n" % data)
1333 fm.plain(b" both: %(nb-common-heads-both)9d\n" % data)
1334 fm.plain(b" local heads: %(nb-head-local)9d\n" % data)
1334 fm.plain(b" local heads: %(nb-head-local)9d\n" % data)
1335 fm.plain(b" common: %(nb-common-heads-local)9d\n" % data)
1335 fm.plain(b" common: %(nb-common-heads-local)9d\n" % data)
1336 fm.plain(b" missing: %(nb-head-local-missing)9d\n" % data)
1336 fm.plain(b" missing: %(nb-head-local-missing)9d\n" % data)
1337 fm.plain(b" remote heads: %(nb-head-remote)9d\n" % data)
1337 fm.plain(b" remote heads: %(nb-head-remote)9d\n" % data)
1338 fm.plain(b" common: %(nb-common-heads-remote)9d\n" % data)
1338 fm.plain(b" common: %(nb-common-heads-remote)9d\n" % data)
1339 fm.plain(b" unknown: %(nb-head-remote-unknown)9d\n" % data)
1339 fm.plain(b" unknown: %(nb-head-remote-unknown)9d\n" % data)
1340 fm.plain(b"local changesets: %(nb-revs)9d\n" % data)
1340 fm.plain(b"local changesets: %(nb-revs)9d\n" % data)
1341 fm.plain(b" common: %(nb-revs-common)9d\n" % data)
1341 fm.plain(b" common: %(nb-revs-common)9d\n" % data)
1342 fm.plain(b" heads: %(nb-common-heads)9d\n" % data)
1342 fm.plain(b" heads: %(nb-common-heads)9d\n" % data)
1343 fm.plain(b" roots: %(nb-common-roots)9d\n" % data)
1343 fm.plain(b" roots: %(nb-common-roots)9d\n" % data)
1344 fm.plain(b" missing: %(nb-revs-missing)9d\n" % data)
1344 fm.plain(b" missing: %(nb-revs-missing)9d\n" % data)
1345 fm.plain(b" heads: %(nb-missing-heads)9d\n" % data)
1345 fm.plain(b" heads: %(nb-missing-heads)9d\n" % data)
1346 fm.plain(b" roots: %(nb-missing-roots)9d\n" % data)
1346 fm.plain(b" roots: %(nb-missing-roots)9d\n" % data)
1347 fm.plain(b" first undecided set: %(nb-ini_und)9d\n" % data)
1347 fm.plain(b" first undecided set: %(nb-ini_und)9d\n" % data)
1348 fm.plain(b" heads: %(nb-ini_und-heads)9d\n" % data)
1348 fm.plain(b" heads: %(nb-ini_und-heads)9d\n" % data)
1349 fm.plain(b" roots: %(nb-ini_und-roots)9d\n" % data)
1349 fm.plain(b" roots: %(nb-ini_und-roots)9d\n" % data)
1350 fm.plain(b" common: %(nb-ini_und-common)9d\n" % data)
1350 fm.plain(b" common: %(nb-ini_und-common)9d\n" % data)
1351 fm.plain(b" missing: %(nb-ini_und-missing)9d\n" % data)
1351 fm.plain(b" missing: %(nb-ini_und-missing)9d\n" % data)
1352
1352
1353 if ui.verbose:
1353 if ui.verbose:
1354 fm.plain(
1354 fm.plain(
1355 b"common heads: %s\n"
1355 b"common heads: %s\n"
1356 % b" ".join(sorted(short(n) for n in heads_common))
1356 % b" ".join(sorted(short(n) for n in heads_common))
1357 )
1357 )
1358 fm.end()
1358 fm.end()
1359
1359
1360
1360
1361 _chunksize = 4 << 10
1361 _chunksize = 4 << 10
1362
1362
1363
1363
1364 @command(
1364 @command(
1365 b'debugdownload',
1365 b'debugdownload',
1366 [
1366 [
1367 (b'o', b'output', b'', _(b'path')),
1367 (b'o', b'output', b'', _(b'path')),
1368 ],
1368 ],
1369 optionalrepo=True,
1369 optionalrepo=True,
1370 )
1370 )
1371 def debugdownload(ui, repo, url, output=None, **opts):
1371 def debugdownload(ui, repo, url, output=None, **opts):
1372 """download a resource using Mercurial logic and config"""
1372 """download a resource using Mercurial logic and config"""
1373 fh = urlmod.open(ui, url, output)
1373 fh = urlmod.open(ui, url, output)
1374
1374
1375 dest = ui
1375 dest = ui
1376 if output:
1376 if output:
1377 dest = open(output, b"wb", _chunksize)
1377 dest = open(output, b"wb", _chunksize)
1378 try:
1378 try:
1379 data = fh.read(_chunksize)
1379 data = fh.read(_chunksize)
1380 while data:
1380 while data:
1381 dest.write(data)
1381 dest.write(data)
1382 data = fh.read(_chunksize)
1382 data = fh.read(_chunksize)
1383 finally:
1383 finally:
1384 if output:
1384 if output:
1385 dest.close()
1385 dest.close()
1386
1386
1387
1387
1388 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1388 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1389 def debugextensions(ui, repo, **opts):
1389 def debugextensions(ui, repo, **opts):
1390 '''show information about active extensions'''
1390 '''show information about active extensions'''
1391 exts = extensions.extensions(ui)
1391 exts = extensions.extensions(ui)
1392 hgver = util.version()
1392 hgver = util.version()
1393 fm = ui.formatter(b'debugextensions', pycompat.byteskwargs(opts))
1393 fm = ui.formatter(b'debugextensions', pycompat.byteskwargs(opts))
1394 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1394 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1395 isinternal = extensions.ismoduleinternal(extmod)
1395 isinternal = extensions.ismoduleinternal(extmod)
1396 extsource = None
1396 extsource = None
1397
1397
1398 if hasattr(extmod, '__file__'):
1398 if hasattr(extmod, '__file__'):
1399 extsource = pycompat.fsencode(extmod.__file__)
1399 extsource = pycompat.fsencode(extmod.__file__)
1400 elif getattr(sys, 'oxidized', False):
1400 elif getattr(sys, 'oxidized', False):
1401 extsource = pycompat.sysexecutable
1401 extsource = pycompat.sysexecutable
1402 if isinternal:
1402 if isinternal:
1403 exttestedwith = [] # never expose magic string to users
1403 exttestedwith = [] # never expose magic string to users
1404 else:
1404 else:
1405 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1405 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1406 extbuglink = getattr(extmod, 'buglink', None)
1406 extbuglink = getattr(extmod, 'buglink', None)
1407
1407
1408 fm.startitem()
1408 fm.startitem()
1409
1409
1410 if ui.quiet or ui.verbose:
1410 if ui.quiet or ui.verbose:
1411 fm.write(b'name', b'%s\n', extname)
1411 fm.write(b'name', b'%s\n', extname)
1412 else:
1412 else:
1413 fm.write(b'name', b'%s', extname)
1413 fm.write(b'name', b'%s', extname)
1414 if isinternal or hgver in exttestedwith:
1414 if isinternal or hgver in exttestedwith:
1415 fm.plain(b'\n')
1415 fm.plain(b'\n')
1416 elif not exttestedwith:
1416 elif not exttestedwith:
1417 fm.plain(_(b' (untested!)\n'))
1417 fm.plain(_(b' (untested!)\n'))
1418 else:
1418 else:
1419 lasttestedversion = exttestedwith[-1]
1419 lasttestedversion = exttestedwith[-1]
1420 fm.plain(b' (%s!)\n' % lasttestedversion)
1420 fm.plain(b' (%s!)\n' % lasttestedversion)
1421
1421
1422 fm.condwrite(
1422 fm.condwrite(
1423 ui.verbose and extsource,
1423 ui.verbose and extsource,
1424 b'source',
1424 b'source',
1425 _(b' location: %s\n'),
1425 _(b' location: %s\n'),
1426 extsource or b"",
1426 extsource or b"",
1427 )
1427 )
1428
1428
1429 if ui.verbose:
1429 if ui.verbose:
1430 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1430 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1431 fm.data(bundled=isinternal)
1431 fm.data(bundled=isinternal)
1432
1432
1433 fm.condwrite(
1433 fm.condwrite(
1434 ui.verbose and exttestedwith,
1434 ui.verbose and exttestedwith,
1435 b'testedwith',
1435 b'testedwith',
1436 _(b' tested with: %s\n'),
1436 _(b' tested with: %s\n'),
1437 fm.formatlist(exttestedwith, name=b'ver'),
1437 fm.formatlist(exttestedwith, name=b'ver'),
1438 )
1438 )
1439
1439
1440 fm.condwrite(
1440 fm.condwrite(
1441 ui.verbose and extbuglink,
1441 ui.verbose and extbuglink,
1442 b'buglink',
1442 b'buglink',
1443 _(b' bug reporting: %s\n'),
1443 _(b' bug reporting: %s\n'),
1444 extbuglink or b"",
1444 extbuglink or b"",
1445 )
1445 )
1446
1446
1447 fm.end()
1447 fm.end()
1448
1448
1449
1449
1450 @command(
1450 @command(
1451 b'debugfileset',
1451 b'debugfileset',
1452 [
1452 [
1453 (
1453 (
1454 b'r',
1454 b'r',
1455 b'rev',
1455 b'rev',
1456 b'',
1456 b'',
1457 _(b'apply the filespec on this revision'),
1457 _(b'apply the filespec on this revision'),
1458 _(b'REV'),
1458 _(b'REV'),
1459 ),
1459 ),
1460 (
1460 (
1461 b'',
1461 b'',
1462 b'all-files',
1462 b'all-files',
1463 False,
1463 False,
1464 _(b'test files from all revisions and working directory'),
1464 _(b'test files from all revisions and working directory'),
1465 ),
1465 ),
1466 (
1466 (
1467 b's',
1467 b's',
1468 b'show-matcher',
1468 b'show-matcher',
1469 None,
1469 None,
1470 _(b'print internal representation of matcher'),
1470 _(b'print internal representation of matcher'),
1471 ),
1471 ),
1472 (
1472 (
1473 b'p',
1473 b'p',
1474 b'show-stage',
1474 b'show-stage',
1475 [],
1475 [],
1476 _(b'print parsed tree at the given stage'),
1476 _(b'print parsed tree at the given stage'),
1477 _(b'NAME'),
1477 _(b'NAME'),
1478 ),
1478 ),
1479 ],
1479 ],
1480 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1480 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1481 )
1481 )
1482 def debugfileset(ui, repo, expr, **opts):
1482 def debugfileset(ui, repo, expr, **opts):
1483 '''parse and apply a fileset specification'''
1483 '''parse and apply a fileset specification'''
1484 from . import fileset
1484 from . import fileset
1485
1485
1486 fileset.symbols # force import of fileset so we have predicates to optimize
1486 fileset.symbols # force import of fileset so we have predicates to optimize
1487
1487
1488 ctx = logcmdutil.revsingle(repo, opts.get('rev'), None)
1488 ctx = logcmdutil.revsingle(repo, opts.get('rev'), None)
1489
1489
1490 stages = [
1490 stages = [
1491 (b'parsed', pycompat.identity),
1491 (b'parsed', pycompat.identity),
1492 (b'analyzed', filesetlang.analyze),
1492 (b'analyzed', filesetlang.analyze),
1493 (b'optimized', filesetlang.optimize),
1493 (b'optimized', filesetlang.optimize),
1494 ]
1494 ]
1495 stagenames = {n for n, f in stages}
1495 stagenames = {n for n, f in stages}
1496
1496
1497 showalways = set()
1497 showalways = set()
1498 if ui.verbose and not opts['show_stage']:
1498 if ui.verbose and not opts['show_stage']:
1499 # show parsed tree by --verbose (deprecated)
1499 # show parsed tree by --verbose (deprecated)
1500 showalways.add(b'parsed')
1500 showalways.add(b'parsed')
1501 if opts['show_stage'] == [b'all']:
1501 if opts['show_stage'] == [b'all']:
1502 showalways.update(stagenames)
1502 showalways.update(stagenames)
1503 else:
1503 else:
1504 for n in opts['show_stage']:
1504 for n in opts['show_stage']:
1505 if n not in stagenames:
1505 if n not in stagenames:
1506 raise error.Abort(_(b'invalid stage name: %s') % n)
1506 raise error.Abort(_(b'invalid stage name: %s') % n)
1507 showalways.update(opts['show_stage'])
1507 showalways.update(opts['show_stage'])
1508
1508
1509 tree = filesetlang.parse(expr)
1509 tree = filesetlang.parse(expr)
1510 for n, f in stages:
1510 for n, f in stages:
1511 tree = f(tree)
1511 tree = f(tree)
1512 if n in showalways:
1512 if n in showalways:
1513 if opts['show_stage'] or n != b'parsed':
1513 if opts['show_stage'] or n != b'parsed':
1514 ui.write(b"* %s:\n" % n)
1514 ui.write(b"* %s:\n" % n)
1515 ui.write(filesetlang.prettyformat(tree), b"\n")
1515 ui.write(filesetlang.prettyformat(tree), b"\n")
1516
1516
1517 files = set()
1517 files = set()
1518 if opts['all_files']:
1518 if opts['all_files']:
1519 for r in repo:
1519 for r in repo:
1520 c = repo[r]
1520 c = repo[r]
1521 files.update(c.files())
1521 files.update(c.files())
1522 files.update(c.substate)
1522 files.update(c.substate)
1523 if opts['all_files'] or ctx.rev() is None:
1523 if opts['all_files'] or ctx.rev() is None:
1524 wctx = repo[None]
1524 wctx = repo[None]
1525 files.update(
1525 files.update(
1526 repo.dirstate.walk(
1526 repo.dirstate.walk(
1527 scmutil.matchall(repo),
1527 scmutil.matchall(repo),
1528 subrepos=list(wctx.substate),
1528 subrepos=list(wctx.substate),
1529 unknown=True,
1529 unknown=True,
1530 ignored=True,
1530 ignored=True,
1531 )
1531 )
1532 )
1532 )
1533 files.update(wctx.substate)
1533 files.update(wctx.substate)
1534 else:
1534 else:
1535 files.update(ctx.files())
1535 files.update(ctx.files())
1536 files.update(ctx.substate)
1536 files.update(ctx.substate)
1537
1537
1538 m = ctx.matchfileset(repo.getcwd(), expr)
1538 m = ctx.matchfileset(repo.getcwd(), expr)
1539 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
1539 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
1540 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1540 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1541 for f in sorted(files):
1541 for f in sorted(files):
1542 if not m(f):
1542 if not m(f):
1543 continue
1543 continue
1544 ui.write(b"%s\n" % f)
1544 ui.write(b"%s\n" % f)
1545
1545
1546
1546
1547 @command(
1547 @command(
1548 b"debug-repair-issue6528",
1548 b"debug-repair-issue6528",
1549 [
1549 [
1550 (
1550 (
1551 b'',
1551 b'',
1552 b'to-report',
1552 b'to-report',
1553 b'',
1553 b'',
1554 _(b'build a report of affected revisions to this file'),
1554 _(b'build a report of affected revisions to this file'),
1555 _(b'FILE'),
1555 _(b'FILE'),
1556 ),
1556 ),
1557 (
1557 (
1558 b'',
1558 b'',
1559 b'from-report',
1559 b'from-report',
1560 b'',
1560 b'',
1561 _(b'repair revisions listed in this report file'),
1561 _(b'repair revisions listed in this report file'),
1562 _(b'FILE'),
1562 _(b'FILE'),
1563 ),
1563 ),
1564 (
1564 (
1565 b'',
1565 b'',
1566 b'paranoid',
1566 b'paranoid',
1567 False,
1567 False,
1568 _(b'check that both detection methods do the same thing'),
1568 _(b'check that both detection methods do the same thing'),
1569 ),
1569 ),
1570 ]
1570 ]
1571 + cmdutil.dryrunopts,
1571 + cmdutil.dryrunopts,
1572 )
1572 )
1573 def debug_repair_issue6528(ui, repo, **opts):
1573 def debug_repair_issue6528(ui, repo, **opts):
1574 """find affected revisions and repair them. See issue6528 for more details.
1574 """find affected revisions and repair them. See issue6528 for more details.
1575
1575
1576 The `--to-report` and `--from-report` flags allow you to cache and reuse the
1576 The `--to-report` and `--from-report` flags allow you to cache and reuse the
1577 computation of affected revisions for a given repository across clones.
1577 computation of affected revisions for a given repository across clones.
1578 The report format is line-based (with empty lines ignored):
1578 The report format is line-based (with empty lines ignored):
1579
1579
1580 ```
1580 ```
1581 <ascii-hex of the affected revision>,... <unencoded filelog index filename>
1581 <ascii-hex of the affected revision>,... <unencoded filelog index filename>
1582 ```
1582 ```
1583
1583
1584 There can be multiple broken revisions per filelog, they are separated by
1584 There can be multiple broken revisions per filelog, they are separated by
1585 a comma with no spaces. The only space is between the revision(s) and the
1585 a comma with no spaces. The only space is between the revision(s) and the
1586 filename.
1586 filename.
1587
1587
1588 Note that this does *not* mean that this repairs future affected revisions,
1588 Note that this does *not* mean that this repairs future affected revisions,
1589 that needs a separate fix at the exchange level that was introduced in
1589 that needs a separate fix at the exchange level that was introduced in
1590 Mercurial 5.9.1.
1590 Mercurial 5.9.1.
1591
1591
1592 There is a `--paranoid` flag to test that the fast implementation is correct
1592 There is a `--paranoid` flag to test that the fast implementation is correct
1593 by checking it against the slow implementation. Since this matter is quite
1593 by checking it against the slow implementation. Since this matter is quite
1594 urgent and testing every edge-case is probably quite costly, we use this
1594 urgent and testing every edge-case is probably quite costly, we use this
1595 method to test on large repositories as a fuzzing method of sorts.
1595 method to test on large repositories as a fuzzing method of sorts.
1596 """
1596 """
1597 cmdutil.check_incompatible_arguments(
1597 cmdutil.check_incompatible_arguments(
1598 opts, 'to_report', ['from_report', 'dry_run']
1598 opts, 'to_report', ['from_report', 'dry_run']
1599 )
1599 )
1600 dry_run = opts.get('dry_run')
1600 dry_run = opts.get('dry_run')
1601 to_report = opts.get('to_report')
1601 to_report = opts.get('to_report')
1602 from_report = opts.get('from_report')
1602 from_report = opts.get('from_report')
1603 paranoid = opts.get('paranoid')
1603 paranoid = opts.get('paranoid')
1604 # TODO maybe add filelog pattern and revision pattern parameters to help
1604 # TODO maybe add filelog pattern and revision pattern parameters to help
1605 # narrow down the search for users that know what they're looking for?
1605 # narrow down the search for users that know what they're looking for?
1606
1606
1607 if requirements.REVLOGV1_REQUIREMENT not in repo.requirements:
1607 if requirements.REVLOGV1_REQUIREMENT not in repo.requirements:
1608 msg = b"can only repair revlogv1 repositories, v2 is not affected"
1608 msg = b"can only repair revlogv1 repositories, v2 is not affected"
1609 raise error.Abort(_(msg))
1609 raise error.Abort(_(msg))
1610
1610
1611 rewrite.repair_issue6528(
1611 rewrite.repair_issue6528(
1612 ui,
1612 ui,
1613 repo,
1613 repo,
1614 dry_run=dry_run,
1614 dry_run=dry_run,
1615 to_report=to_report,
1615 to_report=to_report,
1616 from_report=from_report,
1616 from_report=from_report,
1617 paranoid=paranoid,
1617 paranoid=paranoid,
1618 )
1618 )
1619
1619
1620
1620
1621 @command(b'debugformat', [] + cmdutil.formatteropts)
1621 @command(b'debugformat', [] + cmdutil.formatteropts)
1622 def debugformat(ui, repo, **opts):
1622 def debugformat(ui, repo, **opts):
1623 """display format information about the current repository
1623 """display format information about the current repository
1624
1624
1625 Use --verbose to get extra information about current config value and
1625 Use --verbose to get extra information about current config value and
1626 Mercurial default."""
1626 Mercurial default."""
1627 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1627 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1628 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1628 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1629
1629
1630 def makeformatname(name):
1630 def makeformatname(name):
1631 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1631 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1632
1632
1633 fm = ui.formatter(b'debugformat', pycompat.byteskwargs(opts))
1633 fm = ui.formatter(b'debugformat', pycompat.byteskwargs(opts))
1634 if fm.isplain():
1634 if fm.isplain():
1635
1635
1636 def formatvalue(value):
1636 def formatvalue(value):
1637 if hasattr(value, 'startswith'):
1637 if hasattr(value, 'startswith'):
1638 return value
1638 return value
1639 if value:
1639 if value:
1640 return b'yes'
1640 return b'yes'
1641 else:
1641 else:
1642 return b'no'
1642 return b'no'
1643
1643
1644 else:
1644 else:
1645 formatvalue = pycompat.identity
1645 formatvalue = pycompat.identity
1646
1646
1647 fm.plain(b'format-variant')
1647 fm.plain(b'format-variant')
1648 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1648 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1649 fm.plain(b' repo')
1649 fm.plain(b' repo')
1650 if ui.verbose:
1650 if ui.verbose:
1651 fm.plain(b' config default')
1651 fm.plain(b' config default')
1652 fm.plain(b'\n')
1652 fm.plain(b'\n')
1653 for fv in upgrade.allformatvariant:
1653 for fv in upgrade.allformatvariant:
1654 fm.startitem()
1654 fm.startitem()
1655 repovalue = fv.fromrepo(repo)
1655 repovalue = fv.fromrepo(repo)
1656 configvalue = fv.fromconfig(repo)
1656 configvalue = fv.fromconfig(repo)
1657
1657
1658 if repovalue != configvalue:
1658 if repovalue != configvalue:
1659 namelabel = b'formatvariant.name.mismatchconfig'
1659 namelabel = b'formatvariant.name.mismatchconfig'
1660 repolabel = b'formatvariant.repo.mismatchconfig'
1660 repolabel = b'formatvariant.repo.mismatchconfig'
1661 elif repovalue != fv.default:
1661 elif repovalue != fv.default:
1662 namelabel = b'formatvariant.name.mismatchdefault'
1662 namelabel = b'formatvariant.name.mismatchdefault'
1663 repolabel = b'formatvariant.repo.mismatchdefault'
1663 repolabel = b'formatvariant.repo.mismatchdefault'
1664 else:
1664 else:
1665 namelabel = b'formatvariant.name.uptodate'
1665 namelabel = b'formatvariant.name.uptodate'
1666 repolabel = b'formatvariant.repo.uptodate'
1666 repolabel = b'formatvariant.repo.uptodate'
1667
1667
1668 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1668 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1669 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1669 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1670 if fv.default != configvalue:
1670 if fv.default != configvalue:
1671 configlabel = b'formatvariant.config.special'
1671 configlabel = b'formatvariant.config.special'
1672 else:
1672 else:
1673 configlabel = b'formatvariant.config.default'
1673 configlabel = b'formatvariant.config.default'
1674 fm.condwrite(
1674 fm.condwrite(
1675 ui.verbose,
1675 ui.verbose,
1676 b'config',
1676 b'config',
1677 b' %6s',
1677 b' %6s',
1678 formatvalue(configvalue),
1678 formatvalue(configvalue),
1679 label=configlabel,
1679 label=configlabel,
1680 )
1680 )
1681 fm.condwrite(
1681 fm.condwrite(
1682 ui.verbose,
1682 ui.verbose,
1683 b'default',
1683 b'default',
1684 b' %7s',
1684 b' %7s',
1685 formatvalue(fv.default),
1685 formatvalue(fv.default),
1686 label=b'formatvariant.default',
1686 label=b'formatvariant.default',
1687 )
1687 )
1688 fm.plain(b'\n')
1688 fm.plain(b'\n')
1689 fm.end()
1689 fm.end()
1690
1690
1691
1691
1692 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1692 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1693 def debugfsinfo(ui, path=b"."):
1693 def debugfsinfo(ui, path=b"."):
1694 """show information detected about current filesystem"""
1694 """show information detected about current filesystem"""
1695 ui.writenoi18n(b'path: %s\n' % path)
1695 ui.writenoi18n(b'path: %s\n' % path)
1696 ui.writenoi18n(
1696 ui.writenoi18n(
1697 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1697 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1698 )
1698 )
1699 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1699 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1700 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1700 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1701 ui.writenoi18n(
1701 ui.writenoi18n(
1702 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1702 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1703 )
1703 )
1704 ui.writenoi18n(
1704 ui.writenoi18n(
1705 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1705 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1706 )
1706 )
1707 casesensitive = b'(unknown)'
1707 casesensitive = b'(unknown)'
1708 try:
1708 try:
1709 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1709 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1710 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1710 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1711 except OSError:
1711 except OSError:
1712 pass
1712 pass
1713 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1713 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1714
1714
1715
1715
1716 @command(
1716 @command(
1717 b'debuggetbundle',
1717 b'debuggetbundle',
1718 [
1718 [
1719 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1719 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1720 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1720 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1721 (
1721 (
1722 b't',
1722 b't',
1723 b'type',
1723 b'type',
1724 b'bzip2',
1724 b'bzip2',
1725 _(b'bundle compression type to use'),
1725 _(b'bundle compression type to use'),
1726 _(b'TYPE'),
1726 _(b'TYPE'),
1727 ),
1727 ),
1728 ],
1728 ],
1729 _(b'REPO FILE [-H|-C ID]...'),
1729 _(b'REPO FILE [-H|-C ID]...'),
1730 norepo=True,
1730 norepo=True,
1731 )
1731 )
1732 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1732 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1733 """retrieves a bundle from a repo
1733 """retrieves a bundle from a repo
1734
1734
1735 Every ID must be a full-length hex node id string. Saves the bundle to the
1735 Every ID must be a full-length hex node id string. Saves the bundle to the
1736 given file.
1736 given file.
1737 """
1737 """
1738 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
1738 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
1739 if not repo.capable(b'getbundle'):
1739 if not repo.capable(b'getbundle'):
1740 raise error.Abort(b"getbundle() not supported by target repository")
1740 raise error.Abort(b"getbundle() not supported by target repository")
1741 args = {}
1741 args = {}
1742 if common:
1742 if common:
1743 args['common'] = [bin(s) for s in common]
1743 args['common'] = [bin(s) for s in common]
1744 if head:
1744 if head:
1745 args['heads'] = [bin(s) for s in head]
1745 args['heads'] = [bin(s) for s in head]
1746 # TODO: get desired bundlecaps from command line.
1746 # TODO: get desired bundlecaps from command line.
1747 args['bundlecaps'] = None
1747 args['bundlecaps'] = None
1748 bundle = repo.getbundle(b'debug', **args)
1748 bundle = repo.getbundle(b'debug', **args)
1749
1749
1750 bundletype = opts.get('type', b'bzip2').lower()
1750 bundletype = opts.get('type', b'bzip2').lower()
1751 btypes = {
1751 btypes = {
1752 b'none': b'HG10UN',
1752 b'none': b'HG10UN',
1753 b'bzip2': b'HG10BZ',
1753 b'bzip2': b'HG10BZ',
1754 b'gzip': b'HG10GZ',
1754 b'gzip': b'HG10GZ',
1755 b'bundle2': b'HG20',
1755 b'bundle2': b'HG20',
1756 }
1756 }
1757 bundletype = btypes.get(bundletype)
1757 bundletype = btypes.get(bundletype)
1758 if bundletype not in bundle2.bundletypes:
1758 if bundletype not in bundle2.bundletypes:
1759 raise error.Abort(_(b'unknown bundle type specified with --type'))
1759 raise error.Abort(_(b'unknown bundle type specified with --type'))
1760 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1760 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1761
1761
1762
1762
1763 @command(b'debugignore', [], b'[FILE]...')
1763 @command(b'debugignore', [], b'[FILE]...')
1764 def debugignore(ui, repo, *files, **opts):
1764 def debugignore(ui, repo, *files, **opts):
1765 """display the combined ignore pattern and information about ignored files
1765 """display the combined ignore pattern and information about ignored files
1766
1766
1767 With no argument display the combined ignore pattern.
1767 With no argument display the combined ignore pattern.
1768
1768
1769 Given space separated file names, shows if the given file is ignored and
1769 Given space separated file names, shows if the given file is ignored and
1770 if so, show the ignore rule (file and line number) that matched it.
1770 if so, show the ignore rule (file and line number) that matched it.
1771 """
1771 """
1772 ignore = repo.dirstate._ignore
1772 ignore = repo.dirstate._ignore
1773 if not files:
1773 if not files:
1774 # Show all the patterns
1774 # Show all the patterns
1775 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1775 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1776 else:
1776 else:
1777 m = scmutil.match(repo[None], pats=files)
1777 m = scmutil.match(repo[None], pats=files)
1778 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1778 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1779 for f in m.files():
1779 for f in m.files():
1780 nf = util.normpath(f)
1780 nf = util.normpath(f)
1781 ignored = None
1781 ignored = None
1782 ignoredata = None
1782 ignoredata = None
1783 if nf != b'.':
1783 if nf != b'.':
1784 if ignore(nf):
1784 if ignore(nf):
1785 ignored = nf
1785 ignored = nf
1786 ignoredata = repo.dirstate._ignorefileandline(nf)
1786 ignoredata = repo.dirstate._ignorefileandline(nf)
1787 else:
1787 else:
1788 for p in pathutil.finddirs(nf):
1788 for p in pathutil.finddirs(nf):
1789 if ignore(p):
1789 if ignore(p):
1790 ignored = p
1790 ignored = p
1791 ignoredata = repo.dirstate._ignorefileandline(p)
1791 ignoredata = repo.dirstate._ignorefileandline(p)
1792 break
1792 break
1793 if ignored:
1793 if ignored:
1794 if ignored == nf:
1794 if ignored == nf:
1795 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1795 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1796 else:
1796 else:
1797 ui.write(
1797 ui.write(
1798 _(
1798 _(
1799 b"%s is ignored because of "
1799 b"%s is ignored because of "
1800 b"containing directory %s\n"
1800 b"containing directory %s\n"
1801 )
1801 )
1802 % (uipathfn(f), ignored)
1802 % (uipathfn(f), ignored)
1803 )
1803 )
1804 ignorefile, lineno, line = ignoredata
1804 ignorefile, lineno, line = ignoredata
1805 ui.write(
1805 ui.write(
1806 _(b"(ignore rule in %s, line %d: '%s')\n")
1806 _(b"(ignore rule in %s, line %d: '%s')\n")
1807 % (ignorefile, lineno, line)
1807 % (ignorefile, lineno, line)
1808 )
1808 )
1809 else:
1809 else:
1810 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1810 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1811
1811
1812
1812
1813 @command(
1813 @command(
1814 b'debug-revlog-index|debugindex',
1814 b'debug-revlog-index|debugindex',
1815 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1815 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1816 _(b'-c|-m|FILE'),
1816 _(b'-c|-m|FILE'),
1817 )
1817 )
1818 def debugindex(ui, repo, file_=None, **opts):
1818 def debugindex(ui, repo, file_=None, **opts):
1819 """dump index data for a revlog"""
1819 """dump index data for a revlog"""
1820 opts = pycompat.byteskwargs(opts)
1820 opts = pycompat.byteskwargs(opts)
1821 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1821 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1822
1822
1823 fm = ui.formatter(b'debugindex', opts)
1823 fm = ui.formatter(b'debugindex', opts)
1824
1824
1825 revlog = getattr(store, '_revlog', store)
1825 revlog = getattr(store, '_revlog', store)
1826
1826
1827 return revlog_debug.debug_index(
1827 return revlog_debug.debug_index(
1828 ui,
1828 ui,
1829 repo,
1829 repo,
1830 formatter=fm,
1830 formatter=fm,
1831 revlog=revlog,
1831 revlog=revlog,
1832 full_node=ui.debugflag,
1832 full_node=ui.debugflag,
1833 )
1833 )
1834
1834
1835
1835
1836 @command(
1836 @command(
1837 b'debugindexdot',
1837 b'debugindexdot',
1838 cmdutil.debugrevlogopts,
1838 cmdutil.debugrevlogopts,
1839 _(b'-c|-m|FILE'),
1839 _(b'-c|-m|FILE'),
1840 optionalrepo=True,
1840 optionalrepo=True,
1841 )
1841 )
1842 def debugindexdot(ui, repo, file_=None, **opts):
1842 def debugindexdot(ui, repo, file_=None, **opts):
1843 """dump an index DAG as a graphviz dot file"""
1843 """dump an index DAG as a graphviz dot file"""
1844 r = cmdutil.openstorage(
1844 r = cmdutil.openstorage(
1845 repo, b'debugindexdot', file_, pycompat.byteskwargs(opts)
1845 repo, b'debugindexdot', file_, pycompat.byteskwargs(opts)
1846 )
1846 )
1847 ui.writenoi18n(b"digraph G {\n")
1847 ui.writenoi18n(b"digraph G {\n")
1848 for i in r:
1848 for i in r:
1849 node = r.node(i)
1849 node = r.node(i)
1850 pp = r.parents(node)
1850 pp = r.parents(node)
1851 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1851 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1852 if pp[1] != repo.nullid:
1852 if pp[1] != repo.nullid:
1853 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1853 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1854 ui.write(b"}\n")
1854 ui.write(b"}\n")
1855
1855
1856
1856
1857 @command(b'debugindexstats', [])
1857 @command(b'debugindexstats', [])
1858 def debugindexstats(ui, repo):
1858 def debugindexstats(ui, repo):
1859 """show stats related to the changelog index"""
1859 """show stats related to the changelog index"""
1860 repo.changelog.shortest(repo.nullid, 1)
1860 repo.changelog.shortest(repo.nullid, 1)
1861 index = repo.changelog.index
1861 index = repo.changelog.index
1862 if not hasattr(index, 'stats'):
1862 if not hasattr(index, 'stats'):
1863 raise error.Abort(_(b'debugindexstats only works with native C code'))
1863 raise error.Abort(_(b'debugindexstats only works with native C code'))
1864 for k, v in sorted(index.stats().items()):
1864 for k, v in sorted(index.stats().items()):
1865 ui.write(b'%s: %d\n' % (k, v))
1865 ui.write(b'%s: %d\n' % (k, v))
1866
1866
1867
1867
1868 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1868 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1869 def debuginstall(ui, **opts):
1869 def debuginstall(ui, **opts):
1870 """test Mercurial installation
1870 """test Mercurial installation
1871
1871
1872 Returns 0 on success.
1872 Returns 0 on success.
1873 """
1873 """
1874 problems = 0
1874 problems = 0
1875
1875
1876 fm = ui.formatter(b'debuginstall', pycompat.byteskwargs(opts))
1876 fm = ui.formatter(b'debuginstall', pycompat.byteskwargs(opts))
1877 fm.startitem()
1877 fm.startitem()
1878
1878
1879 # encoding might be unknown or wrong. don't translate these messages.
1879 # encoding might be unknown or wrong. don't translate these messages.
1880 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1880 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1881 err = None
1881 err = None
1882 try:
1882 try:
1883 codecs.lookup(pycompat.sysstr(encoding.encoding))
1883 codecs.lookup(pycompat.sysstr(encoding.encoding))
1884 except LookupError as inst:
1884 except LookupError as inst:
1885 err = stringutil.forcebytestr(inst)
1885 err = stringutil.forcebytestr(inst)
1886 problems += 1
1886 problems += 1
1887 fm.condwrite(
1887 fm.condwrite(
1888 err,
1888 err,
1889 b'encodingerror',
1889 b'encodingerror',
1890 b" %s\n (check that your locale is properly set)\n",
1890 b" %s\n (check that your locale is properly set)\n",
1891 err,
1891 err,
1892 )
1892 )
1893
1893
1894 # Python
1894 # Python
1895 pythonlib = None
1895 pythonlib = None
1896 if hasattr(os, '__file__'):
1896 if hasattr(os, '__file__'):
1897 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1897 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1898 elif getattr(sys, 'oxidized', False):
1898 elif getattr(sys, 'oxidized', False):
1899 pythonlib = pycompat.sysexecutable
1899 pythonlib = pycompat.sysexecutable
1900
1900
1901 fm.write(
1901 fm.write(
1902 b'pythonexe',
1902 b'pythonexe',
1903 _(b"checking Python executable (%s)\n"),
1903 _(b"checking Python executable (%s)\n"),
1904 pycompat.sysexecutable or _(b"unknown"),
1904 pycompat.sysexecutable or _(b"unknown"),
1905 )
1905 )
1906 fm.write(
1906 fm.write(
1907 b'pythonimplementation',
1907 b'pythonimplementation',
1908 _(b"checking Python implementation (%s)\n"),
1908 _(b"checking Python implementation (%s)\n"),
1909 pycompat.sysbytes(platform.python_implementation()),
1909 pycompat.sysbytes(platform.python_implementation()),
1910 )
1910 )
1911 fm.write(
1911 fm.write(
1912 b'pythonver',
1912 b'pythonver',
1913 _(b"checking Python version (%s)\n"),
1913 _(b"checking Python version (%s)\n"),
1914 (b"%d.%d.%d" % sys.version_info[:3]),
1914 (b"%d.%d.%d" % sys.version_info[:3]),
1915 )
1915 )
1916 fm.write(
1916 fm.write(
1917 b'pythonlib',
1917 b'pythonlib',
1918 _(b"checking Python lib (%s)...\n"),
1918 _(b"checking Python lib (%s)...\n"),
1919 pythonlib or _(b"unknown"),
1919 pythonlib or _(b"unknown"),
1920 )
1920 )
1921
1921
1922 try:
1922 try:
1923 from . import rustext # pytype: disable=import-error
1923 from . import rustext # pytype: disable=import-error
1924
1924
1925 rustext.__doc__ # trigger lazy import
1925 rustext.__doc__ # trigger lazy import
1926 except ImportError:
1926 except ImportError:
1927 rustext = None
1927 rustext = None
1928
1928
1929 security = set(sslutil.supportedprotocols)
1929 security = set(sslutil.supportedprotocols)
1930 if sslutil.hassni:
1930 if sslutil.hassni:
1931 security.add(b'sni')
1931 security.add(b'sni')
1932
1932
1933 fm.write(
1933 fm.write(
1934 b'pythonsecurity',
1934 b'pythonsecurity',
1935 _(b"checking Python security support (%s)\n"),
1935 _(b"checking Python security support (%s)\n"),
1936 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
1936 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
1937 )
1937 )
1938
1938
1939 # These are warnings, not errors. So don't increment problem count. This
1939 # These are warnings, not errors. So don't increment problem count. This
1940 # may change in the future.
1940 # may change in the future.
1941 if b'tls1.2' not in security:
1941 if b'tls1.2' not in security:
1942 fm.plain(
1942 fm.plain(
1943 _(
1943 _(
1944 b' TLS 1.2 not supported by Python install; '
1944 b' TLS 1.2 not supported by Python install; '
1945 b'network connections lack modern security\n'
1945 b'network connections lack modern security\n'
1946 )
1946 )
1947 )
1947 )
1948 if b'sni' not in security:
1948 if b'sni' not in security:
1949 fm.plain(
1949 fm.plain(
1950 _(
1950 _(
1951 b' SNI not supported by Python install; may have '
1951 b' SNI not supported by Python install; may have '
1952 b'connectivity issues with some servers\n'
1952 b'connectivity issues with some servers\n'
1953 )
1953 )
1954 )
1954 )
1955
1955
1956 fm.plain(
1956 fm.plain(
1957 _(
1957 _(
1958 b"checking Rust extensions (%s)\n"
1958 b"checking Rust extensions (%s)\n"
1959 % (b'missing' if rustext is None else b'installed')
1959 % (b'missing' if rustext is None else b'installed')
1960 ),
1960 ),
1961 )
1961 )
1962
1962
1963 # TODO print CA cert info
1963 # TODO print CA cert info
1964
1964
1965 # hg version
1965 # hg version
1966 hgver = util.version()
1966 hgver = util.version()
1967 fm.write(
1967 fm.write(
1968 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
1968 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
1969 )
1969 )
1970 fm.write(
1970 fm.write(
1971 b'hgverextra',
1971 b'hgverextra',
1972 _(b"checking Mercurial custom build (%s)\n"),
1972 _(b"checking Mercurial custom build (%s)\n"),
1973 b'+'.join(hgver.split(b'+')[1:]),
1973 b'+'.join(hgver.split(b'+')[1:]),
1974 )
1974 )
1975
1975
1976 # compiled modules
1976 # compiled modules
1977 hgmodules = None
1977 hgmodules = None
1978 if hasattr(sys.modules[__name__], '__file__'):
1978 if hasattr(sys.modules[__name__], '__file__'):
1979 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
1979 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
1980 elif getattr(sys, 'oxidized', False):
1980 elif getattr(sys, 'oxidized', False):
1981 hgmodules = pycompat.sysexecutable
1981 hgmodules = pycompat.sysexecutable
1982
1982
1983 fm.write(
1983 fm.write(
1984 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
1984 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
1985 )
1985 )
1986 fm.write(
1986 fm.write(
1987 b'hgmodules',
1987 b'hgmodules',
1988 _(b"checking installed modules (%s)...\n"),
1988 _(b"checking installed modules (%s)...\n"),
1989 hgmodules or _(b"unknown"),
1989 hgmodules or _(b"unknown"),
1990 )
1990 )
1991
1991
1992 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
1992 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
1993 rustext = rustandc # for now, that's the only case
1993 rustext = rustandc # for now, that's the only case
1994 cext = policy.policy in (b'c', b'allow') or rustandc
1994 cext = policy.policy in (b'c', b'allow') or rustandc
1995 nopure = cext or rustext
1995 nopure = cext or rustext
1996 if nopure:
1996 if nopure:
1997 err = None
1997 err = None
1998 try:
1998 try:
1999 if cext:
1999 if cext:
2000 from .cext import ( # pytype: disable=import-error
2000 from .cext import ( # pytype: disable=import-error
2001 base85,
2001 base85,
2002 bdiff,
2002 bdiff,
2003 mpatch,
2003 mpatch,
2004 osutil,
2004 osutil,
2005 )
2005 )
2006
2006
2007 # quiet pyflakes
2007 # quiet pyflakes
2008 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
2008 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
2009 if rustext:
2009 if rustext:
2010 from .rustext import ( # pytype: disable=import-error
2010 from .rustext import ( # pytype: disable=import-error
2011 ancestor,
2011 ancestor,
2012 dirstate,
2012 dirstate,
2013 )
2013 )
2014
2014
2015 dir(ancestor), dir(dirstate) # quiet pyflakes
2015 dir(ancestor), dir(dirstate) # quiet pyflakes
2016 except Exception as inst:
2016 except Exception as inst:
2017 err = stringutil.forcebytestr(inst)
2017 err = stringutil.forcebytestr(inst)
2018 problems += 1
2018 problems += 1
2019 fm.condwrite(err, b'extensionserror', b" %s\n", err)
2019 fm.condwrite(err, b'extensionserror', b" %s\n", err)
2020
2020
2021 compengines = util.compengines._engines.values()
2021 compengines = util.compengines._engines.values()
2022 fm.write(
2022 fm.write(
2023 b'compengines',
2023 b'compengines',
2024 _(b'checking registered compression engines (%s)\n'),
2024 _(b'checking registered compression engines (%s)\n'),
2025 fm.formatlist(
2025 fm.formatlist(
2026 sorted(e.name() for e in compengines),
2026 sorted(e.name() for e in compengines),
2027 name=b'compengine',
2027 name=b'compengine',
2028 fmt=b'%s',
2028 fmt=b'%s',
2029 sep=b', ',
2029 sep=b', ',
2030 ),
2030 ),
2031 )
2031 )
2032 fm.write(
2032 fm.write(
2033 b'compenginesavail',
2033 b'compenginesavail',
2034 _(b'checking available compression engines (%s)\n'),
2034 _(b'checking available compression engines (%s)\n'),
2035 fm.formatlist(
2035 fm.formatlist(
2036 sorted(e.name() for e in compengines if e.available()),
2036 sorted(e.name() for e in compengines if e.available()),
2037 name=b'compengine',
2037 name=b'compengine',
2038 fmt=b'%s',
2038 fmt=b'%s',
2039 sep=b', ',
2039 sep=b', ',
2040 ),
2040 ),
2041 )
2041 )
2042 wirecompengines = compression.compengines.supportedwireengines(
2042 wirecompengines = compression.compengines.supportedwireengines(
2043 compression.SERVERROLE
2043 compression.SERVERROLE
2044 )
2044 )
2045 fm.write(
2045 fm.write(
2046 b'compenginesserver',
2046 b'compenginesserver',
2047 _(
2047 _(
2048 b'checking available compression engines '
2048 b'checking available compression engines '
2049 b'for wire protocol (%s)\n'
2049 b'for wire protocol (%s)\n'
2050 ),
2050 ),
2051 fm.formatlist(
2051 fm.formatlist(
2052 [e.name() for e in wirecompengines if e.wireprotosupport()],
2052 [e.name() for e in wirecompengines if e.wireprotosupport()],
2053 name=b'compengine',
2053 name=b'compengine',
2054 fmt=b'%s',
2054 fmt=b'%s',
2055 sep=b', ',
2055 sep=b', ',
2056 ),
2056 ),
2057 )
2057 )
2058 re2 = b'missing'
2058 re2 = b'missing'
2059 if util.has_re2():
2059 if util.has_re2():
2060 re2 = b'available'
2060 re2 = b'available'
2061 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
2061 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
2062 fm.data(re2=bool(util._re2))
2062 fm.data(re2=bool(util._re2))
2063
2063
2064 # templates
2064 # templates
2065 p = templater.templatedir()
2065 p = templater.templatedir()
2066 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
2066 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
2067 fm.condwrite(not p, b'', _(b" no template directories found\n"))
2067 fm.condwrite(not p, b'', _(b" no template directories found\n"))
2068 if p:
2068 if p:
2069 (m, fp) = templater.try_open_template(b"map-cmdline.default")
2069 (m, fp) = templater.try_open_template(b"map-cmdline.default")
2070 if m:
2070 if m:
2071 # template found, check if it is working
2071 # template found, check if it is working
2072 err = None
2072 err = None
2073 try:
2073 try:
2074 templater.templater.frommapfile(m)
2074 templater.templater.frommapfile(m)
2075 except Exception as inst:
2075 except Exception as inst:
2076 err = stringutil.forcebytestr(inst)
2076 err = stringutil.forcebytestr(inst)
2077 p = None
2077 p = None
2078 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
2078 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
2079 else:
2079 else:
2080 p = None
2080 p = None
2081 fm.condwrite(
2081 fm.condwrite(
2082 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
2082 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
2083 )
2083 )
2084 fm.condwrite(
2084 fm.condwrite(
2085 not m,
2085 not m,
2086 b'defaulttemplatenotfound',
2086 b'defaulttemplatenotfound',
2087 _(b" template '%s' not found\n"),
2087 _(b" template '%s' not found\n"),
2088 b"default",
2088 b"default",
2089 )
2089 )
2090 if not p:
2090 if not p:
2091 problems += 1
2091 problems += 1
2092 fm.condwrite(
2092 fm.condwrite(
2093 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
2093 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
2094 )
2094 )
2095
2095
2096 # editor
2096 # editor
2097 editor = ui.geteditor()
2097 editor = ui.geteditor()
2098 editor = util.expandpath(editor)
2098 editor = util.expandpath(editor)
2099 editorbin = procutil.shellsplit(editor)[0]
2099 editorbin = procutil.shellsplit(editor)[0]
2100 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
2100 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
2101 cmdpath = procutil.findexe(editorbin)
2101 cmdpath = procutil.findexe(editorbin)
2102 fm.condwrite(
2102 fm.condwrite(
2103 not cmdpath and editor == b'vi',
2103 not cmdpath and editor == b'vi',
2104 b'vinotfound',
2104 b'vinotfound',
2105 _(
2105 _(
2106 b" No commit editor set and can't find %s in PATH\n"
2106 b" No commit editor set and can't find %s in PATH\n"
2107 b" (specify a commit editor in your configuration"
2107 b" (specify a commit editor in your configuration"
2108 b" file)\n"
2108 b" file)\n"
2109 ),
2109 ),
2110 not cmdpath and editor == b'vi' and editorbin,
2110 not cmdpath and editor == b'vi' and editorbin,
2111 )
2111 )
2112 fm.condwrite(
2112 fm.condwrite(
2113 not cmdpath and editor != b'vi',
2113 not cmdpath and editor != b'vi',
2114 b'editornotfound',
2114 b'editornotfound',
2115 _(
2115 _(
2116 b" Can't find editor '%s' in PATH\n"
2116 b" Can't find editor '%s' in PATH\n"
2117 b" (specify a commit editor in your configuration"
2117 b" (specify a commit editor in your configuration"
2118 b" file)\n"
2118 b" file)\n"
2119 ),
2119 ),
2120 not cmdpath and editorbin,
2120 not cmdpath and editorbin,
2121 )
2121 )
2122 if not cmdpath and editor != b'vi':
2122 if not cmdpath and editor != b'vi':
2123 problems += 1
2123 problems += 1
2124
2124
2125 # check username
2125 # check username
2126 username = None
2126 username = None
2127 err = None
2127 err = None
2128 try:
2128 try:
2129 username = ui.username()
2129 username = ui.username()
2130 except error.Abort as e:
2130 except error.Abort as e:
2131 err = e.message
2131 err = e.message
2132 problems += 1
2132 problems += 1
2133
2133
2134 fm.condwrite(
2134 fm.condwrite(
2135 username, b'username', _(b"checking username (%s)\n"), username
2135 username, b'username', _(b"checking username (%s)\n"), username
2136 )
2136 )
2137 fm.condwrite(
2137 fm.condwrite(
2138 err,
2138 err,
2139 b'usernameerror',
2139 b'usernameerror',
2140 _(
2140 _(
2141 b"checking username...\n %s\n"
2141 b"checking username...\n %s\n"
2142 b" (specify a username in your configuration file)\n"
2142 b" (specify a username in your configuration file)\n"
2143 ),
2143 ),
2144 err,
2144 err,
2145 )
2145 )
2146
2146
2147 for name, mod in extensions.extensions():
2147 for name, mod in extensions.extensions():
2148 handler = getattr(mod, 'debuginstall', None)
2148 handler = getattr(mod, 'debuginstall', None)
2149 if handler is not None:
2149 if handler is not None:
2150 problems += handler(ui, fm)
2150 problems += handler(ui, fm)
2151
2151
2152 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
2152 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
2153 if not problems:
2153 if not problems:
2154 fm.data(problems=problems)
2154 fm.data(problems=problems)
2155 fm.condwrite(
2155 fm.condwrite(
2156 problems,
2156 problems,
2157 b'problems',
2157 b'problems',
2158 _(b"%d problems detected, please check your install!\n"),
2158 _(b"%d problems detected, please check your install!\n"),
2159 problems,
2159 problems,
2160 )
2160 )
2161 fm.end()
2161 fm.end()
2162
2162
2163 return problems
2163 return problems
2164
2164
2165
2165
2166 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
2166 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
2167 def debugknown(ui, repopath, *ids, **opts):
2167 def debugknown(ui, repopath, *ids, **opts):
2168 """test whether node ids are known to a repo
2168 """test whether node ids are known to a repo
2169
2169
2170 Every ID must be a full-length hex node id string. Returns a list of 0s
2170 Every ID must be a full-length hex node id string. Returns a list of 0s
2171 and 1s indicating unknown/known.
2171 and 1s indicating unknown/known.
2172 """
2172 """
2173 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
2173 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
2174 if not repo.capable(b'known'):
2174 if not repo.capable(b'known'):
2175 raise error.Abort(b"known() not supported by target repository")
2175 raise error.Abort(b"known() not supported by target repository")
2176 flags = repo.known([bin(s) for s in ids])
2176 flags = repo.known([bin(s) for s in ids])
2177 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
2177 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
2178
2178
2179
2179
2180 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
2180 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
2181 def debuglabelcomplete(ui, repo, *args):
2181 def debuglabelcomplete(ui, repo, *args):
2182 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2182 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2183 debugnamecomplete(ui, repo, *args)
2183 debugnamecomplete(ui, repo, *args)
2184
2184
2185
2185
2186 @command(
2186 @command(
2187 b'debuglocks',
2187 b'debuglocks',
2188 [
2188 [
2189 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
2189 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
2190 (
2190 (
2191 b'W',
2191 b'W',
2192 b'force-free-wlock',
2192 b'force-free-wlock',
2193 None,
2193 None,
2194 _(b'free the working state lock (DANGEROUS)'),
2194 _(b'free the working state lock (DANGEROUS)'),
2195 ),
2195 ),
2196 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
2196 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
2197 (
2197 (
2198 b'S',
2198 b'S',
2199 b'set-wlock',
2199 b'set-wlock',
2200 None,
2200 None,
2201 _(b'set the working state lock until stopped'),
2201 _(b'set the working state lock until stopped'),
2202 ),
2202 ),
2203 ],
2203 ],
2204 _(b'[OPTION]...'),
2204 _(b'[OPTION]...'),
2205 )
2205 )
2206 def debuglocks(ui, repo, **opts):
2206 def debuglocks(ui, repo, **opts):
2207 """show or modify state of locks
2207 """show or modify state of locks
2208
2208
2209 By default, this command will show which locks are held. This
2209 By default, this command will show which locks are held. This
2210 includes the user and process holding the lock, the amount of time
2210 includes the user and process holding the lock, the amount of time
2211 the lock has been held, and the machine name where the process is
2211 the lock has been held, and the machine name where the process is
2212 running if it's not local.
2212 running if it's not local.
2213
2213
2214 Locks protect the integrity of Mercurial's data, so should be
2214 Locks protect the integrity of Mercurial's data, so should be
2215 treated with care. System crashes or other interruptions may cause
2215 treated with care. System crashes or other interruptions may cause
2216 locks to not be properly released, though Mercurial will usually
2216 locks to not be properly released, though Mercurial will usually
2217 detect and remove such stale locks automatically.
2217 detect and remove such stale locks automatically.
2218
2218
2219 However, detecting stale locks may not always be possible (for
2219 However, detecting stale locks may not always be possible (for
2220 instance, on a shared filesystem). Removing locks may also be
2220 instance, on a shared filesystem). Removing locks may also be
2221 blocked by filesystem permissions.
2221 blocked by filesystem permissions.
2222
2222
2223 Setting a lock will prevent other commands from changing the data.
2223 Setting a lock will prevent other commands from changing the data.
2224 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
2224 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
2225 The set locks are removed when the command exits.
2225 The set locks are removed when the command exits.
2226
2226
2227 Returns 0 if no locks are held.
2227 Returns 0 if no locks are held.
2228
2228
2229 """
2229 """
2230
2230
2231 if opts.get('force_free_lock'):
2231 if opts.get('force_free_lock'):
2232 repo.svfs.tryunlink(b'lock')
2232 repo.svfs.tryunlink(b'lock')
2233 if opts.get('force_free_wlock'):
2233 if opts.get('force_free_wlock'):
2234 repo.vfs.tryunlink(b'wlock')
2234 repo.vfs.tryunlink(b'wlock')
2235 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
2235 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
2236 return 0
2236 return 0
2237
2237
2238 locks = []
2238 locks = []
2239 try:
2239 try:
2240 if opts.get('set_wlock'):
2240 if opts.get('set_wlock'):
2241 try:
2241 try:
2242 locks.append(repo.wlock(False))
2242 locks.append(repo.wlock(False))
2243 except error.LockHeld:
2243 except error.LockHeld:
2244 raise error.Abort(_(b'wlock is already held'))
2244 raise error.Abort(_(b'wlock is already held'))
2245 if opts.get('set_lock'):
2245 if opts.get('set_lock'):
2246 try:
2246 try:
2247 locks.append(repo.lock(False))
2247 locks.append(repo.lock(False))
2248 except error.LockHeld:
2248 except error.LockHeld:
2249 raise error.Abort(_(b'lock is already held'))
2249 raise error.Abort(_(b'lock is already held'))
2250 if len(locks):
2250 if len(locks):
2251 try:
2251 try:
2252 if ui.interactive():
2252 if ui.interactive():
2253 prompt = _(b"ready to release the lock (y)? $$ &Yes")
2253 prompt = _(b"ready to release the lock (y)? $$ &Yes")
2254 ui.promptchoice(prompt)
2254 ui.promptchoice(prompt)
2255 else:
2255 else:
2256 msg = b"%d locks held, waiting for signal\n"
2256 msg = b"%d locks held, waiting for signal\n"
2257 msg %= len(locks)
2257 msg %= len(locks)
2258 ui.status(msg)
2258 ui.status(msg)
2259 while True: # XXX wait for a signal
2259 while True: # XXX wait for a signal
2260 time.sleep(0.1)
2260 time.sleep(0.1)
2261 except KeyboardInterrupt:
2261 except KeyboardInterrupt:
2262 msg = b"signal-received releasing locks\n"
2262 msg = b"signal-received releasing locks\n"
2263 ui.status(msg)
2263 ui.status(msg)
2264 return 0
2264 return 0
2265 finally:
2265 finally:
2266 release(*locks)
2266 release(*locks)
2267
2267
2268 now = time.time()
2268 now = time.time()
2269 held = 0
2269 held = 0
2270
2270
2271 def report(vfs, name, method):
2271 def report(vfs, name, method):
2272 # this causes stale locks to get reaped for more accurate reporting
2272 # this causes stale locks to get reaped for more accurate reporting
2273 try:
2273 try:
2274 l = method(False)
2274 l = method(False)
2275 except error.LockHeld:
2275 except error.LockHeld:
2276 l = None
2276 l = None
2277
2277
2278 if l:
2278 if l:
2279 l.release()
2279 l.release()
2280 else:
2280 else:
2281 try:
2281 try:
2282 st = vfs.lstat(name)
2282 st = vfs.lstat(name)
2283 age = now - st[stat.ST_MTIME]
2283 age = now - st[stat.ST_MTIME]
2284 user = util.username(st.st_uid)
2284 user = util.username(st.st_uid)
2285 locker = vfs.readlock(name)
2285 locker = vfs.readlock(name)
2286 if b":" in locker:
2286 if b":" in locker:
2287 host, pid = locker.split(b':')
2287 host, pid = locker.split(b':')
2288 if host == socket.gethostname():
2288 if host == socket.gethostname():
2289 locker = b'user %s, process %s' % (user or b'None', pid)
2289 locker = b'user %s, process %s' % (user or b'None', pid)
2290 else:
2290 else:
2291 locker = b'user %s, process %s, host %s' % (
2291 locker = b'user %s, process %s, host %s' % (
2292 user or b'None',
2292 user or b'None',
2293 pid,
2293 pid,
2294 host,
2294 host,
2295 )
2295 )
2296 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
2296 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
2297 return 1
2297 return 1
2298 except FileNotFoundError:
2298 except FileNotFoundError:
2299 pass
2299 pass
2300
2300
2301 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
2301 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
2302 return 0
2302 return 0
2303
2303
2304 held += report(repo.svfs, b"lock", repo.lock)
2304 held += report(repo.svfs, b"lock", repo.lock)
2305 held += report(repo.vfs, b"wlock", repo.wlock)
2305 held += report(repo.vfs, b"wlock", repo.wlock)
2306
2306
2307 return held
2307 return held
2308
2308
2309
2309
2310 @command(
2310 @command(
2311 b'debugmanifestfulltextcache',
2311 b'debugmanifestfulltextcache',
2312 [
2312 [
2313 (b'', b'clear', False, _(b'clear the cache')),
2313 (b'', b'clear', False, _(b'clear the cache')),
2314 (
2314 (
2315 b'a',
2315 b'a',
2316 b'add',
2316 b'add',
2317 [],
2317 [],
2318 _(b'add the given manifest nodes to the cache'),
2318 _(b'add the given manifest nodes to the cache'),
2319 _(b'NODE'),
2319 _(b'NODE'),
2320 ),
2320 ),
2321 ],
2321 ],
2322 b'',
2322 b'',
2323 )
2323 )
2324 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2324 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2325 """show, clear or amend the contents of the manifest fulltext cache"""
2325 """show, clear or amend the contents of the manifest fulltext cache"""
2326
2326
2327 def getcache():
2327 def getcache():
2328 r = repo.manifestlog.getstorage(b'')
2328 r = repo.manifestlog.getstorage(b'')
2329 try:
2329 try:
2330 return r._fulltextcache
2330 return r._fulltextcache
2331 except AttributeError:
2331 except AttributeError:
2332 msg = _(
2332 msg = _(
2333 b"Current revlog implementation doesn't appear to have a "
2333 b"Current revlog implementation doesn't appear to have a "
2334 b"manifest fulltext cache\n"
2334 b"manifest fulltext cache\n"
2335 )
2335 )
2336 raise error.Abort(msg)
2336 raise error.Abort(msg)
2337
2337
2338 if opts.get('clear'):
2338 if opts.get('clear'):
2339 with repo.wlock():
2339 with repo.wlock():
2340 cache = getcache()
2340 cache = getcache()
2341 cache.clear(clear_persisted_data=True)
2341 cache.clear(clear_persisted_data=True)
2342 return
2342 return
2343
2343
2344 if add:
2344 if add:
2345 with repo.wlock():
2345 with repo.wlock():
2346 m = repo.manifestlog
2346 m = repo.manifestlog
2347 store = m.getstorage(b'')
2347 store = m.getstorage(b'')
2348 for n in add:
2348 for n in add:
2349 try:
2349 try:
2350 manifest = m[store.lookup(n)]
2350 manifest = m[store.lookup(n)]
2351 except error.LookupError as e:
2351 except error.LookupError as e:
2352 raise error.Abort(
2352 raise error.Abort(
2353 bytes(e), hint=b"Check your manifest node id"
2353 bytes(e), hint=b"Check your manifest node id"
2354 )
2354 )
2355 manifest.read() # stores revisision in cache too
2355 manifest.read() # stores revisision in cache too
2356 return
2356 return
2357
2357
2358 cache = getcache()
2358 cache = getcache()
2359 if not len(cache):
2359 if not len(cache):
2360 ui.write(_(b'cache empty\n'))
2360 ui.write(_(b'cache empty\n'))
2361 else:
2361 else:
2362 ui.write(
2362 ui.write(
2363 _(
2363 _(
2364 b'cache contains %d manifest entries, in order of most to '
2364 b'cache contains %d manifest entries, in order of most to '
2365 b'least recent:\n'
2365 b'least recent:\n'
2366 )
2366 )
2367 % (len(cache),)
2367 % (len(cache),)
2368 )
2368 )
2369 totalsize = 0
2369 totalsize = 0
2370 for nodeid in cache:
2370 for nodeid in cache:
2371 # Use cache.get to not update the LRU order
2371 # Use cache.get to not update the LRU order
2372 data = cache.peek(nodeid)
2372 data = cache.peek(nodeid)
2373 size = len(data)
2373 size = len(data)
2374 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2374 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2375 ui.write(
2375 ui.write(
2376 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2376 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2377 )
2377 )
2378 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2378 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2379 ui.write(
2379 ui.write(
2380 _(b'total cache data size %s, on-disk %s\n')
2380 _(b'total cache data size %s, on-disk %s\n')
2381 % (util.bytecount(totalsize), util.bytecount(ondisk))
2381 % (util.bytecount(totalsize), util.bytecount(ondisk))
2382 )
2382 )
2383
2383
2384
2384
2385 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2385 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2386 def debugmergestate(ui, repo, *args, **opts):
2386 def debugmergestate(ui, repo, *args, **opts):
2387 """print merge state
2387 """print merge state
2388
2388
2389 Use --verbose to print out information about whether v1 or v2 merge state
2389 Use --verbose to print out information about whether v1 or v2 merge state
2390 was chosen."""
2390 was chosen."""
2391
2391
2392 if ui.verbose:
2392 if ui.verbose:
2393 ms = mergestatemod.mergestate(repo)
2393 ms = mergestatemod.mergestate(repo)
2394
2394
2395 # sort so that reasonable information is on top
2395 # sort so that reasonable information is on top
2396 v1records = ms._readrecordsv1()
2396 v1records = ms._readrecordsv1()
2397 v2records = ms._readrecordsv2()
2397 v2records = ms._readrecordsv2()
2398
2398
2399 if not v1records and not v2records:
2399 if not v1records and not v2records:
2400 pass
2400 pass
2401 elif not v2records:
2401 elif not v2records:
2402 ui.writenoi18n(b'no version 2 merge state\n')
2402 ui.writenoi18n(b'no version 2 merge state\n')
2403 elif ms._v1v2match(v1records, v2records):
2403 elif ms._v1v2match(v1records, v2records):
2404 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2404 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2405 else:
2405 else:
2406 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2406 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2407
2407
2408 if not opts['template']:
2408 if not opts['template']:
2409 opts['template'] = (
2409 opts['template'] = (
2410 b'{if(commits, "", "no merge state found\n")}'
2410 b'{if(commits, "", "no merge state found\n")}'
2411 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2411 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2412 b'{files % "file: {path} (state \\"{state}\\")\n'
2412 b'{files % "file: {path} (state \\"{state}\\")\n'
2413 b'{if(local_path, "'
2413 b'{if(local_path, "'
2414 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2414 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2415 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2415 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2416 b' other path: {other_path} (node {other_node})\n'
2416 b' other path: {other_path} (node {other_node})\n'
2417 b'")}'
2417 b'")}'
2418 b'{if(rename_side, "'
2418 b'{if(rename_side, "'
2419 b' rename side: {rename_side}\n'
2419 b' rename side: {rename_side}\n'
2420 b' renamed path: {renamed_path}\n'
2420 b' renamed path: {renamed_path}\n'
2421 b'")}'
2421 b'")}'
2422 b'{extras % " extra: {key} = {value}\n"}'
2422 b'{extras % " extra: {key} = {value}\n"}'
2423 b'"}'
2423 b'"}'
2424 b'{extras % "extra: {file} ({key} = {value})\n"}'
2424 b'{extras % "extra: {file} ({key} = {value})\n"}'
2425 )
2425 )
2426
2426
2427 ms = mergestatemod.mergestate.read(repo)
2427 ms = mergestatemod.mergestate.read(repo)
2428
2428
2429 fm = ui.formatter(b'debugmergestate', pycompat.byteskwargs(opts))
2429 fm = ui.formatter(b'debugmergestate', pycompat.byteskwargs(opts))
2430 fm.startitem()
2430 fm.startitem()
2431
2431
2432 fm_commits = fm.nested(b'commits')
2432 fm_commits = fm.nested(b'commits')
2433 if ms.active():
2433 if ms.active():
2434 for name, node, label_index in (
2434 for name, node, label_index in (
2435 (b'local', ms.local, 0),
2435 (b'local', ms.local, 0),
2436 (b'other', ms.other, 1),
2436 (b'other', ms.other, 1),
2437 ):
2437 ):
2438 fm_commits.startitem()
2438 fm_commits.startitem()
2439 fm_commits.data(name=name)
2439 fm_commits.data(name=name)
2440 fm_commits.data(node=hex(node))
2440 fm_commits.data(node=hex(node))
2441 if ms._labels and len(ms._labels) > label_index:
2441 if ms._labels and len(ms._labels) > label_index:
2442 fm_commits.data(label=ms._labels[label_index])
2442 fm_commits.data(label=ms._labels[label_index])
2443 fm_commits.end()
2443 fm_commits.end()
2444
2444
2445 fm_files = fm.nested(b'files')
2445 fm_files = fm.nested(b'files')
2446 if ms.active():
2446 if ms.active():
2447 for f in ms:
2447 for f in ms:
2448 fm_files.startitem()
2448 fm_files.startitem()
2449 fm_files.data(path=f)
2449 fm_files.data(path=f)
2450 state = ms._state[f]
2450 state = ms._state[f]
2451 fm_files.data(state=state[0])
2451 fm_files.data(state=state[0])
2452 if state[0] in (
2452 if state[0] in (
2453 mergestatemod.MERGE_RECORD_UNRESOLVED,
2453 mergestatemod.MERGE_RECORD_UNRESOLVED,
2454 mergestatemod.MERGE_RECORD_RESOLVED,
2454 mergestatemod.MERGE_RECORD_RESOLVED,
2455 ):
2455 ):
2456 fm_files.data(local_key=state[1])
2456 fm_files.data(local_key=state[1])
2457 fm_files.data(local_path=state[2])
2457 fm_files.data(local_path=state[2])
2458 fm_files.data(ancestor_path=state[3])
2458 fm_files.data(ancestor_path=state[3])
2459 fm_files.data(ancestor_node=state[4])
2459 fm_files.data(ancestor_node=state[4])
2460 fm_files.data(other_path=state[5])
2460 fm_files.data(other_path=state[5])
2461 fm_files.data(other_node=state[6])
2461 fm_files.data(other_node=state[6])
2462 fm_files.data(local_flags=state[7])
2462 fm_files.data(local_flags=state[7])
2463 elif state[0] in (
2463 elif state[0] in (
2464 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2464 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2465 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2465 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2466 ):
2466 ):
2467 fm_files.data(renamed_path=state[1])
2467 fm_files.data(renamed_path=state[1])
2468 fm_files.data(rename_side=state[2])
2468 fm_files.data(rename_side=state[2])
2469 fm_extras = fm_files.nested(b'extras')
2469 fm_extras = fm_files.nested(b'extras')
2470 for k, v in sorted(ms.extras(f).items()):
2470 for k, v in sorted(ms.extras(f).items()):
2471 fm_extras.startitem()
2471 fm_extras.startitem()
2472 fm_extras.data(key=k)
2472 fm_extras.data(key=k)
2473 fm_extras.data(value=v)
2473 fm_extras.data(value=v)
2474 fm_extras.end()
2474 fm_extras.end()
2475
2475
2476 fm_files.end()
2476 fm_files.end()
2477
2477
2478 fm_extras = fm.nested(b'extras')
2478 fm_extras = fm.nested(b'extras')
2479 for f, d in sorted(ms.allextras().items()):
2479 for f, d in sorted(ms.allextras().items()):
2480 if f in ms:
2480 if f in ms:
2481 # If file is in mergestate, we have already processed it's extras
2481 # If file is in mergestate, we have already processed it's extras
2482 continue
2482 continue
2483 for k, v in d.items():
2483 for k, v in d.items():
2484 fm_extras.startitem()
2484 fm_extras.startitem()
2485 fm_extras.data(file=f)
2485 fm_extras.data(file=f)
2486 fm_extras.data(key=k)
2486 fm_extras.data(key=k)
2487 fm_extras.data(value=v)
2487 fm_extras.data(value=v)
2488 fm_extras.end()
2488 fm_extras.end()
2489
2489
2490 fm.end()
2490 fm.end()
2491
2491
2492
2492
2493 @command(b'debugnamecomplete', [], _(b'NAME...'))
2493 @command(b'debugnamecomplete', [], _(b'NAME...'))
2494 def debugnamecomplete(ui, repo, *args):
2494 def debugnamecomplete(ui, repo, *args):
2495 '''complete "names" - tags, open branch names, bookmark names'''
2495 '''complete "names" - tags, open branch names, bookmark names'''
2496
2496
2497 names = set()
2497 names = set()
2498 # since we previously only listed open branches, we will handle that
2498 # since we previously only listed open branches, we will handle that
2499 # specially (after this for loop)
2499 # specially (after this for loop)
2500 for name, ns in repo.names.items():
2500 for name, ns in repo.names.items():
2501 if name != b'branches':
2501 if name != b'branches':
2502 names.update(ns.listnames(repo))
2502 names.update(ns.listnames(repo))
2503 names.update(
2503 names.update(
2504 tag
2504 tag
2505 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2505 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2506 if not closed
2506 if not closed
2507 )
2507 )
2508 completions = set()
2508 completions = set()
2509 if not args:
2509 if not args:
2510 args = [b'']
2510 args = [b'']
2511 for a in args:
2511 for a in args:
2512 completions.update(n for n in names if n.startswith(a))
2512 completions.update(n for n in names if n.startswith(a))
2513 ui.write(b'\n'.join(sorted(completions)))
2513 ui.write(b'\n'.join(sorted(completions)))
2514 ui.write(b'\n')
2514 ui.write(b'\n')
2515
2515
2516
2516
2517 @command(
2517 @command(
2518 b'debugnodemap',
2518 b'debugnodemap',
2519 (
2519 (
2520 cmdutil.debugrevlogopts
2520 cmdutil.debugrevlogopts
2521 + [
2521 + [
2522 (
2522 (
2523 b'',
2523 b'',
2524 b'dump-new',
2524 b'dump-new',
2525 False,
2525 False,
2526 _(b'write a (new) persistent binary nodemap on stdout'),
2526 _(b'write a (new) persistent binary nodemap on stdout'),
2527 ),
2527 ),
2528 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2528 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2529 (
2529 (
2530 b'',
2530 b'',
2531 b'check',
2531 b'check',
2532 False,
2532 False,
2533 _(b'check that the data on disk data are correct.'),
2533 _(b'check that the data on disk data are correct.'),
2534 ),
2534 ),
2535 (
2535 (
2536 b'',
2536 b'',
2537 b'metadata',
2537 b'metadata',
2538 False,
2538 False,
2539 _(b'display the on disk meta data for the nodemap'),
2539 _(b'display the on disk meta data for the nodemap'),
2540 ),
2540 ),
2541 ]
2541 ]
2542 ),
2542 ),
2543 _(b'-c|-m|FILE'),
2543 _(b'-c|-m|FILE'),
2544 )
2544 )
2545 def debugnodemap(ui, repo, file_=None, **opts):
2545 def debugnodemap(ui, repo, file_=None, **opts):
2546 """write and inspect on disk nodemap"""
2546 """write and inspect on disk nodemap"""
2547 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2547 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2548 if file_ is not None:
2548 if file_ is not None:
2549 raise error.InputError(
2549 raise error.InputError(
2550 _(b'cannot specify a file with other arguments')
2550 _(b'cannot specify a file with other arguments')
2551 )
2551 )
2552 elif file_ is None:
2552 elif file_ is None:
2553 opts['changelog'] = True
2553 opts['changelog'] = True
2554 r = cmdutil.openstorage(
2554 r = cmdutil.openstorage(
2555 repo.unfiltered(), b'debugnodemap', file_, pycompat.byteskwargs(opts)
2555 repo.unfiltered(), b'debugnodemap', file_, pycompat.byteskwargs(opts)
2556 )
2556 )
2557 if isinstance(r, (manifest.manifestrevlog, filelog.filelog)):
2557 if isinstance(r, (manifest.manifestrevlog, filelog.filelog)):
2558 r = r._revlog
2558 r = r._revlog
2559 if opts['dump_new']:
2559 if opts['dump_new']:
2560 if hasattr(r.index, "nodemap_data_all"):
2560 if hasattr(r.index, "nodemap_data_all"):
2561 data = r.index.nodemap_data_all()
2561 data = r.index.nodemap_data_all()
2562 else:
2562 else:
2563 data = nodemap.persistent_data(r.index)
2563 data = nodemap.persistent_data(r.index)
2564 ui.write(data)
2564 ui.write(data)
2565 elif opts['dump_disk']:
2565 elif opts['dump_disk']:
2566 nm_data = nodemap.persisted_data(r)
2566 nm_data = nodemap.persisted_data(r)
2567 if nm_data is not None:
2567 if nm_data is not None:
2568 docket, data = nm_data
2568 docket, data = nm_data
2569 ui.write(data[:])
2569 ui.write(data[:])
2570 elif opts['check']:
2570 elif opts['check']:
2571 nm_data = nodemap.persisted_data(r)
2571 nm_data = nodemap.persisted_data(r)
2572 if nm_data is not None:
2572 if nm_data is not None:
2573 docket, data = nm_data
2573 docket, data = nm_data
2574 return nodemap.check_data(ui, r.index, data)
2574 return nodemap.check_data(ui, r.index, data)
2575 elif opts['metadata']:
2575 elif opts['metadata']:
2576 nm_data = nodemap.persisted_data(r)
2576 nm_data = nodemap.persisted_data(r)
2577 if nm_data is not None:
2577 if nm_data is not None:
2578 docket, data = nm_data
2578 docket, data = nm_data
2579 ui.write((b"uid: %s\n") % docket.uid)
2579 ui.write((b"uid: %s\n") % docket.uid)
2580 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2580 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2581 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2581 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2582 ui.write((b"data-length: %d\n") % docket.data_length)
2582 ui.write((b"data-length: %d\n") % docket.data_length)
2583 ui.write((b"data-unused: %d\n") % docket.data_unused)
2583 ui.write((b"data-unused: %d\n") % docket.data_unused)
2584 unused_perc = docket.data_unused * 100.0 / docket.data_length
2584 unused_perc = docket.data_unused * 100.0 / docket.data_length
2585 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2585 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2586
2586
2587
2587
2588 @command(
2588 @command(
2589 b'debugobsolete',
2589 b'debugobsolete',
2590 [
2590 [
2591 (b'', b'flags', 0, _(b'markers flag')),
2591 (b'', b'flags', 0, _(b'markers flag')),
2592 (
2592 (
2593 b'',
2593 b'',
2594 b'record-parents',
2594 b'record-parents',
2595 False,
2595 False,
2596 _(b'record parent information for the precursor'),
2596 _(b'record parent information for the precursor'),
2597 ),
2597 ),
2598 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2598 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2599 (
2599 (
2600 b'',
2600 b'',
2601 b'exclusive',
2601 b'exclusive',
2602 False,
2602 False,
2603 _(b'restrict display to markers only relevant to REV'),
2603 _(b'restrict display to markers only relevant to REV'),
2604 ),
2604 ),
2605 (b'', b'index', False, _(b'display index of the marker')),
2605 (b'', b'index', False, _(b'display index of the marker')),
2606 (b'', b'delete', [], _(b'delete markers specified by indices')),
2606 (b'', b'delete', [], _(b'delete markers specified by indices')),
2607 ]
2607 ]
2608 + cmdutil.commitopts2
2608 + cmdutil.commitopts2
2609 + cmdutil.formatteropts,
2609 + cmdutil.formatteropts,
2610 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2610 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2611 )
2611 )
2612 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2612 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2613 """create arbitrary obsolete marker
2613 """create arbitrary obsolete marker
2614
2614
2615 With no arguments, displays the list of obsolescence markers."""
2615 With no arguments, displays the list of obsolescence markers."""
2616
2616
2617 def parsenodeid(s):
2617 def parsenodeid(s):
2618 try:
2618 try:
2619 # We do not use revsingle/revrange functions here to accept
2619 # We do not use revsingle/revrange functions here to accept
2620 # arbitrary node identifiers, possibly not present in the
2620 # arbitrary node identifiers, possibly not present in the
2621 # local repository.
2621 # local repository.
2622 n = bin(s)
2622 n = bin(s)
2623 if len(n) != repo.nodeconstants.nodelen:
2623 if len(n) != repo.nodeconstants.nodelen:
2624 raise ValueError
2624 raise ValueError
2625 return n
2625 return n
2626 except ValueError:
2626 except ValueError:
2627 raise error.InputError(
2627 raise error.InputError(
2628 b'changeset references must be full hexadecimal '
2628 b'changeset references must be full hexadecimal '
2629 b'node identifiers'
2629 b'node identifiers'
2630 )
2630 )
2631
2631
2632 if opts.get('delete'):
2632 if opts.get('delete'):
2633 indices = []
2633 indices = []
2634 for v in opts.get('delete'):
2634 for v in opts.get('delete'):
2635 try:
2635 try:
2636 indices.append(int(v))
2636 indices.append(int(v))
2637 except ValueError:
2637 except ValueError:
2638 raise error.InputError(
2638 raise error.InputError(
2639 _(b'invalid index value: %r') % v,
2639 _(b'invalid index value: %r') % v,
2640 hint=_(b'use integers for indices'),
2640 hint=_(b'use integers for indices'),
2641 )
2641 )
2642
2642
2643 if repo.currenttransaction():
2643 if repo.currenttransaction():
2644 raise error.Abort(
2644 raise error.Abort(
2645 _(b'cannot delete obsmarkers in the middle of transaction.')
2645 _(b'cannot delete obsmarkers in the middle of transaction.')
2646 )
2646 )
2647
2647
2648 with repo.lock():
2648 with repo.lock():
2649 n = repair.deleteobsmarkers(repo.obsstore, indices)
2649 n = repair.deleteobsmarkers(repo.obsstore, indices)
2650 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2650 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2651
2651
2652 return
2652 return
2653
2653
2654 if precursor is not None:
2654 if precursor is not None:
2655 if opts['rev']:
2655 if opts['rev']:
2656 raise error.InputError(
2656 raise error.InputError(
2657 b'cannot select revision when creating marker'
2657 b'cannot select revision when creating marker'
2658 )
2658 )
2659 metadata = {}
2659 metadata = {}
2660 metadata[b'user'] = encoding.fromlocal(opts['user'] or ui.username())
2660 metadata[b'user'] = encoding.fromlocal(opts['user'] or ui.username())
2661 succs = tuple(parsenodeid(succ) for succ in successors)
2661 succs = tuple(parsenodeid(succ) for succ in successors)
2662 l = repo.lock()
2662 l = repo.lock()
2663 try:
2663 try:
2664 tr = repo.transaction(b'debugobsolete')
2664 tr = repo.transaction(b'debugobsolete')
2665 try:
2665 try:
2666 date = opts.get('date')
2666 date = opts.get('date')
2667 if date:
2667 if date:
2668 date = dateutil.parsedate(date)
2668 date = dateutil.parsedate(date)
2669 else:
2669 else:
2670 date = None
2670 date = None
2671 prec = parsenodeid(precursor)
2671 prec = parsenodeid(precursor)
2672 parents = None
2672 parents = None
2673 if opts['record_parents']:
2673 if opts['record_parents']:
2674 if prec not in repo.unfiltered():
2674 if prec not in repo.unfiltered():
2675 raise error.Abort(
2675 raise error.Abort(
2676 b'cannot used --record-parents on '
2676 b'cannot used --record-parents on '
2677 b'unknown changesets'
2677 b'unknown changesets'
2678 )
2678 )
2679 parents = repo.unfiltered()[prec].parents()
2679 parents = repo.unfiltered()[prec].parents()
2680 parents = tuple(p.node() for p in parents)
2680 parents = tuple(p.node() for p in parents)
2681 repo.obsstore.create(
2681 repo.obsstore.create(
2682 tr,
2682 tr,
2683 prec,
2683 prec,
2684 succs,
2684 succs,
2685 opts['flags'],
2685 opts['flags'],
2686 parents=parents,
2686 parents=parents,
2687 date=date,
2687 date=date,
2688 metadata=metadata,
2688 metadata=metadata,
2689 ui=ui,
2689 ui=ui,
2690 )
2690 )
2691 tr.close()
2691 tr.close()
2692 except ValueError as exc:
2692 except ValueError as exc:
2693 raise error.Abort(
2693 raise error.Abort(
2694 _(b'bad obsmarker input: %s') % stringutil.forcebytestr(exc)
2694 _(b'bad obsmarker input: %s') % stringutil.forcebytestr(exc)
2695 )
2695 )
2696 finally:
2696 finally:
2697 tr.release()
2697 tr.release()
2698 finally:
2698 finally:
2699 l.release()
2699 l.release()
2700 else:
2700 else:
2701 if opts['rev']:
2701 if opts['rev']:
2702 revs = logcmdutil.revrange(repo, opts['rev'])
2702 revs = logcmdutil.revrange(repo, opts['rev'])
2703 nodes = [repo[r].node() for r in revs]
2703 nodes = [repo[r].node() for r in revs]
2704 markers = list(
2704 markers = list(
2705 obsutil.getmarkers(
2705 obsutil.getmarkers(
2706 repo, nodes=nodes, exclusive=opts['exclusive']
2706 repo, nodes=nodes, exclusive=opts['exclusive']
2707 )
2707 )
2708 )
2708 )
2709 markers.sort(key=lambda x: x._data)
2709 markers.sort(key=lambda x: x._data)
2710 else:
2710 else:
2711 markers = obsutil.getmarkers(repo)
2711 markers = obsutil.getmarkers(repo)
2712
2712
2713 markerstoiter = markers
2713 markerstoiter = markers
2714 isrelevant = lambda m: True
2714 isrelevant = lambda m: True
2715 if opts.get('rev') and opts.get('index'):
2715 if opts.get('rev') and opts.get('index'):
2716 markerstoiter = obsutil.getmarkers(repo)
2716 markerstoiter = obsutil.getmarkers(repo)
2717 markerset = set(markers)
2717 markerset = set(markers)
2718 isrelevant = lambda m: m in markerset
2718 isrelevant = lambda m: m in markerset
2719
2719
2720 fm = ui.formatter(b'debugobsolete', pycompat.byteskwargs(opts))
2720 fm = ui.formatter(b'debugobsolete', pycompat.byteskwargs(opts))
2721 for i, m in enumerate(markerstoiter):
2721 for i, m in enumerate(markerstoiter):
2722 if not isrelevant(m):
2722 if not isrelevant(m):
2723 # marker can be irrelevant when we're iterating over a set
2723 # marker can be irrelevant when we're iterating over a set
2724 # of markers (markerstoiter) which is bigger than the set
2724 # of markers (markerstoiter) which is bigger than the set
2725 # of markers we want to display (markers)
2725 # of markers we want to display (markers)
2726 # this can happen if both --index and --rev options are
2726 # this can happen if both --index and --rev options are
2727 # provided and thus we need to iterate over all of the markers
2727 # provided and thus we need to iterate over all of the markers
2728 # to get the correct indices, but only display the ones that
2728 # to get the correct indices, but only display the ones that
2729 # are relevant to --rev value
2729 # are relevant to --rev value
2730 continue
2730 continue
2731 fm.startitem()
2731 fm.startitem()
2732 ind = i if opts.get('index') else None
2732 ind = i if opts.get('index') else None
2733 cmdutil.showmarker(fm, m, index=ind)
2733 cmdutil.showmarker(fm, m, index=ind)
2734 fm.end()
2734 fm.end()
2735
2735
2736
2736
2737 @command(
2737 @command(
2738 b'debugp1copies',
2738 b'debugp1copies',
2739 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2739 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2740 _(b'[-r REV]'),
2740 _(b'[-r REV]'),
2741 )
2741 )
2742 def debugp1copies(ui, repo, **opts):
2742 def debugp1copies(ui, repo, **opts):
2743 """dump copy information compared to p1"""
2743 """dump copy information compared to p1"""
2744
2744
2745 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
2745 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
2746 for dst, src in ctx.p1copies().items():
2746 for dst, src in ctx.p1copies().items():
2747 ui.write(b'%s -> %s\n' % (src, dst))
2747 ui.write(b'%s -> %s\n' % (src, dst))
2748
2748
2749
2749
2750 @command(
2750 @command(
2751 b'debugp2copies',
2751 b'debugp2copies',
2752 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2752 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2753 _(b'[-r REV]'),
2753 _(b'[-r REV]'),
2754 )
2754 )
2755 def debugp2copies(ui, repo, **opts):
2755 def debugp2copies(ui, repo, **opts):
2756 """dump copy information compared to p2"""
2756 """dump copy information compared to p2"""
2757
2757
2758 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
2758 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
2759 for dst, src in ctx.p2copies().items():
2759 for dst, src in ctx.p2copies().items():
2760 ui.write(b'%s -> %s\n' % (src, dst))
2760 ui.write(b'%s -> %s\n' % (src, dst))
2761
2761
2762
2762
2763 @command(
2763 @command(
2764 b'debugpathcomplete',
2764 b'debugpathcomplete',
2765 [
2765 [
2766 (b'f', b'full', None, _(b'complete an entire path')),
2766 (b'f', b'full', None, _(b'complete an entire path')),
2767 (b'n', b'normal', None, _(b'show only normal files')),
2767 (b'n', b'normal', None, _(b'show only normal files')),
2768 (b'a', b'added', None, _(b'show only added files')),
2768 (b'a', b'added', None, _(b'show only added files')),
2769 (b'r', b'removed', None, _(b'show only removed files')),
2769 (b'r', b'removed', None, _(b'show only removed files')),
2770 ],
2770 ],
2771 _(b'FILESPEC...'),
2771 _(b'FILESPEC...'),
2772 )
2772 )
2773 def debugpathcomplete(ui, repo, *specs, **opts):
2773 def debugpathcomplete(ui, repo, *specs, **opts):
2774 """complete part or all of a tracked path
2774 """complete part or all of a tracked path
2775
2775
2776 This command supports shells that offer path name completion. It
2776 This command supports shells that offer path name completion. It
2777 currently completes only files already known to the dirstate.
2777 currently completes only files already known to the dirstate.
2778
2778
2779 Completion extends only to the next path segment unless
2779 Completion extends only to the next path segment unless
2780 --full is specified, in which case entire paths are used."""
2780 --full is specified, in which case entire paths are used."""
2781
2781
2782 def complete(path, acceptable):
2782 def complete(path, acceptable):
2783 dirstate = repo.dirstate
2783 dirstate = repo.dirstate
2784 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2784 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2785 rootdir = repo.root + pycompat.ossep
2785 rootdir = repo.root + pycompat.ossep
2786 if spec != repo.root and not spec.startswith(rootdir):
2786 if spec != repo.root and not spec.startswith(rootdir):
2787 return [], []
2787 return [], []
2788 if os.path.isdir(spec):
2788 if os.path.isdir(spec):
2789 spec += b'/'
2789 spec += b'/'
2790 spec = spec[len(rootdir) :]
2790 spec = spec[len(rootdir) :]
2791 fixpaths = pycompat.ossep != b'/'
2791 fixpaths = pycompat.ossep != b'/'
2792 if fixpaths:
2792 if fixpaths:
2793 spec = spec.replace(pycompat.ossep, b'/')
2793 spec = spec.replace(pycompat.ossep, b'/')
2794 speclen = len(spec)
2794 speclen = len(spec)
2795 fullpaths = opts['full']
2795 fullpaths = opts['full']
2796 files, dirs = set(), set()
2796 files, dirs = set(), set()
2797 adddir, addfile = dirs.add, files.add
2797 adddir, addfile = dirs.add, files.add
2798 for f, st in dirstate.items():
2798 for f, st in dirstate.items():
2799 if f.startswith(spec) and st.state in acceptable:
2799 if f.startswith(spec) and st.state in acceptable:
2800 if fixpaths:
2800 if fixpaths:
2801 f = f.replace(b'/', pycompat.ossep)
2801 f = f.replace(b'/', pycompat.ossep)
2802 if fullpaths:
2802 if fullpaths:
2803 addfile(f)
2803 addfile(f)
2804 continue
2804 continue
2805 s = f.find(pycompat.ossep, speclen)
2805 s = f.find(pycompat.ossep, speclen)
2806 if s >= 0:
2806 if s >= 0:
2807 adddir(f[:s])
2807 adddir(f[:s])
2808 else:
2808 else:
2809 addfile(f)
2809 addfile(f)
2810 return files, dirs
2810 return files, dirs
2811
2811
2812 acceptable = b''
2812 acceptable = b''
2813 if opts['normal']:
2813 if opts['normal']:
2814 acceptable += b'nm'
2814 acceptable += b'nm'
2815 if opts['added']:
2815 if opts['added']:
2816 acceptable += b'a'
2816 acceptable += b'a'
2817 if opts['removed']:
2817 if opts['removed']:
2818 acceptable += b'r'
2818 acceptable += b'r'
2819 cwd = repo.getcwd()
2819 cwd = repo.getcwd()
2820 if not specs:
2820 if not specs:
2821 specs = [b'.']
2821 specs = [b'.']
2822
2822
2823 files, dirs = set(), set()
2823 files, dirs = set(), set()
2824 for spec in specs:
2824 for spec in specs:
2825 f, d = complete(spec, acceptable or b'nmar')
2825 f, d = complete(spec, acceptable or b'nmar')
2826 files.update(f)
2826 files.update(f)
2827 dirs.update(d)
2827 dirs.update(d)
2828 files.update(dirs)
2828 files.update(dirs)
2829 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2829 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2830 ui.write(b'\n')
2830 ui.write(b'\n')
2831
2831
2832
2832
2833 @command(
2833 @command(
2834 b'debugpathcopies',
2834 b'debugpathcopies',
2835 cmdutil.walkopts,
2835 cmdutil.walkopts,
2836 b'hg debugpathcopies REV1 REV2 [FILE]',
2836 b'hg debugpathcopies REV1 REV2 [FILE]',
2837 inferrepo=True,
2837 inferrepo=True,
2838 )
2838 )
2839 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2839 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2840 """show copies between two revisions"""
2840 """show copies between two revisions"""
2841 ctx1 = scmutil.revsingle(repo, rev1)
2841 ctx1 = scmutil.revsingle(repo, rev1)
2842 ctx2 = scmutil.revsingle(repo, rev2)
2842 ctx2 = scmutil.revsingle(repo, rev2)
2843 m = scmutil.match(ctx1, pats, opts)
2843 m = scmutil.match(ctx1, pats, opts)
2844 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2844 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2845 ui.write(b'%s -> %s\n' % (src, dst))
2845 ui.write(b'%s -> %s\n' % (src, dst))
2846
2846
2847
2847
2848 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2848 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2849 def debugpeer(ui, path):
2849 def debugpeer(ui, path):
2850 """establish a connection to a peer repository"""
2850 """establish a connection to a peer repository"""
2851 # Always enable peer request logging. Requires --debug to display
2851 # Always enable peer request logging. Requires --debug to display
2852 # though.
2852 # though.
2853 overrides = {
2853 overrides = {
2854 (b'devel', b'debug.peer-request'): True,
2854 (b'devel', b'debug.peer-request'): True,
2855 }
2855 }
2856
2856
2857 with ui.configoverride(overrides):
2857 with ui.configoverride(overrides):
2858 peer = hg.peer(ui, {}, path)
2858 peer = hg.peer(ui, {}, path)
2859
2859
2860 try:
2860 try:
2861 local = peer.local() is not None
2861 local = peer.local() is not None
2862 canpush = peer.canpush()
2862 canpush = peer.canpush()
2863
2863
2864 ui.write(_(b'url: %s\n') % peer.url())
2864 ui.write(_(b'url: %s\n') % peer.url())
2865 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2865 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2866 ui.write(
2866 ui.write(
2867 _(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no'))
2867 _(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no'))
2868 )
2868 )
2869 finally:
2869 finally:
2870 peer.close()
2870 peer.close()
2871
2871
2872
2872
2873 @command(
2873 @command(
2874 b'debugpickmergetool',
2874 b'debugpickmergetool',
2875 [
2875 [
2876 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2876 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2877 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2877 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2878 ]
2878 ]
2879 + cmdutil.walkopts
2879 + cmdutil.walkopts
2880 + cmdutil.mergetoolopts,
2880 + cmdutil.mergetoolopts,
2881 _(b'[PATTERN]...'),
2881 _(b'[PATTERN]...'),
2882 inferrepo=True,
2882 inferrepo=True,
2883 )
2883 )
2884 def debugpickmergetool(ui, repo, *pats, **opts):
2884 def debugpickmergetool(ui, repo, *pats, **opts):
2885 """examine which merge tool is chosen for specified file
2885 """examine which merge tool is chosen for specified file
2886
2886
2887 As described in :hg:`help merge-tools`, Mercurial examines
2887 As described in :hg:`help merge-tools`, Mercurial examines
2888 configurations below in this order to decide which merge tool is
2888 configurations below in this order to decide which merge tool is
2889 chosen for specified file.
2889 chosen for specified file.
2890
2890
2891 1. ``--tool`` option
2891 1. ``--tool`` option
2892 2. ``HGMERGE`` environment variable
2892 2. ``HGMERGE`` environment variable
2893 3. configurations in ``merge-patterns`` section
2893 3. configurations in ``merge-patterns`` section
2894 4. configuration of ``ui.merge``
2894 4. configuration of ``ui.merge``
2895 5. configurations in ``merge-tools`` section
2895 5. configurations in ``merge-tools`` section
2896 6. ``hgmerge`` tool (for historical reason only)
2896 6. ``hgmerge`` tool (for historical reason only)
2897 7. default tool for fallback (``:merge`` or ``:prompt``)
2897 7. default tool for fallback (``:merge`` or ``:prompt``)
2898
2898
2899 This command writes out examination result in the style below::
2899 This command writes out examination result in the style below::
2900
2900
2901 FILE = MERGETOOL
2901 FILE = MERGETOOL
2902
2902
2903 By default, all files known in the first parent context of the
2903 By default, all files known in the first parent context of the
2904 working directory are examined. Use file patterns and/or -I/-X
2904 working directory are examined. Use file patterns and/or -I/-X
2905 options to limit target files. -r/--rev is also useful to examine
2905 options to limit target files. -r/--rev is also useful to examine
2906 files in another context without actual updating to it.
2906 files in another context without actual updating to it.
2907
2907
2908 With --debug, this command shows warning messages while matching
2908 With --debug, this command shows warning messages while matching
2909 against ``merge-patterns`` and so on, too. It is recommended to
2909 against ``merge-patterns`` and so on, too. It is recommended to
2910 use this option with explicit file patterns and/or -I/-X options,
2910 use this option with explicit file patterns and/or -I/-X options,
2911 because this option increases amount of output per file according
2911 because this option increases amount of output per file according
2912 to configurations in hgrc.
2912 to configurations in hgrc.
2913
2913
2914 With -v/--verbose, this command shows configurations below at
2914 With -v/--verbose, this command shows configurations below at
2915 first (only if specified).
2915 first (only if specified).
2916
2916
2917 - ``--tool`` option
2917 - ``--tool`` option
2918 - ``HGMERGE`` environment variable
2918 - ``HGMERGE`` environment variable
2919 - configuration of ``ui.merge``
2919 - configuration of ``ui.merge``
2920
2920
2921 If merge tool is chosen before matching against
2921 If merge tool is chosen before matching against
2922 ``merge-patterns``, this command can't show any helpful
2922 ``merge-patterns``, this command can't show any helpful
2923 information, even with --debug. In such case, information above is
2923 information, even with --debug. In such case, information above is
2924 useful to know why a merge tool is chosen.
2924 useful to know why a merge tool is chosen.
2925 """
2925 """
2926 overrides = {}
2926 overrides = {}
2927 if opts['tool']:
2927 if opts['tool']:
2928 overrides[(b'ui', b'forcemerge')] = opts['tool']
2928 overrides[(b'ui', b'forcemerge')] = opts['tool']
2929 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts['tool'])))
2929 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts['tool'])))
2930
2930
2931 with ui.configoverride(overrides, b'debugmergepatterns'):
2931 with ui.configoverride(overrides, b'debugmergepatterns'):
2932 hgmerge = encoding.environ.get(b"HGMERGE")
2932 hgmerge = encoding.environ.get(b"HGMERGE")
2933 if hgmerge is not None:
2933 if hgmerge is not None:
2934 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
2934 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
2935 uimerge = ui.config(b"ui", b"merge")
2935 uimerge = ui.config(b"ui", b"merge")
2936 if uimerge:
2936 if uimerge:
2937 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
2937 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
2938
2938
2939 ctx = scmutil.revsingle(repo, opts.get('rev'))
2939 ctx = scmutil.revsingle(repo, opts.get('rev'))
2940 m = scmutil.match(ctx, pats, pycompat.byteskwargs(opts))
2940 m = scmutil.match(ctx, pats, pycompat.byteskwargs(opts))
2941 changedelete = opts['changedelete']
2941 changedelete = opts['changedelete']
2942 for path in ctx.walk(m):
2942 for path in ctx.walk(m):
2943 fctx = ctx[path]
2943 fctx = ctx[path]
2944 with ui.silent(
2944 with ui.silent(
2945 error=True
2945 error=True
2946 ) if not ui.debugflag else util.nullcontextmanager():
2946 ) if not ui.debugflag else util.nullcontextmanager():
2947 tool, toolpath = filemerge._picktool(
2947 tool, toolpath = filemerge._picktool(
2948 repo,
2948 repo,
2949 ui,
2949 ui,
2950 path,
2950 path,
2951 fctx.isbinary(),
2951 fctx.isbinary(),
2952 b'l' in fctx.flags(),
2952 b'l' in fctx.flags(),
2953 changedelete,
2953 changedelete,
2954 )
2954 )
2955 ui.write(b'%s = %s\n' % (path, tool))
2955 ui.write(b'%s = %s\n' % (path, tool))
2956
2956
2957
2957
2958 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2958 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2959 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2959 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2960 """access the pushkey key/value protocol
2960 """access the pushkey key/value protocol
2961
2961
2962 With two args, list the keys in the given namespace.
2962 With two args, list the keys in the given namespace.
2963
2963
2964 With five args, set a key to new if it currently is set to old.
2964 With five args, set a key to new if it currently is set to old.
2965 Reports success or failure.
2965 Reports success or failure.
2966 """
2966 """
2967
2967
2968 target = hg.peer(ui, {}, repopath)
2968 target = hg.peer(ui, {}, repopath)
2969 try:
2969 try:
2970 if keyinfo:
2970 if keyinfo:
2971 key, old, new = keyinfo
2971 key, old, new = keyinfo
2972 with target.commandexecutor() as e:
2972 with target.commandexecutor() as e:
2973 r = e.callcommand(
2973 r = e.callcommand(
2974 b'pushkey',
2974 b'pushkey',
2975 {
2975 {
2976 b'namespace': namespace,
2976 b'namespace': namespace,
2977 b'key': key,
2977 b'key': key,
2978 b'old': old,
2978 b'old': old,
2979 b'new': new,
2979 b'new': new,
2980 },
2980 },
2981 ).result()
2981 ).result()
2982
2982
2983 ui.status(pycompat.bytestr(r) + b'\n')
2983 ui.status(pycompat.bytestr(r) + b'\n')
2984 return not r
2984 return not r
2985 else:
2985 else:
2986 for k, v in sorted(target.listkeys(namespace).items()):
2986 for k, v in sorted(target.listkeys(namespace).items()):
2987 ui.write(
2987 ui.write(
2988 b"%s\t%s\n"
2988 b"%s\t%s\n"
2989 % (stringutil.escapestr(k), stringutil.escapestr(v))
2989 % (stringutil.escapestr(k), stringutil.escapestr(v))
2990 )
2990 )
2991 finally:
2991 finally:
2992 target.close()
2992 target.close()
2993
2993
2994
2994
2995 @command(b'debugpvec', [], _(b'A B'))
2995 @command(b'debugpvec', [], _(b'A B'))
2996 def debugpvec(ui, repo, a, b=None):
2996 def debugpvec(ui, repo, a, b=None):
2997 ca = scmutil.revsingle(repo, a)
2997 ca = scmutil.revsingle(repo, a)
2998 cb = scmutil.revsingle(repo, b)
2998 cb = scmutil.revsingle(repo, b)
2999 pa = pvec.ctxpvec(ca)
2999 pa = pvec.ctxpvec(ca)
3000 pb = pvec.ctxpvec(cb)
3000 pb = pvec.ctxpvec(cb)
3001 if pa == pb:
3001 if pa == pb:
3002 rel = b"="
3002 rel = b"="
3003 elif pa > pb:
3003 elif pa > pb:
3004 rel = b">"
3004 rel = b">"
3005 elif pa < pb:
3005 elif pa < pb:
3006 rel = b"<"
3006 rel = b"<"
3007 elif pa | pb:
3007 elif pa | pb:
3008 rel = b"|"
3008 rel = b"|"
3009 ui.write(_(b"a: %s\n") % pa)
3009 ui.write(_(b"a: %s\n") % pa)
3010 ui.write(_(b"b: %s\n") % pb)
3010 ui.write(_(b"b: %s\n") % pb)
3011 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3011 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3012 ui.write(
3012 ui.write(
3013 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
3013 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
3014 % (
3014 % (
3015 abs(pa._depth - pb._depth),
3015 abs(pa._depth - pb._depth),
3016 pvec._hamming(pa._vec, pb._vec),
3016 pvec._hamming(pa._vec, pb._vec),
3017 pa.distance(pb),
3017 pa.distance(pb),
3018 rel,
3018 rel,
3019 )
3019 )
3020 )
3020 )
3021
3021
3022
3022
3023 @command(
3023 @command(
3024 b'debugrebuilddirstate|debugrebuildstate',
3024 b'debugrebuilddirstate|debugrebuildstate',
3025 [
3025 [
3026 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
3026 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
3027 (
3027 (
3028 b'',
3028 b'',
3029 b'minimal',
3029 b'minimal',
3030 None,
3030 None,
3031 _(
3031 _(
3032 b'only rebuild files that are inconsistent with '
3032 b'only rebuild files that are inconsistent with '
3033 b'the working copy parent'
3033 b'the working copy parent'
3034 ),
3034 ),
3035 ),
3035 ),
3036 ],
3036 ],
3037 _(b'[-r REV]'),
3037 _(b'[-r REV]'),
3038 )
3038 )
3039 def debugrebuilddirstate(ui, repo, rev, **opts):
3039 def debugrebuilddirstate(ui, repo, rev, **opts):
3040 """rebuild the dirstate as it would look like for the given revision
3040 """rebuild the dirstate as it would look like for the given revision
3041
3041
3042 If no revision is specified the first current parent will be used.
3042 If no revision is specified the first current parent will be used.
3043
3043
3044 The dirstate will be set to the files of the given revision.
3044 The dirstate will be set to the files of the given revision.
3045 The actual working directory content or existing dirstate
3045 The actual working directory content or existing dirstate
3046 information such as adds or removes is not considered.
3046 information such as adds or removes is not considered.
3047
3047
3048 ``minimal`` will only rebuild the dirstate status for files that claim to be
3048 ``minimal`` will only rebuild the dirstate status for files that claim to be
3049 tracked but are not in the parent manifest, or that exist in the parent
3049 tracked but are not in the parent manifest, or that exist in the parent
3050 manifest but are not in the dirstate. It will not change adds, removes, or
3050 manifest but are not in the dirstate. It will not change adds, removes, or
3051 modified files that are in the working copy parent.
3051 modified files that are in the working copy parent.
3052
3052
3053 One use of this command is to make the next :hg:`status` invocation
3053 One use of this command is to make the next :hg:`status` invocation
3054 check the actual file content.
3054 check the actual file content.
3055 """
3055 """
3056 ctx = scmutil.revsingle(repo, rev)
3056 ctx = scmutil.revsingle(repo, rev)
3057 with repo.wlock():
3057 with repo.wlock():
3058 if repo.currenttransaction() is not None:
3058 if repo.currenttransaction() is not None:
3059 msg = b'rebuild the dirstate outside of a transaction'
3059 msg = b'rebuild the dirstate outside of a transaction'
3060 raise error.ProgrammingError(msg)
3060 raise error.ProgrammingError(msg)
3061 dirstate = repo.dirstate
3061 dirstate = repo.dirstate
3062 changedfiles = None
3062 changedfiles = None
3063 # See command doc for what minimal does.
3063 # See command doc for what minimal does.
3064 if opts.get('minimal'):
3064 if opts.get('minimal'):
3065 manifestfiles = set(ctx.manifest().keys())
3065 manifestfiles = set(ctx.manifest().keys())
3066 dirstatefiles = set(dirstate)
3066 dirstatefiles = set(dirstate)
3067 manifestonly = manifestfiles - dirstatefiles
3067 manifestonly = manifestfiles - dirstatefiles
3068 dsonly = dirstatefiles - manifestfiles
3068 dsonly = dirstatefiles - manifestfiles
3069 dsnotadded = {f for f in dsonly if not dirstate.get_entry(f).added}
3069 dsnotadded = {f for f in dsonly if not dirstate.get_entry(f).added}
3070 changedfiles = manifestonly | dsnotadded
3070 changedfiles = manifestonly | dsnotadded
3071
3071
3072 with dirstate.changing_parents(repo):
3072 with dirstate.changing_parents(repo):
3073 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3073 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3074
3074
3075
3075
3076 @command(
3076 @command(
3077 b'debugrebuildfncache',
3077 b'debugrebuildfncache',
3078 [
3078 [
3079 (
3079 (
3080 b'',
3080 b'',
3081 b'only-data',
3081 b'only-data',
3082 False,
3082 False,
3083 _(b'only look for wrong .d files (much faster)'),
3083 _(b'only look for wrong .d files (much faster)'),
3084 )
3084 )
3085 ],
3085 ],
3086 b'',
3086 b'',
3087 )
3087 )
3088 def debugrebuildfncache(ui, repo, **opts):
3088 def debugrebuildfncache(ui, repo, **opts):
3089 """rebuild the fncache file"""
3089 """rebuild the fncache file"""
3090 repair.rebuildfncache(ui, repo, opts.get("only_data"))
3090 repair.rebuildfncache(ui, repo, opts.get("only_data"))
3091
3091
3092
3092
3093 @command(
3093 @command(
3094 b'debugrename',
3094 b'debugrename',
3095 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
3095 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
3096 _(b'[-r REV] [FILE]...'),
3096 _(b'[-r REV] [FILE]...'),
3097 )
3097 )
3098 def debugrename(ui, repo, *pats, **opts):
3098 def debugrename(ui, repo, *pats, **opts):
3099 """dump rename information"""
3099 """dump rename information"""
3100
3100
3101 ctx = scmutil.revsingle(repo, opts.get('rev'))
3101 ctx = scmutil.revsingle(repo, opts.get('rev'))
3102 m = scmutil.match(ctx, pats, pycompat.byteskwargs(opts))
3102 m = scmutil.match(ctx, pats, pycompat.byteskwargs(opts))
3103 for abs in ctx.walk(m):
3103 for abs in ctx.walk(m):
3104 fctx = ctx[abs]
3104 fctx = ctx[abs]
3105 o = fctx.filelog().renamed(fctx.filenode())
3105 o = fctx.filelog().renamed(fctx.filenode())
3106 rel = repo.pathto(abs)
3106 rel = repo.pathto(abs)
3107 if o:
3107 if o:
3108 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3108 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3109 else:
3109 else:
3110 ui.write(_(b"%s not renamed\n") % rel)
3110 ui.write(_(b"%s not renamed\n") % rel)
3111
3111
3112
3112
3113 @command(b'debugrequires|debugrequirements', [], b'')
3113 @command(b'debugrequires|debugrequirements', [], b'')
3114 def debugrequirements(ui, repo):
3114 def debugrequirements(ui, repo):
3115 """print the current repo requirements"""
3115 """print the current repo requirements"""
3116 for r in sorted(repo.requirements):
3116 for r in sorted(repo.requirements):
3117 ui.write(b"%s\n" % r)
3117 ui.write(b"%s\n" % r)
3118
3118
3119
3119
3120 @command(
3120 @command(
3121 b'debugrevlog',
3121 b'debugrevlog',
3122 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
3122 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
3123 _(b'-c|-m|FILE'),
3123 _(b'-c|-m|FILE'),
3124 optionalrepo=True,
3124 optionalrepo=True,
3125 )
3125 )
3126 def debugrevlog(ui, repo, file_=None, **opts):
3126 def debugrevlog(ui, repo, file_=None, **opts):
3127 """show data and statistics about a revlog"""
3127 """show data and statistics about a revlog"""
3128 r = cmdutil.openrevlog(
3128 r = cmdutil.openrevlog(
3129 repo, b'debugrevlog', file_, pycompat.byteskwargs(opts)
3129 repo, b'debugrevlog', file_, pycompat.byteskwargs(opts)
3130 )
3130 )
3131
3131
3132 if opts.get("dump"):
3132 if opts.get("dump"):
3133 revlog_debug.dump(ui, r)
3133 revlog_debug.dump(ui, r)
3134 else:
3134 else:
3135 revlog_debug.debug_revlog(ui, r)
3135 revlog_debug.debug_revlog(ui, r)
3136 return 0
3136 return 0
3137
3137
3138
3138
3139 @command(
3139 @command(
3140 b'debugrevlogindex',
3140 b'debugrevlogindex',
3141 cmdutil.debugrevlogopts
3141 cmdutil.debugrevlogopts
3142 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3142 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3143 _(b'[-f FORMAT] -c|-m|FILE'),
3143 _(b'[-f FORMAT] -c|-m|FILE'),
3144 optionalrepo=True,
3144 optionalrepo=True,
3145 )
3145 )
3146 def debugrevlogindex(ui, repo, file_=None, **opts):
3146 def debugrevlogindex(ui, repo, file_=None, **opts):
3147 """dump the contents of a revlog index"""
3147 """dump the contents of a revlog index"""
3148 r = cmdutil.openrevlog(
3148 r = cmdutil.openrevlog(
3149 repo, b'debugrevlogindex', file_, pycompat.byteskwargs(opts)
3149 repo, b'debugrevlogindex', file_, pycompat.byteskwargs(opts)
3150 )
3150 )
3151 format = opts.get('format', 0)
3151 format = opts.get('format', 0)
3152 if format not in (0, 1):
3152 if format not in (0, 1):
3153 raise error.Abort(_(b"unknown format %d") % format)
3153 raise error.Abort(_(b"unknown format %d") % format)
3154
3154
3155 if ui.debugflag:
3155 if ui.debugflag:
3156 shortfn = hex
3156 shortfn = hex
3157 else:
3157 else:
3158 shortfn = short
3158 shortfn = short
3159
3159
3160 # There might not be anything in r, so have a sane default
3160 # There might not be anything in r, so have a sane default
3161 idlen = 12
3161 idlen = 12
3162 for i in r:
3162 for i in r:
3163 idlen = len(shortfn(r.node(i)))
3163 idlen = len(shortfn(r.node(i)))
3164 break
3164 break
3165
3165
3166 if format == 0:
3166 if format == 0:
3167 if ui.verbose:
3167 if ui.verbose:
3168 ui.writenoi18n(
3168 ui.writenoi18n(
3169 b" rev offset length linkrev %s %s p2\n"
3169 b" rev offset length linkrev %s %s p2\n"
3170 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3170 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3171 )
3171 )
3172 else:
3172 else:
3173 ui.writenoi18n(
3173 ui.writenoi18n(
3174 b" rev linkrev %s %s p2\n"
3174 b" rev linkrev %s %s p2\n"
3175 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3175 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3176 )
3176 )
3177 elif format == 1:
3177 elif format == 1:
3178 if ui.verbose:
3178 if ui.verbose:
3179 ui.writenoi18n(
3179 ui.writenoi18n(
3180 (
3180 (
3181 b" rev flag offset length size link p1"
3181 b" rev flag offset length size link p1"
3182 b" p2 %s\n"
3182 b" p2 %s\n"
3183 )
3183 )
3184 % b"nodeid".rjust(idlen)
3184 % b"nodeid".rjust(idlen)
3185 )
3185 )
3186 else:
3186 else:
3187 ui.writenoi18n(
3187 ui.writenoi18n(
3188 b" rev flag size link p1 p2 %s\n"
3188 b" rev flag size link p1 p2 %s\n"
3189 % b"nodeid".rjust(idlen)
3189 % b"nodeid".rjust(idlen)
3190 )
3190 )
3191
3191
3192 for i in r:
3192 for i in r:
3193 node = r.node(i)
3193 node = r.node(i)
3194 if format == 0:
3194 if format == 0:
3195 try:
3195 try:
3196 pp = r.parents(node)
3196 pp = r.parents(node)
3197 except Exception:
3197 except Exception:
3198 pp = [repo.nullid, repo.nullid]
3198 pp = [repo.nullid, repo.nullid]
3199 if ui.verbose:
3199 if ui.verbose:
3200 ui.write(
3200 ui.write(
3201 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3201 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3202 % (
3202 % (
3203 i,
3203 i,
3204 r.start(i),
3204 r.start(i),
3205 r.length(i),
3205 r.length(i),
3206 r.linkrev(i),
3206 r.linkrev(i),
3207 shortfn(node),
3207 shortfn(node),
3208 shortfn(pp[0]),
3208 shortfn(pp[0]),
3209 shortfn(pp[1]),
3209 shortfn(pp[1]),
3210 )
3210 )
3211 )
3211 )
3212 else:
3212 else:
3213 ui.write(
3213 ui.write(
3214 b"% 6d % 7d %s %s %s\n"
3214 b"% 6d % 7d %s %s %s\n"
3215 % (
3215 % (
3216 i,
3216 i,
3217 r.linkrev(i),
3217 r.linkrev(i),
3218 shortfn(node),
3218 shortfn(node),
3219 shortfn(pp[0]),
3219 shortfn(pp[0]),
3220 shortfn(pp[1]),
3220 shortfn(pp[1]),
3221 )
3221 )
3222 )
3222 )
3223 elif format == 1:
3223 elif format == 1:
3224 pr = r.parentrevs(i)
3224 pr = r.parentrevs(i)
3225 if ui.verbose:
3225 if ui.verbose:
3226 ui.write(
3226 ui.write(
3227 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3227 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3228 % (
3228 % (
3229 i,
3229 i,
3230 r.flags(i),
3230 r.flags(i),
3231 r.start(i),
3231 r.start(i),
3232 r.length(i),
3232 r.length(i),
3233 r.rawsize(i),
3233 r.rawsize(i),
3234 r.linkrev(i),
3234 r.linkrev(i),
3235 pr[0],
3235 pr[0],
3236 pr[1],
3236 pr[1],
3237 shortfn(node),
3237 shortfn(node),
3238 )
3238 )
3239 )
3239 )
3240 else:
3240 else:
3241 ui.write(
3241 ui.write(
3242 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3242 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3243 % (
3243 % (
3244 i,
3244 i,
3245 r.flags(i),
3245 r.flags(i),
3246 r.rawsize(i),
3246 r.rawsize(i),
3247 r.linkrev(i),
3247 r.linkrev(i),
3248 pr[0],
3248 pr[0],
3249 pr[1],
3249 pr[1],
3250 shortfn(node),
3250 shortfn(node),
3251 )
3251 )
3252 )
3252 )
3253
3253
3254
3254
3255 @command(
3255 @command(
3256 b'debugrevspec',
3256 b'debugrevspec',
3257 [
3257 [
3258 (
3258 (
3259 b'',
3259 b'',
3260 b'optimize',
3260 b'optimize',
3261 None,
3261 None,
3262 _(b'print parsed tree after optimizing (DEPRECATED)'),
3262 _(b'print parsed tree after optimizing (DEPRECATED)'),
3263 ),
3263 ),
3264 (
3264 (
3265 b'',
3265 b'',
3266 b'show-revs',
3266 b'show-revs',
3267 True,
3267 True,
3268 _(b'print list of result revisions (default)'),
3268 _(b'print list of result revisions (default)'),
3269 ),
3269 ),
3270 (
3270 (
3271 b's',
3271 b's',
3272 b'show-set',
3272 b'show-set',
3273 None,
3273 None,
3274 _(b'print internal representation of result set'),
3274 _(b'print internal representation of result set'),
3275 ),
3275 ),
3276 (
3276 (
3277 b'p',
3277 b'p',
3278 b'show-stage',
3278 b'show-stage',
3279 [],
3279 [],
3280 _(b'print parsed tree at the given stage'),
3280 _(b'print parsed tree at the given stage'),
3281 _(b'NAME'),
3281 _(b'NAME'),
3282 ),
3282 ),
3283 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3283 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3284 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3284 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3285 ],
3285 ],
3286 b'REVSPEC',
3286 b'REVSPEC',
3287 )
3287 )
3288 def debugrevspec(ui, repo, expr, **opts):
3288 def debugrevspec(ui, repo, expr, **opts):
3289 """parse and apply a revision specification
3289 """parse and apply a revision specification
3290
3290
3291 Use -p/--show-stage option to print the parsed tree at the given stages.
3291 Use -p/--show-stage option to print the parsed tree at the given stages.
3292 Use -p all to print tree at every stage.
3292 Use -p all to print tree at every stage.
3293
3293
3294 Use --no-show-revs option with -s or -p to print only the set
3294 Use --no-show-revs option with -s or -p to print only the set
3295 representation or the parsed tree respectively.
3295 representation or the parsed tree respectively.
3296
3296
3297 Use --verify-optimized to compare the optimized result with the unoptimized
3297 Use --verify-optimized to compare the optimized result with the unoptimized
3298 one. Returns 1 if the optimized result differs.
3298 one. Returns 1 if the optimized result differs.
3299 """
3299 """
3300 aliases = ui.configitems(b'revsetalias')
3300 aliases = ui.configitems(b'revsetalias')
3301 stages = [
3301 stages = [
3302 (b'parsed', lambda tree: tree),
3302 (b'parsed', lambda tree: tree),
3303 (
3303 (
3304 b'expanded',
3304 b'expanded',
3305 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3305 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3306 ),
3306 ),
3307 (b'concatenated', revsetlang.foldconcat),
3307 (b'concatenated', revsetlang.foldconcat),
3308 (b'analyzed', revsetlang.analyze),
3308 (b'analyzed', revsetlang.analyze),
3309 (b'optimized', revsetlang.optimize),
3309 (b'optimized', revsetlang.optimize),
3310 ]
3310 ]
3311 if opts['no_optimized']:
3311 if opts['no_optimized']:
3312 stages = stages[:-1]
3312 stages = stages[:-1]
3313 if opts['verify_optimized'] and opts['no_optimized']:
3313 if opts['verify_optimized'] and opts['no_optimized']:
3314 raise error.Abort(
3314 raise error.Abort(
3315 _(b'cannot use --verify-optimized with --no-optimized')
3315 _(b'cannot use --verify-optimized with --no-optimized')
3316 )
3316 )
3317 stagenames = {n for n, f in stages}
3317 stagenames = {n for n, f in stages}
3318
3318
3319 showalways = set()
3319 showalways = set()
3320 showchanged = set()
3320 showchanged = set()
3321 if ui.verbose and not opts['show_stage']:
3321 if ui.verbose and not opts['show_stage']:
3322 # show parsed tree by --verbose (deprecated)
3322 # show parsed tree by --verbose (deprecated)
3323 showalways.add(b'parsed')
3323 showalways.add(b'parsed')
3324 showchanged.update([b'expanded', b'concatenated'])
3324 showchanged.update([b'expanded', b'concatenated'])
3325 if opts['optimize']:
3325 if opts['optimize']:
3326 showalways.add(b'optimized')
3326 showalways.add(b'optimized')
3327 if opts['show_stage'] and opts['optimize']:
3327 if opts['show_stage'] and opts['optimize']:
3328 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3328 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3329 if opts['show_stage'] == [b'all']:
3329 if opts['show_stage'] == [b'all']:
3330 showalways.update(stagenames)
3330 showalways.update(stagenames)
3331 else:
3331 else:
3332 for n in opts['show_stage']:
3332 for n in opts['show_stage']:
3333 if n not in stagenames:
3333 if n not in stagenames:
3334 raise error.Abort(_(b'invalid stage name: %s') % n)
3334 raise error.Abort(_(b'invalid stage name: %s') % n)
3335 showalways.update(opts['show_stage'])
3335 showalways.update(opts['show_stage'])
3336
3336
3337 treebystage = {}
3337 treebystage = {}
3338 printedtree = None
3338 printedtree = None
3339 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3339 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3340 for n, f in stages:
3340 for n, f in stages:
3341 treebystage[n] = tree = f(tree)
3341 treebystage[n] = tree = f(tree)
3342 if n in showalways or (n in showchanged and tree != printedtree):
3342 if n in showalways or (n in showchanged and tree != printedtree):
3343 if opts['show_stage'] or n != b'parsed':
3343 if opts['show_stage'] or n != b'parsed':
3344 ui.write(b"* %s:\n" % n)
3344 ui.write(b"* %s:\n" % n)
3345 ui.write(revsetlang.prettyformat(tree), b"\n")
3345 ui.write(revsetlang.prettyformat(tree), b"\n")
3346 printedtree = tree
3346 printedtree = tree
3347
3347
3348 if opts['verify_optimized']:
3348 if opts['verify_optimized']:
3349 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3349 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3350 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3350 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3351 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
3351 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
3352 ui.writenoi18n(
3352 ui.writenoi18n(
3353 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3353 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3354 )
3354 )
3355 ui.writenoi18n(
3355 ui.writenoi18n(
3356 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3356 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3357 )
3357 )
3358 arevs = list(arevs)
3358 arevs = list(arevs)
3359 brevs = list(brevs)
3359 brevs = list(brevs)
3360 if arevs == brevs:
3360 if arevs == brevs:
3361 return 0
3361 return 0
3362 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3362 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3363 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3363 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3364 sm = difflib.SequenceMatcher(None, arevs, brevs)
3364 sm = difflib.SequenceMatcher(None, arevs, brevs)
3365 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3365 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3366 if tag in ('delete', 'replace'):
3366 if tag in ('delete', 'replace'):
3367 for c in arevs[alo:ahi]:
3367 for c in arevs[alo:ahi]:
3368 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3368 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3369 if tag in ('insert', 'replace'):
3369 if tag in ('insert', 'replace'):
3370 for c in brevs[blo:bhi]:
3370 for c in brevs[blo:bhi]:
3371 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3371 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3372 if tag == 'equal':
3372 if tag == 'equal':
3373 for c in arevs[alo:ahi]:
3373 for c in arevs[alo:ahi]:
3374 ui.write(b' %d\n' % c)
3374 ui.write(b' %d\n' % c)
3375 return 1
3375 return 1
3376
3376
3377 func = revset.makematcher(tree)
3377 func = revset.makematcher(tree)
3378 revs = func(repo)
3378 revs = func(repo)
3379 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
3379 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
3380 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3380 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3381 if not opts['show_revs']:
3381 if not opts['show_revs']:
3382 return
3382 return
3383 for c in revs:
3383 for c in revs:
3384 ui.write(b"%d\n" % c)
3384 ui.write(b"%d\n" % c)
3385
3385
3386
3386
3387 @command(
3387 @command(
3388 b'debugserve',
3388 b'debugserve',
3389 [
3389 [
3390 (
3390 (
3391 b'',
3391 b'',
3392 b'sshstdio',
3392 b'sshstdio',
3393 False,
3393 False,
3394 _(b'run an SSH server bound to process handles'),
3394 _(b'run an SSH server bound to process handles'),
3395 ),
3395 ),
3396 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3396 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3397 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3397 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3398 ],
3398 ],
3399 b'',
3399 b'',
3400 )
3400 )
3401 def debugserve(ui, repo, **opts):
3401 def debugserve(ui, repo, **opts):
3402 """run a server with advanced settings
3402 """run a server with advanced settings
3403
3403
3404 This command is similar to :hg:`serve`. It exists partially as a
3404 This command is similar to :hg:`serve`. It exists partially as a
3405 workaround to the fact that ``hg serve --stdio`` must have specific
3405 workaround to the fact that ``hg serve --stdio`` must have specific
3406 arguments for security reasons.
3406 arguments for security reasons.
3407 """
3407 """
3408 if not opts['sshstdio']:
3408 if not opts['sshstdio']:
3409 raise error.Abort(_(b'only --sshstdio is currently supported'))
3409 raise error.Abort(_(b'only --sshstdio is currently supported'))
3410
3410
3411 logfh = None
3411 logfh = None
3412
3412
3413 if opts['logiofd'] and opts['logiofile']:
3413 if opts['logiofd'] and opts['logiofile']:
3414 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3414 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3415
3415
3416 if opts['logiofd']:
3416 if opts['logiofd']:
3417 # Ideally we would be line buffered. But line buffering in binary
3417 # Ideally we would be line buffered. But line buffering in binary
3418 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3418 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3419 # buffering could have performance impacts. But since this isn't
3419 # buffering could have performance impacts. But since this isn't
3420 # performance critical code, it should be fine.
3420 # performance critical code, it should be fine.
3421 try:
3421 try:
3422 logfh = os.fdopen(int(opts['logiofd']), 'ab', 0)
3422 logfh = os.fdopen(int(opts['logiofd']), 'ab', 0)
3423 except OSError as e:
3423 except OSError as e:
3424 if e.errno != errno.ESPIPE:
3424 if e.errno != errno.ESPIPE:
3425 raise
3425 raise
3426 # can't seek a pipe, so `ab` mode fails on py3
3426 # can't seek a pipe, so `ab` mode fails on py3
3427 logfh = os.fdopen(int(opts['logiofd']), 'wb', 0)
3427 logfh = os.fdopen(int(opts['logiofd']), 'wb', 0)
3428 elif opts['logiofile']:
3428 elif opts['logiofile']:
3429 logfh = open(opts['logiofile'], b'ab', 0)
3429 logfh = open(opts['logiofile'], b'ab', 0)
3430
3430
3431 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3431 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3432 s.serve_forever()
3432 s.serve_forever()
3433
3433
3434
3434
3435 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3435 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3436 def debugsetparents(ui, repo, rev1, rev2=None):
3436 def debugsetparents(ui, repo, rev1, rev2=None):
3437 """manually set the parents of the current working directory (DANGEROUS)
3437 """manually set the parents of the current working directory (DANGEROUS)
3438
3438
3439 This command is not what you are looking for and should not be used. Using
3439 This command is not what you are looking for and should not be used. Using
3440 this command will most certainly results in slight corruption of the file
3440 this command will most certainly results in slight corruption of the file
3441 level histories within your repository. DO NOT USE THIS COMMAND.
3441 level histories within your repository. DO NOT USE THIS COMMAND.
3442
3442
3443 The command updates the p1 and p2 fields in the dirstate, without touching
3443 The command updates the p1 and p2 fields in the dirstate, without touching
3444 anything else. This useful for writing repository conversion tools, but
3444 anything else. This useful for writing repository conversion tools, but
3445 should be used with extreme care. For example, neither the working
3445 should be used with extreme care. For example, neither the working
3446 directory nor the dirstate is updated, so file statuses may be incorrect
3446 directory nor the dirstate is updated, so file statuses may be incorrect
3447 after running this command. Use it only if you are one of the few people who
3447 after running this command. Use it only if you are one of the few people who
3448 deeply understands both conversion tools and file level histories. If you are
3448 deeply understands both conversion tools and file level histories. If you are
3449 reading this help, you are not one of those people (most of them sailed west
3449 reading this help, you are not one of those people (most of them sailed west
3450 from Mithlond anyway).
3450 from Mithlond anyway).
3451
3451
3452 So, one more time, DO NOT USE THIS COMMAND.
3452 So, one more time, DO NOT USE THIS COMMAND.
3453
3453
3454 Returns 0 on success.
3454 Returns 0 on success.
3455 """
3455 """
3456
3456
3457 node1 = scmutil.revsingle(repo, rev1).node()
3457 node1 = scmutil.revsingle(repo, rev1).node()
3458 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3458 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3459
3459
3460 with repo.wlock():
3460 with repo.wlock():
3461 repo.setparents(node1, node2)
3461 repo.setparents(node1, node2)
3462
3462
3463
3463
3464 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3464 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3465 def debugsidedata(ui, repo, file_, rev=None, **opts):
3465 def debugsidedata(ui, repo, file_, rev=None, **opts):
3466 """dump the side data for a cl/manifest/file revision
3466 """dump the side data for a cl/manifest/file revision
3467
3467
3468 Use --verbose to dump the sidedata content."""
3468 Use --verbose to dump the sidedata content."""
3469 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
3469 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
3470 if rev is not None:
3470 if rev is not None:
3471 raise error.InputError(
3471 raise error.InputError(
3472 _(b'cannot specify a revision with other arguments')
3472 _(b'cannot specify a revision with other arguments')
3473 )
3473 )
3474 file_, rev = None, file_
3474 file_, rev = None, file_
3475 elif rev is None:
3475 elif rev is None:
3476 raise error.InputError(_(b'please specify a revision'))
3476 raise error.InputError(_(b'please specify a revision'))
3477 r = cmdutil.openstorage(
3477 r = cmdutil.openstorage(
3478 repo, b'debugdata', file_, pycompat.byteskwargs(opts)
3478 repo, b'debugdata', file_, pycompat.byteskwargs(opts)
3479 )
3479 )
3480 r = getattr(r, '_revlog', r)
3480 r = getattr(r, '_revlog', r)
3481 try:
3481 try:
3482 sidedata = r.sidedata(r.lookup(rev))
3482 sidedata = r.sidedata(r.lookup(rev))
3483 except KeyError:
3483 except KeyError:
3484 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3484 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3485 if sidedata:
3485 if sidedata:
3486 sidedata = list(sidedata.items())
3486 sidedata = list(sidedata.items())
3487 sidedata.sort()
3487 sidedata.sort()
3488 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3488 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3489 for key, value in sidedata:
3489 for key, value in sidedata:
3490 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3490 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3491 if ui.verbose:
3491 if ui.verbose:
3492 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3492 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3493
3493
3494
3494
3495 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3495 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3496 def debugssl(ui, repo, source=None, **opts):
3496 def debugssl(ui, repo, source=None, **opts):
3497 """test a secure connection to a server
3497 """test a secure connection to a server
3498
3498
3499 This builds the certificate chain for the server on Windows, installing the
3499 This builds the certificate chain for the server on Windows, installing the
3500 missing intermediates and trusted root via Windows Update if necessary. It
3500 missing intermediates and trusted root via Windows Update if necessary. It
3501 does nothing on other platforms.
3501 does nothing on other platforms.
3502
3502
3503 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3503 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3504 that server is used. See :hg:`help urls` for more information.
3504 that server is used. See :hg:`help urls` for more information.
3505
3505
3506 If the update succeeds, retry the original operation. Otherwise, the cause
3506 If the update succeeds, retry the original operation. Otherwise, the cause
3507 of the SSL error is likely another issue.
3507 of the SSL error is likely another issue.
3508 """
3508 """
3509 if not pycompat.iswindows:
3509 if not pycompat.iswindows:
3510 raise error.Abort(
3510 raise error.Abort(
3511 _(b'certificate chain building is only possible on Windows')
3511 _(b'certificate chain building is only possible on Windows')
3512 )
3512 )
3513
3513
3514 if not source:
3514 if not source:
3515 if not repo:
3515 if not repo:
3516 raise error.Abort(
3516 raise error.Abort(
3517 _(
3517 _(
3518 b"there is no Mercurial repository here, and no "
3518 b"there is no Mercurial repository here, and no "
3519 b"server specified"
3519 b"server specified"
3520 )
3520 )
3521 )
3521 )
3522 source = b"default"
3522 source = b"default"
3523
3523
3524 path = urlutil.get_unique_pull_path_obj(b'debugssl', ui, source)
3524 path = urlutil.get_unique_pull_path_obj(b'debugssl', ui, source)
3525 url = path.url
3525 url = path.url
3526
3526
3527 defaultport = {b'https': 443, b'ssh': 22}
3527 defaultport = {b'https': 443, b'ssh': 22}
3528 if url.scheme in defaultport:
3528 if url.scheme in defaultport:
3529 try:
3529 try:
3530 addr = (url.host, int(url.port or defaultport[url.scheme]))
3530 addr = (url.host, int(url.port or defaultport[url.scheme]))
3531 except ValueError:
3531 except ValueError:
3532 raise error.Abort(_(b"malformed port number in URL"))
3532 raise error.Abort(_(b"malformed port number in URL"))
3533 else:
3533 else:
3534 raise error.Abort(_(b"only https and ssh connections are supported"))
3534 raise error.Abort(_(b"only https and ssh connections are supported"))
3535
3535
3536 from . import win32
3536 from . import win32
3537
3537
3538 s = ssl.wrap_socket(
3538 s = ssl.wrap_socket(
3539 socket.socket(),
3539 socket.socket(),
3540 ssl_version=ssl.PROTOCOL_TLS,
3540 ssl_version=ssl.PROTOCOL_TLS,
3541 cert_reqs=ssl.CERT_NONE,
3541 cert_reqs=ssl.CERT_NONE,
3542 ca_certs=None,
3542 ca_certs=None,
3543 )
3543 )
3544
3544
3545 try:
3545 try:
3546 s.connect(addr)
3546 s.connect(addr)
3547 cert = s.getpeercert(True)
3547 cert = s.getpeercert(True)
3548
3548
3549 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3549 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3550
3550
3551 complete = win32.checkcertificatechain(cert, build=False)
3551 complete = win32.checkcertificatechain(cert, build=False)
3552
3552
3553 if not complete:
3553 if not complete:
3554 ui.status(_(b'certificate chain is incomplete, updating... '))
3554 ui.status(_(b'certificate chain is incomplete, updating... '))
3555
3555
3556 if not win32.checkcertificatechain(cert):
3556 if not win32.checkcertificatechain(cert):
3557 ui.status(_(b'failed.\n'))
3557 ui.status(_(b'failed.\n'))
3558 else:
3558 else:
3559 ui.status(_(b'done.\n'))
3559 ui.status(_(b'done.\n'))
3560 else:
3560 else:
3561 ui.status(_(b'full certificate chain is available\n'))
3561 ui.status(_(b'full certificate chain is available\n'))
3562 finally:
3562 finally:
3563 s.close()
3563 s.close()
3564
3564
3565
3565
3566 @command(
3566 @command(
3567 b'debug::stable-tail-sort',
3567 b'debug::stable-tail-sort',
3568 [
3568 [
3569 (
3569 (
3570 b'T',
3570 b'T',
3571 b'template',
3571 b'template',
3572 b'{rev}\n',
3572 b'{rev}\n',
3573 _(b'display with template'),
3573 _(b'display with template'),
3574 _(b'TEMPLATE'),
3574 _(b'TEMPLATE'),
3575 ),
3575 ),
3576 ],
3576 ],
3577 b'REV',
3577 b'REV',
3578 )
3578 )
3579 def debug_stable_tail_sort(ui, repo, revspec, template, **opts):
3579 def debug_stable_tail_sort(ui, repo, revspec, template, **opts):
3580 """display the stable-tail sort of the ancestors of a given node"""
3580 """display the stable-tail sort of the ancestors of a given node"""
3581 rev = logcmdutil.revsingle(repo, revspec).rev()
3581 rev = logcmdutil.revsingle(repo, revspec).rev()
3582 cl = repo.changelog
3582 cl = repo.changelog
3583
3583
3584 displayer = logcmdutil.maketemplater(ui, repo, template)
3584 displayer = logcmdutil.maketemplater(ui, repo, template)
3585 sorted_revs = stabletailsort._stable_tail_sort_naive(cl, rev)
3585 sorted_revs = stabletailsort._stable_tail_sort_naive(cl, rev)
3586 for ancestor_rev in sorted_revs:
3586 for ancestor_rev in sorted_revs:
3587 displayer.show(repo[ancestor_rev])
3587 displayer.show(repo[ancestor_rev])
3588
3588
3589
3589
3590 @command(
3590 @command(
3591 b'debug::stable-tail-sort-leaps',
3591 b'debug::stable-tail-sort-leaps',
3592 [
3592 [
3593 (
3593 (
3594 b'T',
3594 b'T',
3595 b'template',
3595 b'template',
3596 b'{rev}',
3596 b'{rev}',
3597 _(b'display with template'),
3597 _(b'display with template'),
3598 _(b'TEMPLATE'),
3598 _(b'TEMPLATE'),
3599 ),
3599 ),
3600 (b's', b'specific', False, _(b'restrict to specific leaps')),
3600 (b's', b'specific', False, _(b'restrict to specific leaps')),
3601 ],
3601 ],
3602 b'REV',
3602 b'REV',
3603 )
3603 )
3604 def debug_stable_tail_sort_leaps(ui, repo, rspec, template, specific, **opts):
3604 def debug_stable_tail_sort_leaps(ui, repo, rspec, template, specific, **opts):
3605 """display the leaps in the stable-tail sort of a node, one per line"""
3605 """display the leaps in the stable-tail sort of a node, one per line"""
3606 rev = logcmdutil.revsingle(repo, rspec).rev()
3606 rev = logcmdutil.revsingle(repo, rspec).rev()
3607
3607
3608 if specific:
3608 if specific:
3609 get_leaps = stabletailsort._find_specific_leaps_naive
3609 get_leaps = stabletailsort._find_specific_leaps_naive
3610 else:
3610 else:
3611 get_leaps = stabletailsort._find_all_leaps_naive
3611 get_leaps = stabletailsort._find_all_leaps_naive
3612
3612
3613 displayer = logcmdutil.maketemplater(ui, repo, template)
3613 displayer = logcmdutil.maketemplater(ui, repo, template)
3614 for source, target in get_leaps(repo.changelog, rev):
3614 for source, target in get_leaps(repo.changelog, rev):
3615 displayer.show(repo[source])
3615 displayer.show(repo[source])
3616 displayer.show(repo[target])
3616 displayer.show(repo[target])
3617 ui.write(b'\n')
3617 ui.write(b'\n')
3618
3618
3619
3619
3620 @command(
3620 @command(
3621 b"debugbackupbundle",
3621 b"debugbackupbundle",
3622 [
3622 [
3623 (
3623 (
3624 b"",
3624 b"",
3625 b"recover",
3625 b"recover",
3626 b"",
3626 b"",
3627 b"brings the specified changeset back into the repository",
3627 b"brings the specified changeset back into the repository",
3628 )
3628 )
3629 ]
3629 ]
3630 + cmdutil.logopts,
3630 + cmdutil.logopts,
3631 _(b"hg debugbackupbundle [--recover HASH]"),
3631 _(b"hg debugbackupbundle [--recover HASH]"),
3632 )
3632 )
3633 def debugbackupbundle(ui, repo, *pats, **opts):
3633 def debugbackupbundle(ui, repo, *pats, **opts):
3634 """lists the changesets available in backup bundles
3634 """lists the changesets available in backup bundles
3635
3635
3636 Without any arguments, this command prints a list of the changesets in each
3636 Without any arguments, this command prints a list of the changesets in each
3637 backup bundle.
3637 backup bundle.
3638
3638
3639 --recover takes a changeset hash and unbundles the first bundle that
3639 --recover takes a changeset hash and unbundles the first bundle that
3640 contains that hash, which puts that changeset back in your repository.
3640 contains that hash, which puts that changeset back in your repository.
3641
3641
3642 --verbose will print the entire commit message and the bundle path for that
3642 --verbose will print the entire commit message and the bundle path for that
3643 backup.
3643 backup.
3644 """
3644 """
3645 backups = list(
3645 backups = list(
3646 filter(
3646 filter(
3647 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3647 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3648 )
3648 )
3649 )
3649 )
3650 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3650 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3651
3651
3652 opts["bundle"] = b""
3652 opts["bundle"] = b""
3653 opts["force"] = None
3653 opts["force"] = None
3654 limit = logcmdutil.getlimit(pycompat.byteskwargs(opts))
3654 limit = logcmdutil.getlimit(pycompat.byteskwargs(opts))
3655
3655
3656 def display(other, chlist, displayer):
3656 def display(other, chlist, displayer):
3657 if opts.get("newest_first"):
3657 if opts.get("newest_first"):
3658 chlist.reverse()
3658 chlist.reverse()
3659 count = 0
3659 count = 0
3660 for n in chlist:
3660 for n in chlist:
3661 if limit is not None and count >= limit:
3661 if limit is not None and count >= limit:
3662 break
3662 break
3663 parents = [
3663 parents = [
3664 True for p in other.changelog.parents(n) if p != repo.nullid
3664 True for p in other.changelog.parents(n) if p != repo.nullid
3665 ]
3665 ]
3666 if opts.get("no_merges") and len(parents) == 2:
3666 if opts.get("no_merges") and len(parents) == 2:
3667 continue
3667 continue
3668 count += 1
3668 count += 1
3669 displayer.show(other[n])
3669 displayer.show(other[n])
3670
3670
3671 recovernode = opts.get("recover")
3671 recovernode = opts.get("recover")
3672 if recovernode:
3672 if recovernode:
3673 if scmutil.isrevsymbol(repo, recovernode):
3673 if scmutil.isrevsymbol(repo, recovernode):
3674 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3674 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3675 return
3675 return
3676 elif backups:
3676 elif backups:
3677 msg = _(
3677 msg = _(
3678 b"Recover changesets using: hg debugbackupbundle --recover "
3678 b"Recover changesets using: hg debugbackupbundle --recover "
3679 b"<changeset hash>\n\nAvailable backup changesets:"
3679 b"<changeset hash>\n\nAvailable backup changesets:"
3680 )
3680 )
3681 ui.status(msg, label=b"status.removed")
3681 ui.status(msg, label=b"status.removed")
3682 else:
3682 else:
3683 ui.status(_(b"no backup changesets found\n"))
3683 ui.status(_(b"no backup changesets found\n"))
3684 return
3684 return
3685
3685
3686 for backup in backups:
3686 for backup in backups:
3687 # Much of this is copied from the hg incoming logic
3687 # Much of this is copied from the hg incoming logic
3688 source = os.path.relpath(backup, encoding.getcwd())
3688 source = os.path.relpath(backup, encoding.getcwd())
3689 path = urlutil.get_unique_pull_path_obj(
3689 path = urlutil.get_unique_pull_path_obj(
3690 b'debugbackupbundle',
3690 b'debugbackupbundle',
3691 ui,
3691 ui,
3692 source,
3692 source,
3693 )
3693 )
3694 try:
3694 try:
3695 other = hg.peer(repo, pycompat.byteskwargs(opts), path)
3695 other = hg.peer(repo, pycompat.byteskwargs(opts), path)
3696 except error.LookupError as ex:
3696 except error.LookupError as ex:
3697 msg = _(b"\nwarning: unable to open bundle %s") % path.loc
3697 msg = _(b"\nwarning: unable to open bundle %s") % path.loc
3698 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3698 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3699 ui.warn(msg, hint=hint)
3699 ui.warn(msg, hint=hint)
3700 continue
3700 continue
3701 branches = (path.branch, opts.get('branch', []))
3701 branches = (path.branch, opts.get('branch', []))
3702 revs, checkout = hg.addbranchrevs(
3702 revs, checkout = hg.addbranchrevs(
3703 repo, other, branches, opts.get("rev")
3703 repo, other, branches, opts.get("rev")
3704 )
3704 )
3705
3705
3706 if revs:
3706 if revs:
3707 revs = [other.lookup(rev) for rev in revs]
3707 revs = [other.lookup(rev) for rev in revs]
3708
3708
3709 with ui.silent():
3709 with ui.silent():
3710 try:
3710 try:
3711 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3711 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3712 ui, repo, other, revs, opts["bundle"], opts["force"]
3712 ui, repo, other, revs, opts["bundle"], opts["force"]
3713 )
3713 )
3714 except error.LookupError:
3714 except error.LookupError:
3715 continue
3715 continue
3716
3716
3717 try:
3717 try:
3718 if not chlist:
3718 if not chlist:
3719 continue
3719 continue
3720 if recovernode:
3720 if recovernode:
3721 with repo.lock(), repo.transaction(b"unbundle") as tr:
3721 with repo.lock(), repo.transaction(b"unbundle") as tr:
3722 if scmutil.isrevsymbol(other, recovernode):
3722 if scmutil.isrevsymbol(other, recovernode):
3723 ui.status(_(b"Unbundling %s\n") % (recovernode))
3723 ui.status(_(b"Unbundling %s\n") % (recovernode))
3724 f = hg.openpath(ui, path.loc)
3724 f = hg.openpath(ui, path.loc)
3725 gen = exchange.readbundle(ui, f, path.loc)
3725 gen = exchange.readbundle(ui, f, path.loc)
3726 if isinstance(gen, bundle2.unbundle20):
3726 if isinstance(gen, bundle2.unbundle20):
3727 bundle2.applybundle(
3727 bundle2.applybundle(
3728 repo,
3728 repo,
3729 gen,
3729 gen,
3730 tr,
3730 tr,
3731 source=b"unbundle",
3731 source=b"unbundle",
3732 url=b"bundle:" + path.loc,
3732 url=b"bundle:" + path.loc,
3733 )
3733 )
3734 else:
3734 else:
3735 gen.apply(repo, b"unbundle", b"bundle:" + path.loc)
3735 gen.apply(repo, b"unbundle", b"bundle:" + path.loc)
3736 break
3736 break
3737 else:
3737 else:
3738 backupdate = encoding.strtolocal(
3738 backupdate = encoding.strtolocal(
3739 time.strftime(
3739 time.strftime(
3740 "%a %H:%M, %Y-%m-%d",
3740 "%a %H:%M, %Y-%m-%d",
3741 time.localtime(os.path.getmtime(path.loc)),
3741 time.localtime(os.path.getmtime(path.loc)),
3742 )
3742 )
3743 )
3743 )
3744 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3744 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3745 if ui.verbose:
3745 if ui.verbose:
3746 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), path.loc))
3746 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), path.loc))
3747 else:
3747 else:
3748 opts[
3748 opts[
3749 "template"
3749 "template"
3750 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3750 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3751 displayer = logcmdutil.changesetdisplayer(
3751 displayer = logcmdutil.changesetdisplayer(
3752 ui, other, pycompat.byteskwargs(opts), False
3752 ui, other, pycompat.byteskwargs(opts), False
3753 )
3753 )
3754 display(other, chlist, displayer)
3754 display(other, chlist, displayer)
3755 displayer.close()
3755 displayer.close()
3756 finally:
3756 finally:
3757 cleanupfn()
3757 cleanupfn()
3758
3758
3759
3759
3760 @command(
3760 @command(
3761 b'debugsub',
3761 b'debugsub',
3762 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3762 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3763 _(b'[-r REV] [REV]'),
3763 _(b'[-r REV] [REV]'),
3764 )
3764 )
3765 def debugsub(ui, repo, rev=None):
3765 def debugsub(ui, repo, rev=None):
3766 ctx = scmutil.revsingle(repo, rev, None)
3766 ctx = scmutil.revsingle(repo, rev, None)
3767 for k, v in sorted(ctx.substate.items()):
3767 for k, v in sorted(ctx.substate.items()):
3768 ui.writenoi18n(b'path %s\n' % k)
3768 ui.writenoi18n(b'path %s\n' % k)
3769 ui.writenoi18n(b' source %s\n' % v[0])
3769 ui.writenoi18n(b' source %s\n' % v[0])
3770 ui.writenoi18n(b' revision %s\n' % v[1])
3770 ui.writenoi18n(b' revision %s\n' % v[1])
3771
3771
3772
3772
3773 @command(
3773 @command(
3774 b'debugshell',
3774 b'debugshell',
3775 [
3775 [
3776 (
3776 (
3777 b'c',
3777 b'c',
3778 b'command',
3778 b'command',
3779 b'',
3779 b'',
3780 _(b'program passed in as a string'),
3780 _(b'program passed in as a string'),
3781 _(b'COMMAND'),
3781 _(b'COMMAND'),
3782 )
3782 )
3783 ],
3783 ],
3784 _(b'[-c COMMAND]'),
3784 _(b'[-c COMMAND]'),
3785 optionalrepo=True,
3785 optionalrepo=True,
3786 )
3786 )
3787 def debugshell(ui, repo, **opts):
3787 def debugshell(ui, repo, **opts):
3788 """run an interactive Python interpreter
3788 """run an interactive Python interpreter
3789
3789
3790 The local namespace is provided with a reference to the ui and
3790 The local namespace is provided with a reference to the ui and
3791 the repo instance (if available).
3791 the repo instance (if available).
3792 """
3792 """
3793 import code
3793 import code
3794
3794
3795 imported_objects = {
3795 imported_objects = {
3796 'ui': ui,
3796 'ui': ui,
3797 'repo': repo,
3797 'repo': repo,
3798 }
3798 }
3799
3799
3800 # py2exe disables initialization of the site module, which is responsible
3800 # py2exe disables initialization of the site module, which is responsible
3801 # for arranging for ``quit()`` to exit the interpreter. Manually initialize
3801 # for arranging for ``quit()`` to exit the interpreter. Manually initialize
3802 # the stuff that site normally does here, so that the interpreter can be
3802 # the stuff that site normally does here, so that the interpreter can be
3803 # quit in a consistent manner, whether run with pyoxidizer, exewrapper.c,
3803 # quit in a consistent manner, whether run with pyoxidizer, exewrapper.c,
3804 # py.exe, or py2exe.
3804 # py.exe, or py2exe.
3805 if getattr(sys, "frozen", None) == 'console_exe':
3805 if getattr(sys, "frozen", None) == 'console_exe':
3806 try:
3806 try:
3807 import site
3807 import site
3808
3808
3809 site.setcopyright()
3809 site.setcopyright()
3810 site.sethelper()
3810 site.sethelper()
3811 site.setquit()
3811 site.setquit()
3812 except ImportError:
3812 except ImportError:
3813 site = None # Keep PyCharm happy
3813 site = None # Keep PyCharm happy
3814
3814
3815 command = opts.get('command')
3815 command = opts.get('command')
3816 if command:
3816 if command:
3817 compiled = code.compile_command(encoding.strfromlocal(command))
3817 compiled = code.compile_command(encoding.strfromlocal(command))
3818 code.InteractiveInterpreter(locals=imported_objects).runcode(compiled)
3818 code.InteractiveInterpreter(locals=imported_objects).runcode(compiled)
3819 return
3819 return
3820
3820
3821 code.interact(local=imported_objects)
3821 code.interact(local=imported_objects)
3822
3822
3823
3823
3824 @command(
3824 @command(
3825 b'debug-revlog-stats',
3825 b'debug-revlog-stats',
3826 [
3826 [
3827 (b'c', b'changelog', None, _(b'Display changelog statistics')),
3827 (b'c', b'changelog', None, _(b'Display changelog statistics')),
3828 (b'm', b'manifest', None, _(b'Display manifest statistics')),
3828 (b'm', b'manifest', None, _(b'Display manifest statistics')),
3829 (b'f', b'filelogs', None, _(b'Display filelogs statistics')),
3829 (b'f', b'filelogs', None, _(b'Display filelogs statistics')),
3830 ]
3830 ]
3831 + cmdutil.formatteropts,
3831 + cmdutil.formatteropts,
3832 )
3832 )
3833 def debug_revlog_stats(ui, repo, **opts):
3833 def debug_revlog_stats(ui, repo, **opts):
3834 """display statistics about revlogs in the store"""
3834 """display statistics about revlogs in the store"""
3835 changelog = opts["changelog"]
3835 changelog = opts["changelog"]
3836 manifest = opts["manifest"]
3836 manifest = opts["manifest"]
3837 filelogs = opts["filelogs"]
3837 filelogs = opts["filelogs"]
3838
3838
3839 if changelog is None and manifest is None and filelogs is None:
3839 if changelog is None and manifest is None and filelogs is None:
3840 changelog = True
3840 changelog = True
3841 manifest = True
3841 manifest = True
3842 filelogs = True
3842 filelogs = True
3843
3843
3844 repo = repo.unfiltered()
3844 repo = repo.unfiltered()
3845 fm = ui.formatter(b'debug-revlog-stats', pycompat.byteskwargs(opts))
3845 fm = ui.formatter(b'debug-revlog-stats', pycompat.byteskwargs(opts))
3846 revlog_debug.debug_revlog_stats(repo, fm, changelog, manifest, filelogs)
3846 revlog_debug.debug_revlog_stats(repo, fm, changelog, manifest, filelogs)
3847 fm.end()
3847 fm.end()
3848
3848
3849
3849
3850 @command(
3850 @command(
3851 b'debugsuccessorssets',
3851 b'debugsuccessorssets',
3852 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3852 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3853 _(b'[REV]'),
3853 _(b'[REV]'),
3854 )
3854 )
3855 def debugsuccessorssets(ui, repo, *revs, **opts):
3855 def debugsuccessorssets(ui, repo, *revs, **opts):
3856 """show set of successors for revision
3856 """show set of successors for revision
3857
3857
3858 A successors set of changeset A is a consistent group of revisions that
3858 A successors set of changeset A is a consistent group of revisions that
3859 succeed A. It contains non-obsolete changesets only unless closests
3859 succeed A. It contains non-obsolete changesets only unless closests
3860 successors set is set.
3860 successors set is set.
3861
3861
3862 In most cases a changeset A has a single successors set containing a single
3862 In most cases a changeset A has a single successors set containing a single
3863 successor (changeset A replaced by A').
3863 successor (changeset A replaced by A').
3864
3864
3865 A changeset that is made obsolete with no successors are called "pruned".
3865 A changeset that is made obsolete with no successors are called "pruned".
3866 Such changesets have no successors sets at all.
3866 Such changesets have no successors sets at all.
3867
3867
3868 A changeset that has been "split" will have a successors set containing
3868 A changeset that has been "split" will have a successors set containing
3869 more than one successor.
3869 more than one successor.
3870
3870
3871 A changeset that has been rewritten in multiple different ways is called
3871 A changeset that has been rewritten in multiple different ways is called
3872 "divergent". Such changesets have multiple successor sets (each of which
3872 "divergent". Such changesets have multiple successor sets (each of which
3873 may also be split, i.e. have multiple successors).
3873 may also be split, i.e. have multiple successors).
3874
3874
3875 Results are displayed as follows::
3875 Results are displayed as follows::
3876
3876
3877 <rev1>
3877 <rev1>
3878 <successors-1A>
3878 <successors-1A>
3879 <rev2>
3879 <rev2>
3880 <successors-2A>
3880 <successors-2A>
3881 <successors-2B1> <successors-2B2> <successors-2B3>
3881 <successors-2B1> <successors-2B2> <successors-2B3>
3882
3882
3883 Here rev2 has two possible (i.e. divergent) successors sets. The first
3883 Here rev2 has two possible (i.e. divergent) successors sets. The first
3884 holds one element, whereas the second holds three (i.e. the changeset has
3884 holds one element, whereas the second holds three (i.e. the changeset has
3885 been split).
3885 been split).
3886 """
3886 """
3887 # passed to successorssets caching computation from one call to another
3887 # passed to successorssets caching computation from one call to another
3888 cache = {}
3888 cache = {}
3889 ctx2str = bytes
3889 ctx2str = bytes
3890 node2str = short
3890 node2str = short
3891 for rev in logcmdutil.revrange(repo, revs):
3891 for rev in logcmdutil.revrange(repo, revs):
3892 ctx = repo[rev]
3892 ctx = repo[rev]
3893 ui.write(b'%s\n' % ctx2str(ctx))
3893 ui.write(b'%s\n' % ctx2str(ctx))
3894 for succsset in obsutil.successorssets(
3894 for succsset in obsutil.successorssets(
3895 repo, ctx.node(), closest=opts['closest'], cache=cache
3895 repo, ctx.node(), closest=opts['closest'], cache=cache
3896 ):
3896 ):
3897 if succsset:
3897 if succsset:
3898 ui.write(b' ')
3898 ui.write(b' ')
3899 ui.write(node2str(succsset[0]))
3899 ui.write(node2str(succsset[0]))
3900 for node in succsset[1:]:
3900 for node in succsset[1:]:
3901 ui.write(b' ')
3901 ui.write(b' ')
3902 ui.write(node2str(node))
3902 ui.write(node2str(node))
3903 ui.write(b'\n')
3903 ui.write(b'\n')
3904
3904
3905
3905
3906 @command(b'debugtagscache', [])
3906 @command(b'debugtagscache', [])
3907 def debugtagscache(ui, repo):
3907 def debugtagscache(ui, repo):
3908 """display the contents of .hg/cache/hgtagsfnodes1"""
3908 """display the contents of .hg/cache/hgtagsfnodes1"""
3909 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3909 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3910 flog = repo.file(b'.hgtags')
3910 flog = repo.file(b'.hgtags')
3911 for r in repo:
3911 for r in repo:
3912 node = repo[r].node()
3912 node = repo[r].node()
3913 tagsnode = cache.getfnode(node, computemissing=False)
3913 tagsnode = cache.getfnode(node, computemissing=False)
3914 if tagsnode:
3914 if tagsnode:
3915 tagsnodedisplay = hex(tagsnode)
3915 tagsnodedisplay = hex(tagsnode)
3916 if not flog.hasnode(tagsnode):
3916 if not flog.hasnode(tagsnode):
3917 tagsnodedisplay += b' (unknown node)'
3917 tagsnodedisplay += b' (unknown node)'
3918 elif tagsnode is None:
3918 elif tagsnode is None:
3919 tagsnodedisplay = b'missing'
3919 tagsnodedisplay = b'missing'
3920 else:
3920 else:
3921 tagsnodedisplay = b'invalid'
3921 tagsnodedisplay = b'invalid'
3922
3922
3923 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3923 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3924
3924
3925
3925
3926 @command(
3926 @command(
3927 b'debugtemplate',
3927 b'debugtemplate',
3928 [
3928 [
3929 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3929 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3930 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3930 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3931 ],
3931 ],
3932 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3932 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3933 optionalrepo=True,
3933 optionalrepo=True,
3934 )
3934 )
3935 def debugtemplate(ui, repo, tmpl, **opts):
3935 def debugtemplate(ui, repo, tmpl, **opts):
3936 """parse and apply a template
3936 """parse and apply a template
3937
3937
3938 If -r/--rev is given, the template is processed as a log template and
3938 If -r/--rev is given, the template is processed as a log template and
3939 applied to the given changesets. Otherwise, it is processed as a generic
3939 applied to the given changesets. Otherwise, it is processed as a generic
3940 template.
3940 template.
3941
3941
3942 Use --verbose to print the parsed tree.
3942 Use --verbose to print the parsed tree.
3943 """
3943 """
3944 revs = None
3944 revs = None
3945 if opts['rev']:
3945 if opts['rev']:
3946 if repo is None:
3946 if repo is None:
3947 raise error.RepoError(
3947 raise error.RepoError(
3948 _(b'there is no Mercurial repository here (.hg not found)')
3948 _(b'there is no Mercurial repository here (.hg not found)')
3949 )
3949 )
3950 revs = logcmdutil.revrange(repo, opts['rev'])
3950 revs = logcmdutil.revrange(repo, opts['rev'])
3951
3951
3952 props = {}
3952 props = {}
3953 for d in opts['define']:
3953 for d in opts['define']:
3954 try:
3954 try:
3955 k, v = (e.strip() for e in d.split(b'=', 1))
3955 k, v = (e.strip() for e in d.split(b'=', 1))
3956 if not k or k == b'ui':
3956 if not k or k == b'ui':
3957 raise ValueError
3957 raise ValueError
3958 props[k] = v
3958 props[k] = v
3959 except ValueError:
3959 except ValueError:
3960 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3960 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3961
3961
3962 if ui.verbose:
3962 if ui.verbose:
3963 aliases = ui.configitems(b'templatealias')
3963 aliases = ui.configitems(b'templatealias')
3964 tree = templater.parse(tmpl)
3964 tree = templater.parse(tmpl)
3965 ui.note(templater.prettyformat(tree), b'\n')
3965 ui.note(templater.prettyformat(tree), b'\n')
3966 newtree = templater.expandaliases(tree, aliases)
3966 newtree = templater.expandaliases(tree, aliases)
3967 if newtree != tree:
3967 if newtree != tree:
3968 ui.notenoi18n(
3968 ui.notenoi18n(
3969 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3969 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3970 )
3970 )
3971
3971
3972 if revs is None:
3972 if revs is None:
3973 tres = formatter.templateresources(ui, repo)
3973 tres = formatter.templateresources(ui, repo)
3974 t = formatter.maketemplater(ui, tmpl, resources=tres)
3974 t = formatter.maketemplater(ui, tmpl, resources=tres)
3975 if ui.verbose:
3975 if ui.verbose:
3976 kwds, funcs = t.symbolsuseddefault()
3976 kwds, funcs = t.symbolsuseddefault()
3977 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3977 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3978 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3978 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3979 ui.write(t.renderdefault(props))
3979 ui.write(t.renderdefault(props))
3980 else:
3980 else:
3981 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3981 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3982 if ui.verbose:
3982 if ui.verbose:
3983 kwds, funcs = displayer.t.symbolsuseddefault()
3983 kwds, funcs = displayer.t.symbolsuseddefault()
3984 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3984 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3985 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3985 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3986 for r in revs:
3986 for r in revs:
3987 displayer.show(repo[r], **pycompat.strkwargs(props))
3987 displayer.show(repo[r], **pycompat.strkwargs(props))
3988 displayer.close()
3988 displayer.close()
3989
3989
3990
3990
3991 @command(
3991 @command(
3992 b'debuguigetpass',
3992 b'debuguigetpass',
3993 [
3993 [
3994 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3994 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3995 ],
3995 ],
3996 _(b'[-p TEXT]'),
3996 _(b'[-p TEXT]'),
3997 norepo=True,
3997 norepo=True,
3998 )
3998 )
3999 def debuguigetpass(ui, prompt=b''):
3999 def debuguigetpass(ui, prompt=b''):
4000 """show prompt to type password"""
4000 """show prompt to type password"""
4001 r = ui.getpass(prompt)
4001 r = ui.getpass(prompt)
4002 if r is None:
4002 if r is None:
4003 r = b"<default response>"
4003 r = b"<default response>"
4004 ui.writenoi18n(b'response: %s\n' % r)
4004 ui.writenoi18n(b'response: %s\n' % r)
4005
4005
4006
4006
4007 @command(
4007 @command(
4008 b'debuguiprompt',
4008 b'debuguiprompt',
4009 [
4009 [
4010 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
4010 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
4011 ],
4011 ],
4012 _(b'[-p TEXT]'),
4012 _(b'[-p TEXT]'),
4013 norepo=True,
4013 norepo=True,
4014 )
4014 )
4015 def debuguiprompt(ui, prompt=b''):
4015 def debuguiprompt(ui, prompt=b''):
4016 """show plain prompt"""
4016 """show plain prompt"""
4017 r = ui.prompt(prompt)
4017 r = ui.prompt(prompt)
4018 ui.writenoi18n(b'response: %s\n' % r)
4018 ui.writenoi18n(b'response: %s\n' % r)
4019
4019
4020
4020
4021 @command(b'debugupdatecaches', [])
4021 @command(b'debugupdatecaches', [])
4022 def debugupdatecaches(ui, repo, *pats, **opts):
4022 def debugupdatecaches(ui, repo, *pats, **opts):
4023 """warm all known caches in the repository"""
4023 """warm all known caches in the repository"""
4024 with repo.wlock(), repo.lock():
4024 with repo.wlock(), repo.lock():
4025 repo.updatecaches(caches=repository.CACHES_ALL)
4025 repo.updatecaches(caches=repository.CACHES_ALL)
4026
4026
4027
4027
4028 @command(
4028 @command(
4029 b'debugupgraderepo',
4029 b'debugupgraderepo',
4030 [
4030 [
4031 (
4031 (
4032 b'o',
4032 b'o',
4033 b'optimize',
4033 b'optimize',
4034 [],
4034 [],
4035 _(b'extra optimization to perform'),
4035 _(b'extra optimization to perform'),
4036 _(b'NAME'),
4036 _(b'NAME'),
4037 ),
4037 ),
4038 (b'', b'run', False, _(b'performs an upgrade')),
4038 (b'', b'run', False, _(b'performs an upgrade')),
4039 (b'', b'backup', True, _(b'keep the old repository content around')),
4039 (b'', b'backup', True, _(b'keep the old repository content around')),
4040 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
4040 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
4041 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
4041 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
4042 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
4042 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
4043 ],
4043 ],
4044 )
4044 )
4045 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
4045 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
4046 """upgrade a repository to use different features
4046 """upgrade a repository to use different features
4047
4047
4048 If no arguments are specified, the repository is evaluated for upgrade
4048 If no arguments are specified, the repository is evaluated for upgrade
4049 and a list of problems and potential optimizations is printed.
4049 and a list of problems and potential optimizations is printed.
4050
4050
4051 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
4051 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
4052 can be influenced via additional arguments. More details will be provided
4052 can be influenced via additional arguments. More details will be provided
4053 by the command output when run without ``--run``.
4053 by the command output when run without ``--run``.
4054
4054
4055 During the upgrade, the repository will be locked and no writes will be
4055 During the upgrade, the repository will be locked and no writes will be
4056 allowed.
4056 allowed.
4057
4057
4058 At the end of the upgrade, the repository may not be readable while new
4058 At the end of the upgrade, the repository may not be readable while new
4059 repository data is swapped in. This window will be as long as it takes to
4059 repository data is swapped in. This window will be as long as it takes to
4060 rename some directories inside the ``.hg`` directory. On most machines, this
4060 rename some directories inside the ``.hg`` directory. On most machines, this
4061 should complete almost instantaneously and the chances of a consumer being
4061 should complete almost instantaneously and the chances of a consumer being
4062 unable to access the repository should be low.
4062 unable to access the repository should be low.
4063
4063
4064 By default, all revlogs will be upgraded. You can restrict this using flags
4064 By default, all revlogs will be upgraded. You can restrict this using flags
4065 such as `--manifest`:
4065 such as `--manifest`:
4066
4066
4067 * `--manifest`: only optimize the manifest
4067 * `--manifest`: only optimize the manifest
4068 * `--no-manifest`: optimize all revlog but the manifest
4068 * `--no-manifest`: optimize all revlog but the manifest
4069 * `--changelog`: optimize the changelog only
4069 * `--changelog`: optimize the changelog only
4070 * `--no-changelog --no-manifest`: optimize filelogs only
4070 * `--no-changelog --no-manifest`: optimize filelogs only
4071 * `--filelogs`: optimize the filelogs only
4071 * `--filelogs`: optimize the filelogs only
4072 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
4072 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
4073 """
4073 """
4074 return upgrade.upgraderepo(
4074 return upgrade.upgraderepo(
4075 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
4075 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
4076 )
4076 )
4077
4077
4078
4078
4079 @command(
4079 @command(
4080 b'debug::unbundle',
4081 [
4082 (
4083 b'u',
4084 b'update',
4085 None,
4086 _(b'update to new branch head if changesets were unbundled'),
4087 )
4088 ],
4089 _(b'[-u] FILE...'),
4090 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4091 )
4092 def debugunbundle(ui, repo, *args, **kwargs):
4093 """same as `hg unbundle`, but pretent to come from a push
4094
4095 This is useful to debug behavior and performance change in this case.
4096 """
4097 from . import commands # avoid cycle
4098
4099 unbundle = cmdutil.findcmd(b'unbundle', commands.table)[1][0]
4100 return unbundle(ui, repo, *args, _unbundle_source=b'push', **kwargs)
4101
4102
4103 @command(
4080 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
4104 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
4081 )
4105 )
4082 def debugwalk(ui, repo, *pats, **opts):
4106 def debugwalk(ui, repo, *pats, **opts):
4083 """show how files match on given patterns"""
4107 """show how files match on given patterns"""
4084 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
4108 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
4085 if ui.verbose:
4109 if ui.verbose:
4086 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
4110 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
4087 items = list(repo[None].walk(m))
4111 items = list(repo[None].walk(m))
4088 if not items:
4112 if not items:
4089 return
4113 return
4090 f = lambda fn: fn
4114 f = lambda fn: fn
4091 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
4115 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
4092 f = lambda fn: util.normpath(fn)
4116 f = lambda fn: util.normpath(fn)
4093 fmt = b'f %%-%ds %%-%ds %%s' % (
4117 fmt = b'f %%-%ds %%-%ds %%s' % (
4094 max([len(abs) for abs in items]),
4118 max([len(abs) for abs in items]),
4095 max([len(repo.pathto(abs)) for abs in items]),
4119 max([len(repo.pathto(abs)) for abs in items]),
4096 )
4120 )
4097 for abs in items:
4121 for abs in items:
4098 line = fmt % (
4122 line = fmt % (
4099 abs,
4123 abs,
4100 f(repo.pathto(abs)),
4124 f(repo.pathto(abs)),
4101 m.exact(abs) and b'exact' or b'',
4125 m.exact(abs) and b'exact' or b'',
4102 )
4126 )
4103 ui.write(b"%s\n" % line.rstrip())
4127 ui.write(b"%s\n" % line.rstrip())
4104
4128
4105
4129
4106 @command(b'debugwhyunstable', [], _(b'REV'))
4130 @command(b'debugwhyunstable', [], _(b'REV'))
4107 def debugwhyunstable(ui, repo, rev):
4131 def debugwhyunstable(ui, repo, rev):
4108 """explain instabilities of a changeset"""
4132 """explain instabilities of a changeset"""
4109 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
4133 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
4110 dnodes = b''
4134 dnodes = b''
4111 if entry.get(b'divergentnodes'):
4135 if entry.get(b'divergentnodes'):
4112 dnodes = (
4136 dnodes = (
4113 b' '.join(
4137 b' '.join(
4114 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
4138 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
4115 for ctx in entry[b'divergentnodes']
4139 for ctx in entry[b'divergentnodes']
4116 )
4140 )
4117 + b' '
4141 + b' '
4118 )
4142 )
4119 ui.write(
4143 ui.write(
4120 b'%s: %s%s %s\n'
4144 b'%s: %s%s %s\n'
4121 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4145 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4122 )
4146 )
4123
4147
4124
4148
4125 @command(
4149 @command(
4126 b'debugwireargs',
4150 b'debugwireargs',
4127 [
4151 [
4128 (b'', b'three', b'', b'three'),
4152 (b'', b'three', b'', b'three'),
4129 (b'', b'four', b'', b'four'),
4153 (b'', b'four', b'', b'four'),
4130 (b'', b'five', b'', b'five'),
4154 (b'', b'five', b'', b'five'),
4131 ]
4155 ]
4132 + cmdutil.remoteopts,
4156 + cmdutil.remoteopts,
4133 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4157 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4134 norepo=True,
4158 norepo=True,
4135 )
4159 )
4136 def debugwireargs(ui, repopath, *vals, **opts):
4160 def debugwireargs(ui, repopath, *vals, **opts):
4137 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
4161 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
4138 try:
4162 try:
4139 for opt in cmdutil.remoteopts:
4163 for opt in cmdutil.remoteopts:
4140 del opts[pycompat.sysstr(opt[1])]
4164 del opts[pycompat.sysstr(opt[1])]
4141 args = {}
4165 args = {}
4142 for k, v in opts.items():
4166 for k, v in opts.items():
4143 if v:
4167 if v:
4144 args[k] = v
4168 args[k] = v
4145
4169
4146 # run twice to check that we don't mess up the stream for the next command
4170 # run twice to check that we don't mess up the stream for the next command
4147 res1 = repo.debugwireargs(*vals, **args)
4171 res1 = repo.debugwireargs(*vals, **args)
4148 res2 = repo.debugwireargs(*vals, **args)
4172 res2 = repo.debugwireargs(*vals, **args)
4149 ui.write(b"%s\n" % res1)
4173 ui.write(b"%s\n" % res1)
4150 if res1 != res2:
4174 if res1 != res2:
4151 ui.warn(b"%s\n" % res2)
4175 ui.warn(b"%s\n" % res2)
4152 finally:
4176 finally:
4153 repo.close()
4177 repo.close()
4154
4178
4155
4179
4156 def _parsewirelangblocks(fh):
4180 def _parsewirelangblocks(fh):
4157 activeaction = None
4181 activeaction = None
4158 blocklines = []
4182 blocklines = []
4159 lastindent = 0
4183 lastindent = 0
4160
4184
4161 for line in fh:
4185 for line in fh:
4162 line = line.rstrip()
4186 line = line.rstrip()
4163 if not line:
4187 if not line:
4164 continue
4188 continue
4165
4189
4166 if line.startswith(b'#'):
4190 if line.startswith(b'#'):
4167 continue
4191 continue
4168
4192
4169 if not line.startswith(b' '):
4193 if not line.startswith(b' '):
4170 # New block. Flush previous one.
4194 # New block. Flush previous one.
4171 if activeaction:
4195 if activeaction:
4172 yield activeaction, blocklines
4196 yield activeaction, blocklines
4173
4197
4174 activeaction = line
4198 activeaction = line
4175 blocklines = []
4199 blocklines = []
4176 lastindent = 0
4200 lastindent = 0
4177 continue
4201 continue
4178
4202
4179 # Else we start with an indent.
4203 # Else we start with an indent.
4180
4204
4181 if not activeaction:
4205 if not activeaction:
4182 raise error.Abort(_(b'indented line outside of block'))
4206 raise error.Abort(_(b'indented line outside of block'))
4183
4207
4184 indent = len(line) - len(line.lstrip())
4208 indent = len(line) - len(line.lstrip())
4185
4209
4186 # If this line is indented more than the last line, concatenate it.
4210 # If this line is indented more than the last line, concatenate it.
4187 if indent > lastindent and blocklines:
4211 if indent > lastindent and blocklines:
4188 blocklines[-1] += line.lstrip()
4212 blocklines[-1] += line.lstrip()
4189 else:
4213 else:
4190 blocklines.append(line)
4214 blocklines.append(line)
4191 lastindent = indent
4215 lastindent = indent
4192
4216
4193 # Flush last block.
4217 # Flush last block.
4194 if activeaction:
4218 if activeaction:
4195 yield activeaction, blocklines
4219 yield activeaction, blocklines
4196
4220
4197
4221
4198 @command(
4222 @command(
4199 b'debugwireproto',
4223 b'debugwireproto',
4200 [
4224 [
4201 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4225 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4202 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4226 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4203 (
4227 (
4204 b'',
4228 b'',
4205 b'noreadstderr',
4229 b'noreadstderr',
4206 False,
4230 False,
4207 _(b'do not read from stderr of the remote'),
4231 _(b'do not read from stderr of the remote'),
4208 ),
4232 ),
4209 (
4233 (
4210 b'',
4234 b'',
4211 b'nologhandshake',
4235 b'nologhandshake',
4212 False,
4236 False,
4213 _(b'do not log I/O related to the peer handshake'),
4237 _(b'do not log I/O related to the peer handshake'),
4214 ),
4238 ),
4215 ]
4239 ]
4216 + cmdutil.remoteopts,
4240 + cmdutil.remoteopts,
4217 _(b'[PATH]'),
4241 _(b'[PATH]'),
4218 optionalrepo=True,
4242 optionalrepo=True,
4219 )
4243 )
4220 def debugwireproto(ui, repo, path=None, **opts):
4244 def debugwireproto(ui, repo, path=None, **opts):
4221 """send wire protocol commands to a server
4245 """send wire protocol commands to a server
4222
4246
4223 This command can be used to issue wire protocol commands to remote
4247 This command can be used to issue wire protocol commands to remote
4224 peers and to debug the raw data being exchanged.
4248 peers and to debug the raw data being exchanged.
4225
4249
4226 ``--localssh`` will start an SSH server against the current repository
4250 ``--localssh`` will start an SSH server against the current repository
4227 and connect to that. By default, the connection will perform a handshake
4251 and connect to that. By default, the connection will perform a handshake
4228 and establish an appropriate peer instance.
4252 and establish an appropriate peer instance.
4229
4253
4230 ``--peer`` can be used to bypass the handshake protocol and construct a
4254 ``--peer`` can be used to bypass the handshake protocol and construct a
4231 peer instance using the specified class type. Valid values are ``raw``,
4255 peer instance using the specified class type. Valid values are ``raw``,
4232 ``ssh1``. ``raw`` instances only allow sending raw data payloads and
4256 ``ssh1``. ``raw`` instances only allow sending raw data payloads and
4233 don't support higher-level command actions.
4257 don't support higher-level command actions.
4234
4258
4235 ``--noreadstderr`` can be used to disable automatic reading from stderr
4259 ``--noreadstderr`` can be used to disable automatic reading from stderr
4236 of the peer (for SSH connections only). Disabling automatic reading of
4260 of the peer (for SSH connections only). Disabling automatic reading of
4237 stderr is useful for making output more deterministic.
4261 stderr is useful for making output more deterministic.
4238
4262
4239 Commands are issued via a mini language which is specified via stdin.
4263 Commands are issued via a mini language which is specified via stdin.
4240 The language consists of individual actions to perform. An action is
4264 The language consists of individual actions to perform. An action is
4241 defined by a block. A block is defined as a line with no leading
4265 defined by a block. A block is defined as a line with no leading
4242 space followed by 0 or more lines with leading space. Blocks are
4266 space followed by 0 or more lines with leading space. Blocks are
4243 effectively a high-level command with additional metadata.
4267 effectively a high-level command with additional metadata.
4244
4268
4245 Lines beginning with ``#`` are ignored.
4269 Lines beginning with ``#`` are ignored.
4246
4270
4247 The following sections denote available actions.
4271 The following sections denote available actions.
4248
4272
4249 raw
4273 raw
4250 ---
4274 ---
4251
4275
4252 Send raw data to the server.
4276 Send raw data to the server.
4253
4277
4254 The block payload contains the raw data to send as one atomic send
4278 The block payload contains the raw data to send as one atomic send
4255 operation. The data may not actually be delivered in a single system
4279 operation. The data may not actually be delivered in a single system
4256 call: it depends on the abilities of the transport being used.
4280 call: it depends on the abilities of the transport being used.
4257
4281
4258 Each line in the block is de-indented and concatenated. Then, that
4282 Each line in the block is de-indented and concatenated. Then, that
4259 value is evaluated as a Python b'' literal. This allows the use of
4283 value is evaluated as a Python b'' literal. This allows the use of
4260 backslash escaping, etc.
4284 backslash escaping, etc.
4261
4285
4262 raw+
4286 raw+
4263 ----
4287 ----
4264
4288
4265 Behaves like ``raw`` except flushes output afterwards.
4289 Behaves like ``raw`` except flushes output afterwards.
4266
4290
4267 command <X>
4291 command <X>
4268 -----------
4292 -----------
4269
4293
4270 Send a request to run a named command, whose name follows the ``command``
4294 Send a request to run a named command, whose name follows the ``command``
4271 string.
4295 string.
4272
4296
4273 Arguments to the command are defined as lines in this block. The format of
4297 Arguments to the command are defined as lines in this block. The format of
4274 each line is ``<key> <value>``. e.g.::
4298 each line is ``<key> <value>``. e.g.::
4275
4299
4276 command listkeys
4300 command listkeys
4277 namespace bookmarks
4301 namespace bookmarks
4278
4302
4279 If the value begins with ``eval:``, it will be interpreted as a Python
4303 If the value begins with ``eval:``, it will be interpreted as a Python
4280 literal expression. Otherwise values are interpreted as Python b'' literals.
4304 literal expression. Otherwise values are interpreted as Python b'' literals.
4281 This allows sending complex types and encoding special byte sequences via
4305 This allows sending complex types and encoding special byte sequences via
4282 backslash escaping.
4306 backslash escaping.
4283
4307
4284 The following arguments have special meaning:
4308 The following arguments have special meaning:
4285
4309
4286 ``PUSHFILE``
4310 ``PUSHFILE``
4287 When defined, the *push* mechanism of the peer will be used instead
4311 When defined, the *push* mechanism of the peer will be used instead
4288 of the static request-response mechanism and the content of the
4312 of the static request-response mechanism and the content of the
4289 file specified in the value of this argument will be sent as the
4313 file specified in the value of this argument will be sent as the
4290 command payload.
4314 command payload.
4291
4315
4292 This can be used to submit a local bundle file to the remote.
4316 This can be used to submit a local bundle file to the remote.
4293
4317
4294 batchbegin
4318 batchbegin
4295 ----------
4319 ----------
4296
4320
4297 Instruct the peer to begin a batched send.
4321 Instruct the peer to begin a batched send.
4298
4322
4299 All ``command`` blocks are queued for execution until the next
4323 All ``command`` blocks are queued for execution until the next
4300 ``batchsubmit`` block.
4324 ``batchsubmit`` block.
4301
4325
4302 batchsubmit
4326 batchsubmit
4303 -----------
4327 -----------
4304
4328
4305 Submit previously queued ``command`` blocks as a batch request.
4329 Submit previously queued ``command`` blocks as a batch request.
4306
4330
4307 This action MUST be paired with a ``batchbegin`` action.
4331 This action MUST be paired with a ``batchbegin`` action.
4308
4332
4309 httprequest <method> <path>
4333 httprequest <method> <path>
4310 ---------------------------
4334 ---------------------------
4311
4335
4312 (HTTP peer only)
4336 (HTTP peer only)
4313
4337
4314 Send an HTTP request to the peer.
4338 Send an HTTP request to the peer.
4315
4339
4316 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4340 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4317
4341
4318 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4342 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4319 headers to add to the request. e.g. ``Accept: foo``.
4343 headers to add to the request. e.g. ``Accept: foo``.
4320
4344
4321 The following arguments are special:
4345 The following arguments are special:
4322
4346
4323 ``BODYFILE``
4347 ``BODYFILE``
4324 The content of the file defined as the value to this argument will be
4348 The content of the file defined as the value to this argument will be
4325 transferred verbatim as the HTTP request body.
4349 transferred verbatim as the HTTP request body.
4326
4350
4327 ``frame <type> <flags> <payload>``
4351 ``frame <type> <flags> <payload>``
4328 Send a unified protocol frame as part of the request body.
4352 Send a unified protocol frame as part of the request body.
4329
4353
4330 All frames will be collected and sent as the body to the HTTP
4354 All frames will be collected and sent as the body to the HTTP
4331 request.
4355 request.
4332
4356
4333 close
4357 close
4334 -----
4358 -----
4335
4359
4336 Close the connection to the server.
4360 Close the connection to the server.
4337
4361
4338 flush
4362 flush
4339 -----
4363 -----
4340
4364
4341 Flush data written to the server.
4365 Flush data written to the server.
4342
4366
4343 readavailable
4367 readavailable
4344 -------------
4368 -------------
4345
4369
4346 Close the write end of the connection and read all available data from
4370 Close the write end of the connection and read all available data from
4347 the server.
4371 the server.
4348
4372
4349 If the connection to the server encompasses multiple pipes, we poll both
4373 If the connection to the server encompasses multiple pipes, we poll both
4350 pipes and read available data.
4374 pipes and read available data.
4351
4375
4352 readline
4376 readline
4353 --------
4377 --------
4354
4378
4355 Read a line of output from the server. If there are multiple output
4379 Read a line of output from the server. If there are multiple output
4356 pipes, reads only the main pipe.
4380 pipes, reads only the main pipe.
4357
4381
4358 ereadline
4382 ereadline
4359 ---------
4383 ---------
4360
4384
4361 Like ``readline``, but read from the stderr pipe, if available.
4385 Like ``readline``, but read from the stderr pipe, if available.
4362
4386
4363 read <X>
4387 read <X>
4364 --------
4388 --------
4365
4389
4366 ``read()`` N bytes from the server's main output pipe.
4390 ``read()`` N bytes from the server's main output pipe.
4367
4391
4368 eread <X>
4392 eread <X>
4369 ---------
4393 ---------
4370
4394
4371 ``read()`` N bytes from the server's stderr pipe, if available.
4395 ``read()`` N bytes from the server's stderr pipe, if available.
4372
4396
4373 Specifying Unified Frame-Based Protocol Frames
4397 Specifying Unified Frame-Based Protocol Frames
4374 ----------------------------------------------
4398 ----------------------------------------------
4375
4399
4376 It is possible to emit a *Unified Frame-Based Protocol* by using special
4400 It is possible to emit a *Unified Frame-Based Protocol* by using special
4377 syntax.
4401 syntax.
4378
4402
4379 A frame is composed as a type, flags, and payload. These can be parsed
4403 A frame is composed as a type, flags, and payload. These can be parsed
4380 from a string of the form:
4404 from a string of the form:
4381
4405
4382 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4406 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4383
4407
4384 ``request-id`` and ``stream-id`` are integers defining the request and
4408 ``request-id`` and ``stream-id`` are integers defining the request and
4385 stream identifiers.
4409 stream identifiers.
4386
4410
4387 ``type`` can be an integer value for the frame type or the string name
4411 ``type`` can be an integer value for the frame type or the string name
4388 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4412 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4389 ``command-name``.
4413 ``command-name``.
4390
4414
4391 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4415 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4392 components. Each component (and there can be just one) can be an integer
4416 components. Each component (and there can be just one) can be an integer
4393 or a flag name for stream flags or frame flags, respectively. Values are
4417 or a flag name for stream flags or frame flags, respectively. Values are
4394 resolved to integers and then bitwise OR'd together.
4418 resolved to integers and then bitwise OR'd together.
4395
4419
4396 ``payload`` represents the raw frame payload. If it begins with
4420 ``payload`` represents the raw frame payload. If it begins with
4397 ``cbor:``, the following string is evaluated as Python code and the
4421 ``cbor:``, the following string is evaluated as Python code and the
4398 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4422 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4399 as a Python byte string literal.
4423 as a Python byte string literal.
4400 """
4424 """
4401 if opts['localssh'] and not repo:
4425 if opts['localssh'] and not repo:
4402 raise error.Abort(_(b'--localssh requires a repository'))
4426 raise error.Abort(_(b'--localssh requires a repository'))
4403
4427
4404 if opts['peer'] and opts['peer'] not in (
4428 if opts['peer'] and opts['peer'] not in (
4405 b'raw',
4429 b'raw',
4406 b'ssh1',
4430 b'ssh1',
4407 ):
4431 ):
4408 raise error.Abort(
4432 raise error.Abort(
4409 _(b'invalid value for --peer'),
4433 _(b'invalid value for --peer'),
4410 hint=_(b'valid values are "raw" and "ssh1"'),
4434 hint=_(b'valid values are "raw" and "ssh1"'),
4411 )
4435 )
4412
4436
4413 if path and opts['localssh']:
4437 if path and opts['localssh']:
4414 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4438 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4415
4439
4416 if ui.interactive():
4440 if ui.interactive():
4417 ui.write(_(b'(waiting for commands on stdin)\n'))
4441 ui.write(_(b'(waiting for commands on stdin)\n'))
4418
4442
4419 blocks = list(_parsewirelangblocks(ui.fin))
4443 blocks = list(_parsewirelangblocks(ui.fin))
4420
4444
4421 proc = None
4445 proc = None
4422 stdin = None
4446 stdin = None
4423 stdout = None
4447 stdout = None
4424 stderr = None
4448 stderr = None
4425 opener = None
4449 opener = None
4426
4450
4427 if opts['localssh']:
4451 if opts['localssh']:
4428 # We start the SSH server in its own process so there is process
4452 # We start the SSH server in its own process so there is process
4429 # separation. This prevents a whole class of potential bugs around
4453 # separation. This prevents a whole class of potential bugs around
4430 # shared state from interfering with server operation.
4454 # shared state from interfering with server operation.
4431 args = procutil.hgcmd() + [
4455 args = procutil.hgcmd() + [
4432 b'-R',
4456 b'-R',
4433 repo.root,
4457 repo.root,
4434 b'debugserve',
4458 b'debugserve',
4435 b'--sshstdio',
4459 b'--sshstdio',
4436 ]
4460 ]
4437 proc = subprocess.Popen(
4461 proc = subprocess.Popen(
4438 pycompat.rapply(procutil.tonativestr, args),
4462 pycompat.rapply(procutil.tonativestr, args),
4439 stdin=subprocess.PIPE,
4463 stdin=subprocess.PIPE,
4440 stdout=subprocess.PIPE,
4464 stdout=subprocess.PIPE,
4441 stderr=subprocess.PIPE,
4465 stderr=subprocess.PIPE,
4442 bufsize=0,
4466 bufsize=0,
4443 )
4467 )
4444
4468
4445 stdin = proc.stdin
4469 stdin = proc.stdin
4446 stdout = proc.stdout
4470 stdout = proc.stdout
4447 stderr = proc.stderr
4471 stderr = proc.stderr
4448
4472
4449 # We turn the pipes into observers so we can log I/O.
4473 # We turn the pipes into observers so we can log I/O.
4450 if ui.verbose or opts['peer'] == b'raw':
4474 if ui.verbose or opts['peer'] == b'raw':
4451 stdin = util.makeloggingfileobject(
4475 stdin = util.makeloggingfileobject(
4452 ui, proc.stdin, b'i', logdata=True
4476 ui, proc.stdin, b'i', logdata=True
4453 )
4477 )
4454 stdout = util.makeloggingfileobject(
4478 stdout = util.makeloggingfileobject(
4455 ui, proc.stdout, b'o', logdata=True
4479 ui, proc.stdout, b'o', logdata=True
4456 )
4480 )
4457 stderr = util.makeloggingfileobject(
4481 stderr = util.makeloggingfileobject(
4458 ui, proc.stderr, b'e', logdata=True
4482 ui, proc.stderr, b'e', logdata=True
4459 )
4483 )
4460
4484
4461 # --localssh also implies the peer connection settings.
4485 # --localssh also implies the peer connection settings.
4462
4486
4463 url = b'ssh://localserver'
4487 url = b'ssh://localserver'
4464 autoreadstderr = not opts['noreadstderr']
4488 autoreadstderr = not opts['noreadstderr']
4465
4489
4466 if opts['peer'] == b'ssh1':
4490 if opts['peer'] == b'ssh1':
4467 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4491 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4468 peer = sshpeer.sshv1peer(
4492 peer = sshpeer.sshv1peer(
4469 ui,
4493 ui,
4470 url,
4494 url,
4471 proc,
4495 proc,
4472 stdin,
4496 stdin,
4473 stdout,
4497 stdout,
4474 stderr,
4498 stderr,
4475 None,
4499 None,
4476 autoreadstderr=autoreadstderr,
4500 autoreadstderr=autoreadstderr,
4477 )
4501 )
4478 elif opts['peer'] == b'raw':
4502 elif opts['peer'] == b'raw':
4479 ui.write(_(b'using raw connection to peer\n'))
4503 ui.write(_(b'using raw connection to peer\n'))
4480 peer = None
4504 peer = None
4481 else:
4505 else:
4482 ui.write(_(b'creating ssh peer from handshake results\n'))
4506 ui.write(_(b'creating ssh peer from handshake results\n'))
4483 peer = sshpeer._make_peer(
4507 peer = sshpeer._make_peer(
4484 ui,
4508 ui,
4485 url,
4509 url,
4486 proc,
4510 proc,
4487 stdin,
4511 stdin,
4488 stdout,
4512 stdout,
4489 stderr,
4513 stderr,
4490 autoreadstderr=autoreadstderr,
4514 autoreadstderr=autoreadstderr,
4491 )
4515 )
4492
4516
4493 elif path:
4517 elif path:
4494 # We bypass hg.peer() so we can proxy the sockets.
4518 # We bypass hg.peer() so we can proxy the sockets.
4495 # TODO consider not doing this because we skip
4519 # TODO consider not doing this because we skip
4496 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4520 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4497 u = urlutil.url(path)
4521 u = urlutil.url(path)
4498 if u.scheme != b'http':
4522 if u.scheme != b'http':
4499 raise error.Abort(_(b'only http:// paths are currently supported'))
4523 raise error.Abort(_(b'only http:// paths are currently supported'))
4500
4524
4501 url, authinfo = u.authinfo()
4525 url, authinfo = u.authinfo()
4502 openerargs = {
4526 openerargs = {
4503 'useragent': b'Mercurial debugwireproto',
4527 'useragent': b'Mercurial debugwireproto',
4504 }
4528 }
4505
4529
4506 # Turn pipes/sockets into observers so we can log I/O.
4530 # Turn pipes/sockets into observers so we can log I/O.
4507 if ui.verbose:
4531 if ui.verbose:
4508 openerargs.update(
4532 openerargs.update(
4509 {
4533 {
4510 'loggingfh': ui,
4534 'loggingfh': ui,
4511 'loggingname': b's',
4535 'loggingname': b's',
4512 'loggingopts': {
4536 'loggingopts': {
4513 'logdata': True,
4537 'logdata': True,
4514 'logdataapis': False,
4538 'logdataapis': False,
4515 },
4539 },
4516 }
4540 }
4517 )
4541 )
4518
4542
4519 if ui.debugflag:
4543 if ui.debugflag:
4520 openerargs['loggingopts']['logdataapis'] = True
4544 openerargs['loggingopts']['logdataapis'] = True
4521
4545
4522 # Don't send default headers when in raw mode. This allows us to
4546 # Don't send default headers when in raw mode. This allows us to
4523 # bypass most of the behavior of our URL handling code so we can
4547 # bypass most of the behavior of our URL handling code so we can
4524 # have near complete control over what's sent on the wire.
4548 # have near complete control over what's sent on the wire.
4525 if opts['peer'] == b'raw':
4549 if opts['peer'] == b'raw':
4526 openerargs['sendaccept'] = False
4550 openerargs['sendaccept'] = False
4527
4551
4528 opener = urlmod.opener(ui, authinfo, **openerargs)
4552 opener = urlmod.opener(ui, authinfo, **openerargs)
4529
4553
4530 if opts['peer'] == b'raw':
4554 if opts['peer'] == b'raw':
4531 ui.write(_(b'using raw connection to peer\n'))
4555 ui.write(_(b'using raw connection to peer\n'))
4532 peer = None
4556 peer = None
4533 elif opts['peer']:
4557 elif opts['peer']:
4534 raise error.Abort(
4558 raise error.Abort(
4535 _(b'--peer %s not supported with HTTP peers') % opts['peer']
4559 _(b'--peer %s not supported with HTTP peers') % opts['peer']
4536 )
4560 )
4537 else:
4561 else:
4538 peer_path = urlutil.try_path(ui, path)
4562 peer_path = urlutil.try_path(ui, path)
4539 peer = httppeer._make_peer(ui, peer_path, opener=opener)
4563 peer = httppeer._make_peer(ui, peer_path, opener=opener)
4540
4564
4541 # We /could/ populate stdin/stdout with sock.makefile()...
4565 # We /could/ populate stdin/stdout with sock.makefile()...
4542 else:
4566 else:
4543 raise error.Abort(_(b'unsupported connection configuration'))
4567 raise error.Abort(_(b'unsupported connection configuration'))
4544
4568
4545 batchedcommands = None
4569 batchedcommands = None
4546
4570
4547 # Now perform actions based on the parsed wire language instructions.
4571 # Now perform actions based on the parsed wire language instructions.
4548 for action, lines in blocks:
4572 for action, lines in blocks:
4549 if action in (b'raw', b'raw+'):
4573 if action in (b'raw', b'raw+'):
4550 if not stdin:
4574 if not stdin:
4551 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4575 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4552
4576
4553 # Concatenate the data together.
4577 # Concatenate the data together.
4554 data = b''.join(l.lstrip() for l in lines)
4578 data = b''.join(l.lstrip() for l in lines)
4555 data = stringutil.unescapestr(data)
4579 data = stringutil.unescapestr(data)
4556 stdin.write(data)
4580 stdin.write(data)
4557
4581
4558 if action == b'raw+':
4582 if action == b'raw+':
4559 stdin.flush()
4583 stdin.flush()
4560 elif action == b'flush':
4584 elif action == b'flush':
4561 if not stdin:
4585 if not stdin:
4562 raise error.Abort(_(b'cannot call flush on this peer'))
4586 raise error.Abort(_(b'cannot call flush on this peer'))
4563 stdin.flush()
4587 stdin.flush()
4564 elif action.startswith(b'command'):
4588 elif action.startswith(b'command'):
4565 if not peer:
4589 if not peer:
4566 raise error.Abort(
4590 raise error.Abort(
4567 _(
4591 _(
4568 b'cannot send commands unless peer instance '
4592 b'cannot send commands unless peer instance '
4569 b'is available'
4593 b'is available'
4570 )
4594 )
4571 )
4595 )
4572
4596
4573 command = action.split(b' ', 1)[1]
4597 command = action.split(b' ', 1)[1]
4574
4598
4575 args = {}
4599 args = {}
4576 for line in lines:
4600 for line in lines:
4577 # We need to allow empty values.
4601 # We need to allow empty values.
4578 fields = line.lstrip().split(b' ', 1)
4602 fields = line.lstrip().split(b' ', 1)
4579 if len(fields) == 1:
4603 if len(fields) == 1:
4580 key = fields[0]
4604 key = fields[0]
4581 value = b''
4605 value = b''
4582 else:
4606 else:
4583 key, value = fields
4607 key, value = fields
4584
4608
4585 if value.startswith(b'eval:'):
4609 if value.startswith(b'eval:'):
4586 value = stringutil.evalpythonliteral(value[5:])
4610 value = stringutil.evalpythonliteral(value[5:])
4587 else:
4611 else:
4588 value = stringutil.unescapestr(value)
4612 value = stringutil.unescapestr(value)
4589
4613
4590 args[key] = value
4614 args[key] = value
4591
4615
4592 if batchedcommands is not None:
4616 if batchedcommands is not None:
4593 batchedcommands.append((command, args))
4617 batchedcommands.append((command, args))
4594 continue
4618 continue
4595
4619
4596 ui.status(_(b'sending %s command\n') % command)
4620 ui.status(_(b'sending %s command\n') % command)
4597
4621
4598 if b'PUSHFILE' in args:
4622 if b'PUSHFILE' in args:
4599 with open(args[b'PUSHFILE'], 'rb') as fh:
4623 with open(args[b'PUSHFILE'], 'rb') as fh:
4600 del args[b'PUSHFILE']
4624 del args[b'PUSHFILE']
4601 res, output = peer._callpush(
4625 res, output = peer._callpush(
4602 command, fh, **pycompat.strkwargs(args)
4626 command, fh, **pycompat.strkwargs(args)
4603 )
4627 )
4604 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4628 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4605 ui.status(
4629 ui.status(
4606 _(b'remote output: %s\n') % stringutil.escapestr(output)
4630 _(b'remote output: %s\n') % stringutil.escapestr(output)
4607 )
4631 )
4608 else:
4632 else:
4609 with peer.commandexecutor() as e:
4633 with peer.commandexecutor() as e:
4610 res = e.callcommand(command, args).result()
4634 res = e.callcommand(command, args).result()
4611
4635
4612 ui.status(
4636 ui.status(
4613 _(b'response: %s\n')
4637 _(b'response: %s\n')
4614 % stringutil.pprint(res, bprefix=True, indent=2)
4638 % stringutil.pprint(res, bprefix=True, indent=2)
4615 )
4639 )
4616
4640
4617 elif action == b'batchbegin':
4641 elif action == b'batchbegin':
4618 if batchedcommands is not None:
4642 if batchedcommands is not None:
4619 raise error.Abort(_(b'nested batchbegin not allowed'))
4643 raise error.Abort(_(b'nested batchbegin not allowed'))
4620
4644
4621 batchedcommands = []
4645 batchedcommands = []
4622 elif action == b'batchsubmit':
4646 elif action == b'batchsubmit':
4623 # There is a batching API we could go through. But it would be
4647 # There is a batching API we could go through. But it would be
4624 # difficult to normalize requests into function calls. It is easier
4648 # difficult to normalize requests into function calls. It is easier
4625 # to bypass this layer and normalize to commands + args.
4649 # to bypass this layer and normalize to commands + args.
4626 ui.status(
4650 ui.status(
4627 _(b'sending batch with %d sub-commands\n')
4651 _(b'sending batch with %d sub-commands\n')
4628 % len(batchedcommands)
4652 % len(batchedcommands)
4629 )
4653 )
4630 assert peer is not None
4654 assert peer is not None
4631 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4655 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4632 ui.status(
4656 ui.status(
4633 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4657 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4634 )
4658 )
4635
4659
4636 batchedcommands = None
4660 batchedcommands = None
4637
4661
4638 elif action.startswith(b'httprequest '):
4662 elif action.startswith(b'httprequest '):
4639 if not opener:
4663 if not opener:
4640 raise error.Abort(
4664 raise error.Abort(
4641 _(b'cannot use httprequest without an HTTP peer')
4665 _(b'cannot use httprequest without an HTTP peer')
4642 )
4666 )
4643
4667
4644 request = action.split(b' ', 2)
4668 request = action.split(b' ', 2)
4645 if len(request) != 3:
4669 if len(request) != 3:
4646 raise error.Abort(
4670 raise error.Abort(
4647 _(
4671 _(
4648 b'invalid httprequest: expected format is '
4672 b'invalid httprequest: expected format is '
4649 b'"httprequest <method> <path>'
4673 b'"httprequest <method> <path>'
4650 )
4674 )
4651 )
4675 )
4652
4676
4653 method, httppath = request[1:]
4677 method, httppath = request[1:]
4654 headers = {}
4678 headers = {}
4655 body = None
4679 body = None
4656 frames = []
4680 frames = []
4657 for line in lines:
4681 for line in lines:
4658 line = line.lstrip()
4682 line = line.lstrip()
4659 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4683 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4660 if m:
4684 if m:
4661 # Headers need to use native strings.
4685 # Headers need to use native strings.
4662 key = pycompat.strurl(m.group(1))
4686 key = pycompat.strurl(m.group(1))
4663 value = pycompat.strurl(m.group(2))
4687 value = pycompat.strurl(m.group(2))
4664 headers[key] = value
4688 headers[key] = value
4665 continue
4689 continue
4666
4690
4667 if line.startswith(b'BODYFILE '):
4691 if line.startswith(b'BODYFILE '):
4668 with open(line.split(b' ', 1), b'rb') as fh:
4692 with open(line.split(b' ', 1), b'rb') as fh:
4669 body = fh.read()
4693 body = fh.read()
4670 elif line.startswith(b'frame '):
4694 elif line.startswith(b'frame '):
4671 frame = wireprotoframing.makeframefromhumanstring(
4695 frame = wireprotoframing.makeframefromhumanstring(
4672 line[len(b'frame ') :]
4696 line[len(b'frame ') :]
4673 )
4697 )
4674
4698
4675 frames.append(frame)
4699 frames.append(frame)
4676 else:
4700 else:
4677 raise error.Abort(
4701 raise error.Abort(
4678 _(b'unknown argument to httprequest: %s') % line
4702 _(b'unknown argument to httprequest: %s') % line
4679 )
4703 )
4680
4704
4681 url = path + httppath
4705 url = path + httppath
4682
4706
4683 if frames:
4707 if frames:
4684 body = b''.join(bytes(f) for f in frames)
4708 body = b''.join(bytes(f) for f in frames)
4685
4709
4686 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4710 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4687
4711
4688 # urllib.Request insists on using has_data() as a proxy for
4712 # urllib.Request insists on using has_data() as a proxy for
4689 # determining the request method. Override that to use our
4713 # determining the request method. Override that to use our
4690 # explicitly requested method.
4714 # explicitly requested method.
4691 req.get_method = lambda: pycompat.sysstr(method)
4715 req.get_method = lambda: pycompat.sysstr(method)
4692
4716
4693 try:
4717 try:
4694 res = opener.open(req)
4718 res = opener.open(req)
4695 body = res.read()
4719 body = res.read()
4696 except util.urlerr.urlerror as e:
4720 except util.urlerr.urlerror as e:
4697 # read() method must be called, but only exists in Python 2
4721 # read() method must be called, but only exists in Python 2
4698 getattr(e, 'read', lambda: None)()
4722 getattr(e, 'read', lambda: None)()
4699 continue
4723 continue
4700
4724
4701 ct = res.headers.get('Content-Type')
4725 ct = res.headers.get('Content-Type')
4702 if ct == 'application/mercurial-cbor':
4726 if ct == 'application/mercurial-cbor':
4703 ui.write(
4727 ui.write(
4704 _(b'cbor> %s\n')
4728 _(b'cbor> %s\n')
4705 % stringutil.pprint(
4729 % stringutil.pprint(
4706 cborutil.decodeall(body), bprefix=True, indent=2
4730 cborutil.decodeall(body), bprefix=True, indent=2
4707 )
4731 )
4708 )
4732 )
4709
4733
4710 elif action == b'close':
4734 elif action == b'close':
4711 assert peer is not None
4735 assert peer is not None
4712 peer.close()
4736 peer.close()
4713 elif action == b'readavailable':
4737 elif action == b'readavailable':
4714 if not stdout or not stderr:
4738 if not stdout or not stderr:
4715 raise error.Abort(
4739 raise error.Abort(
4716 _(b'readavailable not available on this peer')
4740 _(b'readavailable not available on this peer')
4717 )
4741 )
4718
4742
4719 stdin.close()
4743 stdin.close()
4720 stdout.read()
4744 stdout.read()
4721 stderr.read()
4745 stderr.read()
4722
4746
4723 elif action == b'readline':
4747 elif action == b'readline':
4724 if not stdout:
4748 if not stdout:
4725 raise error.Abort(_(b'readline not available on this peer'))
4749 raise error.Abort(_(b'readline not available on this peer'))
4726 stdout.readline()
4750 stdout.readline()
4727 elif action == b'ereadline':
4751 elif action == b'ereadline':
4728 if not stderr:
4752 if not stderr:
4729 raise error.Abort(_(b'ereadline not available on this peer'))
4753 raise error.Abort(_(b'ereadline not available on this peer'))
4730 stderr.readline()
4754 stderr.readline()
4731 elif action.startswith(b'read '):
4755 elif action.startswith(b'read '):
4732 count = int(action.split(b' ', 1)[1])
4756 count = int(action.split(b' ', 1)[1])
4733 if not stdout:
4757 if not stdout:
4734 raise error.Abort(_(b'read not available on this peer'))
4758 raise error.Abort(_(b'read not available on this peer'))
4735 stdout.read(count)
4759 stdout.read(count)
4736 elif action.startswith(b'eread '):
4760 elif action.startswith(b'eread '):
4737 count = int(action.split(b' ', 1)[1])
4761 count = int(action.split(b' ', 1)[1])
4738 if not stderr:
4762 if not stderr:
4739 raise error.Abort(_(b'eread not available on this peer'))
4763 raise error.Abort(_(b'eread not available on this peer'))
4740 stderr.read(count)
4764 stderr.read(count)
4741 else:
4765 else:
4742 raise error.Abort(_(b'unknown action: %s') % action)
4766 raise error.Abort(_(b'unknown action: %s') % action)
4743
4767
4744 if batchedcommands is not None:
4768 if batchedcommands is not None:
4745 raise error.Abort(_(b'unclosed "batchbegin" request'))
4769 raise error.Abort(_(b'unclosed "batchbegin" request'))
4746
4770
4747 if peer:
4771 if peer:
4748 peer.close()
4772 peer.close()
4749
4773
4750 if proc:
4774 if proc:
4751 proc.kill()
4775 proc.kill()
@@ -1,458 +1,460 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 admin::verify
6 admin::verify
7 annotate
7 annotate
8 archive
8 archive
9 backout
9 backout
10 bisect
10 bisect
11 bookmarks
11 bookmarks
12 branch
12 branch
13 branches
13 branches
14 bundle
14 bundle
15 cat
15 cat
16 clone
16 clone
17 commit
17 commit
18 config
18 config
19 continue
19 continue
20 copy
20 copy
21 diff
21 diff
22 export
22 export
23 files
23 files
24 forget
24 forget
25 graft
25 graft
26 grep
26 grep
27 heads
27 heads
28 help
28 help
29 identify
29 identify
30 import
30 import
31 incoming
31 incoming
32 init
32 init
33 locate
33 locate
34 log
34 log
35 manifest
35 manifest
36 merge
36 merge
37 outgoing
37 outgoing
38 parents
38 parents
39 paths
39 paths
40 phase
40 phase
41 pull
41 pull
42 purge
42 purge
43 push
43 push
44 recover
44 recover
45 remove
45 remove
46 rename
46 rename
47 resolve
47 resolve
48 revert
48 revert
49 rollback
49 rollback
50 root
50 root
51 serve
51 serve
52 shelve
52 shelve
53 status
53 status
54 summary
54 summary
55 tag
55 tag
56 tags
56 tags
57 tip
57 tip
58 unbundle
58 unbundle
59 unshelve
59 unshelve
60 update
60 update
61 verify
61 verify
62 version
62 version
63
63
64 Show all commands that start with "a"
64 Show all commands that start with "a"
65 $ hg debugcomplete a
65 $ hg debugcomplete a
66 abort
66 abort
67 add
67 add
68 addremove
68 addremove
69 admin::verify
69 admin::verify
70 annotate
70 annotate
71 archive
71 archive
72
72
73 Do not show debug commands if there are other candidates
73 Do not show debug commands if there are other candidates
74 $ hg debugcomplete d
74 $ hg debugcomplete d
75 diff
75 diff
76
76
77 Show debug commands if there are no other candidates
77 Show debug commands if there are no other candidates
78 $ hg debugcomplete debug
78 $ hg debugcomplete debug
79 debug-delta-find
79 debug-delta-find
80 debug-repair-issue6528
80 debug-repair-issue6528
81 debug-revlog-index
81 debug-revlog-index
82 debug-revlog-stats
82 debug-revlog-stats
83 debug::stable-tail-sort
83 debug::stable-tail-sort
84 debug::stable-tail-sort-leaps
84 debug::stable-tail-sort-leaps
85 debug::unbundle
85 debugancestor
86 debugancestor
86 debugantivirusrunning
87 debugantivirusrunning
87 debugapplystreamclonebundle
88 debugapplystreamclonebundle
88 debugbackupbundle
89 debugbackupbundle
89 debugbuilddag
90 debugbuilddag
90 debugbundle
91 debugbundle
91 debugcapabilities
92 debugcapabilities
92 debugchangedfiles
93 debugchangedfiles
93 debugcheckstate
94 debugcheckstate
94 debugcolor
95 debugcolor
95 debugcommands
96 debugcommands
96 debugcomplete
97 debugcomplete
97 debugconfig
98 debugconfig
98 debugcreatestreamclonebundle
99 debugcreatestreamclonebundle
99 debugdag
100 debugdag
100 debugdata
101 debugdata
101 debugdate
102 debugdate
102 debugdeltachain
103 debugdeltachain
103 debugdirstate
104 debugdirstate
104 debugdirstateignorepatternshash
105 debugdirstateignorepatternshash
105 debugdiscovery
106 debugdiscovery
106 debugdownload
107 debugdownload
107 debugextensions
108 debugextensions
108 debugfileset
109 debugfileset
109 debugformat
110 debugformat
110 debugfsinfo
111 debugfsinfo
111 debuggetbundle
112 debuggetbundle
112 debugignore
113 debugignore
113 debugindexdot
114 debugindexdot
114 debugindexstats
115 debugindexstats
115 debuginstall
116 debuginstall
116 debugknown
117 debugknown
117 debuglabelcomplete
118 debuglabelcomplete
118 debuglocks
119 debuglocks
119 debugmanifestfulltextcache
120 debugmanifestfulltextcache
120 debugmergestate
121 debugmergestate
121 debugnamecomplete
122 debugnamecomplete
122 debugnodemap
123 debugnodemap
123 debugobsolete
124 debugobsolete
124 debugp1copies
125 debugp1copies
125 debugp2copies
126 debugp2copies
126 debugpathcomplete
127 debugpathcomplete
127 debugpathcopies
128 debugpathcopies
128 debugpeer
129 debugpeer
129 debugpickmergetool
130 debugpickmergetool
130 debugpushkey
131 debugpushkey
131 debugpvec
132 debugpvec
132 debugrebuilddirstate
133 debugrebuilddirstate
133 debugrebuildfncache
134 debugrebuildfncache
134 debugrename
135 debugrename
135 debugrequires
136 debugrequires
136 debugrevlog
137 debugrevlog
137 debugrevlogindex
138 debugrevlogindex
138 debugrevspec
139 debugrevspec
139 debugserve
140 debugserve
140 debugsetparents
141 debugsetparents
141 debugshell
142 debugshell
142 debugsidedata
143 debugsidedata
143 debugssl
144 debugssl
144 debugstrip
145 debugstrip
145 debugsub
146 debugsub
146 debugsuccessorssets
147 debugsuccessorssets
147 debugtagscache
148 debugtagscache
148 debugtemplate
149 debugtemplate
149 debuguigetpass
150 debuguigetpass
150 debuguiprompt
151 debuguiprompt
151 debugupdatecaches
152 debugupdatecaches
152 debugupgraderepo
153 debugupgraderepo
153 debugwalk
154 debugwalk
154 debugwhyunstable
155 debugwhyunstable
155 debugwireargs
156 debugwireargs
156 debugwireproto
157 debugwireproto
157
158
158 Do not show the alias of a debug command if there are other candidates
159 Do not show the alias of a debug command if there are other candidates
159 (this should hide rawcommit)
160 (this should hide rawcommit)
160 $ hg debugcomplete r
161 $ hg debugcomplete r
161 recover
162 recover
162 remove
163 remove
163 rename
164 rename
164 resolve
165 resolve
165 revert
166 revert
166 rollback
167 rollback
167 root
168 root
168 Show the alias of a debug command if there are no other candidates
169 Show the alias of a debug command if there are no other candidates
169 $ hg debugcomplete rawc
170 $ hg debugcomplete rawc
170
171
171
172
172 Show the global options
173 Show the global options
173 $ hg debugcomplete --options | sort
174 $ hg debugcomplete --options | sort
174 --color
175 --color
175 --config
176 --config
176 --cwd
177 --cwd
177 --debug
178 --debug
178 --debugger
179 --debugger
179 --encoding
180 --encoding
180 --encodingmode
181 --encodingmode
181 --help
182 --help
182 --hidden
183 --hidden
183 --noninteractive
184 --noninteractive
184 --pager
185 --pager
185 --profile
186 --profile
186 --quiet
187 --quiet
187 --repository
188 --repository
188 --time
189 --time
189 --traceback
190 --traceback
190 --verbose
191 --verbose
191 --version
192 --version
192 -R
193 -R
193 -h
194 -h
194 -q
195 -q
195 -v
196 -v
196 -y
197 -y
197
198
198 Show the options for the "serve" command
199 Show the options for the "serve" command
199 $ hg debugcomplete --options serve | sort
200 $ hg debugcomplete --options serve | sort
200 --accesslog
201 --accesslog
201 --address
202 --address
202 --certificate
203 --certificate
203 --cmdserver
204 --cmdserver
204 --color
205 --color
205 --config
206 --config
206 --cwd
207 --cwd
207 --daemon
208 --daemon
208 --daemon-postexec
209 --daemon-postexec
209 --debug
210 --debug
210 --debugger
211 --debugger
211 --encoding
212 --encoding
212 --encodingmode
213 --encodingmode
213 --errorlog
214 --errorlog
214 --help
215 --help
215 --hidden
216 --hidden
216 --ipv6
217 --ipv6
217 --name
218 --name
218 --noninteractive
219 --noninteractive
219 --pager
220 --pager
220 --pid-file
221 --pid-file
221 --port
222 --port
222 --prefix
223 --prefix
223 --print-url
224 --print-url
224 --profile
225 --profile
225 --quiet
226 --quiet
226 --repository
227 --repository
227 --stdio
228 --stdio
228 --style
229 --style
229 --subrepos
230 --subrepos
230 --templates
231 --templates
231 --time
232 --time
232 --traceback
233 --traceback
233 --verbose
234 --verbose
234 --version
235 --version
235 --web-conf
236 --web-conf
236 -6
237 -6
237 -A
238 -A
238 -E
239 -E
239 -R
240 -R
240 -S
241 -S
241 -a
242 -a
242 -d
243 -d
243 -h
244 -h
244 -n
245 -n
245 -p
246 -p
246 -q
247 -q
247 -t
248 -t
248 -v
249 -v
249 -y
250 -y
250
251
251 Show an error if we use --options with an ambiguous abbreviation
252 Show an error if we use --options with an ambiguous abbreviation
252 $ hg debugcomplete --options s
253 $ hg debugcomplete --options s
253 hg: command 's' is ambiguous:
254 hg: command 's' is ambiguous:
254 serve shelve showconfig status summary
255 serve shelve showconfig status summary
255 [10]
256 [10]
256
257
257 Show all commands + options
258 Show all commands + options
258 $ hg debugcommands
259 $ hg debugcommands
259 abort: dry-run
260 abort: dry-run
260 add: include, exclude, subrepos, dry-run
261 add: include, exclude, subrepos, dry-run
261 addremove: similarity, subrepos, include, exclude, dry-run
262 addremove: similarity, subrepos, include, exclude, dry-run
262 admin::verify: check, option
263 admin::verify: check, option
263 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, line-range, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
264 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, line-range, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
264 archive: no-decode, prefix, rev, type, subrepos, include, exclude
265 archive: no-decode, prefix, rev, type, subrepos, include, exclude
265 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
266 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
266 bisect: reset, good, bad, skip, extend, command, noupdate
267 bisect: reset, good, bad, skip, extend, command, noupdate
267 bookmarks: force, rev, delete, rename, inactive, list, template
268 bookmarks: force, rev, delete, rename, inactive, list, template
268 branch: force, clean, rev
269 branch: force, clean, rev
269 branches: active, closed, rev, template
270 branches: active, closed, rev, template
270 bundle: exact, force, rev, branch, base, all, type, ssh, remotecmd, insecure
271 bundle: exact, force, rev, branch, base, all, type, ssh, remotecmd, insecure
271 cat: output, rev, decode, include, exclude, template
272 cat: output, rev, decode, include, exclude, template
272 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
273 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
273 commit: addremove, close-branch, amend, secret, draft, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
274 commit: addremove, close-branch, amend, secret, draft, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
274 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
275 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
275 continue: dry-run
276 continue: dry-run
276 copy: forget, after, at-rev, force, include, exclude, dry-run
277 copy: forget, after, at-rev, force, include, exclude, dry-run
277 debug-delta-find: changelog, manifest, dir, template, source
278 debug-delta-find: changelog, manifest, dir, template, source
278 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
279 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
279 debug-revlog-index: changelog, manifest, dir, template
280 debug-revlog-index: changelog, manifest, dir, template
280 debug-revlog-stats: changelog, manifest, filelogs, template
281 debug-revlog-stats: changelog, manifest, filelogs, template
281 debug::stable-tail-sort: template
282 debug::stable-tail-sort: template
282 debug::stable-tail-sort-leaps: template, specific
283 debug::stable-tail-sort-leaps: template, specific
284 debug::unbundle: update
283 debugancestor:
285 debugancestor:
284 debugantivirusrunning:
286 debugantivirusrunning:
285 debugapplystreamclonebundle:
287 debugapplystreamclonebundle:
286 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
288 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
287 debugbuilddag: mergeable-file, overwritten-file, new-file, from-existing
289 debugbuilddag: mergeable-file, overwritten-file, new-file, from-existing
288 debugbundle: all, part-type, spec
290 debugbundle: all, part-type, spec
289 debugcapabilities:
291 debugcapabilities:
290 debugchangedfiles: compute
292 debugchangedfiles: compute
291 debugcheckstate:
293 debugcheckstate:
292 debugcolor: style
294 debugcolor: style
293 debugcommands:
295 debugcommands:
294 debugcomplete: options
296 debugcomplete: options
295 debugcreatestreamclonebundle:
297 debugcreatestreamclonebundle:
296 debugdag: tags, branches, dots, spaces
298 debugdag: tags, branches, dots, spaces
297 debugdata: changelog, manifest, dir
299 debugdata: changelog, manifest, dir
298 debugdate: extended
300 debugdate: extended
299 debugdeltachain: rev, all-info, size-info, dist-info, sparse-info, changelog, manifest, dir, template
301 debugdeltachain: rev, all-info, size-info, dist-info, sparse-info, changelog, manifest, dir, template
300 debugdirstateignorepatternshash:
302 debugdirstateignorepatternshash:
301 debugdirstate: nodates, dates, datesort, docket, all
303 debugdirstate: nodates, dates, datesort, docket, all
302 debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template
304 debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template
303 debugdownload: output
305 debugdownload: output
304 debugextensions: template
306 debugextensions: template
305 debugfileset: rev, all-files, show-matcher, show-stage
307 debugfileset: rev, all-files, show-matcher, show-stage
306 debugformat: template
308 debugformat: template
307 debugfsinfo:
309 debugfsinfo:
308 debuggetbundle: head, common, type
310 debuggetbundle: head, common, type
309 debugignore:
311 debugignore:
310 debugindexdot: changelog, manifest, dir
312 debugindexdot: changelog, manifest, dir
311 debugindexstats:
313 debugindexstats:
312 debuginstall: template
314 debuginstall: template
313 debugknown:
315 debugknown:
314 debuglabelcomplete:
316 debuglabelcomplete:
315 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
317 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
316 debugmanifestfulltextcache: clear, add
318 debugmanifestfulltextcache: clear, add
317 debugmergestate: style, template
319 debugmergestate: style, template
318 debugnamecomplete:
320 debugnamecomplete:
319 debugnodemap: changelog, manifest, dir, dump-new, dump-disk, check, metadata
321 debugnodemap: changelog, manifest, dir, dump-new, dump-disk, check, metadata
320 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
322 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
321 debugp1copies: rev
323 debugp1copies: rev
322 debugp2copies: rev
324 debugp2copies: rev
323 debugpathcomplete: full, normal, added, removed
325 debugpathcomplete: full, normal, added, removed
324 debugpathcopies: include, exclude
326 debugpathcopies: include, exclude
325 debugpeer:
327 debugpeer:
326 debugpickmergetool: rev, changedelete, include, exclude, tool
328 debugpickmergetool: rev, changedelete, include, exclude, tool
327 debugpushkey:
329 debugpushkey:
328 debugpvec:
330 debugpvec:
329 debugrebuilddirstate: rev, minimal
331 debugrebuilddirstate: rev, minimal
330 debugrebuildfncache: only-data
332 debugrebuildfncache: only-data
331 debugrename: rev
333 debugrename: rev
332 debugrequires:
334 debugrequires:
333 debugrevlog: changelog, manifest, dir, dump
335 debugrevlog: changelog, manifest, dir, dump
334 debugrevlogindex: changelog, manifest, dir, format
336 debugrevlogindex: changelog, manifest, dir, format
335 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
337 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
336 debugserve: sshstdio, logiofd, logiofile
338 debugserve: sshstdio, logiofd, logiofile
337 debugsetparents:
339 debugsetparents:
338 debugshell: command
340 debugshell: command
339 debugsidedata: changelog, manifest, dir
341 debugsidedata: changelog, manifest, dir
340 debugssl:
342 debugssl:
341 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
343 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
342 debugsub: rev
344 debugsub: rev
343 debugsuccessorssets: closest
345 debugsuccessorssets: closest
344 debugtagscache:
346 debugtagscache:
345 debugtemplate: rev, define
347 debugtemplate: rev, define
346 debuguigetpass: prompt
348 debuguigetpass: prompt
347 debuguiprompt: prompt
349 debuguiprompt: prompt
348 debugupdatecaches:
350 debugupdatecaches:
349 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
351 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
350 debugwalk: include, exclude
352 debugwalk: include, exclude
351 debugwhyunstable:
353 debugwhyunstable:
352 debugwireargs: three, four, five, ssh, remotecmd, insecure
354 debugwireargs: three, four, five, ssh, remotecmd, insecure
353 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
355 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
354 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
356 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
355 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
357 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
356 files: rev, print0, include, exclude, template, subrepos
358 files: rev, print0, include, exclude, template, subrepos
357 forget: interactive, include, exclude, dry-run
359 forget: interactive, include, exclude, dry-run
358 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
360 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
359 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
361 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
360 heads: rev, topo, active, closed, style, template
362 heads: rev, topo, active, closed, style, template
361 help: extension, command, keyword, system
363 help: extension, command, keyword, system
362 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
364 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
363 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
365 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
364 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
366 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
365 init: ssh, remotecmd, insecure
367 init: ssh, remotecmd, insecure
366 locate: rev, print0, fullpath, include, exclude
368 locate: rev, print0, fullpath, include, exclude
367 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
369 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
368 manifest: rev, all, template
370 manifest: rev, all, template
369 merge: force, rev, preview, abort, tool
371 merge: force, rev, preview, abort, tool
370 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
372 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
371 parents: rev, style, template
373 parents: rev, style, template
372 paths: template
374 paths: template
373 phase: public, draft, secret, force, rev
375 phase: public, draft, secret, force, rev
374 pull: update, force, confirm, rev, bookmark, branch, remote-hidden, ssh, remotecmd, insecure
376 pull: update, force, confirm, rev, bookmark, branch, remote-hidden, ssh, remotecmd, insecure
375 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
377 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
376 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
378 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
377 recover: verify
379 recover: verify
378 remove: after, force, subrepos, include, exclude, dry-run
380 remove: after, force, subrepos, include, exclude, dry-run
379 rename: forget, after, at-rev, force, include, exclude, dry-run
381 rename: forget, after, at-rev, force, include, exclude, dry-run
380 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
382 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
381 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
383 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
382 rollback: dry-run, force
384 rollback: dry-run, force
383 root: template
385 root: template
384 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
386 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
385 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
387 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
386 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
388 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
387 summary: remote
389 summary: remote
388 tag: force, local, rev, remove, edit, message, date, user
390 tag: force, local, rev, remove, edit, message, date, user
389 tags: template
391 tags: template
390 tip: patch, git, style, template
392 tip: patch, git, style, template
391 unbundle: update
393 unbundle: update
392 unshelve: abort, continue, interactive, keep, name, tool, date
394 unshelve: abort, continue, interactive, keep, name, tool, date
393 update: clean, check, merge, date, rev, tool
395 update: clean, check, merge, date, rev, tool
394 verify: full
396 verify: full
395 version: template
397 version: template
396
398
397 $ hg init a
399 $ hg init a
398 $ cd a
400 $ cd a
399 $ echo fee > fee
401 $ echo fee > fee
400 $ hg ci -q -Amfee
402 $ hg ci -q -Amfee
401 $ hg tag fee
403 $ hg tag fee
402 $ mkdir fie
404 $ mkdir fie
403 $ echo dead > fie/dead
405 $ echo dead > fie/dead
404 $ echo live > fie/live
406 $ echo live > fie/live
405 $ hg bookmark fo
407 $ hg bookmark fo
406 $ hg branch -q fie
408 $ hg branch -q fie
407 $ hg ci -q -Amfie
409 $ hg ci -q -Amfie
408 $ echo fo > fo
410 $ echo fo > fo
409 $ hg branch -qf default
411 $ hg branch -qf default
410 $ hg ci -q -Amfo
412 $ hg ci -q -Amfo
411 $ echo Fum > Fum
413 $ echo Fum > Fum
412 $ hg ci -q -AmFum
414 $ hg ci -q -AmFum
413 $ hg bookmark Fum
415 $ hg bookmark Fum
414
416
415 Test debugpathcomplete
417 Test debugpathcomplete
416
418
417 $ hg debugpathcomplete f
419 $ hg debugpathcomplete f
418 fee
420 fee
419 fie
421 fie
420 fo
422 fo
421 $ hg debugpathcomplete -f f
423 $ hg debugpathcomplete -f f
422 fee
424 fee
423 fie/dead
425 fie/dead
424 fie/live
426 fie/live
425 fo
427 fo
426
428
427 $ hg rm Fum
429 $ hg rm Fum
428 $ hg debugpathcomplete -r F
430 $ hg debugpathcomplete -r F
429 Fum
431 Fum
430
432
431 Test debugnamecomplete
433 Test debugnamecomplete
432
434
433 $ hg debugnamecomplete
435 $ hg debugnamecomplete
434 Fum
436 Fum
435 default
437 default
436 fee
438 fee
437 fie
439 fie
438 fo
440 fo
439 tip
441 tip
440 $ hg debugnamecomplete f
442 $ hg debugnamecomplete f
441 fee
443 fee
442 fie
444 fie
443 fo
445 fo
444
446
445 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
447 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
446 used for completions in some shells.
448 used for completions in some shells.
447
449
448 $ hg debuglabelcomplete
450 $ hg debuglabelcomplete
449 Fum
451 Fum
450 default
452 default
451 fee
453 fee
452 fie
454 fie
453 fo
455 fo
454 tip
456 tip
455 $ hg debuglabelcomplete f
457 $ hg debuglabelcomplete f
456 fee
458 fee
457 fie
459 fie
458 fo
460 fo
@@ -1,818 +1,831 b''
1 $ cat << EOF >> $HGRCPATH
1 $ cat << EOF >> $HGRCPATH
2 > [ui]
2 > [ui]
3 > interactive=yes
3 > interactive=yes
4 > EOF
4 > EOF
5
5
6 $ hg init debugrevlog
6 $ hg init debugrevlog
7 $ cd debugrevlog
7 $ cd debugrevlog
8 $ echo a > a
8 $ echo a > a
9 $ hg ci -Am adda
9 $ hg ci -Am adda
10 adding a
10 adding a
11 $ hg rm .
11 $ hg rm .
12 removing a
12 removing a
13 $ hg ci -Am make-it-empty
13 $ hg ci -Am make-it-empty
14 $ hg revert --all -r 0
14 $ hg revert --all -r 0
15 adding a
15 adding a
16 $ hg ci -Am make-it-full
16 $ hg ci -Am make-it-full
17 #if reporevlogstore
17 #if reporevlogstore
18 $ hg debugrevlog -c
18 $ hg debugrevlog -c
19 format : 1
19 format : 1
20 flags : (none)
20 flags : (none)
21
21
22 revisions : 3
22 revisions : 3
23 merges : 0 ( 0.00%)
23 merges : 0 ( 0.00%)
24 normal : 3 (100.00%)
24 normal : 3 (100.00%)
25 revisions : 3
25 revisions : 3
26 empty : 0 ( 0.00%)
26 empty : 0 ( 0.00%)
27 text : 0 (100.00%)
27 text : 0 (100.00%)
28 delta : 0 (100.00%)
28 delta : 0 (100.00%)
29 snapshot : 3 (100.00%)
29 snapshot : 3 (100.00%)
30 lvl-0 : 3 (100.00%)
30 lvl-0 : 3 (100.00%)
31 deltas : 0 ( 0.00%)
31 deltas : 0 ( 0.00%)
32 revision size : 191
32 revision size : 191
33 snapshot : 191 (100.00%)
33 snapshot : 191 (100.00%)
34 lvl-0 : 191 (100.00%)
34 lvl-0 : 191 (100.00%)
35 deltas : 0 ( 0.00%)
35 deltas : 0 ( 0.00%)
36
36
37 chunks : 3
37 chunks : 3
38 0x75 (u) : 3 (100.00%)
38 0x75 (u) : 3 (100.00%)
39 chunks size : 191
39 chunks size : 191
40 0x75 (u) : 191 (100.00%)
40 0x75 (u) : 191 (100.00%)
41
41
42
42
43 total-stored-content: 188 bytes
43 total-stored-content: 188 bytes
44
44
45 avg chain length : 0
45 avg chain length : 0
46 max chain length : 0
46 max chain length : 0
47 max chain reach : 67
47 max chain reach : 67
48 compression ratio : 0
48 compression ratio : 0
49
49
50 uncompressed data size (min/max/avg) : 57 / 66 / 62
50 uncompressed data size (min/max/avg) : 57 / 66 / 62
51 full revision size (min/max/avg) : 58 / 67 / 63
51 full revision size (min/max/avg) : 58 / 67 / 63
52 inter-snapshot size (min/max/avg) : 0 / 0 / 0
52 inter-snapshot size (min/max/avg) : 0 / 0 / 0
53 delta size (min/max/avg) : 0 / 0 / 0
53 delta size (min/max/avg) : 0 / 0 / 0
54 $ hg debugrevlog -m
54 $ hg debugrevlog -m
55 format : 1
55 format : 1
56 flags : inline, generaldelta
56 flags : inline, generaldelta
57
57
58 revisions : 3
58 revisions : 3
59 merges : 0 ( 0.00%)
59 merges : 0 ( 0.00%)
60 normal : 3 (100.00%)
60 normal : 3 (100.00%)
61 revisions : 3
61 revisions : 3
62 empty : 1 (33.33%)
62 empty : 1 (33.33%)
63 text : 1 (100.00%)
63 text : 1 (100.00%)
64 delta : 0 ( 0.00%)
64 delta : 0 ( 0.00%)
65 snapshot : 2 (66.67%)
65 snapshot : 2 (66.67%)
66 lvl-0 : 2 (66.67%)
66 lvl-0 : 2 (66.67%)
67 deltas : 0 ( 0.00%)
67 deltas : 0 ( 0.00%)
68 revision size : 88
68 revision size : 88
69 snapshot : 88 (100.00%)
69 snapshot : 88 (100.00%)
70 lvl-0 : 88 (100.00%)
70 lvl-0 : 88 (100.00%)
71 deltas : 0 ( 0.00%)
71 deltas : 0 ( 0.00%)
72
72
73 chunks : 3
73 chunks : 3
74 empty : 1 (33.33%)
74 empty : 1 (33.33%)
75 0x75 (u) : 2 (66.67%)
75 0x75 (u) : 2 (66.67%)
76 chunks size : 88
76 chunks size : 88
77 empty : 0 ( 0.00%)
77 empty : 0 ( 0.00%)
78 0x75 (u) : 88 (100.00%)
78 0x75 (u) : 88 (100.00%)
79
79
80
80
81 total-stored-content: 86 bytes
81 total-stored-content: 86 bytes
82
82
83 avg chain length : 0
83 avg chain length : 0
84 max chain length : 0
84 max chain length : 0
85 max chain reach : 44
85 max chain reach : 44
86 compression ratio : 0
86 compression ratio : 0
87
87
88 uncompressed data size (min/max/avg) : 0 / 43 / 28
88 uncompressed data size (min/max/avg) : 0 / 43 / 28
89 full revision size (min/max/avg) : 44 / 44 / 44
89 full revision size (min/max/avg) : 44 / 44 / 44
90 inter-snapshot size (min/max/avg) : 0 / 0 / 0
90 inter-snapshot size (min/max/avg) : 0 / 0 / 0
91 delta size (min/max/avg) : 0 / 0 / 0
91 delta size (min/max/avg) : 0 / 0 / 0
92 $ hg debugrevlog a
92 $ hg debugrevlog a
93 format : 1
93 format : 1
94 flags : inline, generaldelta
94 flags : inline, generaldelta
95
95
96 revisions : 1
96 revisions : 1
97 merges : 0 ( 0.00%)
97 merges : 0 ( 0.00%)
98 normal : 1 (100.00%)
98 normal : 1 (100.00%)
99 revisions : 1
99 revisions : 1
100 empty : 0 ( 0.00%)
100 empty : 0 ( 0.00%)
101 text : 0 (100.00%)
101 text : 0 (100.00%)
102 delta : 0 (100.00%)
102 delta : 0 (100.00%)
103 snapshot : 1 (100.00%)
103 snapshot : 1 (100.00%)
104 lvl-0 : 1 (100.00%)
104 lvl-0 : 1 (100.00%)
105 deltas : 0 ( 0.00%)
105 deltas : 0 ( 0.00%)
106 revision size : 3
106 revision size : 3
107 snapshot : 3 (100.00%)
107 snapshot : 3 (100.00%)
108 lvl-0 : 3 (100.00%)
108 lvl-0 : 3 (100.00%)
109 deltas : 0 ( 0.00%)
109 deltas : 0 ( 0.00%)
110
110
111 chunks : 1
111 chunks : 1
112 0x75 (u) : 1 (100.00%)
112 0x75 (u) : 1 (100.00%)
113 chunks size : 3
113 chunks size : 3
114 0x75 (u) : 3 (100.00%)
114 0x75 (u) : 3 (100.00%)
115
115
116
116
117 total-stored-content: 2 bytes
117 total-stored-content: 2 bytes
118
118
119 avg chain length : 0
119 avg chain length : 0
120 max chain length : 0
120 max chain length : 0
121 max chain reach : 3
121 max chain reach : 3
122 compression ratio : 0
122 compression ratio : 0
123
123
124 uncompressed data size (min/max/avg) : 2 / 2 / 2
124 uncompressed data size (min/max/avg) : 2 / 2 / 2
125 full revision size (min/max/avg) : 3 / 3 / 3
125 full revision size (min/max/avg) : 3 / 3 / 3
126 inter-snapshot size (min/max/avg) : 0 / 0 / 0
126 inter-snapshot size (min/max/avg) : 0 / 0 / 0
127 delta size (min/max/avg) : 0 / 0 / 0
127 delta size (min/max/avg) : 0 / 0 / 0
128 #endif
128 #endif
129
129
130 Test debugindex, with and without the --verbose/--debug flag
130 Test debugindex, with and without the --verbose/--debug flag
131 $ hg debugrevlogindex a
131 $ hg debugrevlogindex a
132 rev linkrev nodeid p1 p2
132 rev linkrev nodeid p1 p2
133 0 0 b789fdd96dc2 000000000000 000000000000
133 0 0 b789fdd96dc2 000000000000 000000000000
134
134
135 #if no-reposimplestore
135 #if no-reposimplestore
136 $ hg --verbose debugrevlogindex a
136 $ hg --verbose debugrevlogindex a
137 rev offset length linkrev nodeid p1 p2
137 rev offset length linkrev nodeid p1 p2
138 0 0 3 0 b789fdd96dc2 000000000000 000000000000
138 0 0 3 0 b789fdd96dc2 000000000000 000000000000
139
139
140 $ hg --debug debugrevlogindex a
140 $ hg --debug debugrevlogindex a
141 rev offset length linkrev nodeid p1 p2
141 rev offset length linkrev nodeid p1 p2
142 0 0 3 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
142 0 0 3 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
143 #endif
143 #endif
144
144
145 $ hg debugrevlogindex -f 1 a
145 $ hg debugrevlogindex -f 1 a
146 rev flag size link p1 p2 nodeid
146 rev flag size link p1 p2 nodeid
147 0 0000 2 0 -1 -1 b789fdd96dc2
147 0 0000 2 0 -1 -1 b789fdd96dc2
148
148
149 #if no-reposimplestore
149 #if no-reposimplestore
150 $ hg --verbose debugrevlogindex -f 1 a
150 $ hg --verbose debugrevlogindex -f 1 a
151 rev flag offset length size link p1 p2 nodeid
151 rev flag offset length size link p1 p2 nodeid
152 0 0000 0 3 2 0 -1 -1 b789fdd96dc2
152 0 0000 0 3 2 0 -1 -1 b789fdd96dc2
153
153
154 $ hg --debug debugrevlogindex -f 1 a
154 $ hg --debug debugrevlogindex -f 1 a
155 rev flag offset length size link p1 p2 nodeid
155 rev flag offset length size link p1 p2 nodeid
156 0 0000 0 3 2 0 -1 -1 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
156 0 0000 0 3 2 0 -1 -1 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
157 #endif
157 #endif
158
158
159 $ hg debugindex -c
159 $ hg debugindex -c
160 rev linkrev nodeid p1-nodeid p2-nodeid
160 rev linkrev nodeid p1-nodeid p2-nodeid
161 0 0 07f494440405 000000000000 000000000000
161 0 0 07f494440405 000000000000 000000000000
162 1 1 8cccb4b5fec2 07f494440405 000000000000
162 1 1 8cccb4b5fec2 07f494440405 000000000000
163 2 2 b1e228c512c5 8cccb4b5fec2 000000000000
163 2 2 b1e228c512c5 8cccb4b5fec2 000000000000
164 $ hg debugindex -c --debug
164 $ hg debugindex -c --debug
165 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
165 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
166 0 -1 0 07f4944404050f47db2e5c5071e0e84e7a27bba9 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 57 0 0 2 0 58 inline 0 0
166 0 -1 0 07f4944404050f47db2e5c5071e0e84e7a27bba9 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 57 0 0 2 0 58 inline 0 0
167 1 -1 1 8cccb4b5fec20cafeb99dd01c26d4dee8ea4388a 0 07f4944404050f47db2e5c5071e0e84e7a27bba9 -1 0000000000000000000000000000000000000000 66 1 0 2 58 67 inline 0 0
167 1 -1 1 8cccb4b5fec20cafeb99dd01c26d4dee8ea4388a 0 07f4944404050f47db2e5c5071e0e84e7a27bba9 -1 0000000000000000000000000000000000000000 66 1 0 2 58 67 inline 0 0
168 2 -1 2 b1e228c512c5d7066d70562ed839c3323a62d6d2 1 8cccb4b5fec20cafeb99dd01c26d4dee8ea4388a -1 0000000000000000000000000000000000000000 65 2 0 2 125 66 inline 0 0
168 2 -1 2 b1e228c512c5d7066d70562ed839c3323a62d6d2 1 8cccb4b5fec20cafeb99dd01c26d4dee8ea4388a -1 0000000000000000000000000000000000000000 65 2 0 2 125 66 inline 0 0
169 $ hg debugindex -m
169 $ hg debugindex -m
170 rev linkrev nodeid p1-nodeid p2-nodeid
170 rev linkrev nodeid p1-nodeid p2-nodeid
171 0 0 a0c8bcbbb45c 000000000000 000000000000
171 0 0 a0c8bcbbb45c 000000000000 000000000000
172 1 1 57faf8a737ae a0c8bcbbb45c 000000000000
172 1 1 57faf8a737ae a0c8bcbbb45c 000000000000
173 2 2 a35b10320954 57faf8a737ae 000000000000
173 2 2 a35b10320954 57faf8a737ae 000000000000
174 $ hg debugindex -m --debug
174 $ hg debugindex -m --debug
175 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
175 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
176 0 -1 0 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 43 0 0 2 0 44 inline 0 0
176 0 -1 0 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 43 0 0 2 0 44 inline 0 0
177 1 -1 1 57faf8a737ae7faf490582941a82319ba6529dca 0 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 -1 0000000000000000000000000000000000000000 0 1 0 2 44 0 inline 0 0
177 1 -1 1 57faf8a737ae7faf490582941a82319ba6529dca 0 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 -1 0000000000000000000000000000000000000000 0 1 0 2 44 0 inline 0 0
178 2 -1 2 a35b103209548032201c16c7688cb2657f037a38 1 57faf8a737ae7faf490582941a82319ba6529dca -1 0000000000000000000000000000000000000000 43 2 0 2 44 44 inline 0 0
178 2 -1 2 a35b103209548032201c16c7688cb2657f037a38 1 57faf8a737ae7faf490582941a82319ba6529dca -1 0000000000000000000000000000000000000000 43 2 0 2 44 44 inline 0 0
179 $ hg debugindex a
179 $ hg debugindex a
180 rev linkrev nodeid p1-nodeid p2-nodeid
180 rev linkrev nodeid p1-nodeid p2-nodeid
181 0 0 b789fdd96dc2 000000000000 000000000000
181 0 0 b789fdd96dc2 000000000000 000000000000
182 $ hg debugindex --debug a
182 $ hg debugindex --debug a
183 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
183 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
184 0 -1 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 2 0 0 2 0 3 inline 0 0
184 0 -1 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 2 0 0 2 0 3 inline 0 0
185
185
186 debugdelta chain basic output
186 debugdelta chain basic output
187
187
188 #if reporevlogstore pure rust
188 #if reporevlogstore pure rust
189 $ hg debugindexstats
189 $ hg debugindexstats
190 abort: debugindexstats only works with native C code
190 abort: debugindexstats only works with native C code
191 [255]
191 [255]
192 #endif
192 #endif
193 #if reporevlogstore no-pure no-rust
193 #if reporevlogstore no-pure no-rust
194 $ hg debugindexstats
194 $ hg debugindexstats
195 node trie capacity: 4
195 node trie capacity: 4
196 node trie count: 2
196 node trie count: 2
197 node trie depth: 1
197 node trie depth: 1
198 node trie last rev scanned: -1 (no-rust !)
198 node trie last rev scanned: -1 (no-rust !)
199 node trie last rev scanned: 3 (rust !)
199 node trie last rev scanned: 3 (rust !)
200 node trie lookups: 4 (no-rust !)
200 node trie lookups: 4 (no-rust !)
201 node trie lookups: 2 (rust !)
201 node trie lookups: 2 (rust !)
202 node trie misses: 1
202 node trie misses: 1
203 node trie splits: 1
203 node trie splits: 1
204 revs in memory: 3
204 revs in memory: 3
205 #endif
205 #endif
206
206
207 #if reporevlogstore no-pure
207 #if reporevlogstore no-pure
208 $ hg debugdeltachain -m --all-info
208 $ hg debugdeltachain -m --all-info
209 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
209 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
210 0 -1 -1 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
210 0 -1 -1 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
211 1 0 -1 2 1 -1 base 0 0 0 0.00000 0 0 0.00000 0 0 1.00000 1
211 1 0 -1 2 1 -1 base 0 0 0 0.00000 0 0 0.00000 0 0 1.00000 1
212 2 1 -1 3 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
212 2 1 -1 3 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
213
213
214 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen}\n'
214 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen}\n'
215 0 1 1
215 0 1 1
216 1 2 1
216 1 2 1
217 2 3 1
217 2 3 1
218
218
219 $ hg debugdeltachain -m -Tjson --size-info
219 $ hg debugdeltachain -m -Tjson --size-info
220 [
220 [
221 {
221 {
222 "chainid": 1,
222 "chainid": 1,
223 "chainlen": 1,
223 "chainlen": 1,
224 "chainratio": 1.0232558139534884,
224 "chainratio": 1.0232558139534884,
225 "chainsize": 44,
225 "chainsize": 44,
226 "compsize": 44,
226 "compsize": 44,
227 "deltatype": "base",
227 "deltatype": "base",
228 "p1": -1,
228 "p1": -1,
229 "p2": -1,
229 "p2": -1,
230 "prevrev": -1,
230 "prevrev": -1,
231 "rev": 0,
231 "rev": 0,
232 "uncompsize": 43
232 "uncompsize": 43
233 },
233 },
234 {
234 {
235 "chainid": 2,
235 "chainid": 2,
236 "chainlen": 1,
236 "chainlen": 1,
237 "chainratio": 0,
237 "chainratio": 0,
238 "chainsize": 0,
238 "chainsize": 0,
239 "compsize": 0,
239 "compsize": 0,
240 "deltatype": "base",
240 "deltatype": "base",
241 "p1": 0,
241 "p1": 0,
242 "p2": -1,
242 "p2": -1,
243 "prevrev": -1,
243 "prevrev": -1,
244 "rev": 1,
244 "rev": 1,
245 "uncompsize": 0
245 "uncompsize": 0
246 },
246 },
247 {
247 {
248 "chainid": 3,
248 "chainid": 3,
249 "chainlen": 1,
249 "chainlen": 1,
250 "chainratio": 1.0232558139534884,
250 "chainratio": 1.0232558139534884,
251 "chainsize": 44,
251 "chainsize": 44,
252 "compsize": 44,
252 "compsize": 44,
253 "deltatype": "base",
253 "deltatype": "base",
254 "p1": 1,
254 "p1": 1,
255 "p2": -1,
255 "p2": -1,
256 "prevrev": -1,
256 "prevrev": -1,
257 "rev": 2,
257 "rev": 2,
258 "uncompsize": 43
258 "uncompsize": 43
259 }
259 }
260 ]
260 ]
261
261
262 $ hg debugdeltachain -m -Tjson --all-info
262 $ hg debugdeltachain -m -Tjson --all-info
263 [
263 [
264 {
264 {
265 "chainid": 1,
265 "chainid": 1,
266 "chainlen": 1,
266 "chainlen": 1,
267 "chainratio": 1.0232558139534884,
267 "chainratio": 1.0232558139534884,
268 "chainsize": 44,
268 "chainsize": 44,
269 "compsize": 44,
269 "compsize": 44,
270 "deltatype": "base",
270 "deltatype": "base",
271 "extradist": 0,
271 "extradist": 0,
272 "extraratio": 0.0,
272 "extraratio": 0.0,
273 "largestblock": 44,
273 "largestblock": 44,
274 "lindist": 44,
274 "lindist": 44,
275 "p1": -1,
275 "p1": -1,
276 "p2": -1,
276 "p2": -1,
277 "prevrev": -1,
277 "prevrev": -1,
278 "readdensity": 1.0,
278 "readdensity": 1.0,
279 "readsize": 44,
279 "readsize": 44,
280 "rev": 0,
280 "rev": 0,
281 "srchunks": 1,
281 "srchunks": 1,
282 "uncompsize": 43
282 "uncompsize": 43
283 },
283 },
284 {
284 {
285 "chainid": 2,
285 "chainid": 2,
286 "chainlen": 1,
286 "chainlen": 1,
287 "chainratio": 0,
287 "chainratio": 0,
288 "chainsize": 0,
288 "chainsize": 0,
289 "compsize": 0,
289 "compsize": 0,
290 "deltatype": "base",
290 "deltatype": "base",
291 "extradist": 0,
291 "extradist": 0,
292 "extraratio": 0,
292 "extraratio": 0,
293 "largestblock": 0,
293 "largestblock": 0,
294 "lindist": 0,
294 "lindist": 0,
295 "p1": 0,
295 "p1": 0,
296 "p2": -1,
296 "p2": -1,
297 "prevrev": -1,
297 "prevrev": -1,
298 "readdensity": 1,
298 "readdensity": 1,
299 "readsize": 0,
299 "readsize": 0,
300 "rev": 1,
300 "rev": 1,
301 "srchunks": 1,
301 "srchunks": 1,
302 "uncompsize": 0
302 "uncompsize": 0
303 },
303 },
304 {
304 {
305 "chainid": 3,
305 "chainid": 3,
306 "chainlen": 1,
306 "chainlen": 1,
307 "chainratio": 1.0232558139534884,
307 "chainratio": 1.0232558139534884,
308 "chainsize": 44,
308 "chainsize": 44,
309 "compsize": 44,
309 "compsize": 44,
310 "deltatype": "base",
310 "deltatype": "base",
311 "extradist": 0,
311 "extradist": 0,
312 "extraratio": 0.0,
312 "extraratio": 0.0,
313 "largestblock": 44,
313 "largestblock": 44,
314 "lindist": 44,
314 "lindist": 44,
315 "p1": 1,
315 "p1": 1,
316 "p2": -1,
316 "p2": -1,
317 "prevrev": -1,
317 "prevrev": -1,
318 "readdensity": 1.0,
318 "readdensity": 1.0,
319 "readsize": 44,
319 "readsize": 44,
320 "rev": 2,
320 "rev": 2,
321 "srchunks": 1,
321 "srchunks": 1,
322 "uncompsize": 43
322 "uncompsize": 43
323 }
323 }
324 ]
324 ]
325
325
326 debugdelta chain with sparse read enabled
326 debugdelta chain with sparse read enabled
327
327
328 $ cat >> $HGRCPATH <<EOF
328 $ cat >> $HGRCPATH <<EOF
329 > [experimental]
329 > [experimental]
330 > sparse-read = True
330 > sparse-read = True
331 > EOF
331 > EOF
332 $ hg debugdeltachain -m --all-info
332 $ hg debugdeltachain -m --all-info
333 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
333 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
334 0 -1 -1 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
334 0 -1 -1 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
335 1 0 -1 2 1 -1 base 0 0 0 0.00000 0 0 0.00000 0 0 1.00000 1
335 1 0 -1 2 1 -1 base 0 0 0 0.00000 0 0 0.00000 0 0 1.00000 1
336 2 1 -1 3 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
336 2 1 -1 3 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
337
337
338 $ hg debugdeltachain -m --sparse-info -T '{rev} {chainid} {chainlen} {readsize} {largestblock} {readdensity}\n'
338 $ hg debugdeltachain -m --sparse-info -T '{rev} {chainid} {chainlen} {readsize} {largestblock} {readdensity}\n'
339 0 1 1 44 44 1.0
339 0 1 1 44 44 1.0
340 1 2 1 0 0 1
340 1 2 1 0 0 1
341 2 3 1 44 44 1.0
341 2 3 1 44 44 1.0
342
342
343 $ hg debugdeltachain -m -Tjson --sparse-info
343 $ hg debugdeltachain -m -Tjson --sparse-info
344 [
344 [
345 {
345 {
346 "chainid": 1,
346 "chainid": 1,
347 "chainlen": 1,
347 "chainlen": 1,
348 "deltatype": "base",
348 "deltatype": "base",
349 "largestblock": 44,
349 "largestblock": 44,
350 "p1": -1,
350 "p1": -1,
351 "p2": -1,
351 "p2": -1,
352 "prevrev": -1,
352 "prevrev": -1,
353 "readdensity": 1.0,
353 "readdensity": 1.0,
354 "readsize": 44,
354 "readsize": 44,
355 "rev": 0,
355 "rev": 0,
356 "srchunks": 1
356 "srchunks": 1
357 },
357 },
358 {
358 {
359 "chainid": 2,
359 "chainid": 2,
360 "chainlen": 1,
360 "chainlen": 1,
361 "deltatype": "base",
361 "deltatype": "base",
362 "largestblock": 0,
362 "largestblock": 0,
363 "p1": 0,
363 "p1": 0,
364 "p2": -1,
364 "p2": -1,
365 "prevrev": -1,
365 "prevrev": -1,
366 "readdensity": 1,
366 "readdensity": 1,
367 "readsize": 0,
367 "readsize": 0,
368 "rev": 1,
368 "rev": 1,
369 "srchunks": 1
369 "srchunks": 1
370 },
370 },
371 {
371 {
372 "chainid": 3,
372 "chainid": 3,
373 "chainlen": 1,
373 "chainlen": 1,
374 "deltatype": "base",
374 "deltatype": "base",
375 "largestblock": 44,
375 "largestblock": 44,
376 "p1": 1,
376 "p1": 1,
377 "p2": -1,
377 "p2": -1,
378 "prevrev": -1,
378 "prevrev": -1,
379 "readdensity": 1.0,
379 "readdensity": 1.0,
380 "readsize": 44,
380 "readsize": 44,
381 "rev": 2,
381 "rev": 2,
382 "srchunks": 1
382 "srchunks": 1
383 }
383 }
384 ]
384 ]
385
385
386 $ hg debugdeltachain -m -Tjson --all-info
386 $ hg debugdeltachain -m -Tjson --all-info
387 [
387 [
388 {
388 {
389 "chainid": 1,
389 "chainid": 1,
390 "chainlen": 1,
390 "chainlen": 1,
391 "chainratio": 1.0232558139534884,
391 "chainratio": 1.0232558139534884,
392 "chainsize": 44,
392 "chainsize": 44,
393 "compsize": 44,
393 "compsize": 44,
394 "deltatype": "base",
394 "deltatype": "base",
395 "extradist": 0,
395 "extradist": 0,
396 "extraratio": 0.0,
396 "extraratio": 0.0,
397 "largestblock": 44,
397 "largestblock": 44,
398 "lindist": 44,
398 "lindist": 44,
399 "p1": -1,
399 "p1": -1,
400 "p2": -1,
400 "p2": -1,
401 "prevrev": -1,
401 "prevrev": -1,
402 "readdensity": 1.0,
402 "readdensity": 1.0,
403 "readsize": 44,
403 "readsize": 44,
404 "rev": 0,
404 "rev": 0,
405 "srchunks": 1,
405 "srchunks": 1,
406 "uncompsize": 43
406 "uncompsize": 43
407 },
407 },
408 {
408 {
409 "chainid": 2,
409 "chainid": 2,
410 "chainlen": 1,
410 "chainlen": 1,
411 "chainratio": 0,
411 "chainratio": 0,
412 "chainsize": 0,
412 "chainsize": 0,
413 "compsize": 0,
413 "compsize": 0,
414 "deltatype": "base",
414 "deltatype": "base",
415 "extradist": 0,
415 "extradist": 0,
416 "extraratio": 0,
416 "extraratio": 0,
417 "largestblock": 0,
417 "largestblock": 0,
418 "lindist": 0,
418 "lindist": 0,
419 "p1": 0,
419 "p1": 0,
420 "p2": -1,
420 "p2": -1,
421 "prevrev": -1,
421 "prevrev": -1,
422 "readdensity": 1,
422 "readdensity": 1,
423 "readsize": 0,
423 "readsize": 0,
424 "rev": 1,
424 "rev": 1,
425 "srchunks": 1,
425 "srchunks": 1,
426 "uncompsize": 0
426 "uncompsize": 0
427 },
427 },
428 {
428 {
429 "chainid": 3,
429 "chainid": 3,
430 "chainlen": 1,
430 "chainlen": 1,
431 "chainratio": 1.0232558139534884,
431 "chainratio": 1.0232558139534884,
432 "chainsize": 44,
432 "chainsize": 44,
433 "compsize": 44,
433 "compsize": 44,
434 "deltatype": "base",
434 "deltatype": "base",
435 "extradist": 0,
435 "extradist": 0,
436 "extraratio": 0.0,
436 "extraratio": 0.0,
437 "largestblock": 44,
437 "largestblock": 44,
438 "lindist": 44,
438 "lindist": 44,
439 "p1": 1,
439 "p1": 1,
440 "p2": -1,
440 "p2": -1,
441 "prevrev": -1,
441 "prevrev": -1,
442 "readdensity": 1.0,
442 "readdensity": 1.0,
443 "readsize": 44,
443 "readsize": 44,
444 "rev": 2,
444 "rev": 2,
445 "srchunks": 1,
445 "srchunks": 1,
446 "uncompsize": 43
446 "uncompsize": 43
447 }
447 }
448 ]
448 ]
449
449
450 $ printf "This test checks things.\n" >> a
450 $ printf "This test checks things.\n" >> a
451 $ hg ci -m a
451 $ hg ci -m a
452 $ hg branch other
452 $ hg branch other
453 marked working directory as branch other
453 marked working directory as branch other
454 (branches are permanent and global, did you want a bookmark?)
454 (branches are permanent and global, did you want a bookmark?)
455 $ for i in `$TESTDIR/seq.py 5`; do
455 $ for i in `$TESTDIR/seq.py 5`; do
456 > printf "shorter ${i}" >> a
456 > printf "shorter ${i}" >> a
457 > hg ci -m "a other:$i"
457 > hg ci -m "a other:$i"
458 > hg up -q default
458 > hg up -q default
459 > printf "for the branch default we want longer chains: ${i}" >> a
459 > printf "for the branch default we want longer chains: ${i}" >> a
460 > hg ci -m "a default:$i"
460 > hg ci -m "a default:$i"
461 > hg up -q other
461 > hg up -q other
462 > done
462 > done
463 $ hg debugdeltachain a -T '{rev} {srchunks}\n' --all-info\
463 $ hg debugdeltachain a -T '{rev} {srchunks}\n' --all-info\
464 > --config experimental.sparse-read.density-threshold=0.50 \
464 > --config experimental.sparse-read.density-threshold=0.50 \
465 > --config experimental.sparse-read.min-gap-size=0
465 > --config experimental.sparse-read.min-gap-size=0
466 0 1
466 0 1
467 1 1
467 1 1
468 2 1
468 2 1
469 3 1
469 3 1
470 4 1
470 4 1
471 5 1
471 5 1
472 6 1
472 6 1
473 7 1
473 7 1
474 8 1
474 8 1
475 9 1
475 9 1
476 10 2 (no-zstd !)
476 10 2 (no-zstd !)
477 10 1 (zstd !)
477 10 1 (zstd !)
478 11 1
478 11 1
479 $ hg --config extensions.strip= strip --no-backup -r 1
479 $ hg --config extensions.strip= strip --no-backup -r 1
480 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
480 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
481
481
482 Test max chain len
482 Test max chain len
483 $ cat >> $HGRCPATH << EOF
483 $ cat >> $HGRCPATH << EOF
484 > [format]
484 > [format]
485 > maxchainlen=4
485 > maxchainlen=4
486 > EOF
486 > EOF
487
487
488 $ printf "This test checks if maxchainlen config value is respected also it can serve as basic test for debugrevlog -d <file>.\n" >> a
488 $ printf "This test checks if maxchainlen config value is respected also it can serve as basic test for debugrevlog -d <file>.\n" >> a
489 $ hg ci -m a
489 $ hg ci -m a
490 $ printf "b\n" >> a
490 $ printf "b\n" >> a
491 $ hg ci -m a
491 $ hg ci -m a
492 $ printf "c\n" >> a
492 $ printf "c\n" >> a
493 $ hg ci -m a
493 $ hg ci -m a
494 $ printf "d\n" >> a
494 $ printf "d\n" >> a
495 $ hg ci -m a
495 $ hg ci -m a
496 $ printf "e\n" >> a
496 $ printf "e\n" >> a
497 $ hg ci -m a
497 $ hg ci -m a
498 $ printf "f\n" >> a
498 $ printf "f\n" >> a
499 $ hg ci -m a
499 $ hg ci -m a
500 $ printf 'g\n' >> a
500 $ printf 'g\n' >> a
501 $ hg ci -m a
501 $ hg ci -m a
502 $ printf 'h\n' >> a
502 $ printf 'h\n' >> a
503 $ hg ci -m a
503 $ hg ci -m a
504
504
505 $ hg debugrevlog -d a
505 $ hg debugrevlog -d a
506 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
506 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
507 0 -1 -1 0 ??? 0 0 0 0 ??? ???? ? 1 0 (glob)
507 0 -1 -1 0 ??? 0 0 0 0 ??? ???? ? 1 0 (glob)
508 1 0 -1 ??? ??? 0 0 0 0 ??? ???? ? 1 1 (glob)
508 1 0 -1 ??? ??? 0 0 0 0 ??? ???? ? 1 1 (glob)
509 2 1 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
509 2 1 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
510 3 2 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
510 3 2 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
511 4 3 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 4 (glob)
511 4 3 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 4 (glob)
512 5 4 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 0 (glob)
512 5 4 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 0 (glob)
513 6 5 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 1 (glob)
513 6 5 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 1 (glob)
514 7 6 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
514 7 6 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
515 8 7 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
515 8 7 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
516 #endif
516 #endif
517
517
518 Test debuglocks command:
518 Test debuglocks command:
519
519
520 $ hg debuglocks
520 $ hg debuglocks
521 lock: free
521 lock: free
522 wlock: free
522 wlock: free
523
523
524 * Test setting the lock
524 * Test setting the lock
525
525
526 waitlock <file> will wait for file to be created. If it isn't in a reasonable
526 waitlock <file> will wait for file to be created. If it isn't in a reasonable
527 amount of time, displays error message and returns 1
527 amount of time, displays error message and returns 1
528 $ waitlock() {
528 $ waitlock() {
529 > start=`date +%s`
529 > start=`date +%s`
530 > timeout=5
530 > timeout=5
531 > while [ \( ! -f $1 \) -a \( ! -L $1 \) ]; do
531 > while [ \( ! -f $1 \) -a \( ! -L $1 \) ]; do
532 > now=`date +%s`
532 > now=`date +%s`
533 > if [ "`expr $now - $start`" -gt $timeout ]; then
533 > if [ "`expr $now - $start`" -gt $timeout ]; then
534 > echo "timeout: $1 was not created in $timeout seconds"
534 > echo "timeout: $1 was not created in $timeout seconds"
535 > return 1
535 > return 1
536 > fi
536 > fi
537 > sleep 0.1
537 > sleep 0.1
538 > done
538 > done
539 > }
539 > }
540 $ dolock() {
540 $ dolock() {
541 > {
541 > {
542 > waitlock .hg/unlock
542 > waitlock .hg/unlock
543 > rm -f .hg/unlock
543 > rm -f .hg/unlock
544 > echo y
544 > echo y
545 > } | hg debuglocks "$@" > /dev/null
545 > } | hg debuglocks "$@" > /dev/null
546 > }
546 > }
547 $ dolock -s &
547 $ dolock -s &
548 $ waitlock .hg/store/lock
548 $ waitlock .hg/store/lock
549
549
550 $ hg debuglocks
550 $ hg debuglocks
551 lock: user *, process * (*s) (glob)
551 lock: user *, process * (*s) (glob)
552 wlock: free
552 wlock: free
553 [1]
553 [1]
554 $ touch .hg/unlock
554 $ touch .hg/unlock
555 $ wait
555 $ wait
556 $ [ -f .hg/store/lock ] || echo "There is no lock"
556 $ [ -f .hg/store/lock ] || echo "There is no lock"
557 There is no lock
557 There is no lock
558
558
559 * Test setting the wlock
559 * Test setting the wlock
560
560
561 $ dolock -S &
561 $ dolock -S &
562 $ waitlock .hg/wlock
562 $ waitlock .hg/wlock
563
563
564 $ hg debuglocks
564 $ hg debuglocks
565 lock: free
565 lock: free
566 wlock: user *, process * (*s) (glob)
566 wlock: user *, process * (*s) (glob)
567 [1]
567 [1]
568 $ touch .hg/unlock
568 $ touch .hg/unlock
569 $ wait
569 $ wait
570 $ [ -f .hg/wlock ] || echo "There is no wlock"
570 $ [ -f .hg/wlock ] || echo "There is no wlock"
571 There is no wlock
571 There is no wlock
572
572
573 * Test setting both locks
573 * Test setting both locks
574
574
575 $ dolock -Ss &
575 $ dolock -Ss &
576 $ waitlock .hg/wlock && waitlock .hg/store/lock
576 $ waitlock .hg/wlock && waitlock .hg/store/lock
577
577
578 $ hg debuglocks
578 $ hg debuglocks
579 lock: user *, process * (*s) (glob)
579 lock: user *, process * (*s) (glob)
580 wlock: user *, process * (*s) (glob)
580 wlock: user *, process * (*s) (glob)
581 [2]
581 [2]
582
582
583 * Test failing to set a lock
583 * Test failing to set a lock
584
584
585 $ hg debuglocks -s
585 $ hg debuglocks -s
586 abort: lock is already held
586 abort: lock is already held
587 [255]
587 [255]
588
588
589 $ hg debuglocks -S
589 $ hg debuglocks -S
590 abort: wlock is already held
590 abort: wlock is already held
591 [255]
591 [255]
592
592
593 $ touch .hg/unlock
593 $ touch .hg/unlock
594 $ wait
594 $ wait
595
595
596 $ hg debuglocks
596 $ hg debuglocks
597 lock: free
597 lock: free
598 wlock: free
598 wlock: free
599
599
600 * Test forcing the lock
600 * Test forcing the lock
601
601
602 $ dolock -s &
602 $ dolock -s &
603 $ waitlock .hg/store/lock
603 $ waitlock .hg/store/lock
604
604
605 $ hg debuglocks
605 $ hg debuglocks
606 lock: user *, process * (*s) (glob)
606 lock: user *, process * (*s) (glob)
607 wlock: free
607 wlock: free
608 [1]
608 [1]
609
609
610 $ hg debuglocks -L
610 $ hg debuglocks -L
611
611
612 $ hg debuglocks
612 $ hg debuglocks
613 lock: free
613 lock: free
614 wlock: free
614 wlock: free
615
615
616 $ touch .hg/unlock
616 $ touch .hg/unlock
617 $ wait
617 $ wait
618
618
619 * Test forcing the wlock
619 * Test forcing the wlock
620
620
621 $ dolock -S &
621 $ dolock -S &
622 $ waitlock .hg/wlock
622 $ waitlock .hg/wlock
623
623
624 $ hg debuglocks
624 $ hg debuglocks
625 lock: free
625 lock: free
626 wlock: user *, process * (*s) (glob)
626 wlock: user *, process * (*s) (glob)
627 [1]
627 [1]
628
628
629 $ hg debuglocks -W
629 $ hg debuglocks -W
630
630
631 $ hg debuglocks
631 $ hg debuglocks
632 lock: free
632 lock: free
633 wlock: free
633 wlock: free
634
634
635 $ touch .hg/unlock
635 $ touch .hg/unlock
636 $ wait
636 $ wait
637
637
638 Test WdirUnsupported exception
638 Test WdirUnsupported exception
639
639
640 $ hg debugdata -c ffffffffffffffffffffffffffffffffffffffff
640 $ hg debugdata -c ffffffffffffffffffffffffffffffffffffffff
641 abort: working directory revision cannot be specified
641 abort: working directory revision cannot be specified
642 [255]
642 [255]
643
643
644 Test cache warming command
644 Test cache warming command
645
645
646 $ rm -rf .hg/cache/
646 $ rm -rf .hg/cache/
647 $ hg debugupdatecaches --debug
647 $ hg debugupdatecaches --debug
648 updating the branch cache
648 updating the branch cache
649 $ ls -r .hg/cache/*
649 $ ls -r .hg/cache/*
650 .hg/cache/tags2-served
650 .hg/cache/tags2-served
651 .hg/cache/tags2
651 .hg/cache/tags2
652 .hg/cache/rbc-revs-v1
652 .hg/cache/rbc-revs-v1
653 .hg/cache/rbc-names-v1
653 .hg/cache/rbc-names-v1
654 .hg/cache/hgtagsfnodes1
654 .hg/cache/hgtagsfnodes1
655 .hg/cache/branch2-visible-hidden
655 .hg/cache/branch2-visible-hidden
656 .hg/cache/branch2-visible
656 .hg/cache/branch2-visible
657 .hg/cache/branch2-served.hidden
657 .hg/cache/branch2-served.hidden
658 .hg/cache/branch2-served
658 .hg/cache/branch2-served
659 .hg/cache/branch2-immutable
659 .hg/cache/branch2-immutable
660 .hg/cache/branch2-base
660 .hg/cache/branch2-base
661
661
662 Test debug::unbundle
663
664 $ hg bundle --exact --rev tip foo.hg
665 1 changesets found
666 $ hg debug::unbundle foo.hg
667 adding changesets
668 adding manifests
669 adding file changes
670 added 0 changesets with 0 changes to 1 files (no-pure !)
671 9 local changesets published (no-pure !)
672 3 local changesets published (pure !)
673 (run 'hg update' to get a working copy)
674
662 Test debugcolor
675 Test debugcolor
663
676
664 #if no-windows
677 #if no-windows
665 $ hg debugcolor --style --color always | grep -E 'mode|style|log\.'
678 $ hg debugcolor --style --color always | grep -E 'mode|style|log\.'
666 color mode: 'ansi'
679 color mode: 'ansi'
667 available style:
680 available style:
668 \x1b[0;33mlog.changeset\x1b[0m: \x1b[0;33myellow\x1b[0m (esc)
681 \x1b[0;33mlog.changeset\x1b[0m: \x1b[0;33myellow\x1b[0m (esc)
669 #endif
682 #endif
670
683
671 $ hg debugcolor --style --color never
684 $ hg debugcolor --style --color never
672 color mode: None
685 color mode: None
673 available style:
686 available style:
674
687
675 $ cd ..
688 $ cd ..
676
689
677 Test internal debugstacktrace command
690 Test internal debugstacktrace command
678
691
679 $ cat > debugstacktrace.py << EOF
692 $ cat > debugstacktrace.py << EOF
680 > from mercurial import (
693 > from mercurial import (
681 > util,
694 > util,
682 > )
695 > )
683 > from mercurial.utils import (
696 > from mercurial.utils import (
684 > procutil,
697 > procutil,
685 > )
698 > )
686 > def f():
699 > def f():
687 > util.debugstacktrace(f=procutil.stdout)
700 > util.debugstacktrace(f=procutil.stdout)
688 > g()
701 > g()
689 > def g():
702 > def g():
690 > util.dst(b'hello from g\\n', skip=1)
703 > util.dst(b'hello from g\\n', skip=1)
691 > h()
704 > h()
692 > def h():
705 > def h():
693 > util.dst(b'hi ...\\nfrom h hidden in g', 1, depth=2)
706 > util.dst(b'hi ...\\nfrom h hidden in g', 1, depth=2)
694 > f()
707 > f()
695 > EOF
708 > EOF
696 $ "$PYTHON" debugstacktrace.py
709 $ "$PYTHON" debugstacktrace.py
697 stacktrace at:
710 stacktrace at:
698 *debugstacktrace.py:15 in * (glob)
711 *debugstacktrace.py:15 in * (glob)
699 *debugstacktrace.py:8 in f (glob)
712 *debugstacktrace.py:8 in f (glob)
700 hello from g at:
713 hello from g at:
701 *debugstacktrace.py:15 in * (glob)
714 *debugstacktrace.py:15 in * (glob)
702 *debugstacktrace.py:9 in f (glob)
715 *debugstacktrace.py:9 in f (glob)
703 hi ...
716 hi ...
704 from h hidden in g at:
717 from h hidden in g at:
705 *debugstacktrace.py:9 in f (glob)
718 *debugstacktrace.py:9 in f (glob)
706 *debugstacktrace.py:12 in g (glob)
719 *debugstacktrace.py:12 in g (glob)
707
720
708 Test debugcapabilities command:
721 Test debugcapabilities command:
709
722
710 $ hg debugcapabilities ./debugrevlog/
723 $ hg debugcapabilities ./debugrevlog/
711 Main capabilities:
724 Main capabilities:
712 branchmap
725 branchmap
713 $USUAL_BUNDLE2_CAPS$
726 $USUAL_BUNDLE2_CAPS$
714 getbundle
727 getbundle
715 known
728 known
716 lookup
729 lookup
717 pushkey
730 pushkey
718 unbundle
731 unbundle
719 Bundle2 capabilities:
732 Bundle2 capabilities:
720 HG20
733 HG20
721 bookmarks
734 bookmarks
722 changegroup
735 changegroup
723 01
736 01
724 02
737 02
725 03
738 03
726 checkheads
739 checkheads
727 related
740 related
728 digests
741 digests
729 md5
742 md5
730 sha1
743 sha1
731 sha512
744 sha512
732 error
745 error
733 abort
746 abort
734 unsupportedcontent
747 unsupportedcontent
735 pushraced
748 pushraced
736 pushkey
749 pushkey
737 hgtagsfnodes
750 hgtagsfnodes
738 listkeys
751 listkeys
739 phases
752 phases
740 heads
753 heads
741 pushkey
754 pushkey
742 remote-changegroup
755 remote-changegroup
743 http
756 http
744 https
757 https
745 stream
758 stream
746 v2
759 v2
747
760
748 Test debugpeer
761 Test debugpeer
749
762
750 $ hg debugpeer ssh://user@dummy/debugrevlog
763 $ hg debugpeer ssh://user@dummy/debugrevlog
751 url: ssh://user@dummy/debugrevlog
764 url: ssh://user@dummy/debugrevlog
752 local: no
765 local: no
753 pushable: yes
766 pushable: yes
754
767
755 #if rust
768 #if rust
756
769
757 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
770 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
758 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
771 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
759 devel-peer-request: hello+between
772 devel-peer-request: hello+between
760 devel-peer-request: pairs: 81 bytes
773 devel-peer-request: pairs: 81 bytes
761 sending hello command
774 sending hello command
762 sending between command
775 sending between command
763 remote: 473
776 remote: 473
764 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlog-compression-zstd,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
777 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlog-compression-zstd,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
765 remote: 1
778 remote: 1
766 devel-peer-request: protocaps
779 devel-peer-request: protocaps
767 devel-peer-request: caps: * bytes (glob)
780 devel-peer-request: caps: * bytes (glob)
768 sending protocaps command
781 sending protocaps command
769 url: ssh://user@dummy/debugrevlog
782 url: ssh://user@dummy/debugrevlog
770 local: no
783 local: no
771 pushable: yes
784 pushable: yes
772
785
773 #endif
786 #endif
774
787
775 #if no-rust zstd
788 #if no-rust zstd
776
789
777 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
790 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
778 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
791 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
779 devel-peer-request: hello+between
792 devel-peer-request: hello+between
780 devel-peer-request: pairs: 81 bytes
793 devel-peer-request: pairs: 81 bytes
781 sending hello command
794 sending hello command
782 sending between command
795 sending between command
783 remote: 473
796 remote: 473
784 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlog-compression-zstd,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
797 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlog-compression-zstd,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
785 remote: 1
798 remote: 1
786 devel-peer-request: protocaps
799 devel-peer-request: protocaps
787 devel-peer-request: caps: * bytes (glob)
800 devel-peer-request: caps: * bytes (glob)
788 sending protocaps command
801 sending protocaps command
789 url: ssh://user@dummy/debugrevlog
802 url: ssh://user@dummy/debugrevlog
790 local: no
803 local: no
791 pushable: yes
804 pushable: yes
792
805
793 #endif
806 #endif
794
807
795 #if no-rust no-zstd
808 #if no-rust no-zstd
796
809
797 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
810 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
798 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
811 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
799 devel-peer-request: hello+between
812 devel-peer-request: hello+between
800 devel-peer-request: pairs: 81 bytes
813 devel-peer-request: pairs: 81 bytes
801 sending hello command
814 sending hello command
802 sending between command
815 sending between command
803 remote: 449
816 remote: 449
804 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
817 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
805 remote: 1
818 remote: 1
806 devel-peer-request: protocaps
819 devel-peer-request: protocaps
807 devel-peer-request: caps: * bytes (glob)
820 devel-peer-request: caps: * bytes (glob)
808 sending protocaps command
821 sending protocaps command
809 url: ssh://user@dummy/debugrevlog
822 url: ssh://user@dummy/debugrevlog
810 local: no
823 local: no
811 pushable: yes
824 pushable: yes
812
825
813 #endif
826 #endif
814
827
815 Test debugshell
828 Test debugshell
816
829
817 $ hg debugshell -c 'ui.write(b"%s\n" % ui.username())'
830 $ hg debugshell -c 'ui.write(b"%s\n" % ui.username())'
818 test
831 test
@@ -1,4106 +1,4108 b''
1 Short help:
1 Short help:
2
2
3 $ hg
3 $ hg
4 Mercurial Distributed SCM
4 Mercurial Distributed SCM
5
5
6 basic commands:
6 basic commands:
7
7
8 add add the specified files on the next commit
8 add add the specified files on the next commit
9 annotate show changeset information by line for each file
9 annotate show changeset information by line for each file
10 clone make a copy of an existing repository
10 clone make a copy of an existing repository
11 commit commit the specified files or all outstanding changes
11 commit commit the specified files or all outstanding changes
12 diff diff repository (or selected files)
12 diff diff repository (or selected files)
13 export dump the header and diffs for one or more changesets
13 export dump the header and diffs for one or more changesets
14 forget forget the specified files on the next commit
14 forget forget the specified files on the next commit
15 init create a new repository in the given directory
15 init create a new repository in the given directory
16 log show revision history of entire repository or files
16 log show revision history of entire repository or files
17 merge merge another revision into working directory
17 merge merge another revision into working directory
18 pull pull changes from the specified source
18 pull pull changes from the specified source
19 push push changes to the specified destination
19 push push changes to the specified destination
20 remove remove the specified files on the next commit
20 remove remove the specified files on the next commit
21 serve start stand-alone webserver
21 serve start stand-alone webserver
22 status show changed files in the working directory
22 status show changed files in the working directory
23 summary summarize working directory state
23 summary summarize working directory state
24 update update working directory (or switch revisions)
24 update update working directory (or switch revisions)
25
25
26 (use 'hg help' for the full list of commands or 'hg -v' for details)
26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27
27
28 $ hg -q
28 $ hg -q
29 add add the specified files on the next commit
29 add add the specified files on the next commit
30 annotate show changeset information by line for each file
30 annotate show changeset information by line for each file
31 clone make a copy of an existing repository
31 clone make a copy of an existing repository
32 commit commit the specified files or all outstanding changes
32 commit commit the specified files or all outstanding changes
33 diff diff repository (or selected files)
33 diff diff repository (or selected files)
34 export dump the header and diffs for one or more changesets
34 export dump the header and diffs for one or more changesets
35 forget forget the specified files on the next commit
35 forget forget the specified files on the next commit
36 init create a new repository in the given directory
36 init create a new repository in the given directory
37 log show revision history of entire repository or files
37 log show revision history of entire repository or files
38 merge merge another revision into working directory
38 merge merge another revision into working directory
39 pull pull changes from the specified source
39 pull pull changes from the specified source
40 push push changes to the specified destination
40 push push changes to the specified destination
41 remove remove the specified files on the next commit
41 remove remove the specified files on the next commit
42 serve start stand-alone webserver
42 serve start stand-alone webserver
43 status show changed files in the working directory
43 status show changed files in the working directory
44 summary summarize working directory state
44 summary summarize working directory state
45 update update working directory (or switch revisions)
45 update update working directory (or switch revisions)
46
46
47 Extra extensions will be printed in help output in a non-reliable order since
47 Extra extensions will be printed in help output in a non-reliable order since
48 the extension is unknown.
48 the extension is unknown.
49 #if no-extraextensions
49 #if no-extraextensions
50
50
51 $ hg help
51 $ hg help
52 Mercurial Distributed SCM
52 Mercurial Distributed SCM
53
53
54 list of commands:
54 list of commands:
55
55
56 Repository creation:
56 Repository creation:
57
57
58 clone make a copy of an existing repository
58 clone make a copy of an existing repository
59 init create a new repository in the given directory
59 init create a new repository in the given directory
60
60
61 Remote repository management:
61 Remote repository management:
62
62
63 incoming show new changesets found in source
63 incoming show new changesets found in source
64 outgoing show changesets not found in the destination
64 outgoing show changesets not found in the destination
65 paths show aliases for remote repositories
65 paths show aliases for remote repositories
66 pull pull changes from the specified source
66 pull pull changes from the specified source
67 push push changes to the specified destination
67 push push changes to the specified destination
68 serve start stand-alone webserver
68 serve start stand-alone webserver
69
69
70 Change creation:
70 Change creation:
71
71
72 commit commit the specified files or all outstanding changes
72 commit commit the specified files or all outstanding changes
73
73
74 Change manipulation:
74 Change manipulation:
75
75
76 backout reverse effect of earlier changeset
76 backout reverse effect of earlier changeset
77 graft copy changes from other branches onto the current branch
77 graft copy changes from other branches onto the current branch
78 merge merge another revision into working directory
78 merge merge another revision into working directory
79
79
80 Change organization:
80 Change organization:
81
81
82 bookmarks create a new bookmark or list existing bookmarks
82 bookmarks create a new bookmark or list existing bookmarks
83 branch set or show the current branch name
83 branch set or show the current branch name
84 branches list repository named branches
84 branches list repository named branches
85 phase set or show the current phase name
85 phase set or show the current phase name
86 tag add one or more tags for the current or given revision
86 tag add one or more tags for the current or given revision
87 tags list repository tags
87 tags list repository tags
88
88
89 File content management:
89 File content management:
90
90
91 annotate show changeset information by line for each file
91 annotate show changeset information by line for each file
92 cat output the current or given revision of files
92 cat output the current or given revision of files
93 copy mark files as copied for the next commit
93 copy mark files as copied for the next commit
94 diff diff repository (or selected files)
94 diff diff repository (or selected files)
95 grep search for a pattern in specified files
95 grep search for a pattern in specified files
96
96
97 Change navigation:
97 Change navigation:
98
98
99 bisect subdivision search of changesets
99 bisect subdivision search of changesets
100 heads show branch heads
100 heads show branch heads
101 identify identify the working directory or specified revision
101 identify identify the working directory or specified revision
102 log show revision history of entire repository or files
102 log show revision history of entire repository or files
103
103
104 Working directory management:
104 Working directory management:
105
105
106 add add the specified files on the next commit
106 add add the specified files on the next commit
107 addremove add all new files, delete all missing files
107 addremove add all new files, delete all missing files
108 files list tracked files
108 files list tracked files
109 forget forget the specified files on the next commit
109 forget forget the specified files on the next commit
110 purge removes files not tracked by Mercurial
110 purge removes files not tracked by Mercurial
111 remove remove the specified files on the next commit
111 remove remove the specified files on the next commit
112 rename rename files; equivalent of copy + remove
112 rename rename files; equivalent of copy + remove
113 resolve redo merges or set/view the merge status of files
113 resolve redo merges or set/view the merge status of files
114 revert restore files to their checkout state
114 revert restore files to their checkout state
115 root print the root (top) of the current working directory
115 root print the root (top) of the current working directory
116 shelve save and set aside changes from the working directory
116 shelve save and set aside changes from the working directory
117 status show changed files in the working directory
117 status show changed files in the working directory
118 summary summarize working directory state
118 summary summarize working directory state
119 unshelve restore a shelved change to the working directory
119 unshelve restore a shelved change to the working directory
120 update update working directory (or switch revisions)
120 update update working directory (or switch revisions)
121
121
122 Change import/export:
122 Change import/export:
123
123
124 archive create an unversioned archive of a repository revision
124 archive create an unversioned archive of a repository revision
125 bundle create a bundle file
125 bundle create a bundle file
126 export dump the header and diffs for one or more changesets
126 export dump the header and diffs for one or more changesets
127 import import an ordered set of patches
127 import import an ordered set of patches
128 unbundle apply one or more bundle files
128 unbundle apply one or more bundle files
129
129
130 Repository maintenance:
130 Repository maintenance:
131
131
132 admin::verify
132 admin::verify
133 verify the integrity of the repository
133 verify the integrity of the repository
134 manifest output the current or given revision of the project manifest
134 manifest output the current or given revision of the project manifest
135 recover roll back an interrupted transaction
135 recover roll back an interrupted transaction
136 verify verify the integrity of the repository
136 verify verify the integrity of the repository
137
137
138 Help:
138 Help:
139
139
140 config show combined config settings from all hgrc files
140 config show combined config settings from all hgrc files
141 help show help for a given topic or a help overview
141 help show help for a given topic or a help overview
142 version output version and copyright information
142 version output version and copyright information
143
143
144 additional help topics:
144 additional help topics:
145
145
146 Mercurial identifiers:
146 Mercurial identifiers:
147
147
148 filesets Specifying File Sets
148 filesets Specifying File Sets
149 hgignore Syntax for Mercurial Ignore Files
149 hgignore Syntax for Mercurial Ignore Files
150 patterns File Name Patterns
150 patterns File Name Patterns
151 revisions Specifying Revisions
151 revisions Specifying Revisions
152 urls URL Paths
152 urls URL Paths
153
153
154 Mercurial output:
154 Mercurial output:
155
155
156 color Colorizing Outputs
156 color Colorizing Outputs
157 dates Date Formats
157 dates Date Formats
158 diffs Diff Formats
158 diffs Diff Formats
159 templating Template Usage
159 templating Template Usage
160
160
161 Mercurial configuration:
161 Mercurial configuration:
162
162
163 config Configuration Files
163 config Configuration Files
164 environment Environment Variables
164 environment Environment Variables
165 extensions Using Additional Features
165 extensions Using Additional Features
166 flags Command-line flags
166 flags Command-line flags
167 hgweb Configuring hgweb
167 hgweb Configuring hgweb
168 merge-tools Merge Tools
168 merge-tools Merge Tools
169 pager Pager Support
169 pager Pager Support
170 rust Rust in Mercurial
170 rust Rust in Mercurial
171
171
172 Concepts:
172 Concepts:
173
173
174 bundlespec Bundle File Formats
174 bundlespec Bundle File Formats
175 evolution Safely rewriting history (EXPERIMENTAL)
175 evolution Safely rewriting history (EXPERIMENTAL)
176 glossary Glossary
176 glossary Glossary
177 phases Working with Phases
177 phases Working with Phases
178 subrepos Subrepositories
178 subrepos Subrepositories
179
179
180 Miscellaneous:
180 Miscellaneous:
181
181
182 deprecated Deprecated Features
182 deprecated Deprecated Features
183 internals Technical implementation topics
183 internals Technical implementation topics
184 scripting Using Mercurial from scripts and automation
184 scripting Using Mercurial from scripts and automation
185
185
186 (use 'hg help -v' to show built-in aliases and global options)
186 (use 'hg help -v' to show built-in aliases and global options)
187
187
188 $ hg -q help
188 $ hg -q help
189 Repository creation:
189 Repository creation:
190
190
191 clone make a copy of an existing repository
191 clone make a copy of an existing repository
192 init create a new repository in the given directory
192 init create a new repository in the given directory
193
193
194 Remote repository management:
194 Remote repository management:
195
195
196 incoming show new changesets found in source
196 incoming show new changesets found in source
197 outgoing show changesets not found in the destination
197 outgoing show changesets not found in the destination
198 paths show aliases for remote repositories
198 paths show aliases for remote repositories
199 pull pull changes from the specified source
199 pull pull changes from the specified source
200 push push changes to the specified destination
200 push push changes to the specified destination
201 serve start stand-alone webserver
201 serve start stand-alone webserver
202
202
203 Change creation:
203 Change creation:
204
204
205 commit commit the specified files or all outstanding changes
205 commit commit the specified files or all outstanding changes
206
206
207 Change manipulation:
207 Change manipulation:
208
208
209 backout reverse effect of earlier changeset
209 backout reverse effect of earlier changeset
210 graft copy changes from other branches onto the current branch
210 graft copy changes from other branches onto the current branch
211 merge merge another revision into working directory
211 merge merge another revision into working directory
212
212
213 Change organization:
213 Change organization:
214
214
215 bookmarks create a new bookmark or list existing bookmarks
215 bookmarks create a new bookmark or list existing bookmarks
216 branch set or show the current branch name
216 branch set or show the current branch name
217 branches list repository named branches
217 branches list repository named branches
218 phase set or show the current phase name
218 phase set or show the current phase name
219 tag add one or more tags for the current or given revision
219 tag add one or more tags for the current or given revision
220 tags list repository tags
220 tags list repository tags
221
221
222 File content management:
222 File content management:
223
223
224 annotate show changeset information by line for each file
224 annotate show changeset information by line for each file
225 cat output the current or given revision of files
225 cat output the current or given revision of files
226 copy mark files as copied for the next commit
226 copy mark files as copied for the next commit
227 diff diff repository (or selected files)
227 diff diff repository (or selected files)
228 grep search for a pattern in specified files
228 grep search for a pattern in specified files
229
229
230 Change navigation:
230 Change navigation:
231
231
232 bisect subdivision search of changesets
232 bisect subdivision search of changesets
233 heads show branch heads
233 heads show branch heads
234 identify identify the working directory or specified revision
234 identify identify the working directory or specified revision
235 log show revision history of entire repository or files
235 log show revision history of entire repository or files
236
236
237 Working directory management:
237 Working directory management:
238
238
239 add add the specified files on the next commit
239 add add the specified files on the next commit
240 addremove add all new files, delete all missing files
240 addremove add all new files, delete all missing files
241 files list tracked files
241 files list tracked files
242 forget forget the specified files on the next commit
242 forget forget the specified files on the next commit
243 purge removes files not tracked by Mercurial
243 purge removes files not tracked by Mercurial
244 remove remove the specified files on the next commit
244 remove remove the specified files on the next commit
245 rename rename files; equivalent of copy + remove
245 rename rename files; equivalent of copy + remove
246 resolve redo merges or set/view the merge status of files
246 resolve redo merges or set/view the merge status of files
247 revert restore files to their checkout state
247 revert restore files to their checkout state
248 root print the root (top) of the current working directory
248 root print the root (top) of the current working directory
249 shelve save and set aside changes from the working directory
249 shelve save and set aside changes from the working directory
250 status show changed files in the working directory
250 status show changed files in the working directory
251 summary summarize working directory state
251 summary summarize working directory state
252 unshelve restore a shelved change to the working directory
252 unshelve restore a shelved change to the working directory
253 update update working directory (or switch revisions)
253 update update working directory (or switch revisions)
254
254
255 Change import/export:
255 Change import/export:
256
256
257 archive create an unversioned archive of a repository revision
257 archive create an unversioned archive of a repository revision
258 bundle create a bundle file
258 bundle create a bundle file
259 export dump the header and diffs for one or more changesets
259 export dump the header and diffs for one or more changesets
260 import import an ordered set of patches
260 import import an ordered set of patches
261 unbundle apply one or more bundle files
261 unbundle apply one or more bundle files
262
262
263 Repository maintenance:
263 Repository maintenance:
264
264
265 admin::verify
265 admin::verify
266 verify the integrity of the repository
266 verify the integrity of the repository
267 manifest output the current or given revision of the project manifest
267 manifest output the current or given revision of the project manifest
268 recover roll back an interrupted transaction
268 recover roll back an interrupted transaction
269 verify verify the integrity of the repository
269 verify verify the integrity of the repository
270
270
271 Help:
271 Help:
272
272
273 config show combined config settings from all hgrc files
273 config show combined config settings from all hgrc files
274 help show help for a given topic or a help overview
274 help show help for a given topic or a help overview
275 version output version and copyright information
275 version output version and copyright information
276
276
277 additional help topics:
277 additional help topics:
278
278
279 Mercurial identifiers:
279 Mercurial identifiers:
280
280
281 filesets Specifying File Sets
281 filesets Specifying File Sets
282 hgignore Syntax for Mercurial Ignore Files
282 hgignore Syntax for Mercurial Ignore Files
283 patterns File Name Patterns
283 patterns File Name Patterns
284 revisions Specifying Revisions
284 revisions Specifying Revisions
285 urls URL Paths
285 urls URL Paths
286
286
287 Mercurial output:
287 Mercurial output:
288
288
289 color Colorizing Outputs
289 color Colorizing Outputs
290 dates Date Formats
290 dates Date Formats
291 diffs Diff Formats
291 diffs Diff Formats
292 templating Template Usage
292 templating Template Usage
293
293
294 Mercurial configuration:
294 Mercurial configuration:
295
295
296 config Configuration Files
296 config Configuration Files
297 environment Environment Variables
297 environment Environment Variables
298 extensions Using Additional Features
298 extensions Using Additional Features
299 flags Command-line flags
299 flags Command-line flags
300 hgweb Configuring hgweb
300 hgweb Configuring hgweb
301 merge-tools Merge Tools
301 merge-tools Merge Tools
302 pager Pager Support
302 pager Pager Support
303 rust Rust in Mercurial
303 rust Rust in Mercurial
304
304
305 Concepts:
305 Concepts:
306
306
307 bundlespec Bundle File Formats
307 bundlespec Bundle File Formats
308 evolution Safely rewriting history (EXPERIMENTAL)
308 evolution Safely rewriting history (EXPERIMENTAL)
309 glossary Glossary
309 glossary Glossary
310 phases Working with Phases
310 phases Working with Phases
311 subrepos Subrepositories
311 subrepos Subrepositories
312
312
313 Miscellaneous:
313 Miscellaneous:
314
314
315 deprecated Deprecated Features
315 deprecated Deprecated Features
316 internals Technical implementation topics
316 internals Technical implementation topics
317 scripting Using Mercurial from scripts and automation
317 scripting Using Mercurial from scripts and automation
318
318
319 Test extension help:
319 Test extension help:
320 $ hg help extensions --config extensions.rebase= --config extensions.children=
320 $ hg help extensions --config extensions.rebase= --config extensions.children=
321 Using Additional Features
321 Using Additional Features
322 """""""""""""""""""""""""
322 """""""""""""""""""""""""
323
323
324 Mercurial has the ability to add new features through the use of
324 Mercurial has the ability to add new features through the use of
325 extensions. Extensions may add new commands, add options to existing
325 extensions. Extensions may add new commands, add options to existing
326 commands, change the default behavior of commands, or implement hooks.
326 commands, change the default behavior of commands, or implement hooks.
327
327
328 To enable the "foo" extension, either shipped with Mercurial or in the
328 To enable the "foo" extension, either shipped with Mercurial or in the
329 Python search path, create an entry for it in your configuration file,
329 Python search path, create an entry for it in your configuration file,
330 like this:
330 like this:
331
331
332 [extensions]
332 [extensions]
333 foo =
333 foo =
334
334
335 You may also specify the full path to an extension:
335 You may also specify the full path to an extension:
336
336
337 [extensions]
337 [extensions]
338 myfeature = ~/.hgext/myfeature.py
338 myfeature = ~/.hgext/myfeature.py
339
339
340 See 'hg help config' for more information on configuration files.
340 See 'hg help config' for more information on configuration files.
341
341
342 Extensions are not loaded by default for a variety of reasons: they can
342 Extensions are not loaded by default for a variety of reasons: they can
343 increase startup overhead; they may be meant for advanced usage only; they
343 increase startup overhead; they may be meant for advanced usage only; they
344 may provide potentially dangerous abilities (such as letting you destroy
344 may provide potentially dangerous abilities (such as letting you destroy
345 or modify history); they might not be ready for prime time; or they may
345 or modify history); they might not be ready for prime time; or they may
346 alter some usual behaviors of stock Mercurial. It is thus up to the user
346 alter some usual behaviors of stock Mercurial. It is thus up to the user
347 to activate extensions as needed.
347 to activate extensions as needed.
348
348
349 To explicitly disable an extension enabled in a configuration file of
349 To explicitly disable an extension enabled in a configuration file of
350 broader scope, prepend its path with !:
350 broader scope, prepend its path with !:
351
351
352 [extensions]
352 [extensions]
353 # disabling extension bar residing in /path/to/extension/bar.py
353 # disabling extension bar residing in /path/to/extension/bar.py
354 bar = !/path/to/extension/bar.py
354 bar = !/path/to/extension/bar.py
355 # ditto, but no path was supplied for extension baz
355 # ditto, but no path was supplied for extension baz
356 baz = !
356 baz = !
357
357
358 enabled extensions:
358 enabled extensions:
359
359
360 children command to display child changesets (DEPRECATED)
360 children command to display child changesets (DEPRECATED)
361 rebase command to move sets of revisions to a different ancestor
361 rebase command to move sets of revisions to a different ancestor
362
362
363 disabled extensions:
363 disabled extensions:
364
364
365 acl hooks for controlling repository access
365 acl hooks for controlling repository access
366 blackbox log repository events to a blackbox for debugging
366 blackbox log repository events to a blackbox for debugging
367 bugzilla hooks for integrating with the Bugzilla bug tracker
367 bugzilla hooks for integrating with the Bugzilla bug tracker
368 censor erase file content at a given revision
368 censor erase file content at a given revision
369 churn command to display statistics about repository history
369 churn command to display statistics about repository history
370 clonebundles advertise pre-generated bundles to seed clones
370 clonebundles advertise pre-generated bundles to seed clones
371 closehead close arbitrary heads without checking them out first
371 closehead close arbitrary heads without checking them out first
372 convert import revisions from foreign VCS repositories into
372 convert import revisions from foreign VCS repositories into
373 Mercurial
373 Mercurial
374 eol automatically manage newlines in repository files
374 eol automatically manage newlines in repository files
375 extdiff command to allow external programs to compare revisions
375 extdiff command to allow external programs to compare revisions
376 factotum http authentication with factotum
376 factotum http authentication with factotum
377 fastexport export repositories as git fast-import stream
377 fastexport export repositories as git fast-import stream
378 githelp try mapping git commands to Mercurial commands
378 githelp try mapping git commands to Mercurial commands
379 gpg commands to sign and verify changesets
379 gpg commands to sign and verify changesets
380 hgk browse the repository in a graphical way
380 hgk browse the repository in a graphical way
381 highlight syntax highlighting for hgweb (requires Pygments)
381 highlight syntax highlighting for hgweb (requires Pygments)
382 histedit interactive history editing
382 histedit interactive history editing
383 keyword expand keywords in tracked files
383 keyword expand keywords in tracked files
384 largefiles track large binary files
384 largefiles track large binary files
385 mq manage a stack of patches
385 mq manage a stack of patches
386 notify hooks for sending email push notifications
386 notify hooks for sending email push notifications
387 patchbomb command to send changesets as (a series of) patch emails
387 patchbomb command to send changesets as (a series of) patch emails
388 relink recreates hardlinks between repository clones
388 relink recreates hardlinks between repository clones
389 schemes extend schemes with shortcuts to repository swarms
389 schemes extend schemes with shortcuts to repository swarms
390 share share a common history between several working directories
390 share share a common history between several working directories
391 transplant command to transplant changesets from another branch
391 transplant command to transplant changesets from another branch
392 win32mbcs allow the use of MBCS paths with problematic encodings
392 win32mbcs allow the use of MBCS paths with problematic encodings
393 zeroconf discover and advertise repositories on the local network
393 zeroconf discover and advertise repositories on the local network
394
394
395 #endif
395 #endif
396
396
397 Verify that deprecated extensions are included if --verbose:
397 Verify that deprecated extensions are included if --verbose:
398
398
399 $ hg -v help extensions | grep children
399 $ hg -v help extensions | grep children
400 children command to display child changesets (DEPRECATED)
400 children command to display child changesets (DEPRECATED)
401
401
402 Verify that extension keywords appear in help templates
402 Verify that extension keywords appear in help templates
403
403
404 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
404 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
405
405
406 Test short command list with verbose option
406 Test short command list with verbose option
407
407
408 $ hg -v help shortlist
408 $ hg -v help shortlist
409 Mercurial Distributed SCM
409 Mercurial Distributed SCM
410
410
411 basic commands:
411 basic commands:
412
412
413 abort abort an unfinished operation (EXPERIMENTAL)
413 abort abort an unfinished operation (EXPERIMENTAL)
414 add add the specified files on the next commit
414 add add the specified files on the next commit
415 annotate, blame
415 annotate, blame
416 show changeset information by line for each file
416 show changeset information by line for each file
417 clone make a copy of an existing repository
417 clone make a copy of an existing repository
418 commit, ci commit the specified files or all outstanding changes
418 commit, ci commit the specified files or all outstanding changes
419 continue resumes an interrupted operation (EXPERIMENTAL)
419 continue resumes an interrupted operation (EXPERIMENTAL)
420 diff diff repository (or selected files)
420 diff diff repository (or selected files)
421 export dump the header and diffs for one or more changesets
421 export dump the header and diffs for one or more changesets
422 forget forget the specified files on the next commit
422 forget forget the specified files on the next commit
423 init create a new repository in the given directory
423 init create a new repository in the given directory
424 log, history show revision history of entire repository or files
424 log, history show revision history of entire repository or files
425 merge merge another revision into working directory
425 merge merge another revision into working directory
426 pull pull changes from the specified source
426 pull pull changes from the specified source
427 push push changes to the specified destination
427 push push changes to the specified destination
428 remove, rm remove the specified files on the next commit
428 remove, rm remove the specified files on the next commit
429 serve start stand-alone webserver
429 serve start stand-alone webserver
430 status, st show changed files in the working directory
430 status, st show changed files in the working directory
431 summary, sum summarize working directory state
431 summary, sum summarize working directory state
432 update, up, checkout, co
432 update, up, checkout, co
433 update working directory (or switch revisions)
433 update working directory (or switch revisions)
434
434
435 global options ([+] can be repeated):
435 global options ([+] can be repeated):
436
436
437 -R --repository REPO repository root directory or name of overlay bundle
437 -R --repository REPO repository root directory or name of overlay bundle
438 file
438 file
439 --cwd DIR change working directory
439 --cwd DIR change working directory
440 -y --noninteractive do not prompt, automatically pick the first choice for
440 -y --noninteractive do not prompt, automatically pick the first choice for
441 all prompts
441 all prompts
442 -q --quiet suppress output
442 -q --quiet suppress output
443 -v --verbose enable additional output
443 -v --verbose enable additional output
444 --color TYPE when to colorize (boolean, always, auto, never, or
444 --color TYPE when to colorize (boolean, always, auto, never, or
445 debug)
445 debug)
446 --config CONFIG [+] set/override config option (use 'section.name=value')
446 --config CONFIG [+] set/override config option (use 'section.name=value')
447 --debug enable debugging output
447 --debug enable debugging output
448 --debugger start debugger
448 --debugger start debugger
449 --encoding ENCODE set the charset encoding (default: ascii)
449 --encoding ENCODE set the charset encoding (default: ascii)
450 --encodingmode MODE set the charset encoding mode (default: strict)
450 --encodingmode MODE set the charset encoding mode (default: strict)
451 --traceback always print a traceback on exception
451 --traceback always print a traceback on exception
452 --time time how long the command takes
452 --time time how long the command takes
453 --profile print command execution profile
453 --profile print command execution profile
454 --version output version information and exit
454 --version output version information and exit
455 -h --help display help and exit
455 -h --help display help and exit
456 --hidden consider hidden changesets
456 --hidden consider hidden changesets
457 --pager TYPE when to paginate (boolean, always, auto, or never)
457 --pager TYPE when to paginate (boolean, always, auto, or never)
458 (default: auto)
458 (default: auto)
459
459
460 (use 'hg help' for the full list of commands)
460 (use 'hg help' for the full list of commands)
461
461
462 $ hg add -h
462 $ hg add -h
463 hg add [OPTION]... [FILE]...
463 hg add [OPTION]... [FILE]...
464
464
465 add the specified files on the next commit
465 add the specified files on the next commit
466
466
467 Schedule files to be version controlled and added to the repository.
467 Schedule files to be version controlled and added to the repository.
468
468
469 The files will be added to the repository at the next commit. To undo an
469 The files will be added to the repository at the next commit. To undo an
470 add before that, see 'hg forget'.
470 add before that, see 'hg forget'.
471
471
472 If no names are given, add all files to the repository (except files
472 If no names are given, add all files to the repository (except files
473 matching ".hgignore").
473 matching ".hgignore").
474
474
475 Returns 0 if all files are successfully added.
475 Returns 0 if all files are successfully added.
476
476
477 options ([+] can be repeated):
477 options ([+] can be repeated):
478
478
479 -I --include PATTERN [+] include names matching the given patterns
479 -I --include PATTERN [+] include names matching the given patterns
480 -X --exclude PATTERN [+] exclude names matching the given patterns
480 -X --exclude PATTERN [+] exclude names matching the given patterns
481 -S --subrepos recurse into subrepositories
481 -S --subrepos recurse into subrepositories
482 -n --dry-run do not perform actions, just print output
482 -n --dry-run do not perform actions, just print output
483
483
484 (some details hidden, use --verbose to show complete help)
484 (some details hidden, use --verbose to show complete help)
485
485
486 Verbose help for add
486 Verbose help for add
487
487
488 $ hg add -hv
488 $ hg add -hv
489 hg add [OPTION]... [FILE]...
489 hg add [OPTION]... [FILE]...
490
490
491 add the specified files on the next commit
491 add the specified files on the next commit
492
492
493 Schedule files to be version controlled and added to the repository.
493 Schedule files to be version controlled and added to the repository.
494
494
495 The files will be added to the repository at the next commit. To undo an
495 The files will be added to the repository at the next commit. To undo an
496 add before that, see 'hg forget'.
496 add before that, see 'hg forget'.
497
497
498 If no names are given, add all files to the repository (except files
498 If no names are given, add all files to the repository (except files
499 matching ".hgignore").
499 matching ".hgignore").
500
500
501 Examples:
501 Examples:
502
502
503 - New (unknown) files are added automatically by 'hg add':
503 - New (unknown) files are added automatically by 'hg add':
504
504
505 $ ls
505 $ ls
506 foo.c
506 foo.c
507 $ hg status
507 $ hg status
508 ? foo.c
508 ? foo.c
509 $ hg add
509 $ hg add
510 adding foo.c
510 adding foo.c
511 $ hg status
511 $ hg status
512 A foo.c
512 A foo.c
513
513
514 - Specific files to be added can be specified:
514 - Specific files to be added can be specified:
515
515
516 $ ls
516 $ ls
517 bar.c foo.c
517 bar.c foo.c
518 $ hg status
518 $ hg status
519 ? bar.c
519 ? bar.c
520 ? foo.c
520 ? foo.c
521 $ hg add bar.c
521 $ hg add bar.c
522 $ hg status
522 $ hg status
523 A bar.c
523 A bar.c
524 ? foo.c
524 ? foo.c
525
525
526 Returns 0 if all files are successfully added.
526 Returns 0 if all files are successfully added.
527
527
528 options ([+] can be repeated):
528 options ([+] can be repeated):
529
529
530 -I --include PATTERN [+] include names matching the given patterns
530 -I --include PATTERN [+] include names matching the given patterns
531 -X --exclude PATTERN [+] exclude names matching the given patterns
531 -X --exclude PATTERN [+] exclude names matching the given patterns
532 -S --subrepos recurse into subrepositories
532 -S --subrepos recurse into subrepositories
533 -n --dry-run do not perform actions, just print output
533 -n --dry-run do not perform actions, just print output
534
534
535 global options ([+] can be repeated):
535 global options ([+] can be repeated):
536
536
537 -R --repository REPO repository root directory or name of overlay bundle
537 -R --repository REPO repository root directory or name of overlay bundle
538 file
538 file
539 --cwd DIR change working directory
539 --cwd DIR change working directory
540 -y --noninteractive do not prompt, automatically pick the first choice for
540 -y --noninteractive do not prompt, automatically pick the first choice for
541 all prompts
541 all prompts
542 -q --quiet suppress output
542 -q --quiet suppress output
543 -v --verbose enable additional output
543 -v --verbose enable additional output
544 --color TYPE when to colorize (boolean, always, auto, never, or
544 --color TYPE when to colorize (boolean, always, auto, never, or
545 debug)
545 debug)
546 --config CONFIG [+] set/override config option (use 'section.name=value')
546 --config CONFIG [+] set/override config option (use 'section.name=value')
547 --debug enable debugging output
547 --debug enable debugging output
548 --debugger start debugger
548 --debugger start debugger
549 --encoding ENCODE set the charset encoding (default: ascii)
549 --encoding ENCODE set the charset encoding (default: ascii)
550 --encodingmode MODE set the charset encoding mode (default: strict)
550 --encodingmode MODE set the charset encoding mode (default: strict)
551 --traceback always print a traceback on exception
551 --traceback always print a traceback on exception
552 --time time how long the command takes
552 --time time how long the command takes
553 --profile print command execution profile
553 --profile print command execution profile
554 --version output version information and exit
554 --version output version information and exit
555 -h --help display help and exit
555 -h --help display help and exit
556 --hidden consider hidden changesets
556 --hidden consider hidden changesets
557 --pager TYPE when to paginate (boolean, always, auto, or never)
557 --pager TYPE when to paginate (boolean, always, auto, or never)
558 (default: auto)
558 (default: auto)
559
559
560 Test the textwidth config option
560 Test the textwidth config option
561
561
562 $ hg root -h --config ui.textwidth=50
562 $ hg root -h --config ui.textwidth=50
563 hg root
563 hg root
564
564
565 print the root (top) of the current working
565 print the root (top) of the current working
566 directory
566 directory
567
567
568 Print the root directory of the current
568 Print the root directory of the current
569 repository.
569 repository.
570
570
571 Returns 0 on success.
571 Returns 0 on success.
572
572
573 options:
573 options:
574
574
575 -T --template TEMPLATE display with template
575 -T --template TEMPLATE display with template
576
576
577 (some details hidden, use --verbose to show
577 (some details hidden, use --verbose to show
578 complete help)
578 complete help)
579
579
580 Test help option with version option
580 Test help option with version option
581
581
582 $ hg add -h --version
582 $ hg add -h --version
583 Mercurial Distributed SCM (version *) (glob)
583 Mercurial Distributed SCM (version *) (glob)
584 (see https://mercurial-scm.org for more information)
584 (see https://mercurial-scm.org for more information)
585
585
586 Copyright (C) 2005-* Olivia Mackall and others (glob)
586 Copyright (C) 2005-* Olivia Mackall and others (glob)
587 This is free software; see the source for copying conditions. There is NO
587 This is free software; see the source for copying conditions. There is NO
588 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
588 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
589
589
590 $ hg add --skjdfks
590 $ hg add --skjdfks
591 hg add: option --skjdfks not recognized
591 hg add: option --skjdfks not recognized
592 hg add [OPTION]... [FILE]...
592 hg add [OPTION]... [FILE]...
593
593
594 add the specified files on the next commit
594 add the specified files on the next commit
595
595
596 options ([+] can be repeated):
596 options ([+] can be repeated):
597
597
598 -I --include PATTERN [+] include names matching the given patterns
598 -I --include PATTERN [+] include names matching the given patterns
599 -X --exclude PATTERN [+] exclude names matching the given patterns
599 -X --exclude PATTERN [+] exclude names matching the given patterns
600 -S --subrepos recurse into subrepositories
600 -S --subrepos recurse into subrepositories
601 -n --dry-run do not perform actions, just print output
601 -n --dry-run do not perform actions, just print output
602
602
603 (use 'hg add -h' to show more help)
603 (use 'hg add -h' to show more help)
604 [10]
604 [10]
605
605
606 Test ambiguous command help
606 Test ambiguous command help
607
607
608 $ hg help ad
608 $ hg help ad
609 list of commands:
609 list of commands:
610
610
611 Working directory management:
611 Working directory management:
612
612
613 add add the specified files on the next commit
613 add add the specified files on the next commit
614 addremove add all new files, delete all missing files
614 addremove add all new files, delete all missing files
615
615
616 Repository maintenance:
616 Repository maintenance:
617
617
618 admin::verify
618 admin::verify
619 verify the integrity of the repository
619 verify the integrity of the repository
620
620
621 (use 'hg help -v ad' to show built-in aliases and global options)
621 (use 'hg help -v ad' to show built-in aliases and global options)
622
622
623 Test command without options
623 Test command without options
624
624
625 $ hg help verify
625 $ hg help verify
626 hg verify
626 hg verify
627
627
628 verify the integrity of the repository
628 verify the integrity of the repository
629
629
630 Verify the integrity of the current repository.
630 Verify the integrity of the current repository.
631
631
632 This will perform an extensive check of the repository's integrity,
632 This will perform an extensive check of the repository's integrity,
633 validating the hashes and checksums of each entry in the changelog,
633 validating the hashes and checksums of each entry in the changelog,
634 manifest, and tracked files, as well as the integrity of their crosslinks
634 manifest, and tracked files, as well as the integrity of their crosslinks
635 and indices.
635 and indices.
636
636
637 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
637 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
638 information about recovery from corruption of the repository.
638 information about recovery from corruption of the repository.
639
639
640 For an alternative UI with a lot more control over the verification
640 For an alternative UI with a lot more control over the verification
641 process and better error reporting, try 'hg help admin::verify'.
641 process and better error reporting, try 'hg help admin::verify'.
642
642
643 Returns 0 on success, 1 if errors are encountered.
643 Returns 0 on success, 1 if errors are encountered.
644
644
645 options:
645 options:
646
646
647 (some details hidden, use --verbose to show complete help)
647 (some details hidden, use --verbose to show complete help)
648
648
649 $ hg help diff
649 $ hg help diff
650 hg diff [OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...
650 hg diff [OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...
651
651
652 diff repository (or selected files)
652 diff repository (or selected files)
653
653
654 Show differences between revisions for the specified files.
654 Show differences between revisions for the specified files.
655
655
656 Differences between files are shown using the unified diff format.
656 Differences between files are shown using the unified diff format.
657
657
658 Note:
658 Note:
659 'hg diff' may generate unexpected results for merges, as it will
659 'hg diff' may generate unexpected results for merges, as it will
660 default to comparing against the working directory's first parent
660 default to comparing against the working directory's first parent
661 changeset if no revisions are specified. To diff against the conflict
661 changeset if no revisions are specified. To diff against the conflict
662 regions, you can use '--config diff.merge=yes'.
662 regions, you can use '--config diff.merge=yes'.
663
663
664 By default, the working directory files are compared to its first parent.
664 By default, the working directory files are compared to its first parent.
665 To see the differences from another revision, use --from. To see the
665 To see the differences from another revision, use --from. To see the
666 difference to another revision, use --to. For example, 'hg diff --from .^'
666 difference to another revision, use --to. For example, 'hg diff --from .^'
667 will show the differences from the working copy's grandparent to the
667 will show the differences from the working copy's grandparent to the
668 working copy, 'hg diff --to .' will show the diff from the working copy to
668 working copy, 'hg diff --to .' will show the diff from the working copy to
669 its parent (i.e. the reverse of the default), and 'hg diff --from 1.0 --to
669 its parent (i.e. the reverse of the default), and 'hg diff --from 1.0 --to
670 1.2' will show the diff between those two revisions.
670 1.2' will show the diff between those two revisions.
671
671
672 Alternatively you can specify -c/--change with a revision to see the
672 Alternatively you can specify -c/--change with a revision to see the
673 changes in that changeset relative to its first parent (i.e. 'hg diff -c
673 changes in that changeset relative to its first parent (i.e. 'hg diff -c
674 42' is equivalent to 'hg diff --from 42^ --to 42')
674 42' is equivalent to 'hg diff --from 42^ --to 42')
675
675
676 Without the -a/--text option, diff will avoid generating diffs of files it
676 Without the -a/--text option, diff will avoid generating diffs of files it
677 detects as binary. With -a, diff will generate a diff anyway, probably
677 detects as binary. With -a, diff will generate a diff anyway, probably
678 with undesirable results.
678 with undesirable results.
679
679
680 Use the -g/--git option to generate diffs in the git extended diff format.
680 Use the -g/--git option to generate diffs in the git extended diff format.
681 For more information, read 'hg help diffs'.
681 For more information, read 'hg help diffs'.
682
682
683 Returns 0 on success.
683 Returns 0 on success.
684
684
685 options ([+] can be repeated):
685 options ([+] can be repeated):
686
686
687 --from REV1 revision to diff from
687 --from REV1 revision to diff from
688 --to REV2 revision to diff to
688 --to REV2 revision to diff to
689 -c --change REV change made by revision
689 -c --change REV change made by revision
690 -a --text treat all files as text
690 -a --text treat all files as text
691 -g --git use git extended diff format
691 -g --git use git extended diff format
692 --binary generate binary diffs in git mode (default)
692 --binary generate binary diffs in git mode (default)
693 --nodates omit dates from diff headers
693 --nodates omit dates from diff headers
694 --noprefix omit a/ and b/ prefixes from filenames
694 --noprefix omit a/ and b/ prefixes from filenames
695 -p --show-function show which function each change is in
695 -p --show-function show which function each change is in
696 --reverse produce a diff that undoes the changes
696 --reverse produce a diff that undoes the changes
697 -w --ignore-all-space ignore white space when comparing lines
697 -w --ignore-all-space ignore white space when comparing lines
698 -b --ignore-space-change ignore changes in the amount of white space
698 -b --ignore-space-change ignore changes in the amount of white space
699 -B --ignore-blank-lines ignore changes whose lines are all blank
699 -B --ignore-blank-lines ignore changes whose lines are all blank
700 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
700 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
701 -U --unified NUM number of lines of context to show
701 -U --unified NUM number of lines of context to show
702 --stat output diffstat-style summary of changes
702 --stat output diffstat-style summary of changes
703 --root DIR produce diffs relative to subdirectory
703 --root DIR produce diffs relative to subdirectory
704 -I --include PATTERN [+] include names matching the given patterns
704 -I --include PATTERN [+] include names matching the given patterns
705 -X --exclude PATTERN [+] exclude names matching the given patterns
705 -X --exclude PATTERN [+] exclude names matching the given patterns
706 -S --subrepos recurse into subrepositories
706 -S --subrepos recurse into subrepositories
707
707
708 (some details hidden, use --verbose to show complete help)
708 (some details hidden, use --verbose to show complete help)
709
709
710 $ hg help status
710 $ hg help status
711 hg status [OPTION]... [FILE]...
711 hg status [OPTION]... [FILE]...
712
712
713 aliases: st
713 aliases: st
714
714
715 show changed files in the working directory
715 show changed files in the working directory
716
716
717 Show status of files in the repository. If names are given, only files
717 Show status of files in the repository. If names are given, only files
718 that match are shown. Files that are clean or ignored or the source of a
718 that match are shown. Files that are clean or ignored or the source of a
719 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
719 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
720 -C/--copies or -A/--all are given. Unless options described with "show
720 -C/--copies or -A/--all are given. Unless options described with "show
721 only ..." are given, the options -mardu are used.
721 only ..." are given, the options -mardu are used.
722
722
723 Option -q/--quiet hides untracked (unknown and ignored) files unless
723 Option -q/--quiet hides untracked (unknown and ignored) files unless
724 explicitly requested with -u/--unknown or -i/--ignored.
724 explicitly requested with -u/--unknown or -i/--ignored.
725
725
726 Note:
726 Note:
727 'hg status' may appear to disagree with diff if permissions have
727 'hg status' may appear to disagree with diff if permissions have
728 changed or a merge has occurred. The standard diff format does not
728 changed or a merge has occurred. The standard diff format does not
729 report permission changes and diff only reports changes relative to one
729 report permission changes and diff only reports changes relative to one
730 merge parent.
730 merge parent.
731
731
732 If one revision is given, it is used as the base revision. If two
732 If one revision is given, it is used as the base revision. If two
733 revisions are given, the differences between them are shown. The --change
733 revisions are given, the differences between them are shown. The --change
734 option can also be used as a shortcut to list the changed files of a
734 option can also be used as a shortcut to list the changed files of a
735 revision from its first parent.
735 revision from its first parent.
736
736
737 The codes used to show the status of files are:
737 The codes used to show the status of files are:
738
738
739 M = modified
739 M = modified
740 A = added
740 A = added
741 R = removed
741 R = removed
742 C = clean
742 C = clean
743 ! = missing (deleted by non-hg command, but still tracked)
743 ! = missing (deleted by non-hg command, but still tracked)
744 ? = not tracked
744 ? = not tracked
745 I = ignored
745 I = ignored
746 = origin of the previous file (with --copies)
746 = origin of the previous file (with --copies)
747
747
748 Returns 0 on success.
748 Returns 0 on success.
749
749
750 options ([+] can be repeated):
750 options ([+] can be repeated):
751
751
752 -A --all show status of all files
752 -A --all show status of all files
753 -m --modified show only modified files
753 -m --modified show only modified files
754 -a --added show only added files
754 -a --added show only added files
755 -r --removed show only removed files
755 -r --removed show only removed files
756 -d --deleted show only missing files
756 -d --deleted show only missing files
757 -c --clean show only files without changes
757 -c --clean show only files without changes
758 -u --unknown show only unknown (not tracked) files
758 -u --unknown show only unknown (not tracked) files
759 -i --ignored show only ignored files
759 -i --ignored show only ignored files
760 -n --no-status hide status prefix
760 -n --no-status hide status prefix
761 -C --copies show source of copied files
761 -C --copies show source of copied files
762 -0 --print0 end filenames with NUL, for use with xargs
762 -0 --print0 end filenames with NUL, for use with xargs
763 --rev REV [+] show difference from revision
763 --rev REV [+] show difference from revision
764 --change REV list the changed files of a revision
764 --change REV list the changed files of a revision
765 -I --include PATTERN [+] include names matching the given patterns
765 -I --include PATTERN [+] include names matching the given patterns
766 -X --exclude PATTERN [+] exclude names matching the given patterns
766 -X --exclude PATTERN [+] exclude names matching the given patterns
767 -S --subrepos recurse into subrepositories
767 -S --subrepos recurse into subrepositories
768 -T --template TEMPLATE display with template
768 -T --template TEMPLATE display with template
769
769
770 (some details hidden, use --verbose to show complete help)
770 (some details hidden, use --verbose to show complete help)
771
771
772 $ hg -q help status
772 $ hg -q help status
773 hg status [OPTION]... [FILE]...
773 hg status [OPTION]... [FILE]...
774
774
775 show changed files in the working directory
775 show changed files in the working directory
776
776
777 $ hg help foo
777 $ hg help foo
778 abort: no such help topic: foo
778 abort: no such help topic: foo
779 (try 'hg help --keyword foo')
779 (try 'hg help --keyword foo')
780 [10]
780 [10]
781
781
782 $ hg skjdfks
782 $ hg skjdfks
783 hg: unknown command 'skjdfks'
783 hg: unknown command 'skjdfks'
784 (use 'hg help' for a list of commands)
784 (use 'hg help' for a list of commands)
785 [10]
785 [10]
786
786
787 Typoed command gives suggestion
787 Typoed command gives suggestion
788 $ hg puls
788 $ hg puls
789 hg: unknown command 'puls'
789 hg: unknown command 'puls'
790 (did you mean one of pull, push?)
790 (did you mean one of pull, push?)
791 [10]
791 [10]
792
792
793 Not enabled extension gets suggested
793 Not enabled extension gets suggested
794
794
795 $ hg rebase
795 $ hg rebase
796 hg: unknown command 'rebase'
796 hg: unknown command 'rebase'
797 'rebase' is provided by the following extension:
797 'rebase' is provided by the following extension:
798
798
799 rebase command to move sets of revisions to a different ancestor
799 rebase command to move sets of revisions to a different ancestor
800
800
801 (use 'hg help extensions' for information on enabling extensions)
801 (use 'hg help extensions' for information on enabling extensions)
802 [10]
802 [10]
803
803
804 Disabled extension gets suggested
804 Disabled extension gets suggested
805 $ hg --config extensions.rebase=! rebase
805 $ hg --config extensions.rebase=! rebase
806 hg: unknown command 'rebase'
806 hg: unknown command 'rebase'
807 'rebase' is provided by the following extension:
807 'rebase' is provided by the following extension:
808
808
809 rebase command to move sets of revisions to a different ancestor
809 rebase command to move sets of revisions to a different ancestor
810
810
811 (use 'hg help extensions' for information on enabling extensions)
811 (use 'hg help extensions' for information on enabling extensions)
812 [10]
812 [10]
813
813
814 Checking that help adapts based on the config:
814 Checking that help adapts based on the config:
815
815
816 $ hg help diff --config ui.tweakdefaults=true | grep -E -e '^ *(-g|config)'
816 $ hg help diff --config ui.tweakdefaults=true | grep -E -e '^ *(-g|config)'
817 -g --[no-]git use git extended diff format (default: on from
817 -g --[no-]git use git extended diff format (default: on from
818 config)
818 config)
819
819
820 Make sure that we don't run afoul of the help system thinking that
820 Make sure that we don't run afoul of the help system thinking that
821 this is a section and erroring out weirdly.
821 this is a section and erroring out weirdly.
822
822
823 $ hg .log
823 $ hg .log
824 hg: unknown command '.log'
824 hg: unknown command '.log'
825 (did you mean log?)
825 (did you mean log?)
826 [10]
826 [10]
827
827
828 $ hg log.
828 $ hg log.
829 hg: unknown command 'log.'
829 hg: unknown command 'log.'
830 (did you mean log?)
830 (did you mean log?)
831 [10]
831 [10]
832 $ hg pu.lh
832 $ hg pu.lh
833 hg: unknown command 'pu.lh'
833 hg: unknown command 'pu.lh'
834 (did you mean one of pull, push?)
834 (did you mean one of pull, push?)
835 [10]
835 [10]
836
836
837 $ cat > helpext.py <<EOF
837 $ cat > helpext.py <<EOF
838 > import os
838 > import os
839 > from mercurial import commands, fancyopts, registrar
839 > from mercurial import commands, fancyopts, registrar
840 >
840 >
841 > def func(arg):
841 > def func(arg):
842 > return '%sfoo' % arg
842 > return '%sfoo' % arg
843 > class customopt(fancyopts.customopt):
843 > class customopt(fancyopts.customopt):
844 > def newstate(self, oldstate, newparam, abort):
844 > def newstate(self, oldstate, newparam, abort):
845 > return '%sbar' % oldstate
845 > return '%sbar' % oldstate
846 > cmdtable = {}
846 > cmdtable = {}
847 > command = registrar.command(cmdtable)
847 > command = registrar.command(cmdtable)
848 >
848 >
849 > @command(b'nohelp',
849 > @command(b'nohelp',
850 > [(b'', b'longdesc', 3, b'x'*67),
850 > [(b'', b'longdesc', 3, b'x'*67),
851 > (b'n', b'', None, b'normal desc'),
851 > (b'n', b'', None, b'normal desc'),
852 > (b'', b'newline', b'', b'line1\nline2'),
852 > (b'', b'newline', b'', b'line1\nline2'),
853 > (b'', b'default-off', False, b'enable X'),
853 > (b'', b'default-off', False, b'enable X'),
854 > (b'', b'default-on', True, b'enable Y'),
854 > (b'', b'default-on', True, b'enable Y'),
855 > (b'', b'callableopt', func, b'adds foo'),
855 > (b'', b'callableopt', func, b'adds foo'),
856 > (b'', b'customopt', customopt(''), b'adds bar'),
856 > (b'', b'customopt', customopt(''), b'adds bar'),
857 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
857 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
858 > b'hg nohelp',
858 > b'hg nohelp',
859 > norepo=True)
859 > norepo=True)
860 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
860 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
861 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
861 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
862 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
862 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
863 > def nohelp(ui, *args, **kwargs):
863 > def nohelp(ui, *args, **kwargs):
864 > pass
864 > pass
865 >
865 >
866 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
866 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
867 > def hashelp(ui, *args, **kwargs):
867 > def hashelp(ui, *args, **kwargs):
868 > """Extension command's help"""
868 > """Extension command's help"""
869 >
869 >
870 > def uisetup(ui):
870 > def uisetup(ui):
871 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
871 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
872 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
872 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
873 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
873 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
874 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
874 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
875 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
875 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
876 >
876 >
877 > EOF
877 > EOF
878 $ echo '[extensions]' >> $HGRCPATH
878 $ echo '[extensions]' >> $HGRCPATH
879 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
879 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
880
880
881 Test for aliases
881 Test for aliases
882
882
883 $ hg help | grep hgalias
883 $ hg help | grep hgalias
884 hgalias My doc
884 hgalias My doc
885
885
886 $ hg help hgalias
886 $ hg help hgalias
887 hg hgalias [--remote]
887 hg hgalias [--remote]
888
888
889 alias for: hg summary
889 alias for: hg summary
890
890
891 My doc
891 My doc
892
892
893 defined by: helpext
893 defined by: helpext
894
894
895 options:
895 options:
896
896
897 --remote check for push and pull
897 --remote check for push and pull
898
898
899 (some details hidden, use --verbose to show complete help)
899 (some details hidden, use --verbose to show complete help)
900 $ hg help hgaliasnodoc
900 $ hg help hgaliasnodoc
901 hg hgaliasnodoc [--remote]
901 hg hgaliasnodoc [--remote]
902
902
903 alias for: hg summary
903 alias for: hg summary
904
904
905 summarize working directory state
905 summarize working directory state
906
906
907 This generates a brief summary of the working directory state, including
907 This generates a brief summary of the working directory state, including
908 parents, branch, commit status, phase and available updates.
908 parents, branch, commit status, phase and available updates.
909
909
910 With the --remote option, this will check the default paths for incoming
910 With the --remote option, this will check the default paths for incoming
911 and outgoing changes. This can be time-consuming.
911 and outgoing changes. This can be time-consuming.
912
912
913 Returns 0 on success.
913 Returns 0 on success.
914
914
915 defined by: helpext
915 defined by: helpext
916
916
917 options:
917 options:
918
918
919 --remote check for push and pull
919 --remote check for push and pull
920
920
921 (some details hidden, use --verbose to show complete help)
921 (some details hidden, use --verbose to show complete help)
922
922
923 $ hg help shellalias
923 $ hg help shellalias
924 hg shellalias
924 hg shellalias
925
925
926 shell alias for: echo hi
926 shell alias for: echo hi
927
927
928 (no help text available)
928 (no help text available)
929
929
930 defined by: helpext
930 defined by: helpext
931
931
932 (some details hidden, use --verbose to show complete help)
932 (some details hidden, use --verbose to show complete help)
933
933
934 Test command with no help text
934 Test command with no help text
935
935
936 $ hg help nohelp
936 $ hg help nohelp
937 hg nohelp
937 hg nohelp
938
938
939 (no help text available)
939 (no help text available)
940
940
941 options:
941 options:
942
942
943 --longdesc VALUE
943 --longdesc VALUE
944 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
944 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
945 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
945 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
946 -n -- normal desc
946 -n -- normal desc
947 --newline VALUE line1 line2
947 --newline VALUE line1 line2
948 --default-off enable X
948 --default-off enable X
949 --[no-]default-on enable Y (default: on)
949 --[no-]default-on enable Y (default: on)
950 --callableopt VALUE adds foo
950 --callableopt VALUE adds foo
951 --customopt VALUE adds bar
951 --customopt VALUE adds bar
952 --customopt-withdefault VALUE adds bar (default: foo)
952 --customopt-withdefault VALUE adds bar (default: foo)
953
953
954 (some details hidden, use --verbose to show complete help)
954 (some details hidden, use --verbose to show complete help)
955
955
956 Test that default list of commands includes extension commands that have help,
956 Test that default list of commands includes extension commands that have help,
957 but not those that don't, except in verbose mode, when a keyword is passed, or
957 but not those that don't, except in verbose mode, when a keyword is passed, or
958 when help about the extension is requested.
958 when help about the extension is requested.
959
959
960 #if no-extraextensions
960 #if no-extraextensions
961
961
962 $ hg help | grep hashelp
962 $ hg help | grep hashelp
963 hashelp Extension command's help
963 hashelp Extension command's help
964 $ hg help | grep nohelp
964 $ hg help | grep nohelp
965 [1]
965 [1]
966 $ hg help -v | grep nohelp
966 $ hg help -v | grep nohelp
967 nohelp (no help text available)
967 nohelp (no help text available)
968
968
969 $ hg help -k nohelp
969 $ hg help -k nohelp
970 Commands:
970 Commands:
971
971
972 nohelp hg nohelp
972 nohelp hg nohelp
973
973
974 Extension Commands:
974 Extension Commands:
975
975
976 nohelp (no help text available)
976 nohelp (no help text available)
977
977
978 $ hg help helpext
978 $ hg help helpext
979 helpext extension - no help text available
979 helpext extension - no help text available
980
980
981 list of commands:
981 list of commands:
982
982
983 hashelp Extension command's help
983 hashelp Extension command's help
984 nohelp (no help text available)
984 nohelp (no help text available)
985
985
986 (use 'hg help -v helpext' to show built-in aliases and global options)
986 (use 'hg help -v helpext' to show built-in aliases and global options)
987
987
988 #endif
988 #endif
989
989
990 Test list of internal help commands
990 Test list of internal help commands
991
991
992 $ hg help debug
992 $ hg help debug
993 debug commands (internal and unsupported):
993 debug commands (internal and unsupported):
994
994
995 debug-delta-find
995 debug-delta-find
996 display the computation to get to a valid delta for storing REV
996 display the computation to get to a valid delta for storing REV
997 debug-repair-issue6528
997 debug-repair-issue6528
998 find affected revisions and repair them. See issue6528 for more
998 find affected revisions and repair them. See issue6528 for more
999 details.
999 details.
1000 debug-revlog-index
1000 debug-revlog-index
1001 dump index data for a revlog
1001 dump index data for a revlog
1002 debug-revlog-stats
1002 debug-revlog-stats
1003 display statistics about revlogs in the store
1003 display statistics about revlogs in the store
1004 debug::stable-tail-sort
1004 debug::stable-tail-sort
1005 display the stable-tail sort of the ancestors of a given node
1005 display the stable-tail sort of the ancestors of a given node
1006 debug::stable-tail-sort-leaps
1006 debug::stable-tail-sort-leaps
1007 display the leaps in the stable-tail sort of a node, one per
1007 display the leaps in the stable-tail sort of a node, one per
1008 line
1008 line
1009 debug::unbundle
1010 same as 'hg unbundle', but pretent to come from a push
1009 debugancestor
1011 debugancestor
1010 find the ancestor revision of two revisions in a given index
1012 find the ancestor revision of two revisions in a given index
1011 debugantivirusrunning
1013 debugantivirusrunning
1012 attempt to trigger an antivirus scanner to see if one is active
1014 attempt to trigger an antivirus scanner to see if one is active
1013 debugapplystreamclonebundle
1015 debugapplystreamclonebundle
1014 apply a stream clone bundle file
1016 apply a stream clone bundle file
1015 debugbackupbundle
1017 debugbackupbundle
1016 lists the changesets available in backup bundles
1018 lists the changesets available in backup bundles
1017 debugbuilddag
1019 debugbuilddag
1018 builds a repo with a given DAG from scratch in the current
1020 builds a repo with a given DAG from scratch in the current
1019 empty repo
1021 empty repo
1020 debugbundle lists the contents of a bundle
1022 debugbundle lists the contents of a bundle
1021 debugcapabilities
1023 debugcapabilities
1022 lists the capabilities of a remote peer
1024 lists the capabilities of a remote peer
1023 debugchangedfiles
1025 debugchangedfiles
1024 list the stored files changes for a revision
1026 list the stored files changes for a revision
1025 debugcheckstate
1027 debugcheckstate
1026 validate the correctness of the current dirstate
1028 validate the correctness of the current dirstate
1027 debugcolor show available color, effects or style
1029 debugcolor show available color, effects or style
1028 debugcommands
1030 debugcommands
1029 list all available commands and options
1031 list all available commands and options
1030 debugcomplete
1032 debugcomplete
1031 returns the completion list associated with the given command
1033 returns the completion list associated with the given command
1032 debugcreatestreamclonebundle
1034 debugcreatestreamclonebundle
1033 create a stream clone bundle file
1035 create a stream clone bundle file
1034 debugdag format the changelog or an index DAG as a concise textual
1036 debugdag format the changelog or an index DAG as a concise textual
1035 description
1037 description
1036 debugdata dump the contents of a data file revision
1038 debugdata dump the contents of a data file revision
1037 debugdate parse and display a date
1039 debugdate parse and display a date
1038 debugdeltachain
1040 debugdeltachain
1039 dump information about delta chains in a revlog
1041 dump information about delta chains in a revlog
1040 debugdirstate
1042 debugdirstate
1041 show the contents of the current dirstate
1043 show the contents of the current dirstate
1042 debugdirstateignorepatternshash
1044 debugdirstateignorepatternshash
1043 show the hash of ignore patterns stored in dirstate if v2,
1045 show the hash of ignore patterns stored in dirstate if v2,
1044 debugdiscovery
1046 debugdiscovery
1045 runs the changeset discovery protocol in isolation
1047 runs the changeset discovery protocol in isolation
1046 debugdownload
1048 debugdownload
1047 download a resource using Mercurial logic and config
1049 download a resource using Mercurial logic and config
1048 debugextensions
1050 debugextensions
1049 show information about active extensions
1051 show information about active extensions
1050 debugfileset parse and apply a fileset specification
1052 debugfileset parse and apply a fileset specification
1051 debugformat display format information about the current repository
1053 debugformat display format information about the current repository
1052 debugfsinfo show information detected about current filesystem
1054 debugfsinfo show information detected about current filesystem
1053 debuggetbundle
1055 debuggetbundle
1054 retrieves a bundle from a repo
1056 retrieves a bundle from a repo
1055 debugignore display the combined ignore pattern and information about
1057 debugignore display the combined ignore pattern and information about
1056 ignored files
1058 ignored files
1057 debugindexdot
1059 debugindexdot
1058 dump an index DAG as a graphviz dot file
1060 dump an index DAG as a graphviz dot file
1059 debugindexstats
1061 debugindexstats
1060 show stats related to the changelog index
1062 show stats related to the changelog index
1061 debuginstall test Mercurial installation
1063 debuginstall test Mercurial installation
1062 debugknown test whether node ids are known to a repo
1064 debugknown test whether node ids are known to a repo
1063 debuglocks show or modify state of locks
1065 debuglocks show or modify state of locks
1064 debugmanifestfulltextcache
1066 debugmanifestfulltextcache
1065 show, clear or amend the contents of the manifest fulltext
1067 show, clear or amend the contents of the manifest fulltext
1066 cache
1068 cache
1067 debugmergestate
1069 debugmergestate
1068 print merge state
1070 print merge state
1069 debugnamecomplete
1071 debugnamecomplete
1070 complete "names" - tags, open branch names, bookmark names
1072 complete "names" - tags, open branch names, bookmark names
1071 debugnodemap write and inspect on disk nodemap
1073 debugnodemap write and inspect on disk nodemap
1072 debugobsolete
1074 debugobsolete
1073 create arbitrary obsolete marker
1075 create arbitrary obsolete marker
1074 debugoptADV (no help text available)
1076 debugoptADV (no help text available)
1075 debugoptDEP (no help text available)
1077 debugoptDEP (no help text available)
1076 debugoptEXP (no help text available)
1078 debugoptEXP (no help text available)
1077 debugp1copies
1079 debugp1copies
1078 dump copy information compared to p1
1080 dump copy information compared to p1
1079 debugp2copies
1081 debugp2copies
1080 dump copy information compared to p2
1082 dump copy information compared to p2
1081 debugpathcomplete
1083 debugpathcomplete
1082 complete part or all of a tracked path
1084 complete part or all of a tracked path
1083 debugpathcopies
1085 debugpathcopies
1084 show copies between two revisions
1086 show copies between two revisions
1085 debugpeer establish a connection to a peer repository
1087 debugpeer establish a connection to a peer repository
1086 debugpickmergetool
1088 debugpickmergetool
1087 examine which merge tool is chosen for specified file
1089 examine which merge tool is chosen for specified file
1088 debugpushkey access the pushkey key/value protocol
1090 debugpushkey access the pushkey key/value protocol
1089 debugpvec (no help text available)
1091 debugpvec (no help text available)
1090 debugrebuilddirstate
1092 debugrebuilddirstate
1091 rebuild the dirstate as it would look like for the given
1093 rebuild the dirstate as it would look like for the given
1092 revision
1094 revision
1093 debugrebuildfncache
1095 debugrebuildfncache
1094 rebuild the fncache file
1096 rebuild the fncache file
1095 debugrename dump rename information
1097 debugrename dump rename information
1096 debugrequires
1098 debugrequires
1097 print the current repo requirements
1099 print the current repo requirements
1098 debugrevlog show data and statistics about a revlog
1100 debugrevlog show data and statistics about a revlog
1099 debugrevlogindex
1101 debugrevlogindex
1100 dump the contents of a revlog index
1102 dump the contents of a revlog index
1101 debugrevspec parse and apply a revision specification
1103 debugrevspec parse and apply a revision specification
1102 debugserve run a server with advanced settings
1104 debugserve run a server with advanced settings
1103 debugsetparents
1105 debugsetparents
1104 manually set the parents of the current working directory
1106 manually set the parents of the current working directory
1105 (DANGEROUS)
1107 (DANGEROUS)
1106 debugshell run an interactive Python interpreter
1108 debugshell run an interactive Python interpreter
1107 debugsidedata
1109 debugsidedata
1108 dump the side data for a cl/manifest/file revision
1110 dump the side data for a cl/manifest/file revision
1109 debugssl test a secure connection to a server
1111 debugssl test a secure connection to a server
1110 debugstrip strip changesets and all their descendants from the repository
1112 debugstrip strip changesets and all their descendants from the repository
1111 debugsub (no help text available)
1113 debugsub (no help text available)
1112 debugsuccessorssets
1114 debugsuccessorssets
1113 show set of successors for revision
1115 show set of successors for revision
1114 debugtagscache
1116 debugtagscache
1115 display the contents of .hg/cache/hgtagsfnodes1
1117 display the contents of .hg/cache/hgtagsfnodes1
1116 debugtemplate
1118 debugtemplate
1117 parse and apply a template
1119 parse and apply a template
1118 debuguigetpass
1120 debuguigetpass
1119 show prompt to type password
1121 show prompt to type password
1120 debuguiprompt
1122 debuguiprompt
1121 show plain prompt
1123 show plain prompt
1122 debugupdatecaches
1124 debugupdatecaches
1123 warm all known caches in the repository
1125 warm all known caches in the repository
1124 debugupgraderepo
1126 debugupgraderepo
1125 upgrade a repository to use different features
1127 upgrade a repository to use different features
1126 debugwalk show how files match on given patterns
1128 debugwalk show how files match on given patterns
1127 debugwhyunstable
1129 debugwhyunstable
1128 explain instabilities of a changeset
1130 explain instabilities of a changeset
1129 debugwireargs
1131 debugwireargs
1130 (no help text available)
1132 (no help text available)
1131 debugwireproto
1133 debugwireproto
1132 send wire protocol commands to a server
1134 send wire protocol commands to a server
1133
1135
1134 (use 'hg help -v debug' to show built-in aliases and global options)
1136 (use 'hg help -v debug' to show built-in aliases and global options)
1135
1137
1136 internals topic renders index of available sub-topics
1138 internals topic renders index of available sub-topics
1137
1139
1138 $ hg help internals
1140 $ hg help internals
1139 Technical implementation topics
1141 Technical implementation topics
1140 """""""""""""""""""""""""""""""
1142 """""""""""""""""""""""""""""""
1141
1143
1142 To access a subtopic, use "hg help internals.{subtopic-name}"
1144 To access a subtopic, use "hg help internals.{subtopic-name}"
1143
1145
1144 bid-merge Bid Merge Algorithm
1146 bid-merge Bid Merge Algorithm
1145 bundle2 Bundle2
1147 bundle2 Bundle2
1146 bundles Bundles
1148 bundles Bundles
1147 cbor CBOR
1149 cbor CBOR
1148 censor Censor
1150 censor Censor
1149 changegroups Changegroups
1151 changegroups Changegroups
1150 config Config Registrar
1152 config Config Registrar
1151 dirstate-v2 dirstate-v2 file format
1153 dirstate-v2 dirstate-v2 file format
1152 extensions Extension API
1154 extensions Extension API
1153 mergestate Mergestate
1155 mergestate Mergestate
1154 requirements Repository Requirements
1156 requirements Repository Requirements
1155 revlogs Revision Logs
1157 revlogs Revision Logs
1156 wireprotocol Wire Protocol
1158 wireprotocol Wire Protocol
1157 wireprotocolrpc
1159 wireprotocolrpc
1158 Wire Protocol RPC
1160 Wire Protocol RPC
1159 wireprotocolv2
1161 wireprotocolv2
1160 Wire Protocol Version 2
1162 Wire Protocol Version 2
1161
1163
1162 sub-topics can be accessed
1164 sub-topics can be accessed
1163
1165
1164 $ hg help internals.changegroups
1166 $ hg help internals.changegroups
1165 Changegroups
1167 Changegroups
1166 """"""""""""
1168 """"""""""""
1167
1169
1168 Changegroups are representations of repository revlog data, specifically
1170 Changegroups are representations of repository revlog data, specifically
1169 the changelog data, root/flat manifest data, treemanifest data, and
1171 the changelog data, root/flat manifest data, treemanifest data, and
1170 filelogs.
1172 filelogs.
1171
1173
1172 There are 4 versions of changegroups: "1", "2", "3" and "4". From a high-
1174 There are 4 versions of changegroups: "1", "2", "3" and "4". From a high-
1173 level, versions "1" and "2" are almost exactly the same, with the only
1175 level, versions "1" and "2" are almost exactly the same, with the only
1174 difference being an additional item in the *delta header*. Version "3"
1176 difference being an additional item in the *delta header*. Version "3"
1175 adds support for storage flags in the *delta header* and optionally
1177 adds support for storage flags in the *delta header* and optionally
1176 exchanging treemanifests (enabled by setting an option on the
1178 exchanging treemanifests (enabled by setting an option on the
1177 "changegroup" part in the bundle2). Version "4" adds support for
1179 "changegroup" part in the bundle2). Version "4" adds support for
1178 exchanging sidedata (additional revision metadata not part of the digest).
1180 exchanging sidedata (additional revision metadata not part of the digest).
1179
1181
1180 Changegroups when not exchanging treemanifests consist of 3 logical
1182 Changegroups when not exchanging treemanifests consist of 3 logical
1181 segments:
1183 segments:
1182
1184
1183 +---------------------------------+
1185 +---------------------------------+
1184 | | | |
1186 | | | |
1185 | changeset | manifest | filelogs |
1187 | changeset | manifest | filelogs |
1186 | | | |
1188 | | | |
1187 | | | |
1189 | | | |
1188 +---------------------------------+
1190 +---------------------------------+
1189
1191
1190 When exchanging treemanifests, there are 4 logical segments:
1192 When exchanging treemanifests, there are 4 logical segments:
1191
1193
1192 +-------------------------------------------------+
1194 +-------------------------------------------------+
1193 | | | | |
1195 | | | | |
1194 | changeset | root | treemanifests | filelogs |
1196 | changeset | root | treemanifests | filelogs |
1195 | | manifest | | |
1197 | | manifest | | |
1196 | | | | |
1198 | | | | |
1197 +-------------------------------------------------+
1199 +-------------------------------------------------+
1198
1200
1199 The principle building block of each segment is a *chunk*. A *chunk* is a
1201 The principle building block of each segment is a *chunk*. A *chunk* is a
1200 framed piece of data:
1202 framed piece of data:
1201
1203
1202 +---------------------------------------+
1204 +---------------------------------------+
1203 | | |
1205 | | |
1204 | length | data |
1206 | length | data |
1205 | (4 bytes) | (<length - 4> bytes) |
1207 | (4 bytes) | (<length - 4> bytes) |
1206 | | |
1208 | | |
1207 +---------------------------------------+
1209 +---------------------------------------+
1208
1210
1209 All integers are big-endian signed integers. Each chunk starts with a
1211 All integers are big-endian signed integers. Each chunk starts with a
1210 32-bit integer indicating the length of the entire chunk (including the
1212 32-bit integer indicating the length of the entire chunk (including the
1211 length field itself).
1213 length field itself).
1212
1214
1213 There is a special case chunk that has a value of 0 for the length
1215 There is a special case chunk that has a value of 0 for the length
1214 ("0x00000000"). We call this an *empty chunk*.
1216 ("0x00000000"). We call this an *empty chunk*.
1215
1217
1216 Delta Groups
1218 Delta Groups
1217 ============
1219 ============
1218
1220
1219 A *delta group* expresses the content of a revlog as a series of deltas,
1221 A *delta group* expresses the content of a revlog as a series of deltas,
1220 or patches against previous revisions.
1222 or patches against previous revisions.
1221
1223
1222 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1224 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1223 to signal the end of the delta group:
1225 to signal the end of the delta group:
1224
1226
1225 +------------------------------------------------------------------------+
1227 +------------------------------------------------------------------------+
1226 | | | | | |
1228 | | | | | |
1227 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1229 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1228 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1230 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1229 | | | | | |
1231 | | | | | |
1230 +------------------------------------------------------------------------+
1232 +------------------------------------------------------------------------+
1231
1233
1232 Each *chunk*'s data consists of the following:
1234 Each *chunk*'s data consists of the following:
1233
1235
1234 +---------------------------------------+
1236 +---------------------------------------+
1235 | | |
1237 | | |
1236 | delta header | delta data |
1238 | delta header | delta data |
1237 | (various by version) | (various) |
1239 | (various by version) | (various) |
1238 | | |
1240 | | |
1239 +---------------------------------------+
1241 +---------------------------------------+
1240
1242
1241 The *delta data* is a series of *delta*s that describe a diff from an
1243 The *delta data* is a series of *delta*s that describe a diff from an
1242 existing entry (either that the recipient already has, or previously
1244 existing entry (either that the recipient already has, or previously
1243 specified in the bundle/changegroup).
1245 specified in the bundle/changegroup).
1244
1246
1245 The *delta header* is different between versions "1", "2", "3" and "4" of
1247 The *delta header* is different between versions "1", "2", "3" and "4" of
1246 the changegroup format.
1248 the changegroup format.
1247
1249
1248 Version 1 (headerlen=80):
1250 Version 1 (headerlen=80):
1249
1251
1250 +------------------------------------------------------+
1252 +------------------------------------------------------+
1251 | | | | |
1253 | | | | |
1252 | node | p1 node | p2 node | link node |
1254 | node | p1 node | p2 node | link node |
1253 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1255 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1254 | | | | |
1256 | | | | |
1255 +------------------------------------------------------+
1257 +------------------------------------------------------+
1256
1258
1257 Version 2 (headerlen=100):
1259 Version 2 (headerlen=100):
1258
1260
1259 +------------------------------------------------------------------+
1261 +------------------------------------------------------------------+
1260 | | | | | |
1262 | | | | | |
1261 | node | p1 node | p2 node | base node | link node |
1263 | node | p1 node | p2 node | base node | link node |
1262 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1264 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1263 | | | | | |
1265 | | | | | |
1264 +------------------------------------------------------------------+
1266 +------------------------------------------------------------------+
1265
1267
1266 Version 3 (headerlen=102):
1268 Version 3 (headerlen=102):
1267
1269
1268 +------------------------------------------------------------------------------+
1270 +------------------------------------------------------------------------------+
1269 | | | | | | |
1271 | | | | | | |
1270 | node | p1 node | p2 node | base node | link node | flags |
1272 | node | p1 node | p2 node | base node | link node | flags |
1271 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1273 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1272 | | | | | | |
1274 | | | | | | |
1273 +------------------------------------------------------------------------------+
1275 +------------------------------------------------------------------------------+
1274
1276
1275 Version 4 (headerlen=103):
1277 Version 4 (headerlen=103):
1276
1278
1277 +------------------------------------------------------------------------------+----------+
1279 +------------------------------------------------------------------------------+----------+
1278 | | | | | | | |
1280 | | | | | | | |
1279 | node | p1 node | p2 node | base node | link node | flags | pflags |
1281 | node | p1 node | p2 node | base node | link node | flags | pflags |
1280 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
1282 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
1281 | | | | | | | |
1283 | | | | | | | |
1282 +------------------------------------------------------------------------------+----------+
1284 +------------------------------------------------------------------------------+----------+
1283
1285
1284 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1286 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1285 contain a series of *delta*s, densely packed (no separators). These deltas
1287 contain a series of *delta*s, densely packed (no separators). These deltas
1286 describe a diff from an existing entry (either that the recipient already
1288 describe a diff from an existing entry (either that the recipient already
1287 has, or previously specified in the bundle/changegroup). The format is
1289 has, or previously specified in the bundle/changegroup). The format is
1288 described more fully in "hg help internals.bdiff", but briefly:
1290 described more fully in "hg help internals.bdiff", but briefly:
1289
1291
1290 +---------------------------------------------------------------+
1292 +---------------------------------------------------------------+
1291 | | | | |
1293 | | | | |
1292 | start offset | end offset | new length | content |
1294 | start offset | end offset | new length | content |
1293 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1295 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1294 | | | | |
1296 | | | | |
1295 +---------------------------------------------------------------+
1297 +---------------------------------------------------------------+
1296
1298
1297 Please note that the length field in the delta data does *not* include
1299 Please note that the length field in the delta data does *not* include
1298 itself.
1300 itself.
1299
1301
1300 In version 1, the delta is always applied against the previous node from
1302 In version 1, the delta is always applied against the previous node from
1301 the changegroup or the first parent if this is the first entry in the
1303 the changegroup or the first parent if this is the first entry in the
1302 changegroup.
1304 changegroup.
1303
1305
1304 In version 2 and up, the delta base node is encoded in the entry in the
1306 In version 2 and up, the delta base node is encoded in the entry in the
1305 changegroup. This allows the delta to be expressed against any parent,
1307 changegroup. This allows the delta to be expressed against any parent,
1306 which can result in smaller deltas and more efficient encoding of data.
1308 which can result in smaller deltas and more efficient encoding of data.
1307
1309
1308 The *flags* field holds bitwise flags affecting the processing of revision
1310 The *flags* field holds bitwise flags affecting the processing of revision
1309 data. The following flags are defined:
1311 data. The following flags are defined:
1310
1312
1311 32768
1313 32768
1312 Censored revision. The revision's fulltext has been replaced by censor
1314 Censored revision. The revision's fulltext has been replaced by censor
1313 metadata. May only occur on file revisions.
1315 metadata. May only occur on file revisions.
1314
1316
1315 16384
1317 16384
1316 Ellipsis revision. Revision hash does not match data (likely due to
1318 Ellipsis revision. Revision hash does not match data (likely due to
1317 rewritten parents).
1319 rewritten parents).
1318
1320
1319 8192
1321 8192
1320 Externally stored. The revision fulltext contains "key:value" "\n"
1322 Externally stored. The revision fulltext contains "key:value" "\n"
1321 delimited metadata defining an object stored elsewhere. Used by the LFS
1323 delimited metadata defining an object stored elsewhere. Used by the LFS
1322 extension.
1324 extension.
1323
1325
1324 4096
1326 4096
1325 Contains copy information. This revision changes files in a way that
1327 Contains copy information. This revision changes files in a way that
1326 could affect copy tracing. This does *not* affect changegroup handling,
1328 could affect copy tracing. This does *not* affect changegroup handling,
1327 but is relevant for other parts of Mercurial.
1329 but is relevant for other parts of Mercurial.
1328
1330
1329 For historical reasons, the integer values are identical to revlog version
1331 For historical reasons, the integer values are identical to revlog version
1330 1 per-revision storage flags and correspond to bits being set in this
1332 1 per-revision storage flags and correspond to bits being set in this
1331 2-byte field. Bits were allocated starting from the most-significant bit,
1333 2-byte field. Bits were allocated starting from the most-significant bit,
1332 hence the reverse ordering and allocation of these flags.
1334 hence the reverse ordering and allocation of these flags.
1333
1335
1334 The *pflags* (protocol flags) field holds bitwise flags affecting the
1336 The *pflags* (protocol flags) field holds bitwise flags affecting the
1335 protocol itself. They are first in the header since they may affect the
1337 protocol itself. They are first in the header since they may affect the
1336 handling of the rest of the fields in a future version. They are defined
1338 handling of the rest of the fields in a future version. They are defined
1337 as such:
1339 as such:
1338
1340
1339 1 indicates whether to read a chunk of sidedata (of variable length) right
1341 1 indicates whether to read a chunk of sidedata (of variable length) right
1340 after the revision flags.
1342 after the revision flags.
1341
1343
1342 Changeset Segment
1344 Changeset Segment
1343 =================
1345 =================
1344
1346
1345 The *changeset segment* consists of a single *delta group* holding
1347 The *changeset segment* consists of a single *delta group* holding
1346 changelog data. The *empty chunk* at the end of the *delta group* denotes
1348 changelog data. The *empty chunk* at the end of the *delta group* denotes
1347 the boundary to the *manifest segment*.
1349 the boundary to the *manifest segment*.
1348
1350
1349 Manifest Segment
1351 Manifest Segment
1350 ================
1352 ================
1351
1353
1352 The *manifest segment* consists of a single *delta group* holding manifest
1354 The *manifest segment* consists of a single *delta group* holding manifest
1353 data. If treemanifests are in use, it contains only the manifest for the
1355 data. If treemanifests are in use, it contains only the manifest for the
1354 root directory of the repository. Otherwise, it contains the entire
1356 root directory of the repository. Otherwise, it contains the entire
1355 manifest data. The *empty chunk* at the end of the *delta group* denotes
1357 manifest data. The *empty chunk* at the end of the *delta group* denotes
1356 the boundary to the next segment (either the *treemanifests segment* or
1358 the boundary to the next segment (either the *treemanifests segment* or
1357 the *filelogs segment*, depending on version and the request options).
1359 the *filelogs segment*, depending on version and the request options).
1358
1360
1359 Treemanifests Segment
1361 Treemanifests Segment
1360 ---------------------
1362 ---------------------
1361
1363
1362 The *treemanifests segment* only exists in changegroup version "3" and
1364 The *treemanifests segment* only exists in changegroup version "3" and
1363 "4", and only if the 'treemanifest' param is part of the bundle2
1365 "4", and only if the 'treemanifest' param is part of the bundle2
1364 changegroup part (it is not possible to use changegroup version 3 or 4
1366 changegroup part (it is not possible to use changegroup version 3 or 4
1365 outside of bundle2). Aside from the filenames in the *treemanifests
1367 outside of bundle2). Aside from the filenames in the *treemanifests
1366 segment* containing a trailing "/" character, it behaves identically to
1368 segment* containing a trailing "/" character, it behaves identically to
1367 the *filelogs segment* (see below). The final sub-segment is followed by
1369 the *filelogs segment* (see below). The final sub-segment is followed by
1368 an *empty chunk* (logically, a sub-segment with filename size 0). This
1370 an *empty chunk* (logically, a sub-segment with filename size 0). This
1369 denotes the boundary to the *filelogs segment*.
1371 denotes the boundary to the *filelogs segment*.
1370
1372
1371 Filelogs Segment
1373 Filelogs Segment
1372 ================
1374 ================
1373
1375
1374 The *filelogs segment* consists of multiple sub-segments, each
1376 The *filelogs segment* consists of multiple sub-segments, each
1375 corresponding to an individual file whose data is being described:
1377 corresponding to an individual file whose data is being described:
1376
1378
1377 +--------------------------------------------------+
1379 +--------------------------------------------------+
1378 | | | | | |
1380 | | | | | |
1379 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1381 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1380 | | | | | (4 bytes) |
1382 | | | | | (4 bytes) |
1381 | | | | | |
1383 | | | | | |
1382 +--------------------------------------------------+
1384 +--------------------------------------------------+
1383
1385
1384 The final filelog sub-segment is followed by an *empty chunk* (logically,
1386 The final filelog sub-segment is followed by an *empty chunk* (logically,
1385 a sub-segment with filename size 0). This denotes the end of the segment
1387 a sub-segment with filename size 0). This denotes the end of the segment
1386 and of the overall changegroup.
1388 and of the overall changegroup.
1387
1389
1388 Each filelog sub-segment consists of the following:
1390 Each filelog sub-segment consists of the following:
1389
1391
1390 +------------------------------------------------------+
1392 +------------------------------------------------------+
1391 | | | |
1393 | | | |
1392 | filename length | filename | delta group |
1394 | filename length | filename | delta group |
1393 | (4 bytes) | (<length - 4> bytes) | (various) |
1395 | (4 bytes) | (<length - 4> bytes) | (various) |
1394 | | | |
1396 | | | |
1395 +------------------------------------------------------+
1397 +------------------------------------------------------+
1396
1398
1397 That is, a *chunk* consisting of the filename (not terminated or padded)
1399 That is, a *chunk* consisting of the filename (not terminated or padded)
1398 followed by N chunks constituting the *delta group* for this file. The
1400 followed by N chunks constituting the *delta group* for this file. The
1399 *empty chunk* at the end of each *delta group* denotes the boundary to the
1401 *empty chunk* at the end of each *delta group* denotes the boundary to the
1400 next filelog sub-segment.
1402 next filelog sub-segment.
1401
1403
1402 non-existent subtopics print an error
1404 non-existent subtopics print an error
1403
1405
1404 $ hg help internals.foo
1406 $ hg help internals.foo
1405 abort: no such help topic: internals.foo
1407 abort: no such help topic: internals.foo
1406 (try 'hg help --keyword foo')
1408 (try 'hg help --keyword foo')
1407 [10]
1409 [10]
1408
1410
1409 test advanced, deprecated and experimental options are hidden in command help
1411 test advanced, deprecated and experimental options are hidden in command help
1410 $ hg help debugoptADV
1412 $ hg help debugoptADV
1411 hg debugoptADV
1413 hg debugoptADV
1412
1414
1413 (no help text available)
1415 (no help text available)
1414
1416
1415 options:
1417 options:
1416
1418
1417 (some details hidden, use --verbose to show complete help)
1419 (some details hidden, use --verbose to show complete help)
1418 $ hg help debugoptDEP
1420 $ hg help debugoptDEP
1419 hg debugoptDEP
1421 hg debugoptDEP
1420
1422
1421 (no help text available)
1423 (no help text available)
1422
1424
1423 options:
1425 options:
1424
1426
1425 (some details hidden, use --verbose to show complete help)
1427 (some details hidden, use --verbose to show complete help)
1426
1428
1427 $ hg help debugoptEXP
1429 $ hg help debugoptEXP
1428 hg debugoptEXP
1430 hg debugoptEXP
1429
1431
1430 (no help text available)
1432 (no help text available)
1431
1433
1432 options:
1434 options:
1433
1435
1434 (some details hidden, use --verbose to show complete help)
1436 (some details hidden, use --verbose to show complete help)
1435
1437
1436 test advanced, deprecated and experimental options are shown with -v
1438 test advanced, deprecated and experimental options are shown with -v
1437 $ hg help -v debugoptADV | grep aopt
1439 $ hg help -v debugoptADV | grep aopt
1438 --aopt option is (ADVANCED)
1440 --aopt option is (ADVANCED)
1439 $ hg help -v debugoptDEP | grep dopt
1441 $ hg help -v debugoptDEP | grep dopt
1440 --dopt option is (DEPRECATED)
1442 --dopt option is (DEPRECATED)
1441 $ hg help -v debugoptEXP | grep eopt
1443 $ hg help -v debugoptEXP | grep eopt
1442 --eopt option is (EXPERIMENTAL)
1444 --eopt option is (EXPERIMENTAL)
1443
1445
1444 #if gettext
1446 #if gettext
1445 test deprecated option is hidden with translation with untranslated description
1447 test deprecated option is hidden with translation with untranslated description
1446 (use many globy for not failing on changed transaction)
1448 (use many globy for not failing on changed transaction)
1447 $ LANGUAGE=sv hg help debugoptDEP
1449 $ LANGUAGE=sv hg help debugoptDEP
1448 hg debugoptDEP
1450 hg debugoptDEP
1449
1451
1450 (*) (glob)
1452 (*) (glob)
1451
1453
1452 options:
1454 options:
1453
1455
1454 (some details hidden, use --verbose to show complete help)
1456 (some details hidden, use --verbose to show complete help)
1455 #endif
1457 #endif
1456
1458
1457 Test commands that collide with topics (issue4240)
1459 Test commands that collide with topics (issue4240)
1458
1460
1459 $ hg config -hq
1461 $ hg config -hq
1460 hg config [-u] [NAME]...
1462 hg config [-u] [NAME]...
1461
1463
1462 show combined config settings from all hgrc files
1464 show combined config settings from all hgrc files
1463 $ hg showconfig -hq
1465 $ hg showconfig -hq
1464 hg config [-u] [NAME]...
1466 hg config [-u] [NAME]...
1465
1467
1466 show combined config settings from all hgrc files
1468 show combined config settings from all hgrc files
1467
1469
1468 Test a help topic
1470 Test a help topic
1469
1471
1470 $ hg help dates
1472 $ hg help dates
1471 Date Formats
1473 Date Formats
1472 """"""""""""
1474 """"""""""""
1473
1475
1474 Some commands allow the user to specify a date, e.g.:
1476 Some commands allow the user to specify a date, e.g.:
1475
1477
1476 - backout, commit, import, tag: Specify the commit date.
1478 - backout, commit, import, tag: Specify the commit date.
1477 - log, revert, update: Select revision(s) by date.
1479 - log, revert, update: Select revision(s) by date.
1478
1480
1479 Many date formats are valid. Here are some examples:
1481 Many date formats are valid. Here are some examples:
1480
1482
1481 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1483 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1482 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1484 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1483 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1485 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1484 - "Dec 6" (midnight)
1486 - "Dec 6" (midnight)
1485 - "13:18" (today assumed)
1487 - "13:18" (today assumed)
1486 - "3:39" (3:39AM assumed)
1488 - "3:39" (3:39AM assumed)
1487 - "3:39pm" (15:39)
1489 - "3:39pm" (15:39)
1488 - "2006-12-06 13:18:29" (ISO 8601 format)
1490 - "2006-12-06 13:18:29" (ISO 8601 format)
1489 - "2006-12-6 13:18"
1491 - "2006-12-6 13:18"
1490 - "2006-12-6"
1492 - "2006-12-6"
1491 - "12-6"
1493 - "12-6"
1492 - "12/6"
1494 - "12/6"
1493 - "12/6/6" (Dec 6 2006)
1495 - "12/6/6" (Dec 6 2006)
1494 - "today" (midnight)
1496 - "today" (midnight)
1495 - "yesterday" (midnight)
1497 - "yesterday" (midnight)
1496 - "now" - right now
1498 - "now" - right now
1497
1499
1498 Lastly, there is Mercurial's internal format:
1500 Lastly, there is Mercurial's internal format:
1499
1501
1500 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1502 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1501
1503
1502 This is the internal representation format for dates. The first number is
1504 This is the internal representation format for dates. The first number is
1503 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1505 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1504 is the offset of the local timezone, in seconds west of UTC (negative if
1506 is the offset of the local timezone, in seconds west of UTC (negative if
1505 the timezone is east of UTC).
1507 the timezone is east of UTC).
1506
1508
1507 The log command also accepts date ranges:
1509 The log command also accepts date ranges:
1508
1510
1509 - "<DATE" - at or before a given date/time
1511 - "<DATE" - at or before a given date/time
1510 - ">DATE" - on or after a given date/time
1512 - ">DATE" - on or after a given date/time
1511 - "DATE to DATE" - a date range, inclusive
1513 - "DATE to DATE" - a date range, inclusive
1512 - "-DAYS" - within a given number of days from today
1514 - "-DAYS" - within a given number of days from today
1513
1515
1514 Test repeated config section name
1516 Test repeated config section name
1515
1517
1516 $ hg help config.host
1518 $ hg help config.host
1517 "http_proxy.host"
1519 "http_proxy.host"
1518 Host name and (optional) port of the proxy server, for example
1520 Host name and (optional) port of the proxy server, for example
1519 "myproxy:8000".
1521 "myproxy:8000".
1520
1522
1521 "smtp.host"
1523 "smtp.host"
1522 Host name of mail server, e.g. "mail.example.com".
1524 Host name of mail server, e.g. "mail.example.com".
1523
1525
1524
1526
1525 Test section name with dot
1527 Test section name with dot
1526
1528
1527 $ hg help config.ui.username
1529 $ hg help config.ui.username
1528 "ui.username"
1530 "ui.username"
1529 The committer of a changeset created when running "commit". Typically
1531 The committer of a changeset created when running "commit". Typically
1530 a person's name and email address, e.g. "Fred Widget
1532 a person's name and email address, e.g. "Fred Widget
1531 <fred@example.com>". Environment variables in the username are
1533 <fred@example.com>". Environment variables in the username are
1532 expanded.
1534 expanded.
1533
1535
1534 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1536 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1535 empty, e.g. if the system admin set "username =" in the system hgrc,
1537 empty, e.g. if the system admin set "username =" in the system hgrc,
1536 it has to be specified manually or in a different hgrc file)
1538 it has to be specified manually or in a different hgrc file)
1537
1539
1538
1540
1539 $ hg help config.annotate.git
1541 $ hg help config.annotate.git
1540 abort: help section not found: config.annotate.git
1542 abort: help section not found: config.annotate.git
1541 [10]
1543 [10]
1542
1544
1543 $ hg help config.update.check
1545 $ hg help config.update.check
1544 "commands.update.check"
1546 "commands.update.check"
1545 Determines what level of checking 'hg update' will perform before
1547 Determines what level of checking 'hg update' will perform before
1546 moving to a destination revision. Valid values are "abort", "none",
1548 moving to a destination revision. Valid values are "abort", "none",
1547 "linear", and "noconflict".
1549 "linear", and "noconflict".
1548
1550
1549 - "abort" always fails if the working directory has uncommitted
1551 - "abort" always fails if the working directory has uncommitted
1550 changes.
1552 changes.
1551 - "none" performs no checking, and may result in a merge with
1553 - "none" performs no checking, and may result in a merge with
1552 uncommitted changes.
1554 uncommitted changes.
1553 - "linear" allows any update as long as it follows a straight line in
1555 - "linear" allows any update as long as it follows a straight line in
1554 the revision history, and may trigger a merge with uncommitted
1556 the revision history, and may trigger a merge with uncommitted
1555 changes.
1557 changes.
1556 - "noconflict" will allow any update which would not trigger a merge
1558 - "noconflict" will allow any update which would not trigger a merge
1557 with uncommitted changes, if any are present.
1559 with uncommitted changes, if any are present.
1558
1560
1559 (default: "linear")
1561 (default: "linear")
1560
1562
1561
1563
1562 $ hg help config.commands.update.check
1564 $ hg help config.commands.update.check
1563 "commands.update.check"
1565 "commands.update.check"
1564 Determines what level of checking 'hg update' will perform before
1566 Determines what level of checking 'hg update' will perform before
1565 moving to a destination revision. Valid values are "abort", "none",
1567 moving to a destination revision. Valid values are "abort", "none",
1566 "linear", and "noconflict".
1568 "linear", and "noconflict".
1567
1569
1568 - "abort" always fails if the working directory has uncommitted
1570 - "abort" always fails if the working directory has uncommitted
1569 changes.
1571 changes.
1570 - "none" performs no checking, and may result in a merge with
1572 - "none" performs no checking, and may result in a merge with
1571 uncommitted changes.
1573 uncommitted changes.
1572 - "linear" allows any update as long as it follows a straight line in
1574 - "linear" allows any update as long as it follows a straight line in
1573 the revision history, and may trigger a merge with uncommitted
1575 the revision history, and may trigger a merge with uncommitted
1574 changes.
1576 changes.
1575 - "noconflict" will allow any update which would not trigger a merge
1577 - "noconflict" will allow any update which would not trigger a merge
1576 with uncommitted changes, if any are present.
1578 with uncommitted changes, if any are present.
1577
1579
1578 (default: "linear")
1580 (default: "linear")
1579
1581
1580
1582
1581 $ hg help config.ommands.update.check
1583 $ hg help config.ommands.update.check
1582 abort: help section not found: config.ommands.update.check
1584 abort: help section not found: config.ommands.update.check
1583 [10]
1585 [10]
1584
1586
1585 Unrelated trailing paragraphs shouldn't be included
1587 Unrelated trailing paragraphs shouldn't be included
1586
1588
1587 $ hg help config.extramsg | grep '^$'
1589 $ hg help config.extramsg | grep '^$'
1588
1590
1589
1591
1590 Test capitalized section name
1592 Test capitalized section name
1591
1593
1592 $ hg help scripting.HGPLAIN > /dev/null
1594 $ hg help scripting.HGPLAIN > /dev/null
1593
1595
1594 Help subsection:
1596 Help subsection:
1595
1597
1596 $ hg help config.charsets |grep "Email example:" > /dev/null
1598 $ hg help config.charsets |grep "Email example:" > /dev/null
1597 [1]
1599 [1]
1598
1600
1599 Show nested definitions
1601 Show nested definitions
1600 ("profiling.type"[break]"ls"[break]"stat"[break])
1602 ("profiling.type"[break]"ls"[break]"stat"[break])
1601
1603
1602 $ hg help config.type | grep -E '^$'|wc -l
1604 $ hg help config.type | grep -E '^$'|wc -l
1603 \s*3 (re)
1605 \s*3 (re)
1604
1606
1605 $ hg help config.profiling.type.ls
1607 $ hg help config.profiling.type.ls
1606 "profiling.type.ls"
1608 "profiling.type.ls"
1607 Use Python's built-in instrumenting profiler. This profiler works on
1609 Use Python's built-in instrumenting profiler. This profiler works on
1608 all platforms, but each line number it reports is the first line of
1610 all platforms, but each line number it reports is the first line of
1609 a function. This restriction makes it difficult to identify the
1611 a function. This restriction makes it difficult to identify the
1610 expensive parts of a non-trivial function.
1612 expensive parts of a non-trivial function.
1611
1613
1612
1614
1613 Separate sections from subsections
1615 Separate sections from subsections
1614
1616
1615 $ hg help config.format | grep -E '^ ("|-)|^\s*$' | uniq
1617 $ hg help config.format | grep -E '^ ("|-)|^\s*$' | uniq
1616 "format"
1618 "format"
1617 --------
1619 --------
1618
1620
1619 "usegeneraldelta"
1621 "usegeneraldelta"
1620
1622
1621 "dotencode"
1623 "dotencode"
1622
1624
1623 "usefncache"
1625 "usefncache"
1624
1626
1625 "use-dirstate-v2"
1627 "use-dirstate-v2"
1626
1628
1627 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories"
1629 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories"
1628
1630
1629 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet"
1631 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet"
1630
1632
1631 "use-dirstate-tracked-hint"
1633 "use-dirstate-tracked-hint"
1632
1634
1633 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories"
1635 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories"
1634
1636
1635 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet"
1637 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet"
1636
1638
1637 "use-persistent-nodemap"
1639 "use-persistent-nodemap"
1638
1640
1639 "use-share-safe"
1641 "use-share-safe"
1640
1642
1641 "use-share-safe.automatic-upgrade-of-mismatching-repositories"
1643 "use-share-safe.automatic-upgrade-of-mismatching-repositories"
1642
1644
1643 "use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet"
1645 "use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet"
1644
1646
1645 "usestore"
1647 "usestore"
1646
1648
1647 "sparse-revlog"
1649 "sparse-revlog"
1648
1650
1649 "revlog-compression"
1651 "revlog-compression"
1650
1652
1651 "bookmarks-in-store"
1653 "bookmarks-in-store"
1652
1654
1653 "profiling"
1655 "profiling"
1654 -----------
1656 -----------
1655
1657
1656 "format"
1658 "format"
1657
1659
1658 "progress"
1660 "progress"
1659 ----------
1661 ----------
1660
1662
1661 "format"
1663 "format"
1662
1664
1663
1665
1664 Last item in help config.*:
1666 Last item in help config.*:
1665
1667
1666 $ hg help config.`hg help config|grep '^ "'| \
1668 $ hg help config.`hg help config|grep '^ "'| \
1667 > tail -1|sed 's![ "]*!!g'`| \
1669 > tail -1|sed 's![ "]*!!g'`| \
1668 > grep 'hg help -c config' > /dev/null
1670 > grep 'hg help -c config' > /dev/null
1669 [1]
1671 [1]
1670
1672
1671 note to use help -c for general hg help config:
1673 note to use help -c for general hg help config:
1672
1674
1673 $ hg help config |grep 'hg help -c config' > /dev/null
1675 $ hg help config |grep 'hg help -c config' > /dev/null
1674
1676
1675 Test templating help
1677 Test templating help
1676
1678
1677 $ hg help templating | grep -E '(desc|diffstat|firstline|nonempty) '
1679 $ hg help templating | grep -E '(desc|diffstat|firstline|nonempty) '
1678 desc String. The text of the changeset description.
1680 desc String. The text of the changeset description.
1679 diffstat String. Statistics of changes with the following format:
1681 diffstat String. Statistics of changes with the following format:
1680 firstline Any text. Returns the first line of text.
1682 firstline Any text. Returns the first line of text.
1681 nonempty Any text. Returns '(none)' if the string is empty.
1683 nonempty Any text. Returns '(none)' if the string is empty.
1682
1684
1683 Test deprecated items
1685 Test deprecated items
1684
1686
1685 $ hg help -v templating | grep currentbookmark
1687 $ hg help -v templating | grep currentbookmark
1686 currentbookmark
1688 currentbookmark
1687 $ hg help templating | (grep currentbookmark || true)
1689 $ hg help templating | (grep currentbookmark || true)
1688
1690
1689 Test help hooks
1691 Test help hooks
1690
1692
1691 $ cat > helphook1.py <<EOF
1693 $ cat > helphook1.py <<EOF
1692 > from mercurial import help
1694 > from mercurial import help
1693 >
1695 >
1694 > def rewrite(ui, topic, doc):
1696 > def rewrite(ui, topic, doc):
1695 > return doc + b'\nhelphook1\n'
1697 > return doc + b'\nhelphook1\n'
1696 >
1698 >
1697 > def extsetup(ui):
1699 > def extsetup(ui):
1698 > help.addtopichook(b'revisions', rewrite)
1700 > help.addtopichook(b'revisions', rewrite)
1699 > EOF
1701 > EOF
1700 $ cat > helphook2.py <<EOF
1702 $ cat > helphook2.py <<EOF
1701 > from mercurial import help
1703 > from mercurial import help
1702 >
1704 >
1703 > def rewrite(ui, topic, doc):
1705 > def rewrite(ui, topic, doc):
1704 > return doc + b'\nhelphook2\n'
1706 > return doc + b'\nhelphook2\n'
1705 >
1707 >
1706 > def extsetup(ui):
1708 > def extsetup(ui):
1707 > help.addtopichook(b'revisions', rewrite)
1709 > help.addtopichook(b'revisions', rewrite)
1708 > EOF
1710 > EOF
1709 $ echo '[extensions]' >> $HGRCPATH
1711 $ echo '[extensions]' >> $HGRCPATH
1710 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1712 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1711 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1713 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1712 $ hg help revsets | grep helphook
1714 $ hg help revsets | grep helphook
1713 helphook1
1715 helphook1
1714 helphook2
1716 helphook2
1715
1717
1716 help -c should only show debug --debug
1718 help -c should only show debug --debug
1717
1719
1718 $ hg help -c --debug|grep -E debug|wc -l|grep -E '^\s*0\s*$'
1720 $ hg help -c --debug|grep -E debug|wc -l|grep -E '^\s*0\s*$'
1719 [1]
1721 [1]
1720
1722
1721 help -c should only show deprecated for -v
1723 help -c should only show deprecated for -v
1722
1724
1723 $ hg help -c -v|grep -E DEPRECATED|wc -l|grep -E '^\s*0\s*$'
1725 $ hg help -c -v|grep -E DEPRECATED|wc -l|grep -E '^\s*0\s*$'
1724 [1]
1726 [1]
1725
1727
1726 Test -s / --system
1728 Test -s / --system
1727
1729
1728 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1730 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1729 > wc -l | sed -e 's/ //g'
1731 > wc -l | sed -e 's/ //g'
1730 0
1732 0
1731 $ hg help config.files --system unix | grep 'USER' | \
1733 $ hg help config.files --system unix | grep 'USER' | \
1732 > wc -l | sed -e 's/ //g'
1734 > wc -l | sed -e 's/ //g'
1733 0
1735 0
1734
1736
1735 Test -e / -c / -k combinations
1737 Test -e / -c / -k combinations
1736
1738
1737 $ hg help -c|grep -E '^[A-Z].*:|^ debug'
1739 $ hg help -c|grep -E '^[A-Z].*:|^ debug'
1738 Commands:
1740 Commands:
1739 $ hg help -e|grep -E '^[A-Z].*:|^ debug'
1741 $ hg help -e|grep -E '^[A-Z].*:|^ debug'
1740 Extensions:
1742 Extensions:
1741 $ hg help -k|grep -E '^[A-Z].*:|^ debug'
1743 $ hg help -k|grep -E '^[A-Z].*:|^ debug'
1742 Topics:
1744 Topics:
1743 Commands:
1745 Commands:
1744 Extensions:
1746 Extensions:
1745 Extension Commands:
1747 Extension Commands:
1746 $ hg help -c schemes
1748 $ hg help -c schemes
1747 abort: no such help topic: schemes
1749 abort: no such help topic: schemes
1748 (try 'hg help --keyword schemes')
1750 (try 'hg help --keyword schemes')
1749 [10]
1751 [10]
1750 $ hg help -e schemes |head -1
1752 $ hg help -e schemes |head -1
1751 schemes extension - extend schemes with shortcuts to repository swarms
1753 schemes extension - extend schemes with shortcuts to repository swarms
1752 $ hg help -c -k dates |grep -E '^(Topics|Extensions|Commands):'
1754 $ hg help -c -k dates |grep -E '^(Topics|Extensions|Commands):'
1753 Commands:
1755 Commands:
1754 $ hg help -e -k a |grep -E '^(Topics|Extensions|Commands):'
1756 $ hg help -e -k a |grep -E '^(Topics|Extensions|Commands):'
1755 Extensions:
1757 Extensions:
1756 $ hg help -e -c -k date |grep -E '^(Topics|Extensions|Commands):'
1758 $ hg help -e -c -k date |grep -E '^(Topics|Extensions|Commands):'
1757 Extensions:
1759 Extensions:
1758 Commands:
1760 Commands:
1759 $ hg help -c commit > /dev/null
1761 $ hg help -c commit > /dev/null
1760 $ hg help -e -c commit > /dev/null
1762 $ hg help -e -c commit > /dev/null
1761 $ hg help -e commit
1763 $ hg help -e commit
1762 abort: no such help topic: commit
1764 abort: no such help topic: commit
1763 (try 'hg help --keyword commit')
1765 (try 'hg help --keyword commit')
1764 [10]
1766 [10]
1765
1767
1766 Test keyword search help
1768 Test keyword search help
1767
1769
1768 $ cat > prefixedname.py <<EOF
1770 $ cat > prefixedname.py <<EOF
1769 > '''matched against word "clone"
1771 > '''matched against word "clone"
1770 > '''
1772 > '''
1771 > EOF
1773 > EOF
1772 $ echo '[extensions]' >> $HGRCPATH
1774 $ echo '[extensions]' >> $HGRCPATH
1773 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1775 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1774 $ hg help -k clone
1776 $ hg help -k clone
1775 Topics:
1777 Topics:
1776
1778
1777 config Configuration Files
1779 config Configuration Files
1778 extensions Using Additional Features
1780 extensions Using Additional Features
1779 glossary Glossary
1781 glossary Glossary
1780 phases Working with Phases
1782 phases Working with Phases
1781 subrepos Subrepositories
1783 subrepos Subrepositories
1782 urls URL Paths
1784 urls URL Paths
1783
1785
1784 Commands:
1786 Commands:
1785
1787
1786 bookmarks create a new bookmark or list existing bookmarks
1788 bookmarks create a new bookmark or list existing bookmarks
1787 clone make a copy of an existing repository
1789 clone make a copy of an existing repository
1788 paths show aliases for remote repositories
1790 paths show aliases for remote repositories
1789 pull pull changes from the specified source
1791 pull pull changes from the specified source
1790 update update working directory (or switch revisions)
1792 update update working directory (or switch revisions)
1791
1793
1792 Extensions:
1794 Extensions:
1793
1795
1794 clonebundles advertise pre-generated bundles to seed clones
1796 clonebundles advertise pre-generated bundles to seed clones
1795 narrow create clones which fetch history data for subset of files
1797 narrow create clones which fetch history data for subset of files
1796 (EXPERIMENTAL)
1798 (EXPERIMENTAL)
1797 prefixedname matched against word "clone"
1799 prefixedname matched against word "clone"
1798 relink recreates hardlinks between repository clones
1800 relink recreates hardlinks between repository clones
1799
1801
1800 Extension Commands:
1802 Extension Commands:
1801
1803
1802 admin::clone-bundles-clear remove existing clone bundle caches
1804 admin::clone-bundles-clear remove existing clone bundle caches
1803 admin::clone-bundles-refresh generate clone bundles according to the
1805 admin::clone-bundles-refresh generate clone bundles according to the
1804 configuration
1806 configuration
1805 qclone clone main and patch repository at same time
1807 qclone clone main and patch repository at same time
1806
1808
1807 Test unfound topic
1809 Test unfound topic
1808
1810
1809 $ hg help nonexistingtopicthatwillneverexisteverever
1811 $ hg help nonexistingtopicthatwillneverexisteverever
1810 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1812 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1811 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1813 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1812 [10]
1814 [10]
1813
1815
1814 Test unfound keyword
1816 Test unfound keyword
1815
1817
1816 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1818 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1817 abort: no matches
1819 abort: no matches
1818 (try 'hg help' for a list of topics)
1820 (try 'hg help' for a list of topics)
1819 [10]
1821 [10]
1820
1822
1821 Test omit indicating for help
1823 Test omit indicating for help
1822
1824
1823 $ cat > addverboseitems.py <<EOF
1825 $ cat > addverboseitems.py <<EOF
1824 > r'''extension to test omit indicating.
1826 > r'''extension to test omit indicating.
1825 >
1827 >
1826 > This paragraph is never omitted (for extension)
1828 > This paragraph is never omitted (for extension)
1827 >
1829 >
1828 > .. container:: verbose
1830 > .. container:: verbose
1829 >
1831 >
1830 > This paragraph is omitted,
1832 > This paragraph is omitted,
1831 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1833 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1832 >
1834 >
1833 > This paragraph is never omitted, too (for extension)
1835 > This paragraph is never omitted, too (for extension)
1834 > '''
1836 > '''
1835 > from mercurial import commands, help
1837 > from mercurial import commands, help
1836 > testtopic = br"""This paragraph is never omitted (for topic).
1838 > testtopic = br"""This paragraph is never omitted (for topic).
1837 >
1839 >
1838 > .. container:: verbose
1840 > .. container:: verbose
1839 >
1841 >
1840 > This paragraph is omitted,
1842 > This paragraph is omitted,
1841 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1843 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1842 >
1844 >
1843 > This paragraph is never omitted, too (for topic)
1845 > This paragraph is never omitted, too (for topic)
1844 > """
1846 > """
1845 > def extsetup(ui):
1847 > def extsetup(ui):
1846 > help.helptable.append(([b"topic-containing-verbose"],
1848 > help.helptable.append(([b"topic-containing-verbose"],
1847 > b"This is the topic to test omit indicating.",
1849 > b"This is the topic to test omit indicating.",
1848 > lambda ui: testtopic))
1850 > lambda ui: testtopic))
1849 > EOF
1851 > EOF
1850 $ echo '[extensions]' >> $HGRCPATH
1852 $ echo '[extensions]' >> $HGRCPATH
1851 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1853 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1852 $ hg help addverboseitems
1854 $ hg help addverboseitems
1853 addverboseitems extension - extension to test omit indicating.
1855 addverboseitems extension - extension to test omit indicating.
1854
1856
1855 This paragraph is never omitted (for extension)
1857 This paragraph is never omitted (for extension)
1856
1858
1857 This paragraph is never omitted, too (for extension)
1859 This paragraph is never omitted, too (for extension)
1858
1860
1859 (some details hidden, use --verbose to show complete help)
1861 (some details hidden, use --verbose to show complete help)
1860
1862
1861 no commands defined
1863 no commands defined
1862 $ hg help -v addverboseitems
1864 $ hg help -v addverboseitems
1863 addverboseitems extension - extension to test omit indicating.
1865 addverboseitems extension - extension to test omit indicating.
1864
1866
1865 This paragraph is never omitted (for extension)
1867 This paragraph is never omitted (for extension)
1866
1868
1867 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1869 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1868 extension)
1870 extension)
1869
1871
1870 This paragraph is never omitted, too (for extension)
1872 This paragraph is never omitted, too (for extension)
1871
1873
1872 no commands defined
1874 no commands defined
1873 $ hg help topic-containing-verbose
1875 $ hg help topic-containing-verbose
1874 This is the topic to test omit indicating.
1876 This is the topic to test omit indicating.
1875 """"""""""""""""""""""""""""""""""""""""""
1877 """"""""""""""""""""""""""""""""""""""""""
1876
1878
1877 This paragraph is never omitted (for topic).
1879 This paragraph is never omitted (for topic).
1878
1880
1879 This paragraph is never omitted, too (for topic)
1881 This paragraph is never omitted, too (for topic)
1880
1882
1881 (some details hidden, use --verbose to show complete help)
1883 (some details hidden, use --verbose to show complete help)
1882 $ hg help -v topic-containing-verbose
1884 $ hg help -v topic-containing-verbose
1883 This is the topic to test omit indicating.
1885 This is the topic to test omit indicating.
1884 """"""""""""""""""""""""""""""""""""""""""
1886 """"""""""""""""""""""""""""""""""""""""""
1885
1887
1886 This paragraph is never omitted (for topic).
1888 This paragraph is never omitted (for topic).
1887
1889
1888 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1890 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1889 topic)
1891 topic)
1890
1892
1891 This paragraph is never omitted, too (for topic)
1893 This paragraph is never omitted, too (for topic)
1892
1894
1893 Test section lookup
1895 Test section lookup
1894
1896
1895 $ hg help revset.merge
1897 $ hg help revset.merge
1896 "merge()"
1898 "merge()"
1897 Changeset is a merge changeset.
1899 Changeset is a merge changeset.
1898
1900
1899 $ hg help glossary.dag
1901 $ hg help glossary.dag
1900 DAG
1902 DAG
1901 The repository of changesets of a distributed version control system
1903 The repository of changesets of a distributed version control system
1902 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1904 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1903 of nodes and edges, where nodes correspond to changesets and edges
1905 of nodes and edges, where nodes correspond to changesets and edges
1904 imply a parent -> child relation. This graph can be visualized by
1906 imply a parent -> child relation. This graph can be visualized by
1905 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1907 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1906 limited by the requirement for children to have at most two parents.
1908 limited by the requirement for children to have at most two parents.
1907
1909
1908
1910
1909 $ hg help hgrc.paths
1911 $ hg help hgrc.paths
1910 "paths"
1912 "paths"
1911 -------
1913 -------
1912
1914
1913 Assigns symbolic names and behavior to repositories.
1915 Assigns symbolic names and behavior to repositories.
1914
1916
1915 Options are symbolic names defining the URL or directory that is the
1917 Options are symbolic names defining the URL or directory that is the
1916 location of the repository. Example:
1918 location of the repository. Example:
1917
1919
1918 [paths]
1920 [paths]
1919 my_server = https://example.com/my_repo
1921 my_server = https://example.com/my_repo
1920 local_path = /home/me/repo
1922 local_path = /home/me/repo
1921
1923
1922 These symbolic names can be used from the command line. To pull from
1924 These symbolic names can be used from the command line. To pull from
1923 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1925 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1924 local_path'. You can check 'hg help urls' for details about valid URLs.
1926 local_path'. You can check 'hg help urls' for details about valid URLs.
1925
1927
1926 Options containing colons (":") denote sub-options that can influence
1928 Options containing colons (":") denote sub-options that can influence
1927 behavior for that specific path. Example:
1929 behavior for that specific path. Example:
1928
1930
1929 [paths]
1931 [paths]
1930 my_server = https://example.com/my_path
1932 my_server = https://example.com/my_path
1931 my_server:pushurl = ssh://example.com/my_path
1933 my_server:pushurl = ssh://example.com/my_path
1932
1934
1933 Paths using the 'path://otherpath' scheme will inherit the sub-options
1935 Paths using the 'path://otherpath' scheme will inherit the sub-options
1934 value from the path they point to.
1936 value from the path they point to.
1935
1937
1936 The following sub-options can be defined:
1938 The following sub-options can be defined:
1937
1939
1938 "multi-urls"
1940 "multi-urls"
1939 A boolean option. When enabled the value of the '[paths]' entry will be
1941 A boolean option. When enabled the value of the '[paths]' entry will be
1940 parsed as a list and the alias will resolve to multiple destination. If
1942 parsed as a list and the alias will resolve to multiple destination. If
1941 some of the list entry use the 'path://' syntax, the suboption will be
1943 some of the list entry use the 'path://' syntax, the suboption will be
1942 inherited individually.
1944 inherited individually.
1943
1945
1944 "pushurl"
1946 "pushurl"
1945 The URL to use for push operations. If not defined, the location
1947 The URL to use for push operations. If not defined, the location
1946 defined by the path's main entry is used.
1948 defined by the path's main entry is used.
1947
1949
1948 "pushrev"
1950 "pushrev"
1949 A revset defining which revisions to push by default.
1951 A revset defining which revisions to push by default.
1950
1952
1951 When 'hg push' is executed without a "-r" argument, the revset defined
1953 When 'hg push' is executed without a "-r" argument, the revset defined
1952 by this sub-option is evaluated to determine what to push.
1954 by this sub-option is evaluated to determine what to push.
1953
1955
1954 For example, a value of "." will push the working directory's revision
1956 For example, a value of "." will push the working directory's revision
1955 by default.
1957 by default.
1956
1958
1957 Revsets specifying bookmarks will not result in the bookmark being
1959 Revsets specifying bookmarks will not result in the bookmark being
1958 pushed.
1960 pushed.
1959
1961
1960 "bookmarks.mode"
1962 "bookmarks.mode"
1961 How bookmark will be dealt during the exchange. It support the following
1963 How bookmark will be dealt during the exchange. It support the following
1962 value
1964 value
1963
1965
1964 - "default": the default behavior, local and remote bookmarks are
1966 - "default": the default behavior, local and remote bookmarks are
1965 "merged" on push/pull.
1967 "merged" on push/pull.
1966 - "mirror": when pulling, replace local bookmarks by remote bookmarks.
1968 - "mirror": when pulling, replace local bookmarks by remote bookmarks.
1967 This is useful to replicate a repository, or as an optimization.
1969 This is useful to replicate a repository, or as an optimization.
1968 - "ignore": ignore bookmarks during exchange. (This currently only
1970 - "ignore": ignore bookmarks during exchange. (This currently only
1969 affect pulling)
1971 affect pulling)
1970
1972
1971 The following special named paths exist:
1973 The following special named paths exist:
1972
1974
1973 "default"
1975 "default"
1974 The URL or directory to use when no source or remote is specified.
1976 The URL or directory to use when no source or remote is specified.
1975
1977
1976 'hg clone' will automatically define this path to the location the
1978 'hg clone' will automatically define this path to the location the
1977 repository was cloned from.
1979 repository was cloned from.
1978
1980
1979 "default-push"
1981 "default-push"
1980 (deprecated) The URL or directory for the default 'hg push' location.
1982 (deprecated) The URL or directory for the default 'hg push' location.
1981 "default:pushurl" should be used instead.
1983 "default:pushurl" should be used instead.
1982
1984
1983 $ hg help glossary.mcguffin
1985 $ hg help glossary.mcguffin
1984 abort: help section not found: glossary.mcguffin
1986 abort: help section not found: glossary.mcguffin
1985 [10]
1987 [10]
1986
1988
1987 $ hg help glossary.mc.guffin
1989 $ hg help glossary.mc.guffin
1988 abort: help section not found: glossary.mc.guffin
1990 abort: help section not found: glossary.mc.guffin
1989 [10]
1991 [10]
1990
1992
1991 $ hg help template.files
1993 $ hg help template.files
1992 files List of strings. All files modified, added, or removed by
1994 files List of strings. All files modified, added, or removed by
1993 this changeset.
1995 this changeset.
1994 files(pattern)
1996 files(pattern)
1995 All files of the current changeset matching the pattern. See
1997 All files of the current changeset matching the pattern. See
1996 'hg help patterns'.
1998 'hg help patterns'.
1997
1999
1998 Test section lookup by translated message
2000 Test section lookup by translated message
1999
2001
2000 str.lower() instead of encoding.lower(str) on translated message might
2002 str.lower() instead of encoding.lower(str) on translated message might
2001 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
2003 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
2002 as the second or later byte of multi-byte character.
2004 as the second or later byte of multi-byte character.
2003
2005
2004 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
2006 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
2005 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
2007 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
2006 replacement makes message meaningless.
2008 replacement makes message meaningless.
2007
2009
2008 This tests that section lookup by translated string isn't broken by
2010 This tests that section lookup by translated string isn't broken by
2009 such str.lower().
2011 such str.lower().
2010
2012
2011 $ "$PYTHON" <<EOF
2013 $ "$PYTHON" <<EOF
2012 > def escape(s):
2014 > def escape(s):
2013 > return b''.join(br'\\u%x' % ord(uc) for uc in s.decode('cp932'))
2015 > return b''.join(br'\\u%x' % ord(uc) for uc in s.decode('cp932'))
2014 > # translation of "record" in ja_JP.cp932
2016 > # translation of "record" in ja_JP.cp932
2015 > upper = b"\x8bL\x98^"
2017 > upper = b"\x8bL\x98^"
2016 > # str.lower()-ed section name should be treated as different one
2018 > # str.lower()-ed section name should be treated as different one
2017 > lower = b"\x8bl\x98^"
2019 > lower = b"\x8bl\x98^"
2018 > with open('ambiguous.py', 'wb') as fp:
2020 > with open('ambiguous.py', 'wb') as fp:
2019 > fp.write(b"""# ambiguous section names in ja_JP.cp932
2021 > fp.write(b"""# ambiguous section names in ja_JP.cp932
2020 > u'''summary of extension
2022 > u'''summary of extension
2021 >
2023 >
2022 > %s
2024 > %s
2023 > ----
2025 > ----
2024 >
2026 >
2025 > Upper name should show only this message
2027 > Upper name should show only this message
2026 >
2028 >
2027 > %s
2029 > %s
2028 > ----
2030 > ----
2029 >
2031 >
2030 > Lower name should show only this message
2032 > Lower name should show only this message
2031 >
2033 >
2032 > subsequent section
2034 > subsequent section
2033 > ------------------
2035 > ------------------
2034 >
2036 >
2035 > This should be hidden at 'hg help ambiguous' with section name.
2037 > This should be hidden at 'hg help ambiguous' with section name.
2036 > '''
2038 > '''
2037 > """ % (escape(upper), escape(lower)))
2039 > """ % (escape(upper), escape(lower)))
2038 > EOF
2040 > EOF
2039
2041
2040 $ cat >> $HGRCPATH <<EOF
2042 $ cat >> $HGRCPATH <<EOF
2041 > [extensions]
2043 > [extensions]
2042 > ambiguous = ./ambiguous.py
2044 > ambiguous = ./ambiguous.py
2043 > EOF
2045 > EOF
2044
2046
2045 $ "$PYTHON" <<EOF | sh
2047 $ "$PYTHON" <<EOF | sh
2046 > from mercurial.utils import procutil
2048 > from mercurial.utils import procutil
2047 > upper = b"\x8bL\x98^"
2049 > upper = b"\x8bL\x98^"
2048 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
2050 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
2049 > EOF
2051 > EOF
2050 \x8bL\x98^ (esc)
2052 \x8bL\x98^ (esc)
2051 ----
2053 ----
2052
2054
2053 Upper name should show only this message
2055 Upper name should show only this message
2054
2056
2055
2057
2056 $ "$PYTHON" <<EOF | sh
2058 $ "$PYTHON" <<EOF | sh
2057 > from mercurial.utils import procutil
2059 > from mercurial.utils import procutil
2058 > lower = b"\x8bl\x98^"
2060 > lower = b"\x8bl\x98^"
2059 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
2061 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
2060 > EOF
2062 > EOF
2061 \x8bl\x98^ (esc)
2063 \x8bl\x98^ (esc)
2062 ----
2064 ----
2063
2065
2064 Lower name should show only this message
2066 Lower name should show only this message
2065
2067
2066
2068
2067 $ cat >> $HGRCPATH <<EOF
2069 $ cat >> $HGRCPATH <<EOF
2068 > [extensions]
2070 > [extensions]
2069 > ambiguous = !
2071 > ambiguous = !
2070 > EOF
2072 > EOF
2071
2073
2072 Show help content of disabled extensions
2074 Show help content of disabled extensions
2073
2075
2074 $ cat >> $HGRCPATH <<EOF
2076 $ cat >> $HGRCPATH <<EOF
2075 > [extensions]
2077 > [extensions]
2076 > ambiguous = !./ambiguous.py
2078 > ambiguous = !./ambiguous.py
2077 > EOF
2079 > EOF
2078 $ hg help -e ambiguous
2080 $ hg help -e ambiguous
2079 ambiguous extension - (no help text available)
2081 ambiguous extension - (no help text available)
2080
2082
2081 (use 'hg help extensions' for information on enabling extensions)
2083 (use 'hg help extensions' for information on enabling extensions)
2082
2084
2083 Test dynamic list of merge tools only shows up once
2085 Test dynamic list of merge tools only shows up once
2084 $ hg help merge-tools
2086 $ hg help merge-tools
2085 Merge Tools
2087 Merge Tools
2086 """""""""""
2088 """""""""""
2087
2089
2088 To merge files Mercurial uses merge tools.
2090 To merge files Mercurial uses merge tools.
2089
2091
2090 A merge tool combines two different versions of a file into a merged file.
2092 A merge tool combines two different versions of a file into a merged file.
2091 Merge tools are given the two files and the greatest common ancestor of
2093 Merge tools are given the two files and the greatest common ancestor of
2092 the two file versions, so they can determine the changes made on both
2094 the two file versions, so they can determine the changes made on both
2093 branches.
2095 branches.
2094
2096
2095 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
2097 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
2096 backout' and in several extensions.
2098 backout' and in several extensions.
2097
2099
2098 Usually, the merge tool tries to automatically reconcile the files by
2100 Usually, the merge tool tries to automatically reconcile the files by
2099 combining all non-overlapping changes that occurred separately in the two
2101 combining all non-overlapping changes that occurred separately in the two
2100 different evolutions of the same initial base file. Furthermore, some
2102 different evolutions of the same initial base file. Furthermore, some
2101 interactive merge programs make it easier to manually resolve conflicting
2103 interactive merge programs make it easier to manually resolve conflicting
2102 merges, either in a graphical way, or by inserting some conflict markers.
2104 merges, either in a graphical way, or by inserting some conflict markers.
2103 Mercurial does not include any interactive merge programs but relies on
2105 Mercurial does not include any interactive merge programs but relies on
2104 external tools for that.
2106 external tools for that.
2105
2107
2106 Available merge tools
2108 Available merge tools
2107 =====================
2109 =====================
2108
2110
2109 External merge tools and their properties are configured in the merge-
2111 External merge tools and their properties are configured in the merge-
2110 tools configuration section - see hgrc(5) - but they can often just be
2112 tools configuration section - see hgrc(5) - but they can often just be
2111 named by their executable.
2113 named by their executable.
2112
2114
2113 A merge tool is generally usable if its executable can be found on the
2115 A merge tool is generally usable if its executable can be found on the
2114 system and if it can handle the merge. The executable is found if it is an
2116 system and if it can handle the merge. The executable is found if it is an
2115 absolute or relative executable path or the name of an application in the
2117 absolute or relative executable path or the name of an application in the
2116 executable search path. The tool is assumed to be able to handle the merge
2118 executable search path. The tool is assumed to be able to handle the merge
2117 if it can handle symlinks if the file is a symlink, if it can handle
2119 if it can handle symlinks if the file is a symlink, if it can handle
2118 binary files if the file is binary, and if a GUI is available if the tool
2120 binary files if the file is binary, and if a GUI is available if the tool
2119 requires a GUI.
2121 requires a GUI.
2120
2122
2121 There are some internal merge tools which can be used. The internal merge
2123 There are some internal merge tools which can be used. The internal merge
2122 tools are:
2124 tools are:
2123
2125
2124 ":dump"
2126 ":dump"
2125 Creates three versions of the files to merge, containing the contents of
2127 Creates three versions of the files to merge, containing the contents of
2126 local, other and base. These files can then be used to perform a merge
2128 local, other and base. These files can then be used to perform a merge
2127 manually. If the file to be merged is named "a.txt", these files will
2129 manually. If the file to be merged is named "a.txt", these files will
2128 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
2130 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
2129 they will be placed in the same directory as "a.txt".
2131 they will be placed in the same directory as "a.txt".
2130
2132
2131 This implies premerge. Therefore, files aren't dumped, if premerge runs
2133 This implies premerge. Therefore, files aren't dumped, if premerge runs
2132 successfully. Use :forcedump to forcibly write files out.
2134 successfully. Use :forcedump to forcibly write files out.
2133
2135
2134 (actual capabilities: binary, symlink)
2136 (actual capabilities: binary, symlink)
2135
2137
2136 ":fail"
2138 ":fail"
2137 Rather than attempting to merge files that were modified on both
2139 Rather than attempting to merge files that were modified on both
2138 branches, it marks them as unresolved. The resolve command must be used
2140 branches, it marks them as unresolved. The resolve command must be used
2139 to resolve these conflicts.
2141 to resolve these conflicts.
2140
2142
2141 (actual capabilities: binary, symlink)
2143 (actual capabilities: binary, symlink)
2142
2144
2143 ":forcedump"
2145 ":forcedump"
2144 Creates three versions of the files as same as :dump, but omits
2146 Creates three versions of the files as same as :dump, but omits
2145 premerge.
2147 premerge.
2146
2148
2147 (actual capabilities: binary, symlink)
2149 (actual capabilities: binary, symlink)
2148
2150
2149 ":local"
2151 ":local"
2150 Uses the local 'p1()' version of files as the merged version.
2152 Uses the local 'p1()' version of files as the merged version.
2151
2153
2152 (actual capabilities: binary, symlink)
2154 (actual capabilities: binary, symlink)
2153
2155
2154 ":merge"
2156 ":merge"
2155 Uses the internal non-interactive simple merge algorithm for merging
2157 Uses the internal non-interactive simple merge algorithm for merging
2156 files. It will fail if there are any conflicts and leave markers in the
2158 files. It will fail if there are any conflicts and leave markers in the
2157 partially merged file. Markers will have two sections, one for each side
2159 partially merged file. Markers will have two sections, one for each side
2158 of merge.
2160 of merge.
2159
2161
2160 ":merge-local"
2162 ":merge-local"
2161 Like :merge, but resolve all conflicts non-interactively in favor of the
2163 Like :merge, but resolve all conflicts non-interactively in favor of the
2162 local 'p1()' changes.
2164 local 'p1()' changes.
2163
2165
2164 ":merge-other"
2166 ":merge-other"
2165 Like :merge, but resolve all conflicts non-interactively in favor of the
2167 Like :merge, but resolve all conflicts non-interactively in favor of the
2166 other 'p2()' changes.
2168 other 'p2()' changes.
2167
2169
2168 ":merge3"
2170 ":merge3"
2169 Uses the internal non-interactive simple merge algorithm for merging
2171 Uses the internal non-interactive simple merge algorithm for merging
2170 files. It will fail if there are any conflicts and leave markers in the
2172 files. It will fail if there are any conflicts and leave markers in the
2171 partially merged file. Marker will have three sections, one from each
2173 partially merged file. Marker will have three sections, one from each
2172 side of the merge and one for the base content.
2174 side of the merge and one for the base content.
2173
2175
2174 ":mergediff"
2176 ":mergediff"
2175 Uses the internal non-interactive simple merge algorithm for merging
2177 Uses the internal non-interactive simple merge algorithm for merging
2176 files. It will fail if there are any conflicts and leave markers in the
2178 files. It will fail if there are any conflicts and leave markers in the
2177 partially merged file. The marker will have two sections, one with the
2179 partially merged file. The marker will have two sections, one with the
2178 content from one side of the merge, and one with a diff from the base
2180 content from one side of the merge, and one with a diff from the base
2179 content to the content on the other side. (experimental)
2181 content to the content on the other side. (experimental)
2180
2182
2181 ":other"
2183 ":other"
2182 Uses the other 'p2()' version of files as the merged version.
2184 Uses the other 'p2()' version of files as the merged version.
2183
2185
2184 (actual capabilities: binary, symlink)
2186 (actual capabilities: binary, symlink)
2185
2187
2186 ":prompt"
2188 ":prompt"
2187 Asks the user which of the local 'p1()' or the other 'p2()' version to
2189 Asks the user which of the local 'p1()' or the other 'p2()' version to
2188 keep as the merged version.
2190 keep as the merged version.
2189
2191
2190 (actual capabilities: binary, symlink)
2192 (actual capabilities: binary, symlink)
2191
2193
2192 ":tagmerge"
2194 ":tagmerge"
2193 Uses the internal tag merge algorithm (experimental).
2195 Uses the internal tag merge algorithm (experimental).
2194
2196
2195 ":union"
2197 ":union"
2196 Uses the internal non-interactive simple merge algorithm for merging
2198 Uses the internal non-interactive simple merge algorithm for merging
2197 files. It will use both local and other sides for conflict regions by
2199 files. It will use both local and other sides for conflict regions by
2198 adding local on top of other. No markers are inserted.
2200 adding local on top of other. No markers are inserted.
2199
2201
2200 ":union-other-first"
2202 ":union-other-first"
2201 Like :union, but add other on top of local.
2203 Like :union, but add other on top of local.
2202
2204
2203 Internal tools are always available and do not require a GUI but will by
2205 Internal tools are always available and do not require a GUI but will by
2204 default not handle symlinks or binary files. See next section for detail
2206 default not handle symlinks or binary files. See next section for detail
2205 about "actual capabilities" described above.
2207 about "actual capabilities" described above.
2206
2208
2207 Choosing a merge tool
2209 Choosing a merge tool
2208 =====================
2210 =====================
2209
2211
2210 Mercurial uses these rules when deciding which merge tool to use:
2212 Mercurial uses these rules when deciding which merge tool to use:
2211
2213
2212 1. If a tool has been specified with the --tool option to merge or
2214 1. If a tool has been specified with the --tool option to merge or
2213 resolve, it is used. If it is the name of a tool in the merge-tools
2215 resolve, it is used. If it is the name of a tool in the merge-tools
2214 configuration, its configuration is used. Otherwise the specified tool
2216 configuration, its configuration is used. Otherwise the specified tool
2215 must be executable by the shell.
2217 must be executable by the shell.
2216 2. If the "HGMERGE" environment variable is present, its value is used and
2218 2. If the "HGMERGE" environment variable is present, its value is used and
2217 must be executable by the shell.
2219 must be executable by the shell.
2218 3. If the filename of the file to be merged matches any of the patterns in
2220 3. If the filename of the file to be merged matches any of the patterns in
2219 the merge-patterns configuration section, the first usable merge tool
2221 the merge-patterns configuration section, the first usable merge tool
2220 corresponding to a matching pattern is used.
2222 corresponding to a matching pattern is used.
2221 4. If ui.merge is set it will be considered next. If the value is not the
2223 4. If ui.merge is set it will be considered next. If the value is not the
2222 name of a configured tool, the specified value is used and must be
2224 name of a configured tool, the specified value is used and must be
2223 executable by the shell. Otherwise the named tool is used if it is
2225 executable by the shell. Otherwise the named tool is used if it is
2224 usable.
2226 usable.
2225 5. If any usable merge tools are present in the merge-tools configuration
2227 5. If any usable merge tools are present in the merge-tools configuration
2226 section, the one with the highest priority is used.
2228 section, the one with the highest priority is used.
2227 6. If a program named "hgmerge" can be found on the system, it is used -
2229 6. If a program named "hgmerge" can be found on the system, it is used -
2228 but it will by default not be used for symlinks and binary files.
2230 but it will by default not be used for symlinks and binary files.
2229 7. If the file to be merged is not binary and is not a symlink, then
2231 7. If the file to be merged is not binary and is not a symlink, then
2230 internal ":merge" is used.
2232 internal ":merge" is used.
2231 8. Otherwise, ":prompt" is used.
2233 8. Otherwise, ":prompt" is used.
2232
2234
2233 For historical reason, Mercurial treats merge tools as below while
2235 For historical reason, Mercurial treats merge tools as below while
2234 examining rules above.
2236 examining rules above.
2235
2237
2236 step specified via binary symlink
2238 step specified via binary symlink
2237 ----------------------------------
2239 ----------------------------------
2238 1. --tool o/o o/o
2240 1. --tool o/o o/o
2239 2. HGMERGE o/o o/o
2241 2. HGMERGE o/o o/o
2240 3. merge-patterns o/o(*) x/?(*)
2242 3. merge-patterns o/o(*) x/?(*)
2241 4. ui.merge x/?(*) x/?(*)
2243 4. ui.merge x/?(*) x/?(*)
2242
2244
2243 Each capability column indicates Mercurial behavior for internal/external
2245 Each capability column indicates Mercurial behavior for internal/external
2244 merge tools at examining each rule.
2246 merge tools at examining each rule.
2245
2247
2246 - "o": "assume that a tool has capability"
2248 - "o": "assume that a tool has capability"
2247 - "x": "assume that a tool does not have capability"
2249 - "x": "assume that a tool does not have capability"
2248 - "?": "check actual capability of a tool"
2250 - "?": "check actual capability of a tool"
2249
2251
2250 If "merge.strict-capability-check" configuration is true, Mercurial checks
2252 If "merge.strict-capability-check" configuration is true, Mercurial checks
2251 capabilities of merge tools strictly in (*) cases above (= each capability
2253 capabilities of merge tools strictly in (*) cases above (= each capability
2252 column becomes "?/?"). It is false by default for backward compatibility.
2254 column becomes "?/?"). It is false by default for backward compatibility.
2253
2255
2254 Note:
2256 Note:
2255 After selecting a merge program, Mercurial will by default attempt to
2257 After selecting a merge program, Mercurial will by default attempt to
2256 merge the files using a simple merge algorithm first. Only if it
2258 merge the files using a simple merge algorithm first. Only if it
2257 doesn't succeed because of conflicting changes will Mercurial actually
2259 doesn't succeed because of conflicting changes will Mercurial actually
2258 execute the merge program. Whether to use the simple merge algorithm
2260 execute the merge program. Whether to use the simple merge algorithm
2259 first can be controlled by the premerge setting of the merge tool.
2261 first can be controlled by the premerge setting of the merge tool.
2260 Premerge is enabled by default unless the file is binary or a symlink.
2262 Premerge is enabled by default unless the file is binary or a symlink.
2261
2263
2262 See the merge-tools and ui sections of hgrc(5) for details on the
2264 See the merge-tools and ui sections of hgrc(5) for details on the
2263 configuration of merge tools.
2265 configuration of merge tools.
2264
2266
2265 Compression engines listed in `hg help bundlespec`
2267 Compression engines listed in `hg help bundlespec`
2266
2268
2267 $ hg help bundlespec | grep gzip
2269 $ hg help bundlespec | grep gzip
2268 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2270 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2269 An algorithm that produces smaller bundles than "gzip".
2271 An algorithm that produces smaller bundles than "gzip".
2270 This engine will likely produce smaller bundles than "gzip" but will be
2272 This engine will likely produce smaller bundles than "gzip" but will be
2271 "gzip"
2273 "gzip"
2272 better compression than "gzip". It also frequently yields better (?)
2274 better compression than "gzip". It also frequently yields better (?)
2273
2275
2274 Test usage of section marks in help documents
2276 Test usage of section marks in help documents
2275
2277
2276 $ cd "$TESTDIR"/../doc
2278 $ cd "$TESTDIR"/../doc
2277 $ "$PYTHON" check-seclevel.py
2279 $ "$PYTHON" check-seclevel.py
2278 $ cd $TESTTMP
2280 $ cd $TESTTMP
2279
2281
2280 #if serve
2282 #if serve
2281
2283
2282 Test the help pages in hgweb.
2284 Test the help pages in hgweb.
2283
2285
2284 Dish up an empty repo; serve it cold.
2286 Dish up an empty repo; serve it cold.
2285
2287
2286 $ hg init "$TESTTMP/test"
2288 $ hg init "$TESTTMP/test"
2287 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2289 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2288 $ cat hg.pid >> $DAEMON_PIDS
2290 $ cat hg.pid >> $DAEMON_PIDS
2289
2291
2290 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2292 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2291 200 Script output follows
2293 200 Script output follows
2292
2294
2293 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2295 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2294 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2296 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2295 <head>
2297 <head>
2296 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2298 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2297 <meta name="robots" content="index, nofollow" />
2299 <meta name="robots" content="index, nofollow" />
2298 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2300 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2299 <script type="text/javascript" src="/static/mercurial.js"></script>
2301 <script type="text/javascript" src="/static/mercurial.js"></script>
2300
2302
2301 <title>Help: Index</title>
2303 <title>Help: Index</title>
2302 </head>
2304 </head>
2303 <body>
2305 <body>
2304
2306
2305 <div class="container">
2307 <div class="container">
2306 <div class="menu">
2308 <div class="menu">
2307 <div class="logo">
2309 <div class="logo">
2308 <a href="https://mercurial-scm.org/">
2310 <a href="https://mercurial-scm.org/">
2309 <img src="/static/hglogo.png" alt="mercurial" /></a>
2311 <img src="/static/hglogo.png" alt="mercurial" /></a>
2310 </div>
2312 </div>
2311 <ul>
2313 <ul>
2312 <li><a href="/shortlog">log</a></li>
2314 <li><a href="/shortlog">log</a></li>
2313 <li><a href="/graph">graph</a></li>
2315 <li><a href="/graph">graph</a></li>
2314 <li><a href="/tags">tags</a></li>
2316 <li><a href="/tags">tags</a></li>
2315 <li><a href="/bookmarks">bookmarks</a></li>
2317 <li><a href="/bookmarks">bookmarks</a></li>
2316 <li><a href="/branches">branches</a></li>
2318 <li><a href="/branches">branches</a></li>
2317 </ul>
2319 </ul>
2318 <ul>
2320 <ul>
2319 <li class="active">help</li>
2321 <li class="active">help</li>
2320 </ul>
2322 </ul>
2321 </div>
2323 </div>
2322
2324
2323 <div class="main">
2325 <div class="main">
2324 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2326 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2325
2327
2326 <form class="search" action="/log">
2328 <form class="search" action="/log">
2327
2329
2328 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2330 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2329 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2331 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2330 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2332 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2331 </form>
2333 </form>
2332 <table class="bigtable">
2334 <table class="bigtable">
2333 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2335 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2334
2336
2335 <tr><td>
2337 <tr><td>
2336 <a href="/help/bundlespec">
2338 <a href="/help/bundlespec">
2337 bundlespec
2339 bundlespec
2338 </a>
2340 </a>
2339 </td><td>
2341 </td><td>
2340 Bundle File Formats
2342 Bundle File Formats
2341 </td></tr>
2343 </td></tr>
2342 <tr><td>
2344 <tr><td>
2343 <a href="/help/color">
2345 <a href="/help/color">
2344 color
2346 color
2345 </a>
2347 </a>
2346 </td><td>
2348 </td><td>
2347 Colorizing Outputs
2349 Colorizing Outputs
2348 </td></tr>
2350 </td></tr>
2349 <tr><td>
2351 <tr><td>
2350 <a href="/help/config">
2352 <a href="/help/config">
2351 config
2353 config
2352 </a>
2354 </a>
2353 </td><td>
2355 </td><td>
2354 Configuration Files
2356 Configuration Files
2355 </td></tr>
2357 </td></tr>
2356 <tr><td>
2358 <tr><td>
2357 <a href="/help/dates">
2359 <a href="/help/dates">
2358 dates
2360 dates
2359 </a>
2361 </a>
2360 </td><td>
2362 </td><td>
2361 Date Formats
2363 Date Formats
2362 </td></tr>
2364 </td></tr>
2363 <tr><td>
2365 <tr><td>
2364 <a href="/help/deprecated">
2366 <a href="/help/deprecated">
2365 deprecated
2367 deprecated
2366 </a>
2368 </a>
2367 </td><td>
2369 </td><td>
2368 Deprecated Features
2370 Deprecated Features
2369 </td></tr>
2371 </td></tr>
2370 <tr><td>
2372 <tr><td>
2371 <a href="/help/diffs">
2373 <a href="/help/diffs">
2372 diffs
2374 diffs
2373 </a>
2375 </a>
2374 </td><td>
2376 </td><td>
2375 Diff Formats
2377 Diff Formats
2376 </td></tr>
2378 </td></tr>
2377 <tr><td>
2379 <tr><td>
2378 <a href="/help/environment">
2380 <a href="/help/environment">
2379 environment
2381 environment
2380 </a>
2382 </a>
2381 </td><td>
2383 </td><td>
2382 Environment Variables
2384 Environment Variables
2383 </td></tr>
2385 </td></tr>
2384 <tr><td>
2386 <tr><td>
2385 <a href="/help/evolution">
2387 <a href="/help/evolution">
2386 evolution
2388 evolution
2387 </a>
2389 </a>
2388 </td><td>
2390 </td><td>
2389 Safely rewriting history (EXPERIMENTAL)
2391 Safely rewriting history (EXPERIMENTAL)
2390 </td></tr>
2392 </td></tr>
2391 <tr><td>
2393 <tr><td>
2392 <a href="/help/extensions">
2394 <a href="/help/extensions">
2393 extensions
2395 extensions
2394 </a>
2396 </a>
2395 </td><td>
2397 </td><td>
2396 Using Additional Features
2398 Using Additional Features
2397 </td></tr>
2399 </td></tr>
2398 <tr><td>
2400 <tr><td>
2399 <a href="/help/filesets">
2401 <a href="/help/filesets">
2400 filesets
2402 filesets
2401 </a>
2403 </a>
2402 </td><td>
2404 </td><td>
2403 Specifying File Sets
2405 Specifying File Sets
2404 </td></tr>
2406 </td></tr>
2405 <tr><td>
2407 <tr><td>
2406 <a href="/help/flags">
2408 <a href="/help/flags">
2407 flags
2409 flags
2408 </a>
2410 </a>
2409 </td><td>
2411 </td><td>
2410 Command-line flags
2412 Command-line flags
2411 </td></tr>
2413 </td></tr>
2412 <tr><td>
2414 <tr><td>
2413 <a href="/help/glossary">
2415 <a href="/help/glossary">
2414 glossary
2416 glossary
2415 </a>
2417 </a>
2416 </td><td>
2418 </td><td>
2417 Glossary
2419 Glossary
2418 </td></tr>
2420 </td></tr>
2419 <tr><td>
2421 <tr><td>
2420 <a href="/help/hgignore">
2422 <a href="/help/hgignore">
2421 hgignore
2423 hgignore
2422 </a>
2424 </a>
2423 </td><td>
2425 </td><td>
2424 Syntax for Mercurial Ignore Files
2426 Syntax for Mercurial Ignore Files
2425 </td></tr>
2427 </td></tr>
2426 <tr><td>
2428 <tr><td>
2427 <a href="/help/hgweb">
2429 <a href="/help/hgweb">
2428 hgweb
2430 hgweb
2429 </a>
2431 </a>
2430 </td><td>
2432 </td><td>
2431 Configuring hgweb
2433 Configuring hgweb
2432 </td></tr>
2434 </td></tr>
2433 <tr><td>
2435 <tr><td>
2434 <a href="/help/internals">
2436 <a href="/help/internals">
2435 internals
2437 internals
2436 </a>
2438 </a>
2437 </td><td>
2439 </td><td>
2438 Technical implementation topics
2440 Technical implementation topics
2439 </td></tr>
2441 </td></tr>
2440 <tr><td>
2442 <tr><td>
2441 <a href="/help/merge-tools">
2443 <a href="/help/merge-tools">
2442 merge-tools
2444 merge-tools
2443 </a>
2445 </a>
2444 </td><td>
2446 </td><td>
2445 Merge Tools
2447 Merge Tools
2446 </td></tr>
2448 </td></tr>
2447 <tr><td>
2449 <tr><td>
2448 <a href="/help/pager">
2450 <a href="/help/pager">
2449 pager
2451 pager
2450 </a>
2452 </a>
2451 </td><td>
2453 </td><td>
2452 Pager Support
2454 Pager Support
2453 </td></tr>
2455 </td></tr>
2454 <tr><td>
2456 <tr><td>
2455 <a href="/help/patterns">
2457 <a href="/help/patterns">
2456 patterns
2458 patterns
2457 </a>
2459 </a>
2458 </td><td>
2460 </td><td>
2459 File Name Patterns
2461 File Name Patterns
2460 </td></tr>
2462 </td></tr>
2461 <tr><td>
2463 <tr><td>
2462 <a href="/help/phases">
2464 <a href="/help/phases">
2463 phases
2465 phases
2464 </a>
2466 </a>
2465 </td><td>
2467 </td><td>
2466 Working with Phases
2468 Working with Phases
2467 </td></tr>
2469 </td></tr>
2468 <tr><td>
2470 <tr><td>
2469 <a href="/help/revisions">
2471 <a href="/help/revisions">
2470 revisions
2472 revisions
2471 </a>
2473 </a>
2472 </td><td>
2474 </td><td>
2473 Specifying Revisions
2475 Specifying Revisions
2474 </td></tr>
2476 </td></tr>
2475 <tr><td>
2477 <tr><td>
2476 <a href="/help/rust">
2478 <a href="/help/rust">
2477 rust
2479 rust
2478 </a>
2480 </a>
2479 </td><td>
2481 </td><td>
2480 Rust in Mercurial
2482 Rust in Mercurial
2481 </td></tr>
2483 </td></tr>
2482 <tr><td>
2484 <tr><td>
2483 <a href="/help/scripting">
2485 <a href="/help/scripting">
2484 scripting
2486 scripting
2485 </a>
2487 </a>
2486 </td><td>
2488 </td><td>
2487 Using Mercurial from scripts and automation
2489 Using Mercurial from scripts and automation
2488 </td></tr>
2490 </td></tr>
2489 <tr><td>
2491 <tr><td>
2490 <a href="/help/subrepos">
2492 <a href="/help/subrepos">
2491 subrepos
2493 subrepos
2492 </a>
2494 </a>
2493 </td><td>
2495 </td><td>
2494 Subrepositories
2496 Subrepositories
2495 </td></tr>
2497 </td></tr>
2496 <tr><td>
2498 <tr><td>
2497 <a href="/help/templating">
2499 <a href="/help/templating">
2498 templating
2500 templating
2499 </a>
2501 </a>
2500 </td><td>
2502 </td><td>
2501 Template Usage
2503 Template Usage
2502 </td></tr>
2504 </td></tr>
2503 <tr><td>
2505 <tr><td>
2504 <a href="/help/urls">
2506 <a href="/help/urls">
2505 urls
2507 urls
2506 </a>
2508 </a>
2507 </td><td>
2509 </td><td>
2508 URL Paths
2510 URL Paths
2509 </td></tr>
2511 </td></tr>
2510 <tr><td>
2512 <tr><td>
2511 <a href="/help/topic-containing-verbose">
2513 <a href="/help/topic-containing-verbose">
2512 topic-containing-verbose
2514 topic-containing-verbose
2513 </a>
2515 </a>
2514 </td><td>
2516 </td><td>
2515 This is the topic to test omit indicating.
2517 This is the topic to test omit indicating.
2516 </td></tr>
2518 </td></tr>
2517
2519
2518
2520
2519 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2521 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2520
2522
2521 <tr><td>
2523 <tr><td>
2522 <a href="/help/abort">
2524 <a href="/help/abort">
2523 abort
2525 abort
2524 </a>
2526 </a>
2525 </td><td>
2527 </td><td>
2526 abort an unfinished operation (EXPERIMENTAL)
2528 abort an unfinished operation (EXPERIMENTAL)
2527 </td></tr>
2529 </td></tr>
2528 <tr><td>
2530 <tr><td>
2529 <a href="/help/add">
2531 <a href="/help/add">
2530 add
2532 add
2531 </a>
2533 </a>
2532 </td><td>
2534 </td><td>
2533 add the specified files on the next commit
2535 add the specified files on the next commit
2534 </td></tr>
2536 </td></tr>
2535 <tr><td>
2537 <tr><td>
2536 <a href="/help/annotate">
2538 <a href="/help/annotate">
2537 annotate
2539 annotate
2538 </a>
2540 </a>
2539 </td><td>
2541 </td><td>
2540 show changeset information by line for each file
2542 show changeset information by line for each file
2541 </td></tr>
2543 </td></tr>
2542 <tr><td>
2544 <tr><td>
2543 <a href="/help/clone">
2545 <a href="/help/clone">
2544 clone
2546 clone
2545 </a>
2547 </a>
2546 </td><td>
2548 </td><td>
2547 make a copy of an existing repository
2549 make a copy of an existing repository
2548 </td></tr>
2550 </td></tr>
2549 <tr><td>
2551 <tr><td>
2550 <a href="/help/commit">
2552 <a href="/help/commit">
2551 commit
2553 commit
2552 </a>
2554 </a>
2553 </td><td>
2555 </td><td>
2554 commit the specified files or all outstanding changes
2556 commit the specified files or all outstanding changes
2555 </td></tr>
2557 </td></tr>
2556 <tr><td>
2558 <tr><td>
2557 <a href="/help/continue">
2559 <a href="/help/continue">
2558 continue
2560 continue
2559 </a>
2561 </a>
2560 </td><td>
2562 </td><td>
2561 resumes an interrupted operation (EXPERIMENTAL)
2563 resumes an interrupted operation (EXPERIMENTAL)
2562 </td></tr>
2564 </td></tr>
2563 <tr><td>
2565 <tr><td>
2564 <a href="/help/diff">
2566 <a href="/help/diff">
2565 diff
2567 diff
2566 </a>
2568 </a>
2567 </td><td>
2569 </td><td>
2568 diff repository (or selected files)
2570 diff repository (or selected files)
2569 </td></tr>
2571 </td></tr>
2570 <tr><td>
2572 <tr><td>
2571 <a href="/help/export">
2573 <a href="/help/export">
2572 export
2574 export
2573 </a>
2575 </a>
2574 </td><td>
2576 </td><td>
2575 dump the header and diffs for one or more changesets
2577 dump the header and diffs for one or more changesets
2576 </td></tr>
2578 </td></tr>
2577 <tr><td>
2579 <tr><td>
2578 <a href="/help/forget">
2580 <a href="/help/forget">
2579 forget
2581 forget
2580 </a>
2582 </a>
2581 </td><td>
2583 </td><td>
2582 forget the specified files on the next commit
2584 forget the specified files on the next commit
2583 </td></tr>
2585 </td></tr>
2584 <tr><td>
2586 <tr><td>
2585 <a href="/help/init">
2587 <a href="/help/init">
2586 init
2588 init
2587 </a>
2589 </a>
2588 </td><td>
2590 </td><td>
2589 create a new repository in the given directory
2591 create a new repository in the given directory
2590 </td></tr>
2592 </td></tr>
2591 <tr><td>
2593 <tr><td>
2592 <a href="/help/log">
2594 <a href="/help/log">
2593 log
2595 log
2594 </a>
2596 </a>
2595 </td><td>
2597 </td><td>
2596 show revision history of entire repository or files
2598 show revision history of entire repository or files
2597 </td></tr>
2599 </td></tr>
2598 <tr><td>
2600 <tr><td>
2599 <a href="/help/merge">
2601 <a href="/help/merge">
2600 merge
2602 merge
2601 </a>
2603 </a>
2602 </td><td>
2604 </td><td>
2603 merge another revision into working directory
2605 merge another revision into working directory
2604 </td></tr>
2606 </td></tr>
2605 <tr><td>
2607 <tr><td>
2606 <a href="/help/pull">
2608 <a href="/help/pull">
2607 pull
2609 pull
2608 </a>
2610 </a>
2609 </td><td>
2611 </td><td>
2610 pull changes from the specified source
2612 pull changes from the specified source
2611 </td></tr>
2613 </td></tr>
2612 <tr><td>
2614 <tr><td>
2613 <a href="/help/push">
2615 <a href="/help/push">
2614 push
2616 push
2615 </a>
2617 </a>
2616 </td><td>
2618 </td><td>
2617 push changes to the specified destination
2619 push changes to the specified destination
2618 </td></tr>
2620 </td></tr>
2619 <tr><td>
2621 <tr><td>
2620 <a href="/help/remove">
2622 <a href="/help/remove">
2621 remove
2623 remove
2622 </a>
2624 </a>
2623 </td><td>
2625 </td><td>
2624 remove the specified files on the next commit
2626 remove the specified files on the next commit
2625 </td></tr>
2627 </td></tr>
2626 <tr><td>
2628 <tr><td>
2627 <a href="/help/serve">
2629 <a href="/help/serve">
2628 serve
2630 serve
2629 </a>
2631 </a>
2630 </td><td>
2632 </td><td>
2631 start stand-alone webserver
2633 start stand-alone webserver
2632 </td></tr>
2634 </td></tr>
2633 <tr><td>
2635 <tr><td>
2634 <a href="/help/status">
2636 <a href="/help/status">
2635 status
2637 status
2636 </a>
2638 </a>
2637 </td><td>
2639 </td><td>
2638 show changed files in the working directory
2640 show changed files in the working directory
2639 </td></tr>
2641 </td></tr>
2640 <tr><td>
2642 <tr><td>
2641 <a href="/help/summary">
2643 <a href="/help/summary">
2642 summary
2644 summary
2643 </a>
2645 </a>
2644 </td><td>
2646 </td><td>
2645 summarize working directory state
2647 summarize working directory state
2646 </td></tr>
2648 </td></tr>
2647 <tr><td>
2649 <tr><td>
2648 <a href="/help/update">
2650 <a href="/help/update">
2649 update
2651 update
2650 </a>
2652 </a>
2651 </td><td>
2653 </td><td>
2652 update working directory (or switch revisions)
2654 update working directory (or switch revisions)
2653 </td></tr>
2655 </td></tr>
2654
2656
2655
2657
2656
2658
2657 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2659 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2658
2660
2659 <tr><td>
2661 <tr><td>
2660 <a href="/help/addremove">
2662 <a href="/help/addremove">
2661 addremove
2663 addremove
2662 </a>
2664 </a>
2663 </td><td>
2665 </td><td>
2664 add all new files, delete all missing files
2666 add all new files, delete all missing files
2665 </td></tr>
2667 </td></tr>
2666 <tr><td>
2668 <tr><td>
2667 <a href="/help/admin::verify">
2669 <a href="/help/admin::verify">
2668 admin::verify
2670 admin::verify
2669 </a>
2671 </a>
2670 </td><td>
2672 </td><td>
2671 verify the integrity of the repository
2673 verify the integrity of the repository
2672 </td></tr>
2674 </td></tr>
2673 <tr><td>
2675 <tr><td>
2674 <a href="/help/archive">
2676 <a href="/help/archive">
2675 archive
2677 archive
2676 </a>
2678 </a>
2677 </td><td>
2679 </td><td>
2678 create an unversioned archive of a repository revision
2680 create an unversioned archive of a repository revision
2679 </td></tr>
2681 </td></tr>
2680 <tr><td>
2682 <tr><td>
2681 <a href="/help/backout">
2683 <a href="/help/backout">
2682 backout
2684 backout
2683 </a>
2685 </a>
2684 </td><td>
2686 </td><td>
2685 reverse effect of earlier changeset
2687 reverse effect of earlier changeset
2686 </td></tr>
2688 </td></tr>
2687 <tr><td>
2689 <tr><td>
2688 <a href="/help/bisect">
2690 <a href="/help/bisect">
2689 bisect
2691 bisect
2690 </a>
2692 </a>
2691 </td><td>
2693 </td><td>
2692 subdivision search of changesets
2694 subdivision search of changesets
2693 </td></tr>
2695 </td></tr>
2694 <tr><td>
2696 <tr><td>
2695 <a href="/help/bookmarks">
2697 <a href="/help/bookmarks">
2696 bookmarks
2698 bookmarks
2697 </a>
2699 </a>
2698 </td><td>
2700 </td><td>
2699 create a new bookmark or list existing bookmarks
2701 create a new bookmark or list existing bookmarks
2700 </td></tr>
2702 </td></tr>
2701 <tr><td>
2703 <tr><td>
2702 <a href="/help/branch">
2704 <a href="/help/branch">
2703 branch
2705 branch
2704 </a>
2706 </a>
2705 </td><td>
2707 </td><td>
2706 set or show the current branch name
2708 set or show the current branch name
2707 </td></tr>
2709 </td></tr>
2708 <tr><td>
2710 <tr><td>
2709 <a href="/help/branches">
2711 <a href="/help/branches">
2710 branches
2712 branches
2711 </a>
2713 </a>
2712 </td><td>
2714 </td><td>
2713 list repository named branches
2715 list repository named branches
2714 </td></tr>
2716 </td></tr>
2715 <tr><td>
2717 <tr><td>
2716 <a href="/help/bundle">
2718 <a href="/help/bundle">
2717 bundle
2719 bundle
2718 </a>
2720 </a>
2719 </td><td>
2721 </td><td>
2720 create a bundle file
2722 create a bundle file
2721 </td></tr>
2723 </td></tr>
2722 <tr><td>
2724 <tr><td>
2723 <a href="/help/cat">
2725 <a href="/help/cat">
2724 cat
2726 cat
2725 </a>
2727 </a>
2726 </td><td>
2728 </td><td>
2727 output the current or given revision of files
2729 output the current or given revision of files
2728 </td></tr>
2730 </td></tr>
2729 <tr><td>
2731 <tr><td>
2730 <a href="/help/config">
2732 <a href="/help/config">
2731 config
2733 config
2732 </a>
2734 </a>
2733 </td><td>
2735 </td><td>
2734 show combined config settings from all hgrc files
2736 show combined config settings from all hgrc files
2735 </td></tr>
2737 </td></tr>
2736 <tr><td>
2738 <tr><td>
2737 <a href="/help/copy">
2739 <a href="/help/copy">
2738 copy
2740 copy
2739 </a>
2741 </a>
2740 </td><td>
2742 </td><td>
2741 mark files as copied for the next commit
2743 mark files as copied for the next commit
2742 </td></tr>
2744 </td></tr>
2743 <tr><td>
2745 <tr><td>
2744 <a href="/help/files">
2746 <a href="/help/files">
2745 files
2747 files
2746 </a>
2748 </a>
2747 </td><td>
2749 </td><td>
2748 list tracked files
2750 list tracked files
2749 </td></tr>
2751 </td></tr>
2750 <tr><td>
2752 <tr><td>
2751 <a href="/help/graft">
2753 <a href="/help/graft">
2752 graft
2754 graft
2753 </a>
2755 </a>
2754 </td><td>
2756 </td><td>
2755 copy changes from other branches onto the current branch
2757 copy changes from other branches onto the current branch
2756 </td></tr>
2758 </td></tr>
2757 <tr><td>
2759 <tr><td>
2758 <a href="/help/grep">
2760 <a href="/help/grep">
2759 grep
2761 grep
2760 </a>
2762 </a>
2761 </td><td>
2763 </td><td>
2762 search for a pattern in specified files
2764 search for a pattern in specified files
2763 </td></tr>
2765 </td></tr>
2764 <tr><td>
2766 <tr><td>
2765 <a href="/help/hashelp">
2767 <a href="/help/hashelp">
2766 hashelp
2768 hashelp
2767 </a>
2769 </a>
2768 </td><td>
2770 </td><td>
2769 Extension command's help
2771 Extension command's help
2770 </td></tr>
2772 </td></tr>
2771 <tr><td>
2773 <tr><td>
2772 <a href="/help/heads">
2774 <a href="/help/heads">
2773 heads
2775 heads
2774 </a>
2776 </a>
2775 </td><td>
2777 </td><td>
2776 show branch heads
2778 show branch heads
2777 </td></tr>
2779 </td></tr>
2778 <tr><td>
2780 <tr><td>
2779 <a href="/help/help">
2781 <a href="/help/help">
2780 help
2782 help
2781 </a>
2783 </a>
2782 </td><td>
2784 </td><td>
2783 show help for a given topic or a help overview
2785 show help for a given topic or a help overview
2784 </td></tr>
2786 </td></tr>
2785 <tr><td>
2787 <tr><td>
2786 <a href="/help/hgalias">
2788 <a href="/help/hgalias">
2787 hgalias
2789 hgalias
2788 </a>
2790 </a>
2789 </td><td>
2791 </td><td>
2790 My doc
2792 My doc
2791 </td></tr>
2793 </td></tr>
2792 <tr><td>
2794 <tr><td>
2793 <a href="/help/hgaliasnodoc">
2795 <a href="/help/hgaliasnodoc">
2794 hgaliasnodoc
2796 hgaliasnodoc
2795 </a>
2797 </a>
2796 </td><td>
2798 </td><td>
2797 summarize working directory state
2799 summarize working directory state
2798 </td></tr>
2800 </td></tr>
2799 <tr><td>
2801 <tr><td>
2800 <a href="/help/identify">
2802 <a href="/help/identify">
2801 identify
2803 identify
2802 </a>
2804 </a>
2803 </td><td>
2805 </td><td>
2804 identify the working directory or specified revision
2806 identify the working directory or specified revision
2805 </td></tr>
2807 </td></tr>
2806 <tr><td>
2808 <tr><td>
2807 <a href="/help/import">
2809 <a href="/help/import">
2808 import
2810 import
2809 </a>
2811 </a>
2810 </td><td>
2812 </td><td>
2811 import an ordered set of patches
2813 import an ordered set of patches
2812 </td></tr>
2814 </td></tr>
2813 <tr><td>
2815 <tr><td>
2814 <a href="/help/incoming">
2816 <a href="/help/incoming">
2815 incoming
2817 incoming
2816 </a>
2818 </a>
2817 </td><td>
2819 </td><td>
2818 show new changesets found in source
2820 show new changesets found in source
2819 </td></tr>
2821 </td></tr>
2820 <tr><td>
2822 <tr><td>
2821 <a href="/help/manifest">
2823 <a href="/help/manifest">
2822 manifest
2824 manifest
2823 </a>
2825 </a>
2824 </td><td>
2826 </td><td>
2825 output the current or given revision of the project manifest
2827 output the current or given revision of the project manifest
2826 </td></tr>
2828 </td></tr>
2827 <tr><td>
2829 <tr><td>
2828 <a href="/help/nohelp">
2830 <a href="/help/nohelp">
2829 nohelp
2831 nohelp
2830 </a>
2832 </a>
2831 </td><td>
2833 </td><td>
2832 (no help text available)
2834 (no help text available)
2833 </td></tr>
2835 </td></tr>
2834 <tr><td>
2836 <tr><td>
2835 <a href="/help/outgoing">
2837 <a href="/help/outgoing">
2836 outgoing
2838 outgoing
2837 </a>
2839 </a>
2838 </td><td>
2840 </td><td>
2839 show changesets not found in the destination
2841 show changesets not found in the destination
2840 </td></tr>
2842 </td></tr>
2841 <tr><td>
2843 <tr><td>
2842 <a href="/help/paths">
2844 <a href="/help/paths">
2843 paths
2845 paths
2844 </a>
2846 </a>
2845 </td><td>
2847 </td><td>
2846 show aliases for remote repositories
2848 show aliases for remote repositories
2847 </td></tr>
2849 </td></tr>
2848 <tr><td>
2850 <tr><td>
2849 <a href="/help/phase">
2851 <a href="/help/phase">
2850 phase
2852 phase
2851 </a>
2853 </a>
2852 </td><td>
2854 </td><td>
2853 set or show the current phase name
2855 set or show the current phase name
2854 </td></tr>
2856 </td></tr>
2855 <tr><td>
2857 <tr><td>
2856 <a href="/help/purge">
2858 <a href="/help/purge">
2857 purge
2859 purge
2858 </a>
2860 </a>
2859 </td><td>
2861 </td><td>
2860 removes files not tracked by Mercurial
2862 removes files not tracked by Mercurial
2861 </td></tr>
2863 </td></tr>
2862 <tr><td>
2864 <tr><td>
2863 <a href="/help/recover">
2865 <a href="/help/recover">
2864 recover
2866 recover
2865 </a>
2867 </a>
2866 </td><td>
2868 </td><td>
2867 roll back an interrupted transaction
2869 roll back an interrupted transaction
2868 </td></tr>
2870 </td></tr>
2869 <tr><td>
2871 <tr><td>
2870 <a href="/help/rename">
2872 <a href="/help/rename">
2871 rename
2873 rename
2872 </a>
2874 </a>
2873 </td><td>
2875 </td><td>
2874 rename files; equivalent of copy + remove
2876 rename files; equivalent of copy + remove
2875 </td></tr>
2877 </td></tr>
2876 <tr><td>
2878 <tr><td>
2877 <a href="/help/resolve">
2879 <a href="/help/resolve">
2878 resolve
2880 resolve
2879 </a>
2881 </a>
2880 </td><td>
2882 </td><td>
2881 redo merges or set/view the merge status of files
2883 redo merges or set/view the merge status of files
2882 </td></tr>
2884 </td></tr>
2883 <tr><td>
2885 <tr><td>
2884 <a href="/help/revert">
2886 <a href="/help/revert">
2885 revert
2887 revert
2886 </a>
2888 </a>
2887 </td><td>
2889 </td><td>
2888 restore files to their checkout state
2890 restore files to their checkout state
2889 </td></tr>
2891 </td></tr>
2890 <tr><td>
2892 <tr><td>
2891 <a href="/help/root">
2893 <a href="/help/root">
2892 root
2894 root
2893 </a>
2895 </a>
2894 </td><td>
2896 </td><td>
2895 print the root (top) of the current working directory
2897 print the root (top) of the current working directory
2896 </td></tr>
2898 </td></tr>
2897 <tr><td>
2899 <tr><td>
2898 <a href="/help/shellalias">
2900 <a href="/help/shellalias">
2899 shellalias
2901 shellalias
2900 </a>
2902 </a>
2901 </td><td>
2903 </td><td>
2902 (no help text available)
2904 (no help text available)
2903 </td></tr>
2905 </td></tr>
2904 <tr><td>
2906 <tr><td>
2905 <a href="/help/shelve">
2907 <a href="/help/shelve">
2906 shelve
2908 shelve
2907 </a>
2909 </a>
2908 </td><td>
2910 </td><td>
2909 save and set aside changes from the working directory
2911 save and set aside changes from the working directory
2910 </td></tr>
2912 </td></tr>
2911 <tr><td>
2913 <tr><td>
2912 <a href="/help/tag">
2914 <a href="/help/tag">
2913 tag
2915 tag
2914 </a>
2916 </a>
2915 </td><td>
2917 </td><td>
2916 add one or more tags for the current or given revision
2918 add one or more tags for the current or given revision
2917 </td></tr>
2919 </td></tr>
2918 <tr><td>
2920 <tr><td>
2919 <a href="/help/tags">
2921 <a href="/help/tags">
2920 tags
2922 tags
2921 </a>
2923 </a>
2922 </td><td>
2924 </td><td>
2923 list repository tags
2925 list repository tags
2924 </td></tr>
2926 </td></tr>
2925 <tr><td>
2927 <tr><td>
2926 <a href="/help/unbundle">
2928 <a href="/help/unbundle">
2927 unbundle
2929 unbundle
2928 </a>
2930 </a>
2929 </td><td>
2931 </td><td>
2930 apply one or more bundle files
2932 apply one or more bundle files
2931 </td></tr>
2933 </td></tr>
2932 <tr><td>
2934 <tr><td>
2933 <a href="/help/unshelve">
2935 <a href="/help/unshelve">
2934 unshelve
2936 unshelve
2935 </a>
2937 </a>
2936 </td><td>
2938 </td><td>
2937 restore a shelved change to the working directory
2939 restore a shelved change to the working directory
2938 </td></tr>
2940 </td></tr>
2939 <tr><td>
2941 <tr><td>
2940 <a href="/help/verify">
2942 <a href="/help/verify">
2941 verify
2943 verify
2942 </a>
2944 </a>
2943 </td><td>
2945 </td><td>
2944 verify the integrity of the repository
2946 verify the integrity of the repository
2945 </td></tr>
2947 </td></tr>
2946 <tr><td>
2948 <tr><td>
2947 <a href="/help/version">
2949 <a href="/help/version">
2948 version
2950 version
2949 </a>
2951 </a>
2950 </td><td>
2952 </td><td>
2951 output version and copyright information
2953 output version and copyright information
2952 </td></tr>
2954 </td></tr>
2953
2955
2954
2956
2955 </table>
2957 </table>
2956 </div>
2958 </div>
2957 </div>
2959 </div>
2958
2960
2959
2961
2960
2962
2961 </body>
2963 </body>
2962 </html>
2964 </html>
2963
2965
2964
2966
2965 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2967 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2966 200 Script output follows
2968 200 Script output follows
2967
2969
2968 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2970 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2969 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2971 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2970 <head>
2972 <head>
2971 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2973 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2972 <meta name="robots" content="index, nofollow" />
2974 <meta name="robots" content="index, nofollow" />
2973 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2975 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2974 <script type="text/javascript" src="/static/mercurial.js"></script>
2976 <script type="text/javascript" src="/static/mercurial.js"></script>
2975
2977
2976 <title>Help: add</title>
2978 <title>Help: add</title>
2977 </head>
2979 </head>
2978 <body>
2980 <body>
2979
2981
2980 <div class="container">
2982 <div class="container">
2981 <div class="menu">
2983 <div class="menu">
2982 <div class="logo">
2984 <div class="logo">
2983 <a href="https://mercurial-scm.org/">
2985 <a href="https://mercurial-scm.org/">
2984 <img src="/static/hglogo.png" alt="mercurial" /></a>
2986 <img src="/static/hglogo.png" alt="mercurial" /></a>
2985 </div>
2987 </div>
2986 <ul>
2988 <ul>
2987 <li><a href="/shortlog">log</a></li>
2989 <li><a href="/shortlog">log</a></li>
2988 <li><a href="/graph">graph</a></li>
2990 <li><a href="/graph">graph</a></li>
2989 <li><a href="/tags">tags</a></li>
2991 <li><a href="/tags">tags</a></li>
2990 <li><a href="/bookmarks">bookmarks</a></li>
2992 <li><a href="/bookmarks">bookmarks</a></li>
2991 <li><a href="/branches">branches</a></li>
2993 <li><a href="/branches">branches</a></li>
2992 </ul>
2994 </ul>
2993 <ul>
2995 <ul>
2994 <li class="active"><a href="/help">help</a></li>
2996 <li class="active"><a href="/help">help</a></li>
2995 </ul>
2997 </ul>
2996 </div>
2998 </div>
2997
2999
2998 <div class="main">
3000 <div class="main">
2999 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3001 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3000 <h3>Help: add</h3>
3002 <h3>Help: add</h3>
3001
3003
3002 <form class="search" action="/log">
3004 <form class="search" action="/log">
3003
3005
3004 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3006 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3005 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3007 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3006 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3008 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3007 </form>
3009 </form>
3008 <div id="doc">
3010 <div id="doc">
3009 <p>
3011 <p>
3010 hg add [OPTION]... [FILE]...
3012 hg add [OPTION]... [FILE]...
3011 </p>
3013 </p>
3012 <p>
3014 <p>
3013 add the specified files on the next commit
3015 add the specified files on the next commit
3014 </p>
3016 </p>
3015 <p>
3017 <p>
3016 Schedule files to be version controlled and added to the
3018 Schedule files to be version controlled and added to the
3017 repository.
3019 repository.
3018 </p>
3020 </p>
3019 <p>
3021 <p>
3020 The files will be added to the repository at the next commit. To
3022 The files will be added to the repository at the next commit. To
3021 undo an add before that, see 'hg forget'.
3023 undo an add before that, see 'hg forget'.
3022 </p>
3024 </p>
3023 <p>
3025 <p>
3024 If no names are given, add all files to the repository (except
3026 If no names are given, add all files to the repository (except
3025 files matching &quot;.hgignore&quot;).
3027 files matching &quot;.hgignore&quot;).
3026 </p>
3028 </p>
3027 <p>
3029 <p>
3028 Examples:
3030 Examples:
3029 </p>
3031 </p>
3030 <ul>
3032 <ul>
3031 <li> New (unknown) files are added automatically by 'hg add':
3033 <li> New (unknown) files are added automatically by 'hg add':
3032 <pre>
3034 <pre>
3033 \$ ls (re)
3035 \$ ls (re)
3034 foo.c
3036 foo.c
3035 \$ hg status (re)
3037 \$ hg status (re)
3036 ? foo.c
3038 ? foo.c
3037 \$ hg add (re)
3039 \$ hg add (re)
3038 adding foo.c
3040 adding foo.c
3039 \$ hg status (re)
3041 \$ hg status (re)
3040 A foo.c
3042 A foo.c
3041 </pre>
3043 </pre>
3042 <li> Specific files to be added can be specified:
3044 <li> Specific files to be added can be specified:
3043 <pre>
3045 <pre>
3044 \$ ls (re)
3046 \$ ls (re)
3045 bar.c foo.c
3047 bar.c foo.c
3046 \$ hg status (re)
3048 \$ hg status (re)
3047 ? bar.c
3049 ? bar.c
3048 ? foo.c
3050 ? foo.c
3049 \$ hg add bar.c (re)
3051 \$ hg add bar.c (re)
3050 \$ hg status (re)
3052 \$ hg status (re)
3051 A bar.c
3053 A bar.c
3052 ? foo.c
3054 ? foo.c
3053 </pre>
3055 </pre>
3054 </ul>
3056 </ul>
3055 <p>
3057 <p>
3056 Returns 0 if all files are successfully added.
3058 Returns 0 if all files are successfully added.
3057 </p>
3059 </p>
3058 <p>
3060 <p>
3059 options ([+] can be repeated):
3061 options ([+] can be repeated):
3060 </p>
3062 </p>
3061 <table>
3063 <table>
3062 <tr><td>-I</td>
3064 <tr><td>-I</td>
3063 <td>--include PATTERN [+]</td>
3065 <td>--include PATTERN [+]</td>
3064 <td>include names matching the given patterns</td></tr>
3066 <td>include names matching the given patterns</td></tr>
3065 <tr><td>-X</td>
3067 <tr><td>-X</td>
3066 <td>--exclude PATTERN [+]</td>
3068 <td>--exclude PATTERN [+]</td>
3067 <td>exclude names matching the given patterns</td></tr>
3069 <td>exclude names matching the given patterns</td></tr>
3068 <tr><td>-S</td>
3070 <tr><td>-S</td>
3069 <td>--subrepos</td>
3071 <td>--subrepos</td>
3070 <td>recurse into subrepositories</td></tr>
3072 <td>recurse into subrepositories</td></tr>
3071 <tr><td>-n</td>
3073 <tr><td>-n</td>
3072 <td>--dry-run</td>
3074 <td>--dry-run</td>
3073 <td>do not perform actions, just print output</td></tr>
3075 <td>do not perform actions, just print output</td></tr>
3074 </table>
3076 </table>
3075 <p>
3077 <p>
3076 global options ([+] can be repeated):
3078 global options ([+] can be repeated):
3077 </p>
3079 </p>
3078 <table>
3080 <table>
3079 <tr><td>-R</td>
3081 <tr><td>-R</td>
3080 <td>--repository REPO</td>
3082 <td>--repository REPO</td>
3081 <td>repository root directory or name of overlay bundle file</td></tr>
3083 <td>repository root directory or name of overlay bundle file</td></tr>
3082 <tr><td></td>
3084 <tr><td></td>
3083 <td>--cwd DIR</td>
3085 <td>--cwd DIR</td>
3084 <td>change working directory</td></tr>
3086 <td>change working directory</td></tr>
3085 <tr><td>-y</td>
3087 <tr><td>-y</td>
3086 <td>--noninteractive</td>
3088 <td>--noninteractive</td>
3087 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3089 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3088 <tr><td>-q</td>
3090 <tr><td>-q</td>
3089 <td>--quiet</td>
3091 <td>--quiet</td>
3090 <td>suppress output</td></tr>
3092 <td>suppress output</td></tr>
3091 <tr><td>-v</td>
3093 <tr><td>-v</td>
3092 <td>--verbose</td>
3094 <td>--verbose</td>
3093 <td>enable additional output</td></tr>
3095 <td>enable additional output</td></tr>
3094 <tr><td></td>
3096 <tr><td></td>
3095 <td>--color TYPE</td>
3097 <td>--color TYPE</td>
3096 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3098 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3097 <tr><td></td>
3099 <tr><td></td>
3098 <td>--config CONFIG [+]</td>
3100 <td>--config CONFIG [+]</td>
3099 <td>set/override config option (use 'section.name=value')</td></tr>
3101 <td>set/override config option (use 'section.name=value')</td></tr>
3100 <tr><td></td>
3102 <tr><td></td>
3101 <td>--debug</td>
3103 <td>--debug</td>
3102 <td>enable debugging output</td></tr>
3104 <td>enable debugging output</td></tr>
3103 <tr><td></td>
3105 <tr><td></td>
3104 <td>--debugger</td>
3106 <td>--debugger</td>
3105 <td>start debugger</td></tr>
3107 <td>start debugger</td></tr>
3106 <tr><td></td>
3108 <tr><td></td>
3107 <td>--encoding ENCODE</td>
3109 <td>--encoding ENCODE</td>
3108 <td>set the charset encoding (default: ascii)</td></tr>
3110 <td>set the charset encoding (default: ascii)</td></tr>
3109 <tr><td></td>
3111 <tr><td></td>
3110 <td>--encodingmode MODE</td>
3112 <td>--encodingmode MODE</td>
3111 <td>set the charset encoding mode (default: strict)</td></tr>
3113 <td>set the charset encoding mode (default: strict)</td></tr>
3112 <tr><td></td>
3114 <tr><td></td>
3113 <td>--traceback</td>
3115 <td>--traceback</td>
3114 <td>always print a traceback on exception</td></tr>
3116 <td>always print a traceback on exception</td></tr>
3115 <tr><td></td>
3117 <tr><td></td>
3116 <td>--time</td>
3118 <td>--time</td>
3117 <td>time how long the command takes</td></tr>
3119 <td>time how long the command takes</td></tr>
3118 <tr><td></td>
3120 <tr><td></td>
3119 <td>--profile</td>
3121 <td>--profile</td>
3120 <td>print command execution profile</td></tr>
3122 <td>print command execution profile</td></tr>
3121 <tr><td></td>
3123 <tr><td></td>
3122 <td>--version</td>
3124 <td>--version</td>
3123 <td>output version information and exit</td></tr>
3125 <td>output version information and exit</td></tr>
3124 <tr><td>-h</td>
3126 <tr><td>-h</td>
3125 <td>--help</td>
3127 <td>--help</td>
3126 <td>display help and exit</td></tr>
3128 <td>display help and exit</td></tr>
3127 <tr><td></td>
3129 <tr><td></td>
3128 <td>--hidden</td>
3130 <td>--hidden</td>
3129 <td>consider hidden changesets</td></tr>
3131 <td>consider hidden changesets</td></tr>
3130 <tr><td></td>
3132 <tr><td></td>
3131 <td>--pager TYPE</td>
3133 <td>--pager TYPE</td>
3132 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3134 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3133 </table>
3135 </table>
3134
3136
3135 </div>
3137 </div>
3136 </div>
3138 </div>
3137 </div>
3139 </div>
3138
3140
3139
3141
3140
3142
3141 </body>
3143 </body>
3142 </html>
3144 </html>
3143
3145
3144
3146
3145 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
3147 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
3146 200 Script output follows
3148 200 Script output follows
3147
3149
3148 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3150 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3149 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3151 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3150 <head>
3152 <head>
3151 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3153 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3152 <meta name="robots" content="index, nofollow" />
3154 <meta name="robots" content="index, nofollow" />
3153 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3155 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3154 <script type="text/javascript" src="/static/mercurial.js"></script>
3156 <script type="text/javascript" src="/static/mercurial.js"></script>
3155
3157
3156 <title>Help: remove</title>
3158 <title>Help: remove</title>
3157 </head>
3159 </head>
3158 <body>
3160 <body>
3159
3161
3160 <div class="container">
3162 <div class="container">
3161 <div class="menu">
3163 <div class="menu">
3162 <div class="logo">
3164 <div class="logo">
3163 <a href="https://mercurial-scm.org/">
3165 <a href="https://mercurial-scm.org/">
3164 <img src="/static/hglogo.png" alt="mercurial" /></a>
3166 <img src="/static/hglogo.png" alt="mercurial" /></a>
3165 </div>
3167 </div>
3166 <ul>
3168 <ul>
3167 <li><a href="/shortlog">log</a></li>
3169 <li><a href="/shortlog">log</a></li>
3168 <li><a href="/graph">graph</a></li>
3170 <li><a href="/graph">graph</a></li>
3169 <li><a href="/tags">tags</a></li>
3171 <li><a href="/tags">tags</a></li>
3170 <li><a href="/bookmarks">bookmarks</a></li>
3172 <li><a href="/bookmarks">bookmarks</a></li>
3171 <li><a href="/branches">branches</a></li>
3173 <li><a href="/branches">branches</a></li>
3172 </ul>
3174 </ul>
3173 <ul>
3175 <ul>
3174 <li class="active"><a href="/help">help</a></li>
3176 <li class="active"><a href="/help">help</a></li>
3175 </ul>
3177 </ul>
3176 </div>
3178 </div>
3177
3179
3178 <div class="main">
3180 <div class="main">
3179 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3181 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3180 <h3>Help: remove</h3>
3182 <h3>Help: remove</h3>
3181
3183
3182 <form class="search" action="/log">
3184 <form class="search" action="/log">
3183
3185
3184 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3186 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3185 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3187 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3186 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3188 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3187 </form>
3189 </form>
3188 <div id="doc">
3190 <div id="doc">
3189 <p>
3191 <p>
3190 hg remove [OPTION]... FILE...
3192 hg remove [OPTION]... FILE...
3191 </p>
3193 </p>
3192 <p>
3194 <p>
3193 aliases: rm
3195 aliases: rm
3194 </p>
3196 </p>
3195 <p>
3197 <p>
3196 remove the specified files on the next commit
3198 remove the specified files on the next commit
3197 </p>
3199 </p>
3198 <p>
3200 <p>
3199 Schedule the indicated files for removal from the current branch.
3201 Schedule the indicated files for removal from the current branch.
3200 </p>
3202 </p>
3201 <p>
3203 <p>
3202 This command schedules the files to be removed at the next commit.
3204 This command schedules the files to be removed at the next commit.
3203 To undo a remove before that, see 'hg revert'. To undo added
3205 To undo a remove before that, see 'hg revert'. To undo added
3204 files, see 'hg forget'.
3206 files, see 'hg forget'.
3205 </p>
3207 </p>
3206 <p>
3208 <p>
3207 -A/--after can be used to remove only files that have already
3209 -A/--after can be used to remove only files that have already
3208 been deleted, -f/--force can be used to force deletion, and -Af
3210 been deleted, -f/--force can be used to force deletion, and -Af
3209 can be used to remove files from the next revision without
3211 can be used to remove files from the next revision without
3210 deleting them from the working directory.
3212 deleting them from the working directory.
3211 </p>
3213 </p>
3212 <p>
3214 <p>
3213 The following table details the behavior of remove for different
3215 The following table details the behavior of remove for different
3214 file states (columns) and option combinations (rows). The file
3216 file states (columns) and option combinations (rows). The file
3215 states are Added [A], Clean [C], Modified [M] and Missing [!]
3217 states are Added [A], Clean [C], Modified [M] and Missing [!]
3216 (as reported by 'hg status'). The actions are Warn, Remove
3218 (as reported by 'hg status'). The actions are Warn, Remove
3217 (from branch) and Delete (from disk):
3219 (from branch) and Delete (from disk):
3218 </p>
3220 </p>
3219 <table>
3221 <table>
3220 <tr><td>opt/state</td>
3222 <tr><td>opt/state</td>
3221 <td>A</td>
3223 <td>A</td>
3222 <td>C</td>
3224 <td>C</td>
3223 <td>M</td>
3225 <td>M</td>
3224 <td>!</td></tr>
3226 <td>!</td></tr>
3225 <tr><td>none</td>
3227 <tr><td>none</td>
3226 <td>W</td>
3228 <td>W</td>
3227 <td>RD</td>
3229 <td>RD</td>
3228 <td>W</td>
3230 <td>W</td>
3229 <td>R</td></tr>
3231 <td>R</td></tr>
3230 <tr><td>-f</td>
3232 <tr><td>-f</td>
3231 <td>R</td>
3233 <td>R</td>
3232 <td>RD</td>
3234 <td>RD</td>
3233 <td>RD</td>
3235 <td>RD</td>
3234 <td>R</td></tr>
3236 <td>R</td></tr>
3235 <tr><td>-A</td>
3237 <tr><td>-A</td>
3236 <td>W</td>
3238 <td>W</td>
3237 <td>W</td>
3239 <td>W</td>
3238 <td>W</td>
3240 <td>W</td>
3239 <td>R</td></tr>
3241 <td>R</td></tr>
3240 <tr><td>-Af</td>
3242 <tr><td>-Af</td>
3241 <td>R</td>
3243 <td>R</td>
3242 <td>R</td>
3244 <td>R</td>
3243 <td>R</td>
3245 <td>R</td>
3244 <td>R</td></tr>
3246 <td>R</td></tr>
3245 </table>
3247 </table>
3246 <p>
3248 <p>
3247 <b>Note:</b>
3249 <b>Note:</b>
3248 </p>
3250 </p>
3249 <p>
3251 <p>
3250 'hg remove' never deletes files in Added [A] state from the
3252 'hg remove' never deletes files in Added [A] state from the
3251 working directory, not even if &quot;--force&quot; is specified.
3253 working directory, not even if &quot;--force&quot; is specified.
3252 </p>
3254 </p>
3253 <p>
3255 <p>
3254 Returns 0 on success, 1 if any warnings encountered.
3256 Returns 0 on success, 1 if any warnings encountered.
3255 </p>
3257 </p>
3256 <p>
3258 <p>
3257 options ([+] can be repeated):
3259 options ([+] can be repeated):
3258 </p>
3260 </p>
3259 <table>
3261 <table>
3260 <tr><td>-A</td>
3262 <tr><td>-A</td>
3261 <td>--after</td>
3263 <td>--after</td>
3262 <td>record delete for missing files</td></tr>
3264 <td>record delete for missing files</td></tr>
3263 <tr><td>-f</td>
3265 <tr><td>-f</td>
3264 <td>--force</td>
3266 <td>--force</td>
3265 <td>forget added files, delete modified files</td></tr>
3267 <td>forget added files, delete modified files</td></tr>
3266 <tr><td>-S</td>
3268 <tr><td>-S</td>
3267 <td>--subrepos</td>
3269 <td>--subrepos</td>
3268 <td>recurse into subrepositories</td></tr>
3270 <td>recurse into subrepositories</td></tr>
3269 <tr><td>-I</td>
3271 <tr><td>-I</td>
3270 <td>--include PATTERN [+]</td>
3272 <td>--include PATTERN [+]</td>
3271 <td>include names matching the given patterns</td></tr>
3273 <td>include names matching the given patterns</td></tr>
3272 <tr><td>-X</td>
3274 <tr><td>-X</td>
3273 <td>--exclude PATTERN [+]</td>
3275 <td>--exclude PATTERN [+]</td>
3274 <td>exclude names matching the given patterns</td></tr>
3276 <td>exclude names matching the given patterns</td></tr>
3275 <tr><td>-n</td>
3277 <tr><td>-n</td>
3276 <td>--dry-run</td>
3278 <td>--dry-run</td>
3277 <td>do not perform actions, just print output</td></tr>
3279 <td>do not perform actions, just print output</td></tr>
3278 </table>
3280 </table>
3279 <p>
3281 <p>
3280 global options ([+] can be repeated):
3282 global options ([+] can be repeated):
3281 </p>
3283 </p>
3282 <table>
3284 <table>
3283 <tr><td>-R</td>
3285 <tr><td>-R</td>
3284 <td>--repository REPO</td>
3286 <td>--repository REPO</td>
3285 <td>repository root directory or name of overlay bundle file</td></tr>
3287 <td>repository root directory or name of overlay bundle file</td></tr>
3286 <tr><td></td>
3288 <tr><td></td>
3287 <td>--cwd DIR</td>
3289 <td>--cwd DIR</td>
3288 <td>change working directory</td></tr>
3290 <td>change working directory</td></tr>
3289 <tr><td>-y</td>
3291 <tr><td>-y</td>
3290 <td>--noninteractive</td>
3292 <td>--noninteractive</td>
3291 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3293 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3292 <tr><td>-q</td>
3294 <tr><td>-q</td>
3293 <td>--quiet</td>
3295 <td>--quiet</td>
3294 <td>suppress output</td></tr>
3296 <td>suppress output</td></tr>
3295 <tr><td>-v</td>
3297 <tr><td>-v</td>
3296 <td>--verbose</td>
3298 <td>--verbose</td>
3297 <td>enable additional output</td></tr>
3299 <td>enable additional output</td></tr>
3298 <tr><td></td>
3300 <tr><td></td>
3299 <td>--color TYPE</td>
3301 <td>--color TYPE</td>
3300 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3302 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3301 <tr><td></td>
3303 <tr><td></td>
3302 <td>--config CONFIG [+]</td>
3304 <td>--config CONFIG [+]</td>
3303 <td>set/override config option (use 'section.name=value')</td></tr>
3305 <td>set/override config option (use 'section.name=value')</td></tr>
3304 <tr><td></td>
3306 <tr><td></td>
3305 <td>--debug</td>
3307 <td>--debug</td>
3306 <td>enable debugging output</td></tr>
3308 <td>enable debugging output</td></tr>
3307 <tr><td></td>
3309 <tr><td></td>
3308 <td>--debugger</td>
3310 <td>--debugger</td>
3309 <td>start debugger</td></tr>
3311 <td>start debugger</td></tr>
3310 <tr><td></td>
3312 <tr><td></td>
3311 <td>--encoding ENCODE</td>
3313 <td>--encoding ENCODE</td>
3312 <td>set the charset encoding (default: ascii)</td></tr>
3314 <td>set the charset encoding (default: ascii)</td></tr>
3313 <tr><td></td>
3315 <tr><td></td>
3314 <td>--encodingmode MODE</td>
3316 <td>--encodingmode MODE</td>
3315 <td>set the charset encoding mode (default: strict)</td></tr>
3317 <td>set the charset encoding mode (default: strict)</td></tr>
3316 <tr><td></td>
3318 <tr><td></td>
3317 <td>--traceback</td>
3319 <td>--traceback</td>
3318 <td>always print a traceback on exception</td></tr>
3320 <td>always print a traceback on exception</td></tr>
3319 <tr><td></td>
3321 <tr><td></td>
3320 <td>--time</td>
3322 <td>--time</td>
3321 <td>time how long the command takes</td></tr>
3323 <td>time how long the command takes</td></tr>
3322 <tr><td></td>
3324 <tr><td></td>
3323 <td>--profile</td>
3325 <td>--profile</td>
3324 <td>print command execution profile</td></tr>
3326 <td>print command execution profile</td></tr>
3325 <tr><td></td>
3327 <tr><td></td>
3326 <td>--version</td>
3328 <td>--version</td>
3327 <td>output version information and exit</td></tr>
3329 <td>output version information and exit</td></tr>
3328 <tr><td>-h</td>
3330 <tr><td>-h</td>
3329 <td>--help</td>
3331 <td>--help</td>
3330 <td>display help and exit</td></tr>
3332 <td>display help and exit</td></tr>
3331 <tr><td></td>
3333 <tr><td></td>
3332 <td>--hidden</td>
3334 <td>--hidden</td>
3333 <td>consider hidden changesets</td></tr>
3335 <td>consider hidden changesets</td></tr>
3334 <tr><td></td>
3336 <tr><td></td>
3335 <td>--pager TYPE</td>
3337 <td>--pager TYPE</td>
3336 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3338 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3337 </table>
3339 </table>
3338
3340
3339 </div>
3341 </div>
3340 </div>
3342 </div>
3341 </div>
3343 </div>
3342
3344
3343
3345
3344
3346
3345 </body>
3347 </body>
3346 </html>
3348 </html>
3347
3349
3348
3350
3349 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3351 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3350 200 Script output follows
3352 200 Script output follows
3351
3353
3352 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3354 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3353 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3355 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3354 <head>
3356 <head>
3355 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3357 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3356 <meta name="robots" content="index, nofollow" />
3358 <meta name="robots" content="index, nofollow" />
3357 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3359 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3358 <script type="text/javascript" src="/static/mercurial.js"></script>
3360 <script type="text/javascript" src="/static/mercurial.js"></script>
3359
3361
3360 <title>Help: dates</title>
3362 <title>Help: dates</title>
3361 </head>
3363 </head>
3362 <body>
3364 <body>
3363
3365
3364 <div class="container">
3366 <div class="container">
3365 <div class="menu">
3367 <div class="menu">
3366 <div class="logo">
3368 <div class="logo">
3367 <a href="https://mercurial-scm.org/">
3369 <a href="https://mercurial-scm.org/">
3368 <img src="/static/hglogo.png" alt="mercurial" /></a>
3370 <img src="/static/hglogo.png" alt="mercurial" /></a>
3369 </div>
3371 </div>
3370 <ul>
3372 <ul>
3371 <li><a href="/shortlog">log</a></li>
3373 <li><a href="/shortlog">log</a></li>
3372 <li><a href="/graph">graph</a></li>
3374 <li><a href="/graph">graph</a></li>
3373 <li><a href="/tags">tags</a></li>
3375 <li><a href="/tags">tags</a></li>
3374 <li><a href="/bookmarks">bookmarks</a></li>
3376 <li><a href="/bookmarks">bookmarks</a></li>
3375 <li><a href="/branches">branches</a></li>
3377 <li><a href="/branches">branches</a></li>
3376 </ul>
3378 </ul>
3377 <ul>
3379 <ul>
3378 <li class="active"><a href="/help">help</a></li>
3380 <li class="active"><a href="/help">help</a></li>
3379 </ul>
3381 </ul>
3380 </div>
3382 </div>
3381
3383
3382 <div class="main">
3384 <div class="main">
3383 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3385 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3384 <h3>Help: dates</h3>
3386 <h3>Help: dates</h3>
3385
3387
3386 <form class="search" action="/log">
3388 <form class="search" action="/log">
3387
3389
3388 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3390 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3389 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3391 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3390 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3392 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3391 </form>
3393 </form>
3392 <div id="doc">
3394 <div id="doc">
3393 <h1>Date Formats</h1>
3395 <h1>Date Formats</h1>
3394 <p>
3396 <p>
3395 Some commands allow the user to specify a date, e.g.:
3397 Some commands allow the user to specify a date, e.g.:
3396 </p>
3398 </p>
3397 <ul>
3399 <ul>
3398 <li> backout, commit, import, tag: Specify the commit date.
3400 <li> backout, commit, import, tag: Specify the commit date.
3399 <li> log, revert, update: Select revision(s) by date.
3401 <li> log, revert, update: Select revision(s) by date.
3400 </ul>
3402 </ul>
3401 <p>
3403 <p>
3402 Many date formats are valid. Here are some examples:
3404 Many date formats are valid. Here are some examples:
3403 </p>
3405 </p>
3404 <ul>
3406 <ul>
3405 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3407 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3406 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3408 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3407 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3409 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3408 <li> &quot;Dec 6&quot; (midnight)
3410 <li> &quot;Dec 6&quot; (midnight)
3409 <li> &quot;13:18&quot; (today assumed)
3411 <li> &quot;13:18&quot; (today assumed)
3410 <li> &quot;3:39&quot; (3:39AM assumed)
3412 <li> &quot;3:39&quot; (3:39AM assumed)
3411 <li> &quot;3:39pm&quot; (15:39)
3413 <li> &quot;3:39pm&quot; (15:39)
3412 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3414 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3413 <li> &quot;2006-12-6 13:18&quot;
3415 <li> &quot;2006-12-6 13:18&quot;
3414 <li> &quot;2006-12-6&quot;
3416 <li> &quot;2006-12-6&quot;
3415 <li> &quot;12-6&quot;
3417 <li> &quot;12-6&quot;
3416 <li> &quot;12/6&quot;
3418 <li> &quot;12/6&quot;
3417 <li> &quot;12/6/6&quot; (Dec 6 2006)
3419 <li> &quot;12/6/6&quot; (Dec 6 2006)
3418 <li> &quot;today&quot; (midnight)
3420 <li> &quot;today&quot; (midnight)
3419 <li> &quot;yesterday&quot; (midnight)
3421 <li> &quot;yesterday&quot; (midnight)
3420 <li> &quot;now&quot; - right now
3422 <li> &quot;now&quot; - right now
3421 </ul>
3423 </ul>
3422 <p>
3424 <p>
3423 Lastly, there is Mercurial's internal format:
3425 Lastly, there is Mercurial's internal format:
3424 </p>
3426 </p>
3425 <ul>
3427 <ul>
3426 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3428 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3427 </ul>
3429 </ul>
3428 <p>
3430 <p>
3429 This is the internal representation format for dates. The first number
3431 This is the internal representation format for dates. The first number
3430 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3432 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3431 second is the offset of the local timezone, in seconds west of UTC
3433 second is the offset of the local timezone, in seconds west of UTC
3432 (negative if the timezone is east of UTC).
3434 (negative if the timezone is east of UTC).
3433 </p>
3435 </p>
3434 <p>
3436 <p>
3435 The log command also accepts date ranges:
3437 The log command also accepts date ranges:
3436 </p>
3438 </p>
3437 <ul>
3439 <ul>
3438 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3440 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3439 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3441 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3440 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3442 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3441 <li> &quot;-DAYS&quot; - within a given number of days from today
3443 <li> &quot;-DAYS&quot; - within a given number of days from today
3442 </ul>
3444 </ul>
3443
3445
3444 </div>
3446 </div>
3445 </div>
3447 </div>
3446 </div>
3448 </div>
3447
3449
3448
3450
3449
3451
3450 </body>
3452 </body>
3451 </html>
3453 </html>
3452
3454
3453
3455
3454 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3456 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3455 200 Script output follows
3457 200 Script output follows
3456
3458
3457 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3459 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3458 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3460 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3459 <head>
3461 <head>
3460 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3462 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3461 <meta name="robots" content="index, nofollow" />
3463 <meta name="robots" content="index, nofollow" />
3462 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3464 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3463 <script type="text/javascript" src="/static/mercurial.js"></script>
3465 <script type="text/javascript" src="/static/mercurial.js"></script>
3464
3466
3465 <title>Help: pager</title>
3467 <title>Help: pager</title>
3466 </head>
3468 </head>
3467 <body>
3469 <body>
3468
3470
3469 <div class="container">
3471 <div class="container">
3470 <div class="menu">
3472 <div class="menu">
3471 <div class="logo">
3473 <div class="logo">
3472 <a href="https://mercurial-scm.org/">
3474 <a href="https://mercurial-scm.org/">
3473 <img src="/static/hglogo.png" alt="mercurial" /></a>
3475 <img src="/static/hglogo.png" alt="mercurial" /></a>
3474 </div>
3476 </div>
3475 <ul>
3477 <ul>
3476 <li><a href="/shortlog">log</a></li>
3478 <li><a href="/shortlog">log</a></li>
3477 <li><a href="/graph">graph</a></li>
3479 <li><a href="/graph">graph</a></li>
3478 <li><a href="/tags">tags</a></li>
3480 <li><a href="/tags">tags</a></li>
3479 <li><a href="/bookmarks">bookmarks</a></li>
3481 <li><a href="/bookmarks">bookmarks</a></li>
3480 <li><a href="/branches">branches</a></li>
3482 <li><a href="/branches">branches</a></li>
3481 </ul>
3483 </ul>
3482 <ul>
3484 <ul>
3483 <li class="active"><a href="/help">help</a></li>
3485 <li class="active"><a href="/help">help</a></li>
3484 </ul>
3486 </ul>
3485 </div>
3487 </div>
3486
3488
3487 <div class="main">
3489 <div class="main">
3488 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3490 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3489 <h3>Help: pager</h3>
3491 <h3>Help: pager</h3>
3490
3492
3491 <form class="search" action="/log">
3493 <form class="search" action="/log">
3492
3494
3493 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3495 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3494 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3496 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3495 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3497 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3496 </form>
3498 </form>
3497 <div id="doc">
3499 <div id="doc">
3498 <h1>Pager Support</h1>
3500 <h1>Pager Support</h1>
3499 <p>
3501 <p>
3500 Some Mercurial commands can produce a lot of output, and Mercurial will
3502 Some Mercurial commands can produce a lot of output, and Mercurial will
3501 attempt to use a pager to make those commands more pleasant.
3503 attempt to use a pager to make those commands more pleasant.
3502 </p>
3504 </p>
3503 <p>
3505 <p>
3504 To set the pager that should be used, set the application variable:
3506 To set the pager that should be used, set the application variable:
3505 </p>
3507 </p>
3506 <pre>
3508 <pre>
3507 [pager]
3509 [pager]
3508 pager = less -FRX
3510 pager = less -FRX
3509 </pre>
3511 </pre>
3510 <p>
3512 <p>
3511 If no pager is set in the user or repository configuration, Mercurial uses the
3513 If no pager is set in the user or repository configuration, Mercurial uses the
3512 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3514 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3513 or system configuration is used. If none of these are set, a default pager will
3515 or system configuration is used. If none of these are set, a default pager will
3514 be used, typically 'less' on Unix and 'more' on Windows.
3516 be used, typically 'less' on Unix and 'more' on Windows.
3515 </p>
3517 </p>
3516 <p>
3518 <p>
3517 You can disable the pager for certain commands by adding them to the
3519 You can disable the pager for certain commands by adding them to the
3518 pager.ignore list:
3520 pager.ignore list:
3519 </p>
3521 </p>
3520 <pre>
3522 <pre>
3521 [pager]
3523 [pager]
3522 ignore = version, help, update
3524 ignore = version, help, update
3523 </pre>
3525 </pre>
3524 <p>
3526 <p>
3525 To ignore global commands like 'hg version' or 'hg help', you have
3527 To ignore global commands like 'hg version' or 'hg help', you have
3526 to specify them in your user configuration file.
3528 to specify them in your user configuration file.
3527 </p>
3529 </p>
3528 <p>
3530 <p>
3529 To control whether the pager is used at all for an individual command,
3531 To control whether the pager is used at all for an individual command,
3530 you can use --pager=&lt;value&gt;:
3532 you can use --pager=&lt;value&gt;:
3531 </p>
3533 </p>
3532 <ul>
3534 <ul>
3533 <li> use as needed: 'auto'.
3535 <li> use as needed: 'auto'.
3534 <li> require the pager: 'yes' or 'on'.
3536 <li> require the pager: 'yes' or 'on'.
3535 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3537 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3536 </ul>
3538 </ul>
3537 <p>
3539 <p>
3538 To globally turn off all attempts to use a pager, set:
3540 To globally turn off all attempts to use a pager, set:
3539 </p>
3541 </p>
3540 <pre>
3542 <pre>
3541 [ui]
3543 [ui]
3542 paginate = never
3544 paginate = never
3543 </pre>
3545 </pre>
3544 <p>
3546 <p>
3545 which will prevent the pager from running.
3547 which will prevent the pager from running.
3546 </p>
3548 </p>
3547
3549
3548 </div>
3550 </div>
3549 </div>
3551 </div>
3550 </div>
3552 </div>
3551
3553
3552
3554
3553
3555
3554 </body>
3556 </body>
3555 </html>
3557 </html>
3556
3558
3557
3559
3558 Sub-topic indexes rendered properly
3560 Sub-topic indexes rendered properly
3559
3561
3560 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3562 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3561 200 Script output follows
3563 200 Script output follows
3562
3564
3563 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3565 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3564 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3566 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3565 <head>
3567 <head>
3566 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3568 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3567 <meta name="robots" content="index, nofollow" />
3569 <meta name="robots" content="index, nofollow" />
3568 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3570 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3569 <script type="text/javascript" src="/static/mercurial.js"></script>
3571 <script type="text/javascript" src="/static/mercurial.js"></script>
3570
3572
3571 <title>Help: internals</title>
3573 <title>Help: internals</title>
3572 </head>
3574 </head>
3573 <body>
3575 <body>
3574
3576
3575 <div class="container">
3577 <div class="container">
3576 <div class="menu">
3578 <div class="menu">
3577 <div class="logo">
3579 <div class="logo">
3578 <a href="https://mercurial-scm.org/">
3580 <a href="https://mercurial-scm.org/">
3579 <img src="/static/hglogo.png" alt="mercurial" /></a>
3581 <img src="/static/hglogo.png" alt="mercurial" /></a>
3580 </div>
3582 </div>
3581 <ul>
3583 <ul>
3582 <li><a href="/shortlog">log</a></li>
3584 <li><a href="/shortlog">log</a></li>
3583 <li><a href="/graph">graph</a></li>
3585 <li><a href="/graph">graph</a></li>
3584 <li><a href="/tags">tags</a></li>
3586 <li><a href="/tags">tags</a></li>
3585 <li><a href="/bookmarks">bookmarks</a></li>
3587 <li><a href="/bookmarks">bookmarks</a></li>
3586 <li><a href="/branches">branches</a></li>
3588 <li><a href="/branches">branches</a></li>
3587 </ul>
3589 </ul>
3588 <ul>
3590 <ul>
3589 <li><a href="/help">help</a></li>
3591 <li><a href="/help">help</a></li>
3590 </ul>
3592 </ul>
3591 </div>
3593 </div>
3592
3594
3593 <div class="main">
3595 <div class="main">
3594 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3596 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3595
3597
3596 <form class="search" action="/log">
3598 <form class="search" action="/log">
3597
3599
3598 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3600 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3599 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3601 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3600 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3602 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3601 </form>
3603 </form>
3602 <table class="bigtable">
3604 <table class="bigtable">
3603 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3605 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3604
3606
3605 <tr><td>
3607 <tr><td>
3606 <a href="/help/internals.bid-merge">
3608 <a href="/help/internals.bid-merge">
3607 bid-merge
3609 bid-merge
3608 </a>
3610 </a>
3609 </td><td>
3611 </td><td>
3610 Bid Merge Algorithm
3612 Bid Merge Algorithm
3611 </td></tr>
3613 </td></tr>
3612 <tr><td>
3614 <tr><td>
3613 <a href="/help/internals.bundle2">
3615 <a href="/help/internals.bundle2">
3614 bundle2
3616 bundle2
3615 </a>
3617 </a>
3616 </td><td>
3618 </td><td>
3617 Bundle2
3619 Bundle2
3618 </td></tr>
3620 </td></tr>
3619 <tr><td>
3621 <tr><td>
3620 <a href="/help/internals.bundles">
3622 <a href="/help/internals.bundles">
3621 bundles
3623 bundles
3622 </a>
3624 </a>
3623 </td><td>
3625 </td><td>
3624 Bundles
3626 Bundles
3625 </td></tr>
3627 </td></tr>
3626 <tr><td>
3628 <tr><td>
3627 <a href="/help/internals.cbor">
3629 <a href="/help/internals.cbor">
3628 cbor
3630 cbor
3629 </a>
3631 </a>
3630 </td><td>
3632 </td><td>
3631 CBOR
3633 CBOR
3632 </td></tr>
3634 </td></tr>
3633 <tr><td>
3635 <tr><td>
3634 <a href="/help/internals.censor">
3636 <a href="/help/internals.censor">
3635 censor
3637 censor
3636 </a>
3638 </a>
3637 </td><td>
3639 </td><td>
3638 Censor
3640 Censor
3639 </td></tr>
3641 </td></tr>
3640 <tr><td>
3642 <tr><td>
3641 <a href="/help/internals.changegroups">
3643 <a href="/help/internals.changegroups">
3642 changegroups
3644 changegroups
3643 </a>
3645 </a>
3644 </td><td>
3646 </td><td>
3645 Changegroups
3647 Changegroups
3646 </td></tr>
3648 </td></tr>
3647 <tr><td>
3649 <tr><td>
3648 <a href="/help/internals.config">
3650 <a href="/help/internals.config">
3649 config
3651 config
3650 </a>
3652 </a>
3651 </td><td>
3653 </td><td>
3652 Config Registrar
3654 Config Registrar
3653 </td></tr>
3655 </td></tr>
3654 <tr><td>
3656 <tr><td>
3655 <a href="/help/internals.dirstate-v2">
3657 <a href="/help/internals.dirstate-v2">
3656 dirstate-v2
3658 dirstate-v2
3657 </a>
3659 </a>
3658 </td><td>
3660 </td><td>
3659 dirstate-v2 file format
3661 dirstate-v2 file format
3660 </td></tr>
3662 </td></tr>
3661 <tr><td>
3663 <tr><td>
3662 <a href="/help/internals.extensions">
3664 <a href="/help/internals.extensions">
3663 extensions
3665 extensions
3664 </a>
3666 </a>
3665 </td><td>
3667 </td><td>
3666 Extension API
3668 Extension API
3667 </td></tr>
3669 </td></tr>
3668 <tr><td>
3670 <tr><td>
3669 <a href="/help/internals.mergestate">
3671 <a href="/help/internals.mergestate">
3670 mergestate
3672 mergestate
3671 </a>
3673 </a>
3672 </td><td>
3674 </td><td>
3673 Mergestate
3675 Mergestate
3674 </td></tr>
3676 </td></tr>
3675 <tr><td>
3677 <tr><td>
3676 <a href="/help/internals.requirements">
3678 <a href="/help/internals.requirements">
3677 requirements
3679 requirements
3678 </a>
3680 </a>
3679 </td><td>
3681 </td><td>
3680 Repository Requirements
3682 Repository Requirements
3681 </td></tr>
3683 </td></tr>
3682 <tr><td>
3684 <tr><td>
3683 <a href="/help/internals.revlogs">
3685 <a href="/help/internals.revlogs">
3684 revlogs
3686 revlogs
3685 </a>
3687 </a>
3686 </td><td>
3688 </td><td>
3687 Revision Logs
3689 Revision Logs
3688 </td></tr>
3690 </td></tr>
3689 <tr><td>
3691 <tr><td>
3690 <a href="/help/internals.wireprotocol">
3692 <a href="/help/internals.wireprotocol">
3691 wireprotocol
3693 wireprotocol
3692 </a>
3694 </a>
3693 </td><td>
3695 </td><td>
3694 Wire Protocol
3696 Wire Protocol
3695 </td></tr>
3697 </td></tr>
3696 <tr><td>
3698 <tr><td>
3697 <a href="/help/internals.wireprotocolrpc">
3699 <a href="/help/internals.wireprotocolrpc">
3698 wireprotocolrpc
3700 wireprotocolrpc
3699 </a>
3701 </a>
3700 </td><td>
3702 </td><td>
3701 Wire Protocol RPC
3703 Wire Protocol RPC
3702 </td></tr>
3704 </td></tr>
3703 <tr><td>
3705 <tr><td>
3704 <a href="/help/internals.wireprotocolv2">
3706 <a href="/help/internals.wireprotocolv2">
3705 wireprotocolv2
3707 wireprotocolv2
3706 </a>
3708 </a>
3707 </td><td>
3709 </td><td>
3708 Wire Protocol Version 2
3710 Wire Protocol Version 2
3709 </td></tr>
3711 </td></tr>
3710
3712
3711
3713
3712
3714
3713
3715
3714
3716
3715 </table>
3717 </table>
3716 </div>
3718 </div>
3717 </div>
3719 </div>
3718
3720
3719
3721
3720
3722
3721 </body>
3723 </body>
3722 </html>
3724 </html>
3723
3725
3724
3726
3725 Sub-topic topics rendered properly
3727 Sub-topic topics rendered properly
3726
3728
3727 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3729 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3728 200 Script output follows
3730 200 Script output follows
3729
3731
3730 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3732 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3731 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3733 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3732 <head>
3734 <head>
3733 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3735 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3734 <meta name="robots" content="index, nofollow" />
3736 <meta name="robots" content="index, nofollow" />
3735 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3737 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3736 <script type="text/javascript" src="/static/mercurial.js"></script>
3738 <script type="text/javascript" src="/static/mercurial.js"></script>
3737
3739
3738 <title>Help: internals.changegroups</title>
3740 <title>Help: internals.changegroups</title>
3739 </head>
3741 </head>
3740 <body>
3742 <body>
3741
3743
3742 <div class="container">
3744 <div class="container">
3743 <div class="menu">
3745 <div class="menu">
3744 <div class="logo">
3746 <div class="logo">
3745 <a href="https://mercurial-scm.org/">
3747 <a href="https://mercurial-scm.org/">
3746 <img src="/static/hglogo.png" alt="mercurial" /></a>
3748 <img src="/static/hglogo.png" alt="mercurial" /></a>
3747 </div>
3749 </div>
3748 <ul>
3750 <ul>
3749 <li><a href="/shortlog">log</a></li>
3751 <li><a href="/shortlog">log</a></li>
3750 <li><a href="/graph">graph</a></li>
3752 <li><a href="/graph">graph</a></li>
3751 <li><a href="/tags">tags</a></li>
3753 <li><a href="/tags">tags</a></li>
3752 <li><a href="/bookmarks">bookmarks</a></li>
3754 <li><a href="/bookmarks">bookmarks</a></li>
3753 <li><a href="/branches">branches</a></li>
3755 <li><a href="/branches">branches</a></li>
3754 </ul>
3756 </ul>
3755 <ul>
3757 <ul>
3756 <li class="active"><a href="/help">help</a></li>
3758 <li class="active"><a href="/help">help</a></li>
3757 </ul>
3759 </ul>
3758 </div>
3760 </div>
3759
3761
3760 <div class="main">
3762 <div class="main">
3761 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3763 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3762 <h3>Help: internals.changegroups</h3>
3764 <h3>Help: internals.changegroups</h3>
3763
3765
3764 <form class="search" action="/log">
3766 <form class="search" action="/log">
3765
3767
3766 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3768 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3767 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3769 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3768 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3770 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3769 </form>
3771 </form>
3770 <div id="doc">
3772 <div id="doc">
3771 <h1>Changegroups</h1>
3773 <h1>Changegroups</h1>
3772 <p>
3774 <p>
3773 Changegroups are representations of repository revlog data, specifically
3775 Changegroups are representations of repository revlog data, specifically
3774 the changelog data, root/flat manifest data, treemanifest data, and
3776 the changelog data, root/flat manifest data, treemanifest data, and
3775 filelogs.
3777 filelogs.
3776 </p>
3778 </p>
3777 <p>
3779 <p>
3778 There are 4 versions of changegroups: &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;. From a
3780 There are 4 versions of changegroups: &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;. From a
3779 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3781 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3780 only difference being an additional item in the *delta header*. Version
3782 only difference being an additional item in the *delta header*. Version
3781 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3783 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3782 exchanging treemanifests (enabled by setting an option on the
3784 exchanging treemanifests (enabled by setting an option on the
3783 &quot;changegroup&quot; part in the bundle2). Version &quot;4&quot; adds support for exchanging
3785 &quot;changegroup&quot; part in the bundle2). Version &quot;4&quot; adds support for exchanging
3784 sidedata (additional revision metadata not part of the digest).
3786 sidedata (additional revision metadata not part of the digest).
3785 </p>
3787 </p>
3786 <p>
3788 <p>
3787 Changegroups when not exchanging treemanifests consist of 3 logical
3789 Changegroups when not exchanging treemanifests consist of 3 logical
3788 segments:
3790 segments:
3789 </p>
3791 </p>
3790 <pre>
3792 <pre>
3791 +---------------------------------+
3793 +---------------------------------+
3792 | | | |
3794 | | | |
3793 | changeset | manifest | filelogs |
3795 | changeset | manifest | filelogs |
3794 | | | |
3796 | | | |
3795 | | | |
3797 | | | |
3796 +---------------------------------+
3798 +---------------------------------+
3797 </pre>
3799 </pre>
3798 <p>
3800 <p>
3799 When exchanging treemanifests, there are 4 logical segments:
3801 When exchanging treemanifests, there are 4 logical segments:
3800 </p>
3802 </p>
3801 <pre>
3803 <pre>
3802 +-------------------------------------------------+
3804 +-------------------------------------------------+
3803 | | | | |
3805 | | | | |
3804 | changeset | root | treemanifests | filelogs |
3806 | changeset | root | treemanifests | filelogs |
3805 | | manifest | | |
3807 | | manifest | | |
3806 | | | | |
3808 | | | | |
3807 +-------------------------------------------------+
3809 +-------------------------------------------------+
3808 </pre>
3810 </pre>
3809 <p>
3811 <p>
3810 The principle building block of each segment is a *chunk*. A *chunk*
3812 The principle building block of each segment is a *chunk*. A *chunk*
3811 is a framed piece of data:
3813 is a framed piece of data:
3812 </p>
3814 </p>
3813 <pre>
3815 <pre>
3814 +---------------------------------------+
3816 +---------------------------------------+
3815 | | |
3817 | | |
3816 | length | data |
3818 | length | data |
3817 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3819 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3818 | | |
3820 | | |
3819 +---------------------------------------+
3821 +---------------------------------------+
3820 </pre>
3822 </pre>
3821 <p>
3823 <p>
3822 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3824 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3823 integer indicating the length of the entire chunk (including the length field
3825 integer indicating the length of the entire chunk (including the length field
3824 itself).
3826 itself).
3825 </p>
3827 </p>
3826 <p>
3828 <p>
3827 There is a special case chunk that has a value of 0 for the length
3829 There is a special case chunk that has a value of 0 for the length
3828 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3830 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3829 </p>
3831 </p>
3830 <h2>Delta Groups</h2>
3832 <h2>Delta Groups</h2>
3831 <p>
3833 <p>
3832 A *delta group* expresses the content of a revlog as a series of deltas,
3834 A *delta group* expresses the content of a revlog as a series of deltas,
3833 or patches against previous revisions.
3835 or patches against previous revisions.
3834 </p>
3836 </p>
3835 <p>
3837 <p>
3836 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3838 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3837 to signal the end of the delta group:
3839 to signal the end of the delta group:
3838 </p>
3840 </p>
3839 <pre>
3841 <pre>
3840 +------------------------------------------------------------------------+
3842 +------------------------------------------------------------------------+
3841 | | | | | |
3843 | | | | | |
3842 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3844 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3843 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3845 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3844 | | | | | |
3846 | | | | | |
3845 +------------------------------------------------------------------------+
3847 +------------------------------------------------------------------------+
3846 </pre>
3848 </pre>
3847 <p>
3849 <p>
3848 Each *chunk*'s data consists of the following:
3850 Each *chunk*'s data consists of the following:
3849 </p>
3851 </p>
3850 <pre>
3852 <pre>
3851 +---------------------------------------+
3853 +---------------------------------------+
3852 | | |
3854 | | |
3853 | delta header | delta data |
3855 | delta header | delta data |
3854 | (various by version) | (various) |
3856 | (various by version) | (various) |
3855 | | |
3857 | | |
3856 +---------------------------------------+
3858 +---------------------------------------+
3857 </pre>
3859 </pre>
3858 <p>
3860 <p>
3859 The *delta data* is a series of *delta*s that describe a diff from an existing
3861 The *delta data* is a series of *delta*s that describe a diff from an existing
3860 entry (either that the recipient already has, or previously specified in the
3862 entry (either that the recipient already has, or previously specified in the
3861 bundle/changegroup).
3863 bundle/changegroup).
3862 </p>
3864 </p>
3863 <p>
3865 <p>
3864 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;
3866 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;
3865 of the changegroup format.
3867 of the changegroup format.
3866 </p>
3868 </p>
3867 <p>
3869 <p>
3868 Version 1 (headerlen=80):
3870 Version 1 (headerlen=80):
3869 </p>
3871 </p>
3870 <pre>
3872 <pre>
3871 +------------------------------------------------------+
3873 +------------------------------------------------------+
3872 | | | | |
3874 | | | | |
3873 | node | p1 node | p2 node | link node |
3875 | node | p1 node | p2 node | link node |
3874 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3876 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3875 | | | | |
3877 | | | | |
3876 +------------------------------------------------------+
3878 +------------------------------------------------------+
3877 </pre>
3879 </pre>
3878 <p>
3880 <p>
3879 Version 2 (headerlen=100):
3881 Version 2 (headerlen=100):
3880 </p>
3882 </p>
3881 <pre>
3883 <pre>
3882 +------------------------------------------------------------------+
3884 +------------------------------------------------------------------+
3883 | | | | | |
3885 | | | | | |
3884 | node | p1 node | p2 node | base node | link node |
3886 | node | p1 node | p2 node | base node | link node |
3885 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3887 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3886 | | | | | |
3888 | | | | | |
3887 +------------------------------------------------------------------+
3889 +------------------------------------------------------------------+
3888 </pre>
3890 </pre>
3889 <p>
3891 <p>
3890 Version 3 (headerlen=102):
3892 Version 3 (headerlen=102):
3891 </p>
3893 </p>
3892 <pre>
3894 <pre>
3893 +------------------------------------------------------------------------------+
3895 +------------------------------------------------------------------------------+
3894 | | | | | | |
3896 | | | | | | |
3895 | node | p1 node | p2 node | base node | link node | flags |
3897 | node | p1 node | p2 node | base node | link node | flags |
3896 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3898 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3897 | | | | | | |
3899 | | | | | | |
3898 +------------------------------------------------------------------------------+
3900 +------------------------------------------------------------------------------+
3899 </pre>
3901 </pre>
3900 <p>
3902 <p>
3901 Version 4 (headerlen=103):
3903 Version 4 (headerlen=103):
3902 </p>
3904 </p>
3903 <pre>
3905 <pre>
3904 +------------------------------------------------------------------------------+----------+
3906 +------------------------------------------------------------------------------+----------+
3905 | | | | | | | |
3907 | | | | | | | |
3906 | node | p1 node | p2 node | base node | link node | flags | pflags |
3908 | node | p1 node | p2 node | base node | link node | flags | pflags |
3907 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
3909 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
3908 | | | | | | | |
3910 | | | | | | | |
3909 +------------------------------------------------------------------------------+----------+
3911 +------------------------------------------------------------------------------+----------+
3910 </pre>
3912 </pre>
3911 <p>
3913 <p>
3912 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3914 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3913 series of *delta*s, densely packed (no separators). These deltas describe a diff
3915 series of *delta*s, densely packed (no separators). These deltas describe a diff
3914 from an existing entry (either that the recipient already has, or previously
3916 from an existing entry (either that the recipient already has, or previously
3915 specified in the bundle/changegroup). The format is described more fully in
3917 specified in the bundle/changegroup). The format is described more fully in
3916 &quot;hg help internals.bdiff&quot;, but briefly:
3918 &quot;hg help internals.bdiff&quot;, but briefly:
3917 </p>
3919 </p>
3918 <pre>
3920 <pre>
3919 +---------------------------------------------------------------+
3921 +---------------------------------------------------------------+
3920 | | | | |
3922 | | | | |
3921 | start offset | end offset | new length | content |
3923 | start offset | end offset | new length | content |
3922 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3924 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3923 | | | | |
3925 | | | | |
3924 +---------------------------------------------------------------+
3926 +---------------------------------------------------------------+
3925 </pre>
3927 </pre>
3926 <p>
3928 <p>
3927 Please note that the length field in the delta data does *not* include itself.
3929 Please note that the length field in the delta data does *not* include itself.
3928 </p>
3930 </p>
3929 <p>
3931 <p>
3930 In version 1, the delta is always applied against the previous node from
3932 In version 1, the delta is always applied against the previous node from
3931 the changegroup or the first parent if this is the first entry in the
3933 the changegroup or the first parent if this is the first entry in the
3932 changegroup.
3934 changegroup.
3933 </p>
3935 </p>
3934 <p>
3936 <p>
3935 In version 2 and up, the delta base node is encoded in the entry in the
3937 In version 2 and up, the delta base node is encoded in the entry in the
3936 changegroup. This allows the delta to be expressed against any parent,
3938 changegroup. This allows the delta to be expressed against any parent,
3937 which can result in smaller deltas and more efficient encoding of data.
3939 which can result in smaller deltas and more efficient encoding of data.
3938 </p>
3940 </p>
3939 <p>
3941 <p>
3940 The *flags* field holds bitwise flags affecting the processing of revision
3942 The *flags* field holds bitwise flags affecting the processing of revision
3941 data. The following flags are defined:
3943 data. The following flags are defined:
3942 </p>
3944 </p>
3943 <dl>
3945 <dl>
3944 <dt>32768
3946 <dt>32768
3945 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3947 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3946 <dt>16384
3948 <dt>16384
3947 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3949 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3948 <dt>8192
3950 <dt>8192
3949 <dd>Externally stored. The revision fulltext contains &quot;key:value&quot; &quot;\n&quot; delimited metadata defining an object stored elsewhere. Used by the LFS extension.
3951 <dd>Externally stored. The revision fulltext contains &quot;key:value&quot; &quot;\n&quot; delimited metadata defining an object stored elsewhere. Used by the LFS extension.
3950 <dt>4096
3952 <dt>4096
3951 <dd>Contains copy information. This revision changes files in a way that could affect copy tracing. This does *not* affect changegroup handling, but is relevant for other parts of Mercurial.
3953 <dd>Contains copy information. This revision changes files in a way that could affect copy tracing. This does *not* affect changegroup handling, but is relevant for other parts of Mercurial.
3952 </dl>
3954 </dl>
3953 <p>
3955 <p>
3954 For historical reasons, the integer values are identical to revlog version 1
3956 For historical reasons, the integer values are identical to revlog version 1
3955 per-revision storage flags and correspond to bits being set in this 2-byte
3957 per-revision storage flags and correspond to bits being set in this 2-byte
3956 field. Bits were allocated starting from the most-significant bit, hence the
3958 field. Bits were allocated starting from the most-significant bit, hence the
3957 reverse ordering and allocation of these flags.
3959 reverse ordering and allocation of these flags.
3958 </p>
3960 </p>
3959 <p>
3961 <p>
3960 The *pflags* (protocol flags) field holds bitwise flags affecting the protocol
3962 The *pflags* (protocol flags) field holds bitwise flags affecting the protocol
3961 itself. They are first in the header since they may affect the handling of the
3963 itself. They are first in the header since they may affect the handling of the
3962 rest of the fields in a future version. They are defined as such:
3964 rest of the fields in a future version. They are defined as such:
3963 </p>
3965 </p>
3964 <dl>
3966 <dl>
3965 <dt>1 indicates whether to read a chunk of sidedata (of variable length) right
3967 <dt>1 indicates whether to read a chunk of sidedata (of variable length) right
3966 <dd>after the revision flags.
3968 <dd>after the revision flags.
3967 </dl>
3969 </dl>
3968 <h2>Changeset Segment</h2>
3970 <h2>Changeset Segment</h2>
3969 <p>
3971 <p>
3970 The *changeset segment* consists of a single *delta group* holding
3972 The *changeset segment* consists of a single *delta group* holding
3971 changelog data. The *empty chunk* at the end of the *delta group* denotes
3973 changelog data. The *empty chunk* at the end of the *delta group* denotes
3972 the boundary to the *manifest segment*.
3974 the boundary to the *manifest segment*.
3973 </p>
3975 </p>
3974 <h2>Manifest Segment</h2>
3976 <h2>Manifest Segment</h2>
3975 <p>
3977 <p>
3976 The *manifest segment* consists of a single *delta group* holding manifest
3978 The *manifest segment* consists of a single *delta group* holding manifest
3977 data. If treemanifests are in use, it contains only the manifest for the
3979 data. If treemanifests are in use, it contains only the manifest for the
3978 root directory of the repository. Otherwise, it contains the entire
3980 root directory of the repository. Otherwise, it contains the entire
3979 manifest data. The *empty chunk* at the end of the *delta group* denotes
3981 manifest data. The *empty chunk* at the end of the *delta group* denotes
3980 the boundary to the next segment (either the *treemanifests segment* or the
3982 the boundary to the next segment (either the *treemanifests segment* or the
3981 *filelogs segment*, depending on version and the request options).
3983 *filelogs segment*, depending on version and the request options).
3982 </p>
3984 </p>
3983 <h3>Treemanifests Segment</h3>
3985 <h3>Treemanifests Segment</h3>
3984 <p>
3986 <p>
3985 The *treemanifests segment* only exists in changegroup version &quot;3&quot; and &quot;4&quot;,
3987 The *treemanifests segment* only exists in changegroup version &quot;3&quot; and &quot;4&quot;,
3986 and only if the 'treemanifest' param is part of the bundle2 changegroup part
3988 and only if the 'treemanifest' param is part of the bundle2 changegroup part
3987 (it is not possible to use changegroup version 3 or 4 outside of bundle2).
3989 (it is not possible to use changegroup version 3 or 4 outside of bundle2).
3988 Aside from the filenames in the *treemanifests segment* containing a
3990 Aside from the filenames in the *treemanifests segment* containing a
3989 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3991 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3990 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3992 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3991 a sub-segment with filename size 0). This denotes the boundary to the
3993 a sub-segment with filename size 0). This denotes the boundary to the
3992 *filelogs segment*.
3994 *filelogs segment*.
3993 </p>
3995 </p>
3994 <h2>Filelogs Segment</h2>
3996 <h2>Filelogs Segment</h2>
3995 <p>
3997 <p>
3996 The *filelogs segment* consists of multiple sub-segments, each
3998 The *filelogs segment* consists of multiple sub-segments, each
3997 corresponding to an individual file whose data is being described:
3999 corresponding to an individual file whose data is being described:
3998 </p>
4000 </p>
3999 <pre>
4001 <pre>
4000 +--------------------------------------------------+
4002 +--------------------------------------------------+
4001 | | | | | |
4003 | | | | | |
4002 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
4004 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
4003 | | | | | (4 bytes) |
4005 | | | | | (4 bytes) |
4004 | | | | | |
4006 | | | | | |
4005 +--------------------------------------------------+
4007 +--------------------------------------------------+
4006 </pre>
4008 </pre>
4007 <p>
4009 <p>
4008 The final filelog sub-segment is followed by an *empty chunk* (logically,
4010 The final filelog sub-segment is followed by an *empty chunk* (logically,
4009 a sub-segment with filename size 0). This denotes the end of the segment
4011 a sub-segment with filename size 0). This denotes the end of the segment
4010 and of the overall changegroup.
4012 and of the overall changegroup.
4011 </p>
4013 </p>
4012 <p>
4014 <p>
4013 Each filelog sub-segment consists of the following:
4015 Each filelog sub-segment consists of the following:
4014 </p>
4016 </p>
4015 <pre>
4017 <pre>
4016 +------------------------------------------------------+
4018 +------------------------------------------------------+
4017 | | | |
4019 | | | |
4018 | filename length | filename | delta group |
4020 | filename length | filename | delta group |
4019 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
4021 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
4020 | | | |
4022 | | | |
4021 +------------------------------------------------------+
4023 +------------------------------------------------------+
4022 </pre>
4024 </pre>
4023 <p>
4025 <p>
4024 That is, a *chunk* consisting of the filename (not terminated or padded)
4026 That is, a *chunk* consisting of the filename (not terminated or padded)
4025 followed by N chunks constituting the *delta group* for this file. The
4027 followed by N chunks constituting the *delta group* for this file. The
4026 *empty chunk* at the end of each *delta group* denotes the boundary to the
4028 *empty chunk* at the end of each *delta group* denotes the boundary to the
4027 next filelog sub-segment.
4029 next filelog sub-segment.
4028 </p>
4030 </p>
4029
4031
4030 </div>
4032 </div>
4031 </div>
4033 </div>
4032 </div>
4034 </div>
4033
4035
4034
4036
4035
4037
4036 </body>
4038 </body>
4037 </html>
4039 </html>
4038
4040
4039
4041
4040 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
4042 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
4041 404 Not Found
4043 404 Not Found
4042
4044
4043 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4045 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4044 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
4046 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
4045 <head>
4047 <head>
4046 <link rel="icon" href="/static/hgicon.png" type="image/png" />
4048 <link rel="icon" href="/static/hgicon.png" type="image/png" />
4047 <meta name="robots" content="index, nofollow" />
4049 <meta name="robots" content="index, nofollow" />
4048 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
4050 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
4049 <script type="text/javascript" src="/static/mercurial.js"></script>
4051 <script type="text/javascript" src="/static/mercurial.js"></script>
4050
4052
4051 <title>test: error</title>
4053 <title>test: error</title>
4052 </head>
4054 </head>
4053 <body>
4055 <body>
4054
4056
4055 <div class="container">
4057 <div class="container">
4056 <div class="menu">
4058 <div class="menu">
4057 <div class="logo">
4059 <div class="logo">
4058 <a href="https://mercurial-scm.org/">
4060 <a href="https://mercurial-scm.org/">
4059 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
4061 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
4060 </div>
4062 </div>
4061 <ul>
4063 <ul>
4062 <li><a href="/shortlog">log</a></li>
4064 <li><a href="/shortlog">log</a></li>
4063 <li><a href="/graph">graph</a></li>
4065 <li><a href="/graph">graph</a></li>
4064 <li><a href="/tags">tags</a></li>
4066 <li><a href="/tags">tags</a></li>
4065 <li><a href="/bookmarks">bookmarks</a></li>
4067 <li><a href="/bookmarks">bookmarks</a></li>
4066 <li><a href="/branches">branches</a></li>
4068 <li><a href="/branches">branches</a></li>
4067 </ul>
4069 </ul>
4068 <ul>
4070 <ul>
4069 <li><a href="/help">help</a></li>
4071 <li><a href="/help">help</a></li>
4070 </ul>
4072 </ul>
4071 </div>
4073 </div>
4072
4074
4073 <div class="main">
4075 <div class="main">
4074
4076
4075 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
4077 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
4076 <h3>error</h3>
4078 <h3>error</h3>
4077
4079
4078
4080
4079 <form class="search" action="/log">
4081 <form class="search" action="/log">
4080
4082
4081 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
4083 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
4082 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
4084 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
4083 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
4085 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
4084 </form>
4086 </form>
4085
4087
4086 <div class="description">
4088 <div class="description">
4087 <p>
4089 <p>
4088 An error occurred while processing your request:
4090 An error occurred while processing your request:
4089 </p>
4091 </p>
4090 <p>
4092 <p>
4091 Not Found
4093 Not Found
4092 </p>
4094 </p>
4093 </div>
4095 </div>
4094 </div>
4096 </div>
4095 </div>
4097 </div>
4096
4098
4097
4099
4098
4100
4099 </body>
4101 </body>
4100 </html>
4102 </html>
4101
4103
4102 [1]
4104 [1]
4103
4105
4104 $ killdaemons.py
4106 $ killdaemons.py
4105
4107
4106 #endif
4108 #endif
General Comments 0
You need to be logged in to leave comments. Login now