##// END OF EJS Templates
diff: add experimental support for "merge diffs"...
Augie Fackler -
r47177:1a7d12c8 default
parent child Browse files
Show More
@@ -1,7855 +1,7884 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import os
11 import os
12 import re
12 import re
13 import sys
13 import sys
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 hex,
17 hex,
18 nullid,
18 nullid,
19 nullrev,
19 nullrev,
20 short,
20 short,
21 wdirhex,
21 wdirhex,
22 wdirrev,
22 wdirrev,
23 )
23 )
24 from .pycompat import open
24 from .pycompat import open
25 from . import (
25 from . import (
26 archival,
26 archival,
27 bookmarks,
27 bookmarks,
28 bundle2,
28 bundle2,
29 bundlecaches,
29 bundlecaches,
30 changegroup,
30 changegroup,
31 cmdutil,
31 cmdutil,
32 context as contextmod,
32 copies,
33 copies,
33 debugcommands as debugcommandsmod,
34 debugcommands as debugcommandsmod,
34 destutil,
35 destutil,
35 dirstateguard,
36 dirstateguard,
36 discovery,
37 discovery,
37 encoding,
38 encoding,
38 error,
39 error,
39 exchange,
40 exchange,
40 extensions,
41 extensions,
41 filemerge,
42 filemerge,
42 formatter,
43 formatter,
43 graphmod,
44 graphmod,
44 grep as grepmod,
45 grep as grepmod,
45 hbisect,
46 hbisect,
46 help,
47 help,
47 hg,
48 hg,
48 logcmdutil,
49 logcmdutil,
49 merge as mergemod,
50 merge as mergemod,
50 mergestate as mergestatemod,
51 mergestate as mergestatemod,
51 narrowspec,
52 narrowspec,
52 obsolete,
53 obsolete,
53 obsutil,
54 obsutil,
54 patch,
55 patch,
55 phases,
56 phases,
56 pycompat,
57 pycompat,
57 rcutil,
58 rcutil,
58 registrar,
59 registrar,
59 requirements,
60 requirements,
60 revsetlang,
61 revsetlang,
61 rewriteutil,
62 rewriteutil,
62 scmutil,
63 scmutil,
63 server,
64 server,
64 shelve as shelvemod,
65 shelve as shelvemod,
65 state as statemod,
66 state as statemod,
66 streamclone,
67 streamclone,
67 tags as tagsmod,
68 tags as tagsmod,
68 ui as uimod,
69 ui as uimod,
69 util,
70 util,
70 verify as verifymod,
71 verify as verifymod,
71 vfs as vfsmod,
72 vfs as vfsmod,
72 wireprotoserver,
73 wireprotoserver,
73 )
74 )
74 from .utils import (
75 from .utils import (
75 dateutil,
76 dateutil,
76 stringutil,
77 stringutil,
77 )
78 )
78
79
79 table = {}
80 table = {}
80 table.update(debugcommandsmod.command._table)
81 table.update(debugcommandsmod.command._table)
81
82
82 command = registrar.command(table)
83 command = registrar.command(table)
83 INTENT_READONLY = registrar.INTENT_READONLY
84 INTENT_READONLY = registrar.INTENT_READONLY
84
85
85 # common command options
86 # common command options
86
87
87 globalopts = [
88 globalopts = [
88 (
89 (
89 b'R',
90 b'R',
90 b'repository',
91 b'repository',
91 b'',
92 b'',
92 _(b'repository root directory or name of overlay bundle file'),
93 _(b'repository root directory or name of overlay bundle file'),
93 _(b'REPO'),
94 _(b'REPO'),
94 ),
95 ),
95 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
96 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
96 (
97 (
97 b'y',
98 b'y',
98 b'noninteractive',
99 b'noninteractive',
99 None,
100 None,
100 _(
101 _(
101 b'do not prompt, automatically pick the first choice for all prompts'
102 b'do not prompt, automatically pick the first choice for all prompts'
102 ),
103 ),
103 ),
104 ),
104 (b'q', b'quiet', None, _(b'suppress output')),
105 (b'q', b'quiet', None, _(b'suppress output')),
105 (b'v', b'verbose', None, _(b'enable additional output')),
106 (b'v', b'verbose', None, _(b'enable additional output')),
106 (
107 (
107 b'',
108 b'',
108 b'color',
109 b'color',
109 b'',
110 b'',
110 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
111 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
111 # and should not be translated
112 # and should not be translated
112 _(b"when to colorize (boolean, always, auto, never, or debug)"),
113 _(b"when to colorize (boolean, always, auto, never, or debug)"),
113 _(b'TYPE'),
114 _(b'TYPE'),
114 ),
115 ),
115 (
116 (
116 b'',
117 b'',
117 b'config',
118 b'config',
118 [],
119 [],
119 _(b'set/override config option (use \'section.name=value\')'),
120 _(b'set/override config option (use \'section.name=value\')'),
120 _(b'CONFIG'),
121 _(b'CONFIG'),
121 ),
122 ),
122 (b'', b'debug', None, _(b'enable debugging output')),
123 (b'', b'debug', None, _(b'enable debugging output')),
123 (b'', b'debugger', None, _(b'start debugger')),
124 (b'', b'debugger', None, _(b'start debugger')),
124 (
125 (
125 b'',
126 b'',
126 b'encoding',
127 b'encoding',
127 encoding.encoding,
128 encoding.encoding,
128 _(b'set the charset encoding'),
129 _(b'set the charset encoding'),
129 _(b'ENCODE'),
130 _(b'ENCODE'),
130 ),
131 ),
131 (
132 (
132 b'',
133 b'',
133 b'encodingmode',
134 b'encodingmode',
134 encoding.encodingmode,
135 encoding.encodingmode,
135 _(b'set the charset encoding mode'),
136 _(b'set the charset encoding mode'),
136 _(b'MODE'),
137 _(b'MODE'),
137 ),
138 ),
138 (b'', b'traceback', None, _(b'always print a traceback on exception')),
139 (b'', b'traceback', None, _(b'always print a traceback on exception')),
139 (b'', b'time', None, _(b'time how long the command takes')),
140 (b'', b'time', None, _(b'time how long the command takes')),
140 (b'', b'profile', None, _(b'print command execution profile')),
141 (b'', b'profile', None, _(b'print command execution profile')),
141 (b'', b'version', None, _(b'output version information and exit')),
142 (b'', b'version', None, _(b'output version information and exit')),
142 (b'h', b'help', None, _(b'display help and exit')),
143 (b'h', b'help', None, _(b'display help and exit')),
143 (b'', b'hidden', False, _(b'consider hidden changesets')),
144 (b'', b'hidden', False, _(b'consider hidden changesets')),
144 (
145 (
145 b'',
146 b'',
146 b'pager',
147 b'pager',
147 b'auto',
148 b'auto',
148 _(b"when to paginate (boolean, always, auto, or never)"),
149 _(b"when to paginate (boolean, always, auto, or never)"),
149 _(b'TYPE'),
150 _(b'TYPE'),
150 ),
151 ),
151 ]
152 ]
152
153
153 dryrunopts = cmdutil.dryrunopts
154 dryrunopts = cmdutil.dryrunopts
154 remoteopts = cmdutil.remoteopts
155 remoteopts = cmdutil.remoteopts
155 walkopts = cmdutil.walkopts
156 walkopts = cmdutil.walkopts
156 commitopts = cmdutil.commitopts
157 commitopts = cmdutil.commitopts
157 commitopts2 = cmdutil.commitopts2
158 commitopts2 = cmdutil.commitopts2
158 commitopts3 = cmdutil.commitopts3
159 commitopts3 = cmdutil.commitopts3
159 formatteropts = cmdutil.formatteropts
160 formatteropts = cmdutil.formatteropts
160 templateopts = cmdutil.templateopts
161 templateopts = cmdutil.templateopts
161 logopts = cmdutil.logopts
162 logopts = cmdutil.logopts
162 diffopts = cmdutil.diffopts
163 diffopts = cmdutil.diffopts
163 diffwsopts = cmdutil.diffwsopts
164 diffwsopts = cmdutil.diffwsopts
164 diffopts2 = cmdutil.diffopts2
165 diffopts2 = cmdutil.diffopts2
165 mergetoolopts = cmdutil.mergetoolopts
166 mergetoolopts = cmdutil.mergetoolopts
166 similarityopts = cmdutil.similarityopts
167 similarityopts = cmdutil.similarityopts
167 subrepoopts = cmdutil.subrepoopts
168 subrepoopts = cmdutil.subrepoopts
168 debugrevlogopts = cmdutil.debugrevlogopts
169 debugrevlogopts = cmdutil.debugrevlogopts
169
170
170 # Commands start here, listed alphabetically
171 # Commands start here, listed alphabetically
171
172
172
173
173 @command(
174 @command(
174 b'abort',
175 b'abort',
175 dryrunopts,
176 dryrunopts,
176 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
177 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
177 helpbasic=True,
178 helpbasic=True,
178 )
179 )
179 def abort(ui, repo, **opts):
180 def abort(ui, repo, **opts):
180 """abort an unfinished operation (EXPERIMENTAL)
181 """abort an unfinished operation (EXPERIMENTAL)
181
182
182 Aborts a multistep operation like graft, histedit, rebase, merge,
183 Aborts a multistep operation like graft, histedit, rebase, merge,
183 and unshelve if they are in an unfinished state.
184 and unshelve if they are in an unfinished state.
184
185
185 use --dry-run/-n to dry run the command.
186 use --dry-run/-n to dry run the command.
186 """
187 """
187 dryrun = opts.get('dry_run')
188 dryrun = opts.get('dry_run')
188 abortstate = cmdutil.getunfinishedstate(repo)
189 abortstate = cmdutil.getunfinishedstate(repo)
189 if not abortstate:
190 if not abortstate:
190 raise error.StateError(_(b'no operation in progress'))
191 raise error.StateError(_(b'no operation in progress'))
191 if not abortstate.abortfunc:
192 if not abortstate.abortfunc:
192 raise error.InputError(
193 raise error.InputError(
193 (
194 (
194 _(b"%s in progress but does not support 'hg abort'")
195 _(b"%s in progress but does not support 'hg abort'")
195 % (abortstate._opname)
196 % (abortstate._opname)
196 ),
197 ),
197 hint=abortstate.hint(),
198 hint=abortstate.hint(),
198 )
199 )
199 if dryrun:
200 if dryrun:
200 ui.status(
201 ui.status(
201 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
202 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
202 )
203 )
203 return
204 return
204 return abortstate.abortfunc(ui, repo)
205 return abortstate.abortfunc(ui, repo)
205
206
206
207
207 @command(
208 @command(
208 b'add',
209 b'add',
209 walkopts + subrepoopts + dryrunopts,
210 walkopts + subrepoopts + dryrunopts,
210 _(b'[OPTION]... [FILE]...'),
211 _(b'[OPTION]... [FILE]...'),
211 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
212 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
212 helpbasic=True,
213 helpbasic=True,
213 inferrepo=True,
214 inferrepo=True,
214 )
215 )
215 def add(ui, repo, *pats, **opts):
216 def add(ui, repo, *pats, **opts):
216 """add the specified files on the next commit
217 """add the specified files on the next commit
217
218
218 Schedule files to be version controlled and added to the
219 Schedule files to be version controlled and added to the
219 repository.
220 repository.
220
221
221 The files will be added to the repository at the next commit. To
222 The files will be added to the repository at the next commit. To
222 undo an add before that, see :hg:`forget`.
223 undo an add before that, see :hg:`forget`.
223
224
224 If no names are given, add all files to the repository (except
225 If no names are given, add all files to the repository (except
225 files matching ``.hgignore``).
226 files matching ``.hgignore``).
226
227
227 .. container:: verbose
228 .. container:: verbose
228
229
229 Examples:
230 Examples:
230
231
231 - New (unknown) files are added
232 - New (unknown) files are added
232 automatically by :hg:`add`::
233 automatically by :hg:`add`::
233
234
234 $ ls
235 $ ls
235 foo.c
236 foo.c
236 $ hg status
237 $ hg status
237 ? foo.c
238 ? foo.c
238 $ hg add
239 $ hg add
239 adding foo.c
240 adding foo.c
240 $ hg status
241 $ hg status
241 A foo.c
242 A foo.c
242
243
243 - Specific files to be added can be specified::
244 - Specific files to be added can be specified::
244
245
245 $ ls
246 $ ls
246 bar.c foo.c
247 bar.c foo.c
247 $ hg status
248 $ hg status
248 ? bar.c
249 ? bar.c
249 ? foo.c
250 ? foo.c
250 $ hg add bar.c
251 $ hg add bar.c
251 $ hg status
252 $ hg status
252 A bar.c
253 A bar.c
253 ? foo.c
254 ? foo.c
254
255
255 Returns 0 if all files are successfully added.
256 Returns 0 if all files are successfully added.
256 """
257 """
257
258
258 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
259 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
259 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
260 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
260 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
261 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
261 return rejected and 1 or 0
262 return rejected and 1 or 0
262
263
263
264
264 @command(
265 @command(
265 b'addremove',
266 b'addremove',
266 similarityopts + subrepoopts + walkopts + dryrunopts,
267 similarityopts + subrepoopts + walkopts + dryrunopts,
267 _(b'[OPTION]... [FILE]...'),
268 _(b'[OPTION]... [FILE]...'),
268 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
269 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
269 inferrepo=True,
270 inferrepo=True,
270 )
271 )
271 def addremove(ui, repo, *pats, **opts):
272 def addremove(ui, repo, *pats, **opts):
272 """add all new files, delete all missing files
273 """add all new files, delete all missing files
273
274
274 Add all new files and remove all missing files from the
275 Add all new files and remove all missing files from the
275 repository.
276 repository.
276
277
277 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
278 the patterns in ``.hgignore``. As with add, these changes take
279 the patterns in ``.hgignore``. As with add, these changes take
279 effect at the next commit.
280 effect at the next commit.
280
281
281 Use the -s/--similarity option to detect renamed files. This
282 Use the -s/--similarity option to detect renamed files. This
282 option takes a percentage between 0 (disabled) and 100 (files must
283 option takes a percentage between 0 (disabled) and 100 (files must
283 be identical) as its parameter. With a parameter greater than 0,
284 be identical) as its parameter. With a parameter greater than 0,
284 this compares every removed file with every added file and records
285 this compares every removed file with every added file and records
285 those similar enough as renames. Detecting renamed files this way
286 those similar enough as renames. Detecting renamed files this way
286 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
287 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
288 not specified, -s/--similarity defaults to 100 and only renames of
289 not specified, -s/--similarity defaults to 100 and only renames of
289 identical files are detected.
290 identical files are detected.
290
291
291 .. container:: verbose
292 .. container:: verbose
292
293
293 Examples:
294 Examples:
294
295
295 - A number of files (bar.c and foo.c) are new,
296 - A number of files (bar.c and foo.c) are new,
296 while foobar.c has been removed (without using :hg:`remove`)
297 while foobar.c has been removed (without using :hg:`remove`)
297 from the repository::
298 from the repository::
298
299
299 $ ls
300 $ ls
300 bar.c foo.c
301 bar.c foo.c
301 $ hg status
302 $ hg status
302 ! foobar.c
303 ! foobar.c
303 ? bar.c
304 ? bar.c
304 ? foo.c
305 ? foo.c
305 $ hg addremove
306 $ hg addremove
306 adding bar.c
307 adding bar.c
307 adding foo.c
308 adding foo.c
308 removing foobar.c
309 removing foobar.c
309 $ hg status
310 $ hg status
310 A bar.c
311 A bar.c
311 A foo.c
312 A foo.c
312 R foobar.c
313 R foobar.c
313
314
314 - 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`.
315 Afterwards, it was edited slightly::
316 Afterwards, it was edited slightly::
316
317
317 $ ls
318 $ ls
318 foo.c
319 foo.c
319 $ hg status
320 $ hg status
320 ! foobar.c
321 ! foobar.c
321 ? foo.c
322 ? foo.c
322 $ hg addremove --similarity 90
323 $ hg addremove --similarity 90
323 removing foobar.c
324 removing foobar.c
324 adding foo.c
325 adding foo.c
325 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)
326 $ hg status -C
327 $ hg status -C
327 A foo.c
328 A foo.c
328 foobar.c
329 foobar.c
329 R foobar.c
330 R foobar.c
330
331
331 Returns 0 if all files are successfully added.
332 Returns 0 if all files are successfully added.
332 """
333 """
333 opts = pycompat.byteskwargs(opts)
334 opts = pycompat.byteskwargs(opts)
334 if not opts.get(b'similarity'):
335 if not opts.get(b'similarity'):
335 opts[b'similarity'] = b'100'
336 opts[b'similarity'] = b'100'
336 matcher = scmutil.match(repo[None], pats, opts)
337 matcher = scmutil.match(repo[None], pats, opts)
337 relative = scmutil.anypats(pats, opts)
338 relative = scmutil.anypats(pats, opts)
338 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
339 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
339 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
340 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
340
341
341
342
342 @command(
343 @command(
343 b'annotate|blame',
344 b'annotate|blame',
344 [
345 [
345 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
346 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
346 (
347 (
347 b'',
348 b'',
348 b'follow',
349 b'follow',
349 None,
350 None,
350 _(b'follow copies/renames and list the filename (DEPRECATED)'),
351 _(b'follow copies/renames and list the filename (DEPRECATED)'),
351 ),
352 ),
352 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
353 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
353 (b'a', b'text', None, _(b'treat all files as text')),
354 (b'a', b'text', None, _(b'treat all files as text')),
354 (b'u', b'user', None, _(b'list the author (long with -v)')),
355 (b'u', b'user', None, _(b'list the author (long with -v)')),
355 (b'f', b'file', None, _(b'list the filename')),
356 (b'f', b'file', None, _(b'list the filename')),
356 (b'd', b'date', None, _(b'list the date (short with -q)')),
357 (b'd', b'date', None, _(b'list the date (short with -q)')),
357 (b'n', b'number', None, _(b'list the revision number (default)')),
358 (b'n', b'number', None, _(b'list the revision number (default)')),
358 (b'c', b'changeset', None, _(b'list the changeset')),
359 (b'c', b'changeset', None, _(b'list the changeset')),
359 (
360 (
360 b'l',
361 b'l',
361 b'line-number',
362 b'line-number',
362 None,
363 None,
363 _(b'show line number at the first appearance'),
364 _(b'show line number at the first appearance'),
364 ),
365 ),
365 (
366 (
366 b'',
367 b'',
367 b'skip',
368 b'skip',
368 [],
369 [],
369 _(b'revset to not display (EXPERIMENTAL)'),
370 _(b'revset to not display (EXPERIMENTAL)'),
370 _(b'REV'),
371 _(b'REV'),
371 ),
372 ),
372 ]
373 ]
373 + diffwsopts
374 + diffwsopts
374 + walkopts
375 + walkopts
375 + formatteropts,
376 + formatteropts,
376 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
377 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
377 helpcategory=command.CATEGORY_FILE_CONTENTS,
378 helpcategory=command.CATEGORY_FILE_CONTENTS,
378 helpbasic=True,
379 helpbasic=True,
379 inferrepo=True,
380 inferrepo=True,
380 )
381 )
381 def annotate(ui, repo, *pats, **opts):
382 def annotate(ui, repo, *pats, **opts):
382 """show changeset information by line for each file
383 """show changeset information by line for each file
383
384
384 List changes in files, showing the revision id responsible for
385 List changes in files, showing the revision id responsible for
385 each line.
386 each line.
386
387
387 This command is useful for discovering when a change was made and
388 This command is useful for discovering when a change was made and
388 by whom.
389 by whom.
389
390
390 If you include --file, --user, or --date, the revision number is
391 If you include --file, --user, or --date, the revision number is
391 suppressed unless you also include --number.
392 suppressed unless you also include --number.
392
393
393 Without the -a/--text option, annotate will avoid processing files
394 Without the -a/--text option, annotate will avoid processing files
394 it detects as binary. With -a, annotate will annotate the file
395 it detects as binary. With -a, annotate will annotate the file
395 anyway, although the results will probably be neither useful
396 anyway, although the results will probably be neither useful
396 nor desirable.
397 nor desirable.
397
398
398 .. container:: verbose
399 .. container:: verbose
399
400
400 Template:
401 Template:
401
402
402 The following keywords are supported in addition to the common template
403 The following keywords are supported in addition to the common template
403 keywords and functions. See also :hg:`help templates`.
404 keywords and functions. See also :hg:`help templates`.
404
405
405 :lines: List of lines with annotation data.
406 :lines: List of lines with annotation data.
406 :path: String. Repository-absolute path of the specified file.
407 :path: String. Repository-absolute path of the specified file.
407
408
408 And each entry of ``{lines}`` provides the following sub-keywords in
409 And each entry of ``{lines}`` provides the following sub-keywords in
409 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
410 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
410
411
411 :line: String. Line content.
412 :line: String. Line content.
412 :lineno: Integer. Line number at that revision.
413 :lineno: Integer. Line number at that revision.
413 :path: String. Repository-absolute path of the file at that revision.
414 :path: String. Repository-absolute path of the file at that revision.
414
415
415 See :hg:`help templates.operators` for the list expansion syntax.
416 See :hg:`help templates.operators` for the list expansion syntax.
416
417
417 Returns 0 on success.
418 Returns 0 on success.
418 """
419 """
419 opts = pycompat.byteskwargs(opts)
420 opts = pycompat.byteskwargs(opts)
420 if not pats:
421 if not pats:
421 raise error.InputError(
422 raise error.InputError(
422 _(b'at least one filename or pattern is required')
423 _(b'at least one filename or pattern is required')
423 )
424 )
424
425
425 if opts.get(b'follow'):
426 if opts.get(b'follow'):
426 # --follow is deprecated and now just an alias for -f/--file
427 # --follow is deprecated and now just an alias for -f/--file
427 # to mimic the behavior of Mercurial before version 1.5
428 # to mimic the behavior of Mercurial before version 1.5
428 opts[b'file'] = True
429 opts[b'file'] = True
429
430
430 if (
431 if (
431 not opts.get(b'user')
432 not opts.get(b'user')
432 and not opts.get(b'changeset')
433 and not opts.get(b'changeset')
433 and not opts.get(b'date')
434 and not opts.get(b'date')
434 and not opts.get(b'file')
435 and not opts.get(b'file')
435 ):
436 ):
436 opts[b'number'] = True
437 opts[b'number'] = True
437
438
438 linenumber = opts.get(b'line_number') is not None
439 linenumber = opts.get(b'line_number') is not None
439 if (
440 if (
440 linenumber
441 linenumber
441 and (not opts.get(b'changeset'))
442 and (not opts.get(b'changeset'))
442 and (not opts.get(b'number'))
443 and (not opts.get(b'number'))
443 ):
444 ):
444 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
445 raise error.InputError(_(b'at least one of -n/-c is required for -l'))
445
446
446 rev = opts.get(b'rev')
447 rev = opts.get(b'rev')
447 if rev:
448 if rev:
448 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
449 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
449 ctx = scmutil.revsingle(repo, rev)
450 ctx = scmutil.revsingle(repo, rev)
450
451
451 ui.pager(b'annotate')
452 ui.pager(b'annotate')
452 rootfm = ui.formatter(b'annotate', opts)
453 rootfm = ui.formatter(b'annotate', opts)
453 if ui.debugflag:
454 if ui.debugflag:
454 shorthex = pycompat.identity
455 shorthex = pycompat.identity
455 else:
456 else:
456
457
457 def shorthex(h):
458 def shorthex(h):
458 return h[:12]
459 return h[:12]
459
460
460 if ui.quiet:
461 if ui.quiet:
461 datefunc = dateutil.shortdate
462 datefunc = dateutil.shortdate
462 else:
463 else:
463 datefunc = dateutil.datestr
464 datefunc = dateutil.datestr
464 if ctx.rev() is None:
465 if ctx.rev() is None:
465 if opts.get(b'changeset'):
466 if opts.get(b'changeset'):
466 # omit "+" suffix which is appended to node hex
467 # omit "+" suffix which is appended to node hex
467 def formatrev(rev):
468 def formatrev(rev):
468 if rev == wdirrev:
469 if rev == wdirrev:
469 return b'%d' % ctx.p1().rev()
470 return b'%d' % ctx.p1().rev()
470 else:
471 else:
471 return b'%d' % rev
472 return b'%d' % rev
472
473
473 else:
474 else:
474
475
475 def formatrev(rev):
476 def formatrev(rev):
476 if rev == wdirrev:
477 if rev == wdirrev:
477 return b'%d+' % ctx.p1().rev()
478 return b'%d+' % ctx.p1().rev()
478 else:
479 else:
479 return b'%d ' % rev
480 return b'%d ' % rev
480
481
481 def formathex(h):
482 def formathex(h):
482 if h == wdirhex:
483 if h == wdirhex:
483 return b'%s+' % shorthex(hex(ctx.p1().node()))
484 return b'%s+' % shorthex(hex(ctx.p1().node()))
484 else:
485 else:
485 return b'%s ' % shorthex(h)
486 return b'%s ' % shorthex(h)
486
487
487 else:
488 else:
488 formatrev = b'%d'.__mod__
489 formatrev = b'%d'.__mod__
489 formathex = shorthex
490 formathex = shorthex
490
491
491 opmap = [
492 opmap = [
492 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
493 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
493 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
494 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
494 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
495 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
495 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
496 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
496 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
497 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
497 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
498 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
498 ]
499 ]
499 opnamemap = {
500 opnamemap = {
500 b'rev': b'number',
501 b'rev': b'number',
501 b'node': b'changeset',
502 b'node': b'changeset',
502 b'path': b'file',
503 b'path': b'file',
503 b'lineno': b'line_number',
504 b'lineno': b'line_number',
504 }
505 }
505
506
506 if rootfm.isplain():
507 if rootfm.isplain():
507
508
508 def makefunc(get, fmt):
509 def makefunc(get, fmt):
509 return lambda x: fmt(get(x))
510 return lambda x: fmt(get(x))
510
511
511 else:
512 else:
512
513
513 def makefunc(get, fmt):
514 def makefunc(get, fmt):
514 return get
515 return get
515
516
516 datahint = rootfm.datahint()
517 datahint = rootfm.datahint()
517 funcmap = [
518 funcmap = [
518 (makefunc(get, fmt), sep)
519 (makefunc(get, fmt), sep)
519 for fn, sep, get, fmt in opmap
520 for fn, sep, get, fmt in opmap
520 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
521 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
521 ]
522 ]
522 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
523 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
523 fields = b' '.join(
524 fields = b' '.join(
524 fn
525 fn
525 for fn, sep, get, fmt in opmap
526 for fn, sep, get, fmt in opmap
526 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
527 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
527 )
528 )
528
529
529 def bad(x, y):
530 def bad(x, y):
530 raise error.Abort(b"%s: %s" % (x, y))
531 raise error.Abort(b"%s: %s" % (x, y))
531
532
532 m = scmutil.match(ctx, pats, opts, badfn=bad)
533 m = scmutil.match(ctx, pats, opts, badfn=bad)
533
534
534 follow = not opts.get(b'no_follow')
535 follow = not opts.get(b'no_follow')
535 diffopts = patch.difffeatureopts(
536 diffopts = patch.difffeatureopts(
536 ui, opts, section=b'annotate', whitespace=True
537 ui, opts, section=b'annotate', whitespace=True
537 )
538 )
538 skiprevs = opts.get(b'skip')
539 skiprevs = opts.get(b'skip')
539 if skiprevs:
540 if skiprevs:
540 skiprevs = scmutil.revrange(repo, skiprevs)
541 skiprevs = scmutil.revrange(repo, skiprevs)
541
542
542 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
543 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
543 for abs in ctx.walk(m):
544 for abs in ctx.walk(m):
544 fctx = ctx[abs]
545 fctx = ctx[abs]
545 rootfm.startitem()
546 rootfm.startitem()
546 rootfm.data(path=abs)
547 rootfm.data(path=abs)
547 if not opts.get(b'text') and fctx.isbinary():
548 if not opts.get(b'text') and fctx.isbinary():
548 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
549 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
549 continue
550 continue
550
551
551 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
552 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
552 lines = fctx.annotate(
553 lines = fctx.annotate(
553 follow=follow, skiprevs=skiprevs, diffopts=diffopts
554 follow=follow, skiprevs=skiprevs, diffopts=diffopts
554 )
555 )
555 if not lines:
556 if not lines:
556 fm.end()
557 fm.end()
557 continue
558 continue
558 formats = []
559 formats = []
559 pieces = []
560 pieces = []
560
561
561 for f, sep in funcmap:
562 for f, sep in funcmap:
562 l = [f(n) for n in lines]
563 l = [f(n) for n in lines]
563 if fm.isplain():
564 if fm.isplain():
564 sizes = [encoding.colwidth(x) for x in l]
565 sizes = [encoding.colwidth(x) for x in l]
565 ml = max(sizes)
566 ml = max(sizes)
566 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
567 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
567 else:
568 else:
568 formats.append([b'%s'] * len(l))
569 formats.append([b'%s'] * len(l))
569 pieces.append(l)
570 pieces.append(l)
570
571
571 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
572 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
572 fm.startitem()
573 fm.startitem()
573 fm.context(fctx=n.fctx)
574 fm.context(fctx=n.fctx)
574 fm.write(fields, b"".join(f), *p)
575 fm.write(fields, b"".join(f), *p)
575 if n.skip:
576 if n.skip:
576 fmt = b"* %s"
577 fmt = b"* %s"
577 else:
578 else:
578 fmt = b": %s"
579 fmt = b": %s"
579 fm.write(b'line', fmt, n.text)
580 fm.write(b'line', fmt, n.text)
580
581
581 if not lines[-1].text.endswith(b'\n'):
582 if not lines[-1].text.endswith(b'\n'):
582 fm.plain(b'\n')
583 fm.plain(b'\n')
583 fm.end()
584 fm.end()
584
585
585 rootfm.end()
586 rootfm.end()
586
587
587
588
588 @command(
589 @command(
589 b'archive',
590 b'archive',
590 [
591 [
591 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
592 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
592 (
593 (
593 b'p',
594 b'p',
594 b'prefix',
595 b'prefix',
595 b'',
596 b'',
596 _(b'directory prefix for files in archive'),
597 _(b'directory prefix for files in archive'),
597 _(b'PREFIX'),
598 _(b'PREFIX'),
598 ),
599 ),
599 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
600 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
600 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
601 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
601 ]
602 ]
602 + subrepoopts
603 + subrepoopts
603 + walkopts,
604 + walkopts,
604 _(b'[OPTION]... DEST'),
605 _(b'[OPTION]... DEST'),
605 helpcategory=command.CATEGORY_IMPORT_EXPORT,
606 helpcategory=command.CATEGORY_IMPORT_EXPORT,
606 )
607 )
607 def archive(ui, repo, dest, **opts):
608 def archive(ui, repo, dest, **opts):
608 """create an unversioned archive of a repository revision
609 """create an unversioned archive of a repository revision
609
610
610 By default, the revision used is the parent of the working
611 By default, the revision used is the parent of the working
611 directory; use -r/--rev to specify a different revision.
612 directory; use -r/--rev to specify a different revision.
612
613
613 The archive type is automatically detected based on file
614 The archive type is automatically detected based on file
614 extension (to override, use -t/--type).
615 extension (to override, use -t/--type).
615
616
616 .. container:: verbose
617 .. container:: verbose
617
618
618 Examples:
619 Examples:
619
620
620 - create a zip file containing the 1.0 release::
621 - create a zip file containing the 1.0 release::
621
622
622 hg archive -r 1.0 project-1.0.zip
623 hg archive -r 1.0 project-1.0.zip
623
624
624 - create a tarball excluding .hg files::
625 - create a tarball excluding .hg files::
625
626
626 hg archive project.tar.gz -X ".hg*"
627 hg archive project.tar.gz -X ".hg*"
627
628
628 Valid types are:
629 Valid types are:
629
630
630 :``files``: a directory full of files (default)
631 :``files``: a directory full of files (default)
631 :``tar``: tar archive, uncompressed
632 :``tar``: tar archive, uncompressed
632 :``tbz2``: tar archive, compressed using bzip2
633 :``tbz2``: tar archive, compressed using bzip2
633 :``tgz``: tar archive, compressed using gzip
634 :``tgz``: tar archive, compressed using gzip
634 :``txz``: tar archive, compressed using lzma (only in Python 3)
635 :``txz``: tar archive, compressed using lzma (only in Python 3)
635 :``uzip``: zip archive, uncompressed
636 :``uzip``: zip archive, uncompressed
636 :``zip``: zip archive, compressed using deflate
637 :``zip``: zip archive, compressed using deflate
637
638
638 The exact name of the destination archive or directory is given
639 The exact name of the destination archive or directory is given
639 using a format string; see :hg:`help export` for details.
640 using a format string; see :hg:`help export` for details.
640
641
641 Each member added to an archive file has a directory prefix
642 Each member added to an archive file has a directory prefix
642 prepended. Use -p/--prefix to specify a format string for the
643 prepended. Use -p/--prefix to specify a format string for the
643 prefix. The default is the basename of the archive, with suffixes
644 prefix. The default is the basename of the archive, with suffixes
644 removed.
645 removed.
645
646
646 Returns 0 on success.
647 Returns 0 on success.
647 """
648 """
648
649
649 opts = pycompat.byteskwargs(opts)
650 opts = pycompat.byteskwargs(opts)
650 rev = opts.get(b'rev')
651 rev = opts.get(b'rev')
651 if rev:
652 if rev:
652 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
653 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
653 ctx = scmutil.revsingle(repo, rev)
654 ctx = scmutil.revsingle(repo, rev)
654 if not ctx:
655 if not ctx:
655 raise error.InputError(
656 raise error.InputError(
656 _(b'no working directory: please specify a revision')
657 _(b'no working directory: please specify a revision')
657 )
658 )
658 node = ctx.node()
659 node = ctx.node()
659 dest = cmdutil.makefilename(ctx, dest)
660 dest = cmdutil.makefilename(ctx, dest)
660 if os.path.realpath(dest) == repo.root:
661 if os.path.realpath(dest) == repo.root:
661 raise error.InputError(_(b'repository root cannot be destination'))
662 raise error.InputError(_(b'repository root cannot be destination'))
662
663
663 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
664 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
664 prefix = opts.get(b'prefix')
665 prefix = opts.get(b'prefix')
665
666
666 if dest == b'-':
667 if dest == b'-':
667 if kind == b'files':
668 if kind == b'files':
668 raise error.InputError(_(b'cannot archive plain files to stdout'))
669 raise error.InputError(_(b'cannot archive plain files to stdout'))
669 dest = cmdutil.makefileobj(ctx, dest)
670 dest = cmdutil.makefileobj(ctx, dest)
670 if not prefix:
671 if not prefix:
671 prefix = os.path.basename(repo.root) + b'-%h'
672 prefix = os.path.basename(repo.root) + b'-%h'
672
673
673 prefix = cmdutil.makefilename(ctx, prefix)
674 prefix = cmdutil.makefilename(ctx, prefix)
674 match = scmutil.match(ctx, [], opts)
675 match = scmutil.match(ctx, [], opts)
675 archival.archive(
676 archival.archive(
676 repo,
677 repo,
677 dest,
678 dest,
678 node,
679 node,
679 kind,
680 kind,
680 not opts.get(b'no_decode'),
681 not opts.get(b'no_decode'),
681 match,
682 match,
682 prefix,
683 prefix,
683 subrepos=opts.get(b'subrepos'),
684 subrepos=opts.get(b'subrepos'),
684 )
685 )
685
686
686
687
687 @command(
688 @command(
688 b'backout',
689 b'backout',
689 [
690 [
690 (
691 (
691 b'',
692 b'',
692 b'merge',
693 b'merge',
693 None,
694 None,
694 _(b'merge with old dirstate parent after backout'),
695 _(b'merge with old dirstate parent after backout'),
695 ),
696 ),
696 (
697 (
697 b'',
698 b'',
698 b'commit',
699 b'commit',
699 None,
700 None,
700 _(b'commit if no conflicts were encountered (DEPRECATED)'),
701 _(b'commit if no conflicts were encountered (DEPRECATED)'),
701 ),
702 ),
702 (b'', b'no-commit', None, _(b'do not commit')),
703 (b'', b'no-commit', None, _(b'do not commit')),
703 (
704 (
704 b'',
705 b'',
705 b'parent',
706 b'parent',
706 b'',
707 b'',
707 _(b'parent to choose when backing out merge (DEPRECATED)'),
708 _(b'parent to choose when backing out merge (DEPRECATED)'),
708 _(b'REV'),
709 _(b'REV'),
709 ),
710 ),
710 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
711 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
711 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
712 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
712 ]
713 ]
713 + mergetoolopts
714 + mergetoolopts
714 + walkopts
715 + walkopts
715 + commitopts
716 + commitopts
716 + commitopts2,
717 + commitopts2,
717 _(b'[OPTION]... [-r] REV'),
718 _(b'[OPTION]... [-r] REV'),
718 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
719 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
719 )
720 )
720 def backout(ui, repo, node=None, rev=None, **opts):
721 def backout(ui, repo, node=None, rev=None, **opts):
721 """reverse effect of earlier changeset
722 """reverse effect of earlier changeset
722
723
723 Prepare a new changeset with the effect of REV undone in the
724 Prepare a new changeset with the effect of REV undone in the
724 current working directory. If no conflicts were encountered,
725 current working directory. If no conflicts were encountered,
725 it will be committed immediately.
726 it will be committed immediately.
726
727
727 If REV is the parent of the working directory, then this new changeset
728 If REV is the parent of the working directory, then this new changeset
728 is committed automatically (unless --no-commit is specified).
729 is committed automatically (unless --no-commit is specified).
729
730
730 .. note::
731 .. note::
731
732
732 :hg:`backout` cannot be used to fix either an unwanted or
733 :hg:`backout` cannot be used to fix either an unwanted or
733 incorrect merge.
734 incorrect merge.
734
735
735 .. container:: verbose
736 .. container:: verbose
736
737
737 Examples:
738 Examples:
738
739
739 - Reverse the effect of the parent of the working directory.
740 - Reverse the effect of the parent of the working directory.
740 This backout will be committed immediately::
741 This backout will be committed immediately::
741
742
742 hg backout -r .
743 hg backout -r .
743
744
744 - Reverse the effect of previous bad revision 23::
745 - Reverse the effect of previous bad revision 23::
745
746
746 hg backout -r 23
747 hg backout -r 23
747
748
748 - Reverse the effect of previous bad revision 23 and
749 - Reverse the effect of previous bad revision 23 and
749 leave changes uncommitted::
750 leave changes uncommitted::
750
751
751 hg backout -r 23 --no-commit
752 hg backout -r 23 --no-commit
752 hg commit -m "Backout revision 23"
753 hg commit -m "Backout revision 23"
753
754
754 By default, the pending changeset will have one parent,
755 By default, the pending changeset will have one parent,
755 maintaining a linear history. With --merge, the pending
756 maintaining a linear history. With --merge, the pending
756 changeset will instead have two parents: the old parent of the
757 changeset will instead have two parents: the old parent of the
757 working directory and a new child of REV that simply undoes REV.
758 working directory and a new child of REV that simply undoes REV.
758
759
759 Before version 1.7, the behavior without --merge was equivalent
760 Before version 1.7, the behavior without --merge was equivalent
760 to specifying --merge followed by :hg:`update --clean .` to
761 to specifying --merge followed by :hg:`update --clean .` to
761 cancel the merge and leave the child of REV as a head to be
762 cancel the merge and leave the child of REV as a head to be
762 merged separately.
763 merged separately.
763
764
764 See :hg:`help dates` for a list of formats valid for -d/--date.
765 See :hg:`help dates` for a list of formats valid for -d/--date.
765
766
766 See :hg:`help revert` for a way to restore files to the state
767 See :hg:`help revert` for a way to restore files to the state
767 of another revision.
768 of another revision.
768
769
769 Returns 0 on success, 1 if nothing to backout or there are unresolved
770 Returns 0 on success, 1 if nothing to backout or there are unresolved
770 files.
771 files.
771 """
772 """
772 with repo.wlock(), repo.lock():
773 with repo.wlock(), repo.lock():
773 return _dobackout(ui, repo, node, rev, **opts)
774 return _dobackout(ui, repo, node, rev, **opts)
774
775
775
776
776 def _dobackout(ui, repo, node=None, rev=None, **opts):
777 def _dobackout(ui, repo, node=None, rev=None, **opts):
777 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
778 cmdutil.check_incompatible_arguments(opts, 'no_commit', ['commit', 'merge'])
778 opts = pycompat.byteskwargs(opts)
779 opts = pycompat.byteskwargs(opts)
779
780
780 if rev and node:
781 if rev and node:
781 raise error.InputError(_(b"please specify just one revision"))
782 raise error.InputError(_(b"please specify just one revision"))
782
783
783 if not rev:
784 if not rev:
784 rev = node
785 rev = node
785
786
786 if not rev:
787 if not rev:
787 raise error.InputError(_(b"please specify a revision to backout"))
788 raise error.InputError(_(b"please specify a revision to backout"))
788
789
789 date = opts.get(b'date')
790 date = opts.get(b'date')
790 if date:
791 if date:
791 opts[b'date'] = dateutil.parsedate(date)
792 opts[b'date'] = dateutil.parsedate(date)
792
793
793 cmdutil.checkunfinished(repo)
794 cmdutil.checkunfinished(repo)
794 cmdutil.bailifchanged(repo)
795 cmdutil.bailifchanged(repo)
795 ctx = scmutil.revsingle(repo, rev)
796 ctx = scmutil.revsingle(repo, rev)
796 node = ctx.node()
797 node = ctx.node()
797
798
798 op1, op2 = repo.dirstate.parents()
799 op1, op2 = repo.dirstate.parents()
799 if not repo.changelog.isancestor(node, op1):
800 if not repo.changelog.isancestor(node, op1):
800 raise error.InputError(
801 raise error.InputError(
801 _(b'cannot backout change that is not an ancestor')
802 _(b'cannot backout change that is not an ancestor')
802 )
803 )
803
804
804 p1, p2 = repo.changelog.parents(node)
805 p1, p2 = repo.changelog.parents(node)
805 if p1 == nullid:
806 if p1 == nullid:
806 raise error.InputError(_(b'cannot backout a change with no parents'))
807 raise error.InputError(_(b'cannot backout a change with no parents'))
807 if p2 != nullid:
808 if p2 != nullid:
808 if not opts.get(b'parent'):
809 if not opts.get(b'parent'):
809 raise error.InputError(_(b'cannot backout a merge changeset'))
810 raise error.InputError(_(b'cannot backout a merge changeset'))
810 p = repo.lookup(opts[b'parent'])
811 p = repo.lookup(opts[b'parent'])
811 if p not in (p1, p2):
812 if p not in (p1, p2):
812 raise error.InputError(
813 raise error.InputError(
813 _(b'%s is not a parent of %s') % (short(p), short(node))
814 _(b'%s is not a parent of %s') % (short(p), short(node))
814 )
815 )
815 parent = p
816 parent = p
816 else:
817 else:
817 if opts.get(b'parent'):
818 if opts.get(b'parent'):
818 raise error.InputError(
819 raise error.InputError(
819 _(b'cannot use --parent on non-merge changeset')
820 _(b'cannot use --parent on non-merge changeset')
820 )
821 )
821 parent = p1
822 parent = p1
822
823
823 # the backout should appear on the same branch
824 # the backout should appear on the same branch
824 branch = repo.dirstate.branch()
825 branch = repo.dirstate.branch()
825 bheads = repo.branchheads(branch)
826 bheads = repo.branchheads(branch)
826 rctx = scmutil.revsingle(repo, hex(parent))
827 rctx = scmutil.revsingle(repo, hex(parent))
827 if not opts.get(b'merge') and op1 != node:
828 if not opts.get(b'merge') and op1 != node:
828 with dirstateguard.dirstateguard(repo, b'backout'):
829 with dirstateguard.dirstateguard(repo, b'backout'):
829 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
830 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
830 with ui.configoverride(overrides, b'backout'):
831 with ui.configoverride(overrides, b'backout'):
831 stats = mergemod.back_out(ctx, parent=repo[parent])
832 stats = mergemod.back_out(ctx, parent=repo[parent])
832 repo.setparents(op1, op2)
833 repo.setparents(op1, op2)
833 hg._showstats(repo, stats)
834 hg._showstats(repo, stats)
834 if stats.unresolvedcount:
835 if stats.unresolvedcount:
835 repo.ui.status(
836 repo.ui.status(
836 _(b"use 'hg resolve' to retry unresolved file merges\n")
837 _(b"use 'hg resolve' to retry unresolved file merges\n")
837 )
838 )
838 return 1
839 return 1
839 else:
840 else:
840 hg.clean(repo, node, show_stats=False)
841 hg.clean(repo, node, show_stats=False)
841 repo.dirstate.setbranch(branch)
842 repo.dirstate.setbranch(branch)
842 cmdutil.revert(ui, repo, rctx)
843 cmdutil.revert(ui, repo, rctx)
843
844
844 if opts.get(b'no_commit'):
845 if opts.get(b'no_commit'):
845 msg = _(b"changeset %s backed out, don't forget to commit.\n")
846 msg = _(b"changeset %s backed out, don't forget to commit.\n")
846 ui.status(msg % short(node))
847 ui.status(msg % short(node))
847 return 0
848 return 0
848
849
849 def commitfunc(ui, repo, message, match, opts):
850 def commitfunc(ui, repo, message, match, opts):
850 editform = b'backout'
851 editform = b'backout'
851 e = cmdutil.getcommiteditor(
852 e = cmdutil.getcommiteditor(
852 editform=editform, **pycompat.strkwargs(opts)
853 editform=editform, **pycompat.strkwargs(opts)
853 )
854 )
854 if not message:
855 if not message:
855 # we don't translate commit messages
856 # we don't translate commit messages
856 message = b"Backed out changeset %s" % short(node)
857 message = b"Backed out changeset %s" % short(node)
857 e = cmdutil.getcommiteditor(edit=True, editform=editform)
858 e = cmdutil.getcommiteditor(edit=True, editform=editform)
858 return repo.commit(
859 return repo.commit(
859 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
860 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
860 )
861 )
861
862
862 # save to detect changes
863 # save to detect changes
863 tip = repo.changelog.tip()
864 tip = repo.changelog.tip()
864
865
865 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
866 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
866 if not newnode:
867 if not newnode:
867 ui.status(_(b"nothing changed\n"))
868 ui.status(_(b"nothing changed\n"))
868 return 1
869 return 1
869 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
870 cmdutil.commitstatus(repo, newnode, branch, bheads, tip)
870
871
871 def nice(node):
872 def nice(node):
872 return b'%d:%s' % (repo.changelog.rev(node), short(node))
873 return b'%d:%s' % (repo.changelog.rev(node), short(node))
873
874
874 ui.status(
875 ui.status(
875 _(b'changeset %s backs out changeset %s\n')
876 _(b'changeset %s backs out changeset %s\n')
876 % (nice(newnode), nice(node))
877 % (nice(newnode), nice(node))
877 )
878 )
878 if opts.get(b'merge') and op1 != node:
879 if opts.get(b'merge') and op1 != node:
879 hg.clean(repo, op1, show_stats=False)
880 hg.clean(repo, op1, show_stats=False)
880 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
881 ui.status(_(b'merging with changeset %s\n') % nice(newnode))
881 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
882 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
882 with ui.configoverride(overrides, b'backout'):
883 with ui.configoverride(overrides, b'backout'):
883 return hg.merge(repo[b'tip'])
884 return hg.merge(repo[b'tip'])
884 return 0
885 return 0
885
886
886
887
887 @command(
888 @command(
888 b'bisect',
889 b'bisect',
889 [
890 [
890 (b'r', b'reset', False, _(b'reset bisect state')),
891 (b'r', b'reset', False, _(b'reset bisect state')),
891 (b'g', b'good', False, _(b'mark changeset good')),
892 (b'g', b'good', False, _(b'mark changeset good')),
892 (b'b', b'bad', False, _(b'mark changeset bad')),
893 (b'b', b'bad', False, _(b'mark changeset bad')),
893 (b's', b'skip', False, _(b'skip testing changeset')),
894 (b's', b'skip', False, _(b'skip testing changeset')),
894 (b'e', b'extend', False, _(b'extend the bisect range')),
895 (b'e', b'extend', False, _(b'extend the bisect range')),
895 (
896 (
896 b'c',
897 b'c',
897 b'command',
898 b'command',
898 b'',
899 b'',
899 _(b'use command to check changeset state'),
900 _(b'use command to check changeset state'),
900 _(b'CMD'),
901 _(b'CMD'),
901 ),
902 ),
902 (b'U', b'noupdate', False, _(b'do not update to target')),
903 (b'U', b'noupdate', False, _(b'do not update to target')),
903 ],
904 ],
904 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
905 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
905 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
906 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
906 )
907 )
907 def bisect(
908 def bisect(
908 ui,
909 ui,
909 repo,
910 repo,
910 positional_1=None,
911 positional_1=None,
911 positional_2=None,
912 positional_2=None,
912 command=None,
913 command=None,
913 reset=None,
914 reset=None,
914 good=None,
915 good=None,
915 bad=None,
916 bad=None,
916 skip=None,
917 skip=None,
917 extend=None,
918 extend=None,
918 noupdate=None,
919 noupdate=None,
919 ):
920 ):
920 """subdivision search of changesets
921 """subdivision search of changesets
921
922
922 This command helps to find changesets which introduce problems. To
923 This command helps to find changesets which introduce problems. To
923 use, mark the earliest changeset you know exhibits the problem as
924 use, mark the earliest changeset you know exhibits the problem as
924 bad, then mark the latest changeset which is free from the problem
925 bad, then mark the latest changeset which is free from the problem
925 as good. Bisect will update your working directory to a revision
926 as good. Bisect will update your working directory to a revision
926 for testing (unless the -U/--noupdate option is specified). Once
927 for testing (unless the -U/--noupdate option is specified). Once
927 you have performed tests, mark the working directory as good or
928 you have performed tests, mark the working directory as good or
928 bad, and bisect will either update to another candidate changeset
929 bad, and bisect will either update to another candidate changeset
929 or announce that it has found the bad revision.
930 or announce that it has found the bad revision.
930
931
931 As a shortcut, you can also use the revision argument to mark a
932 As a shortcut, you can also use the revision argument to mark a
932 revision as good or bad without checking it out first.
933 revision as good or bad without checking it out first.
933
934
934 If you supply a command, it will be used for automatic bisection.
935 If you supply a command, it will be used for automatic bisection.
935 The environment variable HG_NODE will contain the ID of the
936 The environment variable HG_NODE will contain the ID of the
936 changeset being tested. The exit status of the command will be
937 changeset being tested. The exit status of the command will be
937 used to mark revisions as good or bad: status 0 means good, 125
938 used to mark revisions as good or bad: status 0 means good, 125
938 means to skip the revision, 127 (command not found) will abort the
939 means to skip the revision, 127 (command not found) will abort the
939 bisection, and any other non-zero exit status means the revision
940 bisection, and any other non-zero exit status means the revision
940 is bad.
941 is bad.
941
942
942 .. container:: verbose
943 .. container:: verbose
943
944
944 Some examples:
945 Some examples:
945
946
946 - start a bisection with known bad revision 34, and good revision 12::
947 - start a bisection with known bad revision 34, and good revision 12::
947
948
948 hg bisect --bad 34
949 hg bisect --bad 34
949 hg bisect --good 12
950 hg bisect --good 12
950
951
951 - advance the current bisection by marking current revision as good or
952 - advance the current bisection by marking current revision as good or
952 bad::
953 bad::
953
954
954 hg bisect --good
955 hg bisect --good
955 hg bisect --bad
956 hg bisect --bad
956
957
957 - mark the current revision, or a known revision, to be skipped (e.g. if
958 - mark the current revision, or a known revision, to be skipped (e.g. if
958 that revision is not usable because of another issue)::
959 that revision is not usable because of another issue)::
959
960
960 hg bisect --skip
961 hg bisect --skip
961 hg bisect --skip 23
962 hg bisect --skip 23
962
963
963 - skip all revisions that do not touch directories ``foo`` or ``bar``::
964 - skip all revisions that do not touch directories ``foo`` or ``bar``::
964
965
965 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
966 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
966
967
967 - forget the current bisection::
968 - forget the current bisection::
968
969
969 hg bisect --reset
970 hg bisect --reset
970
971
971 - use 'make && make tests' to automatically find the first broken
972 - use 'make && make tests' to automatically find the first broken
972 revision::
973 revision::
973
974
974 hg bisect --reset
975 hg bisect --reset
975 hg bisect --bad 34
976 hg bisect --bad 34
976 hg bisect --good 12
977 hg bisect --good 12
977 hg bisect --command "make && make tests"
978 hg bisect --command "make && make tests"
978
979
979 - see all changesets whose states are already known in the current
980 - see all changesets whose states are already known in the current
980 bisection::
981 bisection::
981
982
982 hg log -r "bisect(pruned)"
983 hg log -r "bisect(pruned)"
983
984
984 - see the changeset currently being bisected (especially useful
985 - see the changeset currently being bisected (especially useful
985 if running with -U/--noupdate)::
986 if running with -U/--noupdate)::
986
987
987 hg log -r "bisect(current)"
988 hg log -r "bisect(current)"
988
989
989 - see all changesets that took part in the current bisection::
990 - see all changesets that took part in the current bisection::
990
991
991 hg log -r "bisect(range)"
992 hg log -r "bisect(range)"
992
993
993 - you can even get a nice graph::
994 - you can even get a nice graph::
994
995
995 hg log --graph -r "bisect(range)"
996 hg log --graph -r "bisect(range)"
996
997
997 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
998 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
998
999
999 Returns 0 on success.
1000 Returns 0 on success.
1000 """
1001 """
1001 rev = []
1002 rev = []
1002 # backward compatibility
1003 # backward compatibility
1003 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1004 if positional_1 in (b"good", b"bad", b"reset", b"init"):
1004 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1005 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1005 cmd = positional_1
1006 cmd = positional_1
1006 rev.append(positional_2)
1007 rev.append(positional_2)
1007 if cmd == b"good":
1008 if cmd == b"good":
1008 good = True
1009 good = True
1009 elif cmd == b"bad":
1010 elif cmd == b"bad":
1010 bad = True
1011 bad = True
1011 else:
1012 else:
1012 reset = True
1013 reset = True
1013 elif positional_2:
1014 elif positional_2:
1014 raise error.InputError(_(b'incompatible arguments'))
1015 raise error.InputError(_(b'incompatible arguments'))
1015 elif positional_1 is not None:
1016 elif positional_1 is not None:
1016 rev.append(positional_1)
1017 rev.append(positional_1)
1017
1018
1018 incompatibles = {
1019 incompatibles = {
1019 b'--bad': bad,
1020 b'--bad': bad,
1020 b'--command': bool(command),
1021 b'--command': bool(command),
1021 b'--extend': extend,
1022 b'--extend': extend,
1022 b'--good': good,
1023 b'--good': good,
1023 b'--reset': reset,
1024 b'--reset': reset,
1024 b'--skip': skip,
1025 b'--skip': skip,
1025 }
1026 }
1026
1027
1027 enabled = [x for x in incompatibles if incompatibles[x]]
1028 enabled = [x for x in incompatibles if incompatibles[x]]
1028
1029
1029 if len(enabled) > 1:
1030 if len(enabled) > 1:
1030 raise error.InputError(
1031 raise error.InputError(
1031 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1032 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1032 )
1033 )
1033
1034
1034 if reset:
1035 if reset:
1035 hbisect.resetstate(repo)
1036 hbisect.resetstate(repo)
1036 return
1037 return
1037
1038
1038 state = hbisect.load_state(repo)
1039 state = hbisect.load_state(repo)
1039
1040
1040 if rev:
1041 if rev:
1041 nodes = [repo[i].node() for i in scmutil.revrange(repo, rev)]
1042 nodes = [repo[i].node() for i in scmutil.revrange(repo, rev)]
1042 else:
1043 else:
1043 nodes = [repo.lookup(b'.')]
1044 nodes = [repo.lookup(b'.')]
1044
1045
1045 # update state
1046 # update state
1046 if good or bad or skip:
1047 if good or bad or skip:
1047 if good:
1048 if good:
1048 state[b'good'] += nodes
1049 state[b'good'] += nodes
1049 elif bad:
1050 elif bad:
1050 state[b'bad'] += nodes
1051 state[b'bad'] += nodes
1051 elif skip:
1052 elif skip:
1052 state[b'skip'] += nodes
1053 state[b'skip'] += nodes
1053 hbisect.save_state(repo, state)
1054 hbisect.save_state(repo, state)
1054 if not (state[b'good'] and state[b'bad']):
1055 if not (state[b'good'] and state[b'bad']):
1055 return
1056 return
1056
1057
1057 def mayupdate(repo, node, show_stats=True):
1058 def mayupdate(repo, node, show_stats=True):
1058 """common used update sequence"""
1059 """common used update sequence"""
1059 if noupdate:
1060 if noupdate:
1060 return
1061 return
1061 cmdutil.checkunfinished(repo)
1062 cmdutil.checkunfinished(repo)
1062 cmdutil.bailifchanged(repo)
1063 cmdutil.bailifchanged(repo)
1063 return hg.clean(repo, node, show_stats=show_stats)
1064 return hg.clean(repo, node, show_stats=show_stats)
1064
1065
1065 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1066 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1066
1067
1067 if command:
1068 if command:
1068 changesets = 1
1069 changesets = 1
1069 if noupdate:
1070 if noupdate:
1070 try:
1071 try:
1071 node = state[b'current'][0]
1072 node = state[b'current'][0]
1072 except LookupError:
1073 except LookupError:
1073 raise error.StateError(
1074 raise error.StateError(
1074 _(
1075 _(
1075 b'current bisect revision is unknown - '
1076 b'current bisect revision is unknown - '
1076 b'start a new bisect to fix'
1077 b'start a new bisect to fix'
1077 )
1078 )
1078 )
1079 )
1079 else:
1080 else:
1080 node, p2 = repo.dirstate.parents()
1081 node, p2 = repo.dirstate.parents()
1081 if p2 != nullid:
1082 if p2 != nullid:
1082 raise error.StateError(_(b'current bisect revision is a merge'))
1083 raise error.StateError(_(b'current bisect revision is a merge'))
1083 if rev:
1084 if rev:
1084 if not nodes:
1085 if not nodes:
1085 raise error.Abort(_(b'empty revision set'))
1086 raise error.Abort(_(b'empty revision set'))
1086 node = repo[nodes.last()].node()
1087 node = repo[nodes.last()].node()
1087 with hbisect.restore_state(repo, state, node):
1088 with hbisect.restore_state(repo, state, node):
1088 while changesets:
1089 while changesets:
1089 # update state
1090 # update state
1090 state[b'current'] = [node]
1091 state[b'current'] = [node]
1091 hbisect.save_state(repo, state)
1092 hbisect.save_state(repo, state)
1092 status = ui.system(
1093 status = ui.system(
1093 command,
1094 command,
1094 environ={b'HG_NODE': hex(node)},
1095 environ={b'HG_NODE': hex(node)},
1095 blockedtag=b'bisect_check',
1096 blockedtag=b'bisect_check',
1096 )
1097 )
1097 if status == 125:
1098 if status == 125:
1098 transition = b"skip"
1099 transition = b"skip"
1099 elif status == 0:
1100 elif status == 0:
1100 transition = b"good"
1101 transition = b"good"
1101 # status < 0 means process was killed
1102 # status < 0 means process was killed
1102 elif status == 127:
1103 elif status == 127:
1103 raise error.Abort(_(b"failed to execute %s") % command)
1104 raise error.Abort(_(b"failed to execute %s") % command)
1104 elif status < 0:
1105 elif status < 0:
1105 raise error.Abort(_(b"%s killed") % command)
1106 raise error.Abort(_(b"%s killed") % command)
1106 else:
1107 else:
1107 transition = b"bad"
1108 transition = b"bad"
1108 state[transition].append(node)
1109 state[transition].append(node)
1109 ctx = repo[node]
1110 ctx = repo[node]
1110 ui.status(
1111 ui.status(
1111 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1112 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1112 )
1113 )
1113 hbisect.checkstate(state)
1114 hbisect.checkstate(state)
1114 # bisect
1115 # bisect
1115 nodes, changesets, bgood = hbisect.bisect(repo, state)
1116 nodes, changesets, bgood = hbisect.bisect(repo, state)
1116 # update to next check
1117 # update to next check
1117 node = nodes[0]
1118 node = nodes[0]
1118 mayupdate(repo, node, show_stats=False)
1119 mayupdate(repo, node, show_stats=False)
1119 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1120 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1120 return
1121 return
1121
1122
1122 hbisect.checkstate(state)
1123 hbisect.checkstate(state)
1123
1124
1124 # actually bisect
1125 # actually bisect
1125 nodes, changesets, good = hbisect.bisect(repo, state)
1126 nodes, changesets, good = hbisect.bisect(repo, state)
1126 if extend:
1127 if extend:
1127 if not changesets:
1128 if not changesets:
1128 extendnode = hbisect.extendrange(repo, state, nodes, good)
1129 extendnode = hbisect.extendrange(repo, state, nodes, good)
1129 if extendnode is not None:
1130 if extendnode is not None:
1130 ui.write(
1131 ui.write(
1131 _(b"Extending search to changeset %d:%s\n")
1132 _(b"Extending search to changeset %d:%s\n")
1132 % (extendnode.rev(), extendnode)
1133 % (extendnode.rev(), extendnode)
1133 )
1134 )
1134 state[b'current'] = [extendnode.node()]
1135 state[b'current'] = [extendnode.node()]
1135 hbisect.save_state(repo, state)
1136 hbisect.save_state(repo, state)
1136 return mayupdate(repo, extendnode.node())
1137 return mayupdate(repo, extendnode.node())
1137 raise error.StateError(_(b"nothing to extend"))
1138 raise error.StateError(_(b"nothing to extend"))
1138
1139
1139 if changesets == 0:
1140 if changesets == 0:
1140 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1141 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1141 else:
1142 else:
1142 assert len(nodes) == 1 # only a single node can be tested next
1143 assert len(nodes) == 1 # only a single node can be tested next
1143 node = nodes[0]
1144 node = nodes[0]
1144 # compute the approximate number of remaining tests
1145 # compute the approximate number of remaining tests
1145 tests, size = 0, 2
1146 tests, size = 0, 2
1146 while size <= changesets:
1147 while size <= changesets:
1147 tests, size = tests + 1, size * 2
1148 tests, size = tests + 1, size * 2
1148 rev = repo.changelog.rev(node)
1149 rev = repo.changelog.rev(node)
1149 ui.write(
1150 ui.write(
1150 _(
1151 _(
1151 b"Testing changeset %d:%s "
1152 b"Testing changeset %d:%s "
1152 b"(%d changesets remaining, ~%d tests)\n"
1153 b"(%d changesets remaining, ~%d tests)\n"
1153 )
1154 )
1154 % (rev, short(node), changesets, tests)
1155 % (rev, short(node), changesets, tests)
1155 )
1156 )
1156 state[b'current'] = [node]
1157 state[b'current'] = [node]
1157 hbisect.save_state(repo, state)
1158 hbisect.save_state(repo, state)
1158 return mayupdate(repo, node)
1159 return mayupdate(repo, node)
1159
1160
1160
1161
1161 @command(
1162 @command(
1162 b'bookmarks|bookmark',
1163 b'bookmarks|bookmark',
1163 [
1164 [
1164 (b'f', b'force', False, _(b'force')),
1165 (b'f', b'force', False, _(b'force')),
1165 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1166 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1166 (b'd', b'delete', False, _(b'delete a given bookmark')),
1167 (b'd', b'delete', False, _(b'delete a given bookmark')),
1167 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1168 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1168 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1169 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1169 (b'l', b'list', False, _(b'list existing bookmarks')),
1170 (b'l', b'list', False, _(b'list existing bookmarks')),
1170 ]
1171 ]
1171 + formatteropts,
1172 + formatteropts,
1172 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1173 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1173 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1174 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1174 )
1175 )
1175 def bookmark(ui, repo, *names, **opts):
1176 def bookmark(ui, repo, *names, **opts):
1176 """create a new bookmark or list existing bookmarks
1177 """create a new bookmark or list existing bookmarks
1177
1178
1178 Bookmarks are labels on changesets to help track lines of development.
1179 Bookmarks are labels on changesets to help track lines of development.
1179 Bookmarks are unversioned and can be moved, renamed and deleted.
1180 Bookmarks are unversioned and can be moved, renamed and deleted.
1180 Deleting or moving a bookmark has no effect on the associated changesets.
1181 Deleting or moving a bookmark has no effect on the associated changesets.
1181
1182
1182 Creating or updating to a bookmark causes it to be marked as 'active'.
1183 Creating or updating to a bookmark causes it to be marked as 'active'.
1183 The active bookmark is indicated with a '*'.
1184 The active bookmark is indicated with a '*'.
1184 When a commit is made, the active bookmark will advance to the new commit.
1185 When a commit is made, the active bookmark will advance to the new commit.
1185 A plain :hg:`update` will also advance an active bookmark, if possible.
1186 A plain :hg:`update` will also advance an active bookmark, if possible.
1186 Updating away from a bookmark will cause it to be deactivated.
1187 Updating away from a bookmark will cause it to be deactivated.
1187
1188
1188 Bookmarks can be pushed and pulled between repositories (see
1189 Bookmarks can be pushed and pulled between repositories (see
1189 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1190 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1190 diverged, a new 'divergent bookmark' of the form 'name@path' will
1191 diverged, a new 'divergent bookmark' of the form 'name@path' will
1191 be created. Using :hg:`merge` will resolve the divergence.
1192 be created. Using :hg:`merge` will resolve the divergence.
1192
1193
1193 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1194 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1194 the active bookmark's name.
1195 the active bookmark's name.
1195
1196
1196 A bookmark named '@' has the special property that :hg:`clone` will
1197 A bookmark named '@' has the special property that :hg:`clone` will
1197 check it out by default if it exists.
1198 check it out by default if it exists.
1198
1199
1199 .. container:: verbose
1200 .. container:: verbose
1200
1201
1201 Template:
1202 Template:
1202
1203
1203 The following keywords are supported in addition to the common template
1204 The following keywords are supported in addition to the common template
1204 keywords and functions such as ``{bookmark}``. See also
1205 keywords and functions such as ``{bookmark}``. See also
1205 :hg:`help templates`.
1206 :hg:`help templates`.
1206
1207
1207 :active: Boolean. True if the bookmark is active.
1208 :active: Boolean. True if the bookmark is active.
1208
1209
1209 Examples:
1210 Examples:
1210
1211
1211 - create an active bookmark for a new line of development::
1212 - create an active bookmark for a new line of development::
1212
1213
1213 hg book new-feature
1214 hg book new-feature
1214
1215
1215 - create an inactive bookmark as a place marker::
1216 - create an inactive bookmark as a place marker::
1216
1217
1217 hg book -i reviewed
1218 hg book -i reviewed
1218
1219
1219 - create an inactive bookmark on another changeset::
1220 - create an inactive bookmark on another changeset::
1220
1221
1221 hg book -r .^ tested
1222 hg book -r .^ tested
1222
1223
1223 - rename bookmark turkey to dinner::
1224 - rename bookmark turkey to dinner::
1224
1225
1225 hg book -m turkey dinner
1226 hg book -m turkey dinner
1226
1227
1227 - move the '@' bookmark from another branch::
1228 - move the '@' bookmark from another branch::
1228
1229
1229 hg book -f @
1230 hg book -f @
1230
1231
1231 - print only the active bookmark name::
1232 - print only the active bookmark name::
1232
1233
1233 hg book -ql .
1234 hg book -ql .
1234 """
1235 """
1235 opts = pycompat.byteskwargs(opts)
1236 opts = pycompat.byteskwargs(opts)
1236 force = opts.get(b'force')
1237 force = opts.get(b'force')
1237 rev = opts.get(b'rev')
1238 rev = opts.get(b'rev')
1238 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1239 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1239
1240
1240 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1241 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1241 if action:
1242 if action:
1242 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1243 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1243 elif names or rev:
1244 elif names or rev:
1244 action = b'add'
1245 action = b'add'
1245 elif inactive:
1246 elif inactive:
1246 action = b'inactive' # meaning deactivate
1247 action = b'inactive' # meaning deactivate
1247 else:
1248 else:
1248 action = b'list'
1249 action = b'list'
1249
1250
1250 cmdutil.check_incompatible_arguments(
1251 cmdutil.check_incompatible_arguments(
1251 opts, b'inactive', [b'delete', b'list']
1252 opts, b'inactive', [b'delete', b'list']
1252 )
1253 )
1253 if not names and action in {b'add', b'delete'}:
1254 if not names and action in {b'add', b'delete'}:
1254 raise error.InputError(_(b"bookmark name required"))
1255 raise error.InputError(_(b"bookmark name required"))
1255
1256
1256 if action in {b'add', b'delete', b'rename', b'inactive'}:
1257 if action in {b'add', b'delete', b'rename', b'inactive'}:
1257 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1258 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1258 if action == b'delete':
1259 if action == b'delete':
1259 names = pycompat.maplist(repo._bookmarks.expandname, names)
1260 names = pycompat.maplist(repo._bookmarks.expandname, names)
1260 bookmarks.delete(repo, tr, names)
1261 bookmarks.delete(repo, tr, names)
1261 elif action == b'rename':
1262 elif action == b'rename':
1262 if not names:
1263 if not names:
1263 raise error.InputError(_(b"new bookmark name required"))
1264 raise error.InputError(_(b"new bookmark name required"))
1264 elif len(names) > 1:
1265 elif len(names) > 1:
1265 raise error.InputError(
1266 raise error.InputError(
1266 _(b"only one new bookmark name allowed")
1267 _(b"only one new bookmark name allowed")
1267 )
1268 )
1268 oldname = repo._bookmarks.expandname(opts[b'rename'])
1269 oldname = repo._bookmarks.expandname(opts[b'rename'])
1269 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1270 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1270 elif action == b'add':
1271 elif action == b'add':
1271 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1272 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1272 elif action == b'inactive':
1273 elif action == b'inactive':
1273 if len(repo._bookmarks) == 0:
1274 if len(repo._bookmarks) == 0:
1274 ui.status(_(b"no bookmarks set\n"))
1275 ui.status(_(b"no bookmarks set\n"))
1275 elif not repo._activebookmark:
1276 elif not repo._activebookmark:
1276 ui.status(_(b"no active bookmark\n"))
1277 ui.status(_(b"no active bookmark\n"))
1277 else:
1278 else:
1278 bookmarks.deactivate(repo)
1279 bookmarks.deactivate(repo)
1279 elif action == b'list':
1280 elif action == b'list':
1280 names = pycompat.maplist(repo._bookmarks.expandname, names)
1281 names = pycompat.maplist(repo._bookmarks.expandname, names)
1281 with ui.formatter(b'bookmarks', opts) as fm:
1282 with ui.formatter(b'bookmarks', opts) as fm:
1282 bookmarks.printbookmarks(ui, repo, fm, names)
1283 bookmarks.printbookmarks(ui, repo, fm, names)
1283 else:
1284 else:
1284 raise error.ProgrammingError(b'invalid action: %s' % action)
1285 raise error.ProgrammingError(b'invalid action: %s' % action)
1285
1286
1286
1287
1287 @command(
1288 @command(
1288 b'branch',
1289 b'branch',
1289 [
1290 [
1290 (
1291 (
1291 b'f',
1292 b'f',
1292 b'force',
1293 b'force',
1293 None,
1294 None,
1294 _(b'set branch name even if it shadows an existing branch'),
1295 _(b'set branch name even if it shadows an existing branch'),
1295 ),
1296 ),
1296 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1297 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1297 (
1298 (
1298 b'r',
1299 b'r',
1299 b'rev',
1300 b'rev',
1300 [],
1301 [],
1301 _(b'change branches of the given revs (EXPERIMENTAL)'),
1302 _(b'change branches of the given revs (EXPERIMENTAL)'),
1302 ),
1303 ),
1303 ],
1304 ],
1304 _(b'[-fC] [NAME]'),
1305 _(b'[-fC] [NAME]'),
1305 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1306 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1306 )
1307 )
1307 def branch(ui, repo, label=None, **opts):
1308 def branch(ui, repo, label=None, **opts):
1308 """set or show the current branch name
1309 """set or show the current branch name
1309
1310
1310 .. note::
1311 .. note::
1311
1312
1312 Branch names are permanent and global. Use :hg:`bookmark` to create a
1313 Branch names are permanent and global. Use :hg:`bookmark` to create a
1313 light-weight bookmark instead. See :hg:`help glossary` for more
1314 light-weight bookmark instead. See :hg:`help glossary` for more
1314 information about named branches and bookmarks.
1315 information about named branches and bookmarks.
1315
1316
1316 With no argument, show the current branch name. With one argument,
1317 With no argument, show the current branch name. With one argument,
1317 set the working directory branch name (the branch will not exist
1318 set the working directory branch name (the branch will not exist
1318 in the repository until the next commit). Standard practice
1319 in the repository until the next commit). Standard practice
1319 recommends that primary development take place on the 'default'
1320 recommends that primary development take place on the 'default'
1320 branch.
1321 branch.
1321
1322
1322 Unless -f/--force is specified, branch will not let you set a
1323 Unless -f/--force is specified, branch will not let you set a
1323 branch name that already exists.
1324 branch name that already exists.
1324
1325
1325 Use -C/--clean to reset the working directory branch to that of
1326 Use -C/--clean to reset the working directory branch to that of
1326 the parent of the working directory, negating a previous branch
1327 the parent of the working directory, negating a previous branch
1327 change.
1328 change.
1328
1329
1329 Use the command :hg:`update` to switch to an existing branch. Use
1330 Use the command :hg:`update` to switch to an existing branch. Use
1330 :hg:`commit --close-branch` to mark this branch head as closed.
1331 :hg:`commit --close-branch` to mark this branch head as closed.
1331 When all heads of a branch are closed, the branch will be
1332 When all heads of a branch are closed, the branch will be
1332 considered closed.
1333 considered closed.
1333
1334
1334 Returns 0 on success.
1335 Returns 0 on success.
1335 """
1336 """
1336 opts = pycompat.byteskwargs(opts)
1337 opts = pycompat.byteskwargs(opts)
1337 revs = opts.get(b'rev')
1338 revs = opts.get(b'rev')
1338 if label:
1339 if label:
1339 label = label.strip()
1340 label = label.strip()
1340
1341
1341 if not opts.get(b'clean') and not label:
1342 if not opts.get(b'clean') and not label:
1342 if revs:
1343 if revs:
1343 raise error.InputError(
1344 raise error.InputError(
1344 _(b"no branch name specified for the revisions")
1345 _(b"no branch name specified for the revisions")
1345 )
1346 )
1346 ui.write(b"%s\n" % repo.dirstate.branch())
1347 ui.write(b"%s\n" % repo.dirstate.branch())
1347 return
1348 return
1348
1349
1349 with repo.wlock():
1350 with repo.wlock():
1350 if opts.get(b'clean'):
1351 if opts.get(b'clean'):
1351 label = repo[b'.'].branch()
1352 label = repo[b'.'].branch()
1352 repo.dirstate.setbranch(label)
1353 repo.dirstate.setbranch(label)
1353 ui.status(_(b'reset working directory to branch %s\n') % label)
1354 ui.status(_(b'reset working directory to branch %s\n') % label)
1354 elif label:
1355 elif label:
1355
1356
1356 scmutil.checknewlabel(repo, label, b'branch')
1357 scmutil.checknewlabel(repo, label, b'branch')
1357 if revs:
1358 if revs:
1358 return cmdutil.changebranch(ui, repo, revs, label, opts)
1359 return cmdutil.changebranch(ui, repo, revs, label, opts)
1359
1360
1360 if not opts.get(b'force') and label in repo.branchmap():
1361 if not opts.get(b'force') and label in repo.branchmap():
1361 if label not in [p.branch() for p in repo[None].parents()]:
1362 if label not in [p.branch() for p in repo[None].parents()]:
1362 raise error.InputError(
1363 raise error.InputError(
1363 _(b'a branch of the same name already exists'),
1364 _(b'a branch of the same name already exists'),
1364 # i18n: "it" refers to an existing branch
1365 # i18n: "it" refers to an existing branch
1365 hint=_(b"use 'hg update' to switch to it"),
1366 hint=_(b"use 'hg update' to switch to it"),
1366 )
1367 )
1367
1368
1368 repo.dirstate.setbranch(label)
1369 repo.dirstate.setbranch(label)
1369 ui.status(_(b'marked working directory as branch %s\n') % label)
1370 ui.status(_(b'marked working directory as branch %s\n') % label)
1370
1371
1371 # find any open named branches aside from default
1372 # find any open named branches aside from default
1372 for n, h, t, c in repo.branchmap().iterbranches():
1373 for n, h, t, c in repo.branchmap().iterbranches():
1373 if n != b"default" and not c:
1374 if n != b"default" and not c:
1374 return 0
1375 return 0
1375 ui.status(
1376 ui.status(
1376 _(
1377 _(
1377 b'(branches are permanent and global, '
1378 b'(branches are permanent and global, '
1378 b'did you want a bookmark?)\n'
1379 b'did you want a bookmark?)\n'
1379 )
1380 )
1380 )
1381 )
1381
1382
1382
1383
1383 @command(
1384 @command(
1384 b'branches',
1385 b'branches',
1385 [
1386 [
1386 (
1387 (
1387 b'a',
1388 b'a',
1388 b'active',
1389 b'active',
1389 False,
1390 False,
1390 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1391 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1391 ),
1392 ),
1392 (b'c', b'closed', False, _(b'show normal and closed branches')),
1393 (b'c', b'closed', False, _(b'show normal and closed branches')),
1393 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1394 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1394 ]
1395 ]
1395 + formatteropts,
1396 + formatteropts,
1396 _(b'[-c]'),
1397 _(b'[-c]'),
1397 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1398 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1398 intents={INTENT_READONLY},
1399 intents={INTENT_READONLY},
1399 )
1400 )
1400 def branches(ui, repo, active=False, closed=False, **opts):
1401 def branches(ui, repo, active=False, closed=False, **opts):
1401 """list repository named branches
1402 """list repository named branches
1402
1403
1403 List the repository's named branches, indicating which ones are
1404 List the repository's named branches, indicating which ones are
1404 inactive. If -c/--closed is specified, also list branches which have
1405 inactive. If -c/--closed is specified, also list branches which have
1405 been marked closed (see :hg:`commit --close-branch`).
1406 been marked closed (see :hg:`commit --close-branch`).
1406
1407
1407 Use the command :hg:`update` to switch to an existing branch.
1408 Use the command :hg:`update` to switch to an existing branch.
1408
1409
1409 .. container:: verbose
1410 .. container:: verbose
1410
1411
1411 Template:
1412 Template:
1412
1413
1413 The following keywords are supported in addition to the common template
1414 The following keywords are supported in addition to the common template
1414 keywords and functions such as ``{branch}``. See also
1415 keywords and functions such as ``{branch}``. See also
1415 :hg:`help templates`.
1416 :hg:`help templates`.
1416
1417
1417 :active: Boolean. True if the branch is active.
1418 :active: Boolean. True if the branch is active.
1418 :closed: Boolean. True if the branch is closed.
1419 :closed: Boolean. True if the branch is closed.
1419 :current: Boolean. True if it is the current branch.
1420 :current: Boolean. True if it is the current branch.
1420
1421
1421 Returns 0.
1422 Returns 0.
1422 """
1423 """
1423
1424
1424 opts = pycompat.byteskwargs(opts)
1425 opts = pycompat.byteskwargs(opts)
1425 revs = opts.get(b'rev')
1426 revs = opts.get(b'rev')
1426 selectedbranches = None
1427 selectedbranches = None
1427 if revs:
1428 if revs:
1428 revs = scmutil.revrange(repo, revs)
1429 revs = scmutil.revrange(repo, revs)
1429 getbi = repo.revbranchcache().branchinfo
1430 getbi = repo.revbranchcache().branchinfo
1430 selectedbranches = {getbi(r)[0] for r in revs}
1431 selectedbranches = {getbi(r)[0] for r in revs}
1431
1432
1432 ui.pager(b'branches')
1433 ui.pager(b'branches')
1433 fm = ui.formatter(b'branches', opts)
1434 fm = ui.formatter(b'branches', opts)
1434 hexfunc = fm.hexfunc
1435 hexfunc = fm.hexfunc
1435
1436
1436 allheads = set(repo.heads())
1437 allheads = set(repo.heads())
1437 branches = []
1438 branches = []
1438 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1439 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1439 if selectedbranches is not None and tag not in selectedbranches:
1440 if selectedbranches is not None and tag not in selectedbranches:
1440 continue
1441 continue
1441 isactive = False
1442 isactive = False
1442 if not isclosed:
1443 if not isclosed:
1443 openheads = set(repo.branchmap().iteropen(heads))
1444 openheads = set(repo.branchmap().iteropen(heads))
1444 isactive = bool(openheads & allheads)
1445 isactive = bool(openheads & allheads)
1445 branches.append((tag, repo[tip], isactive, not isclosed))
1446 branches.append((tag, repo[tip], isactive, not isclosed))
1446 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1447 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1447
1448
1448 for tag, ctx, isactive, isopen in branches:
1449 for tag, ctx, isactive, isopen in branches:
1449 if active and not isactive:
1450 if active and not isactive:
1450 continue
1451 continue
1451 if isactive:
1452 if isactive:
1452 label = b'branches.active'
1453 label = b'branches.active'
1453 notice = b''
1454 notice = b''
1454 elif not isopen:
1455 elif not isopen:
1455 if not closed:
1456 if not closed:
1456 continue
1457 continue
1457 label = b'branches.closed'
1458 label = b'branches.closed'
1458 notice = _(b' (closed)')
1459 notice = _(b' (closed)')
1459 else:
1460 else:
1460 label = b'branches.inactive'
1461 label = b'branches.inactive'
1461 notice = _(b' (inactive)')
1462 notice = _(b' (inactive)')
1462 current = tag == repo.dirstate.branch()
1463 current = tag == repo.dirstate.branch()
1463 if current:
1464 if current:
1464 label = b'branches.current'
1465 label = b'branches.current'
1465
1466
1466 fm.startitem()
1467 fm.startitem()
1467 fm.write(b'branch', b'%s', tag, label=label)
1468 fm.write(b'branch', b'%s', tag, label=label)
1468 rev = ctx.rev()
1469 rev = ctx.rev()
1469 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1470 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1470 fmt = b' ' * padsize + b' %d:%s'
1471 fmt = b' ' * padsize + b' %d:%s'
1471 fm.condwrite(
1472 fm.condwrite(
1472 not ui.quiet,
1473 not ui.quiet,
1473 b'rev node',
1474 b'rev node',
1474 fmt,
1475 fmt,
1475 rev,
1476 rev,
1476 hexfunc(ctx.node()),
1477 hexfunc(ctx.node()),
1477 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1478 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1478 )
1479 )
1479 fm.context(ctx=ctx)
1480 fm.context(ctx=ctx)
1480 fm.data(active=isactive, closed=not isopen, current=current)
1481 fm.data(active=isactive, closed=not isopen, current=current)
1481 if not ui.quiet:
1482 if not ui.quiet:
1482 fm.plain(notice)
1483 fm.plain(notice)
1483 fm.plain(b'\n')
1484 fm.plain(b'\n')
1484 fm.end()
1485 fm.end()
1485
1486
1486
1487
1487 @command(
1488 @command(
1488 b'bundle',
1489 b'bundle',
1489 [
1490 [
1490 (
1491 (
1491 b'f',
1492 b'f',
1492 b'force',
1493 b'force',
1493 None,
1494 None,
1494 _(b'run even when the destination is unrelated'),
1495 _(b'run even when the destination is unrelated'),
1495 ),
1496 ),
1496 (
1497 (
1497 b'r',
1498 b'r',
1498 b'rev',
1499 b'rev',
1499 [],
1500 [],
1500 _(b'a changeset intended to be added to the destination'),
1501 _(b'a changeset intended to be added to the destination'),
1501 _(b'REV'),
1502 _(b'REV'),
1502 ),
1503 ),
1503 (
1504 (
1504 b'b',
1505 b'b',
1505 b'branch',
1506 b'branch',
1506 [],
1507 [],
1507 _(b'a specific branch you would like to bundle'),
1508 _(b'a specific branch you would like to bundle'),
1508 _(b'BRANCH'),
1509 _(b'BRANCH'),
1509 ),
1510 ),
1510 (
1511 (
1511 b'',
1512 b'',
1512 b'base',
1513 b'base',
1513 [],
1514 [],
1514 _(b'a base changeset assumed to be available at the destination'),
1515 _(b'a base changeset assumed to be available at the destination'),
1515 _(b'REV'),
1516 _(b'REV'),
1516 ),
1517 ),
1517 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1518 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1518 (
1519 (
1519 b't',
1520 b't',
1520 b'type',
1521 b'type',
1521 b'bzip2',
1522 b'bzip2',
1522 _(b'bundle compression type to use'),
1523 _(b'bundle compression type to use'),
1523 _(b'TYPE'),
1524 _(b'TYPE'),
1524 ),
1525 ),
1525 ]
1526 ]
1526 + remoteopts,
1527 + remoteopts,
1527 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1528 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1528 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1529 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1529 )
1530 )
1530 def bundle(ui, repo, fname, dest=None, **opts):
1531 def bundle(ui, repo, fname, dest=None, **opts):
1531 """create a bundle file
1532 """create a bundle file
1532
1533
1533 Generate a bundle file containing data to be transferred to another
1534 Generate a bundle file containing data to be transferred to another
1534 repository.
1535 repository.
1535
1536
1536 To create a bundle containing all changesets, use -a/--all
1537 To create a bundle containing all changesets, use -a/--all
1537 (or --base null). Otherwise, hg assumes the destination will have
1538 (or --base null). Otherwise, hg assumes the destination will have
1538 all the nodes you specify with --base parameters. Otherwise, hg
1539 all the nodes you specify with --base parameters. Otherwise, hg
1539 will assume the repository has all the nodes in destination, or
1540 will assume the repository has all the nodes in destination, or
1540 default-push/default if no destination is specified, where destination
1541 default-push/default if no destination is specified, where destination
1541 is the repository you provide through DEST option.
1542 is the repository you provide through DEST option.
1542
1543
1543 You can change bundle format with the -t/--type option. See
1544 You can change bundle format with the -t/--type option. See
1544 :hg:`help bundlespec` for documentation on this format. By default,
1545 :hg:`help bundlespec` for documentation on this format. By default,
1545 the most appropriate format is used and compression defaults to
1546 the most appropriate format is used and compression defaults to
1546 bzip2.
1547 bzip2.
1547
1548
1548 The bundle file can then be transferred using conventional means
1549 The bundle file can then be transferred using conventional means
1549 and applied to another repository with the unbundle or pull
1550 and applied to another repository with the unbundle or pull
1550 command. This is useful when direct push and pull are not
1551 command. This is useful when direct push and pull are not
1551 available or when exporting an entire repository is undesirable.
1552 available or when exporting an entire repository is undesirable.
1552
1553
1553 Applying bundles preserves all changeset contents including
1554 Applying bundles preserves all changeset contents including
1554 permissions, copy/rename information, and revision history.
1555 permissions, copy/rename information, and revision history.
1555
1556
1556 Returns 0 on success, 1 if no changes found.
1557 Returns 0 on success, 1 if no changes found.
1557 """
1558 """
1558 opts = pycompat.byteskwargs(opts)
1559 opts = pycompat.byteskwargs(opts)
1559 revs = None
1560 revs = None
1560 if b'rev' in opts:
1561 if b'rev' in opts:
1561 revstrings = opts[b'rev']
1562 revstrings = opts[b'rev']
1562 revs = scmutil.revrange(repo, revstrings)
1563 revs = scmutil.revrange(repo, revstrings)
1563 if revstrings and not revs:
1564 if revstrings and not revs:
1564 raise error.InputError(_(b'no commits to bundle'))
1565 raise error.InputError(_(b'no commits to bundle'))
1565
1566
1566 bundletype = opts.get(b'type', b'bzip2').lower()
1567 bundletype = opts.get(b'type', b'bzip2').lower()
1567 try:
1568 try:
1568 bundlespec = bundlecaches.parsebundlespec(
1569 bundlespec = bundlecaches.parsebundlespec(
1569 repo, bundletype, strict=False
1570 repo, bundletype, strict=False
1570 )
1571 )
1571 except error.UnsupportedBundleSpecification as e:
1572 except error.UnsupportedBundleSpecification as e:
1572 raise error.InputError(
1573 raise error.InputError(
1573 pycompat.bytestr(e),
1574 pycompat.bytestr(e),
1574 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1575 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1575 )
1576 )
1576 cgversion = bundlespec.contentopts[b"cg.version"]
1577 cgversion = bundlespec.contentopts[b"cg.version"]
1577
1578
1578 # Packed bundles are a pseudo bundle format for now.
1579 # Packed bundles are a pseudo bundle format for now.
1579 if cgversion == b's1':
1580 if cgversion == b's1':
1580 raise error.InputError(
1581 raise error.InputError(
1581 _(b'packed bundles cannot be produced by "hg bundle"'),
1582 _(b'packed bundles cannot be produced by "hg bundle"'),
1582 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1583 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1583 )
1584 )
1584
1585
1585 if opts.get(b'all'):
1586 if opts.get(b'all'):
1586 if dest:
1587 if dest:
1587 raise error.InputError(
1588 raise error.InputError(
1588 _(b"--all is incompatible with specifying a destination")
1589 _(b"--all is incompatible with specifying a destination")
1589 )
1590 )
1590 if opts.get(b'base'):
1591 if opts.get(b'base'):
1591 ui.warn(_(b"ignoring --base because --all was specified\n"))
1592 ui.warn(_(b"ignoring --base because --all was specified\n"))
1592 base = [nullrev]
1593 base = [nullrev]
1593 else:
1594 else:
1594 base = scmutil.revrange(repo, opts.get(b'base'))
1595 base = scmutil.revrange(repo, opts.get(b'base'))
1595 if cgversion not in changegroup.supportedoutgoingversions(repo):
1596 if cgversion not in changegroup.supportedoutgoingversions(repo):
1596 raise error.Abort(
1597 raise error.Abort(
1597 _(b"repository does not support bundle version %s") % cgversion
1598 _(b"repository does not support bundle version %s") % cgversion
1598 )
1599 )
1599
1600
1600 if base:
1601 if base:
1601 if dest:
1602 if dest:
1602 raise error.InputError(
1603 raise error.InputError(
1603 _(b"--base is incompatible with specifying a destination")
1604 _(b"--base is incompatible with specifying a destination")
1604 )
1605 )
1605 common = [repo[rev].node() for rev in base]
1606 common = [repo[rev].node() for rev in base]
1606 heads = [repo[r].node() for r in revs] if revs else None
1607 heads = [repo[r].node() for r in revs] if revs else None
1607 outgoing = discovery.outgoing(repo, common, heads)
1608 outgoing = discovery.outgoing(repo, common, heads)
1608 else:
1609 else:
1609 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1610 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1610 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1611 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1611 other = hg.peer(repo, opts, dest)
1612 other = hg.peer(repo, opts, dest)
1612 revs = [repo[r].hex() for r in revs]
1613 revs = [repo[r].hex() for r in revs]
1613 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1614 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1614 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1615 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1615 outgoing = discovery.findcommonoutgoing(
1616 outgoing = discovery.findcommonoutgoing(
1616 repo,
1617 repo,
1617 other,
1618 other,
1618 onlyheads=heads,
1619 onlyheads=heads,
1619 force=opts.get(b'force'),
1620 force=opts.get(b'force'),
1620 portable=True,
1621 portable=True,
1621 )
1622 )
1622
1623
1623 if not outgoing.missing:
1624 if not outgoing.missing:
1624 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1625 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1625 return 1
1626 return 1
1626
1627
1627 if cgversion == b'01': # bundle1
1628 if cgversion == b'01': # bundle1
1628 bversion = b'HG10' + bundlespec.wirecompression
1629 bversion = b'HG10' + bundlespec.wirecompression
1629 bcompression = None
1630 bcompression = None
1630 elif cgversion in (b'02', b'03'):
1631 elif cgversion in (b'02', b'03'):
1631 bversion = b'HG20'
1632 bversion = b'HG20'
1632 bcompression = bundlespec.wirecompression
1633 bcompression = bundlespec.wirecompression
1633 else:
1634 else:
1634 raise error.ProgrammingError(
1635 raise error.ProgrammingError(
1635 b'bundle: unexpected changegroup version %s' % cgversion
1636 b'bundle: unexpected changegroup version %s' % cgversion
1636 )
1637 )
1637
1638
1638 # TODO compression options should be derived from bundlespec parsing.
1639 # TODO compression options should be derived from bundlespec parsing.
1639 # This is a temporary hack to allow adjusting bundle compression
1640 # This is a temporary hack to allow adjusting bundle compression
1640 # level without a) formalizing the bundlespec changes to declare it
1641 # level without a) formalizing the bundlespec changes to declare it
1641 # b) introducing a command flag.
1642 # b) introducing a command flag.
1642 compopts = {}
1643 compopts = {}
1643 complevel = ui.configint(
1644 complevel = ui.configint(
1644 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1645 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1645 )
1646 )
1646 if complevel is None:
1647 if complevel is None:
1647 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1648 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1648 if complevel is not None:
1649 if complevel is not None:
1649 compopts[b'level'] = complevel
1650 compopts[b'level'] = complevel
1650
1651
1651 # Bundling of obsmarker and phases is optional as not all clients
1652 # Bundling of obsmarker and phases is optional as not all clients
1652 # support the necessary features.
1653 # support the necessary features.
1653 cfg = ui.configbool
1654 cfg = ui.configbool
1654 contentopts = {
1655 contentopts = {
1655 b'obsolescence': cfg(b'experimental', b'evolution.bundle-obsmarker'),
1656 b'obsolescence': cfg(b'experimental', b'evolution.bundle-obsmarker'),
1656 b'obsolescence-mandatory': cfg(
1657 b'obsolescence-mandatory': cfg(
1657 b'experimental', b'evolution.bundle-obsmarker:mandatory'
1658 b'experimental', b'evolution.bundle-obsmarker:mandatory'
1658 ),
1659 ),
1659 b'phases': cfg(b'experimental', b'bundle-phases'),
1660 b'phases': cfg(b'experimental', b'bundle-phases'),
1660 }
1661 }
1661 bundlespec.contentopts.update(contentopts)
1662 bundlespec.contentopts.update(contentopts)
1662
1663
1663 bundle2.writenewbundle(
1664 bundle2.writenewbundle(
1664 ui,
1665 ui,
1665 repo,
1666 repo,
1666 b'bundle',
1667 b'bundle',
1667 fname,
1668 fname,
1668 bversion,
1669 bversion,
1669 outgoing,
1670 outgoing,
1670 bundlespec.contentopts,
1671 bundlespec.contentopts,
1671 compression=bcompression,
1672 compression=bcompression,
1672 compopts=compopts,
1673 compopts=compopts,
1673 )
1674 )
1674
1675
1675
1676
1676 @command(
1677 @command(
1677 b'cat',
1678 b'cat',
1678 [
1679 [
1679 (
1680 (
1680 b'o',
1681 b'o',
1681 b'output',
1682 b'output',
1682 b'',
1683 b'',
1683 _(b'print output to file with formatted name'),
1684 _(b'print output to file with formatted name'),
1684 _(b'FORMAT'),
1685 _(b'FORMAT'),
1685 ),
1686 ),
1686 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1687 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1687 (b'', b'decode', None, _(b'apply any matching decode filter')),
1688 (b'', b'decode', None, _(b'apply any matching decode filter')),
1688 ]
1689 ]
1689 + walkopts
1690 + walkopts
1690 + formatteropts,
1691 + formatteropts,
1691 _(b'[OPTION]... FILE...'),
1692 _(b'[OPTION]... FILE...'),
1692 helpcategory=command.CATEGORY_FILE_CONTENTS,
1693 helpcategory=command.CATEGORY_FILE_CONTENTS,
1693 inferrepo=True,
1694 inferrepo=True,
1694 intents={INTENT_READONLY},
1695 intents={INTENT_READONLY},
1695 )
1696 )
1696 def cat(ui, repo, file1, *pats, **opts):
1697 def cat(ui, repo, file1, *pats, **opts):
1697 """output the current or given revision of files
1698 """output the current or given revision of files
1698
1699
1699 Print the specified files as they were at the given revision. If
1700 Print the specified files as they were at the given revision. If
1700 no revision is given, the parent of the working directory is used.
1701 no revision is given, the parent of the working directory is used.
1701
1702
1702 Output may be to a file, in which case the name of the file is
1703 Output may be to a file, in which case the name of the file is
1703 given using a template string. See :hg:`help templates`. In addition
1704 given using a template string. See :hg:`help templates`. In addition
1704 to the common template keywords, the following formatting rules are
1705 to the common template keywords, the following formatting rules are
1705 supported:
1706 supported:
1706
1707
1707 :``%%``: literal "%" character
1708 :``%%``: literal "%" character
1708 :``%s``: basename of file being printed
1709 :``%s``: basename of file being printed
1709 :``%d``: dirname of file being printed, or '.' if in repository root
1710 :``%d``: dirname of file being printed, or '.' if in repository root
1710 :``%p``: root-relative path name of file being printed
1711 :``%p``: root-relative path name of file being printed
1711 :``%H``: changeset hash (40 hexadecimal digits)
1712 :``%H``: changeset hash (40 hexadecimal digits)
1712 :``%R``: changeset revision number
1713 :``%R``: changeset revision number
1713 :``%h``: short-form changeset hash (12 hexadecimal digits)
1714 :``%h``: short-form changeset hash (12 hexadecimal digits)
1714 :``%r``: zero-padded changeset revision number
1715 :``%r``: zero-padded changeset revision number
1715 :``%b``: basename of the exporting repository
1716 :``%b``: basename of the exporting repository
1716 :``\\``: literal "\\" character
1717 :``\\``: literal "\\" character
1717
1718
1718 .. container:: verbose
1719 .. container:: verbose
1719
1720
1720 Template:
1721 Template:
1721
1722
1722 The following keywords are supported in addition to the common template
1723 The following keywords are supported in addition to the common template
1723 keywords and functions. See also :hg:`help templates`.
1724 keywords and functions. See also :hg:`help templates`.
1724
1725
1725 :data: String. File content.
1726 :data: String. File content.
1726 :path: String. Repository-absolute path of the file.
1727 :path: String. Repository-absolute path of the file.
1727
1728
1728 Returns 0 on success.
1729 Returns 0 on success.
1729 """
1730 """
1730 opts = pycompat.byteskwargs(opts)
1731 opts = pycompat.byteskwargs(opts)
1731 rev = opts.get(b'rev')
1732 rev = opts.get(b'rev')
1732 if rev:
1733 if rev:
1733 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1734 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1734 ctx = scmutil.revsingle(repo, rev)
1735 ctx = scmutil.revsingle(repo, rev)
1735 m = scmutil.match(ctx, (file1,) + pats, opts)
1736 m = scmutil.match(ctx, (file1,) + pats, opts)
1736 fntemplate = opts.pop(b'output', b'')
1737 fntemplate = opts.pop(b'output', b'')
1737 if cmdutil.isstdiofilename(fntemplate):
1738 if cmdutil.isstdiofilename(fntemplate):
1738 fntemplate = b''
1739 fntemplate = b''
1739
1740
1740 if fntemplate:
1741 if fntemplate:
1741 fm = formatter.nullformatter(ui, b'cat', opts)
1742 fm = formatter.nullformatter(ui, b'cat', opts)
1742 else:
1743 else:
1743 ui.pager(b'cat')
1744 ui.pager(b'cat')
1744 fm = ui.formatter(b'cat', opts)
1745 fm = ui.formatter(b'cat', opts)
1745 with fm:
1746 with fm:
1746 return cmdutil.cat(
1747 return cmdutil.cat(
1747 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1748 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1748 )
1749 )
1749
1750
1750
1751
1751 @command(
1752 @command(
1752 b'clone',
1753 b'clone',
1753 [
1754 [
1754 (
1755 (
1755 b'U',
1756 b'U',
1756 b'noupdate',
1757 b'noupdate',
1757 None,
1758 None,
1758 _(
1759 _(
1759 b'the clone will include an empty working '
1760 b'the clone will include an empty working '
1760 b'directory (only a repository)'
1761 b'directory (only a repository)'
1761 ),
1762 ),
1762 ),
1763 ),
1763 (
1764 (
1764 b'u',
1765 b'u',
1765 b'updaterev',
1766 b'updaterev',
1766 b'',
1767 b'',
1767 _(b'revision, tag, or branch to check out'),
1768 _(b'revision, tag, or branch to check out'),
1768 _(b'REV'),
1769 _(b'REV'),
1769 ),
1770 ),
1770 (
1771 (
1771 b'r',
1772 b'r',
1772 b'rev',
1773 b'rev',
1773 [],
1774 [],
1774 _(
1775 _(
1775 b'do not clone everything, but include this changeset'
1776 b'do not clone everything, but include this changeset'
1776 b' and its ancestors'
1777 b' and its ancestors'
1777 ),
1778 ),
1778 _(b'REV'),
1779 _(b'REV'),
1779 ),
1780 ),
1780 (
1781 (
1781 b'b',
1782 b'b',
1782 b'branch',
1783 b'branch',
1783 [],
1784 [],
1784 _(
1785 _(
1785 b'do not clone everything, but include this branch\'s'
1786 b'do not clone everything, but include this branch\'s'
1786 b' changesets and their ancestors'
1787 b' changesets and their ancestors'
1787 ),
1788 ),
1788 _(b'BRANCH'),
1789 _(b'BRANCH'),
1789 ),
1790 ),
1790 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1791 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1791 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1792 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1792 (b'', b'stream', None, _(b'clone with minimal data processing')),
1793 (b'', b'stream', None, _(b'clone with minimal data processing')),
1793 ]
1794 ]
1794 + remoteopts,
1795 + remoteopts,
1795 _(b'[OPTION]... SOURCE [DEST]'),
1796 _(b'[OPTION]... SOURCE [DEST]'),
1796 helpcategory=command.CATEGORY_REPO_CREATION,
1797 helpcategory=command.CATEGORY_REPO_CREATION,
1797 helpbasic=True,
1798 helpbasic=True,
1798 norepo=True,
1799 norepo=True,
1799 )
1800 )
1800 def clone(ui, source, dest=None, **opts):
1801 def clone(ui, source, dest=None, **opts):
1801 """make a copy of an existing repository
1802 """make a copy of an existing repository
1802
1803
1803 Create a copy of an existing repository in a new directory.
1804 Create a copy of an existing repository in a new directory.
1804
1805
1805 If no destination directory name is specified, it defaults to the
1806 If no destination directory name is specified, it defaults to the
1806 basename of the source.
1807 basename of the source.
1807
1808
1808 The location of the source is added to the new repository's
1809 The location of the source is added to the new repository's
1809 ``.hg/hgrc`` file, as the default to be used for future pulls.
1810 ``.hg/hgrc`` file, as the default to be used for future pulls.
1810
1811
1811 Only local paths and ``ssh://`` URLs are supported as
1812 Only local paths and ``ssh://`` URLs are supported as
1812 destinations. For ``ssh://`` destinations, no working directory or
1813 destinations. For ``ssh://`` destinations, no working directory or
1813 ``.hg/hgrc`` will be created on the remote side.
1814 ``.hg/hgrc`` will be created on the remote side.
1814
1815
1815 If the source repository has a bookmark called '@' set, that
1816 If the source repository has a bookmark called '@' set, that
1816 revision will be checked out in the new repository by default.
1817 revision will be checked out in the new repository by default.
1817
1818
1818 To check out a particular version, use -u/--update, or
1819 To check out a particular version, use -u/--update, or
1819 -U/--noupdate to create a clone with no working directory.
1820 -U/--noupdate to create a clone with no working directory.
1820
1821
1821 To pull only a subset of changesets, specify one or more revisions
1822 To pull only a subset of changesets, specify one or more revisions
1822 identifiers with -r/--rev or branches with -b/--branch. The
1823 identifiers with -r/--rev or branches with -b/--branch. The
1823 resulting clone will contain only the specified changesets and
1824 resulting clone will contain only the specified changesets and
1824 their ancestors. These options (or 'clone src#rev dest') imply
1825 their ancestors. These options (or 'clone src#rev dest') imply
1825 --pull, even for local source repositories.
1826 --pull, even for local source repositories.
1826
1827
1827 In normal clone mode, the remote normalizes repository data into a common
1828 In normal clone mode, the remote normalizes repository data into a common
1828 exchange format and the receiving end translates this data into its local
1829 exchange format and the receiving end translates this data into its local
1829 storage format. --stream activates a different clone mode that essentially
1830 storage format. --stream activates a different clone mode that essentially
1830 copies repository files from the remote with minimal data processing. This
1831 copies repository files from the remote with minimal data processing. This
1831 significantly reduces the CPU cost of a clone both remotely and locally.
1832 significantly reduces the CPU cost of a clone both remotely and locally.
1832 However, it often increases the transferred data size by 30-40%. This can
1833 However, it often increases the transferred data size by 30-40%. This can
1833 result in substantially faster clones where I/O throughput is plentiful,
1834 result in substantially faster clones where I/O throughput is plentiful,
1834 especially for larger repositories. A side-effect of --stream clones is
1835 especially for larger repositories. A side-effect of --stream clones is
1835 that storage settings and requirements on the remote are applied locally:
1836 that storage settings and requirements on the remote are applied locally:
1836 a modern client may inherit legacy or inefficient storage used by the
1837 a modern client may inherit legacy or inefficient storage used by the
1837 remote or a legacy Mercurial client may not be able to clone from a
1838 remote or a legacy Mercurial client may not be able to clone from a
1838 modern Mercurial remote.
1839 modern Mercurial remote.
1839
1840
1840 .. note::
1841 .. note::
1841
1842
1842 Specifying a tag will include the tagged changeset but not the
1843 Specifying a tag will include the tagged changeset but not the
1843 changeset containing the tag.
1844 changeset containing the tag.
1844
1845
1845 .. container:: verbose
1846 .. container:: verbose
1846
1847
1847 For efficiency, hardlinks are used for cloning whenever the
1848 For efficiency, hardlinks are used for cloning whenever the
1848 source and destination are on the same filesystem (note this
1849 source and destination are on the same filesystem (note this
1849 applies only to the repository data, not to the working
1850 applies only to the repository data, not to the working
1850 directory). Some filesystems, such as AFS, implement hardlinking
1851 directory). Some filesystems, such as AFS, implement hardlinking
1851 incorrectly, but do not report errors. In these cases, use the
1852 incorrectly, but do not report errors. In these cases, use the
1852 --pull option to avoid hardlinking.
1853 --pull option to avoid hardlinking.
1853
1854
1854 Mercurial will update the working directory to the first applicable
1855 Mercurial will update the working directory to the first applicable
1855 revision from this list:
1856 revision from this list:
1856
1857
1857 a) null if -U or the source repository has no changesets
1858 a) null if -U or the source repository has no changesets
1858 b) if -u . and the source repository is local, the first parent of
1859 b) if -u . and the source repository is local, the first parent of
1859 the source repository's working directory
1860 the source repository's working directory
1860 c) the changeset specified with -u (if a branch name, this means the
1861 c) the changeset specified with -u (if a branch name, this means the
1861 latest head of that branch)
1862 latest head of that branch)
1862 d) the changeset specified with -r
1863 d) the changeset specified with -r
1863 e) the tipmost head specified with -b
1864 e) the tipmost head specified with -b
1864 f) the tipmost head specified with the url#branch source syntax
1865 f) the tipmost head specified with the url#branch source syntax
1865 g) the revision marked with the '@' bookmark, if present
1866 g) the revision marked with the '@' bookmark, if present
1866 h) the tipmost head of the default branch
1867 h) the tipmost head of the default branch
1867 i) tip
1868 i) tip
1868
1869
1869 When cloning from servers that support it, Mercurial may fetch
1870 When cloning from servers that support it, Mercurial may fetch
1870 pre-generated data from a server-advertised URL or inline from the
1871 pre-generated data from a server-advertised URL or inline from the
1871 same stream. When this is done, hooks operating on incoming changesets
1872 same stream. When this is done, hooks operating on incoming changesets
1872 and changegroups may fire more than once, once for each pre-generated
1873 and changegroups may fire more than once, once for each pre-generated
1873 bundle and as well as for any additional remaining data. In addition,
1874 bundle and as well as for any additional remaining data. In addition,
1874 if an error occurs, the repository may be rolled back to a partial
1875 if an error occurs, the repository may be rolled back to a partial
1875 clone. This behavior may change in future releases.
1876 clone. This behavior may change in future releases.
1876 See :hg:`help -e clonebundles` for more.
1877 See :hg:`help -e clonebundles` for more.
1877
1878
1878 Examples:
1879 Examples:
1879
1880
1880 - clone a remote repository to a new directory named hg/::
1881 - clone a remote repository to a new directory named hg/::
1881
1882
1882 hg clone https://www.mercurial-scm.org/repo/hg/
1883 hg clone https://www.mercurial-scm.org/repo/hg/
1883
1884
1884 - create a lightweight local clone::
1885 - create a lightweight local clone::
1885
1886
1886 hg clone project/ project-feature/
1887 hg clone project/ project-feature/
1887
1888
1888 - clone from an absolute path on an ssh server (note double-slash)::
1889 - clone from an absolute path on an ssh server (note double-slash)::
1889
1890
1890 hg clone ssh://user@server//home/projects/alpha/
1891 hg clone ssh://user@server//home/projects/alpha/
1891
1892
1892 - do a streaming clone while checking out a specified version::
1893 - do a streaming clone while checking out a specified version::
1893
1894
1894 hg clone --stream http://server/repo -u 1.5
1895 hg clone --stream http://server/repo -u 1.5
1895
1896
1896 - create a repository without changesets after a particular revision::
1897 - create a repository without changesets after a particular revision::
1897
1898
1898 hg clone -r 04e544 experimental/ good/
1899 hg clone -r 04e544 experimental/ good/
1899
1900
1900 - clone (and track) a particular named branch::
1901 - clone (and track) a particular named branch::
1901
1902
1902 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1903 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1903
1904
1904 See :hg:`help urls` for details on specifying URLs.
1905 See :hg:`help urls` for details on specifying URLs.
1905
1906
1906 Returns 0 on success.
1907 Returns 0 on success.
1907 """
1908 """
1908 opts = pycompat.byteskwargs(opts)
1909 opts = pycompat.byteskwargs(opts)
1909 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1910 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1910
1911
1911 # --include/--exclude can come from narrow or sparse.
1912 # --include/--exclude can come from narrow or sparse.
1912 includepats, excludepats = None, None
1913 includepats, excludepats = None, None
1913
1914
1914 # hg.clone() differentiates between None and an empty set. So make sure
1915 # hg.clone() differentiates between None and an empty set. So make sure
1915 # patterns are sets if narrow is requested without patterns.
1916 # patterns are sets if narrow is requested without patterns.
1916 if opts.get(b'narrow'):
1917 if opts.get(b'narrow'):
1917 includepats = set()
1918 includepats = set()
1918 excludepats = set()
1919 excludepats = set()
1919
1920
1920 if opts.get(b'include'):
1921 if opts.get(b'include'):
1921 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1922 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1922 if opts.get(b'exclude'):
1923 if opts.get(b'exclude'):
1923 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1924 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1924
1925
1925 r = hg.clone(
1926 r = hg.clone(
1926 ui,
1927 ui,
1927 opts,
1928 opts,
1928 source,
1929 source,
1929 dest,
1930 dest,
1930 pull=opts.get(b'pull'),
1931 pull=opts.get(b'pull'),
1931 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1932 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1932 revs=opts.get(b'rev'),
1933 revs=opts.get(b'rev'),
1933 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1934 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1934 branch=opts.get(b'branch'),
1935 branch=opts.get(b'branch'),
1935 shareopts=opts.get(b'shareopts'),
1936 shareopts=opts.get(b'shareopts'),
1936 storeincludepats=includepats,
1937 storeincludepats=includepats,
1937 storeexcludepats=excludepats,
1938 storeexcludepats=excludepats,
1938 depth=opts.get(b'depth') or None,
1939 depth=opts.get(b'depth') or None,
1939 )
1940 )
1940
1941
1941 return r is None
1942 return r is None
1942
1943
1943
1944
1944 @command(
1945 @command(
1945 b'commit|ci',
1946 b'commit|ci',
1946 [
1947 [
1947 (
1948 (
1948 b'A',
1949 b'A',
1949 b'addremove',
1950 b'addremove',
1950 None,
1951 None,
1951 _(b'mark new/missing files as added/removed before committing'),
1952 _(b'mark new/missing files as added/removed before committing'),
1952 ),
1953 ),
1953 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1954 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1954 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1955 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1955 (b's', b'secret', None, _(b'use the secret phase for committing')),
1956 (b's', b'secret', None, _(b'use the secret phase for committing')),
1956 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1957 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1957 (
1958 (
1958 b'',
1959 b'',
1959 b'force-close-branch',
1960 b'force-close-branch',
1960 None,
1961 None,
1961 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1962 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1962 ),
1963 ),
1963 (b'i', b'interactive', None, _(b'use interactive mode')),
1964 (b'i', b'interactive', None, _(b'use interactive mode')),
1964 ]
1965 ]
1965 + walkopts
1966 + walkopts
1966 + commitopts
1967 + commitopts
1967 + commitopts2
1968 + commitopts2
1968 + subrepoopts,
1969 + subrepoopts,
1969 _(b'[OPTION]... [FILE]...'),
1970 _(b'[OPTION]... [FILE]...'),
1970 helpcategory=command.CATEGORY_COMMITTING,
1971 helpcategory=command.CATEGORY_COMMITTING,
1971 helpbasic=True,
1972 helpbasic=True,
1972 inferrepo=True,
1973 inferrepo=True,
1973 )
1974 )
1974 def commit(ui, repo, *pats, **opts):
1975 def commit(ui, repo, *pats, **opts):
1975 """commit the specified files or all outstanding changes
1976 """commit the specified files or all outstanding changes
1976
1977
1977 Commit changes to the given files into the repository. Unlike a
1978 Commit changes to the given files into the repository. Unlike a
1978 centralized SCM, this operation is a local operation. See
1979 centralized SCM, this operation is a local operation. See
1979 :hg:`push` for a way to actively distribute your changes.
1980 :hg:`push` for a way to actively distribute your changes.
1980
1981
1981 If a list of files is omitted, all changes reported by :hg:`status`
1982 If a list of files is omitted, all changes reported by :hg:`status`
1982 will be committed.
1983 will be committed.
1983
1984
1984 If you are committing the result of a merge, do not provide any
1985 If you are committing the result of a merge, do not provide any
1985 filenames or -I/-X filters.
1986 filenames or -I/-X filters.
1986
1987
1987 If no commit message is specified, Mercurial starts your
1988 If no commit message is specified, Mercurial starts your
1988 configured editor where you can enter a message. In case your
1989 configured editor where you can enter a message. In case your
1989 commit fails, you will find a backup of your message in
1990 commit fails, you will find a backup of your message in
1990 ``.hg/last-message.txt``.
1991 ``.hg/last-message.txt``.
1991
1992
1992 The --close-branch flag can be used to mark the current branch
1993 The --close-branch flag can be used to mark the current branch
1993 head closed. When all heads of a branch are closed, the branch
1994 head closed. When all heads of a branch are closed, the branch
1994 will be considered closed and no longer listed.
1995 will be considered closed and no longer listed.
1995
1996
1996 The --amend flag can be used to amend the parent of the
1997 The --amend flag can be used to amend the parent of the
1997 working directory with a new commit that contains the changes
1998 working directory with a new commit that contains the changes
1998 in the parent in addition to those currently reported by :hg:`status`,
1999 in the parent in addition to those currently reported by :hg:`status`,
1999 if there are any. The old commit is stored in a backup bundle in
2000 if there are any. The old commit is stored in a backup bundle in
2000 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2001 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
2001 on how to restore it).
2002 on how to restore it).
2002
2003
2003 Message, user and date are taken from the amended commit unless
2004 Message, user and date are taken from the amended commit unless
2004 specified. When a message isn't specified on the command line,
2005 specified. When a message isn't specified on the command line,
2005 the editor will open with the message of the amended commit.
2006 the editor will open with the message of the amended commit.
2006
2007
2007 It is not possible to amend public changesets (see :hg:`help phases`)
2008 It is not possible to amend public changesets (see :hg:`help phases`)
2008 or changesets that have children.
2009 or changesets that have children.
2009
2010
2010 See :hg:`help dates` for a list of formats valid for -d/--date.
2011 See :hg:`help dates` for a list of formats valid for -d/--date.
2011
2012
2012 Returns 0 on success, 1 if nothing changed.
2013 Returns 0 on success, 1 if nothing changed.
2013
2014
2014 .. container:: verbose
2015 .. container:: verbose
2015
2016
2016 Examples:
2017 Examples:
2017
2018
2018 - commit all files ending in .py::
2019 - commit all files ending in .py::
2019
2020
2020 hg commit --include "set:**.py"
2021 hg commit --include "set:**.py"
2021
2022
2022 - commit all non-binary files::
2023 - commit all non-binary files::
2023
2024
2024 hg commit --exclude "set:binary()"
2025 hg commit --exclude "set:binary()"
2025
2026
2026 - amend the current commit and set the date to now::
2027 - amend the current commit and set the date to now::
2027
2028
2028 hg commit --amend --date now
2029 hg commit --amend --date now
2029 """
2030 """
2030 with repo.wlock(), repo.lock():
2031 with repo.wlock(), repo.lock():
2031 return _docommit(ui, repo, *pats, **opts)
2032 return _docommit(ui, repo, *pats, **opts)
2032
2033
2033
2034
2034 def _docommit(ui, repo, *pats, **opts):
2035 def _docommit(ui, repo, *pats, **opts):
2035 if opts.get('interactive'):
2036 if opts.get('interactive'):
2036 opts.pop('interactive')
2037 opts.pop('interactive')
2037 ret = cmdutil.dorecord(
2038 ret = cmdutil.dorecord(
2038 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2039 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2039 )
2040 )
2040 # ret can be 0 (no changes to record) or the value returned by
2041 # ret can be 0 (no changes to record) or the value returned by
2041 # commit(), 1 if nothing changed or None on success.
2042 # commit(), 1 if nothing changed or None on success.
2042 return 1 if ret == 0 else ret
2043 return 1 if ret == 0 else ret
2043
2044
2044 opts = pycompat.byteskwargs(opts)
2045 opts = pycompat.byteskwargs(opts)
2045 if opts.get(b'subrepos'):
2046 if opts.get(b'subrepos'):
2046 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'amend'])
2047 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'amend'])
2047 # Let --subrepos on the command line override config setting.
2048 # Let --subrepos on the command line override config setting.
2048 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2049 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2049
2050
2050 cmdutil.checkunfinished(repo, commit=True)
2051 cmdutil.checkunfinished(repo, commit=True)
2051
2052
2052 branch = repo[None].branch()
2053 branch = repo[None].branch()
2053 bheads = repo.branchheads(branch)
2054 bheads = repo.branchheads(branch)
2054 tip = repo.changelog.tip()
2055 tip = repo.changelog.tip()
2055
2056
2056 extra = {}
2057 extra = {}
2057 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2058 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2058 extra[b'close'] = b'1'
2059 extra[b'close'] = b'1'
2059
2060
2060 if repo[b'.'].closesbranch():
2061 if repo[b'.'].closesbranch():
2061 raise error.InputError(
2062 raise error.InputError(
2062 _(b'current revision is already a branch closing head')
2063 _(b'current revision is already a branch closing head')
2063 )
2064 )
2064 elif not bheads:
2065 elif not bheads:
2065 raise error.InputError(
2066 raise error.InputError(
2066 _(b'branch "%s" has no heads to close') % branch
2067 _(b'branch "%s" has no heads to close') % branch
2067 )
2068 )
2068 elif (
2069 elif (
2069 branch == repo[b'.'].branch()
2070 branch == repo[b'.'].branch()
2070 and repo[b'.'].node() not in bheads
2071 and repo[b'.'].node() not in bheads
2071 and not opts.get(b'force_close_branch')
2072 and not opts.get(b'force_close_branch')
2072 ):
2073 ):
2073 hint = _(
2074 hint = _(
2074 b'use --force-close-branch to close branch from a non-head'
2075 b'use --force-close-branch to close branch from a non-head'
2075 b' changeset'
2076 b' changeset'
2076 )
2077 )
2077 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2078 raise error.InputError(_(b'can only close branch heads'), hint=hint)
2078 elif opts.get(b'amend'):
2079 elif opts.get(b'amend'):
2079 if (
2080 if (
2080 repo[b'.'].p1().branch() != branch
2081 repo[b'.'].p1().branch() != branch
2081 and repo[b'.'].p2().branch() != branch
2082 and repo[b'.'].p2().branch() != branch
2082 ):
2083 ):
2083 raise error.InputError(_(b'can only close branch heads'))
2084 raise error.InputError(_(b'can only close branch heads'))
2084
2085
2085 if opts.get(b'amend'):
2086 if opts.get(b'amend'):
2086 if ui.configbool(b'ui', b'commitsubrepos'):
2087 if ui.configbool(b'ui', b'commitsubrepos'):
2087 raise error.InputError(
2088 raise error.InputError(
2088 _(b'cannot amend with ui.commitsubrepos enabled')
2089 _(b'cannot amend with ui.commitsubrepos enabled')
2089 )
2090 )
2090
2091
2091 old = repo[b'.']
2092 old = repo[b'.']
2092 rewriteutil.precheck(repo, [old.rev()], b'amend')
2093 rewriteutil.precheck(repo, [old.rev()], b'amend')
2093
2094
2094 # Currently histedit gets confused if an amend happens while histedit
2095 # Currently histedit gets confused if an amend happens while histedit
2095 # is in progress. Since we have a checkunfinished command, we are
2096 # is in progress. Since we have a checkunfinished command, we are
2096 # temporarily honoring it.
2097 # temporarily honoring it.
2097 #
2098 #
2098 # Note: eventually this guard will be removed. Please do not expect
2099 # Note: eventually this guard will be removed. Please do not expect
2099 # this behavior to remain.
2100 # this behavior to remain.
2100 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2101 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2101 cmdutil.checkunfinished(repo)
2102 cmdutil.checkunfinished(repo)
2102
2103
2103 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2104 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2104 if node == old.node():
2105 if node == old.node():
2105 ui.status(_(b"nothing changed\n"))
2106 ui.status(_(b"nothing changed\n"))
2106 return 1
2107 return 1
2107 else:
2108 else:
2108
2109
2109 def commitfunc(ui, repo, message, match, opts):
2110 def commitfunc(ui, repo, message, match, opts):
2110 overrides = {}
2111 overrides = {}
2111 if opts.get(b'secret'):
2112 if opts.get(b'secret'):
2112 overrides[(b'phases', b'new-commit')] = b'secret'
2113 overrides[(b'phases', b'new-commit')] = b'secret'
2113
2114
2114 baseui = repo.baseui
2115 baseui = repo.baseui
2115 with baseui.configoverride(overrides, b'commit'):
2116 with baseui.configoverride(overrides, b'commit'):
2116 with ui.configoverride(overrides, b'commit'):
2117 with ui.configoverride(overrides, b'commit'):
2117 editform = cmdutil.mergeeditform(
2118 editform = cmdutil.mergeeditform(
2118 repo[None], b'commit.normal'
2119 repo[None], b'commit.normal'
2119 )
2120 )
2120 editor = cmdutil.getcommiteditor(
2121 editor = cmdutil.getcommiteditor(
2121 editform=editform, **pycompat.strkwargs(opts)
2122 editform=editform, **pycompat.strkwargs(opts)
2122 )
2123 )
2123 return repo.commit(
2124 return repo.commit(
2124 message,
2125 message,
2125 opts.get(b'user'),
2126 opts.get(b'user'),
2126 opts.get(b'date'),
2127 opts.get(b'date'),
2127 match,
2128 match,
2128 editor=editor,
2129 editor=editor,
2129 extra=extra,
2130 extra=extra,
2130 )
2131 )
2131
2132
2132 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2133 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2133
2134
2134 if not node:
2135 if not node:
2135 stat = cmdutil.postcommitstatus(repo, pats, opts)
2136 stat = cmdutil.postcommitstatus(repo, pats, opts)
2136 if stat.deleted:
2137 if stat.deleted:
2137 ui.status(
2138 ui.status(
2138 _(
2139 _(
2139 b"nothing changed (%d missing files, see "
2140 b"nothing changed (%d missing files, see "
2140 b"'hg status')\n"
2141 b"'hg status')\n"
2141 )
2142 )
2142 % len(stat.deleted)
2143 % len(stat.deleted)
2143 )
2144 )
2144 else:
2145 else:
2145 ui.status(_(b"nothing changed\n"))
2146 ui.status(_(b"nothing changed\n"))
2146 return 1
2147 return 1
2147
2148
2148 cmdutil.commitstatus(repo, node, branch, bheads, tip, opts)
2149 cmdutil.commitstatus(repo, node, branch, bheads, tip, opts)
2149
2150
2150 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2151 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2151 status(
2152 status(
2152 ui,
2153 ui,
2153 repo,
2154 repo,
2154 modified=True,
2155 modified=True,
2155 added=True,
2156 added=True,
2156 removed=True,
2157 removed=True,
2157 deleted=True,
2158 deleted=True,
2158 unknown=True,
2159 unknown=True,
2159 subrepos=opts.get(b'subrepos'),
2160 subrepos=opts.get(b'subrepos'),
2160 )
2161 )
2161
2162
2162
2163
2163 @command(
2164 @command(
2164 b'config|showconfig|debugconfig',
2165 b'config|showconfig|debugconfig',
2165 [
2166 [
2166 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2167 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2167 (b'e', b'edit', None, _(b'edit user config')),
2168 (b'e', b'edit', None, _(b'edit user config')),
2168 (b'l', b'local', None, _(b'edit repository config')),
2169 (b'l', b'local', None, _(b'edit repository config')),
2169 (
2170 (
2170 b'',
2171 b'',
2171 b'shared',
2172 b'shared',
2172 None,
2173 None,
2173 _(b'edit shared source repository config (EXPERIMENTAL)'),
2174 _(b'edit shared source repository config (EXPERIMENTAL)'),
2174 ),
2175 ),
2175 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2176 (b'', b'non-shared', None, _(b'edit non shared config (EXPERIMENTAL)')),
2176 (b'g', b'global', None, _(b'edit global config')),
2177 (b'g', b'global', None, _(b'edit global config')),
2177 ]
2178 ]
2178 + formatteropts,
2179 + formatteropts,
2179 _(b'[-u] [NAME]...'),
2180 _(b'[-u] [NAME]...'),
2180 helpcategory=command.CATEGORY_HELP,
2181 helpcategory=command.CATEGORY_HELP,
2181 optionalrepo=True,
2182 optionalrepo=True,
2182 intents={INTENT_READONLY},
2183 intents={INTENT_READONLY},
2183 )
2184 )
2184 def config(ui, repo, *values, **opts):
2185 def config(ui, repo, *values, **opts):
2185 """show combined config settings from all hgrc files
2186 """show combined config settings from all hgrc files
2186
2187
2187 With no arguments, print names and values of all config items.
2188 With no arguments, print names and values of all config items.
2188
2189
2189 With one argument of the form section.name, print just the value
2190 With one argument of the form section.name, print just the value
2190 of that config item.
2191 of that config item.
2191
2192
2192 With multiple arguments, print names and values of all config
2193 With multiple arguments, print names and values of all config
2193 items with matching section names or section.names.
2194 items with matching section names or section.names.
2194
2195
2195 With --edit, start an editor on the user-level config file. With
2196 With --edit, start an editor on the user-level config file. With
2196 --global, edit the system-wide config file. With --local, edit the
2197 --global, edit the system-wide config file. With --local, edit the
2197 repository-level config file.
2198 repository-level config file.
2198
2199
2199 With --debug, the source (filename and line number) is printed
2200 With --debug, the source (filename and line number) is printed
2200 for each config item.
2201 for each config item.
2201
2202
2202 See :hg:`help config` for more information about config files.
2203 See :hg:`help config` for more information about config files.
2203
2204
2204 .. container:: verbose
2205 .. container:: verbose
2205
2206
2206 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2207 --non-shared flag is used to edit `.hg/hgrc-not-shared` config file.
2207 This file is not shared across shares when in share-safe mode.
2208 This file is not shared across shares when in share-safe mode.
2208
2209
2209 Template:
2210 Template:
2210
2211
2211 The following keywords are supported. See also :hg:`help templates`.
2212 The following keywords are supported. See also :hg:`help templates`.
2212
2213
2213 :name: String. Config name.
2214 :name: String. Config name.
2214 :source: String. Filename and line number where the item is defined.
2215 :source: String. Filename and line number where the item is defined.
2215 :value: String. Config value.
2216 :value: String. Config value.
2216
2217
2217 The --shared flag can be used to edit the config file of shared source
2218 The --shared flag can be used to edit the config file of shared source
2218 repository. It only works when you have shared using the experimental
2219 repository. It only works when you have shared using the experimental
2219 share safe feature.
2220 share safe feature.
2220
2221
2221 Returns 0 on success, 1 if NAME does not exist.
2222 Returns 0 on success, 1 if NAME does not exist.
2222
2223
2223 """
2224 """
2224
2225
2225 opts = pycompat.byteskwargs(opts)
2226 opts = pycompat.byteskwargs(opts)
2226 editopts = (b'edit', b'local', b'global', b'shared', b'non_shared')
2227 editopts = (b'edit', b'local', b'global', b'shared', b'non_shared')
2227 if any(opts.get(o) for o in editopts):
2228 if any(opts.get(o) for o in editopts):
2228 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2229 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2229 if opts.get(b'local'):
2230 if opts.get(b'local'):
2230 if not repo:
2231 if not repo:
2231 raise error.InputError(
2232 raise error.InputError(
2232 _(b"can't use --local outside a repository")
2233 _(b"can't use --local outside a repository")
2233 )
2234 )
2234 paths = [repo.vfs.join(b'hgrc')]
2235 paths = [repo.vfs.join(b'hgrc')]
2235 elif opts.get(b'global'):
2236 elif opts.get(b'global'):
2236 paths = rcutil.systemrcpath()
2237 paths = rcutil.systemrcpath()
2237 elif opts.get(b'shared'):
2238 elif opts.get(b'shared'):
2238 if not repo.shared():
2239 if not repo.shared():
2239 raise error.InputError(
2240 raise error.InputError(
2240 _(b"repository is not shared; can't use --shared")
2241 _(b"repository is not shared; can't use --shared")
2241 )
2242 )
2242 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2243 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2243 raise error.InputError(
2244 raise error.InputError(
2244 _(
2245 _(
2245 b"share safe feature not enabled; "
2246 b"share safe feature not enabled; "
2246 b"unable to edit shared source repository config"
2247 b"unable to edit shared source repository config"
2247 )
2248 )
2248 )
2249 )
2249 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2250 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2250 elif opts.get(b'non_shared'):
2251 elif opts.get(b'non_shared'):
2251 paths = [repo.vfs.join(b'hgrc-not-shared')]
2252 paths = [repo.vfs.join(b'hgrc-not-shared')]
2252 else:
2253 else:
2253 paths = rcutil.userrcpath()
2254 paths = rcutil.userrcpath()
2254
2255
2255 for f in paths:
2256 for f in paths:
2256 if os.path.exists(f):
2257 if os.path.exists(f):
2257 break
2258 break
2258 else:
2259 else:
2259 if opts.get(b'global'):
2260 if opts.get(b'global'):
2260 samplehgrc = uimod.samplehgrcs[b'global']
2261 samplehgrc = uimod.samplehgrcs[b'global']
2261 elif opts.get(b'local'):
2262 elif opts.get(b'local'):
2262 samplehgrc = uimod.samplehgrcs[b'local']
2263 samplehgrc = uimod.samplehgrcs[b'local']
2263 else:
2264 else:
2264 samplehgrc = uimod.samplehgrcs[b'user']
2265 samplehgrc = uimod.samplehgrcs[b'user']
2265
2266
2266 f = paths[0]
2267 f = paths[0]
2267 fp = open(f, b"wb")
2268 fp = open(f, b"wb")
2268 fp.write(util.tonativeeol(samplehgrc))
2269 fp.write(util.tonativeeol(samplehgrc))
2269 fp.close()
2270 fp.close()
2270
2271
2271 editor = ui.geteditor()
2272 editor = ui.geteditor()
2272 ui.system(
2273 ui.system(
2273 b"%s \"%s\"" % (editor, f),
2274 b"%s \"%s\"" % (editor, f),
2274 onerr=error.InputError,
2275 onerr=error.InputError,
2275 errprefix=_(b"edit failed"),
2276 errprefix=_(b"edit failed"),
2276 blockedtag=b'config_edit',
2277 blockedtag=b'config_edit',
2277 )
2278 )
2278 return
2279 return
2279 ui.pager(b'config')
2280 ui.pager(b'config')
2280 fm = ui.formatter(b'config', opts)
2281 fm = ui.formatter(b'config', opts)
2281 for t, f in rcutil.rccomponents():
2282 for t, f in rcutil.rccomponents():
2282 if t == b'path':
2283 if t == b'path':
2283 ui.debug(b'read config from: %s\n' % f)
2284 ui.debug(b'read config from: %s\n' % f)
2284 elif t == b'resource':
2285 elif t == b'resource':
2285 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2286 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2286 elif t == b'items':
2287 elif t == b'items':
2287 # Don't print anything for 'items'.
2288 # Don't print anything for 'items'.
2288 pass
2289 pass
2289 else:
2290 else:
2290 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2291 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2291 untrusted = bool(opts.get(b'untrusted'))
2292 untrusted = bool(opts.get(b'untrusted'))
2292
2293
2293 selsections = selentries = []
2294 selsections = selentries = []
2294 if values:
2295 if values:
2295 selsections = [v for v in values if b'.' not in v]
2296 selsections = [v for v in values if b'.' not in v]
2296 selentries = [v for v in values if b'.' in v]
2297 selentries = [v for v in values if b'.' in v]
2297 uniquesel = len(selentries) == 1 and not selsections
2298 uniquesel = len(selentries) == 1 and not selsections
2298 selsections = set(selsections)
2299 selsections = set(selsections)
2299 selentries = set(selentries)
2300 selentries = set(selentries)
2300
2301
2301 matched = False
2302 matched = False
2302 for section, name, value in ui.walkconfig(untrusted=untrusted):
2303 for section, name, value in ui.walkconfig(untrusted=untrusted):
2303 source = ui.configsource(section, name, untrusted)
2304 source = ui.configsource(section, name, untrusted)
2304 value = pycompat.bytestr(value)
2305 value = pycompat.bytestr(value)
2305 defaultvalue = ui.configdefault(section, name)
2306 defaultvalue = ui.configdefault(section, name)
2306 if fm.isplain():
2307 if fm.isplain():
2307 source = source or b'none'
2308 source = source or b'none'
2308 value = value.replace(b'\n', b'\\n')
2309 value = value.replace(b'\n', b'\\n')
2309 entryname = section + b'.' + name
2310 entryname = section + b'.' + name
2310 if values and not (section in selsections or entryname in selentries):
2311 if values and not (section in selsections or entryname in selentries):
2311 continue
2312 continue
2312 fm.startitem()
2313 fm.startitem()
2313 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2314 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2314 if uniquesel:
2315 if uniquesel:
2315 fm.data(name=entryname)
2316 fm.data(name=entryname)
2316 fm.write(b'value', b'%s\n', value)
2317 fm.write(b'value', b'%s\n', value)
2317 else:
2318 else:
2318 fm.write(b'name value', b'%s=%s\n', entryname, value)
2319 fm.write(b'name value', b'%s=%s\n', entryname, value)
2319 if formatter.isprintable(defaultvalue):
2320 if formatter.isprintable(defaultvalue):
2320 fm.data(defaultvalue=defaultvalue)
2321 fm.data(defaultvalue=defaultvalue)
2321 elif isinstance(defaultvalue, list) and all(
2322 elif isinstance(defaultvalue, list) and all(
2322 formatter.isprintable(e) for e in defaultvalue
2323 formatter.isprintable(e) for e in defaultvalue
2323 ):
2324 ):
2324 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2325 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2325 # TODO: no idea how to process unsupported defaultvalue types
2326 # TODO: no idea how to process unsupported defaultvalue types
2326 matched = True
2327 matched = True
2327 fm.end()
2328 fm.end()
2328 if matched:
2329 if matched:
2329 return 0
2330 return 0
2330 return 1
2331 return 1
2331
2332
2332
2333
2333 @command(
2334 @command(
2334 b'continue',
2335 b'continue',
2335 dryrunopts,
2336 dryrunopts,
2336 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2337 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2337 helpbasic=True,
2338 helpbasic=True,
2338 )
2339 )
2339 def continuecmd(ui, repo, **opts):
2340 def continuecmd(ui, repo, **opts):
2340 """resumes an interrupted operation (EXPERIMENTAL)
2341 """resumes an interrupted operation (EXPERIMENTAL)
2341
2342
2342 Finishes a multistep operation like graft, histedit, rebase, merge,
2343 Finishes a multistep operation like graft, histedit, rebase, merge,
2343 and unshelve if they are in an interrupted state.
2344 and unshelve if they are in an interrupted state.
2344
2345
2345 use --dry-run/-n to dry run the command.
2346 use --dry-run/-n to dry run the command.
2346 """
2347 """
2347 dryrun = opts.get('dry_run')
2348 dryrun = opts.get('dry_run')
2348 contstate = cmdutil.getunfinishedstate(repo)
2349 contstate = cmdutil.getunfinishedstate(repo)
2349 if not contstate:
2350 if not contstate:
2350 raise error.StateError(_(b'no operation in progress'))
2351 raise error.StateError(_(b'no operation in progress'))
2351 if not contstate.continuefunc:
2352 if not contstate.continuefunc:
2352 raise error.StateError(
2353 raise error.StateError(
2353 (
2354 (
2354 _(b"%s in progress but does not support 'hg continue'")
2355 _(b"%s in progress but does not support 'hg continue'")
2355 % (contstate._opname)
2356 % (contstate._opname)
2356 ),
2357 ),
2357 hint=contstate.continuemsg(),
2358 hint=contstate.continuemsg(),
2358 )
2359 )
2359 if dryrun:
2360 if dryrun:
2360 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2361 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2361 return
2362 return
2362 return contstate.continuefunc(ui, repo)
2363 return contstate.continuefunc(ui, repo)
2363
2364
2364
2365
2365 @command(
2366 @command(
2366 b'copy|cp',
2367 b'copy|cp',
2367 [
2368 [
2368 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2369 (b'', b'forget', None, _(b'unmark a destination file as copied')),
2369 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2370 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2370 (
2371 (
2371 b'',
2372 b'',
2372 b'at-rev',
2373 b'at-rev',
2373 b'',
2374 b'',
2374 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2375 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2375 _(b'REV'),
2376 _(b'REV'),
2376 ),
2377 ),
2377 (
2378 (
2378 b'f',
2379 b'f',
2379 b'force',
2380 b'force',
2380 None,
2381 None,
2381 _(b'forcibly copy over an existing managed file'),
2382 _(b'forcibly copy over an existing managed file'),
2382 ),
2383 ),
2383 ]
2384 ]
2384 + walkopts
2385 + walkopts
2385 + dryrunopts,
2386 + dryrunopts,
2386 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2387 _(b'[OPTION]... (SOURCE... DEST | --forget DEST...)'),
2387 helpcategory=command.CATEGORY_FILE_CONTENTS,
2388 helpcategory=command.CATEGORY_FILE_CONTENTS,
2388 )
2389 )
2389 def copy(ui, repo, *pats, **opts):
2390 def copy(ui, repo, *pats, **opts):
2390 """mark files as copied for the next commit
2391 """mark files as copied for the next commit
2391
2392
2392 Mark dest as having copies of source files. If dest is a
2393 Mark dest as having copies of source files. If dest is a
2393 directory, copies are put in that directory. If dest is a file,
2394 directory, copies are put in that directory. If dest is a file,
2394 the source must be a single file.
2395 the source must be a single file.
2395
2396
2396 By default, this command copies the contents of files as they
2397 By default, this command copies the contents of files as they
2397 exist in the working directory. If invoked with -A/--after, the
2398 exist in the working directory. If invoked with -A/--after, the
2398 operation is recorded, but no copying is performed.
2399 operation is recorded, but no copying is performed.
2399
2400
2400 To undo marking a destination file as copied, use --forget. With that
2401 To undo marking a destination file as copied, use --forget. With that
2401 option, all given (positional) arguments are unmarked as copies. The
2402 option, all given (positional) arguments are unmarked as copies. The
2402 destination file(s) will be left in place (still tracked).
2403 destination file(s) will be left in place (still tracked).
2403
2404
2404 This command takes effect with the next commit by default.
2405 This command takes effect with the next commit by default.
2405
2406
2406 Returns 0 on success, 1 if errors are encountered.
2407 Returns 0 on success, 1 if errors are encountered.
2407 """
2408 """
2408 opts = pycompat.byteskwargs(opts)
2409 opts = pycompat.byteskwargs(opts)
2409 with repo.wlock():
2410 with repo.wlock():
2410 return cmdutil.copy(ui, repo, pats, opts)
2411 return cmdutil.copy(ui, repo, pats, opts)
2411
2412
2412
2413
2413 @command(
2414 @command(
2414 b'debugcommands',
2415 b'debugcommands',
2415 [],
2416 [],
2416 _(b'[COMMAND]'),
2417 _(b'[COMMAND]'),
2417 helpcategory=command.CATEGORY_HELP,
2418 helpcategory=command.CATEGORY_HELP,
2418 norepo=True,
2419 norepo=True,
2419 )
2420 )
2420 def debugcommands(ui, cmd=b'', *args):
2421 def debugcommands(ui, cmd=b'', *args):
2421 """list all available commands and options"""
2422 """list all available commands and options"""
2422 for cmd, vals in sorted(pycompat.iteritems(table)):
2423 for cmd, vals in sorted(pycompat.iteritems(table)):
2423 cmd = cmd.split(b'|')[0]
2424 cmd = cmd.split(b'|')[0]
2424 opts = b', '.join([i[1] for i in vals[1]])
2425 opts = b', '.join([i[1] for i in vals[1]])
2425 ui.write(b'%s: %s\n' % (cmd, opts))
2426 ui.write(b'%s: %s\n' % (cmd, opts))
2426
2427
2427
2428
2428 @command(
2429 @command(
2429 b'debugcomplete',
2430 b'debugcomplete',
2430 [(b'o', b'options', None, _(b'show the command options'))],
2431 [(b'o', b'options', None, _(b'show the command options'))],
2431 _(b'[-o] CMD'),
2432 _(b'[-o] CMD'),
2432 helpcategory=command.CATEGORY_HELP,
2433 helpcategory=command.CATEGORY_HELP,
2433 norepo=True,
2434 norepo=True,
2434 )
2435 )
2435 def debugcomplete(ui, cmd=b'', **opts):
2436 def debugcomplete(ui, cmd=b'', **opts):
2436 """returns the completion list associated with the given command"""
2437 """returns the completion list associated with the given command"""
2437
2438
2438 if opts.get('options'):
2439 if opts.get('options'):
2439 options = []
2440 options = []
2440 otables = [globalopts]
2441 otables = [globalopts]
2441 if cmd:
2442 if cmd:
2442 aliases, entry = cmdutil.findcmd(cmd, table, False)
2443 aliases, entry = cmdutil.findcmd(cmd, table, False)
2443 otables.append(entry[1])
2444 otables.append(entry[1])
2444 for t in otables:
2445 for t in otables:
2445 for o in t:
2446 for o in t:
2446 if b"(DEPRECATED)" in o[3]:
2447 if b"(DEPRECATED)" in o[3]:
2447 continue
2448 continue
2448 if o[0]:
2449 if o[0]:
2449 options.append(b'-%s' % o[0])
2450 options.append(b'-%s' % o[0])
2450 options.append(b'--%s' % o[1])
2451 options.append(b'--%s' % o[1])
2451 ui.write(b"%s\n" % b"\n".join(options))
2452 ui.write(b"%s\n" % b"\n".join(options))
2452 return
2453 return
2453
2454
2454 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2455 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2455 if ui.verbose:
2456 if ui.verbose:
2456 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2457 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2457 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2458 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2458
2459
2459
2460
2460 @command(
2461 @command(
2461 b'diff',
2462 b'diff',
2462 [
2463 [
2463 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2464 (b'r', b'rev', [], _(b'revision (DEPRECATED)'), _(b'REV')),
2464 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2465 (b'', b'from', b'', _(b'revision to diff from'), _(b'REV1')),
2465 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2466 (b'', b'to', b'', _(b'revision to diff to'), _(b'REV2')),
2466 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2467 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2468 (
2469 b'',
2470 b'merge',
2471 False,
2472 _(
2473 b'show difference between auto-merge and committed '
2474 b'merge for merge commits (EXPERIMENTAL)'
2475 ),
2476 _(b'REV'),
2477 ),
2467 ]
2478 ]
2468 + diffopts
2479 + diffopts
2469 + diffopts2
2480 + diffopts2
2470 + walkopts
2481 + walkopts
2471 + subrepoopts,
2482 + subrepoopts,
2472 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2483 _(b'[OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...'),
2473 helpcategory=command.CATEGORY_FILE_CONTENTS,
2484 helpcategory=command.CATEGORY_FILE_CONTENTS,
2474 helpbasic=True,
2485 helpbasic=True,
2475 inferrepo=True,
2486 inferrepo=True,
2476 intents={INTENT_READONLY},
2487 intents={INTENT_READONLY},
2477 )
2488 )
2478 def diff(ui, repo, *pats, **opts):
2489 def diff(ui, repo, *pats, **opts):
2479 """diff repository (or selected files)
2490 """diff repository (or selected files)
2480
2491
2481 Show differences between revisions for the specified files.
2492 Show differences between revisions for the specified files.
2482
2493
2483 Differences between files are shown using the unified diff format.
2494 Differences between files are shown using the unified diff format.
2484
2495
2485 .. note::
2496 .. note::
2486
2497
2487 :hg:`diff` may generate unexpected results for merges, as it will
2498 :hg:`diff` may generate unexpected results for merges, as it will
2488 default to comparing against the working directory's first
2499 default to comparing against the working directory's first
2489 parent changeset if no revisions are specified.
2500 parent changeset if no revisions are specified.
2490
2501
2491 By default, the working directory files are compared to its first parent. To
2502 By default, the working directory files are compared to its first parent. To
2492 see the differences from another revision, use --from. To see the difference
2503 see the differences from another revision, use --from. To see the difference
2493 to another revision, use --to. For example, :hg:`diff --from .^` will show
2504 to another revision, use --to. For example, :hg:`diff --from .^` will show
2494 the differences from the working copy's grandparent to the working copy,
2505 the differences from the working copy's grandparent to the working copy,
2495 :hg:`diff --to .` will show the diff from the working copy to its parent
2506 :hg:`diff --to .` will show the diff from the working copy to its parent
2496 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2507 (i.e. the reverse of the default), and :hg:`diff --from 1.0 --to 1.2` will
2497 show the diff between those two revisions.
2508 show the diff between those two revisions.
2498
2509
2499 Alternatively you can specify -c/--change with a revision to see the changes
2510 Alternatively you can specify -c/--change with a revision to see the changes
2500 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2511 in that changeset relative to its first parent (i.e. :hg:`diff -c 42` is
2501 equivalent to :hg:`diff --from 42^ --to 42`)
2512 equivalent to :hg:`diff --from 42^ --to 42`)
2502
2513
2503 Without the -a/--text option, diff will avoid generating diffs of
2514 Without the -a/--text option, diff will avoid generating diffs of
2504 files it detects as binary. With -a, diff will generate a diff
2515 files it detects as binary. With -a, diff will generate a diff
2505 anyway, probably with undesirable results.
2516 anyway, probably with undesirable results.
2506
2517
2507 Use the -g/--git option to generate diffs in the git extended diff
2518 Use the -g/--git option to generate diffs in the git extended diff
2508 format. For more information, read :hg:`help diffs`.
2519 format. For more information, read :hg:`help diffs`.
2509
2520
2510 .. container:: verbose
2521 .. container:: verbose
2511
2522
2512 Examples:
2523 Examples:
2513
2524
2514 - compare a file in the current working directory to its parent::
2525 - compare a file in the current working directory to its parent::
2515
2526
2516 hg diff foo.c
2527 hg diff foo.c
2517
2528
2518 - compare two historical versions of a directory, with rename info::
2529 - compare two historical versions of a directory, with rename info::
2519
2530
2520 hg diff --git --from 1.0 --to 1.2 lib/
2531 hg diff --git --from 1.0 --to 1.2 lib/
2521
2532
2522 - get change stats relative to the last change on some date::
2533 - get change stats relative to the last change on some date::
2523
2534
2524 hg diff --stat --from "date('may 2')"
2535 hg diff --stat --from "date('may 2')"
2525
2536
2526 - diff all newly-added files that contain a keyword::
2537 - diff all newly-added files that contain a keyword::
2527
2538
2528 hg diff "set:added() and grep(GNU)"
2539 hg diff "set:added() and grep(GNU)"
2529
2540
2530 - compare a revision and its parents::
2541 - compare a revision and its parents::
2531
2542
2532 hg diff -c 9353 # compare against first parent
2543 hg diff -c 9353 # compare against first parent
2533 hg diff --from 9353^ --to 9353 # same using revset syntax
2544 hg diff --from 9353^ --to 9353 # same using revset syntax
2534 hg diff --from 9353^2 --to 9353 # compare against the second parent
2545 hg diff --from 9353^2 --to 9353 # compare against the second parent
2535
2546
2536 Returns 0 on success.
2547 Returns 0 on success.
2537 """
2548 """
2538
2549
2539 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2550 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2540 opts = pycompat.byteskwargs(opts)
2551 opts = pycompat.byteskwargs(opts)
2541 revs = opts.get(b'rev')
2552 revs = opts.get(b'rev')
2542 change = opts.get(b'change')
2553 change = opts.get(b'change')
2543 from_rev = opts.get(b'from')
2554 from_rev = opts.get(b'from')
2544 to_rev = opts.get(b'to')
2555 to_rev = opts.get(b'to')
2545 stat = opts.get(b'stat')
2556 stat = opts.get(b'stat')
2546 reverse = opts.get(b'reverse')
2557 reverse = opts.get(b'reverse')
2558 diffmerge = opts.get(b'merge')
2547
2559
2548 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2560 cmdutil.check_incompatible_arguments(opts, b'from', [b'rev', b'change'])
2549 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2561 cmdutil.check_incompatible_arguments(opts, b'to', [b'rev', b'change'])
2550 if change:
2562 if change:
2551 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2563 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2552 ctx2 = scmutil.revsingle(repo, change, None)
2564 ctx2 = scmutil.revsingle(repo, change, None)
2553 ctx1 = ctx2.p1()
2565 if diffmerge and ctx2.p2().node() != nullid:
2566 pctx1 = ctx2.p1()
2567 pctx2 = ctx2.p2()
2568 wctx = contextmod.overlayworkingctx(repo)
2569 wctx.setbase(pctx1)
2570 with ui.configoverride(
2571 {
2572 (
2573 b'ui',
2574 b'forcemerge',
2575 ): b'internal:merge3-lie-about-conflicts',
2576 },
2577 b'diff --merge',
2578 ):
2579 mergemod.merge(pctx2, wc=wctx)
2580 ctx1 = wctx
2581 else:
2582 ctx1 = ctx2.p1()
2554 elif from_rev or to_rev:
2583 elif from_rev or to_rev:
2555 repo = scmutil.unhidehashlikerevs(
2584 repo = scmutil.unhidehashlikerevs(
2556 repo, [from_rev] + [to_rev], b'nowarn'
2585 repo, [from_rev] + [to_rev], b'nowarn'
2557 )
2586 )
2558 ctx1 = scmutil.revsingle(repo, from_rev, None)
2587 ctx1 = scmutil.revsingle(repo, from_rev, None)
2559 ctx2 = scmutil.revsingle(repo, to_rev, None)
2588 ctx2 = scmutil.revsingle(repo, to_rev, None)
2560 else:
2589 else:
2561 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2590 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2562 ctx1, ctx2 = scmutil.revpair(repo, revs)
2591 ctx1, ctx2 = scmutil.revpair(repo, revs)
2563
2592
2564 if reverse:
2593 if reverse:
2565 ctxleft = ctx2
2594 ctxleft = ctx2
2566 ctxright = ctx1
2595 ctxright = ctx1
2567 else:
2596 else:
2568 ctxleft = ctx1
2597 ctxleft = ctx1
2569 ctxright = ctx2
2598 ctxright = ctx2
2570
2599
2571 diffopts = patch.diffallopts(ui, opts)
2600 diffopts = patch.diffallopts(ui, opts)
2572 m = scmutil.match(ctx2, pats, opts)
2601 m = scmutil.match(ctx2, pats, opts)
2573 m = repo.narrowmatch(m)
2602 m = repo.narrowmatch(m)
2574 ui.pager(b'diff')
2603 ui.pager(b'diff')
2575 logcmdutil.diffordiffstat(
2604 logcmdutil.diffordiffstat(
2576 ui,
2605 ui,
2577 repo,
2606 repo,
2578 diffopts,
2607 diffopts,
2579 ctxleft,
2608 ctxleft,
2580 ctxright,
2609 ctxright,
2581 m,
2610 m,
2582 stat=stat,
2611 stat=stat,
2583 listsubrepos=opts.get(b'subrepos'),
2612 listsubrepos=opts.get(b'subrepos'),
2584 root=opts.get(b'root'),
2613 root=opts.get(b'root'),
2585 )
2614 )
2586
2615
2587
2616
2588 @command(
2617 @command(
2589 b'export',
2618 b'export',
2590 [
2619 [
2591 (
2620 (
2592 b'B',
2621 b'B',
2593 b'bookmark',
2622 b'bookmark',
2594 b'',
2623 b'',
2595 _(b'export changes only reachable by given bookmark'),
2624 _(b'export changes only reachable by given bookmark'),
2596 _(b'BOOKMARK'),
2625 _(b'BOOKMARK'),
2597 ),
2626 ),
2598 (
2627 (
2599 b'o',
2628 b'o',
2600 b'output',
2629 b'output',
2601 b'',
2630 b'',
2602 _(b'print output to file with formatted name'),
2631 _(b'print output to file with formatted name'),
2603 _(b'FORMAT'),
2632 _(b'FORMAT'),
2604 ),
2633 ),
2605 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2634 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2606 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2635 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2607 ]
2636 ]
2608 + diffopts
2637 + diffopts
2609 + formatteropts,
2638 + formatteropts,
2610 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2639 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2611 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2640 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2612 helpbasic=True,
2641 helpbasic=True,
2613 intents={INTENT_READONLY},
2642 intents={INTENT_READONLY},
2614 )
2643 )
2615 def export(ui, repo, *changesets, **opts):
2644 def export(ui, repo, *changesets, **opts):
2616 """dump the header and diffs for one or more changesets
2645 """dump the header and diffs for one or more changesets
2617
2646
2618 Print the changeset header and diffs for one or more revisions.
2647 Print the changeset header and diffs for one or more revisions.
2619 If no revision is given, the parent of the working directory is used.
2648 If no revision is given, the parent of the working directory is used.
2620
2649
2621 The information shown in the changeset header is: author, date,
2650 The information shown in the changeset header is: author, date,
2622 branch name (if non-default), changeset hash, parent(s) and commit
2651 branch name (if non-default), changeset hash, parent(s) and commit
2623 comment.
2652 comment.
2624
2653
2625 .. note::
2654 .. note::
2626
2655
2627 :hg:`export` may generate unexpected diff output for merge
2656 :hg:`export` may generate unexpected diff output for merge
2628 changesets, as it will compare the merge changeset against its
2657 changesets, as it will compare the merge changeset against its
2629 first parent only.
2658 first parent only.
2630
2659
2631 Output may be to a file, in which case the name of the file is
2660 Output may be to a file, in which case the name of the file is
2632 given using a template string. See :hg:`help templates`. In addition
2661 given using a template string. See :hg:`help templates`. In addition
2633 to the common template keywords, the following formatting rules are
2662 to the common template keywords, the following formatting rules are
2634 supported:
2663 supported:
2635
2664
2636 :``%%``: literal "%" character
2665 :``%%``: literal "%" character
2637 :``%H``: changeset hash (40 hexadecimal digits)
2666 :``%H``: changeset hash (40 hexadecimal digits)
2638 :``%N``: number of patches being generated
2667 :``%N``: number of patches being generated
2639 :``%R``: changeset revision number
2668 :``%R``: changeset revision number
2640 :``%b``: basename of the exporting repository
2669 :``%b``: basename of the exporting repository
2641 :``%h``: short-form changeset hash (12 hexadecimal digits)
2670 :``%h``: short-form changeset hash (12 hexadecimal digits)
2642 :``%m``: first line of the commit message (only alphanumeric characters)
2671 :``%m``: first line of the commit message (only alphanumeric characters)
2643 :``%n``: zero-padded sequence number, starting at 1
2672 :``%n``: zero-padded sequence number, starting at 1
2644 :``%r``: zero-padded changeset revision number
2673 :``%r``: zero-padded changeset revision number
2645 :``\\``: literal "\\" character
2674 :``\\``: literal "\\" character
2646
2675
2647 Without the -a/--text option, export will avoid generating diffs
2676 Without the -a/--text option, export will avoid generating diffs
2648 of files it detects as binary. With -a, export will generate a
2677 of files it detects as binary. With -a, export will generate a
2649 diff anyway, probably with undesirable results.
2678 diff anyway, probably with undesirable results.
2650
2679
2651 With -B/--bookmark changesets reachable by the given bookmark are
2680 With -B/--bookmark changesets reachable by the given bookmark are
2652 selected.
2681 selected.
2653
2682
2654 Use the -g/--git option to generate diffs in the git extended diff
2683 Use the -g/--git option to generate diffs in the git extended diff
2655 format. See :hg:`help diffs` for more information.
2684 format. See :hg:`help diffs` for more information.
2656
2685
2657 With the --switch-parent option, the diff will be against the
2686 With the --switch-parent option, the diff will be against the
2658 second parent. It can be useful to review a merge.
2687 second parent. It can be useful to review a merge.
2659
2688
2660 .. container:: verbose
2689 .. container:: verbose
2661
2690
2662 Template:
2691 Template:
2663
2692
2664 The following keywords are supported in addition to the common template
2693 The following keywords are supported in addition to the common template
2665 keywords and functions. See also :hg:`help templates`.
2694 keywords and functions. See also :hg:`help templates`.
2666
2695
2667 :diff: String. Diff content.
2696 :diff: String. Diff content.
2668 :parents: List of strings. Parent nodes of the changeset.
2697 :parents: List of strings. Parent nodes of the changeset.
2669
2698
2670 Examples:
2699 Examples:
2671
2700
2672 - use export and import to transplant a bugfix to the current
2701 - use export and import to transplant a bugfix to the current
2673 branch::
2702 branch::
2674
2703
2675 hg export -r 9353 | hg import -
2704 hg export -r 9353 | hg import -
2676
2705
2677 - export all the changesets between two revisions to a file with
2706 - export all the changesets between two revisions to a file with
2678 rename information::
2707 rename information::
2679
2708
2680 hg export --git -r 123:150 > changes.txt
2709 hg export --git -r 123:150 > changes.txt
2681
2710
2682 - split outgoing changes into a series of patches with
2711 - split outgoing changes into a series of patches with
2683 descriptive names::
2712 descriptive names::
2684
2713
2685 hg export -r "outgoing()" -o "%n-%m.patch"
2714 hg export -r "outgoing()" -o "%n-%m.patch"
2686
2715
2687 Returns 0 on success.
2716 Returns 0 on success.
2688 """
2717 """
2689 opts = pycompat.byteskwargs(opts)
2718 opts = pycompat.byteskwargs(opts)
2690 bookmark = opts.get(b'bookmark')
2719 bookmark = opts.get(b'bookmark')
2691 changesets += tuple(opts.get(b'rev', []))
2720 changesets += tuple(opts.get(b'rev', []))
2692
2721
2693 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2722 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2694
2723
2695 if bookmark:
2724 if bookmark:
2696 if bookmark not in repo._bookmarks:
2725 if bookmark not in repo._bookmarks:
2697 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2726 raise error.InputError(_(b"bookmark '%s' not found") % bookmark)
2698
2727
2699 revs = scmutil.bookmarkrevs(repo, bookmark)
2728 revs = scmutil.bookmarkrevs(repo, bookmark)
2700 else:
2729 else:
2701 if not changesets:
2730 if not changesets:
2702 changesets = [b'.']
2731 changesets = [b'.']
2703
2732
2704 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2733 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2705 revs = scmutil.revrange(repo, changesets)
2734 revs = scmutil.revrange(repo, changesets)
2706
2735
2707 if not revs:
2736 if not revs:
2708 raise error.InputError(_(b"export requires at least one changeset"))
2737 raise error.InputError(_(b"export requires at least one changeset"))
2709 if len(revs) > 1:
2738 if len(revs) > 1:
2710 ui.note(_(b'exporting patches:\n'))
2739 ui.note(_(b'exporting patches:\n'))
2711 else:
2740 else:
2712 ui.note(_(b'exporting patch:\n'))
2741 ui.note(_(b'exporting patch:\n'))
2713
2742
2714 fntemplate = opts.get(b'output')
2743 fntemplate = opts.get(b'output')
2715 if cmdutil.isstdiofilename(fntemplate):
2744 if cmdutil.isstdiofilename(fntemplate):
2716 fntemplate = b''
2745 fntemplate = b''
2717
2746
2718 if fntemplate:
2747 if fntemplate:
2719 fm = formatter.nullformatter(ui, b'export', opts)
2748 fm = formatter.nullformatter(ui, b'export', opts)
2720 else:
2749 else:
2721 ui.pager(b'export')
2750 ui.pager(b'export')
2722 fm = ui.formatter(b'export', opts)
2751 fm = ui.formatter(b'export', opts)
2723 with fm:
2752 with fm:
2724 cmdutil.export(
2753 cmdutil.export(
2725 repo,
2754 repo,
2726 revs,
2755 revs,
2727 fm,
2756 fm,
2728 fntemplate=fntemplate,
2757 fntemplate=fntemplate,
2729 switch_parent=opts.get(b'switch_parent'),
2758 switch_parent=opts.get(b'switch_parent'),
2730 opts=patch.diffallopts(ui, opts),
2759 opts=patch.diffallopts(ui, opts),
2731 )
2760 )
2732
2761
2733
2762
2734 @command(
2763 @command(
2735 b'files',
2764 b'files',
2736 [
2765 [
2737 (
2766 (
2738 b'r',
2767 b'r',
2739 b'rev',
2768 b'rev',
2740 b'',
2769 b'',
2741 _(b'search the repository as it is in REV'),
2770 _(b'search the repository as it is in REV'),
2742 _(b'REV'),
2771 _(b'REV'),
2743 ),
2772 ),
2744 (
2773 (
2745 b'0',
2774 b'0',
2746 b'print0',
2775 b'print0',
2747 None,
2776 None,
2748 _(b'end filenames with NUL, for use with xargs'),
2777 _(b'end filenames with NUL, for use with xargs'),
2749 ),
2778 ),
2750 ]
2779 ]
2751 + walkopts
2780 + walkopts
2752 + formatteropts
2781 + formatteropts
2753 + subrepoopts,
2782 + subrepoopts,
2754 _(b'[OPTION]... [FILE]...'),
2783 _(b'[OPTION]... [FILE]...'),
2755 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2784 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2756 intents={INTENT_READONLY},
2785 intents={INTENT_READONLY},
2757 )
2786 )
2758 def files(ui, repo, *pats, **opts):
2787 def files(ui, repo, *pats, **opts):
2759 """list tracked files
2788 """list tracked files
2760
2789
2761 Print files under Mercurial control in the working directory or
2790 Print files under Mercurial control in the working directory or
2762 specified revision for given files (excluding removed files).
2791 specified revision for given files (excluding removed files).
2763 Files can be specified as filenames or filesets.
2792 Files can be specified as filenames or filesets.
2764
2793
2765 If no files are given to match, this command prints the names
2794 If no files are given to match, this command prints the names
2766 of all files under Mercurial control.
2795 of all files under Mercurial control.
2767
2796
2768 .. container:: verbose
2797 .. container:: verbose
2769
2798
2770 Template:
2799 Template:
2771
2800
2772 The following keywords are supported in addition to the common template
2801 The following keywords are supported in addition to the common template
2773 keywords and functions. See also :hg:`help templates`.
2802 keywords and functions. See also :hg:`help templates`.
2774
2803
2775 :flags: String. Character denoting file's symlink and executable bits.
2804 :flags: String. Character denoting file's symlink and executable bits.
2776 :path: String. Repository-absolute path of the file.
2805 :path: String. Repository-absolute path of the file.
2777 :size: Integer. Size of the file in bytes.
2806 :size: Integer. Size of the file in bytes.
2778
2807
2779 Examples:
2808 Examples:
2780
2809
2781 - list all files under the current directory::
2810 - list all files under the current directory::
2782
2811
2783 hg files .
2812 hg files .
2784
2813
2785 - shows sizes and flags for current revision::
2814 - shows sizes and flags for current revision::
2786
2815
2787 hg files -vr .
2816 hg files -vr .
2788
2817
2789 - list all files named README::
2818 - list all files named README::
2790
2819
2791 hg files -I "**/README"
2820 hg files -I "**/README"
2792
2821
2793 - list all binary files::
2822 - list all binary files::
2794
2823
2795 hg files "set:binary()"
2824 hg files "set:binary()"
2796
2825
2797 - find files containing a regular expression::
2826 - find files containing a regular expression::
2798
2827
2799 hg files "set:grep('bob')"
2828 hg files "set:grep('bob')"
2800
2829
2801 - search tracked file contents with xargs and grep::
2830 - search tracked file contents with xargs and grep::
2802
2831
2803 hg files -0 | xargs -0 grep foo
2832 hg files -0 | xargs -0 grep foo
2804
2833
2805 See :hg:`help patterns` and :hg:`help filesets` for more information
2834 See :hg:`help patterns` and :hg:`help filesets` for more information
2806 on specifying file patterns.
2835 on specifying file patterns.
2807
2836
2808 Returns 0 if a match is found, 1 otherwise.
2837 Returns 0 if a match is found, 1 otherwise.
2809
2838
2810 """
2839 """
2811
2840
2812 opts = pycompat.byteskwargs(opts)
2841 opts = pycompat.byteskwargs(opts)
2813 rev = opts.get(b'rev')
2842 rev = opts.get(b'rev')
2814 if rev:
2843 if rev:
2815 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2844 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2816 ctx = scmutil.revsingle(repo, rev, None)
2845 ctx = scmutil.revsingle(repo, rev, None)
2817
2846
2818 end = b'\n'
2847 end = b'\n'
2819 if opts.get(b'print0'):
2848 if opts.get(b'print0'):
2820 end = b'\0'
2849 end = b'\0'
2821 fmt = b'%s' + end
2850 fmt = b'%s' + end
2822
2851
2823 m = scmutil.match(ctx, pats, opts)
2852 m = scmutil.match(ctx, pats, opts)
2824 ui.pager(b'files')
2853 ui.pager(b'files')
2825 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2854 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2826 with ui.formatter(b'files', opts) as fm:
2855 with ui.formatter(b'files', opts) as fm:
2827 return cmdutil.files(
2856 return cmdutil.files(
2828 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2857 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2829 )
2858 )
2830
2859
2831
2860
2832 @command(
2861 @command(
2833 b'forget',
2862 b'forget',
2834 [
2863 [
2835 (b'i', b'interactive', None, _(b'use interactive mode')),
2864 (b'i', b'interactive', None, _(b'use interactive mode')),
2836 ]
2865 ]
2837 + walkopts
2866 + walkopts
2838 + dryrunopts,
2867 + dryrunopts,
2839 _(b'[OPTION]... FILE...'),
2868 _(b'[OPTION]... FILE...'),
2840 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2869 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2841 helpbasic=True,
2870 helpbasic=True,
2842 inferrepo=True,
2871 inferrepo=True,
2843 )
2872 )
2844 def forget(ui, repo, *pats, **opts):
2873 def forget(ui, repo, *pats, **opts):
2845 """forget the specified files on the next commit
2874 """forget the specified files on the next commit
2846
2875
2847 Mark the specified files so they will no longer be tracked
2876 Mark the specified files so they will no longer be tracked
2848 after the next commit.
2877 after the next commit.
2849
2878
2850 This only removes files from the current branch, not from the
2879 This only removes files from the current branch, not from the
2851 entire project history, and it does not delete them from the
2880 entire project history, and it does not delete them from the
2852 working directory.
2881 working directory.
2853
2882
2854 To delete the file from the working directory, see :hg:`remove`.
2883 To delete the file from the working directory, see :hg:`remove`.
2855
2884
2856 To undo a forget before the next commit, see :hg:`add`.
2885 To undo a forget before the next commit, see :hg:`add`.
2857
2886
2858 .. container:: verbose
2887 .. container:: verbose
2859
2888
2860 Examples:
2889 Examples:
2861
2890
2862 - forget newly-added binary files::
2891 - forget newly-added binary files::
2863
2892
2864 hg forget "set:added() and binary()"
2893 hg forget "set:added() and binary()"
2865
2894
2866 - forget files that would be excluded by .hgignore::
2895 - forget files that would be excluded by .hgignore::
2867
2896
2868 hg forget "set:hgignore()"
2897 hg forget "set:hgignore()"
2869
2898
2870 Returns 0 on success.
2899 Returns 0 on success.
2871 """
2900 """
2872
2901
2873 opts = pycompat.byteskwargs(opts)
2902 opts = pycompat.byteskwargs(opts)
2874 if not pats:
2903 if not pats:
2875 raise error.InputError(_(b'no files specified'))
2904 raise error.InputError(_(b'no files specified'))
2876
2905
2877 m = scmutil.match(repo[None], pats, opts)
2906 m = scmutil.match(repo[None], pats, opts)
2878 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2907 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2879 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2908 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2880 rejected = cmdutil.forget(
2909 rejected = cmdutil.forget(
2881 ui,
2910 ui,
2882 repo,
2911 repo,
2883 m,
2912 m,
2884 prefix=b"",
2913 prefix=b"",
2885 uipathfn=uipathfn,
2914 uipathfn=uipathfn,
2886 explicitonly=False,
2915 explicitonly=False,
2887 dryrun=dryrun,
2916 dryrun=dryrun,
2888 interactive=interactive,
2917 interactive=interactive,
2889 )[0]
2918 )[0]
2890 return rejected and 1 or 0
2919 return rejected and 1 or 0
2891
2920
2892
2921
2893 @command(
2922 @command(
2894 b'graft',
2923 b'graft',
2895 [
2924 [
2896 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2925 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2897 (
2926 (
2898 b'',
2927 b'',
2899 b'base',
2928 b'base',
2900 b'',
2929 b'',
2901 _(b'base revision when doing the graft merge (ADVANCED)'),
2930 _(b'base revision when doing the graft merge (ADVANCED)'),
2902 _(b'REV'),
2931 _(b'REV'),
2903 ),
2932 ),
2904 (b'c', b'continue', False, _(b'resume interrupted graft')),
2933 (b'c', b'continue', False, _(b'resume interrupted graft')),
2905 (b'', b'stop', False, _(b'stop interrupted graft')),
2934 (b'', b'stop', False, _(b'stop interrupted graft')),
2906 (b'', b'abort', False, _(b'abort interrupted graft')),
2935 (b'', b'abort', False, _(b'abort interrupted graft')),
2907 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2936 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2908 (b'', b'log', None, _(b'append graft info to log message')),
2937 (b'', b'log', None, _(b'append graft info to log message')),
2909 (
2938 (
2910 b'',
2939 b'',
2911 b'no-commit',
2940 b'no-commit',
2912 None,
2941 None,
2913 _(b"don't commit, just apply the changes in working directory"),
2942 _(b"don't commit, just apply the changes in working directory"),
2914 ),
2943 ),
2915 (b'f', b'force', False, _(b'force graft')),
2944 (b'f', b'force', False, _(b'force graft')),
2916 (
2945 (
2917 b'D',
2946 b'D',
2918 b'currentdate',
2947 b'currentdate',
2919 False,
2948 False,
2920 _(b'record the current date as commit date'),
2949 _(b'record the current date as commit date'),
2921 ),
2950 ),
2922 (
2951 (
2923 b'U',
2952 b'U',
2924 b'currentuser',
2953 b'currentuser',
2925 False,
2954 False,
2926 _(b'record the current user as committer'),
2955 _(b'record the current user as committer'),
2927 ),
2956 ),
2928 ]
2957 ]
2929 + commitopts2
2958 + commitopts2
2930 + mergetoolopts
2959 + mergetoolopts
2931 + dryrunopts,
2960 + dryrunopts,
2932 _(b'[OPTION]... [-r REV]... REV...'),
2961 _(b'[OPTION]... [-r REV]... REV...'),
2933 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2962 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2934 )
2963 )
2935 def graft(ui, repo, *revs, **opts):
2964 def graft(ui, repo, *revs, **opts):
2936 """copy changes from other branches onto the current branch
2965 """copy changes from other branches onto the current branch
2937
2966
2938 This command uses Mercurial's merge logic to copy individual
2967 This command uses Mercurial's merge logic to copy individual
2939 changes from other branches without merging branches in the
2968 changes from other branches without merging branches in the
2940 history graph. This is sometimes known as 'backporting' or
2969 history graph. This is sometimes known as 'backporting' or
2941 'cherry-picking'. By default, graft will copy user, date, and
2970 'cherry-picking'. By default, graft will copy user, date, and
2942 description from the source changesets.
2971 description from the source changesets.
2943
2972
2944 Changesets that are ancestors of the current revision, that have
2973 Changesets that are ancestors of the current revision, that have
2945 already been grafted, or that are merges will be skipped.
2974 already been grafted, or that are merges will be skipped.
2946
2975
2947 If --log is specified, log messages will have a comment appended
2976 If --log is specified, log messages will have a comment appended
2948 of the form::
2977 of the form::
2949
2978
2950 (grafted from CHANGESETHASH)
2979 (grafted from CHANGESETHASH)
2951
2980
2952 If --force is specified, revisions will be grafted even if they
2981 If --force is specified, revisions will be grafted even if they
2953 are already ancestors of, or have been grafted to, the destination.
2982 are already ancestors of, or have been grafted to, the destination.
2954 This is useful when the revisions have since been backed out.
2983 This is useful when the revisions have since been backed out.
2955
2984
2956 If a graft merge results in conflicts, the graft process is
2985 If a graft merge results in conflicts, the graft process is
2957 interrupted so that the current merge can be manually resolved.
2986 interrupted so that the current merge can be manually resolved.
2958 Once all conflicts are addressed, the graft process can be
2987 Once all conflicts are addressed, the graft process can be
2959 continued with the -c/--continue option.
2988 continued with the -c/--continue option.
2960
2989
2961 The -c/--continue option reapplies all the earlier options.
2990 The -c/--continue option reapplies all the earlier options.
2962
2991
2963 .. container:: verbose
2992 .. container:: verbose
2964
2993
2965 The --base option exposes more of how graft internally uses merge with a
2994 The --base option exposes more of how graft internally uses merge with a
2966 custom base revision. --base can be used to specify another ancestor than
2995 custom base revision. --base can be used to specify another ancestor than
2967 the first and only parent.
2996 the first and only parent.
2968
2997
2969 The command::
2998 The command::
2970
2999
2971 hg graft -r 345 --base 234
3000 hg graft -r 345 --base 234
2972
3001
2973 is thus pretty much the same as::
3002 is thus pretty much the same as::
2974
3003
2975 hg diff --from 234 --to 345 | hg import
3004 hg diff --from 234 --to 345 | hg import
2976
3005
2977 but using merge to resolve conflicts and track moved files.
3006 but using merge to resolve conflicts and track moved files.
2978
3007
2979 The result of a merge can thus be backported as a single commit by
3008 The result of a merge can thus be backported as a single commit by
2980 specifying one of the merge parents as base, and thus effectively
3009 specifying one of the merge parents as base, and thus effectively
2981 grafting the changes from the other side.
3010 grafting the changes from the other side.
2982
3011
2983 It is also possible to collapse multiple changesets and clean up history
3012 It is also possible to collapse multiple changesets and clean up history
2984 by specifying another ancestor as base, much like rebase --collapse
3013 by specifying another ancestor as base, much like rebase --collapse
2985 --keep.
3014 --keep.
2986
3015
2987 The commit message can be tweaked after the fact using commit --amend .
3016 The commit message can be tweaked after the fact using commit --amend .
2988
3017
2989 For using non-ancestors as the base to backout changes, see the backout
3018 For using non-ancestors as the base to backout changes, see the backout
2990 command and the hidden --parent option.
3019 command and the hidden --parent option.
2991
3020
2992 .. container:: verbose
3021 .. container:: verbose
2993
3022
2994 Examples:
3023 Examples:
2995
3024
2996 - copy a single change to the stable branch and edit its description::
3025 - copy a single change to the stable branch and edit its description::
2997
3026
2998 hg update stable
3027 hg update stable
2999 hg graft --edit 9393
3028 hg graft --edit 9393
3000
3029
3001 - graft a range of changesets with one exception, updating dates::
3030 - graft a range of changesets with one exception, updating dates::
3002
3031
3003 hg graft -D "2085::2093 and not 2091"
3032 hg graft -D "2085::2093 and not 2091"
3004
3033
3005 - continue a graft after resolving conflicts::
3034 - continue a graft after resolving conflicts::
3006
3035
3007 hg graft -c
3036 hg graft -c
3008
3037
3009 - show the source of a grafted changeset::
3038 - show the source of a grafted changeset::
3010
3039
3011 hg log --debug -r .
3040 hg log --debug -r .
3012
3041
3013 - show revisions sorted by date::
3042 - show revisions sorted by date::
3014
3043
3015 hg log -r "sort(all(), date)"
3044 hg log -r "sort(all(), date)"
3016
3045
3017 - backport the result of a merge as a single commit::
3046 - backport the result of a merge as a single commit::
3018
3047
3019 hg graft -r 123 --base 123^
3048 hg graft -r 123 --base 123^
3020
3049
3021 - land a feature branch as one changeset::
3050 - land a feature branch as one changeset::
3022
3051
3023 hg up -cr default
3052 hg up -cr default
3024 hg graft -r featureX --base "ancestor('featureX', 'default')"
3053 hg graft -r featureX --base "ancestor('featureX', 'default')"
3025
3054
3026 See :hg:`help revisions` for more about specifying revisions.
3055 See :hg:`help revisions` for more about specifying revisions.
3027
3056
3028 Returns 0 on successful completion, 1 if there are unresolved files.
3057 Returns 0 on successful completion, 1 if there are unresolved files.
3029 """
3058 """
3030 with repo.wlock():
3059 with repo.wlock():
3031 return _dograft(ui, repo, *revs, **opts)
3060 return _dograft(ui, repo, *revs, **opts)
3032
3061
3033
3062
3034 def _dograft(ui, repo, *revs, **opts):
3063 def _dograft(ui, repo, *revs, **opts):
3035 opts = pycompat.byteskwargs(opts)
3064 opts = pycompat.byteskwargs(opts)
3036 if revs and opts.get(b'rev'):
3065 if revs and opts.get(b'rev'):
3037 ui.warn(
3066 ui.warn(
3038 _(
3067 _(
3039 b'warning: inconsistent use of --rev might give unexpected '
3068 b'warning: inconsistent use of --rev might give unexpected '
3040 b'revision ordering!\n'
3069 b'revision ordering!\n'
3041 )
3070 )
3042 )
3071 )
3043
3072
3044 revs = list(revs)
3073 revs = list(revs)
3045 revs.extend(opts.get(b'rev'))
3074 revs.extend(opts.get(b'rev'))
3046 # a dict of data to be stored in state file
3075 # a dict of data to be stored in state file
3047 statedata = {}
3076 statedata = {}
3048 # list of new nodes created by ongoing graft
3077 # list of new nodes created by ongoing graft
3049 statedata[b'newnodes'] = []
3078 statedata[b'newnodes'] = []
3050
3079
3051 cmdutil.resolvecommitoptions(ui, opts)
3080 cmdutil.resolvecommitoptions(ui, opts)
3052
3081
3053 editor = cmdutil.getcommiteditor(
3082 editor = cmdutil.getcommiteditor(
3054 editform=b'graft', **pycompat.strkwargs(opts)
3083 editform=b'graft', **pycompat.strkwargs(opts)
3055 )
3084 )
3056
3085
3057 cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
3086 cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
3058
3087
3059 cont = False
3088 cont = False
3060 if opts.get(b'no_commit'):
3089 if opts.get(b'no_commit'):
3061 cmdutil.check_incompatible_arguments(
3090 cmdutil.check_incompatible_arguments(
3062 opts,
3091 opts,
3063 b'no_commit',
3092 b'no_commit',
3064 [b'edit', b'currentuser', b'currentdate', b'log'],
3093 [b'edit', b'currentuser', b'currentdate', b'log'],
3065 )
3094 )
3066
3095
3067 graftstate = statemod.cmdstate(repo, b'graftstate')
3096 graftstate = statemod.cmdstate(repo, b'graftstate')
3068
3097
3069 if opts.get(b'stop'):
3098 if opts.get(b'stop'):
3070 cmdutil.check_incompatible_arguments(
3099 cmdutil.check_incompatible_arguments(
3071 opts,
3100 opts,
3072 b'stop',
3101 b'stop',
3073 [
3102 [
3074 b'edit',
3103 b'edit',
3075 b'log',
3104 b'log',
3076 b'user',
3105 b'user',
3077 b'date',
3106 b'date',
3078 b'currentdate',
3107 b'currentdate',
3079 b'currentuser',
3108 b'currentuser',
3080 b'rev',
3109 b'rev',
3081 ],
3110 ],
3082 )
3111 )
3083 return _stopgraft(ui, repo, graftstate)
3112 return _stopgraft(ui, repo, graftstate)
3084 elif opts.get(b'abort'):
3113 elif opts.get(b'abort'):
3085 cmdutil.check_incompatible_arguments(
3114 cmdutil.check_incompatible_arguments(
3086 opts,
3115 opts,
3087 b'abort',
3116 b'abort',
3088 [
3117 [
3089 b'edit',
3118 b'edit',
3090 b'log',
3119 b'log',
3091 b'user',
3120 b'user',
3092 b'date',
3121 b'date',
3093 b'currentdate',
3122 b'currentdate',
3094 b'currentuser',
3123 b'currentuser',
3095 b'rev',
3124 b'rev',
3096 ],
3125 ],
3097 )
3126 )
3098 return cmdutil.abortgraft(ui, repo, graftstate)
3127 return cmdutil.abortgraft(ui, repo, graftstate)
3099 elif opts.get(b'continue'):
3128 elif opts.get(b'continue'):
3100 cont = True
3129 cont = True
3101 if revs:
3130 if revs:
3102 raise error.InputError(_(b"can't specify --continue and revisions"))
3131 raise error.InputError(_(b"can't specify --continue and revisions"))
3103 # read in unfinished revisions
3132 # read in unfinished revisions
3104 if graftstate.exists():
3133 if graftstate.exists():
3105 statedata = cmdutil.readgraftstate(repo, graftstate)
3134 statedata = cmdutil.readgraftstate(repo, graftstate)
3106 if statedata.get(b'date'):
3135 if statedata.get(b'date'):
3107 opts[b'date'] = statedata[b'date']
3136 opts[b'date'] = statedata[b'date']
3108 if statedata.get(b'user'):
3137 if statedata.get(b'user'):
3109 opts[b'user'] = statedata[b'user']
3138 opts[b'user'] = statedata[b'user']
3110 if statedata.get(b'log'):
3139 if statedata.get(b'log'):
3111 opts[b'log'] = True
3140 opts[b'log'] = True
3112 if statedata.get(b'no_commit'):
3141 if statedata.get(b'no_commit'):
3113 opts[b'no_commit'] = statedata.get(b'no_commit')
3142 opts[b'no_commit'] = statedata.get(b'no_commit')
3114 if statedata.get(b'base'):
3143 if statedata.get(b'base'):
3115 opts[b'base'] = statedata.get(b'base')
3144 opts[b'base'] = statedata.get(b'base')
3116 nodes = statedata[b'nodes']
3145 nodes = statedata[b'nodes']
3117 revs = [repo[node].rev() for node in nodes]
3146 revs = [repo[node].rev() for node in nodes]
3118 else:
3147 else:
3119 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3148 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3120 else:
3149 else:
3121 if not revs:
3150 if not revs:
3122 raise error.InputError(_(b'no revisions specified'))
3151 raise error.InputError(_(b'no revisions specified'))
3123 cmdutil.checkunfinished(repo)
3152 cmdutil.checkunfinished(repo)
3124 cmdutil.bailifchanged(repo)
3153 cmdutil.bailifchanged(repo)
3125 revs = scmutil.revrange(repo, revs)
3154 revs = scmutil.revrange(repo, revs)
3126
3155
3127 skipped = set()
3156 skipped = set()
3128 basectx = None
3157 basectx = None
3129 if opts.get(b'base'):
3158 if opts.get(b'base'):
3130 basectx = scmutil.revsingle(repo, opts[b'base'], None)
3159 basectx = scmutil.revsingle(repo, opts[b'base'], None)
3131 if basectx is None:
3160 if basectx is None:
3132 # check for merges
3161 # check for merges
3133 for rev in repo.revs(b'%ld and merge()', revs):
3162 for rev in repo.revs(b'%ld and merge()', revs):
3134 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3163 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3135 skipped.add(rev)
3164 skipped.add(rev)
3136 revs = [r for r in revs if r not in skipped]
3165 revs = [r for r in revs if r not in skipped]
3137 if not revs:
3166 if not revs:
3138 return -1
3167 return -1
3139 if basectx is not None and len(revs) != 1:
3168 if basectx is not None and len(revs) != 1:
3140 raise error.InputError(_(b'only one revision allowed with --base '))
3169 raise error.InputError(_(b'only one revision allowed with --base '))
3141
3170
3142 # Don't check in the --continue case, in effect retaining --force across
3171 # Don't check in the --continue case, in effect retaining --force across
3143 # --continues. That's because without --force, any revisions we decided to
3172 # --continues. That's because without --force, any revisions we decided to
3144 # skip would have been filtered out here, so they wouldn't have made their
3173 # skip would have been filtered out here, so they wouldn't have made their
3145 # way to the graftstate. With --force, any revisions we would have otherwise
3174 # way to the graftstate. With --force, any revisions we would have otherwise
3146 # skipped would not have been filtered out, and if they hadn't been applied
3175 # skipped would not have been filtered out, and if they hadn't been applied
3147 # already, they'd have been in the graftstate.
3176 # already, they'd have been in the graftstate.
3148 if not (cont or opts.get(b'force')) and basectx is None:
3177 if not (cont or opts.get(b'force')) and basectx is None:
3149 # check for ancestors of dest branch
3178 # check for ancestors of dest branch
3150 ancestors = repo.revs(b'%ld & (::.)', revs)
3179 ancestors = repo.revs(b'%ld & (::.)', revs)
3151 for rev in ancestors:
3180 for rev in ancestors:
3152 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3181 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3153
3182
3154 revs = [r for r in revs if r not in ancestors]
3183 revs = [r for r in revs if r not in ancestors]
3155
3184
3156 if not revs:
3185 if not revs:
3157 return -1
3186 return -1
3158
3187
3159 # analyze revs for earlier grafts
3188 # analyze revs for earlier grafts
3160 ids = {}
3189 ids = {}
3161 for ctx in repo.set(b"%ld", revs):
3190 for ctx in repo.set(b"%ld", revs):
3162 ids[ctx.hex()] = ctx.rev()
3191 ids[ctx.hex()] = ctx.rev()
3163 n = ctx.extra().get(b'source')
3192 n = ctx.extra().get(b'source')
3164 if n:
3193 if n:
3165 ids[n] = ctx.rev()
3194 ids[n] = ctx.rev()
3166
3195
3167 # check ancestors for earlier grafts
3196 # check ancestors for earlier grafts
3168 ui.debug(b'scanning for duplicate grafts\n')
3197 ui.debug(b'scanning for duplicate grafts\n')
3169
3198
3170 # The only changesets we can be sure doesn't contain grafts of any
3199 # The only changesets we can be sure doesn't contain grafts of any
3171 # revs, are the ones that are common ancestors of *all* revs:
3200 # revs, are the ones that are common ancestors of *all* revs:
3172 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3201 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3173 ctx = repo[rev]
3202 ctx = repo[rev]
3174 n = ctx.extra().get(b'source')
3203 n = ctx.extra().get(b'source')
3175 if n in ids:
3204 if n in ids:
3176 try:
3205 try:
3177 r = repo[n].rev()
3206 r = repo[n].rev()
3178 except error.RepoLookupError:
3207 except error.RepoLookupError:
3179 r = None
3208 r = None
3180 if r in revs:
3209 if r in revs:
3181 ui.warn(
3210 ui.warn(
3182 _(
3211 _(
3183 b'skipping revision %d:%s '
3212 b'skipping revision %d:%s '
3184 b'(already grafted to %d:%s)\n'
3213 b'(already grafted to %d:%s)\n'
3185 )
3214 )
3186 % (r, repo[r], rev, ctx)
3215 % (r, repo[r], rev, ctx)
3187 )
3216 )
3188 revs.remove(r)
3217 revs.remove(r)
3189 elif ids[n] in revs:
3218 elif ids[n] in revs:
3190 if r is None:
3219 if r is None:
3191 ui.warn(
3220 ui.warn(
3192 _(
3221 _(
3193 b'skipping already grafted revision %d:%s '
3222 b'skipping already grafted revision %d:%s '
3194 b'(%d:%s also has unknown origin %s)\n'
3223 b'(%d:%s also has unknown origin %s)\n'
3195 )
3224 )
3196 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3225 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3197 )
3226 )
3198 else:
3227 else:
3199 ui.warn(
3228 ui.warn(
3200 _(
3229 _(
3201 b'skipping already grafted revision %d:%s '
3230 b'skipping already grafted revision %d:%s '
3202 b'(%d:%s also has origin %d:%s)\n'
3231 b'(%d:%s also has origin %d:%s)\n'
3203 )
3232 )
3204 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3233 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3205 )
3234 )
3206 revs.remove(ids[n])
3235 revs.remove(ids[n])
3207 elif ctx.hex() in ids:
3236 elif ctx.hex() in ids:
3208 r = ids[ctx.hex()]
3237 r = ids[ctx.hex()]
3209 if r in revs:
3238 if r in revs:
3210 ui.warn(
3239 ui.warn(
3211 _(
3240 _(
3212 b'skipping already grafted revision %d:%s '
3241 b'skipping already grafted revision %d:%s '
3213 b'(was grafted from %d:%s)\n'
3242 b'(was grafted from %d:%s)\n'
3214 )
3243 )
3215 % (r, repo[r], rev, ctx)
3244 % (r, repo[r], rev, ctx)
3216 )
3245 )
3217 revs.remove(r)
3246 revs.remove(r)
3218 if not revs:
3247 if not revs:
3219 return -1
3248 return -1
3220
3249
3221 if opts.get(b'no_commit'):
3250 if opts.get(b'no_commit'):
3222 statedata[b'no_commit'] = True
3251 statedata[b'no_commit'] = True
3223 if opts.get(b'base'):
3252 if opts.get(b'base'):
3224 statedata[b'base'] = opts[b'base']
3253 statedata[b'base'] = opts[b'base']
3225 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3254 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3226 desc = b'%d:%s "%s"' % (
3255 desc = b'%d:%s "%s"' % (
3227 ctx.rev(),
3256 ctx.rev(),
3228 ctx,
3257 ctx,
3229 ctx.description().split(b'\n', 1)[0],
3258 ctx.description().split(b'\n', 1)[0],
3230 )
3259 )
3231 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3260 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3232 if names:
3261 if names:
3233 desc += b' (%s)' % b' '.join(names)
3262 desc += b' (%s)' % b' '.join(names)
3234 ui.status(_(b'grafting %s\n') % desc)
3263 ui.status(_(b'grafting %s\n') % desc)
3235 if opts.get(b'dry_run'):
3264 if opts.get(b'dry_run'):
3236 continue
3265 continue
3237
3266
3238 source = ctx.extra().get(b'source')
3267 source = ctx.extra().get(b'source')
3239 extra = {}
3268 extra = {}
3240 if source:
3269 if source:
3241 extra[b'source'] = source
3270 extra[b'source'] = source
3242 extra[b'intermediate-source'] = ctx.hex()
3271 extra[b'intermediate-source'] = ctx.hex()
3243 else:
3272 else:
3244 extra[b'source'] = ctx.hex()
3273 extra[b'source'] = ctx.hex()
3245 user = ctx.user()
3274 user = ctx.user()
3246 if opts.get(b'user'):
3275 if opts.get(b'user'):
3247 user = opts[b'user']
3276 user = opts[b'user']
3248 statedata[b'user'] = user
3277 statedata[b'user'] = user
3249 date = ctx.date()
3278 date = ctx.date()
3250 if opts.get(b'date'):
3279 if opts.get(b'date'):
3251 date = opts[b'date']
3280 date = opts[b'date']
3252 statedata[b'date'] = date
3281 statedata[b'date'] = date
3253 message = ctx.description()
3282 message = ctx.description()
3254 if opts.get(b'log'):
3283 if opts.get(b'log'):
3255 message += b'\n(grafted from %s)' % ctx.hex()
3284 message += b'\n(grafted from %s)' % ctx.hex()
3256 statedata[b'log'] = True
3285 statedata[b'log'] = True
3257
3286
3258 # we don't merge the first commit when continuing
3287 # we don't merge the first commit when continuing
3259 if not cont:
3288 if not cont:
3260 # perform the graft merge with p1(rev) as 'ancestor'
3289 # perform the graft merge with p1(rev) as 'ancestor'
3261 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3290 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3262 base = ctx.p1() if basectx is None else basectx
3291 base = ctx.p1() if basectx is None else basectx
3263 with ui.configoverride(overrides, b'graft'):
3292 with ui.configoverride(overrides, b'graft'):
3264 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3293 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3265 # report any conflicts
3294 # report any conflicts
3266 if stats.unresolvedcount > 0:
3295 if stats.unresolvedcount > 0:
3267 # write out state for --continue
3296 # write out state for --continue
3268 nodes = [repo[rev].hex() for rev in revs[pos:]]
3297 nodes = [repo[rev].hex() for rev in revs[pos:]]
3269 statedata[b'nodes'] = nodes
3298 statedata[b'nodes'] = nodes
3270 stateversion = 1
3299 stateversion = 1
3271 graftstate.save(stateversion, statedata)
3300 graftstate.save(stateversion, statedata)
3272 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3301 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3273 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3302 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3274 return 1
3303 return 1
3275 else:
3304 else:
3276 cont = False
3305 cont = False
3277
3306
3278 # commit if --no-commit is false
3307 # commit if --no-commit is false
3279 if not opts.get(b'no_commit'):
3308 if not opts.get(b'no_commit'):
3280 node = repo.commit(
3309 node = repo.commit(
3281 text=message, user=user, date=date, extra=extra, editor=editor
3310 text=message, user=user, date=date, extra=extra, editor=editor
3282 )
3311 )
3283 if node is None:
3312 if node is None:
3284 ui.warn(
3313 ui.warn(
3285 _(b'note: graft of %d:%s created no changes to commit\n')
3314 _(b'note: graft of %d:%s created no changes to commit\n')
3286 % (ctx.rev(), ctx)
3315 % (ctx.rev(), ctx)
3287 )
3316 )
3288 # checking that newnodes exist because old state files won't have it
3317 # checking that newnodes exist because old state files won't have it
3289 elif statedata.get(b'newnodes') is not None:
3318 elif statedata.get(b'newnodes') is not None:
3290 statedata[b'newnodes'].append(node)
3319 statedata[b'newnodes'].append(node)
3291
3320
3292 # remove state when we complete successfully
3321 # remove state when we complete successfully
3293 if not opts.get(b'dry_run'):
3322 if not opts.get(b'dry_run'):
3294 graftstate.delete()
3323 graftstate.delete()
3295
3324
3296 return 0
3325 return 0
3297
3326
3298
3327
3299 def _stopgraft(ui, repo, graftstate):
3328 def _stopgraft(ui, repo, graftstate):
3300 """stop the interrupted graft"""
3329 """stop the interrupted graft"""
3301 if not graftstate.exists():
3330 if not graftstate.exists():
3302 raise error.StateError(_(b"no interrupted graft found"))
3331 raise error.StateError(_(b"no interrupted graft found"))
3303 pctx = repo[b'.']
3332 pctx = repo[b'.']
3304 mergemod.clean_update(pctx)
3333 mergemod.clean_update(pctx)
3305 graftstate.delete()
3334 graftstate.delete()
3306 ui.status(_(b"stopped the interrupted graft\n"))
3335 ui.status(_(b"stopped the interrupted graft\n"))
3307 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3336 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3308 return 0
3337 return 0
3309
3338
3310
3339
3311 statemod.addunfinished(
3340 statemod.addunfinished(
3312 b'graft',
3341 b'graft',
3313 fname=b'graftstate',
3342 fname=b'graftstate',
3314 clearable=True,
3343 clearable=True,
3315 stopflag=True,
3344 stopflag=True,
3316 continueflag=True,
3345 continueflag=True,
3317 abortfunc=cmdutil.hgabortgraft,
3346 abortfunc=cmdutil.hgabortgraft,
3318 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3347 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3319 )
3348 )
3320
3349
3321
3350
3322 @command(
3351 @command(
3323 b'grep',
3352 b'grep',
3324 [
3353 [
3325 (b'0', b'print0', None, _(b'end fields with NUL')),
3354 (b'0', b'print0', None, _(b'end fields with NUL')),
3326 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3355 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3327 (
3356 (
3328 b'',
3357 b'',
3329 b'diff',
3358 b'diff',
3330 None,
3359 None,
3331 _(
3360 _(
3332 b'search revision differences for when the pattern was added '
3361 b'search revision differences for when the pattern was added '
3333 b'or removed'
3362 b'or removed'
3334 ),
3363 ),
3335 ),
3364 ),
3336 (b'a', b'text', None, _(b'treat all files as text')),
3365 (b'a', b'text', None, _(b'treat all files as text')),
3337 (
3366 (
3338 b'f',
3367 b'f',
3339 b'follow',
3368 b'follow',
3340 None,
3369 None,
3341 _(
3370 _(
3342 b'follow changeset history,'
3371 b'follow changeset history,'
3343 b' or file history across copies and renames'
3372 b' or file history across copies and renames'
3344 ),
3373 ),
3345 ),
3374 ),
3346 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3375 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3347 (
3376 (
3348 b'l',
3377 b'l',
3349 b'files-with-matches',
3378 b'files-with-matches',
3350 None,
3379 None,
3351 _(b'print only filenames and revisions that match'),
3380 _(b'print only filenames and revisions that match'),
3352 ),
3381 ),
3353 (b'n', b'line-number', None, _(b'print matching line numbers')),
3382 (b'n', b'line-number', None, _(b'print matching line numbers')),
3354 (
3383 (
3355 b'r',
3384 b'r',
3356 b'rev',
3385 b'rev',
3357 [],
3386 [],
3358 _(b'search files changed within revision range'),
3387 _(b'search files changed within revision range'),
3359 _(b'REV'),
3388 _(b'REV'),
3360 ),
3389 ),
3361 (
3390 (
3362 b'',
3391 b'',
3363 b'all-files',
3392 b'all-files',
3364 None,
3393 None,
3365 _(
3394 _(
3366 b'include all files in the changeset while grepping (DEPRECATED)'
3395 b'include all files in the changeset while grepping (DEPRECATED)'
3367 ),
3396 ),
3368 ),
3397 ),
3369 (b'u', b'user', None, _(b'list the author (long with -v)')),
3398 (b'u', b'user', None, _(b'list the author (long with -v)')),
3370 (b'd', b'date', None, _(b'list the date (short with -q)')),
3399 (b'd', b'date', None, _(b'list the date (short with -q)')),
3371 ]
3400 ]
3372 + formatteropts
3401 + formatteropts
3373 + walkopts,
3402 + walkopts,
3374 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3403 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3375 helpcategory=command.CATEGORY_FILE_CONTENTS,
3404 helpcategory=command.CATEGORY_FILE_CONTENTS,
3376 inferrepo=True,
3405 inferrepo=True,
3377 intents={INTENT_READONLY},
3406 intents={INTENT_READONLY},
3378 )
3407 )
3379 def grep(ui, repo, pattern, *pats, **opts):
3408 def grep(ui, repo, pattern, *pats, **opts):
3380 """search for a pattern in specified files
3409 """search for a pattern in specified files
3381
3410
3382 Search the working directory or revision history for a regular
3411 Search the working directory or revision history for a regular
3383 expression in the specified files for the entire repository.
3412 expression in the specified files for the entire repository.
3384
3413
3385 By default, grep searches the repository files in the working
3414 By default, grep searches the repository files in the working
3386 directory and prints the files where it finds a match. To specify
3415 directory and prints the files where it finds a match. To specify
3387 historical revisions instead of the working directory, use the
3416 historical revisions instead of the working directory, use the
3388 --rev flag.
3417 --rev flag.
3389
3418
3390 To search instead historical revision differences that contains a
3419 To search instead historical revision differences that contains a
3391 change in match status ("-" for a match that becomes a non-match,
3420 change in match status ("-" for a match that becomes a non-match,
3392 or "+" for a non-match that becomes a match), use the --diff flag.
3421 or "+" for a non-match that becomes a match), use the --diff flag.
3393
3422
3394 PATTERN can be any Python (roughly Perl-compatible) regular
3423 PATTERN can be any Python (roughly Perl-compatible) regular
3395 expression.
3424 expression.
3396
3425
3397 If no FILEs are specified and the --rev flag isn't supplied, all
3426 If no FILEs are specified and the --rev flag isn't supplied, all
3398 files in the working directory are searched. When using the --rev
3427 files in the working directory are searched. When using the --rev
3399 flag and specifying FILEs, use the --follow argument to also
3428 flag and specifying FILEs, use the --follow argument to also
3400 follow the specified FILEs across renames and copies.
3429 follow the specified FILEs across renames and copies.
3401
3430
3402 .. container:: verbose
3431 .. container:: verbose
3403
3432
3404 Template:
3433 Template:
3405
3434
3406 The following keywords are supported in addition to the common template
3435 The following keywords are supported in addition to the common template
3407 keywords and functions. See also :hg:`help templates`.
3436 keywords and functions. See also :hg:`help templates`.
3408
3437
3409 :change: String. Character denoting insertion ``+`` or removal ``-``.
3438 :change: String. Character denoting insertion ``+`` or removal ``-``.
3410 Available if ``--diff`` is specified.
3439 Available if ``--diff`` is specified.
3411 :lineno: Integer. Line number of the match.
3440 :lineno: Integer. Line number of the match.
3412 :path: String. Repository-absolute path of the file.
3441 :path: String. Repository-absolute path of the file.
3413 :texts: List of text chunks.
3442 :texts: List of text chunks.
3414
3443
3415 And each entry of ``{texts}`` provides the following sub-keywords.
3444 And each entry of ``{texts}`` provides the following sub-keywords.
3416
3445
3417 :matched: Boolean. True if the chunk matches the specified pattern.
3446 :matched: Boolean. True if the chunk matches the specified pattern.
3418 :text: String. Chunk content.
3447 :text: String. Chunk content.
3419
3448
3420 See :hg:`help templates.operators` for the list expansion syntax.
3449 See :hg:`help templates.operators` for the list expansion syntax.
3421
3450
3422 Returns 0 if a match is found, 1 otherwise.
3451 Returns 0 if a match is found, 1 otherwise.
3423
3452
3424 """
3453 """
3425 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3454 cmdutil.check_incompatible_arguments(opts, 'all_files', ['all', 'diff'])
3426 opts = pycompat.byteskwargs(opts)
3455 opts = pycompat.byteskwargs(opts)
3427 diff = opts.get(b'all') or opts.get(b'diff')
3456 diff = opts.get(b'all') or opts.get(b'diff')
3428 follow = opts.get(b'follow')
3457 follow = opts.get(b'follow')
3429 if opts.get(b'all_files') is None and not diff:
3458 if opts.get(b'all_files') is None and not diff:
3430 opts[b'all_files'] = True
3459 opts[b'all_files'] = True
3431 plaingrep = (
3460 plaingrep = (
3432 opts.get(b'all_files')
3461 opts.get(b'all_files')
3433 and not opts.get(b'rev')
3462 and not opts.get(b'rev')
3434 and not opts.get(b'follow')
3463 and not opts.get(b'follow')
3435 )
3464 )
3436 all_files = opts.get(b'all_files')
3465 all_files = opts.get(b'all_files')
3437 if plaingrep:
3466 if plaingrep:
3438 opts[b'rev'] = [b'wdir()']
3467 opts[b'rev'] = [b'wdir()']
3439
3468
3440 reflags = re.M
3469 reflags = re.M
3441 if opts.get(b'ignore_case'):
3470 if opts.get(b'ignore_case'):
3442 reflags |= re.I
3471 reflags |= re.I
3443 try:
3472 try:
3444 regexp = util.re.compile(pattern, reflags)
3473 regexp = util.re.compile(pattern, reflags)
3445 except re.error as inst:
3474 except re.error as inst:
3446 ui.warn(
3475 ui.warn(
3447 _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
3476 _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
3448 )
3477 )
3449 return 1
3478 return 1
3450 sep, eol = b':', b'\n'
3479 sep, eol = b':', b'\n'
3451 if opts.get(b'print0'):
3480 if opts.get(b'print0'):
3452 sep = eol = b'\0'
3481 sep = eol = b'\0'
3453
3482
3454 searcher = grepmod.grepsearcher(
3483 searcher = grepmod.grepsearcher(
3455 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3484 ui, repo, regexp, all_files=all_files, diff=diff, follow=follow
3456 )
3485 )
3457
3486
3458 getfile = searcher._getfile
3487 getfile = searcher._getfile
3459
3488
3460 uipathfn = scmutil.getuipathfn(repo)
3489 uipathfn = scmutil.getuipathfn(repo)
3461
3490
3462 def display(fm, fn, ctx, pstates, states):
3491 def display(fm, fn, ctx, pstates, states):
3463 rev = scmutil.intrev(ctx)
3492 rev = scmutil.intrev(ctx)
3464 if fm.isplain():
3493 if fm.isplain():
3465 formatuser = ui.shortuser
3494 formatuser = ui.shortuser
3466 else:
3495 else:
3467 formatuser = pycompat.bytestr
3496 formatuser = pycompat.bytestr
3468 if ui.quiet:
3497 if ui.quiet:
3469 datefmt = b'%Y-%m-%d'
3498 datefmt = b'%Y-%m-%d'
3470 else:
3499 else:
3471 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3500 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3472 found = False
3501 found = False
3473
3502
3474 @util.cachefunc
3503 @util.cachefunc
3475 def binary():
3504 def binary():
3476 flog = getfile(fn)
3505 flog = getfile(fn)
3477 try:
3506 try:
3478 return stringutil.binary(flog.read(ctx.filenode(fn)))
3507 return stringutil.binary(flog.read(ctx.filenode(fn)))
3479 except error.WdirUnsupported:
3508 except error.WdirUnsupported:
3480 return ctx[fn].isbinary()
3509 return ctx[fn].isbinary()
3481
3510
3482 fieldnamemap = {b'linenumber': b'lineno'}
3511 fieldnamemap = {b'linenumber': b'lineno'}
3483 if diff:
3512 if diff:
3484 iter = grepmod.difflinestates(pstates, states)
3513 iter = grepmod.difflinestates(pstates, states)
3485 else:
3514 else:
3486 iter = [(b'', l) for l in states]
3515 iter = [(b'', l) for l in states]
3487 for change, l in iter:
3516 for change, l in iter:
3488 fm.startitem()
3517 fm.startitem()
3489 fm.context(ctx=ctx)
3518 fm.context(ctx=ctx)
3490 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3519 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3491 fm.plain(uipathfn(fn), label=b'grep.filename')
3520 fm.plain(uipathfn(fn), label=b'grep.filename')
3492
3521
3493 cols = [
3522 cols = [
3494 (b'rev', b'%d', rev, not plaingrep, b''),
3523 (b'rev', b'%d', rev, not plaingrep, b''),
3495 (
3524 (
3496 b'linenumber',
3525 b'linenumber',
3497 b'%d',
3526 b'%d',
3498 l.linenum,
3527 l.linenum,
3499 opts.get(b'line_number'),
3528 opts.get(b'line_number'),
3500 b'',
3529 b'',
3501 ),
3530 ),
3502 ]
3531 ]
3503 if diff:
3532 if diff:
3504 cols.append(
3533 cols.append(
3505 (
3534 (
3506 b'change',
3535 b'change',
3507 b'%s',
3536 b'%s',
3508 change,
3537 change,
3509 True,
3538 True,
3510 b'grep.inserted '
3539 b'grep.inserted '
3511 if change == b'+'
3540 if change == b'+'
3512 else b'grep.deleted ',
3541 else b'grep.deleted ',
3513 )
3542 )
3514 )
3543 )
3515 cols.extend(
3544 cols.extend(
3516 [
3545 [
3517 (
3546 (
3518 b'user',
3547 b'user',
3519 b'%s',
3548 b'%s',
3520 formatuser(ctx.user()),
3549 formatuser(ctx.user()),
3521 opts.get(b'user'),
3550 opts.get(b'user'),
3522 b'',
3551 b'',
3523 ),
3552 ),
3524 (
3553 (
3525 b'date',
3554 b'date',
3526 b'%s',
3555 b'%s',
3527 fm.formatdate(ctx.date(), datefmt),
3556 fm.formatdate(ctx.date(), datefmt),
3528 opts.get(b'date'),
3557 opts.get(b'date'),
3529 b'',
3558 b'',
3530 ),
3559 ),
3531 ]
3560 ]
3532 )
3561 )
3533 for name, fmt, data, cond, extra_label in cols:
3562 for name, fmt, data, cond, extra_label in cols:
3534 if cond:
3563 if cond:
3535 fm.plain(sep, label=b'grep.sep')
3564 fm.plain(sep, label=b'grep.sep')
3536 field = fieldnamemap.get(name, name)
3565 field = fieldnamemap.get(name, name)
3537 label = extra_label + (b'grep.%s' % name)
3566 label = extra_label + (b'grep.%s' % name)
3538 fm.condwrite(cond, field, fmt, data, label=label)
3567 fm.condwrite(cond, field, fmt, data, label=label)
3539 if not opts.get(b'files_with_matches'):
3568 if not opts.get(b'files_with_matches'):
3540 fm.plain(sep, label=b'grep.sep')
3569 fm.plain(sep, label=b'grep.sep')
3541 if not opts.get(b'text') and binary():
3570 if not opts.get(b'text') and binary():
3542 fm.plain(_(b" Binary file matches"))
3571 fm.plain(_(b" Binary file matches"))
3543 else:
3572 else:
3544 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3573 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3545 fm.plain(eol)
3574 fm.plain(eol)
3546 found = True
3575 found = True
3547 if opts.get(b'files_with_matches'):
3576 if opts.get(b'files_with_matches'):
3548 break
3577 break
3549 return found
3578 return found
3550
3579
3551 def displaymatches(fm, l):
3580 def displaymatches(fm, l):
3552 p = 0
3581 p = 0
3553 for s, e in l.findpos(regexp):
3582 for s, e in l.findpos(regexp):
3554 if p < s:
3583 if p < s:
3555 fm.startitem()
3584 fm.startitem()
3556 fm.write(b'text', b'%s', l.line[p:s])
3585 fm.write(b'text', b'%s', l.line[p:s])
3557 fm.data(matched=False)
3586 fm.data(matched=False)
3558 fm.startitem()
3587 fm.startitem()
3559 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3588 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3560 fm.data(matched=True)
3589 fm.data(matched=True)
3561 p = e
3590 p = e
3562 if p < len(l.line):
3591 if p < len(l.line):
3563 fm.startitem()
3592 fm.startitem()
3564 fm.write(b'text', b'%s', l.line[p:])
3593 fm.write(b'text', b'%s', l.line[p:])
3565 fm.data(matched=False)
3594 fm.data(matched=False)
3566 fm.end()
3595 fm.end()
3567
3596
3568 found = False
3597 found = False
3569
3598
3570 wopts = logcmdutil.walkopts(
3599 wopts = logcmdutil.walkopts(
3571 pats=pats,
3600 pats=pats,
3572 opts=opts,
3601 opts=opts,
3573 revspec=opts[b'rev'],
3602 revspec=opts[b'rev'],
3574 include_pats=opts[b'include'],
3603 include_pats=opts[b'include'],
3575 exclude_pats=opts[b'exclude'],
3604 exclude_pats=opts[b'exclude'],
3576 follow=follow,
3605 follow=follow,
3577 force_changelog_traversal=all_files,
3606 force_changelog_traversal=all_files,
3578 filter_revisions_by_pats=not all_files,
3607 filter_revisions_by_pats=not all_files,
3579 )
3608 )
3580 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3609 revs, makefilematcher = logcmdutil.makewalker(repo, wopts)
3581
3610
3582 ui.pager(b'grep')
3611 ui.pager(b'grep')
3583 fm = ui.formatter(b'grep', opts)
3612 fm = ui.formatter(b'grep', opts)
3584 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3613 for fn, ctx, pstates, states in searcher.searchfiles(revs, makefilematcher):
3585 r = display(fm, fn, ctx, pstates, states)
3614 r = display(fm, fn, ctx, pstates, states)
3586 found = found or r
3615 found = found or r
3587 if r and not diff and not all_files:
3616 if r and not diff and not all_files:
3588 searcher.skipfile(fn, ctx.rev())
3617 searcher.skipfile(fn, ctx.rev())
3589 fm.end()
3618 fm.end()
3590
3619
3591 return not found
3620 return not found
3592
3621
3593
3622
3594 @command(
3623 @command(
3595 b'heads',
3624 b'heads',
3596 [
3625 [
3597 (
3626 (
3598 b'r',
3627 b'r',
3599 b'rev',
3628 b'rev',
3600 b'',
3629 b'',
3601 _(b'show only heads which are descendants of STARTREV'),
3630 _(b'show only heads which are descendants of STARTREV'),
3602 _(b'STARTREV'),
3631 _(b'STARTREV'),
3603 ),
3632 ),
3604 (b't', b'topo', False, _(b'show topological heads only')),
3633 (b't', b'topo', False, _(b'show topological heads only')),
3605 (
3634 (
3606 b'a',
3635 b'a',
3607 b'active',
3636 b'active',
3608 False,
3637 False,
3609 _(b'show active branchheads only (DEPRECATED)'),
3638 _(b'show active branchheads only (DEPRECATED)'),
3610 ),
3639 ),
3611 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3640 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3612 ]
3641 ]
3613 + templateopts,
3642 + templateopts,
3614 _(b'[-ct] [-r STARTREV] [REV]...'),
3643 _(b'[-ct] [-r STARTREV] [REV]...'),
3615 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3644 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3616 intents={INTENT_READONLY},
3645 intents={INTENT_READONLY},
3617 )
3646 )
3618 def heads(ui, repo, *branchrevs, **opts):
3647 def heads(ui, repo, *branchrevs, **opts):
3619 """show branch heads
3648 """show branch heads
3620
3649
3621 With no arguments, show all open branch heads in the repository.
3650 With no arguments, show all open branch heads in the repository.
3622 Branch heads are changesets that have no descendants on the
3651 Branch heads are changesets that have no descendants on the
3623 same branch. They are where development generally takes place and
3652 same branch. They are where development generally takes place and
3624 are the usual targets for update and merge operations.
3653 are the usual targets for update and merge operations.
3625
3654
3626 If one or more REVs are given, only open branch heads on the
3655 If one or more REVs are given, only open branch heads on the
3627 branches associated with the specified changesets are shown. This
3656 branches associated with the specified changesets are shown. This
3628 means that you can use :hg:`heads .` to see the heads on the
3657 means that you can use :hg:`heads .` to see the heads on the
3629 currently checked-out branch.
3658 currently checked-out branch.
3630
3659
3631 If -c/--closed is specified, also show branch heads marked closed
3660 If -c/--closed is specified, also show branch heads marked closed
3632 (see :hg:`commit --close-branch`).
3661 (see :hg:`commit --close-branch`).
3633
3662
3634 If STARTREV is specified, only those heads that are descendants of
3663 If STARTREV is specified, only those heads that are descendants of
3635 STARTREV will be displayed.
3664 STARTREV will be displayed.
3636
3665
3637 If -t/--topo is specified, named branch mechanics will be ignored and only
3666 If -t/--topo is specified, named branch mechanics will be ignored and only
3638 topological heads (changesets with no children) will be shown.
3667 topological heads (changesets with no children) will be shown.
3639
3668
3640 Returns 0 if matching heads are found, 1 if not.
3669 Returns 0 if matching heads are found, 1 if not.
3641 """
3670 """
3642
3671
3643 opts = pycompat.byteskwargs(opts)
3672 opts = pycompat.byteskwargs(opts)
3644 start = None
3673 start = None
3645 rev = opts.get(b'rev')
3674 rev = opts.get(b'rev')
3646 if rev:
3675 if rev:
3647 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3676 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3648 start = scmutil.revsingle(repo, rev, None).node()
3677 start = scmutil.revsingle(repo, rev, None).node()
3649
3678
3650 if opts.get(b'topo'):
3679 if opts.get(b'topo'):
3651 heads = [repo[h] for h in repo.heads(start)]
3680 heads = [repo[h] for h in repo.heads(start)]
3652 else:
3681 else:
3653 heads = []
3682 heads = []
3654 for branch in repo.branchmap():
3683 for branch in repo.branchmap():
3655 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3684 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3656 heads = [repo[h] for h in heads]
3685 heads = [repo[h] for h in heads]
3657
3686
3658 if branchrevs:
3687 if branchrevs:
3659 branches = {
3688 branches = {
3660 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3689 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3661 }
3690 }
3662 heads = [h for h in heads if h.branch() in branches]
3691 heads = [h for h in heads if h.branch() in branches]
3663
3692
3664 if opts.get(b'active') and branchrevs:
3693 if opts.get(b'active') and branchrevs:
3665 dagheads = repo.heads(start)
3694 dagheads = repo.heads(start)
3666 heads = [h for h in heads if h.node() in dagheads]
3695 heads = [h for h in heads if h.node() in dagheads]
3667
3696
3668 if branchrevs:
3697 if branchrevs:
3669 haveheads = {h.branch() for h in heads}
3698 haveheads = {h.branch() for h in heads}
3670 if branches - haveheads:
3699 if branches - haveheads:
3671 headless = b', '.join(b for b in branches - haveheads)
3700 headless = b', '.join(b for b in branches - haveheads)
3672 msg = _(b'no open branch heads found on branches %s')
3701 msg = _(b'no open branch heads found on branches %s')
3673 if opts.get(b'rev'):
3702 if opts.get(b'rev'):
3674 msg += _(b' (started at %s)') % opts[b'rev']
3703 msg += _(b' (started at %s)') % opts[b'rev']
3675 ui.warn((msg + b'\n') % headless)
3704 ui.warn((msg + b'\n') % headless)
3676
3705
3677 if not heads:
3706 if not heads:
3678 return 1
3707 return 1
3679
3708
3680 ui.pager(b'heads')
3709 ui.pager(b'heads')
3681 heads = sorted(heads, key=lambda x: -(x.rev()))
3710 heads = sorted(heads, key=lambda x: -(x.rev()))
3682 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3711 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3683 for ctx in heads:
3712 for ctx in heads:
3684 displayer.show(ctx)
3713 displayer.show(ctx)
3685 displayer.close()
3714 displayer.close()
3686
3715
3687
3716
3688 @command(
3717 @command(
3689 b'help',
3718 b'help',
3690 [
3719 [
3691 (b'e', b'extension', None, _(b'show only help for extensions')),
3720 (b'e', b'extension', None, _(b'show only help for extensions')),
3692 (b'c', b'command', None, _(b'show only help for commands')),
3721 (b'c', b'command', None, _(b'show only help for commands')),
3693 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3722 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3694 (
3723 (
3695 b's',
3724 b's',
3696 b'system',
3725 b'system',
3697 [],
3726 [],
3698 _(b'show help for specific platform(s)'),
3727 _(b'show help for specific platform(s)'),
3699 _(b'PLATFORM'),
3728 _(b'PLATFORM'),
3700 ),
3729 ),
3701 ],
3730 ],
3702 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3731 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3703 helpcategory=command.CATEGORY_HELP,
3732 helpcategory=command.CATEGORY_HELP,
3704 norepo=True,
3733 norepo=True,
3705 intents={INTENT_READONLY},
3734 intents={INTENT_READONLY},
3706 )
3735 )
3707 def help_(ui, name=None, **opts):
3736 def help_(ui, name=None, **opts):
3708 """show help for a given topic or a help overview
3737 """show help for a given topic or a help overview
3709
3738
3710 With no arguments, print a list of commands with short help messages.
3739 With no arguments, print a list of commands with short help messages.
3711
3740
3712 Given a topic, extension, or command name, print help for that
3741 Given a topic, extension, or command name, print help for that
3713 topic.
3742 topic.
3714
3743
3715 Returns 0 if successful.
3744 Returns 0 if successful.
3716 """
3745 """
3717
3746
3718 keep = opts.get('system') or []
3747 keep = opts.get('system') or []
3719 if len(keep) == 0:
3748 if len(keep) == 0:
3720 if pycompat.sysplatform.startswith(b'win'):
3749 if pycompat.sysplatform.startswith(b'win'):
3721 keep.append(b'windows')
3750 keep.append(b'windows')
3722 elif pycompat.sysplatform == b'OpenVMS':
3751 elif pycompat.sysplatform == b'OpenVMS':
3723 keep.append(b'vms')
3752 keep.append(b'vms')
3724 elif pycompat.sysplatform == b'plan9':
3753 elif pycompat.sysplatform == b'plan9':
3725 keep.append(b'plan9')
3754 keep.append(b'plan9')
3726 else:
3755 else:
3727 keep.append(b'unix')
3756 keep.append(b'unix')
3728 keep.append(pycompat.sysplatform.lower())
3757 keep.append(pycompat.sysplatform.lower())
3729 if ui.verbose:
3758 if ui.verbose:
3730 keep.append(b'verbose')
3759 keep.append(b'verbose')
3731
3760
3732 commands = sys.modules[__name__]
3761 commands = sys.modules[__name__]
3733 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3762 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3734 ui.pager(b'help')
3763 ui.pager(b'help')
3735 ui.write(formatted)
3764 ui.write(formatted)
3736
3765
3737
3766
3738 @command(
3767 @command(
3739 b'identify|id',
3768 b'identify|id',
3740 [
3769 [
3741 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3770 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3742 (b'n', b'num', None, _(b'show local revision number')),
3771 (b'n', b'num', None, _(b'show local revision number')),
3743 (b'i', b'id', None, _(b'show global revision id')),
3772 (b'i', b'id', None, _(b'show global revision id')),
3744 (b'b', b'branch', None, _(b'show branch')),
3773 (b'b', b'branch', None, _(b'show branch')),
3745 (b't', b'tags', None, _(b'show tags')),
3774 (b't', b'tags', None, _(b'show tags')),
3746 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3775 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3747 ]
3776 ]
3748 + remoteopts
3777 + remoteopts
3749 + formatteropts,
3778 + formatteropts,
3750 _(b'[-nibtB] [-r REV] [SOURCE]'),
3779 _(b'[-nibtB] [-r REV] [SOURCE]'),
3751 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3780 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3752 optionalrepo=True,
3781 optionalrepo=True,
3753 intents={INTENT_READONLY},
3782 intents={INTENT_READONLY},
3754 )
3783 )
3755 def identify(
3784 def identify(
3756 ui,
3785 ui,
3757 repo,
3786 repo,
3758 source=None,
3787 source=None,
3759 rev=None,
3788 rev=None,
3760 num=None,
3789 num=None,
3761 id=None,
3790 id=None,
3762 branch=None,
3791 branch=None,
3763 tags=None,
3792 tags=None,
3764 bookmarks=None,
3793 bookmarks=None,
3765 **opts
3794 **opts
3766 ):
3795 ):
3767 """identify the working directory or specified revision
3796 """identify the working directory or specified revision
3768
3797
3769 Print a summary identifying the repository state at REV using one or
3798 Print a summary identifying the repository state at REV using one or
3770 two parent hash identifiers, followed by a "+" if the working
3799 two parent hash identifiers, followed by a "+" if the working
3771 directory has uncommitted changes, the branch name (if not default),
3800 directory has uncommitted changes, the branch name (if not default),
3772 a list of tags, and a list of bookmarks.
3801 a list of tags, and a list of bookmarks.
3773
3802
3774 When REV is not given, print a summary of the current state of the
3803 When REV is not given, print a summary of the current state of the
3775 repository including the working directory. Specify -r. to get information
3804 repository including the working directory. Specify -r. to get information
3776 of the working directory parent without scanning uncommitted changes.
3805 of the working directory parent without scanning uncommitted changes.
3777
3806
3778 Specifying a path to a repository root or Mercurial bundle will
3807 Specifying a path to a repository root or Mercurial bundle will
3779 cause lookup to operate on that repository/bundle.
3808 cause lookup to operate on that repository/bundle.
3780
3809
3781 .. container:: verbose
3810 .. container:: verbose
3782
3811
3783 Template:
3812 Template:
3784
3813
3785 The following keywords are supported in addition to the common template
3814 The following keywords are supported in addition to the common template
3786 keywords and functions. See also :hg:`help templates`.
3815 keywords and functions. See also :hg:`help templates`.
3787
3816
3788 :dirty: String. Character ``+`` denoting if the working directory has
3817 :dirty: String. Character ``+`` denoting if the working directory has
3789 uncommitted changes.
3818 uncommitted changes.
3790 :id: String. One or two nodes, optionally followed by ``+``.
3819 :id: String. One or two nodes, optionally followed by ``+``.
3791 :parents: List of strings. Parent nodes of the changeset.
3820 :parents: List of strings. Parent nodes of the changeset.
3792
3821
3793 Examples:
3822 Examples:
3794
3823
3795 - generate a build identifier for the working directory::
3824 - generate a build identifier for the working directory::
3796
3825
3797 hg id --id > build-id.dat
3826 hg id --id > build-id.dat
3798
3827
3799 - find the revision corresponding to a tag::
3828 - find the revision corresponding to a tag::
3800
3829
3801 hg id -n -r 1.3
3830 hg id -n -r 1.3
3802
3831
3803 - check the most recent revision of a remote repository::
3832 - check the most recent revision of a remote repository::
3804
3833
3805 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3834 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3806
3835
3807 See :hg:`log` for generating more information about specific revisions,
3836 See :hg:`log` for generating more information about specific revisions,
3808 including full hash identifiers.
3837 including full hash identifiers.
3809
3838
3810 Returns 0 if successful.
3839 Returns 0 if successful.
3811 """
3840 """
3812
3841
3813 opts = pycompat.byteskwargs(opts)
3842 opts = pycompat.byteskwargs(opts)
3814 if not repo and not source:
3843 if not repo and not source:
3815 raise error.InputError(
3844 raise error.InputError(
3816 _(b"there is no Mercurial repository here (.hg not found)")
3845 _(b"there is no Mercurial repository here (.hg not found)")
3817 )
3846 )
3818
3847
3819 default = not (num or id or branch or tags or bookmarks)
3848 default = not (num or id or branch or tags or bookmarks)
3820 output = []
3849 output = []
3821 revs = []
3850 revs = []
3822
3851
3823 if source:
3852 if source:
3824 source, branches = hg.parseurl(ui.expandpath(source))
3853 source, branches = hg.parseurl(ui.expandpath(source))
3825 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3854 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3826 repo = peer.local()
3855 repo = peer.local()
3827 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3856 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3828
3857
3829 fm = ui.formatter(b'identify', opts)
3858 fm = ui.formatter(b'identify', opts)
3830 fm.startitem()
3859 fm.startitem()
3831
3860
3832 if not repo:
3861 if not repo:
3833 if num or branch or tags:
3862 if num or branch or tags:
3834 raise error.InputError(
3863 raise error.InputError(
3835 _(b"can't query remote revision number, branch, or tags")
3864 _(b"can't query remote revision number, branch, or tags")
3836 )
3865 )
3837 if not rev and revs:
3866 if not rev and revs:
3838 rev = revs[0]
3867 rev = revs[0]
3839 if not rev:
3868 if not rev:
3840 rev = b"tip"
3869 rev = b"tip"
3841
3870
3842 remoterev = peer.lookup(rev)
3871 remoterev = peer.lookup(rev)
3843 hexrev = fm.hexfunc(remoterev)
3872 hexrev = fm.hexfunc(remoterev)
3844 if default or id:
3873 if default or id:
3845 output = [hexrev]
3874 output = [hexrev]
3846 fm.data(id=hexrev)
3875 fm.data(id=hexrev)
3847
3876
3848 @util.cachefunc
3877 @util.cachefunc
3849 def getbms():
3878 def getbms():
3850 bms = []
3879 bms = []
3851
3880
3852 if b'bookmarks' in peer.listkeys(b'namespaces'):
3881 if b'bookmarks' in peer.listkeys(b'namespaces'):
3853 hexremoterev = hex(remoterev)
3882 hexremoterev = hex(remoterev)
3854 bms = [
3883 bms = [
3855 bm
3884 bm
3856 for bm, bmr in pycompat.iteritems(
3885 for bm, bmr in pycompat.iteritems(
3857 peer.listkeys(b'bookmarks')
3886 peer.listkeys(b'bookmarks')
3858 )
3887 )
3859 if bmr == hexremoterev
3888 if bmr == hexremoterev
3860 ]
3889 ]
3861
3890
3862 return sorted(bms)
3891 return sorted(bms)
3863
3892
3864 if fm.isplain():
3893 if fm.isplain():
3865 if bookmarks:
3894 if bookmarks:
3866 output.extend(getbms())
3895 output.extend(getbms())
3867 elif default and not ui.quiet:
3896 elif default and not ui.quiet:
3868 # multiple bookmarks for a single parent separated by '/'
3897 # multiple bookmarks for a single parent separated by '/'
3869 bm = b'/'.join(getbms())
3898 bm = b'/'.join(getbms())
3870 if bm:
3899 if bm:
3871 output.append(bm)
3900 output.append(bm)
3872 else:
3901 else:
3873 fm.data(node=hex(remoterev))
3902 fm.data(node=hex(remoterev))
3874 if bookmarks or b'bookmarks' in fm.datahint():
3903 if bookmarks or b'bookmarks' in fm.datahint():
3875 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3904 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3876 else:
3905 else:
3877 if rev:
3906 if rev:
3878 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3907 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3879 ctx = scmutil.revsingle(repo, rev, None)
3908 ctx = scmutil.revsingle(repo, rev, None)
3880
3909
3881 if ctx.rev() is None:
3910 if ctx.rev() is None:
3882 ctx = repo[None]
3911 ctx = repo[None]
3883 parents = ctx.parents()
3912 parents = ctx.parents()
3884 taglist = []
3913 taglist = []
3885 for p in parents:
3914 for p in parents:
3886 taglist.extend(p.tags())
3915 taglist.extend(p.tags())
3887
3916
3888 dirty = b""
3917 dirty = b""
3889 if ctx.dirty(missing=True, merge=False, branch=False):
3918 if ctx.dirty(missing=True, merge=False, branch=False):
3890 dirty = b'+'
3919 dirty = b'+'
3891 fm.data(dirty=dirty)
3920 fm.data(dirty=dirty)
3892
3921
3893 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3922 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3894 if default or id:
3923 if default or id:
3895 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3924 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3896 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3925 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3897
3926
3898 if num:
3927 if num:
3899 numoutput = [b"%d" % p.rev() for p in parents]
3928 numoutput = [b"%d" % p.rev() for p in parents]
3900 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3929 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3901
3930
3902 fm.data(
3931 fm.data(
3903 parents=fm.formatlist(
3932 parents=fm.formatlist(
3904 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3933 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3905 )
3934 )
3906 )
3935 )
3907 else:
3936 else:
3908 hexoutput = fm.hexfunc(ctx.node())
3937 hexoutput = fm.hexfunc(ctx.node())
3909 if default or id:
3938 if default or id:
3910 output = [hexoutput]
3939 output = [hexoutput]
3911 fm.data(id=hexoutput)
3940 fm.data(id=hexoutput)
3912
3941
3913 if num:
3942 if num:
3914 output.append(pycompat.bytestr(ctx.rev()))
3943 output.append(pycompat.bytestr(ctx.rev()))
3915 taglist = ctx.tags()
3944 taglist = ctx.tags()
3916
3945
3917 if default and not ui.quiet:
3946 if default and not ui.quiet:
3918 b = ctx.branch()
3947 b = ctx.branch()
3919 if b != b'default':
3948 if b != b'default':
3920 output.append(b"(%s)" % b)
3949 output.append(b"(%s)" % b)
3921
3950
3922 # multiple tags for a single parent separated by '/'
3951 # multiple tags for a single parent separated by '/'
3923 t = b'/'.join(taglist)
3952 t = b'/'.join(taglist)
3924 if t:
3953 if t:
3925 output.append(t)
3954 output.append(t)
3926
3955
3927 # multiple bookmarks for a single parent separated by '/'
3956 # multiple bookmarks for a single parent separated by '/'
3928 bm = b'/'.join(ctx.bookmarks())
3957 bm = b'/'.join(ctx.bookmarks())
3929 if bm:
3958 if bm:
3930 output.append(bm)
3959 output.append(bm)
3931 else:
3960 else:
3932 if branch:
3961 if branch:
3933 output.append(ctx.branch())
3962 output.append(ctx.branch())
3934
3963
3935 if tags:
3964 if tags:
3936 output.extend(taglist)
3965 output.extend(taglist)
3937
3966
3938 if bookmarks:
3967 if bookmarks:
3939 output.extend(ctx.bookmarks())
3968 output.extend(ctx.bookmarks())
3940
3969
3941 fm.data(node=ctx.hex())
3970 fm.data(node=ctx.hex())
3942 fm.data(branch=ctx.branch())
3971 fm.data(branch=ctx.branch())
3943 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
3972 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
3944 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
3973 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
3945 fm.context(ctx=ctx)
3974 fm.context(ctx=ctx)
3946
3975
3947 fm.plain(b"%s\n" % b' '.join(output))
3976 fm.plain(b"%s\n" % b' '.join(output))
3948 fm.end()
3977 fm.end()
3949
3978
3950
3979
3951 @command(
3980 @command(
3952 b'import|patch',
3981 b'import|patch',
3953 [
3982 [
3954 (
3983 (
3955 b'p',
3984 b'p',
3956 b'strip',
3985 b'strip',
3957 1,
3986 1,
3958 _(
3987 _(
3959 b'directory strip option for patch. This has the same '
3988 b'directory strip option for patch. This has the same '
3960 b'meaning as the corresponding patch option'
3989 b'meaning as the corresponding patch option'
3961 ),
3990 ),
3962 _(b'NUM'),
3991 _(b'NUM'),
3963 ),
3992 ),
3964 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
3993 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
3965 (b'', b'secret', None, _(b'use the secret phase for committing')),
3994 (b'', b'secret', None, _(b'use the secret phase for committing')),
3966 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3995 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
3967 (
3996 (
3968 b'f',
3997 b'f',
3969 b'force',
3998 b'force',
3970 None,
3999 None,
3971 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4000 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
3972 ),
4001 ),
3973 (
4002 (
3974 b'',
4003 b'',
3975 b'no-commit',
4004 b'no-commit',
3976 None,
4005 None,
3977 _(b"don't commit, just update the working directory"),
4006 _(b"don't commit, just update the working directory"),
3978 ),
4007 ),
3979 (
4008 (
3980 b'',
4009 b'',
3981 b'bypass',
4010 b'bypass',
3982 None,
4011 None,
3983 _(b"apply patch without touching the working directory"),
4012 _(b"apply patch without touching the working directory"),
3984 ),
4013 ),
3985 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4014 (b'', b'partial', None, _(b'commit even if some hunks fail')),
3986 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4015 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
3987 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4016 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
3988 (
4017 (
3989 b'',
4018 b'',
3990 b'import-branch',
4019 b'import-branch',
3991 None,
4020 None,
3992 _(b'use any branch information in patch (implied by --exact)'),
4021 _(b'use any branch information in patch (implied by --exact)'),
3993 ),
4022 ),
3994 ]
4023 ]
3995 + commitopts
4024 + commitopts
3996 + commitopts2
4025 + commitopts2
3997 + similarityopts,
4026 + similarityopts,
3998 _(b'[OPTION]... PATCH...'),
4027 _(b'[OPTION]... PATCH...'),
3999 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4028 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4000 )
4029 )
4001 def import_(ui, repo, patch1=None, *patches, **opts):
4030 def import_(ui, repo, patch1=None, *patches, **opts):
4002 """import an ordered set of patches
4031 """import an ordered set of patches
4003
4032
4004 Import a list of patches and commit them individually (unless
4033 Import a list of patches and commit them individually (unless
4005 --no-commit is specified).
4034 --no-commit is specified).
4006
4035
4007 To read a patch from standard input (stdin), use "-" as the patch
4036 To read a patch from standard input (stdin), use "-" as the patch
4008 name. If a URL is specified, the patch will be downloaded from
4037 name. If a URL is specified, the patch will be downloaded from
4009 there.
4038 there.
4010
4039
4011 Import first applies changes to the working directory (unless
4040 Import first applies changes to the working directory (unless
4012 --bypass is specified), import will abort if there are outstanding
4041 --bypass is specified), import will abort if there are outstanding
4013 changes.
4042 changes.
4014
4043
4015 Use --bypass to apply and commit patches directly to the
4044 Use --bypass to apply and commit patches directly to the
4016 repository, without affecting the working directory. Without
4045 repository, without affecting the working directory. Without
4017 --exact, patches will be applied on top of the working directory
4046 --exact, patches will be applied on top of the working directory
4018 parent revision.
4047 parent revision.
4019
4048
4020 You can import a patch straight from a mail message. Even patches
4049 You can import a patch straight from a mail message. Even patches
4021 as attachments work (to use the body part, it must have type
4050 as attachments work (to use the body part, it must have type
4022 text/plain or text/x-patch). From and Subject headers of email
4051 text/plain or text/x-patch). From and Subject headers of email
4023 message are used as default committer and commit message. All
4052 message are used as default committer and commit message. All
4024 text/plain body parts before first diff are added to the commit
4053 text/plain body parts before first diff are added to the commit
4025 message.
4054 message.
4026
4055
4027 If the imported patch was generated by :hg:`export`, user and
4056 If the imported patch was generated by :hg:`export`, user and
4028 description from patch override values from message headers and
4057 description from patch override values from message headers and
4029 body. Values given on command line with -m/--message and -u/--user
4058 body. Values given on command line with -m/--message and -u/--user
4030 override these.
4059 override these.
4031
4060
4032 If --exact is specified, import will set the working directory to
4061 If --exact is specified, import will set the working directory to
4033 the parent of each patch before applying it, and will abort if the
4062 the parent of each patch before applying it, and will abort if the
4034 resulting changeset has a different ID than the one recorded in
4063 resulting changeset has a different ID than the one recorded in
4035 the patch. This will guard against various ways that portable
4064 the patch. This will guard against various ways that portable
4036 patch formats and mail systems might fail to transfer Mercurial
4065 patch formats and mail systems might fail to transfer Mercurial
4037 data or metadata. See :hg:`bundle` for lossless transmission.
4066 data or metadata. See :hg:`bundle` for lossless transmission.
4038
4067
4039 Use --partial to ensure a changeset will be created from the patch
4068 Use --partial to ensure a changeset will be created from the patch
4040 even if some hunks fail to apply. Hunks that fail to apply will be
4069 even if some hunks fail to apply. Hunks that fail to apply will be
4041 written to a <target-file>.rej file. Conflicts can then be resolved
4070 written to a <target-file>.rej file. Conflicts can then be resolved
4042 by hand before :hg:`commit --amend` is run to update the created
4071 by hand before :hg:`commit --amend` is run to update the created
4043 changeset. This flag exists to let people import patches that
4072 changeset. This flag exists to let people import patches that
4044 partially apply without losing the associated metadata (author,
4073 partially apply without losing the associated metadata (author,
4045 date, description, ...).
4074 date, description, ...).
4046
4075
4047 .. note::
4076 .. note::
4048
4077
4049 When no hunks apply cleanly, :hg:`import --partial` will create
4078 When no hunks apply cleanly, :hg:`import --partial` will create
4050 an empty changeset, importing only the patch metadata.
4079 an empty changeset, importing only the patch metadata.
4051
4080
4052 With -s/--similarity, hg will attempt to discover renames and
4081 With -s/--similarity, hg will attempt to discover renames and
4053 copies in the patch in the same way as :hg:`addremove`.
4082 copies in the patch in the same way as :hg:`addremove`.
4054
4083
4055 It is possible to use external patch programs to perform the patch
4084 It is possible to use external patch programs to perform the patch
4056 by setting the ``ui.patch`` configuration option. For the default
4085 by setting the ``ui.patch`` configuration option. For the default
4057 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4086 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4058 See :hg:`help config` for more information about configuration
4087 See :hg:`help config` for more information about configuration
4059 files and how to use these options.
4088 files and how to use these options.
4060
4089
4061 See :hg:`help dates` for a list of formats valid for -d/--date.
4090 See :hg:`help dates` for a list of formats valid for -d/--date.
4062
4091
4063 .. container:: verbose
4092 .. container:: verbose
4064
4093
4065 Examples:
4094 Examples:
4066
4095
4067 - import a traditional patch from a website and detect renames::
4096 - import a traditional patch from a website and detect renames::
4068
4097
4069 hg import -s 80 http://example.com/bugfix.patch
4098 hg import -s 80 http://example.com/bugfix.patch
4070
4099
4071 - import a changeset from an hgweb server::
4100 - import a changeset from an hgweb server::
4072
4101
4073 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4102 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4074
4103
4075 - import all the patches in an Unix-style mbox::
4104 - import all the patches in an Unix-style mbox::
4076
4105
4077 hg import incoming-patches.mbox
4106 hg import incoming-patches.mbox
4078
4107
4079 - import patches from stdin::
4108 - import patches from stdin::
4080
4109
4081 hg import -
4110 hg import -
4082
4111
4083 - attempt to exactly restore an exported changeset (not always
4112 - attempt to exactly restore an exported changeset (not always
4084 possible)::
4113 possible)::
4085
4114
4086 hg import --exact proposed-fix.patch
4115 hg import --exact proposed-fix.patch
4087
4116
4088 - use an external tool to apply a patch which is too fuzzy for
4117 - use an external tool to apply a patch which is too fuzzy for
4089 the default internal tool.
4118 the default internal tool.
4090
4119
4091 hg import --config ui.patch="patch --merge" fuzzy.patch
4120 hg import --config ui.patch="patch --merge" fuzzy.patch
4092
4121
4093 - change the default fuzzing from 2 to a less strict 7
4122 - change the default fuzzing from 2 to a less strict 7
4094
4123
4095 hg import --config ui.fuzz=7 fuzz.patch
4124 hg import --config ui.fuzz=7 fuzz.patch
4096
4125
4097 Returns 0 on success, 1 on partial success (see --partial).
4126 Returns 0 on success, 1 on partial success (see --partial).
4098 """
4127 """
4099
4128
4100 cmdutil.check_incompatible_arguments(
4129 cmdutil.check_incompatible_arguments(
4101 opts, 'no_commit', ['bypass', 'secret']
4130 opts, 'no_commit', ['bypass', 'secret']
4102 )
4131 )
4103 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4132 cmdutil.check_incompatible_arguments(opts, 'exact', ['edit', 'prefix'])
4104 opts = pycompat.byteskwargs(opts)
4133 opts = pycompat.byteskwargs(opts)
4105 if not patch1:
4134 if not patch1:
4106 raise error.InputError(_(b'need at least one patch to import'))
4135 raise error.InputError(_(b'need at least one patch to import'))
4107
4136
4108 patches = (patch1,) + patches
4137 patches = (patch1,) + patches
4109
4138
4110 date = opts.get(b'date')
4139 date = opts.get(b'date')
4111 if date:
4140 if date:
4112 opts[b'date'] = dateutil.parsedate(date)
4141 opts[b'date'] = dateutil.parsedate(date)
4113
4142
4114 exact = opts.get(b'exact')
4143 exact = opts.get(b'exact')
4115 update = not opts.get(b'bypass')
4144 update = not opts.get(b'bypass')
4116 try:
4145 try:
4117 sim = float(opts.get(b'similarity') or 0)
4146 sim = float(opts.get(b'similarity') or 0)
4118 except ValueError:
4147 except ValueError:
4119 raise error.InputError(_(b'similarity must be a number'))
4148 raise error.InputError(_(b'similarity must be a number'))
4120 if sim < 0 or sim > 100:
4149 if sim < 0 or sim > 100:
4121 raise error.InputError(_(b'similarity must be between 0 and 100'))
4150 raise error.InputError(_(b'similarity must be between 0 and 100'))
4122 if sim and not update:
4151 if sim and not update:
4123 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4152 raise error.InputError(_(b'cannot use --similarity with --bypass'))
4124
4153
4125 base = opts[b"base"]
4154 base = opts[b"base"]
4126 msgs = []
4155 msgs = []
4127 ret = 0
4156 ret = 0
4128
4157
4129 with repo.wlock():
4158 with repo.wlock():
4130 if update:
4159 if update:
4131 cmdutil.checkunfinished(repo)
4160 cmdutil.checkunfinished(repo)
4132 if exact or not opts.get(b'force'):
4161 if exact or not opts.get(b'force'):
4133 cmdutil.bailifchanged(repo)
4162 cmdutil.bailifchanged(repo)
4134
4163
4135 if not opts.get(b'no_commit'):
4164 if not opts.get(b'no_commit'):
4136 lock = repo.lock
4165 lock = repo.lock
4137 tr = lambda: repo.transaction(b'import')
4166 tr = lambda: repo.transaction(b'import')
4138 dsguard = util.nullcontextmanager
4167 dsguard = util.nullcontextmanager
4139 else:
4168 else:
4140 lock = util.nullcontextmanager
4169 lock = util.nullcontextmanager
4141 tr = util.nullcontextmanager
4170 tr = util.nullcontextmanager
4142 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4171 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4143 with lock(), tr(), dsguard():
4172 with lock(), tr(), dsguard():
4144 parents = repo[None].parents()
4173 parents = repo[None].parents()
4145 for patchurl in patches:
4174 for patchurl in patches:
4146 if patchurl == b'-':
4175 if patchurl == b'-':
4147 ui.status(_(b'applying patch from stdin\n'))
4176 ui.status(_(b'applying patch from stdin\n'))
4148 patchfile = ui.fin
4177 patchfile = ui.fin
4149 patchurl = b'stdin' # for error message
4178 patchurl = b'stdin' # for error message
4150 else:
4179 else:
4151 patchurl = os.path.join(base, patchurl)
4180 patchurl = os.path.join(base, patchurl)
4152 ui.status(_(b'applying %s\n') % patchurl)
4181 ui.status(_(b'applying %s\n') % patchurl)
4153 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4182 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4154
4183
4155 haspatch = False
4184 haspatch = False
4156 for hunk in patch.split(patchfile):
4185 for hunk in patch.split(patchfile):
4157 with patch.extract(ui, hunk) as patchdata:
4186 with patch.extract(ui, hunk) as patchdata:
4158 msg, node, rej = cmdutil.tryimportone(
4187 msg, node, rej = cmdutil.tryimportone(
4159 ui, repo, patchdata, parents, opts, msgs, hg.clean
4188 ui, repo, patchdata, parents, opts, msgs, hg.clean
4160 )
4189 )
4161 if msg:
4190 if msg:
4162 haspatch = True
4191 haspatch = True
4163 ui.note(msg + b'\n')
4192 ui.note(msg + b'\n')
4164 if update or exact:
4193 if update or exact:
4165 parents = repo[None].parents()
4194 parents = repo[None].parents()
4166 else:
4195 else:
4167 parents = [repo[node]]
4196 parents = [repo[node]]
4168 if rej:
4197 if rej:
4169 ui.write_err(_(b"patch applied partially\n"))
4198 ui.write_err(_(b"patch applied partially\n"))
4170 ui.write_err(
4199 ui.write_err(
4171 _(
4200 _(
4172 b"(fix the .rej files and run "
4201 b"(fix the .rej files and run "
4173 b"`hg commit --amend`)\n"
4202 b"`hg commit --amend`)\n"
4174 )
4203 )
4175 )
4204 )
4176 ret = 1
4205 ret = 1
4177 break
4206 break
4178
4207
4179 if not haspatch:
4208 if not haspatch:
4180 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4209 raise error.InputError(_(b'%s: no diffs found') % patchurl)
4181
4210
4182 if msgs:
4211 if msgs:
4183 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4212 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4184 return ret
4213 return ret
4185
4214
4186
4215
4187 @command(
4216 @command(
4188 b'incoming|in',
4217 b'incoming|in',
4189 [
4218 [
4190 (
4219 (
4191 b'f',
4220 b'f',
4192 b'force',
4221 b'force',
4193 None,
4222 None,
4194 _(b'run even if remote repository is unrelated'),
4223 _(b'run even if remote repository is unrelated'),
4195 ),
4224 ),
4196 (b'n', b'newest-first', None, _(b'show newest record first')),
4225 (b'n', b'newest-first', None, _(b'show newest record first')),
4197 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4226 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4198 (
4227 (
4199 b'r',
4228 b'r',
4200 b'rev',
4229 b'rev',
4201 [],
4230 [],
4202 _(b'a remote changeset intended to be added'),
4231 _(b'a remote changeset intended to be added'),
4203 _(b'REV'),
4232 _(b'REV'),
4204 ),
4233 ),
4205 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4234 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4206 (
4235 (
4207 b'b',
4236 b'b',
4208 b'branch',
4237 b'branch',
4209 [],
4238 [],
4210 _(b'a specific branch you would like to pull'),
4239 _(b'a specific branch you would like to pull'),
4211 _(b'BRANCH'),
4240 _(b'BRANCH'),
4212 ),
4241 ),
4213 ]
4242 ]
4214 + logopts
4243 + logopts
4215 + remoteopts
4244 + remoteopts
4216 + subrepoopts,
4245 + subrepoopts,
4217 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4246 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4218 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4247 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4219 )
4248 )
4220 def incoming(ui, repo, source=b"default", **opts):
4249 def incoming(ui, repo, source=b"default", **opts):
4221 """show new changesets found in source
4250 """show new changesets found in source
4222
4251
4223 Show new changesets found in the specified path/URL or the default
4252 Show new changesets found in the specified path/URL or the default
4224 pull location. These are the changesets that would have been pulled
4253 pull location. These are the changesets that would have been pulled
4225 by :hg:`pull` at the time you issued this command.
4254 by :hg:`pull` at the time you issued this command.
4226
4255
4227 See pull for valid source format details.
4256 See pull for valid source format details.
4228
4257
4229 .. container:: verbose
4258 .. container:: verbose
4230
4259
4231 With -B/--bookmarks, the result of bookmark comparison between
4260 With -B/--bookmarks, the result of bookmark comparison between
4232 local and remote repositories is displayed. With -v/--verbose,
4261 local and remote repositories is displayed. With -v/--verbose,
4233 status is also displayed for each bookmark like below::
4262 status is also displayed for each bookmark like below::
4234
4263
4235 BM1 01234567890a added
4264 BM1 01234567890a added
4236 BM2 1234567890ab advanced
4265 BM2 1234567890ab advanced
4237 BM3 234567890abc diverged
4266 BM3 234567890abc diverged
4238 BM4 34567890abcd changed
4267 BM4 34567890abcd changed
4239
4268
4240 The action taken locally when pulling depends on the
4269 The action taken locally when pulling depends on the
4241 status of each bookmark:
4270 status of each bookmark:
4242
4271
4243 :``added``: pull will create it
4272 :``added``: pull will create it
4244 :``advanced``: pull will update it
4273 :``advanced``: pull will update it
4245 :``diverged``: pull will create a divergent bookmark
4274 :``diverged``: pull will create a divergent bookmark
4246 :``changed``: result depends on remote changesets
4275 :``changed``: result depends on remote changesets
4247
4276
4248 From the point of view of pulling behavior, bookmark
4277 From the point of view of pulling behavior, bookmark
4249 existing only in the remote repository are treated as ``added``,
4278 existing only in the remote repository are treated as ``added``,
4250 even if it is in fact locally deleted.
4279 even if it is in fact locally deleted.
4251
4280
4252 .. container:: verbose
4281 .. container:: verbose
4253
4282
4254 For remote repository, using --bundle avoids downloading the
4283 For remote repository, using --bundle avoids downloading the
4255 changesets twice if the incoming is followed by a pull.
4284 changesets twice if the incoming is followed by a pull.
4256
4285
4257 Examples:
4286 Examples:
4258
4287
4259 - show incoming changes with patches and full description::
4288 - show incoming changes with patches and full description::
4260
4289
4261 hg incoming -vp
4290 hg incoming -vp
4262
4291
4263 - show incoming changes excluding merges, store a bundle::
4292 - show incoming changes excluding merges, store a bundle::
4264
4293
4265 hg in -vpM --bundle incoming.hg
4294 hg in -vpM --bundle incoming.hg
4266 hg pull incoming.hg
4295 hg pull incoming.hg
4267
4296
4268 - briefly list changes inside a bundle::
4297 - briefly list changes inside a bundle::
4269
4298
4270 hg in changes.hg -T "{desc|firstline}\\n"
4299 hg in changes.hg -T "{desc|firstline}\\n"
4271
4300
4272 Returns 0 if there are incoming changes, 1 otherwise.
4301 Returns 0 if there are incoming changes, 1 otherwise.
4273 """
4302 """
4274 opts = pycompat.byteskwargs(opts)
4303 opts = pycompat.byteskwargs(opts)
4275 if opts.get(b'graph'):
4304 if opts.get(b'graph'):
4276 logcmdutil.checkunsupportedgraphflags([], opts)
4305 logcmdutil.checkunsupportedgraphflags([], opts)
4277
4306
4278 def display(other, chlist, displayer):
4307 def display(other, chlist, displayer):
4279 revdag = logcmdutil.graphrevs(other, chlist, opts)
4308 revdag = logcmdutil.graphrevs(other, chlist, opts)
4280 logcmdutil.displaygraph(
4309 logcmdutil.displaygraph(
4281 ui, repo, revdag, displayer, graphmod.asciiedges
4310 ui, repo, revdag, displayer, graphmod.asciiedges
4282 )
4311 )
4283
4312
4284 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4313 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4285 return 0
4314 return 0
4286
4315
4287 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4316 cmdutil.check_incompatible_arguments(opts, b'subrepos', [b'bundle'])
4288
4317
4289 if opts.get(b'bookmarks'):
4318 if opts.get(b'bookmarks'):
4290 source, branches = hg.parseurl(
4319 source, branches = hg.parseurl(
4291 ui.expandpath(source), opts.get(b'branch')
4320 ui.expandpath(source), opts.get(b'branch')
4292 )
4321 )
4293 other = hg.peer(repo, opts, source)
4322 other = hg.peer(repo, opts, source)
4294 if b'bookmarks' not in other.listkeys(b'namespaces'):
4323 if b'bookmarks' not in other.listkeys(b'namespaces'):
4295 ui.warn(_(b"remote doesn't support bookmarks\n"))
4324 ui.warn(_(b"remote doesn't support bookmarks\n"))
4296 return 0
4325 return 0
4297 ui.pager(b'incoming')
4326 ui.pager(b'incoming')
4298 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4327 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4299 return bookmarks.incoming(ui, repo, other)
4328 return bookmarks.incoming(ui, repo, other)
4300
4329
4301 repo._subtoppath = ui.expandpath(source)
4330 repo._subtoppath = ui.expandpath(source)
4302 try:
4331 try:
4303 return hg.incoming(ui, repo, source, opts)
4332 return hg.incoming(ui, repo, source, opts)
4304 finally:
4333 finally:
4305 del repo._subtoppath
4334 del repo._subtoppath
4306
4335
4307
4336
4308 @command(
4337 @command(
4309 b'init',
4338 b'init',
4310 remoteopts,
4339 remoteopts,
4311 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4340 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4312 helpcategory=command.CATEGORY_REPO_CREATION,
4341 helpcategory=command.CATEGORY_REPO_CREATION,
4313 helpbasic=True,
4342 helpbasic=True,
4314 norepo=True,
4343 norepo=True,
4315 )
4344 )
4316 def init(ui, dest=b".", **opts):
4345 def init(ui, dest=b".", **opts):
4317 """create a new repository in the given directory
4346 """create a new repository in the given directory
4318
4347
4319 Initialize a new repository in the given directory. If the given
4348 Initialize a new repository in the given directory. If the given
4320 directory does not exist, it will be created.
4349 directory does not exist, it will be created.
4321
4350
4322 If no directory is given, the current directory is used.
4351 If no directory is given, the current directory is used.
4323
4352
4324 It is possible to specify an ``ssh://`` URL as the destination.
4353 It is possible to specify an ``ssh://`` URL as the destination.
4325 See :hg:`help urls` for more information.
4354 See :hg:`help urls` for more information.
4326
4355
4327 Returns 0 on success.
4356 Returns 0 on success.
4328 """
4357 """
4329 opts = pycompat.byteskwargs(opts)
4358 opts = pycompat.byteskwargs(opts)
4330 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4359 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4331
4360
4332
4361
4333 @command(
4362 @command(
4334 b'locate',
4363 b'locate',
4335 [
4364 [
4336 (
4365 (
4337 b'r',
4366 b'r',
4338 b'rev',
4367 b'rev',
4339 b'',
4368 b'',
4340 _(b'search the repository as it is in REV'),
4369 _(b'search the repository as it is in REV'),
4341 _(b'REV'),
4370 _(b'REV'),
4342 ),
4371 ),
4343 (
4372 (
4344 b'0',
4373 b'0',
4345 b'print0',
4374 b'print0',
4346 None,
4375 None,
4347 _(b'end filenames with NUL, for use with xargs'),
4376 _(b'end filenames with NUL, for use with xargs'),
4348 ),
4377 ),
4349 (
4378 (
4350 b'f',
4379 b'f',
4351 b'fullpath',
4380 b'fullpath',
4352 None,
4381 None,
4353 _(b'print complete paths from the filesystem root'),
4382 _(b'print complete paths from the filesystem root'),
4354 ),
4383 ),
4355 ]
4384 ]
4356 + walkopts,
4385 + walkopts,
4357 _(b'[OPTION]... [PATTERN]...'),
4386 _(b'[OPTION]... [PATTERN]...'),
4358 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4387 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4359 )
4388 )
4360 def locate(ui, repo, *pats, **opts):
4389 def locate(ui, repo, *pats, **opts):
4361 """locate files matching specific patterns (DEPRECATED)
4390 """locate files matching specific patterns (DEPRECATED)
4362
4391
4363 Print files under Mercurial control in the working directory whose
4392 Print files under Mercurial control in the working directory whose
4364 names match the given patterns.
4393 names match the given patterns.
4365
4394
4366 By default, this command searches all directories in the working
4395 By default, this command searches all directories in the working
4367 directory. To search just the current directory and its
4396 directory. To search just the current directory and its
4368 subdirectories, use "--include .".
4397 subdirectories, use "--include .".
4369
4398
4370 If no patterns are given to match, this command prints the names
4399 If no patterns are given to match, this command prints the names
4371 of all files under Mercurial control in the working directory.
4400 of all files under Mercurial control in the working directory.
4372
4401
4373 If you want to feed the output of this command into the "xargs"
4402 If you want to feed the output of this command into the "xargs"
4374 command, use the -0 option to both this command and "xargs". This
4403 command, use the -0 option to both this command and "xargs". This
4375 will avoid the problem of "xargs" treating single filenames that
4404 will avoid the problem of "xargs" treating single filenames that
4376 contain whitespace as multiple filenames.
4405 contain whitespace as multiple filenames.
4377
4406
4378 See :hg:`help files` for a more versatile command.
4407 See :hg:`help files` for a more versatile command.
4379
4408
4380 Returns 0 if a match is found, 1 otherwise.
4409 Returns 0 if a match is found, 1 otherwise.
4381 """
4410 """
4382 opts = pycompat.byteskwargs(opts)
4411 opts = pycompat.byteskwargs(opts)
4383 if opts.get(b'print0'):
4412 if opts.get(b'print0'):
4384 end = b'\0'
4413 end = b'\0'
4385 else:
4414 else:
4386 end = b'\n'
4415 end = b'\n'
4387 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4416 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4388
4417
4389 ret = 1
4418 ret = 1
4390 m = scmutil.match(
4419 m = scmutil.match(
4391 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4420 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4392 )
4421 )
4393
4422
4394 ui.pager(b'locate')
4423 ui.pager(b'locate')
4395 if ctx.rev() is None:
4424 if ctx.rev() is None:
4396 # When run on the working copy, "locate" includes removed files, so
4425 # When run on the working copy, "locate" includes removed files, so
4397 # we get the list of files from the dirstate.
4426 # we get the list of files from the dirstate.
4398 filesgen = sorted(repo.dirstate.matches(m))
4427 filesgen = sorted(repo.dirstate.matches(m))
4399 else:
4428 else:
4400 filesgen = ctx.matches(m)
4429 filesgen = ctx.matches(m)
4401 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4430 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4402 for abs in filesgen:
4431 for abs in filesgen:
4403 if opts.get(b'fullpath'):
4432 if opts.get(b'fullpath'):
4404 ui.write(repo.wjoin(abs), end)
4433 ui.write(repo.wjoin(abs), end)
4405 else:
4434 else:
4406 ui.write(uipathfn(abs), end)
4435 ui.write(uipathfn(abs), end)
4407 ret = 0
4436 ret = 0
4408
4437
4409 return ret
4438 return ret
4410
4439
4411
4440
4412 @command(
4441 @command(
4413 b'log|history',
4442 b'log|history',
4414 [
4443 [
4415 (
4444 (
4416 b'f',
4445 b'f',
4417 b'follow',
4446 b'follow',
4418 None,
4447 None,
4419 _(
4448 _(
4420 b'follow changeset history, or file history across copies and renames'
4449 b'follow changeset history, or file history across copies and renames'
4421 ),
4450 ),
4422 ),
4451 ),
4423 (
4452 (
4424 b'',
4453 b'',
4425 b'follow-first',
4454 b'follow-first',
4426 None,
4455 None,
4427 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4456 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4428 ),
4457 ),
4429 (
4458 (
4430 b'd',
4459 b'd',
4431 b'date',
4460 b'date',
4432 b'',
4461 b'',
4433 _(b'show revisions matching date spec'),
4462 _(b'show revisions matching date spec'),
4434 _(b'DATE'),
4463 _(b'DATE'),
4435 ),
4464 ),
4436 (b'C', b'copies', None, _(b'show copied files')),
4465 (b'C', b'copies', None, _(b'show copied files')),
4437 (
4466 (
4438 b'k',
4467 b'k',
4439 b'keyword',
4468 b'keyword',
4440 [],
4469 [],
4441 _(b'do case-insensitive search for a given text'),
4470 _(b'do case-insensitive search for a given text'),
4442 _(b'TEXT'),
4471 _(b'TEXT'),
4443 ),
4472 ),
4444 (
4473 (
4445 b'r',
4474 b'r',
4446 b'rev',
4475 b'rev',
4447 [],
4476 [],
4448 _(b'revisions to select or follow from'),
4477 _(b'revisions to select or follow from'),
4449 _(b'REV'),
4478 _(b'REV'),
4450 ),
4479 ),
4451 (
4480 (
4452 b'L',
4481 b'L',
4453 b'line-range',
4482 b'line-range',
4454 [],
4483 [],
4455 _(b'follow line range of specified file (EXPERIMENTAL)'),
4484 _(b'follow line range of specified file (EXPERIMENTAL)'),
4456 _(b'FILE,RANGE'),
4485 _(b'FILE,RANGE'),
4457 ),
4486 ),
4458 (
4487 (
4459 b'',
4488 b'',
4460 b'removed',
4489 b'removed',
4461 None,
4490 None,
4462 _(b'include revisions where files were removed'),
4491 _(b'include revisions where files were removed'),
4463 ),
4492 ),
4464 (
4493 (
4465 b'm',
4494 b'm',
4466 b'only-merges',
4495 b'only-merges',
4467 None,
4496 None,
4468 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4497 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4469 ),
4498 ),
4470 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4499 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4471 (
4500 (
4472 b'',
4501 b'',
4473 b'only-branch',
4502 b'only-branch',
4474 [],
4503 [],
4475 _(
4504 _(
4476 b'show only changesets within the given named branch (DEPRECATED)'
4505 b'show only changesets within the given named branch (DEPRECATED)'
4477 ),
4506 ),
4478 _(b'BRANCH'),
4507 _(b'BRANCH'),
4479 ),
4508 ),
4480 (
4509 (
4481 b'b',
4510 b'b',
4482 b'branch',
4511 b'branch',
4483 [],
4512 [],
4484 _(b'show changesets within the given named branch'),
4513 _(b'show changesets within the given named branch'),
4485 _(b'BRANCH'),
4514 _(b'BRANCH'),
4486 ),
4515 ),
4487 (
4516 (
4488 b'B',
4517 b'B',
4489 b'bookmark',
4518 b'bookmark',
4490 [],
4519 [],
4491 _(b"show changesets within the given bookmark"),
4520 _(b"show changesets within the given bookmark"),
4492 _(b'BOOKMARK'),
4521 _(b'BOOKMARK'),
4493 ),
4522 ),
4494 (
4523 (
4495 b'P',
4524 b'P',
4496 b'prune',
4525 b'prune',
4497 [],
4526 [],
4498 _(b'do not display revision or any of its ancestors'),
4527 _(b'do not display revision or any of its ancestors'),
4499 _(b'REV'),
4528 _(b'REV'),
4500 ),
4529 ),
4501 ]
4530 ]
4502 + logopts
4531 + logopts
4503 + walkopts,
4532 + walkopts,
4504 _(b'[OPTION]... [FILE]'),
4533 _(b'[OPTION]... [FILE]'),
4505 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4534 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4506 helpbasic=True,
4535 helpbasic=True,
4507 inferrepo=True,
4536 inferrepo=True,
4508 intents={INTENT_READONLY},
4537 intents={INTENT_READONLY},
4509 )
4538 )
4510 def log(ui, repo, *pats, **opts):
4539 def log(ui, repo, *pats, **opts):
4511 """show revision history of entire repository or files
4540 """show revision history of entire repository or files
4512
4541
4513 Print the revision history of the specified files or the entire
4542 Print the revision history of the specified files or the entire
4514 project.
4543 project.
4515
4544
4516 If no revision range is specified, the default is ``tip:0`` unless
4545 If no revision range is specified, the default is ``tip:0`` unless
4517 --follow is set.
4546 --follow is set.
4518
4547
4519 File history is shown without following rename or copy history of
4548 File history is shown without following rename or copy history of
4520 files. Use -f/--follow with a filename to follow history across
4549 files. Use -f/--follow with a filename to follow history across
4521 renames and copies. --follow without a filename will only show
4550 renames and copies. --follow without a filename will only show
4522 ancestors of the starting revisions. The starting revisions can be
4551 ancestors of the starting revisions. The starting revisions can be
4523 specified by -r/--rev, which default to the working directory parent.
4552 specified by -r/--rev, which default to the working directory parent.
4524
4553
4525 By default this command prints revision number and changeset id,
4554 By default this command prints revision number and changeset id,
4526 tags, non-trivial parents, user, date and time, and a summary for
4555 tags, non-trivial parents, user, date and time, and a summary for
4527 each commit. When the -v/--verbose switch is used, the list of
4556 each commit. When the -v/--verbose switch is used, the list of
4528 changed files and full commit message are shown.
4557 changed files and full commit message are shown.
4529
4558
4530 With --graph the revisions are shown as an ASCII art DAG with the most
4559 With --graph the revisions are shown as an ASCII art DAG with the most
4531 recent changeset at the top.
4560 recent changeset at the top.
4532 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4561 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4533 involved in an unresolved merge conflict, '_' closes a branch,
4562 involved in an unresolved merge conflict, '_' closes a branch,
4534 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4563 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4535 changeset from the lines below is a parent of the 'o' merge on the same
4564 changeset from the lines below is a parent of the 'o' merge on the same
4536 line.
4565 line.
4537 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4566 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4538 of a '|' indicates one or more revisions in a path are omitted.
4567 of a '|' indicates one or more revisions in a path are omitted.
4539
4568
4540 .. container:: verbose
4569 .. container:: verbose
4541
4570
4542 Use -L/--line-range FILE,M:N options to follow the history of lines
4571 Use -L/--line-range FILE,M:N options to follow the history of lines
4543 from M to N in FILE. With -p/--patch only diff hunks affecting
4572 from M to N in FILE. With -p/--patch only diff hunks affecting
4544 specified line range will be shown. This option requires --follow;
4573 specified line range will be shown. This option requires --follow;
4545 it can be specified multiple times. Currently, this option is not
4574 it can be specified multiple times. Currently, this option is not
4546 compatible with --graph. This option is experimental.
4575 compatible with --graph. This option is experimental.
4547
4576
4548 .. note::
4577 .. note::
4549
4578
4550 :hg:`log --patch` may generate unexpected diff output for merge
4579 :hg:`log --patch` may generate unexpected diff output for merge
4551 changesets, as it will only compare the merge changeset against
4580 changesets, as it will only compare the merge changeset against
4552 its first parent. Also, only files different from BOTH parents
4581 its first parent. Also, only files different from BOTH parents
4553 will appear in files:.
4582 will appear in files:.
4554
4583
4555 .. note::
4584 .. note::
4556
4585
4557 For performance reasons, :hg:`log FILE` may omit duplicate changes
4586 For performance reasons, :hg:`log FILE` may omit duplicate changes
4558 made on branches and will not show removals or mode changes. To
4587 made on branches and will not show removals or mode changes. To
4559 see all such changes, use the --removed switch.
4588 see all such changes, use the --removed switch.
4560
4589
4561 .. container:: verbose
4590 .. container:: verbose
4562
4591
4563 .. note::
4592 .. note::
4564
4593
4565 The history resulting from -L/--line-range options depends on diff
4594 The history resulting from -L/--line-range options depends on diff
4566 options; for instance if white-spaces are ignored, respective changes
4595 options; for instance if white-spaces are ignored, respective changes
4567 with only white-spaces in specified line range will not be listed.
4596 with only white-spaces in specified line range will not be listed.
4568
4597
4569 .. container:: verbose
4598 .. container:: verbose
4570
4599
4571 Some examples:
4600 Some examples:
4572
4601
4573 - changesets with full descriptions and file lists::
4602 - changesets with full descriptions and file lists::
4574
4603
4575 hg log -v
4604 hg log -v
4576
4605
4577 - changesets ancestral to the working directory::
4606 - changesets ancestral to the working directory::
4578
4607
4579 hg log -f
4608 hg log -f
4580
4609
4581 - last 10 commits on the current branch::
4610 - last 10 commits on the current branch::
4582
4611
4583 hg log -l 10 -b .
4612 hg log -l 10 -b .
4584
4613
4585 - changesets showing all modifications of a file, including removals::
4614 - changesets showing all modifications of a file, including removals::
4586
4615
4587 hg log --removed file.c
4616 hg log --removed file.c
4588
4617
4589 - all changesets that touch a directory, with diffs, excluding merges::
4618 - all changesets that touch a directory, with diffs, excluding merges::
4590
4619
4591 hg log -Mp lib/
4620 hg log -Mp lib/
4592
4621
4593 - all revision numbers that match a keyword::
4622 - all revision numbers that match a keyword::
4594
4623
4595 hg log -k bug --template "{rev}\\n"
4624 hg log -k bug --template "{rev}\\n"
4596
4625
4597 - the full hash identifier of the working directory parent::
4626 - the full hash identifier of the working directory parent::
4598
4627
4599 hg log -r . --template "{node}\\n"
4628 hg log -r . --template "{node}\\n"
4600
4629
4601 - list available log templates::
4630 - list available log templates::
4602
4631
4603 hg log -T list
4632 hg log -T list
4604
4633
4605 - check if a given changeset is included in a tagged release::
4634 - check if a given changeset is included in a tagged release::
4606
4635
4607 hg log -r "a21ccf and ancestor(1.9)"
4636 hg log -r "a21ccf and ancestor(1.9)"
4608
4637
4609 - find all changesets by some user in a date range::
4638 - find all changesets by some user in a date range::
4610
4639
4611 hg log -k alice -d "may 2008 to jul 2008"
4640 hg log -k alice -d "may 2008 to jul 2008"
4612
4641
4613 - summary of all changesets after the last tag::
4642 - summary of all changesets after the last tag::
4614
4643
4615 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4644 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4616
4645
4617 - changesets touching lines 13 to 23 for file.c::
4646 - changesets touching lines 13 to 23 for file.c::
4618
4647
4619 hg log -L file.c,13:23
4648 hg log -L file.c,13:23
4620
4649
4621 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4650 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4622 main.c with patch::
4651 main.c with patch::
4623
4652
4624 hg log -L file.c,13:23 -L main.c,2:6 -p
4653 hg log -L file.c,13:23 -L main.c,2:6 -p
4625
4654
4626 See :hg:`help dates` for a list of formats valid for -d/--date.
4655 See :hg:`help dates` for a list of formats valid for -d/--date.
4627
4656
4628 See :hg:`help revisions` for more about specifying and ordering
4657 See :hg:`help revisions` for more about specifying and ordering
4629 revisions.
4658 revisions.
4630
4659
4631 See :hg:`help templates` for more about pre-packaged styles and
4660 See :hg:`help templates` for more about pre-packaged styles and
4632 specifying custom templates. The default template used by the log
4661 specifying custom templates. The default template used by the log
4633 command can be customized via the ``command-templates.log`` configuration
4662 command can be customized via the ``command-templates.log`` configuration
4634 setting.
4663 setting.
4635
4664
4636 Returns 0 on success.
4665 Returns 0 on success.
4637
4666
4638 """
4667 """
4639 opts = pycompat.byteskwargs(opts)
4668 opts = pycompat.byteskwargs(opts)
4640 linerange = opts.get(b'line_range')
4669 linerange = opts.get(b'line_range')
4641
4670
4642 if linerange and not opts.get(b'follow'):
4671 if linerange and not opts.get(b'follow'):
4643 raise error.InputError(_(b'--line-range requires --follow'))
4672 raise error.InputError(_(b'--line-range requires --follow'))
4644
4673
4645 if linerange and pats:
4674 if linerange and pats:
4646 # TODO: take pats as patterns with no line-range filter
4675 # TODO: take pats as patterns with no line-range filter
4647 raise error.InputError(
4676 raise error.InputError(
4648 _(b'FILE arguments are not compatible with --line-range option')
4677 _(b'FILE arguments are not compatible with --line-range option')
4649 )
4678 )
4650
4679
4651 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4680 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4652 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4681 walk_opts = logcmdutil.parseopts(ui, pats, opts)
4653 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4682 revs, differ = logcmdutil.getrevs(repo, walk_opts)
4654 if linerange:
4683 if linerange:
4655 # TODO: should follow file history from logcmdutil._initialrevs(),
4684 # TODO: should follow file history from logcmdutil._initialrevs(),
4656 # then filter the result by logcmdutil._makerevset() and --limit
4685 # then filter the result by logcmdutil._makerevset() and --limit
4657 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4686 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4658
4687
4659 getcopies = None
4688 getcopies = None
4660 if opts.get(b'copies'):
4689 if opts.get(b'copies'):
4661 endrev = None
4690 endrev = None
4662 if revs:
4691 if revs:
4663 endrev = revs.max() + 1
4692 endrev = revs.max() + 1
4664 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4693 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4665
4694
4666 ui.pager(b'log')
4695 ui.pager(b'log')
4667 displayer = logcmdutil.changesetdisplayer(
4696 displayer = logcmdutil.changesetdisplayer(
4668 ui, repo, opts, differ, buffered=True
4697 ui, repo, opts, differ, buffered=True
4669 )
4698 )
4670 if opts.get(b'graph'):
4699 if opts.get(b'graph'):
4671 displayfn = logcmdutil.displaygraphrevs
4700 displayfn = logcmdutil.displaygraphrevs
4672 else:
4701 else:
4673 displayfn = logcmdutil.displayrevs
4702 displayfn = logcmdutil.displayrevs
4674 displayfn(ui, repo, revs, displayer, getcopies)
4703 displayfn(ui, repo, revs, displayer, getcopies)
4675
4704
4676
4705
4677 @command(
4706 @command(
4678 b'manifest',
4707 b'manifest',
4679 [
4708 [
4680 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4709 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4681 (b'', b'all', False, _(b"list files from all revisions")),
4710 (b'', b'all', False, _(b"list files from all revisions")),
4682 ]
4711 ]
4683 + formatteropts,
4712 + formatteropts,
4684 _(b'[-r REV]'),
4713 _(b'[-r REV]'),
4685 helpcategory=command.CATEGORY_MAINTENANCE,
4714 helpcategory=command.CATEGORY_MAINTENANCE,
4686 intents={INTENT_READONLY},
4715 intents={INTENT_READONLY},
4687 )
4716 )
4688 def manifest(ui, repo, node=None, rev=None, **opts):
4717 def manifest(ui, repo, node=None, rev=None, **opts):
4689 """output the current or given revision of the project manifest
4718 """output the current or given revision of the project manifest
4690
4719
4691 Print a list of version controlled files for the given revision.
4720 Print a list of version controlled files for the given revision.
4692 If no revision is given, the first parent of the working directory
4721 If no revision is given, the first parent of the working directory
4693 is used, or the null revision if no revision is checked out.
4722 is used, or the null revision if no revision is checked out.
4694
4723
4695 With -v, print file permissions, symlink and executable bits.
4724 With -v, print file permissions, symlink and executable bits.
4696 With --debug, print file revision hashes.
4725 With --debug, print file revision hashes.
4697
4726
4698 If option --all is specified, the list of all files from all revisions
4727 If option --all is specified, the list of all files from all revisions
4699 is printed. This includes deleted and renamed files.
4728 is printed. This includes deleted and renamed files.
4700
4729
4701 Returns 0 on success.
4730 Returns 0 on success.
4702 """
4731 """
4703 opts = pycompat.byteskwargs(opts)
4732 opts = pycompat.byteskwargs(opts)
4704 fm = ui.formatter(b'manifest', opts)
4733 fm = ui.formatter(b'manifest', opts)
4705
4734
4706 if opts.get(b'all'):
4735 if opts.get(b'all'):
4707 if rev or node:
4736 if rev or node:
4708 raise error.InputError(_(b"can't specify a revision with --all"))
4737 raise error.InputError(_(b"can't specify a revision with --all"))
4709
4738
4710 res = set()
4739 res = set()
4711 for rev in repo:
4740 for rev in repo:
4712 ctx = repo[rev]
4741 ctx = repo[rev]
4713 res |= set(ctx.files())
4742 res |= set(ctx.files())
4714
4743
4715 ui.pager(b'manifest')
4744 ui.pager(b'manifest')
4716 for f in sorted(res):
4745 for f in sorted(res):
4717 fm.startitem()
4746 fm.startitem()
4718 fm.write(b"path", b'%s\n', f)
4747 fm.write(b"path", b'%s\n', f)
4719 fm.end()
4748 fm.end()
4720 return
4749 return
4721
4750
4722 if rev and node:
4751 if rev and node:
4723 raise error.InputError(_(b"please specify just one revision"))
4752 raise error.InputError(_(b"please specify just one revision"))
4724
4753
4725 if not node:
4754 if not node:
4726 node = rev
4755 node = rev
4727
4756
4728 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4757 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4729 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4758 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4730 if node:
4759 if node:
4731 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4760 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4732 ctx = scmutil.revsingle(repo, node)
4761 ctx = scmutil.revsingle(repo, node)
4733 mf = ctx.manifest()
4762 mf = ctx.manifest()
4734 ui.pager(b'manifest')
4763 ui.pager(b'manifest')
4735 for f in ctx:
4764 for f in ctx:
4736 fm.startitem()
4765 fm.startitem()
4737 fm.context(ctx=ctx)
4766 fm.context(ctx=ctx)
4738 fl = ctx[f].flags()
4767 fl = ctx[f].flags()
4739 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4768 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4740 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4769 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4741 fm.write(b'path', b'%s\n', f)
4770 fm.write(b'path', b'%s\n', f)
4742 fm.end()
4771 fm.end()
4743
4772
4744
4773
4745 @command(
4774 @command(
4746 b'merge',
4775 b'merge',
4747 [
4776 [
4748 (
4777 (
4749 b'f',
4778 b'f',
4750 b'force',
4779 b'force',
4751 None,
4780 None,
4752 _(b'force a merge including outstanding changes (DEPRECATED)'),
4781 _(b'force a merge including outstanding changes (DEPRECATED)'),
4753 ),
4782 ),
4754 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4783 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4755 (
4784 (
4756 b'P',
4785 b'P',
4757 b'preview',
4786 b'preview',
4758 None,
4787 None,
4759 _(b'review revisions to merge (no merge is performed)'),
4788 _(b'review revisions to merge (no merge is performed)'),
4760 ),
4789 ),
4761 (b'', b'abort', None, _(b'abort the ongoing merge')),
4790 (b'', b'abort', None, _(b'abort the ongoing merge')),
4762 ]
4791 ]
4763 + mergetoolopts,
4792 + mergetoolopts,
4764 _(b'[-P] [[-r] REV]'),
4793 _(b'[-P] [[-r] REV]'),
4765 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4794 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4766 helpbasic=True,
4795 helpbasic=True,
4767 )
4796 )
4768 def merge(ui, repo, node=None, **opts):
4797 def merge(ui, repo, node=None, **opts):
4769 """merge another revision into working directory
4798 """merge another revision into working directory
4770
4799
4771 The current working directory is updated with all changes made in
4800 The current working directory is updated with all changes made in
4772 the requested revision since the last common predecessor revision.
4801 the requested revision since the last common predecessor revision.
4773
4802
4774 Files that changed between either parent are marked as changed for
4803 Files that changed between either parent are marked as changed for
4775 the next commit and a commit must be performed before any further
4804 the next commit and a commit must be performed before any further
4776 updates to the repository are allowed. The next commit will have
4805 updates to the repository are allowed. The next commit will have
4777 two parents.
4806 two parents.
4778
4807
4779 ``--tool`` can be used to specify the merge tool used for file
4808 ``--tool`` can be used to specify the merge tool used for file
4780 merges. It overrides the HGMERGE environment variable and your
4809 merges. It overrides the HGMERGE environment variable and your
4781 configuration files. See :hg:`help merge-tools` for options.
4810 configuration files. See :hg:`help merge-tools` for options.
4782
4811
4783 If no revision is specified, the working directory's parent is a
4812 If no revision is specified, the working directory's parent is a
4784 head revision, and the current branch contains exactly one other
4813 head revision, and the current branch contains exactly one other
4785 head, the other head is merged with by default. Otherwise, an
4814 head, the other head is merged with by default. Otherwise, an
4786 explicit revision with which to merge must be provided.
4815 explicit revision with which to merge must be provided.
4787
4816
4788 See :hg:`help resolve` for information on handling file conflicts.
4817 See :hg:`help resolve` for information on handling file conflicts.
4789
4818
4790 To undo an uncommitted merge, use :hg:`merge --abort` which
4819 To undo an uncommitted merge, use :hg:`merge --abort` which
4791 will check out a clean copy of the original merge parent, losing
4820 will check out a clean copy of the original merge parent, losing
4792 all changes.
4821 all changes.
4793
4822
4794 Returns 0 on success, 1 if there are unresolved files.
4823 Returns 0 on success, 1 if there are unresolved files.
4795 """
4824 """
4796
4825
4797 opts = pycompat.byteskwargs(opts)
4826 opts = pycompat.byteskwargs(opts)
4798 abort = opts.get(b'abort')
4827 abort = opts.get(b'abort')
4799 if abort and repo.dirstate.p2() == nullid:
4828 if abort and repo.dirstate.p2() == nullid:
4800 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4829 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4801 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4830 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4802 if abort:
4831 if abort:
4803 state = cmdutil.getunfinishedstate(repo)
4832 state = cmdutil.getunfinishedstate(repo)
4804 if state and state._opname != b'merge':
4833 if state and state._opname != b'merge':
4805 raise error.StateError(
4834 raise error.StateError(
4806 _(b'cannot abort merge with %s in progress') % (state._opname),
4835 _(b'cannot abort merge with %s in progress') % (state._opname),
4807 hint=state.hint(),
4836 hint=state.hint(),
4808 )
4837 )
4809 if node:
4838 if node:
4810 raise error.InputError(_(b"cannot specify a node with --abort"))
4839 raise error.InputError(_(b"cannot specify a node with --abort"))
4811 return hg.abortmerge(repo.ui, repo)
4840 return hg.abortmerge(repo.ui, repo)
4812
4841
4813 if opts.get(b'rev') and node:
4842 if opts.get(b'rev') and node:
4814 raise error.InputError(_(b"please specify just one revision"))
4843 raise error.InputError(_(b"please specify just one revision"))
4815 if not node:
4844 if not node:
4816 node = opts.get(b'rev')
4845 node = opts.get(b'rev')
4817
4846
4818 if node:
4847 if node:
4819 ctx = scmutil.revsingle(repo, node)
4848 ctx = scmutil.revsingle(repo, node)
4820 else:
4849 else:
4821 if ui.configbool(b'commands', b'merge.require-rev'):
4850 if ui.configbool(b'commands', b'merge.require-rev'):
4822 raise error.InputError(
4851 raise error.InputError(
4823 _(
4852 _(
4824 b'configuration requires specifying revision to merge '
4853 b'configuration requires specifying revision to merge '
4825 b'with'
4854 b'with'
4826 )
4855 )
4827 )
4856 )
4828 ctx = repo[destutil.destmerge(repo)]
4857 ctx = repo[destutil.destmerge(repo)]
4829
4858
4830 if ctx.node() is None:
4859 if ctx.node() is None:
4831 raise error.InputError(
4860 raise error.InputError(
4832 _(b'merging with the working copy has no effect')
4861 _(b'merging with the working copy has no effect')
4833 )
4862 )
4834
4863
4835 if opts.get(b'preview'):
4864 if opts.get(b'preview'):
4836 # find nodes that are ancestors of p2 but not of p1
4865 # find nodes that are ancestors of p2 but not of p1
4837 p1 = repo[b'.'].node()
4866 p1 = repo[b'.'].node()
4838 p2 = ctx.node()
4867 p2 = ctx.node()
4839 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4868 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4840
4869
4841 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4870 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4842 for node in nodes:
4871 for node in nodes:
4843 displayer.show(repo[node])
4872 displayer.show(repo[node])
4844 displayer.close()
4873 displayer.close()
4845 return 0
4874 return 0
4846
4875
4847 # ui.forcemerge is an internal variable, do not document
4876 # ui.forcemerge is an internal variable, do not document
4848 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4877 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4849 with ui.configoverride(overrides, b'merge'):
4878 with ui.configoverride(overrides, b'merge'):
4850 force = opts.get(b'force')
4879 force = opts.get(b'force')
4851 labels = [b'working copy', b'merge rev']
4880 labels = [b'working copy', b'merge rev']
4852 return hg.merge(ctx, force=force, labels=labels)
4881 return hg.merge(ctx, force=force, labels=labels)
4853
4882
4854
4883
4855 statemod.addunfinished(
4884 statemod.addunfinished(
4856 b'merge',
4885 b'merge',
4857 fname=None,
4886 fname=None,
4858 clearable=True,
4887 clearable=True,
4859 allowcommit=True,
4888 allowcommit=True,
4860 cmdmsg=_(b'outstanding uncommitted merge'),
4889 cmdmsg=_(b'outstanding uncommitted merge'),
4861 abortfunc=hg.abortmerge,
4890 abortfunc=hg.abortmerge,
4862 statushint=_(
4891 statushint=_(
4863 b'To continue: hg commit\nTo abort: hg merge --abort'
4892 b'To continue: hg commit\nTo abort: hg merge --abort'
4864 ),
4893 ),
4865 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4894 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4866 )
4895 )
4867
4896
4868
4897
4869 @command(
4898 @command(
4870 b'outgoing|out',
4899 b'outgoing|out',
4871 [
4900 [
4872 (
4901 (
4873 b'f',
4902 b'f',
4874 b'force',
4903 b'force',
4875 None,
4904 None,
4876 _(b'run even when the destination is unrelated'),
4905 _(b'run even when the destination is unrelated'),
4877 ),
4906 ),
4878 (
4907 (
4879 b'r',
4908 b'r',
4880 b'rev',
4909 b'rev',
4881 [],
4910 [],
4882 _(b'a changeset intended to be included in the destination'),
4911 _(b'a changeset intended to be included in the destination'),
4883 _(b'REV'),
4912 _(b'REV'),
4884 ),
4913 ),
4885 (b'n', b'newest-first', None, _(b'show newest record first')),
4914 (b'n', b'newest-first', None, _(b'show newest record first')),
4886 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4915 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4887 (
4916 (
4888 b'b',
4917 b'b',
4889 b'branch',
4918 b'branch',
4890 [],
4919 [],
4891 _(b'a specific branch you would like to push'),
4920 _(b'a specific branch you would like to push'),
4892 _(b'BRANCH'),
4921 _(b'BRANCH'),
4893 ),
4922 ),
4894 ]
4923 ]
4895 + logopts
4924 + logopts
4896 + remoteopts
4925 + remoteopts
4897 + subrepoopts,
4926 + subrepoopts,
4898 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4927 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4899 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4928 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4900 )
4929 )
4901 def outgoing(ui, repo, dest=None, **opts):
4930 def outgoing(ui, repo, dest=None, **opts):
4902 """show changesets not found in the destination
4931 """show changesets not found in the destination
4903
4932
4904 Show changesets not found in the specified destination repository
4933 Show changesets not found in the specified destination repository
4905 or the default push location. These are the changesets that would
4934 or the default push location. These are the changesets that would
4906 be pushed if a push was requested.
4935 be pushed if a push was requested.
4907
4936
4908 See pull for details of valid destination formats.
4937 See pull for details of valid destination formats.
4909
4938
4910 .. container:: verbose
4939 .. container:: verbose
4911
4940
4912 With -B/--bookmarks, the result of bookmark comparison between
4941 With -B/--bookmarks, the result of bookmark comparison between
4913 local and remote repositories is displayed. With -v/--verbose,
4942 local and remote repositories is displayed. With -v/--verbose,
4914 status is also displayed for each bookmark like below::
4943 status is also displayed for each bookmark like below::
4915
4944
4916 BM1 01234567890a added
4945 BM1 01234567890a added
4917 BM2 deleted
4946 BM2 deleted
4918 BM3 234567890abc advanced
4947 BM3 234567890abc advanced
4919 BM4 34567890abcd diverged
4948 BM4 34567890abcd diverged
4920 BM5 4567890abcde changed
4949 BM5 4567890abcde changed
4921
4950
4922 The action taken when pushing depends on the
4951 The action taken when pushing depends on the
4923 status of each bookmark:
4952 status of each bookmark:
4924
4953
4925 :``added``: push with ``-B`` will create it
4954 :``added``: push with ``-B`` will create it
4926 :``deleted``: push with ``-B`` will delete it
4955 :``deleted``: push with ``-B`` will delete it
4927 :``advanced``: push will update it
4956 :``advanced``: push will update it
4928 :``diverged``: push with ``-B`` will update it
4957 :``diverged``: push with ``-B`` will update it
4929 :``changed``: push with ``-B`` will update it
4958 :``changed``: push with ``-B`` will update it
4930
4959
4931 From the point of view of pushing behavior, bookmarks
4960 From the point of view of pushing behavior, bookmarks
4932 existing only in the remote repository are treated as
4961 existing only in the remote repository are treated as
4933 ``deleted``, even if it is in fact added remotely.
4962 ``deleted``, even if it is in fact added remotely.
4934
4963
4935 Returns 0 if there are outgoing changes, 1 otherwise.
4964 Returns 0 if there are outgoing changes, 1 otherwise.
4936 """
4965 """
4937 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4966 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4938 # style URLs, so don't overwrite dest.
4967 # style URLs, so don't overwrite dest.
4939 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
4968 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
4940 if not path:
4969 if not path:
4941 raise error.ConfigError(
4970 raise error.ConfigError(
4942 _(b'default repository not configured!'),
4971 _(b'default repository not configured!'),
4943 hint=_(b"see 'hg help config.paths'"),
4972 hint=_(b"see 'hg help config.paths'"),
4944 )
4973 )
4945
4974
4946 opts = pycompat.byteskwargs(opts)
4975 opts = pycompat.byteskwargs(opts)
4947 if opts.get(b'graph'):
4976 if opts.get(b'graph'):
4948 logcmdutil.checkunsupportedgraphflags([], opts)
4977 logcmdutil.checkunsupportedgraphflags([], opts)
4949 o, other = hg._outgoing(ui, repo, dest, opts)
4978 o, other = hg._outgoing(ui, repo, dest, opts)
4950 if not o:
4979 if not o:
4951 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4980 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4952 return
4981 return
4953
4982
4954 revdag = logcmdutil.graphrevs(repo, o, opts)
4983 revdag = logcmdutil.graphrevs(repo, o, opts)
4955 ui.pager(b'outgoing')
4984 ui.pager(b'outgoing')
4956 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4985 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4957 logcmdutil.displaygraph(
4986 logcmdutil.displaygraph(
4958 ui, repo, revdag, displayer, graphmod.asciiedges
4987 ui, repo, revdag, displayer, graphmod.asciiedges
4959 )
4988 )
4960 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4989 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4961 return 0
4990 return 0
4962
4991
4963 if opts.get(b'bookmarks'):
4992 if opts.get(b'bookmarks'):
4964 dest = path.pushloc or path.loc
4993 dest = path.pushloc or path.loc
4965 other = hg.peer(repo, opts, dest)
4994 other = hg.peer(repo, opts, dest)
4966 if b'bookmarks' not in other.listkeys(b'namespaces'):
4995 if b'bookmarks' not in other.listkeys(b'namespaces'):
4967 ui.warn(_(b"remote doesn't support bookmarks\n"))
4996 ui.warn(_(b"remote doesn't support bookmarks\n"))
4968 return 0
4997 return 0
4969 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
4998 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
4970 ui.pager(b'outgoing')
4999 ui.pager(b'outgoing')
4971 return bookmarks.outgoing(ui, repo, other)
5000 return bookmarks.outgoing(ui, repo, other)
4972
5001
4973 repo._subtoppath = path.pushloc or path.loc
5002 repo._subtoppath = path.pushloc or path.loc
4974 try:
5003 try:
4975 return hg.outgoing(ui, repo, dest, opts)
5004 return hg.outgoing(ui, repo, dest, opts)
4976 finally:
5005 finally:
4977 del repo._subtoppath
5006 del repo._subtoppath
4978
5007
4979
5008
4980 @command(
5009 @command(
4981 b'parents',
5010 b'parents',
4982 [
5011 [
4983 (
5012 (
4984 b'r',
5013 b'r',
4985 b'rev',
5014 b'rev',
4986 b'',
5015 b'',
4987 _(b'show parents of the specified revision'),
5016 _(b'show parents of the specified revision'),
4988 _(b'REV'),
5017 _(b'REV'),
4989 ),
5018 ),
4990 ]
5019 ]
4991 + templateopts,
5020 + templateopts,
4992 _(b'[-r REV] [FILE]'),
5021 _(b'[-r REV] [FILE]'),
4993 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5022 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4994 inferrepo=True,
5023 inferrepo=True,
4995 )
5024 )
4996 def parents(ui, repo, file_=None, **opts):
5025 def parents(ui, repo, file_=None, **opts):
4997 """show the parents of the working directory or revision (DEPRECATED)
5026 """show the parents of the working directory or revision (DEPRECATED)
4998
5027
4999 Print the working directory's parent revisions. If a revision is
5028 Print the working directory's parent revisions. If a revision is
5000 given via -r/--rev, the parent of that revision will be printed.
5029 given via -r/--rev, the parent of that revision will be printed.
5001 If a file argument is given, the revision in which the file was
5030 If a file argument is given, the revision in which the file was
5002 last changed (before the working directory revision or the
5031 last changed (before the working directory revision or the
5003 argument to --rev if given) is printed.
5032 argument to --rev if given) is printed.
5004
5033
5005 This command is equivalent to::
5034 This command is equivalent to::
5006
5035
5007 hg log -r "p1()+p2()" or
5036 hg log -r "p1()+p2()" or
5008 hg log -r "p1(REV)+p2(REV)" or
5037 hg log -r "p1(REV)+p2(REV)" or
5009 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5038 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5010 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5039 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5011
5040
5012 See :hg:`summary` and :hg:`help revsets` for related information.
5041 See :hg:`summary` and :hg:`help revsets` for related information.
5013
5042
5014 Returns 0 on success.
5043 Returns 0 on success.
5015 """
5044 """
5016
5045
5017 opts = pycompat.byteskwargs(opts)
5046 opts = pycompat.byteskwargs(opts)
5018 rev = opts.get(b'rev')
5047 rev = opts.get(b'rev')
5019 if rev:
5048 if rev:
5020 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5049 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5021 ctx = scmutil.revsingle(repo, rev, None)
5050 ctx = scmutil.revsingle(repo, rev, None)
5022
5051
5023 if file_:
5052 if file_:
5024 m = scmutil.match(ctx, (file_,), opts)
5053 m = scmutil.match(ctx, (file_,), opts)
5025 if m.anypats() or len(m.files()) != 1:
5054 if m.anypats() or len(m.files()) != 1:
5026 raise error.InputError(_(b'can only specify an explicit filename'))
5055 raise error.InputError(_(b'can only specify an explicit filename'))
5027 file_ = m.files()[0]
5056 file_ = m.files()[0]
5028 filenodes = []
5057 filenodes = []
5029 for cp in ctx.parents():
5058 for cp in ctx.parents():
5030 if not cp:
5059 if not cp:
5031 continue
5060 continue
5032 try:
5061 try:
5033 filenodes.append(cp.filenode(file_))
5062 filenodes.append(cp.filenode(file_))
5034 except error.LookupError:
5063 except error.LookupError:
5035 pass
5064 pass
5036 if not filenodes:
5065 if not filenodes:
5037 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5066 raise error.InputError(_(b"'%s' not found in manifest") % file_)
5038 p = []
5067 p = []
5039 for fn in filenodes:
5068 for fn in filenodes:
5040 fctx = repo.filectx(file_, fileid=fn)
5069 fctx = repo.filectx(file_, fileid=fn)
5041 p.append(fctx.node())
5070 p.append(fctx.node())
5042 else:
5071 else:
5043 p = [cp.node() for cp in ctx.parents()]
5072 p = [cp.node() for cp in ctx.parents()]
5044
5073
5045 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5074 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5046 for n in p:
5075 for n in p:
5047 if n != nullid:
5076 if n != nullid:
5048 displayer.show(repo[n])
5077 displayer.show(repo[n])
5049 displayer.close()
5078 displayer.close()
5050
5079
5051
5080
5052 @command(
5081 @command(
5053 b'paths',
5082 b'paths',
5054 formatteropts,
5083 formatteropts,
5055 _(b'[NAME]'),
5084 _(b'[NAME]'),
5056 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5085 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5057 optionalrepo=True,
5086 optionalrepo=True,
5058 intents={INTENT_READONLY},
5087 intents={INTENT_READONLY},
5059 )
5088 )
5060 def paths(ui, repo, search=None, **opts):
5089 def paths(ui, repo, search=None, **opts):
5061 """show aliases for remote repositories
5090 """show aliases for remote repositories
5062
5091
5063 Show definition of symbolic path name NAME. If no name is given,
5092 Show definition of symbolic path name NAME. If no name is given,
5064 show definition of all available names.
5093 show definition of all available names.
5065
5094
5066 Option -q/--quiet suppresses all output when searching for NAME
5095 Option -q/--quiet suppresses all output when searching for NAME
5067 and shows only the path names when listing all definitions.
5096 and shows only the path names when listing all definitions.
5068
5097
5069 Path names are defined in the [paths] section of your
5098 Path names are defined in the [paths] section of your
5070 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5099 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5071 repository, ``.hg/hgrc`` is used, too.
5100 repository, ``.hg/hgrc`` is used, too.
5072
5101
5073 The path names ``default`` and ``default-push`` have a special
5102 The path names ``default`` and ``default-push`` have a special
5074 meaning. When performing a push or pull operation, they are used
5103 meaning. When performing a push or pull operation, they are used
5075 as fallbacks if no location is specified on the command-line.
5104 as fallbacks if no location is specified on the command-line.
5076 When ``default-push`` is set, it will be used for push and
5105 When ``default-push`` is set, it will be used for push and
5077 ``default`` will be used for pull; otherwise ``default`` is used
5106 ``default`` will be used for pull; otherwise ``default`` is used
5078 as the fallback for both. When cloning a repository, the clone
5107 as the fallback for both. When cloning a repository, the clone
5079 source is written as ``default`` in ``.hg/hgrc``.
5108 source is written as ``default`` in ``.hg/hgrc``.
5080
5109
5081 .. note::
5110 .. note::
5082
5111
5083 ``default`` and ``default-push`` apply to all inbound (e.g.
5112 ``default`` and ``default-push`` apply to all inbound (e.g.
5084 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5113 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5085 and :hg:`bundle`) operations.
5114 and :hg:`bundle`) operations.
5086
5115
5087 See :hg:`help urls` for more information.
5116 See :hg:`help urls` for more information.
5088
5117
5089 .. container:: verbose
5118 .. container:: verbose
5090
5119
5091 Template:
5120 Template:
5092
5121
5093 The following keywords are supported. See also :hg:`help templates`.
5122 The following keywords are supported. See also :hg:`help templates`.
5094
5123
5095 :name: String. Symbolic name of the path alias.
5124 :name: String. Symbolic name of the path alias.
5096 :pushurl: String. URL for push operations.
5125 :pushurl: String. URL for push operations.
5097 :url: String. URL or directory path for the other operations.
5126 :url: String. URL or directory path for the other operations.
5098
5127
5099 Returns 0 on success.
5128 Returns 0 on success.
5100 """
5129 """
5101
5130
5102 opts = pycompat.byteskwargs(opts)
5131 opts = pycompat.byteskwargs(opts)
5103 ui.pager(b'paths')
5132 ui.pager(b'paths')
5104 if search:
5133 if search:
5105 pathitems = [
5134 pathitems = [
5106 (name, path)
5135 (name, path)
5107 for name, path in pycompat.iteritems(ui.paths)
5136 for name, path in pycompat.iteritems(ui.paths)
5108 if name == search
5137 if name == search
5109 ]
5138 ]
5110 else:
5139 else:
5111 pathitems = sorted(pycompat.iteritems(ui.paths))
5140 pathitems = sorted(pycompat.iteritems(ui.paths))
5112
5141
5113 fm = ui.formatter(b'paths', opts)
5142 fm = ui.formatter(b'paths', opts)
5114 if fm.isplain():
5143 if fm.isplain():
5115 hidepassword = util.hidepassword
5144 hidepassword = util.hidepassword
5116 else:
5145 else:
5117 hidepassword = bytes
5146 hidepassword = bytes
5118 if ui.quiet:
5147 if ui.quiet:
5119 namefmt = b'%s\n'
5148 namefmt = b'%s\n'
5120 else:
5149 else:
5121 namefmt = b'%s = '
5150 namefmt = b'%s = '
5122 showsubopts = not search and not ui.quiet
5151 showsubopts = not search and not ui.quiet
5123
5152
5124 for name, path in pathitems:
5153 for name, path in pathitems:
5125 fm.startitem()
5154 fm.startitem()
5126 fm.condwrite(not search, b'name', namefmt, name)
5155 fm.condwrite(not search, b'name', namefmt, name)
5127 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5156 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5128 for subopt, value in sorted(path.suboptions.items()):
5157 for subopt, value in sorted(path.suboptions.items()):
5129 assert subopt not in (b'name', b'url')
5158 assert subopt not in (b'name', b'url')
5130 if showsubopts:
5159 if showsubopts:
5131 fm.plain(b'%s:%s = ' % (name, subopt))
5160 fm.plain(b'%s:%s = ' % (name, subopt))
5132 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5161 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5133
5162
5134 fm.end()
5163 fm.end()
5135
5164
5136 if search and not pathitems:
5165 if search and not pathitems:
5137 if not ui.quiet:
5166 if not ui.quiet:
5138 ui.warn(_(b"not found!\n"))
5167 ui.warn(_(b"not found!\n"))
5139 return 1
5168 return 1
5140 else:
5169 else:
5141 return 0
5170 return 0
5142
5171
5143
5172
5144 @command(
5173 @command(
5145 b'phase',
5174 b'phase',
5146 [
5175 [
5147 (b'p', b'public', False, _(b'set changeset phase to public')),
5176 (b'p', b'public', False, _(b'set changeset phase to public')),
5148 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5177 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5149 (b's', b'secret', False, _(b'set changeset phase to secret')),
5178 (b's', b'secret', False, _(b'set changeset phase to secret')),
5150 (b'f', b'force', False, _(b'allow to move boundary backward')),
5179 (b'f', b'force', False, _(b'allow to move boundary backward')),
5151 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5180 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5152 ],
5181 ],
5153 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5182 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5154 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5183 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5155 )
5184 )
5156 def phase(ui, repo, *revs, **opts):
5185 def phase(ui, repo, *revs, **opts):
5157 """set or show the current phase name
5186 """set or show the current phase name
5158
5187
5159 With no argument, show the phase name of the current revision(s).
5188 With no argument, show the phase name of the current revision(s).
5160
5189
5161 With one of -p/--public, -d/--draft or -s/--secret, change the
5190 With one of -p/--public, -d/--draft or -s/--secret, change the
5162 phase value of the specified revisions.
5191 phase value of the specified revisions.
5163
5192
5164 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5193 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5165 lower phase to a higher phase. Phases are ordered as follows::
5194 lower phase to a higher phase. Phases are ordered as follows::
5166
5195
5167 public < draft < secret
5196 public < draft < secret
5168
5197
5169 Returns 0 on success, 1 if some phases could not be changed.
5198 Returns 0 on success, 1 if some phases could not be changed.
5170
5199
5171 (For more information about the phases concept, see :hg:`help phases`.)
5200 (For more information about the phases concept, see :hg:`help phases`.)
5172 """
5201 """
5173 opts = pycompat.byteskwargs(opts)
5202 opts = pycompat.byteskwargs(opts)
5174 # search for a unique phase argument
5203 # search for a unique phase argument
5175 targetphase = None
5204 targetphase = None
5176 for idx, name in enumerate(phases.cmdphasenames):
5205 for idx, name in enumerate(phases.cmdphasenames):
5177 if opts[name]:
5206 if opts[name]:
5178 if targetphase is not None:
5207 if targetphase is not None:
5179 raise error.InputError(_(b'only one phase can be specified'))
5208 raise error.InputError(_(b'only one phase can be specified'))
5180 targetphase = idx
5209 targetphase = idx
5181
5210
5182 # look for specified revision
5211 # look for specified revision
5183 revs = list(revs)
5212 revs = list(revs)
5184 revs.extend(opts[b'rev'])
5213 revs.extend(opts[b'rev'])
5185 if not revs:
5214 if not revs:
5186 # display both parents as the second parent phase can influence
5215 # display both parents as the second parent phase can influence
5187 # the phase of a merge commit
5216 # the phase of a merge commit
5188 revs = [c.rev() for c in repo[None].parents()]
5217 revs = [c.rev() for c in repo[None].parents()]
5189
5218
5190 revs = scmutil.revrange(repo, revs)
5219 revs = scmutil.revrange(repo, revs)
5191
5220
5192 ret = 0
5221 ret = 0
5193 if targetphase is None:
5222 if targetphase is None:
5194 # display
5223 # display
5195 for r in revs:
5224 for r in revs:
5196 ctx = repo[r]
5225 ctx = repo[r]
5197 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5226 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5198 else:
5227 else:
5199 with repo.lock(), repo.transaction(b"phase") as tr:
5228 with repo.lock(), repo.transaction(b"phase") as tr:
5200 # set phase
5229 # set phase
5201 if not revs:
5230 if not revs:
5202 raise error.InputError(_(b'empty revision set'))
5231 raise error.InputError(_(b'empty revision set'))
5203 nodes = [repo[r].node() for r in revs]
5232 nodes = [repo[r].node() for r in revs]
5204 # moving revision from public to draft may hide them
5233 # moving revision from public to draft may hide them
5205 # We have to check result on an unfiltered repository
5234 # We have to check result on an unfiltered repository
5206 unfi = repo.unfiltered()
5235 unfi = repo.unfiltered()
5207 getphase = unfi._phasecache.phase
5236 getphase = unfi._phasecache.phase
5208 olddata = [getphase(unfi, r) for r in unfi]
5237 olddata = [getphase(unfi, r) for r in unfi]
5209 phases.advanceboundary(repo, tr, targetphase, nodes)
5238 phases.advanceboundary(repo, tr, targetphase, nodes)
5210 if opts[b'force']:
5239 if opts[b'force']:
5211 phases.retractboundary(repo, tr, targetphase, nodes)
5240 phases.retractboundary(repo, tr, targetphase, nodes)
5212 getphase = unfi._phasecache.phase
5241 getphase = unfi._phasecache.phase
5213 newdata = [getphase(unfi, r) for r in unfi]
5242 newdata = [getphase(unfi, r) for r in unfi]
5214 changes = sum(newdata[r] != olddata[r] for r in unfi)
5243 changes = sum(newdata[r] != olddata[r] for r in unfi)
5215 cl = unfi.changelog
5244 cl = unfi.changelog
5216 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5245 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5217 if rejected:
5246 if rejected:
5218 ui.warn(
5247 ui.warn(
5219 _(
5248 _(
5220 b'cannot move %i changesets to a higher '
5249 b'cannot move %i changesets to a higher '
5221 b'phase, use --force\n'
5250 b'phase, use --force\n'
5222 )
5251 )
5223 % len(rejected)
5252 % len(rejected)
5224 )
5253 )
5225 ret = 1
5254 ret = 1
5226 if changes:
5255 if changes:
5227 msg = _(b'phase changed for %i changesets\n') % changes
5256 msg = _(b'phase changed for %i changesets\n') % changes
5228 if ret:
5257 if ret:
5229 ui.status(msg)
5258 ui.status(msg)
5230 else:
5259 else:
5231 ui.note(msg)
5260 ui.note(msg)
5232 else:
5261 else:
5233 ui.warn(_(b'no phases changed\n'))
5262 ui.warn(_(b'no phases changed\n'))
5234 return ret
5263 return ret
5235
5264
5236
5265
5237 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5266 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5238 """Run after a changegroup has been added via pull/unbundle
5267 """Run after a changegroup has been added via pull/unbundle
5239
5268
5240 This takes arguments below:
5269 This takes arguments below:
5241
5270
5242 :modheads: change of heads by pull/unbundle
5271 :modheads: change of heads by pull/unbundle
5243 :optupdate: updating working directory is needed or not
5272 :optupdate: updating working directory is needed or not
5244 :checkout: update destination revision (or None to default destination)
5273 :checkout: update destination revision (or None to default destination)
5245 :brev: a name, which might be a bookmark to be activated after updating
5274 :brev: a name, which might be a bookmark to be activated after updating
5246 """
5275 """
5247 if modheads == 0:
5276 if modheads == 0:
5248 return
5277 return
5249 if optupdate:
5278 if optupdate:
5250 try:
5279 try:
5251 return hg.updatetotally(ui, repo, checkout, brev)
5280 return hg.updatetotally(ui, repo, checkout, brev)
5252 except error.UpdateAbort as inst:
5281 except error.UpdateAbort as inst:
5253 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5282 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5254 hint = inst.hint
5283 hint = inst.hint
5255 raise error.UpdateAbort(msg, hint=hint)
5284 raise error.UpdateAbort(msg, hint=hint)
5256 if modheads is not None and modheads > 1:
5285 if modheads is not None and modheads > 1:
5257 currentbranchheads = len(repo.branchheads())
5286 currentbranchheads = len(repo.branchheads())
5258 if currentbranchheads == modheads:
5287 if currentbranchheads == modheads:
5259 ui.status(
5288 ui.status(
5260 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5289 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5261 )
5290 )
5262 elif currentbranchheads > 1:
5291 elif currentbranchheads > 1:
5263 ui.status(
5292 ui.status(
5264 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5293 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5265 )
5294 )
5266 else:
5295 else:
5267 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5296 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5268 elif not ui.configbool(b'commands', b'update.requiredest'):
5297 elif not ui.configbool(b'commands', b'update.requiredest'):
5269 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5298 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5270
5299
5271
5300
5272 @command(
5301 @command(
5273 b'pull',
5302 b'pull',
5274 [
5303 [
5275 (
5304 (
5276 b'u',
5305 b'u',
5277 b'update',
5306 b'update',
5278 None,
5307 None,
5279 _(b'update to new branch head if new descendants were pulled'),
5308 _(b'update to new branch head if new descendants were pulled'),
5280 ),
5309 ),
5281 (
5310 (
5282 b'f',
5311 b'f',
5283 b'force',
5312 b'force',
5284 None,
5313 None,
5285 _(b'run even when remote repository is unrelated'),
5314 _(b'run even when remote repository is unrelated'),
5286 ),
5315 ),
5287 (
5316 (
5288 b'',
5317 b'',
5289 b'confirm',
5318 b'confirm',
5290 None,
5319 None,
5291 _(b'confirm pull before applying changes'),
5320 _(b'confirm pull before applying changes'),
5292 ),
5321 ),
5293 (
5322 (
5294 b'r',
5323 b'r',
5295 b'rev',
5324 b'rev',
5296 [],
5325 [],
5297 _(b'a remote changeset intended to be added'),
5326 _(b'a remote changeset intended to be added'),
5298 _(b'REV'),
5327 _(b'REV'),
5299 ),
5328 ),
5300 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5329 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5301 (
5330 (
5302 b'b',
5331 b'b',
5303 b'branch',
5332 b'branch',
5304 [],
5333 [],
5305 _(b'a specific branch you would like to pull'),
5334 _(b'a specific branch you would like to pull'),
5306 _(b'BRANCH'),
5335 _(b'BRANCH'),
5307 ),
5336 ),
5308 ]
5337 ]
5309 + remoteopts,
5338 + remoteopts,
5310 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
5339 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
5311 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5340 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5312 helpbasic=True,
5341 helpbasic=True,
5313 )
5342 )
5314 def pull(ui, repo, source=b"default", **opts):
5343 def pull(ui, repo, source=b"default", **opts):
5315 """pull changes from the specified source
5344 """pull changes from the specified source
5316
5345
5317 Pull changes from a remote repository to a local one.
5346 Pull changes from a remote repository to a local one.
5318
5347
5319 This finds all changes from the repository at the specified path
5348 This finds all changes from the repository at the specified path
5320 or URL and adds them to a local repository (the current one unless
5349 or URL and adds them to a local repository (the current one unless
5321 -R is specified). By default, this does not update the copy of the
5350 -R is specified). By default, this does not update the copy of the
5322 project in the working directory.
5351 project in the working directory.
5323
5352
5324 When cloning from servers that support it, Mercurial may fetch
5353 When cloning from servers that support it, Mercurial may fetch
5325 pre-generated data. When this is done, hooks operating on incoming
5354 pre-generated data. When this is done, hooks operating on incoming
5326 changesets and changegroups may fire more than once, once for each
5355 changesets and changegroups may fire more than once, once for each
5327 pre-generated bundle and as well as for any additional remaining
5356 pre-generated bundle and as well as for any additional remaining
5328 data. See :hg:`help -e clonebundles` for more.
5357 data. See :hg:`help -e clonebundles` for more.
5329
5358
5330 Use :hg:`incoming` if you want to see what would have been added
5359 Use :hg:`incoming` if you want to see what would have been added
5331 by a pull at the time you issued this command. If you then decide
5360 by a pull at the time you issued this command. If you then decide
5332 to add those changes to the repository, you should use :hg:`pull
5361 to add those changes to the repository, you should use :hg:`pull
5333 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5362 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5334
5363
5335 If SOURCE is omitted, the 'default' path will be used.
5364 If SOURCE is omitted, the 'default' path will be used.
5336 See :hg:`help urls` for more information.
5365 See :hg:`help urls` for more information.
5337
5366
5338 Specifying bookmark as ``.`` is equivalent to specifying the active
5367 Specifying bookmark as ``.`` is equivalent to specifying the active
5339 bookmark's name.
5368 bookmark's name.
5340
5369
5341 Returns 0 on success, 1 if an update had unresolved files.
5370 Returns 0 on success, 1 if an update had unresolved files.
5342 """
5371 """
5343
5372
5344 opts = pycompat.byteskwargs(opts)
5373 opts = pycompat.byteskwargs(opts)
5345 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5374 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5346 b'update'
5375 b'update'
5347 ):
5376 ):
5348 msg = _(b'update destination required by configuration')
5377 msg = _(b'update destination required by configuration')
5349 hint = _(b'use hg pull followed by hg update DEST')
5378 hint = _(b'use hg pull followed by hg update DEST')
5350 raise error.InputError(msg, hint=hint)
5379 raise error.InputError(msg, hint=hint)
5351
5380
5352 source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
5381 source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
5353 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5382 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5354 ui.flush()
5383 ui.flush()
5355 other = hg.peer(repo, opts, source)
5384 other = hg.peer(repo, opts, source)
5356 try:
5385 try:
5357 revs, checkout = hg.addbranchrevs(
5386 revs, checkout = hg.addbranchrevs(
5358 repo, other, branches, opts.get(b'rev')
5387 repo, other, branches, opts.get(b'rev')
5359 )
5388 )
5360
5389
5361 pullopargs = {}
5390 pullopargs = {}
5362
5391
5363 nodes = None
5392 nodes = None
5364 if opts.get(b'bookmark') or revs:
5393 if opts.get(b'bookmark') or revs:
5365 # The list of bookmark used here is the same used to actually update
5394 # The list of bookmark used here is the same used to actually update
5366 # the bookmark names, to avoid the race from issue 4689 and we do
5395 # the bookmark names, to avoid the race from issue 4689 and we do
5367 # all lookup and bookmark queries in one go so they see the same
5396 # all lookup and bookmark queries in one go so they see the same
5368 # version of the server state (issue 4700).
5397 # version of the server state (issue 4700).
5369 nodes = []
5398 nodes = []
5370 fnodes = []
5399 fnodes = []
5371 revs = revs or []
5400 revs = revs or []
5372 if revs and not other.capable(b'lookup'):
5401 if revs and not other.capable(b'lookup'):
5373 err = _(
5402 err = _(
5374 b"other repository doesn't support revision lookup, "
5403 b"other repository doesn't support revision lookup, "
5375 b"so a rev cannot be specified."
5404 b"so a rev cannot be specified."
5376 )
5405 )
5377 raise error.Abort(err)
5406 raise error.Abort(err)
5378 with other.commandexecutor() as e:
5407 with other.commandexecutor() as e:
5379 fremotebookmarks = e.callcommand(
5408 fremotebookmarks = e.callcommand(
5380 b'listkeys', {b'namespace': b'bookmarks'}
5409 b'listkeys', {b'namespace': b'bookmarks'}
5381 )
5410 )
5382 for r in revs:
5411 for r in revs:
5383 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5412 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5384 remotebookmarks = fremotebookmarks.result()
5413 remotebookmarks = fremotebookmarks.result()
5385 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5414 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5386 pullopargs[b'remotebookmarks'] = remotebookmarks
5415 pullopargs[b'remotebookmarks'] = remotebookmarks
5387 for b in opts.get(b'bookmark', []):
5416 for b in opts.get(b'bookmark', []):
5388 b = repo._bookmarks.expandname(b)
5417 b = repo._bookmarks.expandname(b)
5389 if b not in remotebookmarks:
5418 if b not in remotebookmarks:
5390 raise error.InputError(
5419 raise error.InputError(
5391 _(b'remote bookmark %s not found!') % b
5420 _(b'remote bookmark %s not found!') % b
5392 )
5421 )
5393 nodes.append(remotebookmarks[b])
5422 nodes.append(remotebookmarks[b])
5394 for i, rev in enumerate(revs):
5423 for i, rev in enumerate(revs):
5395 node = fnodes[i].result()
5424 node = fnodes[i].result()
5396 nodes.append(node)
5425 nodes.append(node)
5397 if rev == checkout:
5426 if rev == checkout:
5398 checkout = node
5427 checkout = node
5399
5428
5400 wlock = util.nullcontextmanager()
5429 wlock = util.nullcontextmanager()
5401 if opts.get(b'update'):
5430 if opts.get(b'update'):
5402 wlock = repo.wlock()
5431 wlock = repo.wlock()
5403 with wlock:
5432 with wlock:
5404 pullopargs.update(opts.get(b'opargs', {}))
5433 pullopargs.update(opts.get(b'opargs', {}))
5405 modheads = exchange.pull(
5434 modheads = exchange.pull(
5406 repo,
5435 repo,
5407 other,
5436 other,
5408 heads=nodes,
5437 heads=nodes,
5409 force=opts.get(b'force'),
5438 force=opts.get(b'force'),
5410 bookmarks=opts.get(b'bookmark', ()),
5439 bookmarks=opts.get(b'bookmark', ()),
5411 opargs=pullopargs,
5440 opargs=pullopargs,
5412 confirm=opts.get(b'confirm'),
5441 confirm=opts.get(b'confirm'),
5413 ).cgresult
5442 ).cgresult
5414
5443
5415 # brev is a name, which might be a bookmark to be activated at
5444 # brev is a name, which might be a bookmark to be activated at
5416 # the end of the update. In other words, it is an explicit
5445 # the end of the update. In other words, it is an explicit
5417 # destination of the update
5446 # destination of the update
5418 brev = None
5447 brev = None
5419
5448
5420 if checkout:
5449 if checkout:
5421 checkout = repo.unfiltered().changelog.rev(checkout)
5450 checkout = repo.unfiltered().changelog.rev(checkout)
5422
5451
5423 # order below depends on implementation of
5452 # order below depends on implementation of
5424 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5453 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5425 # because 'checkout' is determined without it.
5454 # because 'checkout' is determined without it.
5426 if opts.get(b'rev'):
5455 if opts.get(b'rev'):
5427 brev = opts[b'rev'][0]
5456 brev = opts[b'rev'][0]
5428 elif opts.get(b'branch'):
5457 elif opts.get(b'branch'):
5429 brev = opts[b'branch'][0]
5458 brev = opts[b'branch'][0]
5430 else:
5459 else:
5431 brev = branches[0]
5460 brev = branches[0]
5432 repo._subtoppath = source
5461 repo._subtoppath = source
5433 try:
5462 try:
5434 ret = postincoming(
5463 ret = postincoming(
5435 ui, repo, modheads, opts.get(b'update'), checkout, brev
5464 ui, repo, modheads, opts.get(b'update'), checkout, brev
5436 )
5465 )
5437 except error.FilteredRepoLookupError as exc:
5466 except error.FilteredRepoLookupError as exc:
5438 msg = _(b'cannot update to target: %s') % exc.args[0]
5467 msg = _(b'cannot update to target: %s') % exc.args[0]
5439 exc.args = (msg,) + exc.args[1:]
5468 exc.args = (msg,) + exc.args[1:]
5440 raise
5469 raise
5441 finally:
5470 finally:
5442 del repo._subtoppath
5471 del repo._subtoppath
5443
5472
5444 finally:
5473 finally:
5445 other.close()
5474 other.close()
5446 return ret
5475 return ret
5447
5476
5448
5477
5449 @command(
5478 @command(
5450 b'purge|clean',
5479 b'purge|clean',
5451 [
5480 [
5452 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5481 (b'a', b'abort-on-err', None, _(b'abort if an error occurs')),
5453 (b'', b'all', None, _(b'purge ignored files too')),
5482 (b'', b'all', None, _(b'purge ignored files too')),
5454 (b'i', b'ignored', None, _(b'purge only ignored files')),
5483 (b'i', b'ignored', None, _(b'purge only ignored files')),
5455 (b'', b'dirs', None, _(b'purge empty directories')),
5484 (b'', b'dirs', None, _(b'purge empty directories')),
5456 (b'', b'files', None, _(b'purge files')),
5485 (b'', b'files', None, _(b'purge files')),
5457 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5486 (b'p', b'print', None, _(b'print filenames instead of deleting them')),
5458 (
5487 (
5459 b'0',
5488 b'0',
5460 b'print0',
5489 b'print0',
5461 None,
5490 None,
5462 _(
5491 _(
5463 b'end filenames with NUL, for use with xargs'
5492 b'end filenames with NUL, for use with xargs'
5464 b' (implies -p/--print)'
5493 b' (implies -p/--print)'
5465 ),
5494 ),
5466 ),
5495 ),
5467 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5496 (b'', b'confirm', None, _(b'ask before permanently deleting files')),
5468 ]
5497 ]
5469 + cmdutil.walkopts,
5498 + cmdutil.walkopts,
5470 _(b'hg purge [OPTION]... [DIR]...'),
5499 _(b'hg purge [OPTION]... [DIR]...'),
5471 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5500 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5472 )
5501 )
5473 def purge(ui, repo, *dirs, **opts):
5502 def purge(ui, repo, *dirs, **opts):
5474 """removes files not tracked by Mercurial
5503 """removes files not tracked by Mercurial
5475
5504
5476 Delete files not known to Mercurial. This is useful to test local
5505 Delete files not known to Mercurial. This is useful to test local
5477 and uncommitted changes in an otherwise-clean source tree.
5506 and uncommitted changes in an otherwise-clean source tree.
5478
5507
5479 This means that purge will delete the following by default:
5508 This means that purge will delete the following by default:
5480
5509
5481 - Unknown files: files marked with "?" by :hg:`status`
5510 - Unknown files: files marked with "?" by :hg:`status`
5482 - Empty directories: in fact Mercurial ignores directories unless
5511 - Empty directories: in fact Mercurial ignores directories unless
5483 they contain files under source control management
5512 they contain files under source control management
5484
5513
5485 But it will leave untouched:
5514 But it will leave untouched:
5486
5515
5487 - Modified and unmodified tracked files
5516 - Modified and unmodified tracked files
5488 - Ignored files (unless -i or --all is specified)
5517 - Ignored files (unless -i or --all is specified)
5489 - New files added to the repository (with :hg:`add`)
5518 - New files added to the repository (with :hg:`add`)
5490
5519
5491 The --files and --dirs options can be used to direct purge to delete
5520 The --files and --dirs options can be used to direct purge to delete
5492 only files, only directories, or both. If neither option is given,
5521 only files, only directories, or both. If neither option is given,
5493 both will be deleted.
5522 both will be deleted.
5494
5523
5495 If directories are given on the command line, only files in these
5524 If directories are given on the command line, only files in these
5496 directories are considered.
5525 directories are considered.
5497
5526
5498 Be careful with purge, as you could irreversibly delete some files
5527 Be careful with purge, as you could irreversibly delete some files
5499 you forgot to add to the repository. If you only want to print the
5528 you forgot to add to the repository. If you only want to print the
5500 list of files that this program would delete, use the --print
5529 list of files that this program would delete, use the --print
5501 option.
5530 option.
5502 """
5531 """
5503 opts = pycompat.byteskwargs(opts)
5532 opts = pycompat.byteskwargs(opts)
5504 cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
5533 cmdutil.check_at_most_one_arg(opts, b'all', b'ignored')
5505
5534
5506 act = not opts.get(b'print')
5535 act = not opts.get(b'print')
5507 eol = b'\n'
5536 eol = b'\n'
5508 if opts.get(b'print0'):
5537 if opts.get(b'print0'):
5509 eol = b'\0'
5538 eol = b'\0'
5510 act = False # --print0 implies --print
5539 act = False # --print0 implies --print
5511 if opts.get(b'all', False):
5540 if opts.get(b'all', False):
5512 ignored = True
5541 ignored = True
5513 unknown = True
5542 unknown = True
5514 else:
5543 else:
5515 ignored = opts.get(b'ignored', False)
5544 ignored = opts.get(b'ignored', False)
5516 unknown = not ignored
5545 unknown = not ignored
5517
5546
5518 removefiles = opts.get(b'files')
5547 removefiles = opts.get(b'files')
5519 removedirs = opts.get(b'dirs')
5548 removedirs = opts.get(b'dirs')
5520 confirm = opts.get(b'confirm')
5549 confirm = opts.get(b'confirm')
5521 if confirm is None:
5550 if confirm is None:
5522 try:
5551 try:
5523 extensions.find(b'purge')
5552 extensions.find(b'purge')
5524 confirm = False
5553 confirm = False
5525 except KeyError:
5554 except KeyError:
5526 confirm = True
5555 confirm = True
5527
5556
5528 if not removefiles and not removedirs:
5557 if not removefiles and not removedirs:
5529 removefiles = True
5558 removefiles = True
5530 removedirs = True
5559 removedirs = True
5531
5560
5532 match = scmutil.match(repo[None], dirs, opts)
5561 match = scmutil.match(repo[None], dirs, opts)
5533
5562
5534 paths = mergemod.purge(
5563 paths = mergemod.purge(
5535 repo,
5564 repo,
5536 match,
5565 match,
5537 unknown=unknown,
5566 unknown=unknown,
5538 ignored=ignored,
5567 ignored=ignored,
5539 removeemptydirs=removedirs,
5568 removeemptydirs=removedirs,
5540 removefiles=removefiles,
5569 removefiles=removefiles,
5541 abortonerror=opts.get(b'abort_on_err'),
5570 abortonerror=opts.get(b'abort_on_err'),
5542 noop=not act,
5571 noop=not act,
5543 confirm=confirm,
5572 confirm=confirm,
5544 )
5573 )
5545
5574
5546 for path in paths:
5575 for path in paths:
5547 if not act:
5576 if not act:
5548 ui.write(b'%s%s' % (path, eol))
5577 ui.write(b'%s%s' % (path, eol))
5549
5578
5550
5579
5551 @command(
5580 @command(
5552 b'push',
5581 b'push',
5553 [
5582 [
5554 (b'f', b'force', None, _(b'force push')),
5583 (b'f', b'force', None, _(b'force push')),
5555 (
5584 (
5556 b'r',
5585 b'r',
5557 b'rev',
5586 b'rev',
5558 [],
5587 [],
5559 _(b'a changeset intended to be included in the destination'),
5588 _(b'a changeset intended to be included in the destination'),
5560 _(b'REV'),
5589 _(b'REV'),
5561 ),
5590 ),
5562 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5591 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5563 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5592 (b'', b'all-bookmarks', None, _(b"push all bookmarks (EXPERIMENTAL)")),
5564 (
5593 (
5565 b'b',
5594 b'b',
5566 b'branch',
5595 b'branch',
5567 [],
5596 [],
5568 _(b'a specific branch you would like to push'),
5597 _(b'a specific branch you would like to push'),
5569 _(b'BRANCH'),
5598 _(b'BRANCH'),
5570 ),
5599 ),
5571 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5600 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5572 (
5601 (
5573 b'',
5602 b'',
5574 b'pushvars',
5603 b'pushvars',
5575 [],
5604 [],
5576 _(b'variables that can be sent to server (ADVANCED)'),
5605 _(b'variables that can be sent to server (ADVANCED)'),
5577 ),
5606 ),
5578 (
5607 (
5579 b'',
5608 b'',
5580 b'publish',
5609 b'publish',
5581 False,
5610 False,
5582 _(b'push the changeset as public (EXPERIMENTAL)'),
5611 _(b'push the changeset as public (EXPERIMENTAL)'),
5583 ),
5612 ),
5584 ]
5613 ]
5585 + remoteopts,
5614 + remoteopts,
5586 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
5615 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
5587 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5616 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5588 helpbasic=True,
5617 helpbasic=True,
5589 )
5618 )
5590 def push(ui, repo, dest=None, **opts):
5619 def push(ui, repo, dest=None, **opts):
5591 """push changes to the specified destination
5620 """push changes to the specified destination
5592
5621
5593 Push changesets from the local repository to the specified
5622 Push changesets from the local repository to the specified
5594 destination.
5623 destination.
5595
5624
5596 This operation is symmetrical to pull: it is identical to a pull
5625 This operation is symmetrical to pull: it is identical to a pull
5597 in the destination repository from the current one.
5626 in the destination repository from the current one.
5598
5627
5599 By default, push will not allow creation of new heads at the
5628 By default, push will not allow creation of new heads at the
5600 destination, since multiple heads would make it unclear which head
5629 destination, since multiple heads would make it unclear which head
5601 to use. In this situation, it is recommended to pull and merge
5630 to use. In this situation, it is recommended to pull and merge
5602 before pushing.
5631 before pushing.
5603
5632
5604 Use --new-branch if you want to allow push to create a new named
5633 Use --new-branch if you want to allow push to create a new named
5605 branch that is not present at the destination. This allows you to
5634 branch that is not present at the destination. This allows you to
5606 only create a new branch without forcing other changes.
5635 only create a new branch without forcing other changes.
5607
5636
5608 .. note::
5637 .. note::
5609
5638
5610 Extra care should be taken with the -f/--force option,
5639 Extra care should be taken with the -f/--force option,
5611 which will push all new heads on all branches, an action which will
5640 which will push all new heads on all branches, an action which will
5612 almost always cause confusion for collaborators.
5641 almost always cause confusion for collaborators.
5613
5642
5614 If -r/--rev is used, the specified revision and all its ancestors
5643 If -r/--rev is used, the specified revision and all its ancestors
5615 will be pushed to the remote repository.
5644 will be pushed to the remote repository.
5616
5645
5617 If -B/--bookmark is used, the specified bookmarked revision, its
5646 If -B/--bookmark is used, the specified bookmarked revision, its
5618 ancestors, and the bookmark will be pushed to the remote
5647 ancestors, and the bookmark will be pushed to the remote
5619 repository. Specifying ``.`` is equivalent to specifying the active
5648 repository. Specifying ``.`` is equivalent to specifying the active
5620 bookmark's name. Use the --all-bookmarks option for pushing all
5649 bookmark's name. Use the --all-bookmarks option for pushing all
5621 current bookmarks.
5650 current bookmarks.
5622
5651
5623 Please see :hg:`help urls` for important details about ``ssh://``
5652 Please see :hg:`help urls` for important details about ``ssh://``
5624 URLs. If DESTINATION is omitted, a default path will be used.
5653 URLs. If DESTINATION is omitted, a default path will be used.
5625
5654
5626 .. container:: verbose
5655 .. container:: verbose
5627
5656
5628 The --pushvars option sends strings to the server that become
5657 The --pushvars option sends strings to the server that become
5629 environment variables prepended with ``HG_USERVAR_``. For example,
5658 environment variables prepended with ``HG_USERVAR_``. For example,
5630 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5659 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5631 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5660 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5632
5661
5633 pushvars can provide for user-overridable hooks as well as set debug
5662 pushvars can provide for user-overridable hooks as well as set debug
5634 levels. One example is having a hook that blocks commits containing
5663 levels. One example is having a hook that blocks commits containing
5635 conflict markers, but enables the user to override the hook if the file
5664 conflict markers, but enables the user to override the hook if the file
5636 is using conflict markers for testing purposes or the file format has
5665 is using conflict markers for testing purposes or the file format has
5637 strings that look like conflict markers.
5666 strings that look like conflict markers.
5638
5667
5639 By default, servers will ignore `--pushvars`. To enable it add the
5668 By default, servers will ignore `--pushvars`. To enable it add the
5640 following to your configuration file::
5669 following to your configuration file::
5641
5670
5642 [push]
5671 [push]
5643 pushvars.server = true
5672 pushvars.server = true
5644
5673
5645 Returns 0 if push was successful, 1 if nothing to push.
5674 Returns 0 if push was successful, 1 if nothing to push.
5646 """
5675 """
5647
5676
5648 opts = pycompat.byteskwargs(opts)
5677 opts = pycompat.byteskwargs(opts)
5649
5678
5650 if opts.get(b'all_bookmarks'):
5679 if opts.get(b'all_bookmarks'):
5651 cmdutil.check_incompatible_arguments(
5680 cmdutil.check_incompatible_arguments(
5652 opts,
5681 opts,
5653 b'all_bookmarks',
5682 b'all_bookmarks',
5654 [b'bookmark', b'rev'],
5683 [b'bookmark', b'rev'],
5655 )
5684 )
5656 opts[b'bookmark'] = list(repo._bookmarks)
5685 opts[b'bookmark'] = list(repo._bookmarks)
5657
5686
5658 if opts.get(b'bookmark'):
5687 if opts.get(b'bookmark'):
5659 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5688 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5660 for b in opts[b'bookmark']:
5689 for b in opts[b'bookmark']:
5661 # translate -B options to -r so changesets get pushed
5690 # translate -B options to -r so changesets get pushed
5662 b = repo._bookmarks.expandname(b)
5691 b = repo._bookmarks.expandname(b)
5663 if b in repo._bookmarks:
5692 if b in repo._bookmarks:
5664 opts.setdefault(b'rev', []).append(b)
5693 opts.setdefault(b'rev', []).append(b)
5665 else:
5694 else:
5666 # if we try to push a deleted bookmark, translate it to null
5695 # if we try to push a deleted bookmark, translate it to null
5667 # this lets simultaneous -r, -b options continue working
5696 # this lets simultaneous -r, -b options continue working
5668 opts.setdefault(b'rev', []).append(b"null")
5697 opts.setdefault(b'rev', []).append(b"null")
5669
5698
5670 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5699 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5671 if not path:
5700 if not path:
5672 raise error.ConfigError(
5701 raise error.ConfigError(
5673 _(b'default repository not configured!'),
5702 _(b'default repository not configured!'),
5674 hint=_(b"see 'hg help config.paths'"),
5703 hint=_(b"see 'hg help config.paths'"),
5675 )
5704 )
5676 dest = path.pushloc or path.loc
5705 dest = path.pushloc or path.loc
5677 branches = (path.branch, opts.get(b'branch') or [])
5706 branches = (path.branch, opts.get(b'branch') or [])
5678 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5707 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5679 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
5708 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
5680 other = hg.peer(repo, opts, dest)
5709 other = hg.peer(repo, opts, dest)
5681
5710
5682 if revs:
5711 if revs:
5683 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5712 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5684 if not revs:
5713 if not revs:
5685 raise error.InputError(
5714 raise error.InputError(
5686 _(b"specified revisions evaluate to an empty set"),
5715 _(b"specified revisions evaluate to an empty set"),
5687 hint=_(b"use different revision arguments"),
5716 hint=_(b"use different revision arguments"),
5688 )
5717 )
5689 elif path.pushrev:
5718 elif path.pushrev:
5690 # It doesn't make any sense to specify ancestor revisions. So limit
5719 # It doesn't make any sense to specify ancestor revisions. So limit
5691 # to DAG heads to make discovery simpler.
5720 # to DAG heads to make discovery simpler.
5692 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5721 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5693 revs = scmutil.revrange(repo, [expr])
5722 revs = scmutil.revrange(repo, [expr])
5694 revs = [repo[rev].node() for rev in revs]
5723 revs = [repo[rev].node() for rev in revs]
5695 if not revs:
5724 if not revs:
5696 raise error.InputError(
5725 raise error.InputError(
5697 _(b'default push revset for path evaluates to an empty set')
5726 _(b'default push revset for path evaluates to an empty set')
5698 )
5727 )
5699 elif ui.configbool(b'commands', b'push.require-revs'):
5728 elif ui.configbool(b'commands', b'push.require-revs'):
5700 raise error.InputError(
5729 raise error.InputError(
5701 _(b'no revisions specified to push'),
5730 _(b'no revisions specified to push'),
5702 hint=_(b'did you mean "hg push -r ."?'),
5731 hint=_(b'did you mean "hg push -r ."?'),
5703 )
5732 )
5704
5733
5705 repo._subtoppath = dest
5734 repo._subtoppath = dest
5706 try:
5735 try:
5707 # push subrepos depth-first for coherent ordering
5736 # push subrepos depth-first for coherent ordering
5708 c = repo[b'.']
5737 c = repo[b'.']
5709 subs = c.substate # only repos that are committed
5738 subs = c.substate # only repos that are committed
5710 for s in sorted(subs):
5739 for s in sorted(subs):
5711 result = c.sub(s).push(opts)
5740 result = c.sub(s).push(opts)
5712 if result == 0:
5741 if result == 0:
5713 return not result
5742 return not result
5714 finally:
5743 finally:
5715 del repo._subtoppath
5744 del repo._subtoppath
5716
5745
5717 opargs = dict(opts.get(b'opargs', {})) # copy opargs since we may mutate it
5746 opargs = dict(opts.get(b'opargs', {})) # copy opargs since we may mutate it
5718 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5747 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5719
5748
5720 pushop = exchange.push(
5749 pushop = exchange.push(
5721 repo,
5750 repo,
5722 other,
5751 other,
5723 opts.get(b'force'),
5752 opts.get(b'force'),
5724 revs=revs,
5753 revs=revs,
5725 newbranch=opts.get(b'new_branch'),
5754 newbranch=opts.get(b'new_branch'),
5726 bookmarks=opts.get(b'bookmark', ()),
5755 bookmarks=opts.get(b'bookmark', ()),
5727 publish=opts.get(b'publish'),
5756 publish=opts.get(b'publish'),
5728 opargs=opargs,
5757 opargs=opargs,
5729 )
5758 )
5730
5759
5731 result = not pushop.cgresult
5760 result = not pushop.cgresult
5732
5761
5733 if pushop.bkresult is not None:
5762 if pushop.bkresult is not None:
5734 if pushop.bkresult == 2:
5763 if pushop.bkresult == 2:
5735 result = 2
5764 result = 2
5736 elif not result and pushop.bkresult:
5765 elif not result and pushop.bkresult:
5737 result = 2
5766 result = 2
5738
5767
5739 return result
5768 return result
5740
5769
5741
5770
5742 @command(
5771 @command(
5743 b'recover',
5772 b'recover',
5744 [
5773 [
5745 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5774 (b'', b'verify', False, b"run `hg verify` after successful recover"),
5746 ],
5775 ],
5747 helpcategory=command.CATEGORY_MAINTENANCE,
5776 helpcategory=command.CATEGORY_MAINTENANCE,
5748 )
5777 )
5749 def recover(ui, repo, **opts):
5778 def recover(ui, repo, **opts):
5750 """roll back an interrupted transaction
5779 """roll back an interrupted transaction
5751
5780
5752 Recover from an interrupted commit or pull.
5781 Recover from an interrupted commit or pull.
5753
5782
5754 This command tries to fix the repository status after an
5783 This command tries to fix the repository status after an
5755 interrupted operation. It should only be necessary when Mercurial
5784 interrupted operation. It should only be necessary when Mercurial
5756 suggests it.
5785 suggests it.
5757
5786
5758 Returns 0 if successful, 1 if nothing to recover or verify fails.
5787 Returns 0 if successful, 1 if nothing to recover or verify fails.
5759 """
5788 """
5760 ret = repo.recover()
5789 ret = repo.recover()
5761 if ret:
5790 if ret:
5762 if opts['verify']:
5791 if opts['verify']:
5763 return hg.verify(repo)
5792 return hg.verify(repo)
5764 else:
5793 else:
5765 msg = _(
5794 msg = _(
5766 b"(verify step skipped, run `hg verify` to check your "
5795 b"(verify step skipped, run `hg verify` to check your "
5767 b"repository content)\n"
5796 b"repository content)\n"
5768 )
5797 )
5769 ui.warn(msg)
5798 ui.warn(msg)
5770 return 0
5799 return 0
5771 return 1
5800 return 1
5772
5801
5773
5802
5774 @command(
5803 @command(
5775 b'remove|rm',
5804 b'remove|rm',
5776 [
5805 [
5777 (b'A', b'after', None, _(b'record delete for missing files')),
5806 (b'A', b'after', None, _(b'record delete for missing files')),
5778 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5807 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5779 ]
5808 ]
5780 + subrepoopts
5809 + subrepoopts
5781 + walkopts
5810 + walkopts
5782 + dryrunopts,
5811 + dryrunopts,
5783 _(b'[OPTION]... FILE...'),
5812 _(b'[OPTION]... FILE...'),
5784 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5813 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5785 helpbasic=True,
5814 helpbasic=True,
5786 inferrepo=True,
5815 inferrepo=True,
5787 )
5816 )
5788 def remove(ui, repo, *pats, **opts):
5817 def remove(ui, repo, *pats, **opts):
5789 """remove the specified files on the next commit
5818 """remove the specified files on the next commit
5790
5819
5791 Schedule the indicated files for removal from the current branch.
5820 Schedule the indicated files for removal from the current branch.
5792
5821
5793 This command schedules the files to be removed at the next commit.
5822 This command schedules the files to be removed at the next commit.
5794 To undo a remove before that, see :hg:`revert`. To undo added
5823 To undo a remove before that, see :hg:`revert`. To undo added
5795 files, see :hg:`forget`.
5824 files, see :hg:`forget`.
5796
5825
5797 .. container:: verbose
5826 .. container:: verbose
5798
5827
5799 -A/--after can be used to remove only files that have already
5828 -A/--after can be used to remove only files that have already
5800 been deleted, -f/--force can be used to force deletion, and -Af
5829 been deleted, -f/--force can be used to force deletion, and -Af
5801 can be used to remove files from the next revision without
5830 can be used to remove files from the next revision without
5802 deleting them from the working directory.
5831 deleting them from the working directory.
5803
5832
5804 The following table details the behavior of remove for different
5833 The following table details the behavior of remove for different
5805 file states (columns) and option combinations (rows). The file
5834 file states (columns) and option combinations (rows). The file
5806 states are Added [A], Clean [C], Modified [M] and Missing [!]
5835 states are Added [A], Clean [C], Modified [M] and Missing [!]
5807 (as reported by :hg:`status`). The actions are Warn, Remove
5836 (as reported by :hg:`status`). The actions are Warn, Remove
5808 (from branch) and Delete (from disk):
5837 (from branch) and Delete (from disk):
5809
5838
5810 ========= == == == ==
5839 ========= == == == ==
5811 opt/state A C M !
5840 opt/state A C M !
5812 ========= == == == ==
5841 ========= == == == ==
5813 none W RD W R
5842 none W RD W R
5814 -f R RD RD R
5843 -f R RD RD R
5815 -A W W W R
5844 -A W W W R
5816 -Af R R R R
5845 -Af R R R R
5817 ========= == == == ==
5846 ========= == == == ==
5818
5847
5819 .. note::
5848 .. note::
5820
5849
5821 :hg:`remove` never deletes files in Added [A] state from the
5850 :hg:`remove` never deletes files in Added [A] state from the
5822 working directory, not even if ``--force`` is specified.
5851 working directory, not even if ``--force`` is specified.
5823
5852
5824 Returns 0 on success, 1 if any warnings encountered.
5853 Returns 0 on success, 1 if any warnings encountered.
5825 """
5854 """
5826
5855
5827 opts = pycompat.byteskwargs(opts)
5856 opts = pycompat.byteskwargs(opts)
5828 after, force = opts.get(b'after'), opts.get(b'force')
5857 after, force = opts.get(b'after'), opts.get(b'force')
5829 dryrun = opts.get(b'dry_run')
5858 dryrun = opts.get(b'dry_run')
5830 if not pats and not after:
5859 if not pats and not after:
5831 raise error.InputError(_(b'no files specified'))
5860 raise error.InputError(_(b'no files specified'))
5832
5861
5833 m = scmutil.match(repo[None], pats, opts)
5862 m = scmutil.match(repo[None], pats, opts)
5834 subrepos = opts.get(b'subrepos')
5863 subrepos = opts.get(b'subrepos')
5835 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5864 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5836 return cmdutil.remove(
5865 return cmdutil.remove(
5837 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5866 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5838 )
5867 )
5839
5868
5840
5869
5841 @command(
5870 @command(
5842 b'rename|move|mv',
5871 b'rename|move|mv',
5843 [
5872 [
5844 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5873 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5845 (
5874 (
5846 b'',
5875 b'',
5847 b'at-rev',
5876 b'at-rev',
5848 b'',
5877 b'',
5849 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5878 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5850 _(b'REV'),
5879 _(b'REV'),
5851 ),
5880 ),
5852 (
5881 (
5853 b'f',
5882 b'f',
5854 b'force',
5883 b'force',
5855 None,
5884 None,
5856 _(b'forcibly move over an existing managed file'),
5885 _(b'forcibly move over an existing managed file'),
5857 ),
5886 ),
5858 ]
5887 ]
5859 + walkopts
5888 + walkopts
5860 + dryrunopts,
5889 + dryrunopts,
5861 _(b'[OPTION]... SOURCE... DEST'),
5890 _(b'[OPTION]... SOURCE... DEST'),
5862 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5891 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5863 )
5892 )
5864 def rename(ui, repo, *pats, **opts):
5893 def rename(ui, repo, *pats, **opts):
5865 """rename files; equivalent of copy + remove
5894 """rename files; equivalent of copy + remove
5866
5895
5867 Mark dest as copies of sources; mark sources for deletion. If dest
5896 Mark dest as copies of sources; mark sources for deletion. If dest
5868 is a directory, copies are put in that directory. If dest is a
5897 is a directory, copies are put in that directory. If dest is a
5869 file, there can only be one source.
5898 file, there can only be one source.
5870
5899
5871 By default, this command copies the contents of files as they
5900 By default, this command copies the contents of files as they
5872 exist in the working directory. If invoked with -A/--after, the
5901 exist in the working directory. If invoked with -A/--after, the
5873 operation is recorded, but no copying is performed.
5902 operation is recorded, but no copying is performed.
5874
5903
5875 This command takes effect at the next commit. To undo a rename
5904 This command takes effect at the next commit. To undo a rename
5876 before that, see :hg:`revert`.
5905 before that, see :hg:`revert`.
5877
5906
5878 Returns 0 on success, 1 if errors are encountered.
5907 Returns 0 on success, 1 if errors are encountered.
5879 """
5908 """
5880 opts = pycompat.byteskwargs(opts)
5909 opts = pycompat.byteskwargs(opts)
5881 with repo.wlock():
5910 with repo.wlock():
5882 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5911 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5883
5912
5884
5913
5885 @command(
5914 @command(
5886 b'resolve',
5915 b'resolve',
5887 [
5916 [
5888 (b'a', b'all', None, _(b'select all unresolved files')),
5917 (b'a', b'all', None, _(b'select all unresolved files')),
5889 (b'l', b'list', None, _(b'list state of files needing merge')),
5918 (b'l', b'list', None, _(b'list state of files needing merge')),
5890 (b'm', b'mark', None, _(b'mark files as resolved')),
5919 (b'm', b'mark', None, _(b'mark files as resolved')),
5891 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5920 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5892 (b'n', b'no-status', None, _(b'hide status prefix')),
5921 (b'n', b'no-status', None, _(b'hide status prefix')),
5893 (b'', b're-merge', None, _(b're-merge files')),
5922 (b'', b're-merge', None, _(b're-merge files')),
5894 ]
5923 ]
5895 + mergetoolopts
5924 + mergetoolopts
5896 + walkopts
5925 + walkopts
5897 + formatteropts,
5926 + formatteropts,
5898 _(b'[OPTION]... [FILE]...'),
5927 _(b'[OPTION]... [FILE]...'),
5899 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5928 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5900 inferrepo=True,
5929 inferrepo=True,
5901 )
5930 )
5902 def resolve(ui, repo, *pats, **opts):
5931 def resolve(ui, repo, *pats, **opts):
5903 """redo merges or set/view the merge status of files
5932 """redo merges or set/view the merge status of files
5904
5933
5905 Merges with unresolved conflicts are often the result of
5934 Merges with unresolved conflicts are often the result of
5906 non-interactive merging using the ``internal:merge`` configuration
5935 non-interactive merging using the ``internal:merge`` configuration
5907 setting, or a command-line merge tool like ``diff3``. The resolve
5936 setting, or a command-line merge tool like ``diff3``. The resolve
5908 command is used to manage the files involved in a merge, after
5937 command is used to manage the files involved in a merge, after
5909 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5938 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5910 working directory must have two parents). See :hg:`help
5939 working directory must have two parents). See :hg:`help
5911 merge-tools` for information on configuring merge tools.
5940 merge-tools` for information on configuring merge tools.
5912
5941
5913 The resolve command can be used in the following ways:
5942 The resolve command can be used in the following ways:
5914
5943
5915 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5944 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5916 the specified files, discarding any previous merge attempts. Re-merging
5945 the specified files, discarding any previous merge attempts. Re-merging
5917 is not performed for files already marked as resolved. Use ``--all/-a``
5946 is not performed for files already marked as resolved. Use ``--all/-a``
5918 to select all unresolved files. ``--tool`` can be used to specify
5947 to select all unresolved files. ``--tool`` can be used to specify
5919 the merge tool used for the given files. It overrides the HGMERGE
5948 the merge tool used for the given files. It overrides the HGMERGE
5920 environment variable and your configuration files. Previous file
5949 environment variable and your configuration files. Previous file
5921 contents are saved with a ``.orig`` suffix.
5950 contents are saved with a ``.orig`` suffix.
5922
5951
5923 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5952 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5924 (e.g. after having manually fixed-up the files). The default is
5953 (e.g. after having manually fixed-up the files). The default is
5925 to mark all unresolved files.
5954 to mark all unresolved files.
5926
5955
5927 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5956 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5928 default is to mark all resolved files.
5957 default is to mark all resolved files.
5929
5958
5930 - :hg:`resolve -l`: list files which had or still have conflicts.
5959 - :hg:`resolve -l`: list files which had or still have conflicts.
5931 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5960 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5932 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5961 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5933 the list. See :hg:`help filesets` for details.
5962 the list. See :hg:`help filesets` for details.
5934
5963
5935 .. note::
5964 .. note::
5936
5965
5937 Mercurial will not let you commit files with unresolved merge
5966 Mercurial will not let you commit files with unresolved merge
5938 conflicts. You must use :hg:`resolve -m ...` before you can
5967 conflicts. You must use :hg:`resolve -m ...` before you can
5939 commit after a conflicting merge.
5968 commit after a conflicting merge.
5940
5969
5941 .. container:: verbose
5970 .. container:: verbose
5942
5971
5943 Template:
5972 Template:
5944
5973
5945 The following keywords are supported in addition to the common template
5974 The following keywords are supported in addition to the common template
5946 keywords and functions. See also :hg:`help templates`.
5975 keywords and functions. See also :hg:`help templates`.
5947
5976
5948 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
5977 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
5949 :path: String. Repository-absolute path of the file.
5978 :path: String. Repository-absolute path of the file.
5950
5979
5951 Returns 0 on success, 1 if any files fail a resolve attempt.
5980 Returns 0 on success, 1 if any files fail a resolve attempt.
5952 """
5981 """
5953
5982
5954 opts = pycompat.byteskwargs(opts)
5983 opts = pycompat.byteskwargs(opts)
5955 confirm = ui.configbool(b'commands', b'resolve.confirm')
5984 confirm = ui.configbool(b'commands', b'resolve.confirm')
5956 flaglist = b'all mark unmark list no_status re_merge'.split()
5985 flaglist = b'all mark unmark list no_status re_merge'.split()
5957 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
5986 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
5958
5987
5959 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
5988 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
5960 if actioncount > 1:
5989 if actioncount > 1:
5961 raise error.InputError(_(b"too many actions specified"))
5990 raise error.InputError(_(b"too many actions specified"))
5962 elif actioncount == 0 and ui.configbool(
5991 elif actioncount == 0 and ui.configbool(
5963 b'commands', b'resolve.explicit-re-merge'
5992 b'commands', b'resolve.explicit-re-merge'
5964 ):
5993 ):
5965 hint = _(b'use --mark, --unmark, --list or --re-merge')
5994 hint = _(b'use --mark, --unmark, --list or --re-merge')
5966 raise error.InputError(_(b'no action specified'), hint=hint)
5995 raise error.InputError(_(b'no action specified'), hint=hint)
5967 if pats and all:
5996 if pats and all:
5968 raise error.InputError(_(b"can't specify --all and patterns"))
5997 raise error.InputError(_(b"can't specify --all and patterns"))
5969 if not (all or pats or show or mark or unmark):
5998 if not (all or pats or show or mark or unmark):
5970 raise error.InputError(
5999 raise error.InputError(
5971 _(b'no files or directories specified'),
6000 _(b'no files or directories specified'),
5972 hint=b'use --all to re-merge all unresolved files',
6001 hint=b'use --all to re-merge all unresolved files',
5973 )
6002 )
5974
6003
5975 if confirm:
6004 if confirm:
5976 if all:
6005 if all:
5977 if ui.promptchoice(
6006 if ui.promptchoice(
5978 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
6007 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
5979 ):
6008 ):
5980 raise error.CanceledError(_(b'user quit'))
6009 raise error.CanceledError(_(b'user quit'))
5981 if mark and not pats:
6010 if mark and not pats:
5982 if ui.promptchoice(
6011 if ui.promptchoice(
5983 _(
6012 _(
5984 b'mark all unresolved files as resolved (yn)?'
6013 b'mark all unresolved files as resolved (yn)?'
5985 b'$$ &Yes $$ &No'
6014 b'$$ &Yes $$ &No'
5986 )
6015 )
5987 ):
6016 ):
5988 raise error.CanceledError(_(b'user quit'))
6017 raise error.CanceledError(_(b'user quit'))
5989 if unmark and not pats:
6018 if unmark and not pats:
5990 if ui.promptchoice(
6019 if ui.promptchoice(
5991 _(
6020 _(
5992 b'mark all resolved files as unresolved (yn)?'
6021 b'mark all resolved files as unresolved (yn)?'
5993 b'$$ &Yes $$ &No'
6022 b'$$ &Yes $$ &No'
5994 )
6023 )
5995 ):
6024 ):
5996 raise error.CanceledError(_(b'user quit'))
6025 raise error.CanceledError(_(b'user quit'))
5997
6026
5998 uipathfn = scmutil.getuipathfn(repo)
6027 uipathfn = scmutil.getuipathfn(repo)
5999
6028
6000 if show:
6029 if show:
6001 ui.pager(b'resolve')
6030 ui.pager(b'resolve')
6002 fm = ui.formatter(b'resolve', opts)
6031 fm = ui.formatter(b'resolve', opts)
6003 ms = mergestatemod.mergestate.read(repo)
6032 ms = mergestatemod.mergestate.read(repo)
6004 wctx = repo[None]
6033 wctx = repo[None]
6005 m = scmutil.match(wctx, pats, opts)
6034 m = scmutil.match(wctx, pats, opts)
6006
6035
6007 # Labels and keys based on merge state. Unresolved path conflicts show
6036 # Labels and keys based on merge state. Unresolved path conflicts show
6008 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6037 # as 'P'. Resolved path conflicts show as 'R', the same as normal
6009 # resolved conflicts.
6038 # resolved conflicts.
6010 mergestateinfo = {
6039 mergestateinfo = {
6011 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6040 mergestatemod.MERGE_RECORD_UNRESOLVED: (
6012 b'resolve.unresolved',
6041 b'resolve.unresolved',
6013 b'U',
6042 b'U',
6014 ),
6043 ),
6015 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6044 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
6016 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6045 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
6017 b'resolve.unresolved',
6046 b'resolve.unresolved',
6018 b'P',
6047 b'P',
6019 ),
6048 ),
6020 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6049 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
6021 b'resolve.resolved',
6050 b'resolve.resolved',
6022 b'R',
6051 b'R',
6023 ),
6052 ),
6024 }
6053 }
6025
6054
6026 for f in ms:
6055 for f in ms:
6027 if not m(f):
6056 if not m(f):
6028 continue
6057 continue
6029
6058
6030 label, key = mergestateinfo[ms[f]]
6059 label, key = mergestateinfo[ms[f]]
6031 fm.startitem()
6060 fm.startitem()
6032 fm.context(ctx=wctx)
6061 fm.context(ctx=wctx)
6033 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6062 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6034 fm.data(path=f)
6063 fm.data(path=f)
6035 fm.plain(b'%s\n' % uipathfn(f), label=label)
6064 fm.plain(b'%s\n' % uipathfn(f), label=label)
6036 fm.end()
6065 fm.end()
6037 return 0
6066 return 0
6038
6067
6039 with repo.wlock():
6068 with repo.wlock():
6040 ms = mergestatemod.mergestate.read(repo)
6069 ms = mergestatemod.mergestate.read(repo)
6041
6070
6042 if not (ms.active() or repo.dirstate.p2() != nullid):
6071 if not (ms.active() or repo.dirstate.p2() != nullid):
6043 raise error.StateError(
6072 raise error.StateError(
6044 _(b'resolve command not applicable when not merging')
6073 _(b'resolve command not applicable when not merging')
6045 )
6074 )
6046
6075
6047 wctx = repo[None]
6076 wctx = repo[None]
6048 m = scmutil.match(wctx, pats, opts)
6077 m = scmutil.match(wctx, pats, opts)
6049 ret = 0
6078 ret = 0
6050 didwork = False
6079 didwork = False
6051
6080
6052 tocomplete = []
6081 tocomplete = []
6053 hasconflictmarkers = []
6082 hasconflictmarkers = []
6054 if mark:
6083 if mark:
6055 markcheck = ui.config(b'commands', b'resolve.mark-check')
6084 markcheck = ui.config(b'commands', b'resolve.mark-check')
6056 if markcheck not in [b'warn', b'abort']:
6085 if markcheck not in [b'warn', b'abort']:
6057 # Treat all invalid / unrecognized values as 'none'.
6086 # Treat all invalid / unrecognized values as 'none'.
6058 markcheck = False
6087 markcheck = False
6059 for f in ms:
6088 for f in ms:
6060 if not m(f):
6089 if not m(f):
6061 continue
6090 continue
6062
6091
6063 didwork = True
6092 didwork = True
6064
6093
6065 # path conflicts must be resolved manually
6094 # path conflicts must be resolved manually
6066 if ms[f] in (
6095 if ms[f] in (
6067 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6096 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6068 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6097 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6069 ):
6098 ):
6070 if mark:
6099 if mark:
6071 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6100 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6072 elif unmark:
6101 elif unmark:
6073 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6102 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6074 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6103 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6075 ui.warn(
6104 ui.warn(
6076 _(b'%s: path conflict must be resolved manually\n')
6105 _(b'%s: path conflict must be resolved manually\n')
6077 % uipathfn(f)
6106 % uipathfn(f)
6078 )
6107 )
6079 continue
6108 continue
6080
6109
6081 if mark:
6110 if mark:
6082 if markcheck:
6111 if markcheck:
6083 fdata = repo.wvfs.tryread(f)
6112 fdata = repo.wvfs.tryread(f)
6084 if (
6113 if (
6085 filemerge.hasconflictmarkers(fdata)
6114 filemerge.hasconflictmarkers(fdata)
6086 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6115 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6087 ):
6116 ):
6088 hasconflictmarkers.append(f)
6117 hasconflictmarkers.append(f)
6089 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6118 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6090 elif unmark:
6119 elif unmark:
6091 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6120 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6092 else:
6121 else:
6093 # backup pre-resolve (merge uses .orig for its own purposes)
6122 # backup pre-resolve (merge uses .orig for its own purposes)
6094 a = repo.wjoin(f)
6123 a = repo.wjoin(f)
6095 try:
6124 try:
6096 util.copyfile(a, a + b".resolve")
6125 util.copyfile(a, a + b".resolve")
6097 except (IOError, OSError) as inst:
6126 except (IOError, OSError) as inst:
6098 if inst.errno != errno.ENOENT:
6127 if inst.errno != errno.ENOENT:
6099 raise
6128 raise
6100
6129
6101 try:
6130 try:
6102 # preresolve file
6131 # preresolve file
6103 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6132 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6104 with ui.configoverride(overrides, b'resolve'):
6133 with ui.configoverride(overrides, b'resolve'):
6105 complete, r = ms.preresolve(f, wctx)
6134 complete, r = ms.preresolve(f, wctx)
6106 if not complete:
6135 if not complete:
6107 tocomplete.append(f)
6136 tocomplete.append(f)
6108 elif r:
6137 elif r:
6109 ret = 1
6138 ret = 1
6110 finally:
6139 finally:
6111 ms.commit()
6140 ms.commit()
6112
6141
6113 # replace filemerge's .orig file with our resolve file, but only
6142 # replace filemerge's .orig file with our resolve file, but only
6114 # for merges that are complete
6143 # for merges that are complete
6115 if complete:
6144 if complete:
6116 try:
6145 try:
6117 util.rename(
6146 util.rename(
6118 a + b".resolve", scmutil.backuppath(ui, repo, f)
6147 a + b".resolve", scmutil.backuppath(ui, repo, f)
6119 )
6148 )
6120 except OSError as inst:
6149 except OSError as inst:
6121 if inst.errno != errno.ENOENT:
6150 if inst.errno != errno.ENOENT:
6122 raise
6151 raise
6123
6152
6124 if hasconflictmarkers:
6153 if hasconflictmarkers:
6125 ui.warn(
6154 ui.warn(
6126 _(
6155 _(
6127 b'warning: the following files still have conflict '
6156 b'warning: the following files still have conflict '
6128 b'markers:\n'
6157 b'markers:\n'
6129 )
6158 )
6130 + b''.join(
6159 + b''.join(
6131 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6160 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6132 )
6161 )
6133 )
6162 )
6134 if markcheck == b'abort' and not all and not pats:
6163 if markcheck == b'abort' and not all and not pats:
6135 raise error.StateError(
6164 raise error.StateError(
6136 _(b'conflict markers detected'),
6165 _(b'conflict markers detected'),
6137 hint=_(b'use --all to mark anyway'),
6166 hint=_(b'use --all to mark anyway'),
6138 )
6167 )
6139
6168
6140 for f in tocomplete:
6169 for f in tocomplete:
6141 try:
6170 try:
6142 # resolve file
6171 # resolve file
6143 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6172 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6144 with ui.configoverride(overrides, b'resolve'):
6173 with ui.configoverride(overrides, b'resolve'):
6145 r = ms.resolve(f, wctx)
6174 r = ms.resolve(f, wctx)
6146 if r:
6175 if r:
6147 ret = 1
6176 ret = 1
6148 finally:
6177 finally:
6149 ms.commit()
6178 ms.commit()
6150
6179
6151 # replace filemerge's .orig file with our resolve file
6180 # replace filemerge's .orig file with our resolve file
6152 a = repo.wjoin(f)
6181 a = repo.wjoin(f)
6153 try:
6182 try:
6154 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
6183 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
6155 except OSError as inst:
6184 except OSError as inst:
6156 if inst.errno != errno.ENOENT:
6185 if inst.errno != errno.ENOENT:
6157 raise
6186 raise
6158
6187
6159 ms.commit()
6188 ms.commit()
6160 branchmerge = repo.dirstate.p2() != nullid
6189 branchmerge = repo.dirstate.p2() != nullid
6161 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6190 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6162
6191
6163 if not didwork and pats:
6192 if not didwork and pats:
6164 hint = None
6193 hint = None
6165 if not any([p for p in pats if p.find(b':') >= 0]):
6194 if not any([p for p in pats if p.find(b':') >= 0]):
6166 pats = [b'path:%s' % p for p in pats]
6195 pats = [b'path:%s' % p for p in pats]
6167 m = scmutil.match(wctx, pats, opts)
6196 m = scmutil.match(wctx, pats, opts)
6168 for f in ms:
6197 for f in ms:
6169 if not m(f):
6198 if not m(f):
6170 continue
6199 continue
6171
6200
6172 def flag(o):
6201 def flag(o):
6173 if o == b're_merge':
6202 if o == b're_merge':
6174 return b'--re-merge '
6203 return b'--re-merge '
6175 return b'-%s ' % o[0:1]
6204 return b'-%s ' % o[0:1]
6176
6205
6177 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6206 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6178 hint = _(b"(try: hg resolve %s%s)\n") % (
6207 hint = _(b"(try: hg resolve %s%s)\n") % (
6179 flags,
6208 flags,
6180 b' '.join(pats),
6209 b' '.join(pats),
6181 )
6210 )
6182 break
6211 break
6183 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6212 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6184 if hint:
6213 if hint:
6185 ui.warn(hint)
6214 ui.warn(hint)
6186
6215
6187 unresolvedf = ms.unresolvedcount()
6216 unresolvedf = ms.unresolvedcount()
6188 if not unresolvedf:
6217 if not unresolvedf:
6189 ui.status(_(b'(no more unresolved files)\n'))
6218 ui.status(_(b'(no more unresolved files)\n'))
6190 cmdutil.checkafterresolved(repo)
6219 cmdutil.checkafterresolved(repo)
6191
6220
6192 return ret
6221 return ret
6193
6222
6194
6223
6195 @command(
6224 @command(
6196 b'revert',
6225 b'revert',
6197 [
6226 [
6198 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6227 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6199 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6228 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6200 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6229 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6201 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6230 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6202 (b'i', b'interactive', None, _(b'interactively select the changes')),
6231 (b'i', b'interactive', None, _(b'interactively select the changes')),
6203 ]
6232 ]
6204 + walkopts
6233 + walkopts
6205 + dryrunopts,
6234 + dryrunopts,
6206 _(b'[OPTION]... [-r REV] [NAME]...'),
6235 _(b'[OPTION]... [-r REV] [NAME]...'),
6207 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6236 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6208 )
6237 )
6209 def revert(ui, repo, *pats, **opts):
6238 def revert(ui, repo, *pats, **opts):
6210 """restore files to their checkout state
6239 """restore files to their checkout state
6211
6240
6212 .. note::
6241 .. note::
6213
6242
6214 To check out earlier revisions, you should use :hg:`update REV`.
6243 To check out earlier revisions, you should use :hg:`update REV`.
6215 To cancel an uncommitted merge (and lose your changes),
6244 To cancel an uncommitted merge (and lose your changes),
6216 use :hg:`merge --abort`.
6245 use :hg:`merge --abort`.
6217
6246
6218 With no revision specified, revert the specified files or directories
6247 With no revision specified, revert the specified files or directories
6219 to the contents they had in the parent of the working directory.
6248 to the contents they had in the parent of the working directory.
6220 This restores the contents of files to an unmodified
6249 This restores the contents of files to an unmodified
6221 state and unschedules adds, removes, copies, and renames. If the
6250 state and unschedules adds, removes, copies, and renames. If the
6222 working directory has two parents, you must explicitly specify a
6251 working directory has two parents, you must explicitly specify a
6223 revision.
6252 revision.
6224
6253
6225 Using the -r/--rev or -d/--date options, revert the given files or
6254 Using the -r/--rev or -d/--date options, revert the given files or
6226 directories to their states as of a specific revision. Because
6255 directories to their states as of a specific revision. Because
6227 revert does not change the working directory parents, this will
6256 revert does not change the working directory parents, this will
6228 cause these files to appear modified. This can be helpful to "back
6257 cause these files to appear modified. This can be helpful to "back
6229 out" some or all of an earlier change. See :hg:`backout` for a
6258 out" some or all of an earlier change. See :hg:`backout` for a
6230 related method.
6259 related method.
6231
6260
6232 Modified files are saved with a .orig suffix before reverting.
6261 Modified files are saved with a .orig suffix before reverting.
6233 To disable these backups, use --no-backup. It is possible to store
6262 To disable these backups, use --no-backup. It is possible to store
6234 the backup files in a custom directory relative to the root of the
6263 the backup files in a custom directory relative to the root of the
6235 repository by setting the ``ui.origbackuppath`` configuration
6264 repository by setting the ``ui.origbackuppath`` configuration
6236 option.
6265 option.
6237
6266
6238 See :hg:`help dates` for a list of formats valid for -d/--date.
6267 See :hg:`help dates` for a list of formats valid for -d/--date.
6239
6268
6240 See :hg:`help backout` for a way to reverse the effect of an
6269 See :hg:`help backout` for a way to reverse the effect of an
6241 earlier changeset.
6270 earlier changeset.
6242
6271
6243 Returns 0 on success.
6272 Returns 0 on success.
6244 """
6273 """
6245
6274
6246 opts = pycompat.byteskwargs(opts)
6275 opts = pycompat.byteskwargs(opts)
6247 if opts.get(b"date"):
6276 if opts.get(b"date"):
6248 cmdutil.check_incompatible_arguments(opts, b'date', [b'rev'])
6277 cmdutil.check_incompatible_arguments(opts, b'date', [b'rev'])
6249 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6278 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6250
6279
6251 parent, p2 = repo.dirstate.parents()
6280 parent, p2 = repo.dirstate.parents()
6252 if not opts.get(b'rev') and p2 != nullid:
6281 if not opts.get(b'rev') and p2 != nullid:
6253 # revert after merge is a trap for new users (issue2915)
6282 # revert after merge is a trap for new users (issue2915)
6254 raise error.InputError(
6283 raise error.InputError(
6255 _(b'uncommitted merge with no revision specified'),
6284 _(b'uncommitted merge with no revision specified'),
6256 hint=_(b"use 'hg update' or see 'hg help revert'"),
6285 hint=_(b"use 'hg update' or see 'hg help revert'"),
6257 )
6286 )
6258
6287
6259 rev = opts.get(b'rev')
6288 rev = opts.get(b'rev')
6260 if rev:
6289 if rev:
6261 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6290 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6262 ctx = scmutil.revsingle(repo, rev)
6291 ctx = scmutil.revsingle(repo, rev)
6263
6292
6264 if not (
6293 if not (
6265 pats
6294 pats
6266 or opts.get(b'include')
6295 or opts.get(b'include')
6267 or opts.get(b'exclude')
6296 or opts.get(b'exclude')
6268 or opts.get(b'all')
6297 or opts.get(b'all')
6269 or opts.get(b'interactive')
6298 or opts.get(b'interactive')
6270 ):
6299 ):
6271 msg = _(b"no files or directories specified")
6300 msg = _(b"no files or directories specified")
6272 if p2 != nullid:
6301 if p2 != nullid:
6273 hint = _(
6302 hint = _(
6274 b"uncommitted merge, use --all to discard all changes,"
6303 b"uncommitted merge, use --all to discard all changes,"
6275 b" or 'hg update -C .' to abort the merge"
6304 b" or 'hg update -C .' to abort the merge"
6276 )
6305 )
6277 raise error.InputError(msg, hint=hint)
6306 raise error.InputError(msg, hint=hint)
6278 dirty = any(repo.status())
6307 dirty = any(repo.status())
6279 node = ctx.node()
6308 node = ctx.node()
6280 if node != parent:
6309 if node != parent:
6281 if dirty:
6310 if dirty:
6282 hint = (
6311 hint = (
6283 _(
6312 _(
6284 b"uncommitted changes, use --all to discard all"
6313 b"uncommitted changes, use --all to discard all"
6285 b" changes, or 'hg update %d' to update"
6314 b" changes, or 'hg update %d' to update"
6286 )
6315 )
6287 % ctx.rev()
6316 % ctx.rev()
6288 )
6317 )
6289 else:
6318 else:
6290 hint = (
6319 hint = (
6291 _(
6320 _(
6292 b"use --all to revert all files,"
6321 b"use --all to revert all files,"
6293 b" or 'hg update %d' to update"
6322 b" or 'hg update %d' to update"
6294 )
6323 )
6295 % ctx.rev()
6324 % ctx.rev()
6296 )
6325 )
6297 elif dirty:
6326 elif dirty:
6298 hint = _(b"uncommitted changes, use --all to discard all changes")
6327 hint = _(b"uncommitted changes, use --all to discard all changes")
6299 else:
6328 else:
6300 hint = _(b"use --all to revert all files")
6329 hint = _(b"use --all to revert all files")
6301 raise error.InputError(msg, hint=hint)
6330 raise error.InputError(msg, hint=hint)
6302
6331
6303 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6332 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6304
6333
6305
6334
6306 @command(
6335 @command(
6307 b'rollback',
6336 b'rollback',
6308 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6337 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6309 helpcategory=command.CATEGORY_MAINTENANCE,
6338 helpcategory=command.CATEGORY_MAINTENANCE,
6310 )
6339 )
6311 def rollback(ui, repo, **opts):
6340 def rollback(ui, repo, **opts):
6312 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6341 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6313
6342
6314 Please use :hg:`commit --amend` instead of rollback to correct
6343 Please use :hg:`commit --amend` instead of rollback to correct
6315 mistakes in the last commit.
6344 mistakes in the last commit.
6316
6345
6317 This command should be used with care. There is only one level of
6346 This command should be used with care. There is only one level of
6318 rollback, and there is no way to undo a rollback. It will also
6347 rollback, and there is no way to undo a rollback. It will also
6319 restore the dirstate at the time of the last transaction, losing
6348 restore the dirstate at the time of the last transaction, losing
6320 any dirstate changes since that time. This command does not alter
6349 any dirstate changes since that time. This command does not alter
6321 the working directory.
6350 the working directory.
6322
6351
6323 Transactions are used to encapsulate the effects of all commands
6352 Transactions are used to encapsulate the effects of all commands
6324 that create new changesets or propagate existing changesets into a
6353 that create new changesets or propagate existing changesets into a
6325 repository.
6354 repository.
6326
6355
6327 .. container:: verbose
6356 .. container:: verbose
6328
6357
6329 For example, the following commands are transactional, and their
6358 For example, the following commands are transactional, and their
6330 effects can be rolled back:
6359 effects can be rolled back:
6331
6360
6332 - commit
6361 - commit
6333 - import
6362 - import
6334 - pull
6363 - pull
6335 - push (with this repository as the destination)
6364 - push (with this repository as the destination)
6336 - unbundle
6365 - unbundle
6337
6366
6338 To avoid permanent data loss, rollback will refuse to rollback a
6367 To avoid permanent data loss, rollback will refuse to rollback a
6339 commit transaction if it isn't checked out. Use --force to
6368 commit transaction if it isn't checked out. Use --force to
6340 override this protection.
6369 override this protection.
6341
6370
6342 The rollback command can be entirely disabled by setting the
6371 The rollback command can be entirely disabled by setting the
6343 ``ui.rollback`` configuration setting to false. If you're here
6372 ``ui.rollback`` configuration setting to false. If you're here
6344 because you want to use rollback and it's disabled, you can
6373 because you want to use rollback and it's disabled, you can
6345 re-enable the command by setting ``ui.rollback`` to true.
6374 re-enable the command by setting ``ui.rollback`` to true.
6346
6375
6347 This command is not intended for use on public repositories. Once
6376 This command is not intended for use on public repositories. Once
6348 changes are visible for pull by other users, rolling a transaction
6377 changes are visible for pull by other users, rolling a transaction
6349 back locally is ineffective (someone else may already have pulled
6378 back locally is ineffective (someone else may already have pulled
6350 the changes). Furthermore, a race is possible with readers of the
6379 the changes). Furthermore, a race is possible with readers of the
6351 repository; for example an in-progress pull from the repository
6380 repository; for example an in-progress pull from the repository
6352 may fail if a rollback is performed.
6381 may fail if a rollback is performed.
6353
6382
6354 Returns 0 on success, 1 if no rollback data is available.
6383 Returns 0 on success, 1 if no rollback data is available.
6355 """
6384 """
6356 if not ui.configbool(b'ui', b'rollback'):
6385 if not ui.configbool(b'ui', b'rollback'):
6357 raise error.Abort(
6386 raise error.Abort(
6358 _(b'rollback is disabled because it is unsafe'),
6387 _(b'rollback is disabled because it is unsafe'),
6359 hint=b'see `hg help -v rollback` for information',
6388 hint=b'see `hg help -v rollback` for information',
6360 )
6389 )
6361 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6390 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6362
6391
6363
6392
6364 @command(
6393 @command(
6365 b'root',
6394 b'root',
6366 [] + formatteropts,
6395 [] + formatteropts,
6367 intents={INTENT_READONLY},
6396 intents={INTENT_READONLY},
6368 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6397 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6369 )
6398 )
6370 def root(ui, repo, **opts):
6399 def root(ui, repo, **opts):
6371 """print the root (top) of the current working directory
6400 """print the root (top) of the current working directory
6372
6401
6373 Print the root directory of the current repository.
6402 Print the root directory of the current repository.
6374
6403
6375 .. container:: verbose
6404 .. container:: verbose
6376
6405
6377 Template:
6406 Template:
6378
6407
6379 The following keywords are supported in addition to the common template
6408 The following keywords are supported in addition to the common template
6380 keywords and functions. See also :hg:`help templates`.
6409 keywords and functions. See also :hg:`help templates`.
6381
6410
6382 :hgpath: String. Path to the .hg directory.
6411 :hgpath: String. Path to the .hg directory.
6383 :storepath: String. Path to the directory holding versioned data.
6412 :storepath: String. Path to the directory holding versioned data.
6384
6413
6385 Returns 0 on success.
6414 Returns 0 on success.
6386 """
6415 """
6387 opts = pycompat.byteskwargs(opts)
6416 opts = pycompat.byteskwargs(opts)
6388 with ui.formatter(b'root', opts) as fm:
6417 with ui.formatter(b'root', opts) as fm:
6389 fm.startitem()
6418 fm.startitem()
6390 fm.write(b'reporoot', b'%s\n', repo.root)
6419 fm.write(b'reporoot', b'%s\n', repo.root)
6391 fm.data(hgpath=repo.path, storepath=repo.spath)
6420 fm.data(hgpath=repo.path, storepath=repo.spath)
6392
6421
6393
6422
6394 @command(
6423 @command(
6395 b'serve',
6424 b'serve',
6396 [
6425 [
6397 (
6426 (
6398 b'A',
6427 b'A',
6399 b'accesslog',
6428 b'accesslog',
6400 b'',
6429 b'',
6401 _(b'name of access log file to write to'),
6430 _(b'name of access log file to write to'),
6402 _(b'FILE'),
6431 _(b'FILE'),
6403 ),
6432 ),
6404 (b'd', b'daemon', None, _(b'run server in background')),
6433 (b'd', b'daemon', None, _(b'run server in background')),
6405 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6434 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6406 (
6435 (
6407 b'E',
6436 b'E',
6408 b'errorlog',
6437 b'errorlog',
6409 b'',
6438 b'',
6410 _(b'name of error log file to write to'),
6439 _(b'name of error log file to write to'),
6411 _(b'FILE'),
6440 _(b'FILE'),
6412 ),
6441 ),
6413 # use string type, then we can check if something was passed
6442 # use string type, then we can check if something was passed
6414 (
6443 (
6415 b'p',
6444 b'p',
6416 b'port',
6445 b'port',
6417 b'',
6446 b'',
6418 _(b'port to listen on (default: 8000)'),
6447 _(b'port to listen on (default: 8000)'),
6419 _(b'PORT'),
6448 _(b'PORT'),
6420 ),
6449 ),
6421 (
6450 (
6422 b'a',
6451 b'a',
6423 b'address',
6452 b'address',
6424 b'',
6453 b'',
6425 _(b'address to listen on (default: all interfaces)'),
6454 _(b'address to listen on (default: all interfaces)'),
6426 _(b'ADDR'),
6455 _(b'ADDR'),
6427 ),
6456 ),
6428 (
6457 (
6429 b'',
6458 b'',
6430 b'prefix',
6459 b'prefix',
6431 b'',
6460 b'',
6432 _(b'prefix path to serve from (default: server root)'),
6461 _(b'prefix path to serve from (default: server root)'),
6433 _(b'PREFIX'),
6462 _(b'PREFIX'),
6434 ),
6463 ),
6435 (
6464 (
6436 b'n',
6465 b'n',
6437 b'name',
6466 b'name',
6438 b'',
6467 b'',
6439 _(b'name to show in web pages (default: working directory)'),
6468 _(b'name to show in web pages (default: working directory)'),
6440 _(b'NAME'),
6469 _(b'NAME'),
6441 ),
6470 ),
6442 (
6471 (
6443 b'',
6472 b'',
6444 b'web-conf',
6473 b'web-conf',
6445 b'',
6474 b'',
6446 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6475 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6447 _(b'FILE'),
6476 _(b'FILE'),
6448 ),
6477 ),
6449 (
6478 (
6450 b'',
6479 b'',
6451 b'webdir-conf',
6480 b'webdir-conf',
6452 b'',
6481 b'',
6453 _(b'name of the hgweb config file (DEPRECATED)'),
6482 _(b'name of the hgweb config file (DEPRECATED)'),
6454 _(b'FILE'),
6483 _(b'FILE'),
6455 ),
6484 ),
6456 (
6485 (
6457 b'',
6486 b'',
6458 b'pid-file',
6487 b'pid-file',
6459 b'',
6488 b'',
6460 _(b'name of file to write process ID to'),
6489 _(b'name of file to write process ID to'),
6461 _(b'FILE'),
6490 _(b'FILE'),
6462 ),
6491 ),
6463 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6492 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6464 (
6493 (
6465 b'',
6494 b'',
6466 b'cmdserver',
6495 b'cmdserver',
6467 b'',
6496 b'',
6468 _(b'for remote clients (ADVANCED)'),
6497 _(b'for remote clients (ADVANCED)'),
6469 _(b'MODE'),
6498 _(b'MODE'),
6470 ),
6499 ),
6471 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6500 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6472 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6501 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6473 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6502 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6474 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6503 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6475 (b'', b'print-url', None, _(b'start and print only the URL')),
6504 (b'', b'print-url', None, _(b'start and print only the URL')),
6476 ]
6505 ]
6477 + subrepoopts,
6506 + subrepoopts,
6478 _(b'[OPTION]...'),
6507 _(b'[OPTION]...'),
6479 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6508 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6480 helpbasic=True,
6509 helpbasic=True,
6481 optionalrepo=True,
6510 optionalrepo=True,
6482 )
6511 )
6483 def serve(ui, repo, **opts):
6512 def serve(ui, repo, **opts):
6484 """start stand-alone webserver
6513 """start stand-alone webserver
6485
6514
6486 Start a local HTTP repository browser and pull server. You can use
6515 Start a local HTTP repository browser and pull server. You can use
6487 this for ad-hoc sharing and browsing of repositories. It is
6516 this for ad-hoc sharing and browsing of repositories. It is
6488 recommended to use a real web server to serve a repository for
6517 recommended to use a real web server to serve a repository for
6489 longer periods of time.
6518 longer periods of time.
6490
6519
6491 Please note that the server does not implement access control.
6520 Please note that the server does not implement access control.
6492 This means that, by default, anybody can read from the server and
6521 This means that, by default, anybody can read from the server and
6493 nobody can write to it by default. Set the ``web.allow-push``
6522 nobody can write to it by default. Set the ``web.allow-push``
6494 option to ``*`` to allow everybody to push to the server. You
6523 option to ``*`` to allow everybody to push to the server. You
6495 should use a real web server if you need to authenticate users.
6524 should use a real web server if you need to authenticate users.
6496
6525
6497 By default, the server logs accesses to stdout and errors to
6526 By default, the server logs accesses to stdout and errors to
6498 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6527 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6499 files.
6528 files.
6500
6529
6501 To have the server choose a free port number to listen on, specify
6530 To have the server choose a free port number to listen on, specify
6502 a port number of 0; in this case, the server will print the port
6531 a port number of 0; in this case, the server will print the port
6503 number it uses.
6532 number it uses.
6504
6533
6505 Returns 0 on success.
6534 Returns 0 on success.
6506 """
6535 """
6507
6536
6508 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6537 cmdutil.check_incompatible_arguments(opts, 'stdio', ['cmdserver'])
6509 opts = pycompat.byteskwargs(opts)
6538 opts = pycompat.byteskwargs(opts)
6510 if opts[b"print_url"] and ui.verbose:
6539 if opts[b"print_url"] and ui.verbose:
6511 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6540 raise error.InputError(_(b"cannot use --print-url with --verbose"))
6512
6541
6513 if opts[b"stdio"]:
6542 if opts[b"stdio"]:
6514 if repo is None:
6543 if repo is None:
6515 raise error.RepoError(
6544 raise error.RepoError(
6516 _(b"there is no Mercurial repository here (.hg not found)")
6545 _(b"there is no Mercurial repository here (.hg not found)")
6517 )
6546 )
6518 s = wireprotoserver.sshserver(ui, repo)
6547 s = wireprotoserver.sshserver(ui, repo)
6519 s.serve_forever()
6548 s.serve_forever()
6520 return
6549 return
6521
6550
6522 service = server.createservice(ui, repo, opts)
6551 service = server.createservice(ui, repo, opts)
6523 return server.runservice(opts, initfn=service.init, runfn=service.run)
6552 return server.runservice(opts, initfn=service.init, runfn=service.run)
6524
6553
6525
6554
6526 @command(
6555 @command(
6527 b'shelve',
6556 b'shelve',
6528 [
6557 [
6529 (
6558 (
6530 b'A',
6559 b'A',
6531 b'addremove',
6560 b'addremove',
6532 None,
6561 None,
6533 _(b'mark new/missing files as added/removed before shelving'),
6562 _(b'mark new/missing files as added/removed before shelving'),
6534 ),
6563 ),
6535 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6564 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6536 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6565 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6537 (
6566 (
6538 b'',
6567 b'',
6539 b'date',
6568 b'date',
6540 b'',
6569 b'',
6541 _(b'shelve with the specified commit date'),
6570 _(b'shelve with the specified commit date'),
6542 _(b'DATE'),
6571 _(b'DATE'),
6543 ),
6572 ),
6544 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6573 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6545 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6574 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6546 (
6575 (
6547 b'k',
6576 b'k',
6548 b'keep',
6577 b'keep',
6549 False,
6578 False,
6550 _(b'shelve, but keep changes in the working directory'),
6579 _(b'shelve, but keep changes in the working directory'),
6551 ),
6580 ),
6552 (b'l', b'list', None, _(b'list current shelves')),
6581 (b'l', b'list', None, _(b'list current shelves')),
6553 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6582 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6554 (
6583 (
6555 b'n',
6584 b'n',
6556 b'name',
6585 b'name',
6557 b'',
6586 b'',
6558 _(b'use the given name for the shelved commit'),
6587 _(b'use the given name for the shelved commit'),
6559 _(b'NAME'),
6588 _(b'NAME'),
6560 ),
6589 ),
6561 (
6590 (
6562 b'p',
6591 b'p',
6563 b'patch',
6592 b'patch',
6564 None,
6593 None,
6565 _(
6594 _(
6566 b'output patches for changes (provide the names of the shelved '
6595 b'output patches for changes (provide the names of the shelved '
6567 b'changes as positional arguments)'
6596 b'changes as positional arguments)'
6568 ),
6597 ),
6569 ),
6598 ),
6570 (b'i', b'interactive', None, _(b'interactive mode')),
6599 (b'i', b'interactive', None, _(b'interactive mode')),
6571 (
6600 (
6572 b'',
6601 b'',
6573 b'stat',
6602 b'stat',
6574 None,
6603 None,
6575 _(
6604 _(
6576 b'output diffstat-style summary of changes (provide the names of '
6605 b'output diffstat-style summary of changes (provide the names of '
6577 b'the shelved changes as positional arguments)'
6606 b'the shelved changes as positional arguments)'
6578 ),
6607 ),
6579 ),
6608 ),
6580 ]
6609 ]
6581 + cmdutil.walkopts,
6610 + cmdutil.walkopts,
6582 _(b'hg shelve [OPTION]... [FILE]...'),
6611 _(b'hg shelve [OPTION]... [FILE]...'),
6583 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6612 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6584 )
6613 )
6585 def shelve(ui, repo, *pats, **opts):
6614 def shelve(ui, repo, *pats, **opts):
6586 """save and set aside changes from the working directory
6615 """save and set aside changes from the working directory
6587
6616
6588 Shelving takes files that "hg status" reports as not clean, saves
6617 Shelving takes files that "hg status" reports as not clean, saves
6589 the modifications to a bundle (a shelved change), and reverts the
6618 the modifications to a bundle (a shelved change), and reverts the
6590 files so that their state in the working directory becomes clean.
6619 files so that their state in the working directory becomes clean.
6591
6620
6592 To restore these changes to the working directory, using "hg
6621 To restore these changes to the working directory, using "hg
6593 unshelve"; this will work even if you switch to a different
6622 unshelve"; this will work even if you switch to a different
6594 commit.
6623 commit.
6595
6624
6596 When no files are specified, "hg shelve" saves all not-clean
6625 When no files are specified, "hg shelve" saves all not-clean
6597 files. If specific files or directories are named, only changes to
6626 files. If specific files or directories are named, only changes to
6598 those files are shelved.
6627 those files are shelved.
6599
6628
6600 In bare shelve (when no files are specified, without interactive,
6629 In bare shelve (when no files are specified, without interactive,
6601 include and exclude option), shelving remembers information if the
6630 include and exclude option), shelving remembers information if the
6602 working directory was on newly created branch, in other words working
6631 working directory was on newly created branch, in other words working
6603 directory was on different branch than its first parent. In this
6632 directory was on different branch than its first parent. In this
6604 situation unshelving restores branch information to the working directory.
6633 situation unshelving restores branch information to the working directory.
6605
6634
6606 Each shelved change has a name that makes it easier to find later.
6635 Each shelved change has a name that makes it easier to find later.
6607 The name of a shelved change defaults to being based on the active
6636 The name of a shelved change defaults to being based on the active
6608 bookmark, or if there is no active bookmark, the current named
6637 bookmark, or if there is no active bookmark, the current named
6609 branch. To specify a different name, use ``--name``.
6638 branch. To specify a different name, use ``--name``.
6610
6639
6611 To see a list of existing shelved changes, use the ``--list``
6640 To see a list of existing shelved changes, use the ``--list``
6612 option. For each shelved change, this will print its name, age,
6641 option. For each shelved change, this will print its name, age,
6613 and description; use ``--patch`` or ``--stat`` for more details.
6642 and description; use ``--patch`` or ``--stat`` for more details.
6614
6643
6615 To delete specific shelved changes, use ``--delete``. To delete
6644 To delete specific shelved changes, use ``--delete``. To delete
6616 all shelved changes, use ``--cleanup``.
6645 all shelved changes, use ``--cleanup``.
6617 """
6646 """
6618 opts = pycompat.byteskwargs(opts)
6647 opts = pycompat.byteskwargs(opts)
6619 allowables = [
6648 allowables = [
6620 (b'addremove', {b'create'}), # 'create' is pseudo action
6649 (b'addremove', {b'create'}), # 'create' is pseudo action
6621 (b'unknown', {b'create'}),
6650 (b'unknown', {b'create'}),
6622 (b'cleanup', {b'cleanup'}),
6651 (b'cleanup', {b'cleanup'}),
6623 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6652 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6624 (b'delete', {b'delete'}),
6653 (b'delete', {b'delete'}),
6625 (b'edit', {b'create'}),
6654 (b'edit', {b'create'}),
6626 (b'keep', {b'create'}),
6655 (b'keep', {b'create'}),
6627 (b'list', {b'list'}),
6656 (b'list', {b'list'}),
6628 (b'message', {b'create'}),
6657 (b'message', {b'create'}),
6629 (b'name', {b'create'}),
6658 (b'name', {b'create'}),
6630 (b'patch', {b'patch', b'list'}),
6659 (b'patch', {b'patch', b'list'}),
6631 (b'stat', {b'stat', b'list'}),
6660 (b'stat', {b'stat', b'list'}),
6632 ]
6661 ]
6633
6662
6634 def checkopt(opt):
6663 def checkopt(opt):
6635 if opts.get(opt):
6664 if opts.get(opt):
6636 for i, allowable in allowables:
6665 for i, allowable in allowables:
6637 if opts[i] and opt not in allowable:
6666 if opts[i] and opt not in allowable:
6638 raise error.InputError(
6667 raise error.InputError(
6639 _(
6668 _(
6640 b"options '--%s' and '--%s' may not be "
6669 b"options '--%s' and '--%s' may not be "
6641 b"used together"
6670 b"used together"
6642 )
6671 )
6643 % (opt, i)
6672 % (opt, i)
6644 )
6673 )
6645 return True
6674 return True
6646
6675
6647 if checkopt(b'cleanup'):
6676 if checkopt(b'cleanup'):
6648 if pats:
6677 if pats:
6649 raise error.InputError(
6678 raise error.InputError(
6650 _(b"cannot specify names when using '--cleanup'")
6679 _(b"cannot specify names when using '--cleanup'")
6651 )
6680 )
6652 return shelvemod.cleanupcmd(ui, repo)
6681 return shelvemod.cleanupcmd(ui, repo)
6653 elif checkopt(b'delete'):
6682 elif checkopt(b'delete'):
6654 return shelvemod.deletecmd(ui, repo, pats)
6683 return shelvemod.deletecmd(ui, repo, pats)
6655 elif checkopt(b'list'):
6684 elif checkopt(b'list'):
6656 return shelvemod.listcmd(ui, repo, pats, opts)
6685 return shelvemod.listcmd(ui, repo, pats, opts)
6657 elif checkopt(b'patch') or checkopt(b'stat'):
6686 elif checkopt(b'patch') or checkopt(b'stat'):
6658 return shelvemod.patchcmds(ui, repo, pats, opts)
6687 return shelvemod.patchcmds(ui, repo, pats, opts)
6659 else:
6688 else:
6660 return shelvemod.createcmd(ui, repo, pats, opts)
6689 return shelvemod.createcmd(ui, repo, pats, opts)
6661
6690
6662
6691
6663 _NOTTERSE = b'nothing'
6692 _NOTTERSE = b'nothing'
6664
6693
6665
6694
6666 @command(
6695 @command(
6667 b'status|st',
6696 b'status|st',
6668 [
6697 [
6669 (b'A', b'all', None, _(b'show status of all files')),
6698 (b'A', b'all', None, _(b'show status of all files')),
6670 (b'm', b'modified', None, _(b'show only modified files')),
6699 (b'm', b'modified', None, _(b'show only modified files')),
6671 (b'a', b'added', None, _(b'show only added files')),
6700 (b'a', b'added', None, _(b'show only added files')),
6672 (b'r', b'removed', None, _(b'show only removed files')),
6701 (b'r', b'removed', None, _(b'show only removed files')),
6673 (b'd', b'deleted', None, _(b'show only missing files')),
6702 (b'd', b'deleted', None, _(b'show only missing files')),
6674 (b'c', b'clean', None, _(b'show only files without changes')),
6703 (b'c', b'clean', None, _(b'show only files without changes')),
6675 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6704 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6676 (b'i', b'ignored', None, _(b'show only ignored files')),
6705 (b'i', b'ignored', None, _(b'show only ignored files')),
6677 (b'n', b'no-status', None, _(b'hide status prefix')),
6706 (b'n', b'no-status', None, _(b'hide status prefix')),
6678 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6707 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6679 (
6708 (
6680 b'C',
6709 b'C',
6681 b'copies',
6710 b'copies',
6682 None,
6711 None,
6683 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6712 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6684 ),
6713 ),
6685 (
6714 (
6686 b'0',
6715 b'0',
6687 b'print0',
6716 b'print0',
6688 None,
6717 None,
6689 _(b'end filenames with NUL, for use with xargs'),
6718 _(b'end filenames with NUL, for use with xargs'),
6690 ),
6719 ),
6691 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6720 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6692 (
6721 (
6693 b'',
6722 b'',
6694 b'change',
6723 b'change',
6695 b'',
6724 b'',
6696 _(b'list the changed files of a revision'),
6725 _(b'list the changed files of a revision'),
6697 _(b'REV'),
6726 _(b'REV'),
6698 ),
6727 ),
6699 ]
6728 ]
6700 + walkopts
6729 + walkopts
6701 + subrepoopts
6730 + subrepoopts
6702 + formatteropts,
6731 + formatteropts,
6703 _(b'[OPTION]... [FILE]...'),
6732 _(b'[OPTION]... [FILE]...'),
6704 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6733 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6705 helpbasic=True,
6734 helpbasic=True,
6706 inferrepo=True,
6735 inferrepo=True,
6707 intents={INTENT_READONLY},
6736 intents={INTENT_READONLY},
6708 )
6737 )
6709 def status(ui, repo, *pats, **opts):
6738 def status(ui, repo, *pats, **opts):
6710 """show changed files in the working directory
6739 """show changed files in the working directory
6711
6740
6712 Show status of files in the repository. If names are given, only
6741 Show status of files in the repository. If names are given, only
6713 files that match are shown. Files that are clean or ignored or
6742 files that match are shown. Files that are clean or ignored or
6714 the source of a copy/move operation, are not listed unless
6743 the source of a copy/move operation, are not listed unless
6715 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6744 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6716 Unless options described with "show only ..." are given, the
6745 Unless options described with "show only ..." are given, the
6717 options -mardu are used.
6746 options -mardu are used.
6718
6747
6719 Option -q/--quiet hides untracked (unknown and ignored) files
6748 Option -q/--quiet hides untracked (unknown and ignored) files
6720 unless explicitly requested with -u/--unknown or -i/--ignored.
6749 unless explicitly requested with -u/--unknown or -i/--ignored.
6721
6750
6722 .. note::
6751 .. note::
6723
6752
6724 :hg:`status` may appear to disagree with diff if permissions have
6753 :hg:`status` may appear to disagree with diff if permissions have
6725 changed or a merge has occurred. The standard diff format does
6754 changed or a merge has occurred. The standard diff format does
6726 not report permission changes and diff only reports changes
6755 not report permission changes and diff only reports changes
6727 relative to one merge parent.
6756 relative to one merge parent.
6728
6757
6729 If one revision is given, it is used as the base revision.
6758 If one revision is given, it is used as the base revision.
6730 If two revisions are given, the differences between them are
6759 If two revisions are given, the differences between them are
6731 shown. The --change option can also be used as a shortcut to list
6760 shown. The --change option can also be used as a shortcut to list
6732 the changed files of a revision from its first parent.
6761 the changed files of a revision from its first parent.
6733
6762
6734 The codes used to show the status of files are::
6763 The codes used to show the status of files are::
6735
6764
6736 M = modified
6765 M = modified
6737 A = added
6766 A = added
6738 R = removed
6767 R = removed
6739 C = clean
6768 C = clean
6740 ! = missing (deleted by non-hg command, but still tracked)
6769 ! = missing (deleted by non-hg command, but still tracked)
6741 ? = not tracked
6770 ? = not tracked
6742 I = ignored
6771 I = ignored
6743 = origin of the previous file (with --copies)
6772 = origin of the previous file (with --copies)
6744
6773
6745 .. container:: verbose
6774 .. container:: verbose
6746
6775
6747 The -t/--terse option abbreviates the output by showing only the directory
6776 The -t/--terse option abbreviates the output by showing only the directory
6748 name if all the files in it share the same status. The option takes an
6777 name if all the files in it share the same status. The option takes an
6749 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6778 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6750 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6779 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6751 for 'ignored' and 'c' for clean.
6780 for 'ignored' and 'c' for clean.
6752
6781
6753 It abbreviates only those statuses which are passed. Note that clean and
6782 It abbreviates only those statuses which are passed. Note that clean and
6754 ignored files are not displayed with '--terse ic' unless the -c/--clean
6783 ignored files are not displayed with '--terse ic' unless the -c/--clean
6755 and -i/--ignored options are also used.
6784 and -i/--ignored options are also used.
6756
6785
6757 The -v/--verbose option shows information when the repository is in an
6786 The -v/--verbose option shows information when the repository is in an
6758 unfinished merge, shelve, rebase state etc. You can have this behavior
6787 unfinished merge, shelve, rebase state etc. You can have this behavior
6759 turned on by default by enabling the ``commands.status.verbose`` option.
6788 turned on by default by enabling the ``commands.status.verbose`` option.
6760
6789
6761 You can skip displaying some of these states by setting
6790 You can skip displaying some of these states by setting
6762 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6791 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6763 'histedit', 'merge', 'rebase', or 'unshelve'.
6792 'histedit', 'merge', 'rebase', or 'unshelve'.
6764
6793
6765 Template:
6794 Template:
6766
6795
6767 The following keywords are supported in addition to the common template
6796 The following keywords are supported in addition to the common template
6768 keywords and functions. See also :hg:`help templates`.
6797 keywords and functions. See also :hg:`help templates`.
6769
6798
6770 :path: String. Repository-absolute path of the file.
6799 :path: String. Repository-absolute path of the file.
6771 :source: String. Repository-absolute path of the file originated from.
6800 :source: String. Repository-absolute path of the file originated from.
6772 Available if ``--copies`` is specified.
6801 Available if ``--copies`` is specified.
6773 :status: String. Character denoting file's status.
6802 :status: String. Character denoting file's status.
6774
6803
6775 Examples:
6804 Examples:
6776
6805
6777 - show changes in the working directory relative to a
6806 - show changes in the working directory relative to a
6778 changeset::
6807 changeset::
6779
6808
6780 hg status --rev 9353
6809 hg status --rev 9353
6781
6810
6782 - show changes in the working directory relative to the
6811 - show changes in the working directory relative to the
6783 current directory (see :hg:`help patterns` for more information)::
6812 current directory (see :hg:`help patterns` for more information)::
6784
6813
6785 hg status re:
6814 hg status re:
6786
6815
6787 - show all changes including copies in an existing changeset::
6816 - show all changes including copies in an existing changeset::
6788
6817
6789 hg status --copies --change 9353
6818 hg status --copies --change 9353
6790
6819
6791 - get a NUL separated list of added files, suitable for xargs::
6820 - get a NUL separated list of added files, suitable for xargs::
6792
6821
6793 hg status -an0
6822 hg status -an0
6794
6823
6795 - show more information about the repository status, abbreviating
6824 - show more information about the repository status, abbreviating
6796 added, removed, modified, deleted, and untracked paths::
6825 added, removed, modified, deleted, and untracked paths::
6797
6826
6798 hg status -v -t mardu
6827 hg status -v -t mardu
6799
6828
6800 Returns 0 on success.
6829 Returns 0 on success.
6801
6830
6802 """
6831 """
6803
6832
6804 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6833 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6805 opts = pycompat.byteskwargs(opts)
6834 opts = pycompat.byteskwargs(opts)
6806 revs = opts.get(b'rev')
6835 revs = opts.get(b'rev')
6807 change = opts.get(b'change')
6836 change = opts.get(b'change')
6808 terse = opts.get(b'terse')
6837 terse = opts.get(b'terse')
6809 if terse is _NOTTERSE:
6838 if terse is _NOTTERSE:
6810 if revs:
6839 if revs:
6811 terse = b''
6840 terse = b''
6812 else:
6841 else:
6813 terse = ui.config(b'commands', b'status.terse')
6842 terse = ui.config(b'commands', b'status.terse')
6814
6843
6815 if revs and terse:
6844 if revs and terse:
6816 msg = _(b'cannot use --terse with --rev')
6845 msg = _(b'cannot use --terse with --rev')
6817 raise error.InputError(msg)
6846 raise error.InputError(msg)
6818 elif change:
6847 elif change:
6819 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6848 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6820 ctx2 = scmutil.revsingle(repo, change, None)
6849 ctx2 = scmutil.revsingle(repo, change, None)
6821 ctx1 = ctx2.p1()
6850 ctx1 = ctx2.p1()
6822 else:
6851 else:
6823 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6852 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6824 ctx1, ctx2 = scmutil.revpair(repo, revs)
6853 ctx1, ctx2 = scmutil.revpair(repo, revs)
6825
6854
6826 forcerelativevalue = None
6855 forcerelativevalue = None
6827 if ui.hasconfig(b'commands', b'status.relative'):
6856 if ui.hasconfig(b'commands', b'status.relative'):
6828 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6857 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6829 uipathfn = scmutil.getuipathfn(
6858 uipathfn = scmutil.getuipathfn(
6830 repo,
6859 repo,
6831 legacyrelativevalue=bool(pats),
6860 legacyrelativevalue=bool(pats),
6832 forcerelativevalue=forcerelativevalue,
6861 forcerelativevalue=forcerelativevalue,
6833 )
6862 )
6834
6863
6835 if opts.get(b'print0'):
6864 if opts.get(b'print0'):
6836 end = b'\0'
6865 end = b'\0'
6837 else:
6866 else:
6838 end = b'\n'
6867 end = b'\n'
6839 states = b'modified added removed deleted unknown ignored clean'.split()
6868 states = b'modified added removed deleted unknown ignored clean'.split()
6840 show = [k for k in states if opts.get(k)]
6869 show = [k for k in states if opts.get(k)]
6841 if opts.get(b'all'):
6870 if opts.get(b'all'):
6842 show += ui.quiet and (states[:4] + [b'clean']) or states
6871 show += ui.quiet and (states[:4] + [b'clean']) or states
6843
6872
6844 if not show:
6873 if not show:
6845 if ui.quiet:
6874 if ui.quiet:
6846 show = states[:4]
6875 show = states[:4]
6847 else:
6876 else:
6848 show = states[:5]
6877 show = states[:5]
6849
6878
6850 m = scmutil.match(ctx2, pats, opts)
6879 m = scmutil.match(ctx2, pats, opts)
6851 if terse:
6880 if terse:
6852 # we need to compute clean and unknown to terse
6881 # we need to compute clean and unknown to terse
6853 stat = repo.status(
6882 stat = repo.status(
6854 ctx1.node(),
6883 ctx1.node(),
6855 ctx2.node(),
6884 ctx2.node(),
6856 m,
6885 m,
6857 b'ignored' in show or b'i' in terse,
6886 b'ignored' in show or b'i' in terse,
6858 clean=True,
6887 clean=True,
6859 unknown=True,
6888 unknown=True,
6860 listsubrepos=opts.get(b'subrepos'),
6889 listsubrepos=opts.get(b'subrepos'),
6861 )
6890 )
6862
6891
6863 stat = cmdutil.tersedir(stat, terse)
6892 stat = cmdutil.tersedir(stat, terse)
6864 else:
6893 else:
6865 stat = repo.status(
6894 stat = repo.status(
6866 ctx1.node(),
6895 ctx1.node(),
6867 ctx2.node(),
6896 ctx2.node(),
6868 m,
6897 m,
6869 b'ignored' in show,
6898 b'ignored' in show,
6870 b'clean' in show,
6899 b'clean' in show,
6871 b'unknown' in show,
6900 b'unknown' in show,
6872 opts.get(b'subrepos'),
6901 opts.get(b'subrepos'),
6873 )
6902 )
6874
6903
6875 changestates = zip(
6904 changestates = zip(
6876 states,
6905 states,
6877 pycompat.iterbytestr(b'MAR!?IC'),
6906 pycompat.iterbytestr(b'MAR!?IC'),
6878 [getattr(stat, s.decode('utf8')) for s in states],
6907 [getattr(stat, s.decode('utf8')) for s in states],
6879 )
6908 )
6880
6909
6881 copy = {}
6910 copy = {}
6882 if (
6911 if (
6883 opts.get(b'all')
6912 opts.get(b'all')
6884 or opts.get(b'copies')
6913 or opts.get(b'copies')
6885 or ui.configbool(b'ui', b'statuscopies')
6914 or ui.configbool(b'ui', b'statuscopies')
6886 ) and not opts.get(b'no_status'):
6915 ) and not opts.get(b'no_status'):
6887 copy = copies.pathcopies(ctx1, ctx2, m)
6916 copy = copies.pathcopies(ctx1, ctx2, m)
6888
6917
6889 morestatus = None
6918 morestatus = None
6890 if (
6919 if (
6891 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
6920 (ui.verbose or ui.configbool(b'commands', b'status.verbose'))
6892 and not ui.plain()
6921 and not ui.plain()
6893 and not opts.get(b'print0')
6922 and not opts.get(b'print0')
6894 ):
6923 ):
6895 morestatus = cmdutil.readmorestatus(repo)
6924 morestatus = cmdutil.readmorestatus(repo)
6896
6925
6897 ui.pager(b'status')
6926 ui.pager(b'status')
6898 fm = ui.formatter(b'status', opts)
6927 fm = ui.formatter(b'status', opts)
6899 fmt = b'%s' + end
6928 fmt = b'%s' + end
6900 showchar = not opts.get(b'no_status')
6929 showchar = not opts.get(b'no_status')
6901
6930
6902 for state, char, files in changestates:
6931 for state, char, files in changestates:
6903 if state in show:
6932 if state in show:
6904 label = b'status.' + state
6933 label = b'status.' + state
6905 for f in files:
6934 for f in files:
6906 fm.startitem()
6935 fm.startitem()
6907 fm.context(ctx=ctx2)
6936 fm.context(ctx=ctx2)
6908 fm.data(itemtype=b'file', path=f)
6937 fm.data(itemtype=b'file', path=f)
6909 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6938 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6910 fm.plain(fmt % uipathfn(f), label=label)
6939 fm.plain(fmt % uipathfn(f), label=label)
6911 if f in copy:
6940 if f in copy:
6912 fm.data(source=copy[f])
6941 fm.data(source=copy[f])
6913 fm.plain(
6942 fm.plain(
6914 (b' %s' + end) % uipathfn(copy[f]),
6943 (b' %s' + end) % uipathfn(copy[f]),
6915 label=b'status.copied',
6944 label=b'status.copied',
6916 )
6945 )
6917 if morestatus:
6946 if morestatus:
6918 morestatus.formatfile(f, fm)
6947 morestatus.formatfile(f, fm)
6919
6948
6920 if morestatus:
6949 if morestatus:
6921 morestatus.formatfooter(fm)
6950 morestatus.formatfooter(fm)
6922 fm.end()
6951 fm.end()
6923
6952
6924
6953
6925 @command(
6954 @command(
6926 b'summary|sum',
6955 b'summary|sum',
6927 [(b'', b'remote', None, _(b'check for push and pull'))],
6956 [(b'', b'remote', None, _(b'check for push and pull'))],
6928 b'[--remote]',
6957 b'[--remote]',
6929 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6958 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6930 helpbasic=True,
6959 helpbasic=True,
6931 intents={INTENT_READONLY},
6960 intents={INTENT_READONLY},
6932 )
6961 )
6933 def summary(ui, repo, **opts):
6962 def summary(ui, repo, **opts):
6934 """summarize working directory state
6963 """summarize working directory state
6935
6964
6936 This generates a brief summary of the working directory state,
6965 This generates a brief summary of the working directory state,
6937 including parents, branch, commit status, phase and available updates.
6966 including parents, branch, commit status, phase and available updates.
6938
6967
6939 With the --remote option, this will check the default paths for
6968 With the --remote option, this will check the default paths for
6940 incoming and outgoing changes. This can be time-consuming.
6969 incoming and outgoing changes. This can be time-consuming.
6941
6970
6942 Returns 0 on success.
6971 Returns 0 on success.
6943 """
6972 """
6944
6973
6945 opts = pycompat.byteskwargs(opts)
6974 opts = pycompat.byteskwargs(opts)
6946 ui.pager(b'summary')
6975 ui.pager(b'summary')
6947 ctx = repo[None]
6976 ctx = repo[None]
6948 parents = ctx.parents()
6977 parents = ctx.parents()
6949 pnode = parents[0].node()
6978 pnode = parents[0].node()
6950 marks = []
6979 marks = []
6951
6980
6952 try:
6981 try:
6953 ms = mergestatemod.mergestate.read(repo)
6982 ms = mergestatemod.mergestate.read(repo)
6954 except error.UnsupportedMergeRecords as e:
6983 except error.UnsupportedMergeRecords as e:
6955 s = b' '.join(e.recordtypes)
6984 s = b' '.join(e.recordtypes)
6956 ui.warn(
6985 ui.warn(
6957 _(b'warning: merge state has unsupported record types: %s\n') % s
6986 _(b'warning: merge state has unsupported record types: %s\n') % s
6958 )
6987 )
6959 unresolved = []
6988 unresolved = []
6960 else:
6989 else:
6961 unresolved = list(ms.unresolved())
6990 unresolved = list(ms.unresolved())
6962
6991
6963 for p in parents:
6992 for p in parents:
6964 # label with log.changeset (instead of log.parent) since this
6993 # label with log.changeset (instead of log.parent) since this
6965 # shows a working directory parent *changeset*:
6994 # shows a working directory parent *changeset*:
6966 # i18n: column positioning for "hg summary"
6995 # i18n: column positioning for "hg summary"
6967 ui.write(
6996 ui.write(
6968 _(b'parent: %d:%s ') % (p.rev(), p),
6997 _(b'parent: %d:%s ') % (p.rev(), p),
6969 label=logcmdutil.changesetlabels(p),
6998 label=logcmdutil.changesetlabels(p),
6970 )
6999 )
6971 ui.write(b' '.join(p.tags()), label=b'log.tag')
7000 ui.write(b' '.join(p.tags()), label=b'log.tag')
6972 if p.bookmarks():
7001 if p.bookmarks():
6973 marks.extend(p.bookmarks())
7002 marks.extend(p.bookmarks())
6974 if p.rev() == -1:
7003 if p.rev() == -1:
6975 if not len(repo):
7004 if not len(repo):
6976 ui.write(_(b' (empty repository)'))
7005 ui.write(_(b' (empty repository)'))
6977 else:
7006 else:
6978 ui.write(_(b' (no revision checked out)'))
7007 ui.write(_(b' (no revision checked out)'))
6979 if p.obsolete():
7008 if p.obsolete():
6980 ui.write(_(b' (obsolete)'))
7009 ui.write(_(b' (obsolete)'))
6981 if p.isunstable():
7010 if p.isunstable():
6982 instabilities = (
7011 instabilities = (
6983 ui.label(instability, b'trouble.%s' % instability)
7012 ui.label(instability, b'trouble.%s' % instability)
6984 for instability in p.instabilities()
7013 for instability in p.instabilities()
6985 )
7014 )
6986 ui.write(b' (' + b', '.join(instabilities) + b')')
7015 ui.write(b' (' + b', '.join(instabilities) + b')')
6987 ui.write(b'\n')
7016 ui.write(b'\n')
6988 if p.description():
7017 if p.description():
6989 ui.status(
7018 ui.status(
6990 b' ' + p.description().splitlines()[0].strip() + b'\n',
7019 b' ' + p.description().splitlines()[0].strip() + b'\n',
6991 label=b'log.summary',
7020 label=b'log.summary',
6992 )
7021 )
6993
7022
6994 branch = ctx.branch()
7023 branch = ctx.branch()
6995 bheads = repo.branchheads(branch)
7024 bheads = repo.branchheads(branch)
6996 # i18n: column positioning for "hg summary"
7025 # i18n: column positioning for "hg summary"
6997 m = _(b'branch: %s\n') % branch
7026 m = _(b'branch: %s\n') % branch
6998 if branch != b'default':
7027 if branch != b'default':
6999 ui.write(m, label=b'log.branch')
7028 ui.write(m, label=b'log.branch')
7000 else:
7029 else:
7001 ui.status(m, label=b'log.branch')
7030 ui.status(m, label=b'log.branch')
7002
7031
7003 if marks:
7032 if marks:
7004 active = repo._activebookmark
7033 active = repo._activebookmark
7005 # i18n: column positioning for "hg summary"
7034 # i18n: column positioning for "hg summary"
7006 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7035 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7007 if active is not None:
7036 if active is not None:
7008 if active in marks:
7037 if active in marks:
7009 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7038 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7010 marks.remove(active)
7039 marks.remove(active)
7011 else:
7040 else:
7012 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7041 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7013 for m in marks:
7042 for m in marks:
7014 ui.write(b' ' + m, label=b'log.bookmark')
7043 ui.write(b' ' + m, label=b'log.bookmark')
7015 ui.write(b'\n', label=b'log.bookmark')
7044 ui.write(b'\n', label=b'log.bookmark')
7016
7045
7017 status = repo.status(unknown=True)
7046 status = repo.status(unknown=True)
7018
7047
7019 c = repo.dirstate.copies()
7048 c = repo.dirstate.copies()
7020 copied, renamed = [], []
7049 copied, renamed = [], []
7021 for d, s in pycompat.iteritems(c):
7050 for d, s in pycompat.iteritems(c):
7022 if s in status.removed:
7051 if s in status.removed:
7023 status.removed.remove(s)
7052 status.removed.remove(s)
7024 renamed.append(d)
7053 renamed.append(d)
7025 else:
7054 else:
7026 copied.append(d)
7055 copied.append(d)
7027 if d in status.added:
7056 if d in status.added:
7028 status.added.remove(d)
7057 status.added.remove(d)
7029
7058
7030 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7059 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7031
7060
7032 labels = [
7061 labels = [
7033 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7062 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7034 (ui.label(_(b'%d added'), b'status.added'), status.added),
7063 (ui.label(_(b'%d added'), b'status.added'), status.added),
7035 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7064 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7036 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7065 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7037 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7066 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7038 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7067 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7039 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7068 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7040 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7069 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7041 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7070 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7042 ]
7071 ]
7043 t = []
7072 t = []
7044 for l, s in labels:
7073 for l, s in labels:
7045 if s:
7074 if s:
7046 t.append(l % len(s))
7075 t.append(l % len(s))
7047
7076
7048 t = b', '.join(t)
7077 t = b', '.join(t)
7049 cleanworkdir = False
7078 cleanworkdir = False
7050
7079
7051 if repo.vfs.exists(b'graftstate'):
7080 if repo.vfs.exists(b'graftstate'):
7052 t += _(b' (graft in progress)')
7081 t += _(b' (graft in progress)')
7053 if repo.vfs.exists(b'updatestate'):
7082 if repo.vfs.exists(b'updatestate'):
7054 t += _(b' (interrupted update)')
7083 t += _(b' (interrupted update)')
7055 elif len(parents) > 1:
7084 elif len(parents) > 1:
7056 t += _(b' (merge)')
7085 t += _(b' (merge)')
7057 elif branch != parents[0].branch():
7086 elif branch != parents[0].branch():
7058 t += _(b' (new branch)')
7087 t += _(b' (new branch)')
7059 elif parents[0].closesbranch() and pnode in repo.branchheads(
7088 elif parents[0].closesbranch() and pnode in repo.branchheads(
7060 branch, closed=True
7089 branch, closed=True
7061 ):
7090 ):
7062 t += _(b' (head closed)')
7091 t += _(b' (head closed)')
7063 elif not (
7092 elif not (
7064 status.modified
7093 status.modified
7065 or status.added
7094 or status.added
7066 or status.removed
7095 or status.removed
7067 or renamed
7096 or renamed
7068 or copied
7097 or copied
7069 or subs
7098 or subs
7070 ):
7099 ):
7071 t += _(b' (clean)')
7100 t += _(b' (clean)')
7072 cleanworkdir = True
7101 cleanworkdir = True
7073 elif pnode not in bheads:
7102 elif pnode not in bheads:
7074 t += _(b' (new branch head)')
7103 t += _(b' (new branch head)')
7075
7104
7076 if parents:
7105 if parents:
7077 pendingphase = max(p.phase() for p in parents)
7106 pendingphase = max(p.phase() for p in parents)
7078 else:
7107 else:
7079 pendingphase = phases.public
7108 pendingphase = phases.public
7080
7109
7081 if pendingphase > phases.newcommitphase(ui):
7110 if pendingphase > phases.newcommitphase(ui):
7082 t += b' (%s)' % phases.phasenames[pendingphase]
7111 t += b' (%s)' % phases.phasenames[pendingphase]
7083
7112
7084 if cleanworkdir:
7113 if cleanworkdir:
7085 # i18n: column positioning for "hg summary"
7114 # i18n: column positioning for "hg summary"
7086 ui.status(_(b'commit: %s\n') % t.strip())
7115 ui.status(_(b'commit: %s\n') % t.strip())
7087 else:
7116 else:
7088 # i18n: column positioning for "hg summary"
7117 # i18n: column positioning for "hg summary"
7089 ui.write(_(b'commit: %s\n') % t.strip())
7118 ui.write(_(b'commit: %s\n') % t.strip())
7090
7119
7091 # all ancestors of branch heads - all ancestors of parent = new csets
7120 # all ancestors of branch heads - all ancestors of parent = new csets
7092 new = len(
7121 new = len(
7093 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7122 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7094 )
7123 )
7095
7124
7096 if new == 0:
7125 if new == 0:
7097 # i18n: column positioning for "hg summary"
7126 # i18n: column positioning for "hg summary"
7098 ui.status(_(b'update: (current)\n'))
7127 ui.status(_(b'update: (current)\n'))
7099 elif pnode not in bheads:
7128 elif pnode not in bheads:
7100 # i18n: column positioning for "hg summary"
7129 # i18n: column positioning for "hg summary"
7101 ui.write(_(b'update: %d new changesets (update)\n') % new)
7130 ui.write(_(b'update: %d new changesets (update)\n') % new)
7102 else:
7131 else:
7103 # i18n: column positioning for "hg summary"
7132 # i18n: column positioning for "hg summary"
7104 ui.write(
7133 ui.write(
7105 _(b'update: %d new changesets, %d branch heads (merge)\n')
7134 _(b'update: %d new changesets, %d branch heads (merge)\n')
7106 % (new, len(bheads))
7135 % (new, len(bheads))
7107 )
7136 )
7108
7137
7109 t = []
7138 t = []
7110 draft = len(repo.revs(b'draft()'))
7139 draft = len(repo.revs(b'draft()'))
7111 if draft:
7140 if draft:
7112 t.append(_(b'%d draft') % draft)
7141 t.append(_(b'%d draft') % draft)
7113 secret = len(repo.revs(b'secret()'))
7142 secret = len(repo.revs(b'secret()'))
7114 if secret:
7143 if secret:
7115 t.append(_(b'%d secret') % secret)
7144 t.append(_(b'%d secret') % secret)
7116
7145
7117 if draft or secret:
7146 if draft or secret:
7118 ui.status(_(b'phases: %s\n') % b', '.join(t))
7147 ui.status(_(b'phases: %s\n') % b', '.join(t))
7119
7148
7120 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7149 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7121 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7150 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7122 numtrouble = len(repo.revs(trouble + b"()"))
7151 numtrouble = len(repo.revs(trouble + b"()"))
7123 # We write all the possibilities to ease translation
7152 # We write all the possibilities to ease translation
7124 troublemsg = {
7153 troublemsg = {
7125 b"orphan": _(b"orphan: %d changesets"),
7154 b"orphan": _(b"orphan: %d changesets"),
7126 b"contentdivergent": _(b"content-divergent: %d changesets"),
7155 b"contentdivergent": _(b"content-divergent: %d changesets"),
7127 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7156 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7128 }
7157 }
7129 if numtrouble > 0:
7158 if numtrouble > 0:
7130 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7159 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7131
7160
7132 cmdutil.summaryhooks(ui, repo)
7161 cmdutil.summaryhooks(ui, repo)
7133
7162
7134 if opts.get(b'remote'):
7163 if opts.get(b'remote'):
7135 needsincoming, needsoutgoing = True, True
7164 needsincoming, needsoutgoing = True, True
7136 else:
7165 else:
7137 needsincoming, needsoutgoing = False, False
7166 needsincoming, needsoutgoing = False, False
7138 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7167 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7139 if i:
7168 if i:
7140 needsincoming = True
7169 needsincoming = True
7141 if o:
7170 if o:
7142 needsoutgoing = True
7171 needsoutgoing = True
7143 if not needsincoming and not needsoutgoing:
7172 if not needsincoming and not needsoutgoing:
7144 return
7173 return
7145
7174
7146 def getincoming():
7175 def getincoming():
7147 source, branches = hg.parseurl(ui.expandpath(b'default'))
7176 source, branches = hg.parseurl(ui.expandpath(b'default'))
7148 sbranch = branches[0]
7177 sbranch = branches[0]
7149 try:
7178 try:
7150 other = hg.peer(repo, {}, source)
7179 other = hg.peer(repo, {}, source)
7151 except error.RepoError:
7180 except error.RepoError:
7152 if opts.get(b'remote'):
7181 if opts.get(b'remote'):
7153 raise
7182 raise
7154 return source, sbranch, None, None, None
7183 return source, sbranch, None, None, None
7155 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7184 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7156 if revs:
7185 if revs:
7157 revs = [other.lookup(rev) for rev in revs]
7186 revs = [other.lookup(rev) for rev in revs]
7158 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
7187 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
7159 repo.ui.pushbuffer()
7188 repo.ui.pushbuffer()
7160 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7189 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7161 repo.ui.popbuffer()
7190 repo.ui.popbuffer()
7162 return source, sbranch, other, commoninc, commoninc[1]
7191 return source, sbranch, other, commoninc, commoninc[1]
7163
7192
7164 if needsincoming:
7193 if needsincoming:
7165 source, sbranch, sother, commoninc, incoming = getincoming()
7194 source, sbranch, sother, commoninc, incoming = getincoming()
7166 else:
7195 else:
7167 source = sbranch = sother = commoninc = incoming = None
7196 source = sbranch = sother = commoninc = incoming = None
7168
7197
7169 def getoutgoing():
7198 def getoutgoing():
7170 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
7199 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
7171 dbranch = branches[0]
7200 dbranch = branches[0]
7172 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
7201 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
7173 if source != dest:
7202 if source != dest:
7174 try:
7203 try:
7175 dother = hg.peer(repo, {}, dest)
7204 dother = hg.peer(repo, {}, dest)
7176 except error.RepoError:
7205 except error.RepoError:
7177 if opts.get(b'remote'):
7206 if opts.get(b'remote'):
7178 raise
7207 raise
7179 return dest, dbranch, None, None
7208 return dest, dbranch, None, None
7180 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7209 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7181 elif sother is None:
7210 elif sother is None:
7182 # there is no explicit destination peer, but source one is invalid
7211 # there is no explicit destination peer, but source one is invalid
7183 return dest, dbranch, None, None
7212 return dest, dbranch, None, None
7184 else:
7213 else:
7185 dother = sother
7214 dother = sother
7186 if source != dest or (sbranch is not None and sbranch != dbranch):
7215 if source != dest or (sbranch is not None and sbranch != dbranch):
7187 common = None
7216 common = None
7188 else:
7217 else:
7189 common = commoninc
7218 common = commoninc
7190 if revs:
7219 if revs:
7191 revs = [repo.lookup(rev) for rev in revs]
7220 revs = [repo.lookup(rev) for rev in revs]
7192 repo.ui.pushbuffer()
7221 repo.ui.pushbuffer()
7193 outgoing = discovery.findcommonoutgoing(
7222 outgoing = discovery.findcommonoutgoing(
7194 repo, dother, onlyheads=revs, commoninc=common
7223 repo, dother, onlyheads=revs, commoninc=common
7195 )
7224 )
7196 repo.ui.popbuffer()
7225 repo.ui.popbuffer()
7197 return dest, dbranch, dother, outgoing
7226 return dest, dbranch, dother, outgoing
7198
7227
7199 if needsoutgoing:
7228 if needsoutgoing:
7200 dest, dbranch, dother, outgoing = getoutgoing()
7229 dest, dbranch, dother, outgoing = getoutgoing()
7201 else:
7230 else:
7202 dest = dbranch = dother = outgoing = None
7231 dest = dbranch = dother = outgoing = None
7203
7232
7204 if opts.get(b'remote'):
7233 if opts.get(b'remote'):
7205 t = []
7234 t = []
7206 if incoming:
7235 if incoming:
7207 t.append(_(b'1 or more incoming'))
7236 t.append(_(b'1 or more incoming'))
7208 o = outgoing.missing
7237 o = outgoing.missing
7209 if o:
7238 if o:
7210 t.append(_(b'%d outgoing') % len(o))
7239 t.append(_(b'%d outgoing') % len(o))
7211 other = dother or sother
7240 other = dother or sother
7212 if b'bookmarks' in other.listkeys(b'namespaces'):
7241 if b'bookmarks' in other.listkeys(b'namespaces'):
7213 counts = bookmarks.summary(repo, other)
7242 counts = bookmarks.summary(repo, other)
7214 if counts[0] > 0:
7243 if counts[0] > 0:
7215 t.append(_(b'%d incoming bookmarks') % counts[0])
7244 t.append(_(b'%d incoming bookmarks') % counts[0])
7216 if counts[1] > 0:
7245 if counts[1] > 0:
7217 t.append(_(b'%d outgoing bookmarks') % counts[1])
7246 t.append(_(b'%d outgoing bookmarks') % counts[1])
7218
7247
7219 if t:
7248 if t:
7220 # i18n: column positioning for "hg summary"
7249 # i18n: column positioning for "hg summary"
7221 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7250 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7222 else:
7251 else:
7223 # i18n: column positioning for "hg summary"
7252 # i18n: column positioning for "hg summary"
7224 ui.status(_(b'remote: (synced)\n'))
7253 ui.status(_(b'remote: (synced)\n'))
7225
7254
7226 cmdutil.summaryremotehooks(
7255 cmdutil.summaryremotehooks(
7227 ui,
7256 ui,
7228 repo,
7257 repo,
7229 opts,
7258 opts,
7230 (
7259 (
7231 (source, sbranch, sother, commoninc),
7260 (source, sbranch, sother, commoninc),
7232 (dest, dbranch, dother, outgoing),
7261 (dest, dbranch, dother, outgoing),
7233 ),
7262 ),
7234 )
7263 )
7235
7264
7236
7265
7237 @command(
7266 @command(
7238 b'tag',
7267 b'tag',
7239 [
7268 [
7240 (b'f', b'force', None, _(b'force tag')),
7269 (b'f', b'force', None, _(b'force tag')),
7241 (b'l', b'local', None, _(b'make the tag local')),
7270 (b'l', b'local', None, _(b'make the tag local')),
7242 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7271 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7243 (b'', b'remove', None, _(b'remove a tag')),
7272 (b'', b'remove', None, _(b'remove a tag')),
7244 # -l/--local is already there, commitopts cannot be used
7273 # -l/--local is already there, commitopts cannot be used
7245 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7274 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7246 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7275 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7247 ]
7276 ]
7248 + commitopts2,
7277 + commitopts2,
7249 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7278 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7250 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7279 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7251 )
7280 )
7252 def tag(ui, repo, name1, *names, **opts):
7281 def tag(ui, repo, name1, *names, **opts):
7253 """add one or more tags for the current or given revision
7282 """add one or more tags for the current or given revision
7254
7283
7255 Name a particular revision using <name>.
7284 Name a particular revision using <name>.
7256
7285
7257 Tags are used to name particular revisions of the repository and are
7286 Tags are used to name particular revisions of the repository and are
7258 very useful to compare different revisions, to go back to significant
7287 very useful to compare different revisions, to go back to significant
7259 earlier versions or to mark branch points as releases, etc. Changing
7288 earlier versions or to mark branch points as releases, etc. Changing
7260 an existing tag is normally disallowed; use -f/--force to override.
7289 an existing tag is normally disallowed; use -f/--force to override.
7261
7290
7262 If no revision is given, the parent of the working directory is
7291 If no revision is given, the parent of the working directory is
7263 used.
7292 used.
7264
7293
7265 To facilitate version control, distribution, and merging of tags,
7294 To facilitate version control, distribution, and merging of tags,
7266 they are stored as a file named ".hgtags" which is managed similarly
7295 they are stored as a file named ".hgtags" which is managed similarly
7267 to other project files and can be hand-edited if necessary. This
7296 to other project files and can be hand-edited if necessary. This
7268 also means that tagging creates a new commit. The file
7297 also means that tagging creates a new commit. The file
7269 ".hg/localtags" is used for local tags (not shared among
7298 ".hg/localtags" is used for local tags (not shared among
7270 repositories).
7299 repositories).
7271
7300
7272 Tag commits are usually made at the head of a branch. If the parent
7301 Tag commits are usually made at the head of a branch. If the parent
7273 of the working directory is not a branch head, :hg:`tag` aborts; use
7302 of the working directory is not a branch head, :hg:`tag` aborts; use
7274 -f/--force to force the tag commit to be based on a non-head
7303 -f/--force to force the tag commit to be based on a non-head
7275 changeset.
7304 changeset.
7276
7305
7277 See :hg:`help dates` for a list of formats valid for -d/--date.
7306 See :hg:`help dates` for a list of formats valid for -d/--date.
7278
7307
7279 Since tag names have priority over branch names during revision
7308 Since tag names have priority over branch names during revision
7280 lookup, using an existing branch name as a tag name is discouraged.
7309 lookup, using an existing branch name as a tag name is discouraged.
7281
7310
7282 Returns 0 on success.
7311 Returns 0 on success.
7283 """
7312 """
7284 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7313 cmdutil.check_incompatible_arguments(opts, 'remove', ['rev'])
7285 opts = pycompat.byteskwargs(opts)
7314 opts = pycompat.byteskwargs(opts)
7286 with repo.wlock(), repo.lock():
7315 with repo.wlock(), repo.lock():
7287 rev_ = b"."
7316 rev_ = b"."
7288 names = [t.strip() for t in (name1,) + names]
7317 names = [t.strip() for t in (name1,) + names]
7289 if len(names) != len(set(names)):
7318 if len(names) != len(set(names)):
7290 raise error.InputError(_(b'tag names must be unique'))
7319 raise error.InputError(_(b'tag names must be unique'))
7291 for n in names:
7320 for n in names:
7292 scmutil.checknewlabel(repo, n, b'tag')
7321 scmutil.checknewlabel(repo, n, b'tag')
7293 if not n:
7322 if not n:
7294 raise error.InputError(
7323 raise error.InputError(
7295 _(b'tag names cannot consist entirely of whitespace')
7324 _(b'tag names cannot consist entirely of whitespace')
7296 )
7325 )
7297 if opts.get(b'rev'):
7326 if opts.get(b'rev'):
7298 rev_ = opts[b'rev']
7327 rev_ = opts[b'rev']
7299 message = opts.get(b'message')
7328 message = opts.get(b'message')
7300 if opts.get(b'remove'):
7329 if opts.get(b'remove'):
7301 if opts.get(b'local'):
7330 if opts.get(b'local'):
7302 expectedtype = b'local'
7331 expectedtype = b'local'
7303 else:
7332 else:
7304 expectedtype = b'global'
7333 expectedtype = b'global'
7305
7334
7306 for n in names:
7335 for n in names:
7307 if repo.tagtype(n) == b'global':
7336 if repo.tagtype(n) == b'global':
7308 alltags = tagsmod.findglobaltags(ui, repo)
7337 alltags = tagsmod.findglobaltags(ui, repo)
7309 if alltags[n][0] == nullid:
7338 if alltags[n][0] == nullid:
7310 raise error.InputError(
7339 raise error.InputError(
7311 _(b"tag '%s' is already removed") % n
7340 _(b"tag '%s' is already removed") % n
7312 )
7341 )
7313 if not repo.tagtype(n):
7342 if not repo.tagtype(n):
7314 raise error.InputError(_(b"tag '%s' does not exist") % n)
7343 raise error.InputError(_(b"tag '%s' does not exist") % n)
7315 if repo.tagtype(n) != expectedtype:
7344 if repo.tagtype(n) != expectedtype:
7316 if expectedtype == b'global':
7345 if expectedtype == b'global':
7317 raise error.InputError(
7346 raise error.InputError(
7318 _(b"tag '%s' is not a global tag") % n
7347 _(b"tag '%s' is not a global tag") % n
7319 )
7348 )
7320 else:
7349 else:
7321 raise error.InputError(
7350 raise error.InputError(
7322 _(b"tag '%s' is not a local tag") % n
7351 _(b"tag '%s' is not a local tag") % n
7323 )
7352 )
7324 rev_ = b'null'
7353 rev_ = b'null'
7325 if not message:
7354 if not message:
7326 # we don't translate commit messages
7355 # we don't translate commit messages
7327 message = b'Removed tag %s' % b', '.join(names)
7356 message = b'Removed tag %s' % b', '.join(names)
7328 elif not opts.get(b'force'):
7357 elif not opts.get(b'force'):
7329 for n in names:
7358 for n in names:
7330 if n in repo.tags():
7359 if n in repo.tags():
7331 raise error.InputError(
7360 raise error.InputError(
7332 _(b"tag '%s' already exists (use -f to force)") % n
7361 _(b"tag '%s' already exists (use -f to force)") % n
7333 )
7362 )
7334 if not opts.get(b'local'):
7363 if not opts.get(b'local'):
7335 p1, p2 = repo.dirstate.parents()
7364 p1, p2 = repo.dirstate.parents()
7336 if p2 != nullid:
7365 if p2 != nullid:
7337 raise error.StateError(_(b'uncommitted merge'))
7366 raise error.StateError(_(b'uncommitted merge'))
7338 bheads = repo.branchheads()
7367 bheads = repo.branchheads()
7339 if not opts.get(b'force') and bheads and p1 not in bheads:
7368 if not opts.get(b'force') and bheads and p1 not in bheads:
7340 raise error.InputError(
7369 raise error.InputError(
7341 _(
7370 _(
7342 b'working directory is not at a branch head '
7371 b'working directory is not at a branch head '
7343 b'(use -f to force)'
7372 b'(use -f to force)'
7344 )
7373 )
7345 )
7374 )
7346 node = scmutil.revsingle(repo, rev_).node()
7375 node = scmutil.revsingle(repo, rev_).node()
7347
7376
7348 if not message:
7377 if not message:
7349 # we don't translate commit messages
7378 # we don't translate commit messages
7350 message = b'Added tag %s for changeset %s' % (
7379 message = b'Added tag %s for changeset %s' % (
7351 b', '.join(names),
7380 b', '.join(names),
7352 short(node),
7381 short(node),
7353 )
7382 )
7354
7383
7355 date = opts.get(b'date')
7384 date = opts.get(b'date')
7356 if date:
7385 if date:
7357 date = dateutil.parsedate(date)
7386 date = dateutil.parsedate(date)
7358
7387
7359 if opts.get(b'remove'):
7388 if opts.get(b'remove'):
7360 editform = b'tag.remove'
7389 editform = b'tag.remove'
7361 else:
7390 else:
7362 editform = b'tag.add'
7391 editform = b'tag.add'
7363 editor = cmdutil.getcommiteditor(
7392 editor = cmdutil.getcommiteditor(
7364 editform=editform, **pycompat.strkwargs(opts)
7393 editform=editform, **pycompat.strkwargs(opts)
7365 )
7394 )
7366
7395
7367 # don't allow tagging the null rev
7396 # don't allow tagging the null rev
7368 if (
7397 if (
7369 not opts.get(b'remove')
7398 not opts.get(b'remove')
7370 and scmutil.revsingle(repo, rev_).rev() == nullrev
7399 and scmutil.revsingle(repo, rev_).rev() == nullrev
7371 ):
7400 ):
7372 raise error.InputError(_(b"cannot tag null revision"))
7401 raise error.InputError(_(b"cannot tag null revision"))
7373
7402
7374 tagsmod.tag(
7403 tagsmod.tag(
7375 repo,
7404 repo,
7376 names,
7405 names,
7377 node,
7406 node,
7378 message,
7407 message,
7379 opts.get(b'local'),
7408 opts.get(b'local'),
7380 opts.get(b'user'),
7409 opts.get(b'user'),
7381 date,
7410 date,
7382 editor=editor,
7411 editor=editor,
7383 )
7412 )
7384
7413
7385
7414
7386 @command(
7415 @command(
7387 b'tags',
7416 b'tags',
7388 formatteropts,
7417 formatteropts,
7389 b'',
7418 b'',
7390 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7419 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7391 intents={INTENT_READONLY},
7420 intents={INTENT_READONLY},
7392 )
7421 )
7393 def tags(ui, repo, **opts):
7422 def tags(ui, repo, **opts):
7394 """list repository tags
7423 """list repository tags
7395
7424
7396 This lists both regular and local tags. When the -v/--verbose
7425 This lists both regular and local tags. When the -v/--verbose
7397 switch is used, a third column "local" is printed for local tags.
7426 switch is used, a third column "local" is printed for local tags.
7398 When the -q/--quiet switch is used, only the tag name is printed.
7427 When the -q/--quiet switch is used, only the tag name is printed.
7399
7428
7400 .. container:: verbose
7429 .. container:: verbose
7401
7430
7402 Template:
7431 Template:
7403
7432
7404 The following keywords are supported in addition to the common template
7433 The following keywords are supported in addition to the common template
7405 keywords and functions such as ``{tag}``. See also
7434 keywords and functions such as ``{tag}``. See also
7406 :hg:`help templates`.
7435 :hg:`help templates`.
7407
7436
7408 :type: String. ``local`` for local tags.
7437 :type: String. ``local`` for local tags.
7409
7438
7410 Returns 0 on success.
7439 Returns 0 on success.
7411 """
7440 """
7412
7441
7413 opts = pycompat.byteskwargs(opts)
7442 opts = pycompat.byteskwargs(opts)
7414 ui.pager(b'tags')
7443 ui.pager(b'tags')
7415 fm = ui.formatter(b'tags', opts)
7444 fm = ui.formatter(b'tags', opts)
7416 hexfunc = fm.hexfunc
7445 hexfunc = fm.hexfunc
7417
7446
7418 for t, n in reversed(repo.tagslist()):
7447 for t, n in reversed(repo.tagslist()):
7419 hn = hexfunc(n)
7448 hn = hexfunc(n)
7420 label = b'tags.normal'
7449 label = b'tags.normal'
7421 tagtype = repo.tagtype(t)
7450 tagtype = repo.tagtype(t)
7422 if not tagtype or tagtype == b'global':
7451 if not tagtype or tagtype == b'global':
7423 tagtype = b''
7452 tagtype = b''
7424 else:
7453 else:
7425 label = b'tags.' + tagtype
7454 label = b'tags.' + tagtype
7426
7455
7427 fm.startitem()
7456 fm.startitem()
7428 fm.context(repo=repo)
7457 fm.context(repo=repo)
7429 fm.write(b'tag', b'%s', t, label=label)
7458 fm.write(b'tag', b'%s', t, label=label)
7430 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7459 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7431 fm.condwrite(
7460 fm.condwrite(
7432 not ui.quiet,
7461 not ui.quiet,
7433 b'rev node',
7462 b'rev node',
7434 fmt,
7463 fmt,
7435 repo.changelog.rev(n),
7464 repo.changelog.rev(n),
7436 hn,
7465 hn,
7437 label=label,
7466 label=label,
7438 )
7467 )
7439 fm.condwrite(
7468 fm.condwrite(
7440 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7469 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7441 )
7470 )
7442 fm.plain(b'\n')
7471 fm.plain(b'\n')
7443 fm.end()
7472 fm.end()
7444
7473
7445
7474
7446 @command(
7475 @command(
7447 b'tip',
7476 b'tip',
7448 [
7477 [
7449 (b'p', b'patch', None, _(b'show patch')),
7478 (b'p', b'patch', None, _(b'show patch')),
7450 (b'g', b'git', None, _(b'use git extended diff format')),
7479 (b'g', b'git', None, _(b'use git extended diff format')),
7451 ]
7480 ]
7452 + templateopts,
7481 + templateopts,
7453 _(b'[-p] [-g]'),
7482 _(b'[-p] [-g]'),
7454 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7483 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7455 )
7484 )
7456 def tip(ui, repo, **opts):
7485 def tip(ui, repo, **opts):
7457 """show the tip revision (DEPRECATED)
7486 """show the tip revision (DEPRECATED)
7458
7487
7459 The tip revision (usually just called the tip) is the changeset
7488 The tip revision (usually just called the tip) is the changeset
7460 most recently added to the repository (and therefore the most
7489 most recently added to the repository (and therefore the most
7461 recently changed head).
7490 recently changed head).
7462
7491
7463 If you have just made a commit, that commit will be the tip. If
7492 If you have just made a commit, that commit will be the tip. If
7464 you have just pulled changes from another repository, the tip of
7493 you have just pulled changes from another repository, the tip of
7465 that repository becomes the current tip. The "tip" tag is special
7494 that repository becomes the current tip. The "tip" tag is special
7466 and cannot be renamed or assigned to a different changeset.
7495 and cannot be renamed or assigned to a different changeset.
7467
7496
7468 This command is deprecated, please use :hg:`heads` instead.
7497 This command is deprecated, please use :hg:`heads` instead.
7469
7498
7470 Returns 0 on success.
7499 Returns 0 on success.
7471 """
7500 """
7472 opts = pycompat.byteskwargs(opts)
7501 opts = pycompat.byteskwargs(opts)
7473 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7502 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7474 displayer.show(repo[b'tip'])
7503 displayer.show(repo[b'tip'])
7475 displayer.close()
7504 displayer.close()
7476
7505
7477
7506
7478 @command(
7507 @command(
7479 b'unbundle',
7508 b'unbundle',
7480 [
7509 [
7481 (
7510 (
7482 b'u',
7511 b'u',
7483 b'update',
7512 b'update',
7484 None,
7513 None,
7485 _(b'update to new branch head if changesets were unbundled'),
7514 _(b'update to new branch head if changesets were unbundled'),
7486 )
7515 )
7487 ],
7516 ],
7488 _(b'[-u] FILE...'),
7517 _(b'[-u] FILE...'),
7489 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7518 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7490 )
7519 )
7491 def unbundle(ui, repo, fname1, *fnames, **opts):
7520 def unbundle(ui, repo, fname1, *fnames, **opts):
7492 """apply one or more bundle files
7521 """apply one or more bundle files
7493
7522
7494 Apply one or more bundle files generated by :hg:`bundle`.
7523 Apply one or more bundle files generated by :hg:`bundle`.
7495
7524
7496 Returns 0 on success, 1 if an update has unresolved files.
7525 Returns 0 on success, 1 if an update has unresolved files.
7497 """
7526 """
7498 fnames = (fname1,) + fnames
7527 fnames = (fname1,) + fnames
7499
7528
7500 with repo.lock():
7529 with repo.lock():
7501 for fname in fnames:
7530 for fname in fnames:
7502 f = hg.openpath(ui, fname)
7531 f = hg.openpath(ui, fname)
7503 gen = exchange.readbundle(ui, f, fname)
7532 gen = exchange.readbundle(ui, f, fname)
7504 if isinstance(gen, streamclone.streamcloneapplier):
7533 if isinstance(gen, streamclone.streamcloneapplier):
7505 raise error.InputError(
7534 raise error.InputError(
7506 _(
7535 _(
7507 b'packed bundles cannot be applied with '
7536 b'packed bundles cannot be applied with '
7508 b'"hg unbundle"'
7537 b'"hg unbundle"'
7509 ),
7538 ),
7510 hint=_(b'use "hg debugapplystreamclonebundle"'),
7539 hint=_(b'use "hg debugapplystreamclonebundle"'),
7511 )
7540 )
7512 url = b'bundle:' + fname
7541 url = b'bundle:' + fname
7513 try:
7542 try:
7514 txnname = b'unbundle'
7543 txnname = b'unbundle'
7515 if not isinstance(gen, bundle2.unbundle20):
7544 if not isinstance(gen, bundle2.unbundle20):
7516 txnname = b'unbundle\n%s' % util.hidepassword(url)
7545 txnname = b'unbundle\n%s' % util.hidepassword(url)
7517 with repo.transaction(txnname) as tr:
7546 with repo.transaction(txnname) as tr:
7518 op = bundle2.applybundle(
7547 op = bundle2.applybundle(
7519 repo, gen, tr, source=b'unbundle', url=url
7548 repo, gen, tr, source=b'unbundle', url=url
7520 )
7549 )
7521 except error.BundleUnknownFeatureError as exc:
7550 except error.BundleUnknownFeatureError as exc:
7522 raise error.Abort(
7551 raise error.Abort(
7523 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7552 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7524 hint=_(
7553 hint=_(
7525 b"see https://mercurial-scm.org/"
7554 b"see https://mercurial-scm.org/"
7526 b"wiki/BundleFeature for more "
7555 b"wiki/BundleFeature for more "
7527 b"information"
7556 b"information"
7528 ),
7557 ),
7529 )
7558 )
7530 modheads = bundle2.combinechangegroupresults(op)
7559 modheads = bundle2.combinechangegroupresults(op)
7531
7560
7532 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7561 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7533
7562
7534
7563
7535 @command(
7564 @command(
7536 b'unshelve',
7565 b'unshelve',
7537 [
7566 [
7538 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7567 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7539 (
7568 (
7540 b'c',
7569 b'c',
7541 b'continue',
7570 b'continue',
7542 None,
7571 None,
7543 _(b'continue an incomplete unshelve operation'),
7572 _(b'continue an incomplete unshelve operation'),
7544 ),
7573 ),
7545 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7574 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7546 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7575 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7547 (
7576 (
7548 b'n',
7577 b'n',
7549 b'name',
7578 b'name',
7550 b'',
7579 b'',
7551 _(b'restore shelved change with given name'),
7580 _(b'restore shelved change with given name'),
7552 _(b'NAME'),
7581 _(b'NAME'),
7553 ),
7582 ),
7554 (b't', b'tool', b'', _(b'specify merge tool')),
7583 (b't', b'tool', b'', _(b'specify merge tool')),
7555 (
7584 (
7556 b'',
7585 b'',
7557 b'date',
7586 b'date',
7558 b'',
7587 b'',
7559 _(b'set date for temporary commits (DEPRECATED)'),
7588 _(b'set date for temporary commits (DEPRECATED)'),
7560 _(b'DATE'),
7589 _(b'DATE'),
7561 ),
7590 ),
7562 ],
7591 ],
7563 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7592 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7564 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7593 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7565 )
7594 )
7566 def unshelve(ui, repo, *shelved, **opts):
7595 def unshelve(ui, repo, *shelved, **opts):
7567 """restore a shelved change to the working directory
7596 """restore a shelved change to the working directory
7568
7597
7569 This command accepts an optional name of a shelved change to
7598 This command accepts an optional name of a shelved change to
7570 restore. If none is given, the most recent shelved change is used.
7599 restore. If none is given, the most recent shelved change is used.
7571
7600
7572 If a shelved change is applied successfully, the bundle that
7601 If a shelved change is applied successfully, the bundle that
7573 contains the shelved changes is moved to a backup location
7602 contains the shelved changes is moved to a backup location
7574 (.hg/shelve-backup).
7603 (.hg/shelve-backup).
7575
7604
7576 Since you can restore a shelved change on top of an arbitrary
7605 Since you can restore a shelved change on top of an arbitrary
7577 commit, it is possible that unshelving will result in a conflict
7606 commit, it is possible that unshelving will result in a conflict
7578 between your changes and the commits you are unshelving onto. If
7607 between your changes and the commits you are unshelving onto. If
7579 this occurs, you must resolve the conflict, then use
7608 this occurs, you must resolve the conflict, then use
7580 ``--continue`` to complete the unshelve operation. (The bundle
7609 ``--continue`` to complete the unshelve operation. (The bundle
7581 will not be moved until you successfully complete the unshelve.)
7610 will not be moved until you successfully complete the unshelve.)
7582
7611
7583 (Alternatively, you can use ``--abort`` to abandon an unshelve
7612 (Alternatively, you can use ``--abort`` to abandon an unshelve
7584 that causes a conflict. This reverts the unshelved changes, and
7613 that causes a conflict. This reverts the unshelved changes, and
7585 leaves the bundle in place.)
7614 leaves the bundle in place.)
7586
7615
7587 If bare shelved change (without interactive, include and exclude
7616 If bare shelved change (without interactive, include and exclude
7588 option) was done on newly created branch it would restore branch
7617 option) was done on newly created branch it would restore branch
7589 information to the working directory.
7618 information to the working directory.
7590
7619
7591 After a successful unshelve, the shelved changes are stored in a
7620 After a successful unshelve, the shelved changes are stored in a
7592 backup directory. Only the N most recent backups are kept. N
7621 backup directory. Only the N most recent backups are kept. N
7593 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7622 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7594 configuration option.
7623 configuration option.
7595
7624
7596 .. container:: verbose
7625 .. container:: verbose
7597
7626
7598 Timestamp in seconds is used to decide order of backups. More
7627 Timestamp in seconds is used to decide order of backups. More
7599 than ``maxbackups`` backups are kept, if same timestamp
7628 than ``maxbackups`` backups are kept, if same timestamp
7600 prevents from deciding exact order of them, for safety.
7629 prevents from deciding exact order of them, for safety.
7601
7630
7602 Selected changes can be unshelved with ``--interactive`` flag.
7631 Selected changes can be unshelved with ``--interactive`` flag.
7603 The working directory is updated with the selected changes, and
7632 The working directory is updated with the selected changes, and
7604 only the unselected changes remain shelved.
7633 only the unselected changes remain shelved.
7605 Note: The whole shelve is applied to working directory first before
7634 Note: The whole shelve is applied to working directory first before
7606 running interactively. So, this will bring up all the conflicts between
7635 running interactively. So, this will bring up all the conflicts between
7607 working directory and the shelve, irrespective of which changes will be
7636 working directory and the shelve, irrespective of which changes will be
7608 unshelved.
7637 unshelved.
7609 """
7638 """
7610 with repo.wlock():
7639 with repo.wlock():
7611 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7640 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7612
7641
7613
7642
7614 statemod.addunfinished(
7643 statemod.addunfinished(
7615 b'unshelve',
7644 b'unshelve',
7616 fname=b'shelvedstate',
7645 fname=b'shelvedstate',
7617 continueflag=True,
7646 continueflag=True,
7618 abortfunc=shelvemod.hgabortunshelve,
7647 abortfunc=shelvemod.hgabortunshelve,
7619 continuefunc=shelvemod.hgcontinueunshelve,
7648 continuefunc=shelvemod.hgcontinueunshelve,
7620 cmdmsg=_(b'unshelve already in progress'),
7649 cmdmsg=_(b'unshelve already in progress'),
7621 )
7650 )
7622
7651
7623
7652
7624 @command(
7653 @command(
7625 b'update|up|checkout|co',
7654 b'update|up|checkout|co',
7626 [
7655 [
7627 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7656 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7628 (b'c', b'check', None, _(b'require clean working directory')),
7657 (b'c', b'check', None, _(b'require clean working directory')),
7629 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7658 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7630 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7659 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7631 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7660 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7632 ]
7661 ]
7633 + mergetoolopts,
7662 + mergetoolopts,
7634 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7663 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7635 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7664 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7636 helpbasic=True,
7665 helpbasic=True,
7637 )
7666 )
7638 def update(ui, repo, node=None, **opts):
7667 def update(ui, repo, node=None, **opts):
7639 """update working directory (or switch revisions)
7668 """update working directory (or switch revisions)
7640
7669
7641 Update the repository's working directory to the specified
7670 Update the repository's working directory to the specified
7642 changeset. If no changeset is specified, update to the tip of the
7671 changeset. If no changeset is specified, update to the tip of the
7643 current named branch and move the active bookmark (see :hg:`help
7672 current named branch and move the active bookmark (see :hg:`help
7644 bookmarks`).
7673 bookmarks`).
7645
7674
7646 Update sets the working directory's parent revision to the specified
7675 Update sets the working directory's parent revision to the specified
7647 changeset (see :hg:`help parents`).
7676 changeset (see :hg:`help parents`).
7648
7677
7649 If the changeset is not a descendant or ancestor of the working
7678 If the changeset is not a descendant or ancestor of the working
7650 directory's parent and there are uncommitted changes, the update is
7679 directory's parent and there are uncommitted changes, the update is
7651 aborted. With the -c/--check option, the working directory is checked
7680 aborted. With the -c/--check option, the working directory is checked
7652 for uncommitted changes; if none are found, the working directory is
7681 for uncommitted changes; if none are found, the working directory is
7653 updated to the specified changeset.
7682 updated to the specified changeset.
7654
7683
7655 .. container:: verbose
7684 .. container:: verbose
7656
7685
7657 The -C/--clean, -c/--check, and -m/--merge options control what
7686 The -C/--clean, -c/--check, and -m/--merge options control what
7658 happens if the working directory contains uncommitted changes.
7687 happens if the working directory contains uncommitted changes.
7659 At most of one of them can be specified.
7688 At most of one of them can be specified.
7660
7689
7661 1. If no option is specified, and if
7690 1. If no option is specified, and if
7662 the requested changeset is an ancestor or descendant of
7691 the requested changeset is an ancestor or descendant of
7663 the working directory's parent, the uncommitted changes
7692 the working directory's parent, the uncommitted changes
7664 are merged into the requested changeset and the merged
7693 are merged into the requested changeset and the merged
7665 result is left uncommitted. If the requested changeset is
7694 result is left uncommitted. If the requested changeset is
7666 not an ancestor or descendant (that is, it is on another
7695 not an ancestor or descendant (that is, it is on another
7667 branch), the update is aborted and the uncommitted changes
7696 branch), the update is aborted and the uncommitted changes
7668 are preserved.
7697 are preserved.
7669
7698
7670 2. With the -m/--merge option, the update is allowed even if the
7699 2. With the -m/--merge option, the update is allowed even if the
7671 requested changeset is not an ancestor or descendant of
7700 requested changeset is not an ancestor or descendant of
7672 the working directory's parent.
7701 the working directory's parent.
7673
7702
7674 3. With the -c/--check option, the update is aborted and the
7703 3. With the -c/--check option, the update is aborted and the
7675 uncommitted changes are preserved.
7704 uncommitted changes are preserved.
7676
7705
7677 4. With the -C/--clean option, uncommitted changes are discarded and
7706 4. With the -C/--clean option, uncommitted changes are discarded and
7678 the working directory is updated to the requested changeset.
7707 the working directory is updated to the requested changeset.
7679
7708
7680 To cancel an uncommitted merge (and lose your changes), use
7709 To cancel an uncommitted merge (and lose your changes), use
7681 :hg:`merge --abort`.
7710 :hg:`merge --abort`.
7682
7711
7683 Use null as the changeset to remove the working directory (like
7712 Use null as the changeset to remove the working directory (like
7684 :hg:`clone -U`).
7713 :hg:`clone -U`).
7685
7714
7686 If you want to revert just one file to an older revision, use
7715 If you want to revert just one file to an older revision, use
7687 :hg:`revert [-r REV] NAME`.
7716 :hg:`revert [-r REV] NAME`.
7688
7717
7689 See :hg:`help dates` for a list of formats valid for -d/--date.
7718 See :hg:`help dates` for a list of formats valid for -d/--date.
7690
7719
7691 Returns 0 on success, 1 if there are unresolved files.
7720 Returns 0 on success, 1 if there are unresolved files.
7692 """
7721 """
7693 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7722 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7694 rev = opts.get('rev')
7723 rev = opts.get('rev')
7695 date = opts.get('date')
7724 date = opts.get('date')
7696 clean = opts.get('clean')
7725 clean = opts.get('clean')
7697 check = opts.get('check')
7726 check = opts.get('check')
7698 merge = opts.get('merge')
7727 merge = opts.get('merge')
7699 if rev and node:
7728 if rev and node:
7700 raise error.InputError(_(b"please specify just one revision"))
7729 raise error.InputError(_(b"please specify just one revision"))
7701
7730
7702 if ui.configbool(b'commands', b'update.requiredest'):
7731 if ui.configbool(b'commands', b'update.requiredest'):
7703 if not node and not rev and not date:
7732 if not node and not rev and not date:
7704 raise error.InputError(
7733 raise error.InputError(
7705 _(b'you must specify a destination'),
7734 _(b'you must specify a destination'),
7706 hint=_(b'for example: hg update ".::"'),
7735 hint=_(b'for example: hg update ".::"'),
7707 )
7736 )
7708
7737
7709 if rev is None or rev == b'':
7738 if rev is None or rev == b'':
7710 rev = node
7739 rev = node
7711
7740
7712 if date and rev is not None:
7741 if date and rev is not None:
7713 raise error.InputError(_(b"you can't specify a revision and a date"))
7742 raise error.InputError(_(b"you can't specify a revision and a date"))
7714
7743
7715 updatecheck = None
7744 updatecheck = None
7716 if check:
7745 if check:
7717 updatecheck = b'abort'
7746 updatecheck = b'abort'
7718 elif merge:
7747 elif merge:
7719 updatecheck = b'none'
7748 updatecheck = b'none'
7720
7749
7721 with repo.wlock():
7750 with repo.wlock():
7722 cmdutil.clearunfinished(repo)
7751 cmdutil.clearunfinished(repo)
7723 if date:
7752 if date:
7724 rev = cmdutil.finddate(ui, repo, date)
7753 rev = cmdutil.finddate(ui, repo, date)
7725
7754
7726 # if we defined a bookmark, we have to remember the original name
7755 # if we defined a bookmark, we have to remember the original name
7727 brev = rev
7756 brev = rev
7728 if rev:
7757 if rev:
7729 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7758 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7730 ctx = scmutil.revsingle(repo, rev, default=None)
7759 ctx = scmutil.revsingle(repo, rev, default=None)
7731 rev = ctx.rev()
7760 rev = ctx.rev()
7732 hidden = ctx.hidden()
7761 hidden = ctx.hidden()
7733 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7762 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7734 with ui.configoverride(overrides, b'update'):
7763 with ui.configoverride(overrides, b'update'):
7735 ret = hg.updatetotally(
7764 ret = hg.updatetotally(
7736 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7765 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7737 )
7766 )
7738 if hidden:
7767 if hidden:
7739 ctxstr = ctx.hex()[:12]
7768 ctxstr = ctx.hex()[:12]
7740 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7769 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7741
7770
7742 if ctx.obsolete():
7771 if ctx.obsolete():
7743 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7772 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7744 ui.warn(b"(%s)\n" % obsfatemsg)
7773 ui.warn(b"(%s)\n" % obsfatemsg)
7745 return ret
7774 return ret
7746
7775
7747
7776
7748 @command(
7777 @command(
7749 b'verify',
7778 b'verify',
7750 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7779 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7751 helpcategory=command.CATEGORY_MAINTENANCE,
7780 helpcategory=command.CATEGORY_MAINTENANCE,
7752 )
7781 )
7753 def verify(ui, repo, **opts):
7782 def verify(ui, repo, **opts):
7754 """verify the integrity of the repository
7783 """verify the integrity of the repository
7755
7784
7756 Verify the integrity of the current repository.
7785 Verify the integrity of the current repository.
7757
7786
7758 This will perform an extensive check of the repository's
7787 This will perform an extensive check of the repository's
7759 integrity, validating the hashes and checksums of each entry in
7788 integrity, validating the hashes and checksums of each entry in
7760 the changelog, manifest, and tracked files, as well as the
7789 the changelog, manifest, and tracked files, as well as the
7761 integrity of their crosslinks and indices.
7790 integrity of their crosslinks and indices.
7762
7791
7763 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7792 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7764 for more information about recovery from corruption of the
7793 for more information about recovery from corruption of the
7765 repository.
7794 repository.
7766
7795
7767 Returns 0 on success, 1 if errors are encountered.
7796 Returns 0 on success, 1 if errors are encountered.
7768 """
7797 """
7769 opts = pycompat.byteskwargs(opts)
7798 opts = pycompat.byteskwargs(opts)
7770
7799
7771 level = None
7800 level = None
7772 if opts[b'full']:
7801 if opts[b'full']:
7773 level = verifymod.VERIFY_FULL
7802 level = verifymod.VERIFY_FULL
7774 return hg.verify(repo, level)
7803 return hg.verify(repo, level)
7775
7804
7776
7805
7777 @command(
7806 @command(
7778 b'version',
7807 b'version',
7779 [] + formatteropts,
7808 [] + formatteropts,
7780 helpcategory=command.CATEGORY_HELP,
7809 helpcategory=command.CATEGORY_HELP,
7781 norepo=True,
7810 norepo=True,
7782 intents={INTENT_READONLY},
7811 intents={INTENT_READONLY},
7783 )
7812 )
7784 def version_(ui, **opts):
7813 def version_(ui, **opts):
7785 """output version and copyright information
7814 """output version and copyright information
7786
7815
7787 .. container:: verbose
7816 .. container:: verbose
7788
7817
7789 Template:
7818 Template:
7790
7819
7791 The following keywords are supported. See also :hg:`help templates`.
7820 The following keywords are supported. See also :hg:`help templates`.
7792
7821
7793 :extensions: List of extensions.
7822 :extensions: List of extensions.
7794 :ver: String. Version number.
7823 :ver: String. Version number.
7795
7824
7796 And each entry of ``{extensions}`` provides the following sub-keywords
7825 And each entry of ``{extensions}`` provides the following sub-keywords
7797 in addition to ``{ver}``.
7826 in addition to ``{ver}``.
7798
7827
7799 :bundled: Boolean. True if included in the release.
7828 :bundled: Boolean. True if included in the release.
7800 :name: String. Extension name.
7829 :name: String. Extension name.
7801 """
7830 """
7802 opts = pycompat.byteskwargs(opts)
7831 opts = pycompat.byteskwargs(opts)
7803 if ui.verbose:
7832 if ui.verbose:
7804 ui.pager(b'version')
7833 ui.pager(b'version')
7805 fm = ui.formatter(b"version", opts)
7834 fm = ui.formatter(b"version", opts)
7806 fm.startitem()
7835 fm.startitem()
7807 fm.write(
7836 fm.write(
7808 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7837 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7809 )
7838 )
7810 license = _(
7839 license = _(
7811 b"(see https://mercurial-scm.org for more information)\n"
7840 b"(see https://mercurial-scm.org for more information)\n"
7812 b"\nCopyright (C) 2005-2021 Matt Mackall and others\n"
7841 b"\nCopyright (C) 2005-2021 Matt Mackall and others\n"
7813 b"This is free software; see the source for copying conditions. "
7842 b"This is free software; see the source for copying conditions. "
7814 b"There is NO\nwarranty; "
7843 b"There is NO\nwarranty; "
7815 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7844 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7816 )
7845 )
7817 if not ui.quiet:
7846 if not ui.quiet:
7818 fm.plain(license)
7847 fm.plain(license)
7819
7848
7820 if ui.verbose:
7849 if ui.verbose:
7821 fm.plain(_(b"\nEnabled extensions:\n\n"))
7850 fm.plain(_(b"\nEnabled extensions:\n\n"))
7822 # format names and versions into columns
7851 # format names and versions into columns
7823 names = []
7852 names = []
7824 vers = []
7853 vers = []
7825 isinternals = []
7854 isinternals = []
7826 for name, module in sorted(extensions.extensions()):
7855 for name, module in sorted(extensions.extensions()):
7827 names.append(name)
7856 names.append(name)
7828 vers.append(extensions.moduleversion(module) or None)
7857 vers.append(extensions.moduleversion(module) or None)
7829 isinternals.append(extensions.ismoduleinternal(module))
7858 isinternals.append(extensions.ismoduleinternal(module))
7830 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7859 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7831 if names:
7860 if names:
7832 namefmt = b" %%-%ds " % max(len(n) for n in names)
7861 namefmt = b" %%-%ds " % max(len(n) for n in names)
7833 places = [_(b"external"), _(b"internal")]
7862 places = [_(b"external"), _(b"internal")]
7834 for n, v, p in zip(names, vers, isinternals):
7863 for n, v, p in zip(names, vers, isinternals):
7835 fn.startitem()
7864 fn.startitem()
7836 fn.condwrite(ui.verbose, b"name", namefmt, n)
7865 fn.condwrite(ui.verbose, b"name", namefmt, n)
7837 if ui.verbose:
7866 if ui.verbose:
7838 fn.plain(b"%s " % places[p])
7867 fn.plain(b"%s " % places[p])
7839 fn.data(bundled=p)
7868 fn.data(bundled=p)
7840 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7869 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7841 if ui.verbose:
7870 if ui.verbose:
7842 fn.plain(b"\n")
7871 fn.plain(b"\n")
7843 fn.end()
7872 fn.end()
7844 fm.end()
7873 fm.end()
7845
7874
7846
7875
7847 def loadcmdtable(ui, name, cmdtable):
7876 def loadcmdtable(ui, name, cmdtable):
7848 """Load command functions from specified cmdtable"""
7877 """Load command functions from specified cmdtable"""
7849 overrides = [cmd for cmd in cmdtable if cmd in table]
7878 overrides = [cmd for cmd in cmdtable if cmd in table]
7850 if overrides:
7879 if overrides:
7851 ui.warn(
7880 ui.warn(
7852 _(b"extension '%s' overrides commands: %s\n")
7881 _(b"extension '%s' overrides commands: %s\n")
7853 % (name, b" ".join(overrides))
7882 % (name, b" ".join(overrides))
7854 )
7883 )
7855 table.update(cmdtable)
7884 table.update(cmdtable)
@@ -1,443 +1,443 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 abort
3 abort
4 add
4 add
5 addremove
5 addremove
6 annotate
6 annotate
7 archive
7 archive
8 backout
8 backout
9 bisect
9 bisect
10 bookmarks
10 bookmarks
11 branch
11 branch
12 branches
12 branches
13 bundle
13 bundle
14 cat
14 cat
15 clone
15 clone
16 commit
16 commit
17 config
17 config
18 continue
18 continue
19 copy
19 copy
20 diff
20 diff
21 export
21 export
22 files
22 files
23 forget
23 forget
24 graft
24 graft
25 grep
25 grep
26 heads
26 heads
27 help
27 help
28 identify
28 identify
29 import
29 import
30 incoming
30 incoming
31 init
31 init
32 locate
32 locate
33 log
33 log
34 manifest
34 manifest
35 merge
35 merge
36 outgoing
36 outgoing
37 parents
37 parents
38 paths
38 paths
39 phase
39 phase
40 pull
40 pull
41 purge
41 purge
42 push
42 push
43 recover
43 recover
44 remove
44 remove
45 rename
45 rename
46 resolve
46 resolve
47 revert
47 revert
48 rollback
48 rollback
49 root
49 root
50 serve
50 serve
51 shelve
51 shelve
52 status
52 status
53 summary
53 summary
54 tag
54 tag
55 tags
55 tags
56 tip
56 tip
57 unbundle
57 unbundle
58 unshelve
58 unshelve
59 update
59 update
60 verify
60 verify
61 version
61 version
62
62
63 Show all commands that start with "a"
63 Show all commands that start with "a"
64 $ hg debugcomplete a
64 $ hg debugcomplete a
65 abort
65 abort
66 add
66 add
67 addremove
67 addremove
68 annotate
68 annotate
69 archive
69 archive
70
70
71 Do not show debug commands if there are other candidates
71 Do not show debug commands if there are other candidates
72 $ hg debugcomplete d
72 $ hg debugcomplete d
73 diff
73 diff
74
74
75 Show debug commands if there are no other candidates
75 Show debug commands if there are no other candidates
76 $ hg debugcomplete debug
76 $ hg debugcomplete debug
77 debugancestor
77 debugancestor
78 debugantivirusrunning
78 debugantivirusrunning
79 debugapplystreamclonebundle
79 debugapplystreamclonebundle
80 debugbackupbundle
80 debugbackupbundle
81 debugbuilddag
81 debugbuilddag
82 debugbundle
82 debugbundle
83 debugcapabilities
83 debugcapabilities
84 debugchangedfiles
84 debugchangedfiles
85 debugcheckstate
85 debugcheckstate
86 debugcolor
86 debugcolor
87 debugcommands
87 debugcommands
88 debugcomplete
88 debugcomplete
89 debugconfig
89 debugconfig
90 debugcreatestreamclonebundle
90 debugcreatestreamclonebundle
91 debugdag
91 debugdag
92 debugdata
92 debugdata
93 debugdate
93 debugdate
94 debugdeltachain
94 debugdeltachain
95 debugdirstate
95 debugdirstate
96 debugdiscovery
96 debugdiscovery
97 debugdownload
97 debugdownload
98 debugextensions
98 debugextensions
99 debugfileset
99 debugfileset
100 debugformat
100 debugformat
101 debugfsinfo
101 debugfsinfo
102 debuggetbundle
102 debuggetbundle
103 debugignore
103 debugignore
104 debugindex
104 debugindex
105 debugindexdot
105 debugindexdot
106 debugindexstats
106 debugindexstats
107 debuginstall
107 debuginstall
108 debugknown
108 debugknown
109 debuglabelcomplete
109 debuglabelcomplete
110 debuglocks
110 debuglocks
111 debugmanifestfulltextcache
111 debugmanifestfulltextcache
112 debugmergestate
112 debugmergestate
113 debugnamecomplete
113 debugnamecomplete
114 debugnodemap
114 debugnodemap
115 debugobsolete
115 debugobsolete
116 debugp1copies
116 debugp1copies
117 debugp2copies
117 debugp2copies
118 debugpathcomplete
118 debugpathcomplete
119 debugpathcopies
119 debugpathcopies
120 debugpeer
120 debugpeer
121 debugpickmergetool
121 debugpickmergetool
122 debugpushkey
122 debugpushkey
123 debugpvec
123 debugpvec
124 debugrebuilddirstate
124 debugrebuilddirstate
125 debugrebuildfncache
125 debugrebuildfncache
126 debugrename
126 debugrename
127 debugrequires
127 debugrequires
128 debugrevlog
128 debugrevlog
129 debugrevlogindex
129 debugrevlogindex
130 debugrevspec
130 debugrevspec
131 debugserve
131 debugserve
132 debugsetparents
132 debugsetparents
133 debugshell
133 debugshell
134 debugsidedata
134 debugsidedata
135 debugssl
135 debugssl
136 debugstrip
136 debugstrip
137 debugsub
137 debugsub
138 debugsuccessorssets
138 debugsuccessorssets
139 debugtagscache
139 debugtagscache
140 debugtemplate
140 debugtemplate
141 debuguigetpass
141 debuguigetpass
142 debuguiprompt
142 debuguiprompt
143 debugupdatecaches
143 debugupdatecaches
144 debugupgraderepo
144 debugupgraderepo
145 debugwalk
145 debugwalk
146 debugwhyunstable
146 debugwhyunstable
147 debugwireargs
147 debugwireargs
148 debugwireproto
148 debugwireproto
149
149
150 Do not show the alias of a debug command if there are other candidates
150 Do not show the alias of a debug command if there are other candidates
151 (this should hide rawcommit)
151 (this should hide rawcommit)
152 $ hg debugcomplete r
152 $ hg debugcomplete r
153 recover
153 recover
154 remove
154 remove
155 rename
155 rename
156 resolve
156 resolve
157 revert
157 revert
158 rollback
158 rollback
159 root
159 root
160 Show the alias of a debug command if there are no other candidates
160 Show the alias of a debug command if there are no other candidates
161 $ hg debugcomplete rawc
161 $ hg debugcomplete rawc
162
162
163
163
164 Show the global options
164 Show the global options
165 $ hg debugcomplete --options | sort
165 $ hg debugcomplete --options | sort
166 --color
166 --color
167 --config
167 --config
168 --cwd
168 --cwd
169 --debug
169 --debug
170 --debugger
170 --debugger
171 --encoding
171 --encoding
172 --encodingmode
172 --encodingmode
173 --help
173 --help
174 --hidden
174 --hidden
175 --noninteractive
175 --noninteractive
176 --pager
176 --pager
177 --profile
177 --profile
178 --quiet
178 --quiet
179 --repository
179 --repository
180 --time
180 --time
181 --traceback
181 --traceback
182 --verbose
182 --verbose
183 --version
183 --version
184 -R
184 -R
185 -h
185 -h
186 -q
186 -q
187 -v
187 -v
188 -y
188 -y
189
189
190 Show the options for the "serve" command
190 Show the options for the "serve" command
191 $ hg debugcomplete --options serve | sort
191 $ hg debugcomplete --options serve | sort
192 --accesslog
192 --accesslog
193 --address
193 --address
194 --certificate
194 --certificate
195 --cmdserver
195 --cmdserver
196 --color
196 --color
197 --config
197 --config
198 --cwd
198 --cwd
199 --daemon
199 --daemon
200 --daemon-postexec
200 --daemon-postexec
201 --debug
201 --debug
202 --debugger
202 --debugger
203 --encoding
203 --encoding
204 --encodingmode
204 --encodingmode
205 --errorlog
205 --errorlog
206 --help
206 --help
207 --hidden
207 --hidden
208 --ipv6
208 --ipv6
209 --name
209 --name
210 --noninteractive
210 --noninteractive
211 --pager
211 --pager
212 --pid-file
212 --pid-file
213 --port
213 --port
214 --prefix
214 --prefix
215 --print-url
215 --print-url
216 --profile
216 --profile
217 --quiet
217 --quiet
218 --repository
218 --repository
219 --stdio
219 --stdio
220 --style
220 --style
221 --subrepos
221 --subrepos
222 --templates
222 --templates
223 --time
223 --time
224 --traceback
224 --traceback
225 --verbose
225 --verbose
226 --version
226 --version
227 --web-conf
227 --web-conf
228 -6
228 -6
229 -A
229 -A
230 -E
230 -E
231 -R
231 -R
232 -S
232 -S
233 -a
233 -a
234 -d
234 -d
235 -h
235 -h
236 -n
236 -n
237 -p
237 -p
238 -q
238 -q
239 -t
239 -t
240 -v
240 -v
241 -y
241 -y
242
242
243 Show an error if we use --options with an ambiguous abbreviation
243 Show an error if we use --options with an ambiguous abbreviation
244 $ hg debugcomplete --options s
244 $ hg debugcomplete --options s
245 hg: command 's' is ambiguous:
245 hg: command 's' is ambiguous:
246 serve shelve showconfig status summary
246 serve shelve showconfig status summary
247 [10]
247 [10]
248
248
249 Show all commands + options
249 Show all commands + options
250 $ hg debugcommands
250 $ hg debugcommands
251 abort: dry-run
251 abort: dry-run
252 add: include, exclude, subrepos, dry-run
252 add: include, exclude, subrepos, dry-run
253 addremove: similarity, subrepos, include, exclude, dry-run
253 addremove: similarity, subrepos, include, exclude, dry-run
254 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
254 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
255 archive: no-decode, prefix, rev, type, subrepos, include, exclude
255 archive: no-decode, prefix, rev, type, subrepos, include, exclude
256 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
256 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
257 bisect: reset, good, bad, skip, extend, command, noupdate
257 bisect: reset, good, bad, skip, extend, command, noupdate
258 bookmarks: force, rev, delete, rename, inactive, list, template
258 bookmarks: force, rev, delete, rename, inactive, list, template
259 branch: force, clean, rev
259 branch: force, clean, rev
260 branches: active, closed, rev, template
260 branches: active, closed, rev, template
261 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
261 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
262 cat: output, rev, decode, include, exclude, template
262 cat: output, rev, decode, include, exclude, template
263 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
263 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
264 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
264 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
265 config: untrusted, edit, local, shared, non-shared, global, template
265 config: untrusted, edit, local, shared, non-shared, global, template
266 continue: dry-run
266 continue: dry-run
267 copy: forget, after, at-rev, force, include, exclude, dry-run
267 copy: forget, after, at-rev, force, include, exclude, dry-run
268 debugancestor:
268 debugancestor:
269 debugantivirusrunning:
269 debugantivirusrunning:
270 debugapplystreamclonebundle:
270 debugapplystreamclonebundle:
271 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
271 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
272 debugbuilddag: mergeable-file, overwritten-file, new-file
272 debugbuilddag: mergeable-file, overwritten-file, new-file
273 debugbundle: all, part-type, spec
273 debugbundle: all, part-type, spec
274 debugcapabilities:
274 debugcapabilities:
275 debugchangedfiles:
275 debugchangedfiles:
276 debugcheckstate:
276 debugcheckstate:
277 debugcolor: style
277 debugcolor: style
278 debugcommands:
278 debugcommands:
279 debugcomplete: options
279 debugcomplete: options
280 debugcreatestreamclonebundle:
280 debugcreatestreamclonebundle:
281 debugdag: tags, branches, dots, spaces
281 debugdag: tags, branches, dots, spaces
282 debugdata: changelog, manifest, dir
282 debugdata: changelog, manifest, dir
283 debugdate: extended
283 debugdate: extended
284 debugdeltachain: changelog, manifest, dir, template
284 debugdeltachain: changelog, manifest, dir, template
285 debugdirstate: nodates, dates, datesort
285 debugdirstate: nodates, dates, datesort
286 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
286 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
287 debugdownload: output
287 debugdownload: output
288 debugextensions: template
288 debugextensions: template
289 debugfileset: rev, all-files, show-matcher, show-stage
289 debugfileset: rev, all-files, show-matcher, show-stage
290 debugformat: template
290 debugformat: template
291 debugfsinfo:
291 debugfsinfo:
292 debuggetbundle: head, common, type
292 debuggetbundle: head, common, type
293 debugignore:
293 debugignore:
294 debugindex: changelog, manifest, dir, template
294 debugindex: changelog, manifest, dir, template
295 debugindexdot: changelog, manifest, dir
295 debugindexdot: changelog, manifest, dir
296 debugindexstats:
296 debugindexstats:
297 debuginstall: template
297 debuginstall: template
298 debugknown:
298 debugknown:
299 debuglabelcomplete:
299 debuglabelcomplete:
300 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
300 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
301 debugmanifestfulltextcache: clear, add
301 debugmanifestfulltextcache: clear, add
302 debugmergestate: style, template
302 debugmergestate: style, template
303 debugnamecomplete:
303 debugnamecomplete:
304 debugnodemap: dump-new, dump-disk, check, metadata
304 debugnodemap: dump-new, dump-disk, check, metadata
305 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
305 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
306 debugp1copies: rev
306 debugp1copies: rev
307 debugp2copies: rev
307 debugp2copies: rev
308 debugpathcomplete: full, normal, added, removed
308 debugpathcomplete: full, normal, added, removed
309 debugpathcopies: include, exclude
309 debugpathcopies: include, exclude
310 debugpeer:
310 debugpeer:
311 debugpickmergetool: rev, changedelete, include, exclude, tool
311 debugpickmergetool: rev, changedelete, include, exclude, tool
312 debugpushkey:
312 debugpushkey:
313 debugpvec:
313 debugpvec:
314 debugrebuilddirstate: rev, minimal
314 debugrebuilddirstate: rev, minimal
315 debugrebuildfncache:
315 debugrebuildfncache:
316 debugrename: rev
316 debugrename: rev
317 debugrequires:
317 debugrequires:
318 debugrevlog: changelog, manifest, dir, dump
318 debugrevlog: changelog, manifest, dir, dump
319 debugrevlogindex: changelog, manifest, dir, format
319 debugrevlogindex: changelog, manifest, dir, format
320 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
320 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
321 debugserve: sshstdio, logiofd, logiofile
321 debugserve: sshstdio, logiofd, logiofile
322 debugsetparents:
322 debugsetparents:
323 debugshell:
323 debugshell:
324 debugsidedata: changelog, manifest, dir
324 debugsidedata: changelog, manifest, dir
325 debugssl:
325 debugssl:
326 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
326 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
327 debugsub: rev
327 debugsub: rev
328 debugsuccessorssets: closest
328 debugsuccessorssets: closest
329 debugtagscache:
329 debugtagscache:
330 debugtemplate: rev, define
330 debugtemplate: rev, define
331 debuguigetpass: prompt
331 debuguigetpass: prompt
332 debuguiprompt: prompt
332 debuguiprompt: prompt
333 debugupdatecaches:
333 debugupdatecaches:
334 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
334 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
335 debugwalk: include, exclude
335 debugwalk: include, exclude
336 debugwhyunstable:
336 debugwhyunstable:
337 debugwireargs: three, four, five, ssh, remotecmd, insecure
337 debugwireargs: three, four, five, ssh, remotecmd, insecure
338 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
338 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
339 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
339 diff: rev, from, to, change, merge, 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
340 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
340 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
341 files: rev, print0, include, exclude, template, subrepos
341 files: rev, print0, include, exclude, template, subrepos
342 forget: interactive, include, exclude, dry-run
342 forget: interactive, include, exclude, dry-run
343 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
343 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
344 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
344 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
345 heads: rev, topo, active, closed, style, template
345 heads: rev, topo, active, closed, style, template
346 help: extension, command, keyword, system
346 help: extension, command, keyword, system
347 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
347 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
348 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
348 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
349 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
349 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
350 init: ssh, remotecmd, insecure
350 init: ssh, remotecmd, insecure
351 locate: rev, print0, fullpath, include, exclude
351 locate: rev, print0, fullpath, include, exclude
352 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
352 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
353 manifest: rev, all, template
353 manifest: rev, all, template
354 merge: force, rev, preview, abort, tool
354 merge: force, rev, preview, abort, tool
355 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
355 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
356 parents: rev, style, template
356 parents: rev, style, template
357 paths: template
357 paths: template
358 phase: public, draft, secret, force, rev
358 phase: public, draft, secret, force, rev
359 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
359 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
360 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
360 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
361 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
361 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
362 recover: verify
362 recover: verify
363 remove: after, force, subrepos, include, exclude, dry-run
363 remove: after, force, subrepos, include, exclude, dry-run
364 rename: after, at-rev, force, include, exclude, dry-run
364 rename: after, at-rev, force, include, exclude, dry-run
365 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
365 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
366 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
366 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
367 rollback: dry-run, force
367 rollback: dry-run, force
368 root: template
368 root: template
369 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
369 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
370 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
370 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
371 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
371 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
372 summary: remote
372 summary: remote
373 tag: force, local, rev, remove, edit, message, date, user
373 tag: force, local, rev, remove, edit, message, date, user
374 tags: template
374 tags: template
375 tip: patch, git, style, template
375 tip: patch, git, style, template
376 unbundle: update
376 unbundle: update
377 unshelve: abort, continue, interactive, keep, name, tool, date
377 unshelve: abort, continue, interactive, keep, name, tool, date
378 update: clean, check, merge, date, rev, tool
378 update: clean, check, merge, date, rev, tool
379 verify: full
379 verify: full
380 version: template
380 version: template
381
381
382 $ hg init a
382 $ hg init a
383 $ cd a
383 $ cd a
384 $ echo fee > fee
384 $ echo fee > fee
385 $ hg ci -q -Amfee
385 $ hg ci -q -Amfee
386 $ hg tag fee
386 $ hg tag fee
387 $ mkdir fie
387 $ mkdir fie
388 $ echo dead > fie/dead
388 $ echo dead > fie/dead
389 $ echo live > fie/live
389 $ echo live > fie/live
390 $ hg bookmark fo
390 $ hg bookmark fo
391 $ hg branch -q fie
391 $ hg branch -q fie
392 $ hg ci -q -Amfie
392 $ hg ci -q -Amfie
393 $ echo fo > fo
393 $ echo fo > fo
394 $ hg branch -qf default
394 $ hg branch -qf default
395 $ hg ci -q -Amfo
395 $ hg ci -q -Amfo
396 $ echo Fum > Fum
396 $ echo Fum > Fum
397 $ hg ci -q -AmFum
397 $ hg ci -q -AmFum
398 $ hg bookmark Fum
398 $ hg bookmark Fum
399
399
400 Test debugpathcomplete
400 Test debugpathcomplete
401
401
402 $ hg debugpathcomplete f
402 $ hg debugpathcomplete f
403 fee
403 fee
404 fie
404 fie
405 fo
405 fo
406 $ hg debugpathcomplete -f f
406 $ hg debugpathcomplete -f f
407 fee
407 fee
408 fie/dead
408 fie/dead
409 fie/live
409 fie/live
410 fo
410 fo
411
411
412 $ hg rm Fum
412 $ hg rm Fum
413 $ hg debugpathcomplete -r F
413 $ hg debugpathcomplete -r F
414 Fum
414 Fum
415
415
416 Test debugnamecomplete
416 Test debugnamecomplete
417
417
418 $ hg debugnamecomplete
418 $ hg debugnamecomplete
419 Fum
419 Fum
420 default
420 default
421 fee
421 fee
422 fie
422 fie
423 fo
423 fo
424 tip
424 tip
425 $ hg debugnamecomplete f
425 $ hg debugnamecomplete f
426 fee
426 fee
427 fie
427 fie
428 fo
428 fo
429
429
430 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
430 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
431 used for completions in some shells.
431 used for completions in some shells.
432
432
433 $ hg debuglabelcomplete
433 $ hg debuglabelcomplete
434 Fum
434 Fum
435 default
435 default
436 fee
436 fee
437 fie
437 fie
438 fo
438 fo
439 tip
439 tip
440 $ hg debuglabelcomplete f
440 $ hg debuglabelcomplete f
441 fee
441 fee
442 fie
442 fie
443 fo
443 fo
@@ -1,197 +1,301 b''
1 Testing diff --change, --from, --to
1 Testing diff --change, --from, --to
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5
5
6 $ echo "first" > file.txt
6 $ echo "first" > file.txt
7 $ hg add file.txt
7 $ hg add file.txt
8 $ hg commit -m 'first commit' # 0
8 $ hg commit -m 'first commit' # 0
9
9
10 $ echo "second" > file.txt
10 $ echo "second" > file.txt
11 $ hg commit -m 'second commit' # 1
11 $ hg commit -m 'second commit' # 1
12
12
13 $ echo "third" > file.txt
13 $ echo "third" > file.txt
14 $ hg commit -m 'third commit' # 2
14 $ hg commit -m 'third commit' # 2
15
15
16 $ hg diff --nodates --change 1
16 $ hg diff --nodates --change 1
17 diff -r 4bb65dda5db4 -r e9b286083166 file.txt
17 diff -r 4bb65dda5db4 -r e9b286083166 file.txt
18 --- a/file.txt
18 --- a/file.txt
19 +++ b/file.txt
19 +++ b/file.txt
20 @@ -1,1 +1,1 @@
20 @@ -1,1 +1,1 @@
21 -first
21 -first
22 +second
22 +second
23
23
24 $ hg diff --change e9b286083166
24 $ hg diff --change e9b286083166
25 diff -r 4bb65dda5db4 -r e9b286083166 file.txt
25 diff -r 4bb65dda5db4 -r e9b286083166 file.txt
26 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
26 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
27 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
27 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
28 @@ -1,1 +1,1 @@
28 @@ -1,1 +1,1 @@
29 -first
29 -first
30 +second
30 +second
31
31
32 Test --from and --to
32 Test --from and --to
33
33
34 $ hg diff --from . --rev .
34 $ hg diff --from . --rev .
35 abort: cannot specify both --from and --rev
35 abort: cannot specify both --from and --rev
36 [10]
36 [10]
37 $ hg diff --to . --rev .
37 $ hg diff --to . --rev .
38 abort: cannot specify both --to and --rev
38 abort: cannot specify both --to and --rev
39 [10]
39 [10]
40 $ hg diff --from . --change .
40 $ hg diff --from . --change .
41 abort: cannot specify both --from and --change
41 abort: cannot specify both --from and --change
42 [10]
42 [10]
43 $ hg diff --to . --change .
43 $ hg diff --to . --change .
44 abort: cannot specify both --to and --change
44 abort: cannot specify both --to and --change
45 [10]
45 [10]
46 $ echo dirty > file.txt
46 $ echo dirty > file.txt
47 $ hg diff --from .
47 $ hg diff --from .
48 diff -r bf5ff72eb7e0 file.txt
48 diff -r bf5ff72eb7e0 file.txt
49 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
49 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
50 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
50 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
51 @@ -1,1 +1,1 @@
51 @@ -1,1 +1,1 @@
52 -third
52 -third
53 +dirty
53 +dirty
54 $ hg diff --from . --reverse
54 $ hg diff --from . --reverse
55 diff -r bf5ff72eb7e0 file.txt
55 diff -r bf5ff72eb7e0 file.txt
56 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
56 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
57 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
57 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
58 @@ -1,1 +1,1 @@
58 @@ -1,1 +1,1 @@
59 -dirty
59 -dirty
60 +third
60 +third
61 $ hg diff --to .
61 $ hg diff --to .
62 diff -r bf5ff72eb7e0 file.txt
62 diff -r bf5ff72eb7e0 file.txt
63 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
63 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
64 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
64 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
65 @@ -1,1 +1,1 @@
65 @@ -1,1 +1,1 @@
66 -dirty
66 -dirty
67 +third
67 +third
68 $ hg diff --from 0 --to 2
68 $ hg diff --from 0 --to 2
69 diff -r 4bb65dda5db4 -r bf5ff72eb7e0 file.txt
69 diff -r 4bb65dda5db4 -r bf5ff72eb7e0 file.txt
70 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
70 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
71 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
71 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
72 @@ -1,1 +1,1 @@
72 @@ -1,1 +1,1 @@
73 -first
73 -first
74 +third
74 +third
75 $ hg diff --from 2 --to 0
75 $ hg diff --from 2 --to 0
76 diff -r bf5ff72eb7e0 -r 4bb65dda5db4 file.txt
76 diff -r bf5ff72eb7e0 -r 4bb65dda5db4 file.txt
77 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
77 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
78 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
78 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
79 @@ -1,1 +1,1 @@
79 @@ -1,1 +1,1 @@
80 -third
80 -third
81 +first
81 +first
82 $ hg co -C .
82 $ hg co -C .
83 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
84
84
85 $ cd ..
85 $ cd ..
86
86
87 Test dumb revspecs: top-level "x:y", "x:", ":y" and ":" ranges should be handled
87 Test dumb revspecs: top-level "x:y", "x:", ":y" and ":" ranges should be handled
88 as pairs even if x == y, but not for "f(x:y)" nor "x::y" (issue3474, issue4774)
88 as pairs even if x == y, but not for "f(x:y)" nor "x::y" (issue3474, issue4774)
89
89
90 $ hg clone -q a dumbspec
90 $ hg clone -q a dumbspec
91 $ cd dumbspec
91 $ cd dumbspec
92 $ echo "wdir" > file.txt
92 $ echo "wdir" > file.txt
93
93
94 $ hg diff -r 2:2
94 $ hg diff -r 2:2
95 $ hg diff -r 2:.
95 $ hg diff -r 2:.
96 $ hg diff -r 2:
96 $ hg diff -r 2:
97 $ hg diff -r :0
97 $ hg diff -r :0
98 $ hg diff -r '2:first(2:2)'
98 $ hg diff -r '2:first(2:2)'
99 $ hg diff -r 'first(2:2)' --nodates
99 $ hg diff -r 'first(2:2)' --nodates
100 diff -r bf5ff72eb7e0 file.txt
100 diff -r bf5ff72eb7e0 file.txt
101 --- a/file.txt
101 --- a/file.txt
102 +++ b/file.txt
102 +++ b/file.txt
103 @@ -1,1 +1,1 @@
103 @@ -1,1 +1,1 @@
104 -third
104 -third
105 +wdir
105 +wdir
106 $ hg diff -r '(2:2)' --nodates
106 $ hg diff -r '(2:2)' --nodates
107 diff -r bf5ff72eb7e0 file.txt
107 diff -r bf5ff72eb7e0 file.txt
108 --- a/file.txt
108 --- a/file.txt
109 +++ b/file.txt
109 +++ b/file.txt
110 @@ -1,1 +1,1 @@
110 @@ -1,1 +1,1 @@
111 -third
111 -third
112 +wdir
112 +wdir
113 $ hg diff -r 2::2 --nodates
113 $ hg diff -r 2::2 --nodates
114 diff -r bf5ff72eb7e0 file.txt
114 diff -r bf5ff72eb7e0 file.txt
115 --- a/file.txt
115 --- a/file.txt
116 +++ b/file.txt
116 +++ b/file.txt
117 @@ -1,1 +1,1 @@
117 @@ -1,1 +1,1 @@
118 -third
118 -third
119 +wdir
119 +wdir
120 $ hg diff -r "2 and 1"
120 $ hg diff -r "2 and 1"
121 abort: empty revision range
121 abort: empty revision range
122 [255]
122 [255]
123
123
124 $ cd ..
124 $ cd ..
125
125
126 $ hg clone -qr0 a dumbspec-rev0
126 $ hg clone -qr0 a dumbspec-rev0
127 $ cd dumbspec-rev0
127 $ cd dumbspec-rev0
128 $ echo "wdir" > file.txt
128 $ echo "wdir" > file.txt
129
129
130 $ hg diff -r :
130 $ hg diff -r :
131 $ hg diff -r 'first(:)' --nodates
131 $ hg diff -r 'first(:)' --nodates
132 diff -r 4bb65dda5db4 file.txt
132 diff -r 4bb65dda5db4 file.txt
133 --- a/file.txt
133 --- a/file.txt
134 +++ b/file.txt
134 +++ b/file.txt
135 @@ -1,1 +1,1 @@
135 @@ -1,1 +1,1 @@
136 -first
136 -first
137 +wdir
137 +wdir
138
138
139 $ cd ..
139 $ cd ..
140
140
141 Testing diff --change when merge:
141 Testing diff --change when merge:
142
142
143 $ cd a
143 $ cd a
144
144
145 $ for i in 1 2 3 4 5 6 7 8 9 10; do
145 $ for i in 1 2 3 4 5 6 7 8 9 10; do
146 > echo $i >> file.txt
146 > echo $i >> file.txt
147 > done
147 > done
148 $ hg commit -m "lots of text" # 3
148 $ hg commit -m "lots of text" # 3
149
149
150 $ sed -e 's,^2$,x,' file.txt > file.txt.tmp
150 $ sed -e 's,^2$,x,' file.txt > file.txt.tmp
151 $ mv file.txt.tmp file.txt
151 $ mv file.txt.tmp file.txt
152 $ hg commit -m "change 2 to x" # 4
152 $ hg commit -m "change 2 to x" # 4
153
153
154 $ hg up -r 3
154 $ hg up -r 3
155 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 $ sed -e 's,^8$,y,' file.txt > file.txt.tmp
156 $ sed -e 's,^8$,y,' file.txt > file.txt.tmp
157 $ mv file.txt.tmp file.txt
157 $ mv file.txt.tmp file.txt
158 $ hg commit -m "change 8 to y"
158 $ hg commit -m "change 8 to y"
159 created new head
159 created new head
160
160
161 $ hg up -C -r 4
161 $ hg up -C -r 4
162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
163 $ hg merge -r 5
163 $ hg merge -r 5
164 merging file.txt
164 merging file.txt
165 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
165 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
166 (branch merge, don't forget to commit)
166 (branch merge, don't forget to commit)
167 $ hg commit -m "merge 8 to y" # 6
167 $ hg commit -m "merge 8 to y" # 6
168
168
169 $ hg diff --change 5
169 $ hg diff --change 5
170 diff -r ae119d680c82 -r 9085c5c02e52 file.txt
170 diff -r ae119d680c82 -r 9085c5c02e52 file.txt
171 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
171 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
172 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
172 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
173 @@ -6,6 +6,6 @@
173 @@ -6,6 +6,6 @@
174 5
174 5
175 6
175 6
176 7
176 7
177 -8
177 -8
178 +y
178 +y
179 9
179 9
180 10
180 10
181
181
182 must be similar to 'hg diff --change 5':
182 must be similar to 'hg diff --change 5':
183
183
184 $ hg diff -c 6
184 $ hg diff -c 6
185 diff -r 273b50f17c6d -r 979ca961fd2e file.txt
185 diff -r 273b50f17c6d -r 979ca961fd2e file.txt
186 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
186 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
187 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
187 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
188 @@ -6,6 +6,6 @@
188 @@ -6,6 +6,6 @@
189 5
189 5
190 6
190 6
191 7
191 7
192 -8
192 -8
193 +y
193 +y
194 9
194 9
195 10
195 10
196
196
197 merge diff should show only manual edits to a merge:
198
199 $ hg diff --merge -c 6
200 merging file.txt
201 (no diff output is expected here)
202
203 Construct an "evil merge" that does something other than just the merge.
204
205 $ hg co ".^"
206 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 $ hg merge -r 5
208 merging file.txt
209 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
210 (branch merge, don't forget to commit)
211 $ echo 11 >> file.txt
212 $ hg ci -m 'merge 8 to y with manual edit of 11' # 7
213 created new head
214 $ hg diff -c 7
215 diff -r 273b50f17c6d -r 8ad85e839ba7 file.txt
216 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
217 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
218 @@ -6,6 +6,7 @@
219 5
220 6
221 7
222 -8
223 +y
224 9
225 10
226 +11
227 Contrast with the `hg diff -c 7` version above: only the manual edit shows
228 up, making it easy to identify changes someone is otherwise trying to sneak
229 into a merge.
230 $ hg diff --merge -c 7
231 merging file.txt
232 diff -r 8ad85e839ba7 file.txt
233 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
234 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
235 @@ -9,3 +9,4 @@
236 y
237 9
238 10
239 +11
240
241 Set up a conflict.
242 $ hg co ".^"
243 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
244 $ sed -e 's,^8$,z,' file.txt > file.txt.tmp
245 $ mv file.txt.tmp file.txt
246 $ hg ci -m 'conflicting edit: 8 to z'
247 created new head
248 $ echo "this file is new in p1 of the merge" > new-file-p1.txt
249 $ hg ci -Am 'new file' new-file-p1.txt
250 $ hg log -r . --template 'p1 will be rev {rev}\n'
251 p1 will be rev 9
252 $ hg co 5
253 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
254 $ echo "this file is new in p2 of the merge" > new-file-p2.txt
255 $ hg ci -Am 'new file' new-file-p2.txt
256 created new head
257 $ hg log -r . --template 'p2 will be rev {rev}\n'
258 p2 will be rev 10
259 $ hg co -- 9
260 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
261 $ hg merge -r 10
262 merging file.txt
263 warning: conflicts while merging file.txt! (edit, then use 'hg resolve --mark')
264 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
265 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
266 [1]
267 $ hg revert file.txt -r .
268 $ hg resolve -ma
269 (no more unresolved files)
270 $ hg commit -m 'merge conflicted edit'
271 Without --merge, it's a diff against p1
272 $ hg diff --no-merge -c 11
273 diff -r fd1f17c90d7c -r 5010caab09f6 new-file-p2.txt
274 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
275 +++ b/new-file-p2.txt Thu Jan 01 00:00:00 1970 +0000
276 @@ -0,0 +1,1 @@
277 +this file is new in p2 of the merge
278 With --merge, it's a diff against the conflicted content.
279 $ hg diff --merge -c 11
280 merging file.txt
281 diff -r 5010caab09f6 file.txt
282 --- a/file.txt Thu Jan 01 00:00:00 1970 +0000
283 +++ b/file.txt Thu Jan 01 00:00:00 1970 +0000
284 @@ -6,12 +6,6 @@
285 5
286 6
287 7
288 -<<<<<<< local: fd1f17c90d7c - test: new file
289 z
290 -||||||| base
291 -8
292 -=======
293 -y
294 ->>>>>>> other: d9e7de69eac3 - test: new file
295 9
296 10
297
298 There must _NOT_ be a .hg/merge directory leftover.
299 $ test ! -d .hg/merge
300 (No output is expected)
197 $ cd ..
301 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now