##// END OF EJS Templates
config: add `--shared` flag to edit config file of shared source...
Pulkit Goyal -
r46058:ac7a3da0 default
parent child Browse files
Show More
@@ -1,7848 +1,7871 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import os
12 import os
13 import re
13 import re
14 import sys
14 import sys
15
15
16 from .i18n import _
16 from .i18n import _
17 from .node import (
17 from .node import (
18 hex,
18 hex,
19 nullid,
19 nullid,
20 nullrev,
20 nullrev,
21 short,
21 short,
22 wdirhex,
22 wdirhex,
23 wdirrev,
23 wdirrev,
24 )
24 )
25 from .pycompat import open
25 from .pycompat import open
26 from . import (
26 from . import (
27 archival,
27 archival,
28 bookmarks,
28 bookmarks,
29 bundle2,
29 bundle2,
30 changegroup,
30 changegroup,
31 cmdutil,
31 cmdutil,
32 copies,
32 copies,
33 debugcommands as debugcommandsmod,
33 debugcommands as debugcommandsmod,
34 destutil,
34 destutil,
35 dirstateguard,
35 dirstateguard,
36 discovery,
36 discovery,
37 encoding,
37 encoding,
38 error,
38 error,
39 exchange,
39 exchange,
40 extensions,
40 extensions,
41 filemerge,
41 filemerge,
42 formatter,
42 formatter,
43 graphmod,
43 graphmod,
44 hbisect,
44 hbisect,
45 help,
45 help,
46 hg,
46 hg,
47 logcmdutil,
47 logcmdutil,
48 merge as mergemod,
48 merge as mergemod,
49 mergestate as mergestatemod,
49 mergestate as mergestatemod,
50 narrowspec,
50 narrowspec,
51 obsolete,
51 obsolete,
52 obsutil,
52 obsutil,
53 patch,
53 patch,
54 phases,
54 phases,
55 pycompat,
55 pycompat,
56 rcutil,
56 rcutil,
57 registrar,
57 registrar,
58 requirements,
58 revsetlang,
59 revsetlang,
59 rewriteutil,
60 rewriteutil,
60 scmutil,
61 scmutil,
61 server,
62 server,
62 shelve as shelvemod,
63 shelve as shelvemod,
63 state as statemod,
64 state as statemod,
64 streamclone,
65 streamclone,
65 tags as tagsmod,
66 tags as tagsmod,
66 ui as uimod,
67 ui as uimod,
67 util,
68 util,
68 verify as verifymod,
69 verify as verifymod,
70 vfs as vfsmod,
69 wireprotoserver,
71 wireprotoserver,
70 )
72 )
71 from .utils import (
73 from .utils import (
72 dateutil,
74 dateutil,
73 stringutil,
75 stringutil,
74 )
76 )
75
77
76 table = {}
78 table = {}
77 table.update(debugcommandsmod.command._table)
79 table.update(debugcommandsmod.command._table)
78
80
79 command = registrar.command(table)
81 command = registrar.command(table)
80 INTENT_READONLY = registrar.INTENT_READONLY
82 INTENT_READONLY = registrar.INTENT_READONLY
81
83
82 # common command options
84 # common command options
83
85
84 globalopts = [
86 globalopts = [
85 (
87 (
86 b'R',
88 b'R',
87 b'repository',
89 b'repository',
88 b'',
90 b'',
89 _(b'repository root directory or name of overlay bundle file'),
91 _(b'repository root directory or name of overlay bundle file'),
90 _(b'REPO'),
92 _(b'REPO'),
91 ),
93 ),
92 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
94 (b'', b'cwd', b'', _(b'change working directory'), _(b'DIR')),
93 (
95 (
94 b'y',
96 b'y',
95 b'noninteractive',
97 b'noninteractive',
96 None,
98 None,
97 _(
99 _(
98 b'do not prompt, automatically pick the first choice for all prompts'
100 b'do not prompt, automatically pick the first choice for all prompts'
99 ),
101 ),
100 ),
102 ),
101 (b'q', b'quiet', None, _(b'suppress output')),
103 (b'q', b'quiet', None, _(b'suppress output')),
102 (b'v', b'verbose', None, _(b'enable additional output')),
104 (b'v', b'verbose', None, _(b'enable additional output')),
103 (
105 (
104 b'',
106 b'',
105 b'color',
107 b'color',
106 b'',
108 b'',
107 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
109 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
108 # and should not be translated
110 # and should not be translated
109 _(b"when to colorize (boolean, always, auto, never, or debug)"),
111 _(b"when to colorize (boolean, always, auto, never, or debug)"),
110 _(b'TYPE'),
112 _(b'TYPE'),
111 ),
113 ),
112 (
114 (
113 b'',
115 b'',
114 b'config',
116 b'config',
115 [],
117 [],
116 _(b'set/override config option (use \'section.name=value\')'),
118 _(b'set/override config option (use \'section.name=value\')'),
117 _(b'CONFIG'),
119 _(b'CONFIG'),
118 ),
120 ),
119 (b'', b'debug', None, _(b'enable debugging output')),
121 (b'', b'debug', None, _(b'enable debugging output')),
120 (b'', b'debugger', None, _(b'start debugger')),
122 (b'', b'debugger', None, _(b'start debugger')),
121 (
123 (
122 b'',
124 b'',
123 b'encoding',
125 b'encoding',
124 encoding.encoding,
126 encoding.encoding,
125 _(b'set the charset encoding'),
127 _(b'set the charset encoding'),
126 _(b'ENCODE'),
128 _(b'ENCODE'),
127 ),
129 ),
128 (
130 (
129 b'',
131 b'',
130 b'encodingmode',
132 b'encodingmode',
131 encoding.encodingmode,
133 encoding.encodingmode,
132 _(b'set the charset encoding mode'),
134 _(b'set the charset encoding mode'),
133 _(b'MODE'),
135 _(b'MODE'),
134 ),
136 ),
135 (b'', b'traceback', None, _(b'always print a traceback on exception')),
137 (b'', b'traceback', None, _(b'always print a traceback on exception')),
136 (b'', b'time', None, _(b'time how long the command takes')),
138 (b'', b'time', None, _(b'time how long the command takes')),
137 (b'', b'profile', None, _(b'print command execution profile')),
139 (b'', b'profile', None, _(b'print command execution profile')),
138 (b'', b'version', None, _(b'output version information and exit')),
140 (b'', b'version', None, _(b'output version information and exit')),
139 (b'h', b'help', None, _(b'display help and exit')),
141 (b'h', b'help', None, _(b'display help and exit')),
140 (b'', b'hidden', False, _(b'consider hidden changesets')),
142 (b'', b'hidden', False, _(b'consider hidden changesets')),
141 (
143 (
142 b'',
144 b'',
143 b'pager',
145 b'pager',
144 b'auto',
146 b'auto',
145 _(b"when to paginate (boolean, always, auto, or never)"),
147 _(b"when to paginate (boolean, always, auto, or never)"),
146 _(b'TYPE'),
148 _(b'TYPE'),
147 ),
149 ),
148 ]
150 ]
149
151
150 dryrunopts = cmdutil.dryrunopts
152 dryrunopts = cmdutil.dryrunopts
151 remoteopts = cmdutil.remoteopts
153 remoteopts = cmdutil.remoteopts
152 walkopts = cmdutil.walkopts
154 walkopts = cmdutil.walkopts
153 commitopts = cmdutil.commitopts
155 commitopts = cmdutil.commitopts
154 commitopts2 = cmdutil.commitopts2
156 commitopts2 = cmdutil.commitopts2
155 commitopts3 = cmdutil.commitopts3
157 commitopts3 = cmdutil.commitopts3
156 formatteropts = cmdutil.formatteropts
158 formatteropts = cmdutil.formatteropts
157 templateopts = cmdutil.templateopts
159 templateopts = cmdutil.templateopts
158 logopts = cmdutil.logopts
160 logopts = cmdutil.logopts
159 diffopts = cmdutil.diffopts
161 diffopts = cmdutil.diffopts
160 diffwsopts = cmdutil.diffwsopts
162 diffwsopts = cmdutil.diffwsopts
161 diffopts2 = cmdutil.diffopts2
163 diffopts2 = cmdutil.diffopts2
162 mergetoolopts = cmdutil.mergetoolopts
164 mergetoolopts = cmdutil.mergetoolopts
163 similarityopts = cmdutil.similarityopts
165 similarityopts = cmdutil.similarityopts
164 subrepoopts = cmdutil.subrepoopts
166 subrepoopts = cmdutil.subrepoopts
165 debugrevlogopts = cmdutil.debugrevlogopts
167 debugrevlogopts = cmdutil.debugrevlogopts
166
168
167 # Commands start here, listed alphabetically
169 # Commands start here, listed alphabetically
168
170
169
171
170 @command(
172 @command(
171 b'abort',
173 b'abort',
172 dryrunopts,
174 dryrunopts,
173 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
175 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
174 helpbasic=True,
176 helpbasic=True,
175 )
177 )
176 def abort(ui, repo, **opts):
178 def abort(ui, repo, **opts):
177 """abort an unfinished operation (EXPERIMENTAL)
179 """abort an unfinished operation (EXPERIMENTAL)
178
180
179 Aborts a multistep operation like graft, histedit, rebase, merge,
181 Aborts a multistep operation like graft, histedit, rebase, merge,
180 and unshelve if they are in an unfinished state.
182 and unshelve if they are in an unfinished state.
181
183
182 use --dry-run/-n to dry run the command.
184 use --dry-run/-n to dry run the command.
183 """
185 """
184 dryrun = opts.get('dry_run')
186 dryrun = opts.get('dry_run')
185 abortstate = cmdutil.getunfinishedstate(repo)
187 abortstate = cmdutil.getunfinishedstate(repo)
186 if not abortstate:
188 if not abortstate:
187 raise error.Abort(_(b'no operation in progress'))
189 raise error.Abort(_(b'no operation in progress'))
188 if not abortstate.abortfunc:
190 if not abortstate.abortfunc:
189 raise error.Abort(
191 raise error.Abort(
190 (
192 (
191 _(b"%s in progress but does not support 'hg abort'")
193 _(b"%s in progress but does not support 'hg abort'")
192 % (abortstate._opname)
194 % (abortstate._opname)
193 ),
195 ),
194 hint=abortstate.hint(),
196 hint=abortstate.hint(),
195 )
197 )
196 if dryrun:
198 if dryrun:
197 ui.status(
199 ui.status(
198 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
200 _(b'%s in progress, will be aborted\n') % (abortstate._opname)
199 )
201 )
200 return
202 return
201 return abortstate.abortfunc(ui, repo)
203 return abortstate.abortfunc(ui, repo)
202
204
203
205
204 @command(
206 @command(
205 b'add',
207 b'add',
206 walkopts + subrepoopts + dryrunopts,
208 walkopts + subrepoopts + dryrunopts,
207 _(b'[OPTION]... [FILE]...'),
209 _(b'[OPTION]... [FILE]...'),
208 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
210 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
209 helpbasic=True,
211 helpbasic=True,
210 inferrepo=True,
212 inferrepo=True,
211 )
213 )
212 def add(ui, repo, *pats, **opts):
214 def add(ui, repo, *pats, **opts):
213 """add the specified files on the next commit
215 """add the specified files on the next commit
214
216
215 Schedule files to be version controlled and added to the
217 Schedule files to be version controlled and added to the
216 repository.
218 repository.
217
219
218 The files will be added to the repository at the next commit. To
220 The files will be added to the repository at the next commit. To
219 undo an add before that, see :hg:`forget`.
221 undo an add before that, see :hg:`forget`.
220
222
221 If no names are given, add all files to the repository (except
223 If no names are given, add all files to the repository (except
222 files matching ``.hgignore``).
224 files matching ``.hgignore``).
223
225
224 .. container:: verbose
226 .. container:: verbose
225
227
226 Examples:
228 Examples:
227
229
228 - New (unknown) files are added
230 - New (unknown) files are added
229 automatically by :hg:`add`::
231 automatically by :hg:`add`::
230
232
231 $ ls
233 $ ls
232 foo.c
234 foo.c
233 $ hg status
235 $ hg status
234 ? foo.c
236 ? foo.c
235 $ hg add
237 $ hg add
236 adding foo.c
238 adding foo.c
237 $ hg status
239 $ hg status
238 A foo.c
240 A foo.c
239
241
240 - Specific files to be added can be specified::
242 - Specific files to be added can be specified::
241
243
242 $ ls
244 $ ls
243 bar.c foo.c
245 bar.c foo.c
244 $ hg status
246 $ hg status
245 ? bar.c
247 ? bar.c
246 ? foo.c
248 ? foo.c
247 $ hg add bar.c
249 $ hg add bar.c
248 $ hg status
250 $ hg status
249 A bar.c
251 A bar.c
250 ? foo.c
252 ? foo.c
251
253
252 Returns 0 if all files are successfully added.
254 Returns 0 if all files are successfully added.
253 """
255 """
254
256
255 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
257 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
256 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
258 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
257 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
259 rejected = cmdutil.add(ui, repo, m, b"", uipathfn, False, **opts)
258 return rejected and 1 or 0
260 return rejected and 1 or 0
259
261
260
262
261 @command(
263 @command(
262 b'addremove',
264 b'addremove',
263 similarityopts + subrepoopts + walkopts + dryrunopts,
265 similarityopts + subrepoopts + walkopts + dryrunopts,
264 _(b'[OPTION]... [FILE]...'),
266 _(b'[OPTION]... [FILE]...'),
265 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
267 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
266 inferrepo=True,
268 inferrepo=True,
267 )
269 )
268 def addremove(ui, repo, *pats, **opts):
270 def addremove(ui, repo, *pats, **opts):
269 """add all new files, delete all missing files
271 """add all new files, delete all missing files
270
272
271 Add all new files and remove all missing files from the
273 Add all new files and remove all missing files from the
272 repository.
274 repository.
273
275
274 Unless names are given, new files are ignored if they match any of
276 Unless names are given, new files are ignored if they match any of
275 the patterns in ``.hgignore``. As with add, these changes take
277 the patterns in ``.hgignore``. As with add, these changes take
276 effect at the next commit.
278 effect at the next commit.
277
279
278 Use the -s/--similarity option to detect renamed files. This
280 Use the -s/--similarity option to detect renamed files. This
279 option takes a percentage between 0 (disabled) and 100 (files must
281 option takes a percentage between 0 (disabled) and 100 (files must
280 be identical) as its parameter. With a parameter greater than 0,
282 be identical) as its parameter. With a parameter greater than 0,
281 this compares every removed file with every added file and records
283 this compares every removed file with every added file and records
282 those similar enough as renames. Detecting renamed files this way
284 those similar enough as renames. Detecting renamed files this way
283 can be expensive. After using this option, :hg:`status -C` can be
285 can be expensive. After using this option, :hg:`status -C` can be
284 used to check which files were identified as moved or renamed. If
286 used to check which files were identified as moved or renamed. If
285 not specified, -s/--similarity defaults to 100 and only renames of
287 not specified, -s/--similarity defaults to 100 and only renames of
286 identical files are detected.
288 identical files are detected.
287
289
288 .. container:: verbose
290 .. container:: verbose
289
291
290 Examples:
292 Examples:
291
293
292 - A number of files (bar.c and foo.c) are new,
294 - A number of files (bar.c and foo.c) are new,
293 while foobar.c has been removed (without using :hg:`remove`)
295 while foobar.c has been removed (without using :hg:`remove`)
294 from the repository::
296 from the repository::
295
297
296 $ ls
298 $ ls
297 bar.c foo.c
299 bar.c foo.c
298 $ hg status
300 $ hg status
299 ! foobar.c
301 ! foobar.c
300 ? bar.c
302 ? bar.c
301 ? foo.c
303 ? foo.c
302 $ hg addremove
304 $ hg addremove
303 adding bar.c
305 adding bar.c
304 adding foo.c
306 adding foo.c
305 removing foobar.c
307 removing foobar.c
306 $ hg status
308 $ hg status
307 A bar.c
309 A bar.c
308 A foo.c
310 A foo.c
309 R foobar.c
311 R foobar.c
310
312
311 - A file foobar.c was moved to foo.c without using :hg:`rename`.
313 - A file foobar.c was moved to foo.c without using :hg:`rename`.
312 Afterwards, it was edited slightly::
314 Afterwards, it was edited slightly::
313
315
314 $ ls
316 $ ls
315 foo.c
317 foo.c
316 $ hg status
318 $ hg status
317 ! foobar.c
319 ! foobar.c
318 ? foo.c
320 ? foo.c
319 $ hg addremove --similarity 90
321 $ hg addremove --similarity 90
320 removing foobar.c
322 removing foobar.c
321 adding foo.c
323 adding foo.c
322 recording removal of foobar.c as rename to foo.c (94% similar)
324 recording removal of foobar.c as rename to foo.c (94% similar)
323 $ hg status -C
325 $ hg status -C
324 A foo.c
326 A foo.c
325 foobar.c
327 foobar.c
326 R foobar.c
328 R foobar.c
327
329
328 Returns 0 if all files are successfully added.
330 Returns 0 if all files are successfully added.
329 """
331 """
330 opts = pycompat.byteskwargs(opts)
332 opts = pycompat.byteskwargs(opts)
331 if not opts.get(b'similarity'):
333 if not opts.get(b'similarity'):
332 opts[b'similarity'] = b'100'
334 opts[b'similarity'] = b'100'
333 matcher = scmutil.match(repo[None], pats, opts)
335 matcher = scmutil.match(repo[None], pats, opts)
334 relative = scmutil.anypats(pats, opts)
336 relative = scmutil.anypats(pats, opts)
335 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
337 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
336 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
338 return scmutil.addremove(repo, matcher, b"", uipathfn, opts)
337
339
338
340
339 @command(
341 @command(
340 b'annotate|blame',
342 b'annotate|blame',
341 [
343 [
342 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
344 (b'r', b'rev', b'', _(b'annotate the specified revision'), _(b'REV')),
343 (
345 (
344 b'',
346 b'',
345 b'follow',
347 b'follow',
346 None,
348 None,
347 _(b'follow copies/renames and list the filename (DEPRECATED)'),
349 _(b'follow copies/renames and list the filename (DEPRECATED)'),
348 ),
350 ),
349 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
351 (b'', b'no-follow', None, _(b"don't follow copies and renames")),
350 (b'a', b'text', None, _(b'treat all files as text')),
352 (b'a', b'text', None, _(b'treat all files as text')),
351 (b'u', b'user', None, _(b'list the author (long with -v)')),
353 (b'u', b'user', None, _(b'list the author (long with -v)')),
352 (b'f', b'file', None, _(b'list the filename')),
354 (b'f', b'file', None, _(b'list the filename')),
353 (b'd', b'date', None, _(b'list the date (short with -q)')),
355 (b'd', b'date', None, _(b'list the date (short with -q)')),
354 (b'n', b'number', None, _(b'list the revision number (default)')),
356 (b'n', b'number', None, _(b'list the revision number (default)')),
355 (b'c', b'changeset', None, _(b'list the changeset')),
357 (b'c', b'changeset', None, _(b'list the changeset')),
356 (
358 (
357 b'l',
359 b'l',
358 b'line-number',
360 b'line-number',
359 None,
361 None,
360 _(b'show line number at the first appearance'),
362 _(b'show line number at the first appearance'),
361 ),
363 ),
362 (
364 (
363 b'',
365 b'',
364 b'skip',
366 b'skip',
365 [],
367 [],
366 _(b'revset to not display (EXPERIMENTAL)'),
368 _(b'revset to not display (EXPERIMENTAL)'),
367 _(b'REV'),
369 _(b'REV'),
368 ),
370 ),
369 ]
371 ]
370 + diffwsopts
372 + diffwsopts
371 + walkopts
373 + walkopts
372 + formatteropts,
374 + formatteropts,
373 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
375 _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
374 helpcategory=command.CATEGORY_FILE_CONTENTS,
376 helpcategory=command.CATEGORY_FILE_CONTENTS,
375 helpbasic=True,
377 helpbasic=True,
376 inferrepo=True,
378 inferrepo=True,
377 )
379 )
378 def annotate(ui, repo, *pats, **opts):
380 def annotate(ui, repo, *pats, **opts):
379 """show changeset information by line for each file
381 """show changeset information by line for each file
380
382
381 List changes in files, showing the revision id responsible for
383 List changes in files, showing the revision id responsible for
382 each line.
384 each line.
383
385
384 This command is useful for discovering when a change was made and
386 This command is useful for discovering when a change was made and
385 by whom.
387 by whom.
386
388
387 If you include --file, --user, or --date, the revision number is
389 If you include --file, --user, or --date, the revision number is
388 suppressed unless you also include --number.
390 suppressed unless you also include --number.
389
391
390 Without the -a/--text option, annotate will avoid processing files
392 Without the -a/--text option, annotate will avoid processing files
391 it detects as binary. With -a, annotate will annotate the file
393 it detects as binary. With -a, annotate will annotate the file
392 anyway, although the results will probably be neither useful
394 anyway, although the results will probably be neither useful
393 nor desirable.
395 nor desirable.
394
396
395 .. container:: verbose
397 .. container:: verbose
396
398
397 Template:
399 Template:
398
400
399 The following keywords are supported in addition to the common template
401 The following keywords are supported in addition to the common template
400 keywords and functions. See also :hg:`help templates`.
402 keywords and functions. See also :hg:`help templates`.
401
403
402 :lines: List of lines with annotation data.
404 :lines: List of lines with annotation data.
403 :path: String. Repository-absolute path of the specified file.
405 :path: String. Repository-absolute path of the specified file.
404
406
405 And each entry of ``{lines}`` provides the following sub-keywords in
407 And each entry of ``{lines}`` provides the following sub-keywords in
406 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
408 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
407
409
408 :line: String. Line content.
410 :line: String. Line content.
409 :lineno: Integer. Line number at that revision.
411 :lineno: Integer. Line number at that revision.
410 :path: String. Repository-absolute path of the file at that revision.
412 :path: String. Repository-absolute path of the file at that revision.
411
413
412 See :hg:`help templates.operators` for the list expansion syntax.
414 See :hg:`help templates.operators` for the list expansion syntax.
413
415
414 Returns 0 on success.
416 Returns 0 on success.
415 """
417 """
416 opts = pycompat.byteskwargs(opts)
418 opts = pycompat.byteskwargs(opts)
417 if not pats:
419 if not pats:
418 raise error.Abort(_(b'at least one filename or pattern is required'))
420 raise error.Abort(_(b'at least one filename or pattern is required'))
419
421
420 if opts.get(b'follow'):
422 if opts.get(b'follow'):
421 # --follow is deprecated and now just an alias for -f/--file
423 # --follow is deprecated and now just an alias for -f/--file
422 # to mimic the behavior of Mercurial before version 1.5
424 # to mimic the behavior of Mercurial before version 1.5
423 opts[b'file'] = True
425 opts[b'file'] = True
424
426
425 if (
427 if (
426 not opts.get(b'user')
428 not opts.get(b'user')
427 and not opts.get(b'changeset')
429 and not opts.get(b'changeset')
428 and not opts.get(b'date')
430 and not opts.get(b'date')
429 and not opts.get(b'file')
431 and not opts.get(b'file')
430 ):
432 ):
431 opts[b'number'] = True
433 opts[b'number'] = True
432
434
433 linenumber = opts.get(b'line_number') is not None
435 linenumber = opts.get(b'line_number') is not None
434 if (
436 if (
435 linenumber
437 linenumber
436 and (not opts.get(b'changeset'))
438 and (not opts.get(b'changeset'))
437 and (not opts.get(b'number'))
439 and (not opts.get(b'number'))
438 ):
440 ):
439 raise error.Abort(_(b'at least one of -n/-c is required for -l'))
441 raise error.Abort(_(b'at least one of -n/-c is required for -l'))
440
442
441 rev = opts.get(b'rev')
443 rev = opts.get(b'rev')
442 if rev:
444 if rev:
443 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
445 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
444 ctx = scmutil.revsingle(repo, rev)
446 ctx = scmutil.revsingle(repo, rev)
445
447
446 ui.pager(b'annotate')
448 ui.pager(b'annotate')
447 rootfm = ui.formatter(b'annotate', opts)
449 rootfm = ui.formatter(b'annotate', opts)
448 if ui.debugflag:
450 if ui.debugflag:
449 shorthex = pycompat.identity
451 shorthex = pycompat.identity
450 else:
452 else:
451
453
452 def shorthex(h):
454 def shorthex(h):
453 return h[:12]
455 return h[:12]
454
456
455 if ui.quiet:
457 if ui.quiet:
456 datefunc = dateutil.shortdate
458 datefunc = dateutil.shortdate
457 else:
459 else:
458 datefunc = dateutil.datestr
460 datefunc = dateutil.datestr
459 if ctx.rev() is None:
461 if ctx.rev() is None:
460 if opts.get(b'changeset'):
462 if opts.get(b'changeset'):
461 # omit "+" suffix which is appended to node hex
463 # omit "+" suffix which is appended to node hex
462 def formatrev(rev):
464 def formatrev(rev):
463 if rev == wdirrev:
465 if rev == wdirrev:
464 return b'%d' % ctx.p1().rev()
466 return b'%d' % ctx.p1().rev()
465 else:
467 else:
466 return b'%d' % rev
468 return b'%d' % rev
467
469
468 else:
470 else:
469
471
470 def formatrev(rev):
472 def formatrev(rev):
471 if rev == wdirrev:
473 if rev == wdirrev:
472 return b'%d+' % ctx.p1().rev()
474 return b'%d+' % ctx.p1().rev()
473 else:
475 else:
474 return b'%d ' % rev
476 return b'%d ' % rev
475
477
476 def formathex(h):
478 def formathex(h):
477 if h == wdirhex:
479 if h == wdirhex:
478 return b'%s+' % shorthex(hex(ctx.p1().node()))
480 return b'%s+' % shorthex(hex(ctx.p1().node()))
479 else:
481 else:
480 return b'%s ' % shorthex(h)
482 return b'%s ' % shorthex(h)
481
483
482 else:
484 else:
483 formatrev = b'%d'.__mod__
485 formatrev = b'%d'.__mod__
484 formathex = shorthex
486 formathex = shorthex
485
487
486 opmap = [
488 opmap = [
487 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
489 (b'user', b' ', lambda x: x.fctx.user(), ui.shortuser),
488 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
490 (b'rev', b' ', lambda x: scmutil.intrev(x.fctx), formatrev),
489 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
491 (b'node', b' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
490 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
492 (b'date', b' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
491 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
493 (b'path', b' ', lambda x: x.fctx.path(), pycompat.bytestr),
492 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
494 (b'lineno', b':', lambda x: x.lineno, pycompat.bytestr),
493 ]
495 ]
494 opnamemap = {
496 opnamemap = {
495 b'rev': b'number',
497 b'rev': b'number',
496 b'node': b'changeset',
498 b'node': b'changeset',
497 b'path': b'file',
499 b'path': b'file',
498 b'lineno': b'line_number',
500 b'lineno': b'line_number',
499 }
501 }
500
502
501 if rootfm.isplain():
503 if rootfm.isplain():
502
504
503 def makefunc(get, fmt):
505 def makefunc(get, fmt):
504 return lambda x: fmt(get(x))
506 return lambda x: fmt(get(x))
505
507
506 else:
508 else:
507
509
508 def makefunc(get, fmt):
510 def makefunc(get, fmt):
509 return get
511 return get
510
512
511 datahint = rootfm.datahint()
513 datahint = rootfm.datahint()
512 funcmap = [
514 funcmap = [
513 (makefunc(get, fmt), sep)
515 (makefunc(get, fmt), sep)
514 for fn, sep, get, fmt in opmap
516 for fn, sep, get, fmt in opmap
515 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
517 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
516 ]
518 ]
517 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
519 funcmap[0] = (funcmap[0][0], b'') # no separator in front of first column
518 fields = b' '.join(
520 fields = b' '.join(
519 fn
521 fn
520 for fn, sep, get, fmt in opmap
522 for fn, sep, get, fmt in opmap
521 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
523 if opts.get(opnamemap.get(fn, fn)) or fn in datahint
522 )
524 )
523
525
524 def bad(x, y):
526 def bad(x, y):
525 raise error.Abort(b"%s: %s" % (x, y))
527 raise error.Abort(b"%s: %s" % (x, y))
526
528
527 m = scmutil.match(ctx, pats, opts, badfn=bad)
529 m = scmutil.match(ctx, pats, opts, badfn=bad)
528
530
529 follow = not opts.get(b'no_follow')
531 follow = not opts.get(b'no_follow')
530 diffopts = patch.difffeatureopts(
532 diffopts = patch.difffeatureopts(
531 ui, opts, section=b'annotate', whitespace=True
533 ui, opts, section=b'annotate', whitespace=True
532 )
534 )
533 skiprevs = opts.get(b'skip')
535 skiprevs = opts.get(b'skip')
534 if skiprevs:
536 if skiprevs:
535 skiprevs = scmutil.revrange(repo, skiprevs)
537 skiprevs = scmutil.revrange(repo, skiprevs)
536
538
537 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
539 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
538 for abs in ctx.walk(m):
540 for abs in ctx.walk(m):
539 fctx = ctx[abs]
541 fctx = ctx[abs]
540 rootfm.startitem()
542 rootfm.startitem()
541 rootfm.data(path=abs)
543 rootfm.data(path=abs)
542 if not opts.get(b'text') and fctx.isbinary():
544 if not opts.get(b'text') and fctx.isbinary():
543 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
545 rootfm.plain(_(b"%s: binary file\n") % uipathfn(abs))
544 continue
546 continue
545
547
546 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
548 fm = rootfm.nested(b'lines', tmpl=b'{rev}: {line}')
547 lines = fctx.annotate(
549 lines = fctx.annotate(
548 follow=follow, skiprevs=skiprevs, diffopts=diffopts
550 follow=follow, skiprevs=skiprevs, diffopts=diffopts
549 )
551 )
550 if not lines:
552 if not lines:
551 fm.end()
553 fm.end()
552 continue
554 continue
553 formats = []
555 formats = []
554 pieces = []
556 pieces = []
555
557
556 for f, sep in funcmap:
558 for f, sep in funcmap:
557 l = [f(n) for n in lines]
559 l = [f(n) for n in lines]
558 if fm.isplain():
560 if fm.isplain():
559 sizes = [encoding.colwidth(x) for x in l]
561 sizes = [encoding.colwidth(x) for x in l]
560 ml = max(sizes)
562 ml = max(sizes)
561 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
563 formats.append([sep + b' ' * (ml - w) + b'%s' for w in sizes])
562 else:
564 else:
563 formats.append([b'%s'] * len(l))
565 formats.append([b'%s'] * len(l))
564 pieces.append(l)
566 pieces.append(l)
565
567
566 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
568 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
567 fm.startitem()
569 fm.startitem()
568 fm.context(fctx=n.fctx)
570 fm.context(fctx=n.fctx)
569 fm.write(fields, b"".join(f), *p)
571 fm.write(fields, b"".join(f), *p)
570 if n.skip:
572 if n.skip:
571 fmt = b"* %s"
573 fmt = b"* %s"
572 else:
574 else:
573 fmt = b": %s"
575 fmt = b": %s"
574 fm.write(b'line', fmt, n.text)
576 fm.write(b'line', fmt, n.text)
575
577
576 if not lines[-1].text.endswith(b'\n'):
578 if not lines[-1].text.endswith(b'\n'):
577 fm.plain(b'\n')
579 fm.plain(b'\n')
578 fm.end()
580 fm.end()
579
581
580 rootfm.end()
582 rootfm.end()
581
583
582
584
583 @command(
585 @command(
584 b'archive',
586 b'archive',
585 [
587 [
586 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
588 (b'', b'no-decode', None, _(b'do not pass files through decoders')),
587 (
589 (
588 b'p',
590 b'p',
589 b'prefix',
591 b'prefix',
590 b'',
592 b'',
591 _(b'directory prefix for files in archive'),
593 _(b'directory prefix for files in archive'),
592 _(b'PREFIX'),
594 _(b'PREFIX'),
593 ),
595 ),
594 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
596 (b'r', b'rev', b'', _(b'revision to distribute'), _(b'REV')),
595 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
597 (b't', b'type', b'', _(b'type of distribution to create'), _(b'TYPE')),
596 ]
598 ]
597 + subrepoopts
599 + subrepoopts
598 + walkopts,
600 + walkopts,
599 _(b'[OPTION]... DEST'),
601 _(b'[OPTION]... DEST'),
600 helpcategory=command.CATEGORY_IMPORT_EXPORT,
602 helpcategory=command.CATEGORY_IMPORT_EXPORT,
601 )
603 )
602 def archive(ui, repo, dest, **opts):
604 def archive(ui, repo, dest, **opts):
603 '''create an unversioned archive of a repository revision
605 '''create an unversioned archive of a repository revision
604
606
605 By default, the revision used is the parent of the working
607 By default, the revision used is the parent of the working
606 directory; use -r/--rev to specify a different revision.
608 directory; use -r/--rev to specify a different revision.
607
609
608 The archive type is automatically detected based on file
610 The archive type is automatically detected based on file
609 extension (to override, use -t/--type).
611 extension (to override, use -t/--type).
610
612
611 .. container:: verbose
613 .. container:: verbose
612
614
613 Examples:
615 Examples:
614
616
615 - create a zip file containing the 1.0 release::
617 - create a zip file containing the 1.0 release::
616
618
617 hg archive -r 1.0 project-1.0.zip
619 hg archive -r 1.0 project-1.0.zip
618
620
619 - create a tarball excluding .hg files::
621 - create a tarball excluding .hg files::
620
622
621 hg archive project.tar.gz -X ".hg*"
623 hg archive project.tar.gz -X ".hg*"
622
624
623 Valid types are:
625 Valid types are:
624
626
625 :``files``: a directory full of files (default)
627 :``files``: a directory full of files (default)
626 :``tar``: tar archive, uncompressed
628 :``tar``: tar archive, uncompressed
627 :``tbz2``: tar archive, compressed using bzip2
629 :``tbz2``: tar archive, compressed using bzip2
628 :``tgz``: tar archive, compressed using gzip
630 :``tgz``: tar archive, compressed using gzip
629 :``txz``: tar archive, compressed using lzma (only in Python 3)
631 :``txz``: tar archive, compressed using lzma (only in Python 3)
630 :``uzip``: zip archive, uncompressed
632 :``uzip``: zip archive, uncompressed
631 :``zip``: zip archive, compressed using deflate
633 :``zip``: zip archive, compressed using deflate
632
634
633 The exact name of the destination archive or directory is given
635 The exact name of the destination archive or directory is given
634 using a format string; see :hg:`help export` for details.
636 using a format string; see :hg:`help export` for details.
635
637
636 Each member added to an archive file has a directory prefix
638 Each member added to an archive file has a directory prefix
637 prepended. Use -p/--prefix to specify a format string for the
639 prepended. Use -p/--prefix to specify a format string for the
638 prefix. The default is the basename of the archive, with suffixes
640 prefix. The default is the basename of the archive, with suffixes
639 removed.
641 removed.
640
642
641 Returns 0 on success.
643 Returns 0 on success.
642 '''
644 '''
643
645
644 opts = pycompat.byteskwargs(opts)
646 opts = pycompat.byteskwargs(opts)
645 rev = opts.get(b'rev')
647 rev = opts.get(b'rev')
646 if rev:
648 if rev:
647 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
649 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
648 ctx = scmutil.revsingle(repo, rev)
650 ctx = scmutil.revsingle(repo, rev)
649 if not ctx:
651 if not ctx:
650 raise error.Abort(_(b'no working directory: please specify a revision'))
652 raise error.Abort(_(b'no working directory: please specify a revision'))
651 node = ctx.node()
653 node = ctx.node()
652 dest = cmdutil.makefilename(ctx, dest)
654 dest = cmdutil.makefilename(ctx, dest)
653 if os.path.realpath(dest) == repo.root:
655 if os.path.realpath(dest) == repo.root:
654 raise error.Abort(_(b'repository root cannot be destination'))
656 raise error.Abort(_(b'repository root cannot be destination'))
655
657
656 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
658 kind = opts.get(b'type') or archival.guesskind(dest) or b'files'
657 prefix = opts.get(b'prefix')
659 prefix = opts.get(b'prefix')
658
660
659 if dest == b'-':
661 if dest == b'-':
660 if kind == b'files':
662 if kind == b'files':
661 raise error.Abort(_(b'cannot archive plain files to stdout'))
663 raise error.Abort(_(b'cannot archive plain files to stdout'))
662 dest = cmdutil.makefileobj(ctx, dest)
664 dest = cmdutil.makefileobj(ctx, dest)
663 if not prefix:
665 if not prefix:
664 prefix = os.path.basename(repo.root) + b'-%h'
666 prefix = os.path.basename(repo.root) + b'-%h'
665
667
666 prefix = cmdutil.makefilename(ctx, prefix)
668 prefix = cmdutil.makefilename(ctx, prefix)
667 match = scmutil.match(ctx, [], opts)
669 match = scmutil.match(ctx, [], opts)
668 archival.archive(
670 archival.archive(
669 repo,
671 repo,
670 dest,
672 dest,
671 node,
673 node,
672 kind,
674 kind,
673 not opts.get(b'no_decode'),
675 not opts.get(b'no_decode'),
674 match,
676 match,
675 prefix,
677 prefix,
676 subrepos=opts.get(b'subrepos'),
678 subrepos=opts.get(b'subrepos'),
677 )
679 )
678
680
679
681
680 @command(
682 @command(
681 b'backout',
683 b'backout',
682 [
684 [
683 (
685 (
684 b'',
686 b'',
685 b'merge',
687 b'merge',
686 None,
688 None,
687 _(b'merge with old dirstate parent after backout'),
689 _(b'merge with old dirstate parent after backout'),
688 ),
690 ),
689 (
691 (
690 b'',
692 b'',
691 b'commit',
693 b'commit',
692 None,
694 None,
693 _(b'commit if no conflicts were encountered (DEPRECATED)'),
695 _(b'commit if no conflicts were encountered (DEPRECATED)'),
694 ),
696 ),
695 (b'', b'no-commit', None, _(b'do not commit')),
697 (b'', b'no-commit', None, _(b'do not commit')),
696 (
698 (
697 b'',
699 b'',
698 b'parent',
700 b'parent',
699 b'',
701 b'',
700 _(b'parent to choose when backing out merge (DEPRECATED)'),
702 _(b'parent to choose when backing out merge (DEPRECATED)'),
701 _(b'REV'),
703 _(b'REV'),
702 ),
704 ),
703 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
705 (b'r', b'rev', b'', _(b'revision to backout'), _(b'REV')),
704 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
706 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
705 ]
707 ]
706 + mergetoolopts
708 + mergetoolopts
707 + walkopts
709 + walkopts
708 + commitopts
710 + commitopts
709 + commitopts2,
711 + commitopts2,
710 _(b'[OPTION]... [-r] REV'),
712 _(b'[OPTION]... [-r] REV'),
711 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
713 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
712 )
714 )
713 def backout(ui, repo, node=None, rev=None, **opts):
715 def backout(ui, repo, node=None, rev=None, **opts):
714 '''reverse effect of earlier changeset
716 '''reverse effect of earlier changeset
715
717
716 Prepare a new changeset with the effect of REV undone in the
718 Prepare a new changeset with the effect of REV undone in the
717 current working directory. If no conflicts were encountered,
719 current working directory. If no conflicts were encountered,
718 it will be committed immediately.
720 it will be committed immediately.
719
721
720 If REV is the parent of the working directory, then this new changeset
722 If REV is the parent of the working directory, then this new changeset
721 is committed automatically (unless --no-commit is specified).
723 is committed automatically (unless --no-commit is specified).
722
724
723 .. note::
725 .. note::
724
726
725 :hg:`backout` cannot be used to fix either an unwanted or
727 :hg:`backout` cannot be used to fix either an unwanted or
726 incorrect merge.
728 incorrect merge.
727
729
728 .. container:: verbose
730 .. container:: verbose
729
731
730 Examples:
732 Examples:
731
733
732 - Reverse the effect of the parent of the working directory.
734 - Reverse the effect of the parent of the working directory.
733 This backout will be committed immediately::
735 This backout will be committed immediately::
734
736
735 hg backout -r .
737 hg backout -r .
736
738
737 - Reverse the effect of previous bad revision 23::
739 - Reverse the effect of previous bad revision 23::
738
740
739 hg backout -r 23
741 hg backout -r 23
740
742
741 - Reverse the effect of previous bad revision 23 and
743 - Reverse the effect of previous bad revision 23 and
742 leave changes uncommitted::
744 leave changes uncommitted::
743
745
744 hg backout -r 23 --no-commit
746 hg backout -r 23 --no-commit
745 hg commit -m "Backout revision 23"
747 hg commit -m "Backout revision 23"
746
748
747 By default, the pending changeset will have one parent,
749 By default, the pending changeset will have one parent,
748 maintaining a linear history. With --merge, the pending
750 maintaining a linear history. With --merge, the pending
749 changeset will instead have two parents: the old parent of the
751 changeset will instead have two parents: the old parent of the
750 working directory and a new child of REV that simply undoes REV.
752 working directory and a new child of REV that simply undoes REV.
751
753
752 Before version 1.7, the behavior without --merge was equivalent
754 Before version 1.7, the behavior without --merge was equivalent
753 to specifying --merge followed by :hg:`update --clean .` to
755 to specifying --merge followed by :hg:`update --clean .` to
754 cancel the merge and leave the child of REV as a head to be
756 cancel the merge and leave the child of REV as a head to be
755 merged separately.
757 merged separately.
756
758
757 See :hg:`help dates` for a list of formats valid for -d/--date.
759 See :hg:`help dates` for a list of formats valid for -d/--date.
758
760
759 See :hg:`help revert` for a way to restore files to the state
761 See :hg:`help revert` for a way to restore files to the state
760 of another revision.
762 of another revision.
761
763
762 Returns 0 on success, 1 if nothing to backout or there are unresolved
764 Returns 0 on success, 1 if nothing to backout or there are unresolved
763 files.
765 files.
764 '''
766 '''
765 with repo.wlock(), repo.lock():
767 with repo.wlock(), repo.lock():
766 return _dobackout(ui, repo, node, rev, **opts)
768 return _dobackout(ui, repo, node, rev, **opts)
767
769
768
770
769 def _dobackout(ui, repo, node=None, rev=None, **opts):
771 def _dobackout(ui, repo, node=None, rev=None, **opts):
770 opts = pycompat.byteskwargs(opts)
772 opts = pycompat.byteskwargs(opts)
771 if opts.get(b'commit') and opts.get(b'no_commit'):
773 if opts.get(b'commit') and opts.get(b'no_commit'):
772 raise error.Abort(_(b"cannot use --commit with --no-commit"))
774 raise error.Abort(_(b"cannot use --commit with --no-commit"))
773 if opts.get(b'merge') and opts.get(b'no_commit'):
775 if opts.get(b'merge') and opts.get(b'no_commit'):
774 raise error.Abort(_(b"cannot use --merge with --no-commit"))
776 raise error.Abort(_(b"cannot use --merge with --no-commit"))
775
777
776 if rev and node:
778 if rev and node:
777 raise error.Abort(_(b"please specify just one revision"))
779 raise error.Abort(_(b"please specify just one revision"))
778
780
779 if not rev:
781 if not rev:
780 rev = node
782 rev = node
781
783
782 if not rev:
784 if not rev:
783 raise error.Abort(_(b"please specify a revision to backout"))
785 raise error.Abort(_(b"please specify a revision to backout"))
784
786
785 date = opts.get(b'date')
787 date = opts.get(b'date')
786 if date:
788 if date:
787 opts[b'date'] = dateutil.parsedate(date)
789 opts[b'date'] = dateutil.parsedate(date)
788
790
789 cmdutil.checkunfinished(repo)
791 cmdutil.checkunfinished(repo)
790 cmdutil.bailifchanged(repo)
792 cmdutil.bailifchanged(repo)
791 node = scmutil.revsingle(repo, rev).node()
793 node = scmutil.revsingle(repo, rev).node()
792
794
793 op1, op2 = repo.dirstate.parents()
795 op1, op2 = repo.dirstate.parents()
794 if not repo.changelog.isancestor(node, op1):
796 if not repo.changelog.isancestor(node, op1):
795 raise error.Abort(_(b'cannot backout change that is not an ancestor'))
797 raise error.Abort(_(b'cannot backout change that is not an ancestor'))
796
798
797 p1, p2 = repo.changelog.parents(node)
799 p1, p2 = repo.changelog.parents(node)
798 if p1 == nullid:
800 if p1 == nullid:
799 raise error.Abort(_(b'cannot backout a change with no parents'))
801 raise error.Abort(_(b'cannot backout a change with no parents'))
800 if p2 != nullid:
802 if p2 != nullid:
801 if not opts.get(b'parent'):
803 if not opts.get(b'parent'):
802 raise error.Abort(_(b'cannot backout a merge changeset'))
804 raise error.Abort(_(b'cannot backout a merge changeset'))
803 p = repo.lookup(opts[b'parent'])
805 p = repo.lookup(opts[b'parent'])
804 if p not in (p1, p2):
806 if p not in (p1, p2):
805 raise error.Abort(
807 raise error.Abort(
806 _(b'%s is not a parent of %s') % (short(p), short(node))
808 _(b'%s is not a parent of %s') % (short(p), short(node))
807 )
809 )
808 parent = p
810 parent = p
809 else:
811 else:
810 if opts.get(b'parent'):
812 if opts.get(b'parent'):
811 raise error.Abort(_(b'cannot use --parent on non-merge changeset'))
813 raise error.Abort(_(b'cannot use --parent on non-merge changeset'))
812 parent = p1
814 parent = p1
813
815
814 # the backout should appear on the same branch
816 # the backout should appear on the same branch
815 branch = repo.dirstate.branch()
817 branch = repo.dirstate.branch()
816 bheads = repo.branchheads(branch)
818 bheads = repo.branchheads(branch)
817 rctx = scmutil.revsingle(repo, hex(parent))
819 rctx = scmutil.revsingle(repo, hex(parent))
818 if not opts.get(b'merge') and op1 != node:
820 if not opts.get(b'merge') and op1 != node:
819 with dirstateguard.dirstateguard(repo, b'backout'):
821 with dirstateguard.dirstateguard(repo, b'backout'):
820 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
822 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
821 with ui.configoverride(overrides, b'backout'):
823 with ui.configoverride(overrides, b'backout'):
822 stats = mergemod.update(
824 stats = mergemod.update(
823 repo,
825 repo,
824 parent,
826 parent,
825 branchmerge=True,
827 branchmerge=True,
826 force=True,
828 force=True,
827 ancestor=node,
829 ancestor=node,
828 mergeancestor=False,
830 mergeancestor=False,
829 )
831 )
830 repo.setparents(op1, op2)
832 repo.setparents(op1, op2)
831 hg._showstats(repo, stats)
833 hg._showstats(repo, stats)
832 if stats.unresolvedcount:
834 if stats.unresolvedcount:
833 repo.ui.status(
835 repo.ui.status(
834 _(b"use 'hg resolve' to retry unresolved file merges\n")
836 _(b"use 'hg resolve' to retry unresolved file merges\n")
835 )
837 )
836 return 1
838 return 1
837 else:
839 else:
838 hg.clean(repo, node, show_stats=False)
840 hg.clean(repo, node, show_stats=False)
839 repo.dirstate.setbranch(branch)
841 repo.dirstate.setbranch(branch)
840 cmdutil.revert(ui, repo, rctx)
842 cmdutil.revert(ui, repo, rctx)
841
843
842 if opts.get(b'no_commit'):
844 if opts.get(b'no_commit'):
843 msg = _(b"changeset %s backed out, don't forget to commit.\n")
845 msg = _(b"changeset %s backed out, don't forget to commit.\n")
844 ui.status(msg % short(node))
846 ui.status(msg % short(node))
845 return 0
847 return 0
846
848
847 def commitfunc(ui, repo, message, match, opts):
849 def commitfunc(ui, repo, message, match, opts):
848 editform = b'backout'
850 editform = b'backout'
849 e = cmdutil.getcommiteditor(
851 e = cmdutil.getcommiteditor(
850 editform=editform, **pycompat.strkwargs(opts)
852 editform=editform, **pycompat.strkwargs(opts)
851 )
853 )
852 if not message:
854 if not message:
853 # we don't translate commit messages
855 # we don't translate commit messages
854 message = b"Backed out changeset %s" % short(node)
856 message = b"Backed out changeset %s" % short(node)
855 e = cmdutil.getcommiteditor(edit=True, editform=editform)
857 e = cmdutil.getcommiteditor(edit=True, editform=editform)
856 return repo.commit(
858 return repo.commit(
857 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
859 message, opts.get(b'user'), opts.get(b'date'), match, editor=e
858 )
860 )
859
861
860 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
862 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
861 if not newnode:
863 if not newnode:
862 ui.status(_(b"nothing changed\n"))
864 ui.status(_(b"nothing changed\n"))
863 return 1
865 return 1
864 cmdutil.commitstatus(repo, newnode, branch, bheads)
866 cmdutil.commitstatus(repo, newnode, branch, bheads)
865
867
866 def nice(node):
868 def nice(node):
867 return b'%d:%s' % (repo.changelog.rev(node), short(node))
869 return b'%d:%s' % (repo.changelog.rev(node), short(node))
868
870
869 ui.status(
871 ui.status(
870 _(b'changeset %s backs out changeset %s\n')
872 _(b'changeset %s backs out changeset %s\n')
871 % (nice(repo.changelog.tip()), nice(node))
873 % (nice(repo.changelog.tip()), nice(node))
872 )
874 )
873 if opts.get(b'merge') and op1 != node:
875 if opts.get(b'merge') and op1 != node:
874 hg.clean(repo, op1, show_stats=False)
876 hg.clean(repo, op1, show_stats=False)
875 ui.status(
877 ui.status(
876 _(b'merging with changeset %s\n') % nice(repo.changelog.tip())
878 _(b'merging with changeset %s\n') % nice(repo.changelog.tip())
877 )
879 )
878 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
880 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
879 with ui.configoverride(overrides, b'backout'):
881 with ui.configoverride(overrides, b'backout'):
880 return hg.merge(repo[b'tip'])
882 return hg.merge(repo[b'tip'])
881 return 0
883 return 0
882
884
883
885
884 @command(
886 @command(
885 b'bisect',
887 b'bisect',
886 [
888 [
887 (b'r', b'reset', False, _(b'reset bisect state')),
889 (b'r', b'reset', False, _(b'reset bisect state')),
888 (b'g', b'good', False, _(b'mark changeset good')),
890 (b'g', b'good', False, _(b'mark changeset good')),
889 (b'b', b'bad', False, _(b'mark changeset bad')),
891 (b'b', b'bad', False, _(b'mark changeset bad')),
890 (b's', b'skip', False, _(b'skip testing changeset')),
892 (b's', b'skip', False, _(b'skip testing changeset')),
891 (b'e', b'extend', False, _(b'extend the bisect range')),
893 (b'e', b'extend', False, _(b'extend the bisect range')),
892 (
894 (
893 b'c',
895 b'c',
894 b'command',
896 b'command',
895 b'',
897 b'',
896 _(b'use command to check changeset state'),
898 _(b'use command to check changeset state'),
897 _(b'CMD'),
899 _(b'CMD'),
898 ),
900 ),
899 (b'U', b'noupdate', False, _(b'do not update to target')),
901 (b'U', b'noupdate', False, _(b'do not update to target')),
900 ],
902 ],
901 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
903 _(b"[-gbsr] [-U] [-c CMD] [REV]"),
902 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
904 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
903 )
905 )
904 def bisect(
906 def bisect(
905 ui,
907 ui,
906 repo,
908 repo,
907 rev=None,
909 rev=None,
908 extra=None,
910 extra=None,
909 command=None,
911 command=None,
910 reset=None,
912 reset=None,
911 good=None,
913 good=None,
912 bad=None,
914 bad=None,
913 skip=None,
915 skip=None,
914 extend=None,
916 extend=None,
915 noupdate=None,
917 noupdate=None,
916 ):
918 ):
917 """subdivision search of changesets
919 """subdivision search of changesets
918
920
919 This command helps to find changesets which introduce problems. To
921 This command helps to find changesets which introduce problems. To
920 use, mark the earliest changeset you know exhibits the problem as
922 use, mark the earliest changeset you know exhibits the problem as
921 bad, then mark the latest changeset which is free from the problem
923 bad, then mark the latest changeset which is free from the problem
922 as good. Bisect will update your working directory to a revision
924 as good. Bisect will update your working directory to a revision
923 for testing (unless the -U/--noupdate option is specified). Once
925 for testing (unless the -U/--noupdate option is specified). Once
924 you have performed tests, mark the working directory as good or
926 you have performed tests, mark the working directory as good or
925 bad, and bisect will either update to another candidate changeset
927 bad, and bisect will either update to another candidate changeset
926 or announce that it has found the bad revision.
928 or announce that it has found the bad revision.
927
929
928 As a shortcut, you can also use the revision argument to mark a
930 As a shortcut, you can also use the revision argument to mark a
929 revision as good or bad without checking it out first.
931 revision as good or bad without checking it out first.
930
932
931 If you supply a command, it will be used for automatic bisection.
933 If you supply a command, it will be used for automatic bisection.
932 The environment variable HG_NODE will contain the ID of the
934 The environment variable HG_NODE will contain the ID of the
933 changeset being tested. The exit status of the command will be
935 changeset being tested. The exit status of the command will be
934 used to mark revisions as good or bad: status 0 means good, 125
936 used to mark revisions as good or bad: status 0 means good, 125
935 means to skip the revision, 127 (command not found) will abort the
937 means to skip the revision, 127 (command not found) will abort the
936 bisection, and any other non-zero exit status means the revision
938 bisection, and any other non-zero exit status means the revision
937 is bad.
939 is bad.
938
940
939 .. container:: verbose
941 .. container:: verbose
940
942
941 Some examples:
943 Some examples:
942
944
943 - start a bisection with known bad revision 34, and good revision 12::
945 - start a bisection with known bad revision 34, and good revision 12::
944
946
945 hg bisect --bad 34
947 hg bisect --bad 34
946 hg bisect --good 12
948 hg bisect --good 12
947
949
948 - advance the current bisection by marking current revision as good or
950 - advance the current bisection by marking current revision as good or
949 bad::
951 bad::
950
952
951 hg bisect --good
953 hg bisect --good
952 hg bisect --bad
954 hg bisect --bad
953
955
954 - mark the current revision, or a known revision, to be skipped (e.g. if
956 - mark the current revision, or a known revision, to be skipped (e.g. if
955 that revision is not usable because of another issue)::
957 that revision is not usable because of another issue)::
956
958
957 hg bisect --skip
959 hg bisect --skip
958 hg bisect --skip 23
960 hg bisect --skip 23
959
961
960 - skip all revisions that do not touch directories ``foo`` or ``bar``::
962 - skip all revisions that do not touch directories ``foo`` or ``bar``::
961
963
962 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
964 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
963
965
964 - forget the current bisection::
966 - forget the current bisection::
965
967
966 hg bisect --reset
968 hg bisect --reset
967
969
968 - use 'make && make tests' to automatically find the first broken
970 - use 'make && make tests' to automatically find the first broken
969 revision::
971 revision::
970
972
971 hg bisect --reset
973 hg bisect --reset
972 hg bisect --bad 34
974 hg bisect --bad 34
973 hg bisect --good 12
975 hg bisect --good 12
974 hg bisect --command "make && make tests"
976 hg bisect --command "make && make tests"
975
977
976 - see all changesets whose states are already known in the current
978 - see all changesets whose states are already known in the current
977 bisection::
979 bisection::
978
980
979 hg log -r "bisect(pruned)"
981 hg log -r "bisect(pruned)"
980
982
981 - see the changeset currently being bisected (especially useful
983 - see the changeset currently being bisected (especially useful
982 if running with -U/--noupdate)::
984 if running with -U/--noupdate)::
983
985
984 hg log -r "bisect(current)"
986 hg log -r "bisect(current)"
985
987
986 - see all changesets that took part in the current bisection::
988 - see all changesets that took part in the current bisection::
987
989
988 hg log -r "bisect(range)"
990 hg log -r "bisect(range)"
989
991
990 - you can even get a nice graph::
992 - you can even get a nice graph::
991
993
992 hg log --graph -r "bisect(range)"
994 hg log --graph -r "bisect(range)"
993
995
994 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
996 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
995
997
996 Returns 0 on success.
998 Returns 0 on success.
997 """
999 """
998 # backward compatibility
1000 # backward compatibility
999 if rev in b"good bad reset init".split():
1001 if rev in b"good bad reset init".split():
1000 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1002 ui.warn(_(b"(use of 'hg bisect <cmd>' is deprecated)\n"))
1001 cmd, rev, extra = rev, extra, None
1003 cmd, rev, extra = rev, extra, None
1002 if cmd == b"good":
1004 if cmd == b"good":
1003 good = True
1005 good = True
1004 elif cmd == b"bad":
1006 elif cmd == b"bad":
1005 bad = True
1007 bad = True
1006 else:
1008 else:
1007 reset = True
1009 reset = True
1008 elif extra:
1010 elif extra:
1009 raise error.Abort(_(b'incompatible arguments'))
1011 raise error.Abort(_(b'incompatible arguments'))
1010
1012
1011 incompatibles = {
1013 incompatibles = {
1012 b'--bad': bad,
1014 b'--bad': bad,
1013 b'--command': bool(command),
1015 b'--command': bool(command),
1014 b'--extend': extend,
1016 b'--extend': extend,
1015 b'--good': good,
1017 b'--good': good,
1016 b'--reset': reset,
1018 b'--reset': reset,
1017 b'--skip': skip,
1019 b'--skip': skip,
1018 }
1020 }
1019
1021
1020 enabled = [x for x in incompatibles if incompatibles[x]]
1022 enabled = [x for x in incompatibles if incompatibles[x]]
1021
1023
1022 if len(enabled) > 1:
1024 if len(enabled) > 1:
1023 raise error.Abort(
1025 raise error.Abort(
1024 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1026 _(b'%s and %s are incompatible') % tuple(sorted(enabled)[0:2])
1025 )
1027 )
1026
1028
1027 if reset:
1029 if reset:
1028 hbisect.resetstate(repo)
1030 hbisect.resetstate(repo)
1029 return
1031 return
1030
1032
1031 state = hbisect.load_state(repo)
1033 state = hbisect.load_state(repo)
1032
1034
1033 # update state
1035 # update state
1034 if good or bad or skip:
1036 if good or bad or skip:
1035 if rev:
1037 if rev:
1036 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
1038 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
1037 else:
1039 else:
1038 nodes = [repo.lookup(b'.')]
1040 nodes = [repo.lookup(b'.')]
1039 if good:
1041 if good:
1040 state[b'good'] += nodes
1042 state[b'good'] += nodes
1041 elif bad:
1043 elif bad:
1042 state[b'bad'] += nodes
1044 state[b'bad'] += nodes
1043 elif skip:
1045 elif skip:
1044 state[b'skip'] += nodes
1046 state[b'skip'] += nodes
1045 hbisect.save_state(repo, state)
1047 hbisect.save_state(repo, state)
1046 if not (state[b'good'] and state[b'bad']):
1048 if not (state[b'good'] and state[b'bad']):
1047 return
1049 return
1048
1050
1049 def mayupdate(repo, node, show_stats=True):
1051 def mayupdate(repo, node, show_stats=True):
1050 """common used update sequence"""
1052 """common used update sequence"""
1051 if noupdate:
1053 if noupdate:
1052 return
1054 return
1053 cmdutil.checkunfinished(repo)
1055 cmdutil.checkunfinished(repo)
1054 cmdutil.bailifchanged(repo)
1056 cmdutil.bailifchanged(repo)
1055 return hg.clean(repo, node, show_stats=show_stats)
1057 return hg.clean(repo, node, show_stats=show_stats)
1056
1058
1057 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1059 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
1058
1060
1059 if command:
1061 if command:
1060 changesets = 1
1062 changesets = 1
1061 if noupdate:
1063 if noupdate:
1062 try:
1064 try:
1063 node = state[b'current'][0]
1065 node = state[b'current'][0]
1064 except LookupError:
1066 except LookupError:
1065 raise error.Abort(
1067 raise error.Abort(
1066 _(
1068 _(
1067 b'current bisect revision is unknown - '
1069 b'current bisect revision is unknown - '
1068 b'start a new bisect to fix'
1070 b'start a new bisect to fix'
1069 )
1071 )
1070 )
1072 )
1071 else:
1073 else:
1072 node, p2 = repo.dirstate.parents()
1074 node, p2 = repo.dirstate.parents()
1073 if p2 != nullid:
1075 if p2 != nullid:
1074 raise error.Abort(_(b'current bisect revision is a merge'))
1076 raise error.Abort(_(b'current bisect revision is a merge'))
1075 if rev:
1077 if rev:
1076 node = repo[scmutil.revsingle(repo, rev, node)].node()
1078 node = repo[scmutil.revsingle(repo, rev, node)].node()
1077 with hbisect.restore_state(repo, state, node):
1079 with hbisect.restore_state(repo, state, node):
1078 while changesets:
1080 while changesets:
1079 # update state
1081 # update state
1080 state[b'current'] = [node]
1082 state[b'current'] = [node]
1081 hbisect.save_state(repo, state)
1083 hbisect.save_state(repo, state)
1082 status = ui.system(
1084 status = ui.system(
1083 command,
1085 command,
1084 environ={b'HG_NODE': hex(node)},
1086 environ={b'HG_NODE': hex(node)},
1085 blockedtag=b'bisect_check',
1087 blockedtag=b'bisect_check',
1086 )
1088 )
1087 if status == 125:
1089 if status == 125:
1088 transition = b"skip"
1090 transition = b"skip"
1089 elif status == 0:
1091 elif status == 0:
1090 transition = b"good"
1092 transition = b"good"
1091 # status < 0 means process was killed
1093 # status < 0 means process was killed
1092 elif status == 127:
1094 elif status == 127:
1093 raise error.Abort(_(b"failed to execute %s") % command)
1095 raise error.Abort(_(b"failed to execute %s") % command)
1094 elif status < 0:
1096 elif status < 0:
1095 raise error.Abort(_(b"%s killed") % command)
1097 raise error.Abort(_(b"%s killed") % command)
1096 else:
1098 else:
1097 transition = b"bad"
1099 transition = b"bad"
1098 state[transition].append(node)
1100 state[transition].append(node)
1099 ctx = repo[node]
1101 ctx = repo[node]
1100 ui.status(
1102 ui.status(
1101 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1103 _(b'changeset %d:%s: %s\n') % (ctx.rev(), ctx, transition)
1102 )
1104 )
1103 hbisect.checkstate(state)
1105 hbisect.checkstate(state)
1104 # bisect
1106 # bisect
1105 nodes, changesets, bgood = hbisect.bisect(repo, state)
1107 nodes, changesets, bgood = hbisect.bisect(repo, state)
1106 # update to next check
1108 # update to next check
1107 node = nodes[0]
1109 node = nodes[0]
1108 mayupdate(repo, node, show_stats=False)
1110 mayupdate(repo, node, show_stats=False)
1109 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1111 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
1110 return
1112 return
1111
1113
1112 hbisect.checkstate(state)
1114 hbisect.checkstate(state)
1113
1115
1114 # actually bisect
1116 # actually bisect
1115 nodes, changesets, good = hbisect.bisect(repo, state)
1117 nodes, changesets, good = hbisect.bisect(repo, state)
1116 if extend:
1118 if extend:
1117 if not changesets:
1119 if not changesets:
1118 extendnode = hbisect.extendrange(repo, state, nodes, good)
1120 extendnode = hbisect.extendrange(repo, state, nodes, good)
1119 if extendnode is not None:
1121 if extendnode is not None:
1120 ui.write(
1122 ui.write(
1121 _(b"Extending search to changeset %d:%s\n")
1123 _(b"Extending search to changeset %d:%s\n")
1122 % (extendnode.rev(), extendnode)
1124 % (extendnode.rev(), extendnode)
1123 )
1125 )
1124 state[b'current'] = [extendnode.node()]
1126 state[b'current'] = [extendnode.node()]
1125 hbisect.save_state(repo, state)
1127 hbisect.save_state(repo, state)
1126 return mayupdate(repo, extendnode.node())
1128 return mayupdate(repo, extendnode.node())
1127 raise error.Abort(_(b"nothing to extend"))
1129 raise error.Abort(_(b"nothing to extend"))
1128
1130
1129 if changesets == 0:
1131 if changesets == 0:
1130 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1132 hbisect.printresult(ui, repo, state, displayer, nodes, good)
1131 else:
1133 else:
1132 assert len(nodes) == 1 # only a single node can be tested next
1134 assert len(nodes) == 1 # only a single node can be tested next
1133 node = nodes[0]
1135 node = nodes[0]
1134 # compute the approximate number of remaining tests
1136 # compute the approximate number of remaining tests
1135 tests, size = 0, 2
1137 tests, size = 0, 2
1136 while size <= changesets:
1138 while size <= changesets:
1137 tests, size = tests + 1, size * 2
1139 tests, size = tests + 1, size * 2
1138 rev = repo.changelog.rev(node)
1140 rev = repo.changelog.rev(node)
1139 ui.write(
1141 ui.write(
1140 _(
1142 _(
1141 b"Testing changeset %d:%s "
1143 b"Testing changeset %d:%s "
1142 b"(%d changesets remaining, ~%d tests)\n"
1144 b"(%d changesets remaining, ~%d tests)\n"
1143 )
1145 )
1144 % (rev, short(node), changesets, tests)
1146 % (rev, short(node), changesets, tests)
1145 )
1147 )
1146 state[b'current'] = [node]
1148 state[b'current'] = [node]
1147 hbisect.save_state(repo, state)
1149 hbisect.save_state(repo, state)
1148 return mayupdate(repo, node)
1150 return mayupdate(repo, node)
1149
1151
1150
1152
1151 @command(
1153 @command(
1152 b'bookmarks|bookmark',
1154 b'bookmarks|bookmark',
1153 [
1155 [
1154 (b'f', b'force', False, _(b'force')),
1156 (b'f', b'force', False, _(b'force')),
1155 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1157 (b'r', b'rev', b'', _(b'revision for bookmark action'), _(b'REV')),
1156 (b'd', b'delete', False, _(b'delete a given bookmark')),
1158 (b'd', b'delete', False, _(b'delete a given bookmark')),
1157 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1159 (b'm', b'rename', b'', _(b'rename a given bookmark'), _(b'OLD')),
1158 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1160 (b'i', b'inactive', False, _(b'mark a bookmark inactive')),
1159 (b'l', b'list', False, _(b'list existing bookmarks')),
1161 (b'l', b'list', False, _(b'list existing bookmarks')),
1160 ]
1162 ]
1161 + formatteropts,
1163 + formatteropts,
1162 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1164 _(b'hg bookmarks [OPTIONS]... [NAME]...'),
1163 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1165 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1164 )
1166 )
1165 def bookmark(ui, repo, *names, **opts):
1167 def bookmark(ui, repo, *names, **opts):
1166 '''create a new bookmark or list existing bookmarks
1168 '''create a new bookmark or list existing bookmarks
1167
1169
1168 Bookmarks are labels on changesets to help track lines of development.
1170 Bookmarks are labels on changesets to help track lines of development.
1169 Bookmarks are unversioned and can be moved, renamed and deleted.
1171 Bookmarks are unversioned and can be moved, renamed and deleted.
1170 Deleting or moving a bookmark has no effect on the associated changesets.
1172 Deleting or moving a bookmark has no effect on the associated changesets.
1171
1173
1172 Creating or updating to a bookmark causes it to be marked as 'active'.
1174 Creating or updating to a bookmark causes it to be marked as 'active'.
1173 The active bookmark is indicated with a '*'.
1175 The active bookmark is indicated with a '*'.
1174 When a commit is made, the active bookmark will advance to the new commit.
1176 When a commit is made, the active bookmark will advance to the new commit.
1175 A plain :hg:`update` will also advance an active bookmark, if possible.
1177 A plain :hg:`update` will also advance an active bookmark, if possible.
1176 Updating away from a bookmark will cause it to be deactivated.
1178 Updating away from a bookmark will cause it to be deactivated.
1177
1179
1178 Bookmarks can be pushed and pulled between repositories (see
1180 Bookmarks can be pushed and pulled between repositories (see
1179 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1181 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
1180 diverged, a new 'divergent bookmark' of the form 'name@path' will
1182 diverged, a new 'divergent bookmark' of the form 'name@path' will
1181 be created. Using :hg:`merge` will resolve the divergence.
1183 be created. Using :hg:`merge` will resolve the divergence.
1182
1184
1183 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1185 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
1184 the active bookmark's name.
1186 the active bookmark's name.
1185
1187
1186 A bookmark named '@' has the special property that :hg:`clone` will
1188 A bookmark named '@' has the special property that :hg:`clone` will
1187 check it out by default if it exists.
1189 check it out by default if it exists.
1188
1190
1189 .. container:: verbose
1191 .. container:: verbose
1190
1192
1191 Template:
1193 Template:
1192
1194
1193 The following keywords are supported in addition to the common template
1195 The following keywords are supported in addition to the common template
1194 keywords and functions such as ``{bookmark}``. See also
1196 keywords and functions such as ``{bookmark}``. See also
1195 :hg:`help templates`.
1197 :hg:`help templates`.
1196
1198
1197 :active: Boolean. True if the bookmark is active.
1199 :active: Boolean. True if the bookmark is active.
1198
1200
1199 Examples:
1201 Examples:
1200
1202
1201 - create an active bookmark for a new line of development::
1203 - create an active bookmark for a new line of development::
1202
1204
1203 hg book new-feature
1205 hg book new-feature
1204
1206
1205 - create an inactive bookmark as a place marker::
1207 - create an inactive bookmark as a place marker::
1206
1208
1207 hg book -i reviewed
1209 hg book -i reviewed
1208
1210
1209 - create an inactive bookmark on another changeset::
1211 - create an inactive bookmark on another changeset::
1210
1212
1211 hg book -r .^ tested
1213 hg book -r .^ tested
1212
1214
1213 - rename bookmark turkey to dinner::
1215 - rename bookmark turkey to dinner::
1214
1216
1215 hg book -m turkey dinner
1217 hg book -m turkey dinner
1216
1218
1217 - move the '@' bookmark from another branch::
1219 - move the '@' bookmark from another branch::
1218
1220
1219 hg book -f @
1221 hg book -f @
1220
1222
1221 - print only the active bookmark name::
1223 - print only the active bookmark name::
1222
1224
1223 hg book -ql .
1225 hg book -ql .
1224 '''
1226 '''
1225 opts = pycompat.byteskwargs(opts)
1227 opts = pycompat.byteskwargs(opts)
1226 force = opts.get(b'force')
1228 force = opts.get(b'force')
1227 rev = opts.get(b'rev')
1229 rev = opts.get(b'rev')
1228 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1230 inactive = opts.get(b'inactive') # meaning add/rename to inactive bookmark
1229
1231
1230 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1232 action = cmdutil.check_at_most_one_arg(opts, b'delete', b'rename', b'list')
1231 if action:
1233 if action:
1232 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1234 cmdutil.check_incompatible_arguments(opts, action, [b'rev'])
1233 elif names or rev:
1235 elif names or rev:
1234 action = b'add'
1236 action = b'add'
1235 elif inactive:
1237 elif inactive:
1236 action = b'inactive' # meaning deactivate
1238 action = b'inactive' # meaning deactivate
1237 else:
1239 else:
1238 action = b'list'
1240 action = b'list'
1239
1241
1240 cmdutil.check_incompatible_arguments(
1242 cmdutil.check_incompatible_arguments(
1241 opts, b'inactive', [b'delete', b'list']
1243 opts, b'inactive', [b'delete', b'list']
1242 )
1244 )
1243 if not names and action in {b'add', b'delete'}:
1245 if not names and action in {b'add', b'delete'}:
1244 raise error.Abort(_(b"bookmark name required"))
1246 raise error.Abort(_(b"bookmark name required"))
1245
1247
1246 if action in {b'add', b'delete', b'rename', b'inactive'}:
1248 if action in {b'add', b'delete', b'rename', b'inactive'}:
1247 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1249 with repo.wlock(), repo.lock(), repo.transaction(b'bookmark') as tr:
1248 if action == b'delete':
1250 if action == b'delete':
1249 names = pycompat.maplist(repo._bookmarks.expandname, names)
1251 names = pycompat.maplist(repo._bookmarks.expandname, names)
1250 bookmarks.delete(repo, tr, names)
1252 bookmarks.delete(repo, tr, names)
1251 elif action == b'rename':
1253 elif action == b'rename':
1252 if not names:
1254 if not names:
1253 raise error.Abort(_(b"new bookmark name required"))
1255 raise error.Abort(_(b"new bookmark name required"))
1254 elif len(names) > 1:
1256 elif len(names) > 1:
1255 raise error.Abort(_(b"only one new bookmark name allowed"))
1257 raise error.Abort(_(b"only one new bookmark name allowed"))
1256 oldname = repo._bookmarks.expandname(opts[b'rename'])
1258 oldname = repo._bookmarks.expandname(opts[b'rename'])
1257 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1259 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1258 elif action == b'add':
1260 elif action == b'add':
1259 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1261 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1260 elif action == b'inactive':
1262 elif action == b'inactive':
1261 if len(repo._bookmarks) == 0:
1263 if len(repo._bookmarks) == 0:
1262 ui.status(_(b"no bookmarks set\n"))
1264 ui.status(_(b"no bookmarks set\n"))
1263 elif not repo._activebookmark:
1265 elif not repo._activebookmark:
1264 ui.status(_(b"no active bookmark\n"))
1266 ui.status(_(b"no active bookmark\n"))
1265 else:
1267 else:
1266 bookmarks.deactivate(repo)
1268 bookmarks.deactivate(repo)
1267 elif action == b'list':
1269 elif action == b'list':
1268 names = pycompat.maplist(repo._bookmarks.expandname, names)
1270 names = pycompat.maplist(repo._bookmarks.expandname, names)
1269 with ui.formatter(b'bookmarks', opts) as fm:
1271 with ui.formatter(b'bookmarks', opts) as fm:
1270 bookmarks.printbookmarks(ui, repo, fm, names)
1272 bookmarks.printbookmarks(ui, repo, fm, names)
1271 else:
1273 else:
1272 raise error.ProgrammingError(b'invalid action: %s' % action)
1274 raise error.ProgrammingError(b'invalid action: %s' % action)
1273
1275
1274
1276
1275 @command(
1277 @command(
1276 b'branch',
1278 b'branch',
1277 [
1279 [
1278 (
1280 (
1279 b'f',
1281 b'f',
1280 b'force',
1282 b'force',
1281 None,
1283 None,
1282 _(b'set branch name even if it shadows an existing branch'),
1284 _(b'set branch name even if it shadows an existing branch'),
1283 ),
1285 ),
1284 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1286 (b'C', b'clean', None, _(b'reset branch name to parent branch name')),
1285 (
1287 (
1286 b'r',
1288 b'r',
1287 b'rev',
1289 b'rev',
1288 [],
1290 [],
1289 _(b'change branches of the given revs (EXPERIMENTAL)'),
1291 _(b'change branches of the given revs (EXPERIMENTAL)'),
1290 ),
1292 ),
1291 ],
1293 ],
1292 _(b'[-fC] [NAME]'),
1294 _(b'[-fC] [NAME]'),
1293 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1295 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1294 )
1296 )
1295 def branch(ui, repo, label=None, **opts):
1297 def branch(ui, repo, label=None, **opts):
1296 """set or show the current branch name
1298 """set or show the current branch name
1297
1299
1298 .. note::
1300 .. note::
1299
1301
1300 Branch names are permanent and global. Use :hg:`bookmark` to create a
1302 Branch names are permanent and global. Use :hg:`bookmark` to create a
1301 light-weight bookmark instead. See :hg:`help glossary` for more
1303 light-weight bookmark instead. See :hg:`help glossary` for more
1302 information about named branches and bookmarks.
1304 information about named branches and bookmarks.
1303
1305
1304 With no argument, show the current branch name. With one argument,
1306 With no argument, show the current branch name. With one argument,
1305 set the working directory branch name (the branch will not exist
1307 set the working directory branch name (the branch will not exist
1306 in the repository until the next commit). Standard practice
1308 in the repository until the next commit). Standard practice
1307 recommends that primary development take place on the 'default'
1309 recommends that primary development take place on the 'default'
1308 branch.
1310 branch.
1309
1311
1310 Unless -f/--force is specified, branch will not let you set a
1312 Unless -f/--force is specified, branch will not let you set a
1311 branch name that already exists.
1313 branch name that already exists.
1312
1314
1313 Use -C/--clean to reset the working directory branch to that of
1315 Use -C/--clean to reset the working directory branch to that of
1314 the parent of the working directory, negating a previous branch
1316 the parent of the working directory, negating a previous branch
1315 change.
1317 change.
1316
1318
1317 Use the command :hg:`update` to switch to an existing branch. Use
1319 Use the command :hg:`update` to switch to an existing branch. Use
1318 :hg:`commit --close-branch` to mark this branch head as closed.
1320 :hg:`commit --close-branch` to mark this branch head as closed.
1319 When all heads of a branch are closed, the branch will be
1321 When all heads of a branch are closed, the branch will be
1320 considered closed.
1322 considered closed.
1321
1323
1322 Returns 0 on success.
1324 Returns 0 on success.
1323 """
1325 """
1324 opts = pycompat.byteskwargs(opts)
1326 opts = pycompat.byteskwargs(opts)
1325 revs = opts.get(b'rev')
1327 revs = opts.get(b'rev')
1326 if label:
1328 if label:
1327 label = label.strip()
1329 label = label.strip()
1328
1330
1329 if not opts.get(b'clean') and not label:
1331 if not opts.get(b'clean') and not label:
1330 if revs:
1332 if revs:
1331 raise error.Abort(_(b"no branch name specified for the revisions"))
1333 raise error.Abort(_(b"no branch name specified for the revisions"))
1332 ui.write(b"%s\n" % repo.dirstate.branch())
1334 ui.write(b"%s\n" % repo.dirstate.branch())
1333 return
1335 return
1334
1336
1335 with repo.wlock():
1337 with repo.wlock():
1336 if opts.get(b'clean'):
1338 if opts.get(b'clean'):
1337 label = repo[b'.'].branch()
1339 label = repo[b'.'].branch()
1338 repo.dirstate.setbranch(label)
1340 repo.dirstate.setbranch(label)
1339 ui.status(_(b'reset working directory to branch %s\n') % label)
1341 ui.status(_(b'reset working directory to branch %s\n') % label)
1340 elif label:
1342 elif label:
1341
1343
1342 scmutil.checknewlabel(repo, label, b'branch')
1344 scmutil.checknewlabel(repo, label, b'branch')
1343 if revs:
1345 if revs:
1344 return cmdutil.changebranch(ui, repo, revs, label, opts)
1346 return cmdutil.changebranch(ui, repo, revs, label, opts)
1345
1347
1346 if not opts.get(b'force') and label in repo.branchmap():
1348 if not opts.get(b'force') and label in repo.branchmap():
1347 if label not in [p.branch() for p in repo[None].parents()]:
1349 if label not in [p.branch() for p in repo[None].parents()]:
1348 raise error.Abort(
1350 raise error.Abort(
1349 _(b'a branch of the same name already exists'),
1351 _(b'a branch of the same name already exists'),
1350 # i18n: "it" refers to an existing branch
1352 # i18n: "it" refers to an existing branch
1351 hint=_(b"use 'hg update' to switch to it"),
1353 hint=_(b"use 'hg update' to switch to it"),
1352 )
1354 )
1353
1355
1354 repo.dirstate.setbranch(label)
1356 repo.dirstate.setbranch(label)
1355 ui.status(_(b'marked working directory as branch %s\n') % label)
1357 ui.status(_(b'marked working directory as branch %s\n') % label)
1356
1358
1357 # find any open named branches aside from default
1359 # find any open named branches aside from default
1358 for n, h, t, c in repo.branchmap().iterbranches():
1360 for n, h, t, c in repo.branchmap().iterbranches():
1359 if n != b"default" and not c:
1361 if n != b"default" and not c:
1360 return 0
1362 return 0
1361 ui.status(
1363 ui.status(
1362 _(
1364 _(
1363 b'(branches are permanent and global, '
1365 b'(branches are permanent and global, '
1364 b'did you want a bookmark?)\n'
1366 b'did you want a bookmark?)\n'
1365 )
1367 )
1366 )
1368 )
1367
1369
1368
1370
1369 @command(
1371 @command(
1370 b'branches',
1372 b'branches',
1371 [
1373 [
1372 (
1374 (
1373 b'a',
1375 b'a',
1374 b'active',
1376 b'active',
1375 False,
1377 False,
1376 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1378 _(b'show only branches that have unmerged heads (DEPRECATED)'),
1377 ),
1379 ),
1378 (b'c', b'closed', False, _(b'show normal and closed branches')),
1380 (b'c', b'closed', False, _(b'show normal and closed branches')),
1379 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1381 (b'r', b'rev', [], _(b'show branch name(s) of the given rev')),
1380 ]
1382 ]
1381 + formatteropts,
1383 + formatteropts,
1382 _(b'[-c]'),
1384 _(b'[-c]'),
1383 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1385 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1384 intents={INTENT_READONLY},
1386 intents={INTENT_READONLY},
1385 )
1387 )
1386 def branches(ui, repo, active=False, closed=False, **opts):
1388 def branches(ui, repo, active=False, closed=False, **opts):
1387 """list repository named branches
1389 """list repository named branches
1388
1390
1389 List the repository's named branches, indicating which ones are
1391 List the repository's named branches, indicating which ones are
1390 inactive. If -c/--closed is specified, also list branches which have
1392 inactive. If -c/--closed is specified, also list branches which have
1391 been marked closed (see :hg:`commit --close-branch`).
1393 been marked closed (see :hg:`commit --close-branch`).
1392
1394
1393 Use the command :hg:`update` to switch to an existing branch.
1395 Use the command :hg:`update` to switch to an existing branch.
1394
1396
1395 .. container:: verbose
1397 .. container:: verbose
1396
1398
1397 Template:
1399 Template:
1398
1400
1399 The following keywords are supported in addition to the common template
1401 The following keywords are supported in addition to the common template
1400 keywords and functions such as ``{branch}``. See also
1402 keywords and functions such as ``{branch}``. See also
1401 :hg:`help templates`.
1403 :hg:`help templates`.
1402
1404
1403 :active: Boolean. True if the branch is active.
1405 :active: Boolean. True if the branch is active.
1404 :closed: Boolean. True if the branch is closed.
1406 :closed: Boolean. True if the branch is closed.
1405 :current: Boolean. True if it is the current branch.
1407 :current: Boolean. True if it is the current branch.
1406
1408
1407 Returns 0.
1409 Returns 0.
1408 """
1410 """
1409
1411
1410 opts = pycompat.byteskwargs(opts)
1412 opts = pycompat.byteskwargs(opts)
1411 revs = opts.get(b'rev')
1413 revs = opts.get(b'rev')
1412 selectedbranches = None
1414 selectedbranches = None
1413 if revs:
1415 if revs:
1414 revs = scmutil.revrange(repo, revs)
1416 revs = scmutil.revrange(repo, revs)
1415 getbi = repo.revbranchcache().branchinfo
1417 getbi = repo.revbranchcache().branchinfo
1416 selectedbranches = {getbi(r)[0] for r in revs}
1418 selectedbranches = {getbi(r)[0] for r in revs}
1417
1419
1418 ui.pager(b'branches')
1420 ui.pager(b'branches')
1419 fm = ui.formatter(b'branches', opts)
1421 fm = ui.formatter(b'branches', opts)
1420 hexfunc = fm.hexfunc
1422 hexfunc = fm.hexfunc
1421
1423
1422 allheads = set(repo.heads())
1424 allheads = set(repo.heads())
1423 branches = []
1425 branches = []
1424 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1426 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1425 if selectedbranches is not None and tag not in selectedbranches:
1427 if selectedbranches is not None and tag not in selectedbranches:
1426 continue
1428 continue
1427 isactive = False
1429 isactive = False
1428 if not isclosed:
1430 if not isclosed:
1429 openheads = set(repo.branchmap().iteropen(heads))
1431 openheads = set(repo.branchmap().iteropen(heads))
1430 isactive = bool(openheads & allheads)
1432 isactive = bool(openheads & allheads)
1431 branches.append((tag, repo[tip], isactive, not isclosed))
1433 branches.append((tag, repo[tip], isactive, not isclosed))
1432 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1434 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]), reverse=True)
1433
1435
1434 for tag, ctx, isactive, isopen in branches:
1436 for tag, ctx, isactive, isopen in branches:
1435 if active and not isactive:
1437 if active and not isactive:
1436 continue
1438 continue
1437 if isactive:
1439 if isactive:
1438 label = b'branches.active'
1440 label = b'branches.active'
1439 notice = b''
1441 notice = b''
1440 elif not isopen:
1442 elif not isopen:
1441 if not closed:
1443 if not closed:
1442 continue
1444 continue
1443 label = b'branches.closed'
1445 label = b'branches.closed'
1444 notice = _(b' (closed)')
1446 notice = _(b' (closed)')
1445 else:
1447 else:
1446 label = b'branches.inactive'
1448 label = b'branches.inactive'
1447 notice = _(b' (inactive)')
1449 notice = _(b' (inactive)')
1448 current = tag == repo.dirstate.branch()
1450 current = tag == repo.dirstate.branch()
1449 if current:
1451 if current:
1450 label = b'branches.current'
1452 label = b'branches.current'
1451
1453
1452 fm.startitem()
1454 fm.startitem()
1453 fm.write(b'branch', b'%s', tag, label=label)
1455 fm.write(b'branch', b'%s', tag, label=label)
1454 rev = ctx.rev()
1456 rev = ctx.rev()
1455 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1457 padsize = max(31 - len(b"%d" % rev) - encoding.colwidth(tag), 0)
1456 fmt = b' ' * padsize + b' %d:%s'
1458 fmt = b' ' * padsize + b' %d:%s'
1457 fm.condwrite(
1459 fm.condwrite(
1458 not ui.quiet,
1460 not ui.quiet,
1459 b'rev node',
1461 b'rev node',
1460 fmt,
1462 fmt,
1461 rev,
1463 rev,
1462 hexfunc(ctx.node()),
1464 hexfunc(ctx.node()),
1463 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1465 label=b'log.changeset changeset.%s' % ctx.phasestr(),
1464 )
1466 )
1465 fm.context(ctx=ctx)
1467 fm.context(ctx=ctx)
1466 fm.data(active=isactive, closed=not isopen, current=current)
1468 fm.data(active=isactive, closed=not isopen, current=current)
1467 if not ui.quiet:
1469 if not ui.quiet:
1468 fm.plain(notice)
1470 fm.plain(notice)
1469 fm.plain(b'\n')
1471 fm.plain(b'\n')
1470 fm.end()
1472 fm.end()
1471
1473
1472
1474
1473 @command(
1475 @command(
1474 b'bundle',
1476 b'bundle',
1475 [
1477 [
1476 (
1478 (
1477 b'f',
1479 b'f',
1478 b'force',
1480 b'force',
1479 None,
1481 None,
1480 _(b'run even when the destination is unrelated'),
1482 _(b'run even when the destination is unrelated'),
1481 ),
1483 ),
1482 (
1484 (
1483 b'r',
1485 b'r',
1484 b'rev',
1486 b'rev',
1485 [],
1487 [],
1486 _(b'a changeset intended to be added to the destination'),
1488 _(b'a changeset intended to be added to the destination'),
1487 _(b'REV'),
1489 _(b'REV'),
1488 ),
1490 ),
1489 (
1491 (
1490 b'b',
1492 b'b',
1491 b'branch',
1493 b'branch',
1492 [],
1494 [],
1493 _(b'a specific branch you would like to bundle'),
1495 _(b'a specific branch you would like to bundle'),
1494 _(b'BRANCH'),
1496 _(b'BRANCH'),
1495 ),
1497 ),
1496 (
1498 (
1497 b'',
1499 b'',
1498 b'base',
1500 b'base',
1499 [],
1501 [],
1500 _(b'a base changeset assumed to be available at the destination'),
1502 _(b'a base changeset assumed to be available at the destination'),
1501 _(b'REV'),
1503 _(b'REV'),
1502 ),
1504 ),
1503 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1505 (b'a', b'all', None, _(b'bundle all changesets in the repository')),
1504 (
1506 (
1505 b't',
1507 b't',
1506 b'type',
1508 b'type',
1507 b'bzip2',
1509 b'bzip2',
1508 _(b'bundle compression type to use'),
1510 _(b'bundle compression type to use'),
1509 _(b'TYPE'),
1511 _(b'TYPE'),
1510 ),
1512 ),
1511 ]
1513 ]
1512 + remoteopts,
1514 + remoteopts,
1513 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1515 _(b'[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1514 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1516 helpcategory=command.CATEGORY_IMPORT_EXPORT,
1515 )
1517 )
1516 def bundle(ui, repo, fname, dest=None, **opts):
1518 def bundle(ui, repo, fname, dest=None, **opts):
1517 """create a bundle file
1519 """create a bundle file
1518
1520
1519 Generate a bundle file containing data to be transferred to another
1521 Generate a bundle file containing data to be transferred to another
1520 repository.
1522 repository.
1521
1523
1522 To create a bundle containing all changesets, use -a/--all
1524 To create a bundle containing all changesets, use -a/--all
1523 (or --base null). Otherwise, hg assumes the destination will have
1525 (or --base null). Otherwise, hg assumes the destination will have
1524 all the nodes you specify with --base parameters. Otherwise, hg
1526 all the nodes you specify with --base parameters. Otherwise, hg
1525 will assume the repository has all the nodes in destination, or
1527 will assume the repository has all the nodes in destination, or
1526 default-push/default if no destination is specified, where destination
1528 default-push/default if no destination is specified, where destination
1527 is the repository you provide through DEST option.
1529 is the repository you provide through DEST option.
1528
1530
1529 You can change bundle format with the -t/--type option. See
1531 You can change bundle format with the -t/--type option. See
1530 :hg:`help bundlespec` for documentation on this format. By default,
1532 :hg:`help bundlespec` for documentation on this format. By default,
1531 the most appropriate format is used and compression defaults to
1533 the most appropriate format is used and compression defaults to
1532 bzip2.
1534 bzip2.
1533
1535
1534 The bundle file can then be transferred using conventional means
1536 The bundle file can then be transferred using conventional means
1535 and applied to another repository with the unbundle or pull
1537 and applied to another repository with the unbundle or pull
1536 command. This is useful when direct push and pull are not
1538 command. This is useful when direct push and pull are not
1537 available or when exporting an entire repository is undesirable.
1539 available or when exporting an entire repository is undesirable.
1538
1540
1539 Applying bundles preserves all changeset contents including
1541 Applying bundles preserves all changeset contents including
1540 permissions, copy/rename information, and revision history.
1542 permissions, copy/rename information, and revision history.
1541
1543
1542 Returns 0 on success, 1 if no changes found.
1544 Returns 0 on success, 1 if no changes found.
1543 """
1545 """
1544 opts = pycompat.byteskwargs(opts)
1546 opts = pycompat.byteskwargs(opts)
1545 revs = None
1547 revs = None
1546 if b'rev' in opts:
1548 if b'rev' in opts:
1547 revstrings = opts[b'rev']
1549 revstrings = opts[b'rev']
1548 revs = scmutil.revrange(repo, revstrings)
1550 revs = scmutil.revrange(repo, revstrings)
1549 if revstrings and not revs:
1551 if revstrings and not revs:
1550 raise error.Abort(_(b'no commits to bundle'))
1552 raise error.Abort(_(b'no commits to bundle'))
1551
1553
1552 bundletype = opts.get(b'type', b'bzip2').lower()
1554 bundletype = opts.get(b'type', b'bzip2').lower()
1553 try:
1555 try:
1554 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1556 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1555 except error.UnsupportedBundleSpecification as e:
1557 except error.UnsupportedBundleSpecification as e:
1556 raise error.Abort(
1558 raise error.Abort(
1557 pycompat.bytestr(e),
1559 pycompat.bytestr(e),
1558 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1560 hint=_(b"see 'hg help bundlespec' for supported values for --type"),
1559 )
1561 )
1560 cgversion = bundlespec.contentopts[b"cg.version"]
1562 cgversion = bundlespec.contentopts[b"cg.version"]
1561
1563
1562 # Packed bundles are a pseudo bundle format for now.
1564 # Packed bundles are a pseudo bundle format for now.
1563 if cgversion == b's1':
1565 if cgversion == b's1':
1564 raise error.Abort(
1566 raise error.Abort(
1565 _(b'packed bundles cannot be produced by "hg bundle"'),
1567 _(b'packed bundles cannot be produced by "hg bundle"'),
1566 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1568 hint=_(b"use 'hg debugcreatestreamclonebundle'"),
1567 )
1569 )
1568
1570
1569 if opts.get(b'all'):
1571 if opts.get(b'all'):
1570 if dest:
1572 if dest:
1571 raise error.Abort(
1573 raise error.Abort(
1572 _(b"--all is incompatible with specifying a destination")
1574 _(b"--all is incompatible with specifying a destination")
1573 )
1575 )
1574 if opts.get(b'base'):
1576 if opts.get(b'base'):
1575 ui.warn(_(b"ignoring --base because --all was specified\n"))
1577 ui.warn(_(b"ignoring --base because --all was specified\n"))
1576 base = [nullrev]
1578 base = [nullrev]
1577 else:
1579 else:
1578 base = scmutil.revrange(repo, opts.get(b'base'))
1580 base = scmutil.revrange(repo, opts.get(b'base'))
1579 if cgversion not in changegroup.supportedoutgoingversions(repo):
1581 if cgversion not in changegroup.supportedoutgoingversions(repo):
1580 raise error.Abort(
1582 raise error.Abort(
1581 _(b"repository does not support bundle version %s") % cgversion
1583 _(b"repository does not support bundle version %s") % cgversion
1582 )
1584 )
1583
1585
1584 if base:
1586 if base:
1585 if dest:
1587 if dest:
1586 raise error.Abort(
1588 raise error.Abort(
1587 _(b"--base is incompatible with specifying a destination")
1589 _(b"--base is incompatible with specifying a destination")
1588 )
1590 )
1589 common = [repo[rev].node() for rev in base]
1591 common = [repo[rev].node() for rev in base]
1590 heads = [repo[r].node() for r in revs] if revs else None
1592 heads = [repo[r].node() for r in revs] if revs else None
1591 outgoing = discovery.outgoing(repo, common, heads)
1593 outgoing = discovery.outgoing(repo, common, heads)
1592 else:
1594 else:
1593 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1595 dest = ui.expandpath(dest or b'default-push', dest or b'default')
1594 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1596 dest, branches = hg.parseurl(dest, opts.get(b'branch'))
1595 other = hg.peer(repo, opts, dest)
1597 other = hg.peer(repo, opts, dest)
1596 revs = [repo[r].hex() for r in revs]
1598 revs = [repo[r].hex() for r in revs]
1597 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1599 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1598 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1600 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1599 outgoing = discovery.findcommonoutgoing(
1601 outgoing = discovery.findcommonoutgoing(
1600 repo,
1602 repo,
1601 other,
1603 other,
1602 onlyheads=heads,
1604 onlyheads=heads,
1603 force=opts.get(b'force'),
1605 force=opts.get(b'force'),
1604 portable=True,
1606 portable=True,
1605 )
1607 )
1606
1608
1607 if not outgoing.missing:
1609 if not outgoing.missing:
1608 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1610 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1609 return 1
1611 return 1
1610
1612
1611 if cgversion == b'01': # bundle1
1613 if cgversion == b'01': # bundle1
1612 bversion = b'HG10' + bundlespec.wirecompression
1614 bversion = b'HG10' + bundlespec.wirecompression
1613 bcompression = None
1615 bcompression = None
1614 elif cgversion in (b'02', b'03'):
1616 elif cgversion in (b'02', b'03'):
1615 bversion = b'HG20'
1617 bversion = b'HG20'
1616 bcompression = bundlespec.wirecompression
1618 bcompression = bundlespec.wirecompression
1617 else:
1619 else:
1618 raise error.ProgrammingError(
1620 raise error.ProgrammingError(
1619 b'bundle: unexpected changegroup version %s' % cgversion
1621 b'bundle: unexpected changegroup version %s' % cgversion
1620 )
1622 )
1621
1623
1622 # TODO compression options should be derived from bundlespec parsing.
1624 # TODO compression options should be derived from bundlespec parsing.
1623 # This is a temporary hack to allow adjusting bundle compression
1625 # This is a temporary hack to allow adjusting bundle compression
1624 # level without a) formalizing the bundlespec changes to declare it
1626 # level without a) formalizing the bundlespec changes to declare it
1625 # b) introducing a command flag.
1627 # b) introducing a command flag.
1626 compopts = {}
1628 compopts = {}
1627 complevel = ui.configint(
1629 complevel = ui.configint(
1628 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1630 b'experimental', b'bundlecomplevel.' + bundlespec.compression
1629 )
1631 )
1630 if complevel is None:
1632 if complevel is None:
1631 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1633 complevel = ui.configint(b'experimental', b'bundlecomplevel')
1632 if complevel is not None:
1634 if complevel is not None:
1633 compopts[b'level'] = complevel
1635 compopts[b'level'] = complevel
1634
1636
1635 # Allow overriding the bundling of obsmarker in phases through
1637 # Allow overriding the bundling of obsmarker in phases through
1636 # configuration while we don't have a bundle version that include them
1638 # configuration while we don't have a bundle version that include them
1637 if repo.ui.configbool(b'experimental', b'evolution.bundle-obsmarker'):
1639 if repo.ui.configbool(b'experimental', b'evolution.bundle-obsmarker'):
1638 bundlespec.contentopts[b'obsolescence'] = True
1640 bundlespec.contentopts[b'obsolescence'] = True
1639 if repo.ui.configbool(b'experimental', b'bundle-phases'):
1641 if repo.ui.configbool(b'experimental', b'bundle-phases'):
1640 bundlespec.contentopts[b'phases'] = True
1642 bundlespec.contentopts[b'phases'] = True
1641
1643
1642 bundle2.writenewbundle(
1644 bundle2.writenewbundle(
1643 ui,
1645 ui,
1644 repo,
1646 repo,
1645 b'bundle',
1647 b'bundle',
1646 fname,
1648 fname,
1647 bversion,
1649 bversion,
1648 outgoing,
1650 outgoing,
1649 bundlespec.contentopts,
1651 bundlespec.contentopts,
1650 compression=bcompression,
1652 compression=bcompression,
1651 compopts=compopts,
1653 compopts=compopts,
1652 )
1654 )
1653
1655
1654
1656
1655 @command(
1657 @command(
1656 b'cat',
1658 b'cat',
1657 [
1659 [
1658 (
1660 (
1659 b'o',
1661 b'o',
1660 b'output',
1662 b'output',
1661 b'',
1663 b'',
1662 _(b'print output to file with formatted name'),
1664 _(b'print output to file with formatted name'),
1663 _(b'FORMAT'),
1665 _(b'FORMAT'),
1664 ),
1666 ),
1665 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1667 (b'r', b'rev', b'', _(b'print the given revision'), _(b'REV')),
1666 (b'', b'decode', None, _(b'apply any matching decode filter')),
1668 (b'', b'decode', None, _(b'apply any matching decode filter')),
1667 ]
1669 ]
1668 + walkopts
1670 + walkopts
1669 + formatteropts,
1671 + formatteropts,
1670 _(b'[OPTION]... FILE...'),
1672 _(b'[OPTION]... FILE...'),
1671 helpcategory=command.CATEGORY_FILE_CONTENTS,
1673 helpcategory=command.CATEGORY_FILE_CONTENTS,
1672 inferrepo=True,
1674 inferrepo=True,
1673 intents={INTENT_READONLY},
1675 intents={INTENT_READONLY},
1674 )
1676 )
1675 def cat(ui, repo, file1, *pats, **opts):
1677 def cat(ui, repo, file1, *pats, **opts):
1676 """output the current or given revision of files
1678 """output the current or given revision of files
1677
1679
1678 Print the specified files as they were at the given revision. If
1680 Print the specified files as they were at the given revision. If
1679 no revision is given, the parent of the working directory is used.
1681 no revision is given, the parent of the working directory is used.
1680
1682
1681 Output may be to a file, in which case the name of the file is
1683 Output may be to a file, in which case the name of the file is
1682 given using a template string. See :hg:`help templates`. In addition
1684 given using a template string. See :hg:`help templates`. In addition
1683 to the common template keywords, the following formatting rules are
1685 to the common template keywords, the following formatting rules are
1684 supported:
1686 supported:
1685
1687
1686 :``%%``: literal "%" character
1688 :``%%``: literal "%" character
1687 :``%s``: basename of file being printed
1689 :``%s``: basename of file being printed
1688 :``%d``: dirname of file being printed, or '.' if in repository root
1690 :``%d``: dirname of file being printed, or '.' if in repository root
1689 :``%p``: root-relative path name of file being printed
1691 :``%p``: root-relative path name of file being printed
1690 :``%H``: changeset hash (40 hexadecimal digits)
1692 :``%H``: changeset hash (40 hexadecimal digits)
1691 :``%R``: changeset revision number
1693 :``%R``: changeset revision number
1692 :``%h``: short-form changeset hash (12 hexadecimal digits)
1694 :``%h``: short-form changeset hash (12 hexadecimal digits)
1693 :``%r``: zero-padded changeset revision number
1695 :``%r``: zero-padded changeset revision number
1694 :``%b``: basename of the exporting repository
1696 :``%b``: basename of the exporting repository
1695 :``\\``: literal "\\" character
1697 :``\\``: literal "\\" character
1696
1698
1697 .. container:: verbose
1699 .. container:: verbose
1698
1700
1699 Template:
1701 Template:
1700
1702
1701 The following keywords are supported in addition to the common template
1703 The following keywords are supported in addition to the common template
1702 keywords and functions. See also :hg:`help templates`.
1704 keywords and functions. See also :hg:`help templates`.
1703
1705
1704 :data: String. File content.
1706 :data: String. File content.
1705 :path: String. Repository-absolute path of the file.
1707 :path: String. Repository-absolute path of the file.
1706
1708
1707 Returns 0 on success.
1709 Returns 0 on success.
1708 """
1710 """
1709 opts = pycompat.byteskwargs(opts)
1711 opts = pycompat.byteskwargs(opts)
1710 rev = opts.get(b'rev')
1712 rev = opts.get(b'rev')
1711 if rev:
1713 if rev:
1712 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1714 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
1713 ctx = scmutil.revsingle(repo, rev)
1715 ctx = scmutil.revsingle(repo, rev)
1714 m = scmutil.match(ctx, (file1,) + pats, opts)
1716 m = scmutil.match(ctx, (file1,) + pats, opts)
1715 fntemplate = opts.pop(b'output', b'')
1717 fntemplate = opts.pop(b'output', b'')
1716 if cmdutil.isstdiofilename(fntemplate):
1718 if cmdutil.isstdiofilename(fntemplate):
1717 fntemplate = b''
1719 fntemplate = b''
1718
1720
1719 if fntemplate:
1721 if fntemplate:
1720 fm = formatter.nullformatter(ui, b'cat', opts)
1722 fm = formatter.nullformatter(ui, b'cat', opts)
1721 else:
1723 else:
1722 ui.pager(b'cat')
1724 ui.pager(b'cat')
1723 fm = ui.formatter(b'cat', opts)
1725 fm = ui.formatter(b'cat', opts)
1724 with fm:
1726 with fm:
1725 return cmdutil.cat(
1727 return cmdutil.cat(
1726 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1728 ui, repo, ctx, m, fm, fntemplate, b'', **pycompat.strkwargs(opts)
1727 )
1729 )
1728
1730
1729
1731
1730 @command(
1732 @command(
1731 b'clone',
1733 b'clone',
1732 [
1734 [
1733 (
1735 (
1734 b'U',
1736 b'U',
1735 b'noupdate',
1737 b'noupdate',
1736 None,
1738 None,
1737 _(
1739 _(
1738 b'the clone will include an empty working '
1740 b'the clone will include an empty working '
1739 b'directory (only a repository)'
1741 b'directory (only a repository)'
1740 ),
1742 ),
1741 ),
1743 ),
1742 (
1744 (
1743 b'u',
1745 b'u',
1744 b'updaterev',
1746 b'updaterev',
1745 b'',
1747 b'',
1746 _(b'revision, tag, or branch to check out'),
1748 _(b'revision, tag, or branch to check out'),
1747 _(b'REV'),
1749 _(b'REV'),
1748 ),
1750 ),
1749 (
1751 (
1750 b'r',
1752 b'r',
1751 b'rev',
1753 b'rev',
1752 [],
1754 [],
1753 _(
1755 _(
1754 b'do not clone everything, but include this changeset'
1756 b'do not clone everything, but include this changeset'
1755 b' and its ancestors'
1757 b' and its ancestors'
1756 ),
1758 ),
1757 _(b'REV'),
1759 _(b'REV'),
1758 ),
1760 ),
1759 (
1761 (
1760 b'b',
1762 b'b',
1761 b'branch',
1763 b'branch',
1762 [],
1764 [],
1763 _(
1765 _(
1764 b'do not clone everything, but include this branch\'s'
1766 b'do not clone everything, but include this branch\'s'
1765 b' changesets and their ancestors'
1767 b' changesets and their ancestors'
1766 ),
1768 ),
1767 _(b'BRANCH'),
1769 _(b'BRANCH'),
1768 ),
1770 ),
1769 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1771 (b'', b'pull', None, _(b'use pull protocol to copy metadata')),
1770 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1772 (b'', b'uncompressed', None, _(b'an alias to --stream (DEPRECATED)')),
1771 (b'', b'stream', None, _(b'clone with minimal data processing')),
1773 (b'', b'stream', None, _(b'clone with minimal data processing')),
1772 ]
1774 ]
1773 + remoteopts,
1775 + remoteopts,
1774 _(b'[OPTION]... SOURCE [DEST]'),
1776 _(b'[OPTION]... SOURCE [DEST]'),
1775 helpcategory=command.CATEGORY_REPO_CREATION,
1777 helpcategory=command.CATEGORY_REPO_CREATION,
1776 helpbasic=True,
1778 helpbasic=True,
1777 norepo=True,
1779 norepo=True,
1778 )
1780 )
1779 def clone(ui, source, dest=None, **opts):
1781 def clone(ui, source, dest=None, **opts):
1780 """make a copy of an existing repository
1782 """make a copy of an existing repository
1781
1783
1782 Create a copy of an existing repository in a new directory.
1784 Create a copy of an existing repository in a new directory.
1783
1785
1784 If no destination directory name is specified, it defaults to the
1786 If no destination directory name is specified, it defaults to the
1785 basename of the source.
1787 basename of the source.
1786
1788
1787 The location of the source is added to the new repository's
1789 The location of the source is added to the new repository's
1788 ``.hg/hgrc`` file, as the default to be used for future pulls.
1790 ``.hg/hgrc`` file, as the default to be used for future pulls.
1789
1791
1790 Only local paths and ``ssh://`` URLs are supported as
1792 Only local paths and ``ssh://`` URLs are supported as
1791 destinations. For ``ssh://`` destinations, no working directory or
1793 destinations. For ``ssh://`` destinations, no working directory or
1792 ``.hg/hgrc`` will be created on the remote side.
1794 ``.hg/hgrc`` will be created on the remote side.
1793
1795
1794 If the source repository has a bookmark called '@' set, that
1796 If the source repository has a bookmark called '@' set, that
1795 revision will be checked out in the new repository by default.
1797 revision will be checked out in the new repository by default.
1796
1798
1797 To check out a particular version, use -u/--update, or
1799 To check out a particular version, use -u/--update, or
1798 -U/--noupdate to create a clone with no working directory.
1800 -U/--noupdate to create a clone with no working directory.
1799
1801
1800 To pull only a subset of changesets, specify one or more revisions
1802 To pull only a subset of changesets, specify one or more revisions
1801 identifiers with -r/--rev or branches with -b/--branch. The
1803 identifiers with -r/--rev or branches with -b/--branch. The
1802 resulting clone will contain only the specified changesets and
1804 resulting clone will contain only the specified changesets and
1803 their ancestors. These options (or 'clone src#rev dest') imply
1805 their ancestors. These options (or 'clone src#rev dest') imply
1804 --pull, even for local source repositories.
1806 --pull, even for local source repositories.
1805
1807
1806 In normal clone mode, the remote normalizes repository data into a common
1808 In normal clone mode, the remote normalizes repository data into a common
1807 exchange format and the receiving end translates this data into its local
1809 exchange format and the receiving end translates this data into its local
1808 storage format. --stream activates a different clone mode that essentially
1810 storage format. --stream activates a different clone mode that essentially
1809 copies repository files from the remote with minimal data processing. This
1811 copies repository files from the remote with minimal data processing. This
1810 significantly reduces the CPU cost of a clone both remotely and locally.
1812 significantly reduces the CPU cost of a clone both remotely and locally.
1811 However, it often increases the transferred data size by 30-40%. This can
1813 However, it often increases the transferred data size by 30-40%. This can
1812 result in substantially faster clones where I/O throughput is plentiful,
1814 result in substantially faster clones where I/O throughput is plentiful,
1813 especially for larger repositories. A side-effect of --stream clones is
1815 especially for larger repositories. A side-effect of --stream clones is
1814 that storage settings and requirements on the remote are applied locally:
1816 that storage settings and requirements on the remote are applied locally:
1815 a modern client may inherit legacy or inefficient storage used by the
1817 a modern client may inherit legacy or inefficient storage used by the
1816 remote or a legacy Mercurial client may not be able to clone from a
1818 remote or a legacy Mercurial client may not be able to clone from a
1817 modern Mercurial remote.
1819 modern Mercurial remote.
1818
1820
1819 .. note::
1821 .. note::
1820
1822
1821 Specifying a tag will include the tagged changeset but not the
1823 Specifying a tag will include the tagged changeset but not the
1822 changeset containing the tag.
1824 changeset containing the tag.
1823
1825
1824 .. container:: verbose
1826 .. container:: verbose
1825
1827
1826 For efficiency, hardlinks are used for cloning whenever the
1828 For efficiency, hardlinks are used for cloning whenever the
1827 source and destination are on the same filesystem (note this
1829 source and destination are on the same filesystem (note this
1828 applies only to the repository data, not to the working
1830 applies only to the repository data, not to the working
1829 directory). Some filesystems, such as AFS, implement hardlinking
1831 directory). Some filesystems, such as AFS, implement hardlinking
1830 incorrectly, but do not report errors. In these cases, use the
1832 incorrectly, but do not report errors. In these cases, use the
1831 --pull option to avoid hardlinking.
1833 --pull option to avoid hardlinking.
1832
1834
1833 Mercurial will update the working directory to the first applicable
1835 Mercurial will update the working directory to the first applicable
1834 revision from this list:
1836 revision from this list:
1835
1837
1836 a) null if -U or the source repository has no changesets
1838 a) null if -U or the source repository has no changesets
1837 b) if -u . and the source repository is local, the first parent of
1839 b) if -u . and the source repository is local, the first parent of
1838 the source repository's working directory
1840 the source repository's working directory
1839 c) the changeset specified with -u (if a branch name, this means the
1841 c) the changeset specified with -u (if a branch name, this means the
1840 latest head of that branch)
1842 latest head of that branch)
1841 d) the changeset specified with -r
1843 d) the changeset specified with -r
1842 e) the tipmost head specified with -b
1844 e) the tipmost head specified with -b
1843 f) the tipmost head specified with the url#branch source syntax
1845 f) the tipmost head specified with the url#branch source syntax
1844 g) the revision marked with the '@' bookmark, if present
1846 g) the revision marked with the '@' bookmark, if present
1845 h) the tipmost head of the default branch
1847 h) the tipmost head of the default branch
1846 i) tip
1848 i) tip
1847
1849
1848 When cloning from servers that support it, Mercurial may fetch
1850 When cloning from servers that support it, Mercurial may fetch
1849 pre-generated data from a server-advertised URL or inline from the
1851 pre-generated data from a server-advertised URL or inline from the
1850 same stream. When this is done, hooks operating on incoming changesets
1852 same stream. When this is done, hooks operating on incoming changesets
1851 and changegroups may fire more than once, once for each pre-generated
1853 and changegroups may fire more than once, once for each pre-generated
1852 bundle and as well as for any additional remaining data. In addition,
1854 bundle and as well as for any additional remaining data. In addition,
1853 if an error occurs, the repository may be rolled back to a partial
1855 if an error occurs, the repository may be rolled back to a partial
1854 clone. This behavior may change in future releases.
1856 clone. This behavior may change in future releases.
1855 See :hg:`help -e clonebundles` for more.
1857 See :hg:`help -e clonebundles` for more.
1856
1858
1857 Examples:
1859 Examples:
1858
1860
1859 - clone a remote repository to a new directory named hg/::
1861 - clone a remote repository to a new directory named hg/::
1860
1862
1861 hg clone https://www.mercurial-scm.org/repo/hg/
1863 hg clone https://www.mercurial-scm.org/repo/hg/
1862
1864
1863 - create a lightweight local clone::
1865 - create a lightweight local clone::
1864
1866
1865 hg clone project/ project-feature/
1867 hg clone project/ project-feature/
1866
1868
1867 - clone from an absolute path on an ssh server (note double-slash)::
1869 - clone from an absolute path on an ssh server (note double-slash)::
1868
1870
1869 hg clone ssh://user@server//home/projects/alpha/
1871 hg clone ssh://user@server//home/projects/alpha/
1870
1872
1871 - do a streaming clone while checking out a specified version::
1873 - do a streaming clone while checking out a specified version::
1872
1874
1873 hg clone --stream http://server/repo -u 1.5
1875 hg clone --stream http://server/repo -u 1.5
1874
1876
1875 - create a repository without changesets after a particular revision::
1877 - create a repository without changesets after a particular revision::
1876
1878
1877 hg clone -r 04e544 experimental/ good/
1879 hg clone -r 04e544 experimental/ good/
1878
1880
1879 - clone (and track) a particular named branch::
1881 - clone (and track) a particular named branch::
1880
1882
1881 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1883 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1882
1884
1883 See :hg:`help urls` for details on specifying URLs.
1885 See :hg:`help urls` for details on specifying URLs.
1884
1886
1885 Returns 0 on success.
1887 Returns 0 on success.
1886 """
1888 """
1887 opts = pycompat.byteskwargs(opts)
1889 opts = pycompat.byteskwargs(opts)
1888 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1890 cmdutil.check_at_most_one_arg(opts, b'noupdate', b'updaterev')
1889
1891
1890 # --include/--exclude can come from narrow or sparse.
1892 # --include/--exclude can come from narrow or sparse.
1891 includepats, excludepats = None, None
1893 includepats, excludepats = None, None
1892
1894
1893 # hg.clone() differentiates between None and an empty set. So make sure
1895 # hg.clone() differentiates between None and an empty set. So make sure
1894 # patterns are sets if narrow is requested without patterns.
1896 # patterns are sets if narrow is requested without patterns.
1895 if opts.get(b'narrow'):
1897 if opts.get(b'narrow'):
1896 includepats = set()
1898 includepats = set()
1897 excludepats = set()
1899 excludepats = set()
1898
1900
1899 if opts.get(b'include'):
1901 if opts.get(b'include'):
1900 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1902 includepats = narrowspec.parsepatterns(opts.get(b'include'))
1901 if opts.get(b'exclude'):
1903 if opts.get(b'exclude'):
1902 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1904 excludepats = narrowspec.parsepatterns(opts.get(b'exclude'))
1903
1905
1904 r = hg.clone(
1906 r = hg.clone(
1905 ui,
1907 ui,
1906 opts,
1908 opts,
1907 source,
1909 source,
1908 dest,
1910 dest,
1909 pull=opts.get(b'pull'),
1911 pull=opts.get(b'pull'),
1910 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1912 stream=opts.get(b'stream') or opts.get(b'uncompressed'),
1911 revs=opts.get(b'rev'),
1913 revs=opts.get(b'rev'),
1912 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1914 update=opts.get(b'updaterev') or not opts.get(b'noupdate'),
1913 branch=opts.get(b'branch'),
1915 branch=opts.get(b'branch'),
1914 shareopts=opts.get(b'shareopts'),
1916 shareopts=opts.get(b'shareopts'),
1915 storeincludepats=includepats,
1917 storeincludepats=includepats,
1916 storeexcludepats=excludepats,
1918 storeexcludepats=excludepats,
1917 depth=opts.get(b'depth') or None,
1919 depth=opts.get(b'depth') or None,
1918 )
1920 )
1919
1921
1920 return r is None
1922 return r is None
1921
1923
1922
1924
1923 @command(
1925 @command(
1924 b'commit|ci',
1926 b'commit|ci',
1925 [
1927 [
1926 (
1928 (
1927 b'A',
1929 b'A',
1928 b'addremove',
1930 b'addremove',
1929 None,
1931 None,
1930 _(b'mark new/missing files as added/removed before committing'),
1932 _(b'mark new/missing files as added/removed before committing'),
1931 ),
1933 ),
1932 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1934 (b'', b'close-branch', None, _(b'mark a branch head as closed')),
1933 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1935 (b'', b'amend', None, _(b'amend the parent of the working directory')),
1934 (b's', b'secret', None, _(b'use the secret phase for committing')),
1936 (b's', b'secret', None, _(b'use the secret phase for committing')),
1935 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1937 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
1936 (
1938 (
1937 b'',
1939 b'',
1938 b'force-close-branch',
1940 b'force-close-branch',
1939 None,
1941 None,
1940 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1942 _(b'forcibly close branch from a non-head changeset (ADVANCED)'),
1941 ),
1943 ),
1942 (b'i', b'interactive', None, _(b'use interactive mode')),
1944 (b'i', b'interactive', None, _(b'use interactive mode')),
1943 ]
1945 ]
1944 + walkopts
1946 + walkopts
1945 + commitopts
1947 + commitopts
1946 + commitopts2
1948 + commitopts2
1947 + subrepoopts,
1949 + subrepoopts,
1948 _(b'[OPTION]... [FILE]...'),
1950 _(b'[OPTION]... [FILE]...'),
1949 helpcategory=command.CATEGORY_COMMITTING,
1951 helpcategory=command.CATEGORY_COMMITTING,
1950 helpbasic=True,
1952 helpbasic=True,
1951 inferrepo=True,
1953 inferrepo=True,
1952 )
1954 )
1953 def commit(ui, repo, *pats, **opts):
1955 def commit(ui, repo, *pats, **opts):
1954 """commit the specified files or all outstanding changes
1956 """commit the specified files or all outstanding changes
1955
1957
1956 Commit changes to the given files into the repository. Unlike a
1958 Commit changes to the given files into the repository. Unlike a
1957 centralized SCM, this operation is a local operation. See
1959 centralized SCM, this operation is a local operation. See
1958 :hg:`push` for a way to actively distribute your changes.
1960 :hg:`push` for a way to actively distribute your changes.
1959
1961
1960 If a list of files is omitted, all changes reported by :hg:`status`
1962 If a list of files is omitted, all changes reported by :hg:`status`
1961 will be committed.
1963 will be committed.
1962
1964
1963 If you are committing the result of a merge, do not provide any
1965 If you are committing the result of a merge, do not provide any
1964 filenames or -I/-X filters.
1966 filenames or -I/-X filters.
1965
1967
1966 If no commit message is specified, Mercurial starts your
1968 If no commit message is specified, Mercurial starts your
1967 configured editor where you can enter a message. In case your
1969 configured editor where you can enter a message. In case your
1968 commit fails, you will find a backup of your message in
1970 commit fails, you will find a backup of your message in
1969 ``.hg/last-message.txt``.
1971 ``.hg/last-message.txt``.
1970
1972
1971 The --close-branch flag can be used to mark the current branch
1973 The --close-branch flag can be used to mark the current branch
1972 head closed. When all heads of a branch are closed, the branch
1974 head closed. When all heads of a branch are closed, the branch
1973 will be considered closed and no longer listed.
1975 will be considered closed and no longer listed.
1974
1976
1975 The --amend flag can be used to amend the parent of the
1977 The --amend flag can be used to amend the parent of the
1976 working directory with a new commit that contains the changes
1978 working directory with a new commit that contains the changes
1977 in the parent in addition to those currently reported by :hg:`status`,
1979 in the parent in addition to those currently reported by :hg:`status`,
1978 if there are any. The old commit is stored in a backup bundle in
1980 if there are any. The old commit is stored in a backup bundle in
1979 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1981 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1980 on how to restore it).
1982 on how to restore it).
1981
1983
1982 Message, user and date are taken from the amended commit unless
1984 Message, user and date are taken from the amended commit unless
1983 specified. When a message isn't specified on the command line,
1985 specified. When a message isn't specified on the command line,
1984 the editor will open with the message of the amended commit.
1986 the editor will open with the message of the amended commit.
1985
1987
1986 It is not possible to amend public changesets (see :hg:`help phases`)
1988 It is not possible to amend public changesets (see :hg:`help phases`)
1987 or changesets that have children.
1989 or changesets that have children.
1988
1990
1989 See :hg:`help dates` for a list of formats valid for -d/--date.
1991 See :hg:`help dates` for a list of formats valid for -d/--date.
1990
1992
1991 Returns 0 on success, 1 if nothing changed.
1993 Returns 0 on success, 1 if nothing changed.
1992
1994
1993 .. container:: verbose
1995 .. container:: verbose
1994
1996
1995 Examples:
1997 Examples:
1996
1998
1997 - commit all files ending in .py::
1999 - commit all files ending in .py::
1998
2000
1999 hg commit --include "set:**.py"
2001 hg commit --include "set:**.py"
2000
2002
2001 - commit all non-binary files::
2003 - commit all non-binary files::
2002
2004
2003 hg commit --exclude "set:binary()"
2005 hg commit --exclude "set:binary()"
2004
2006
2005 - amend the current commit and set the date to now::
2007 - amend the current commit and set the date to now::
2006
2008
2007 hg commit --amend --date now
2009 hg commit --amend --date now
2008 """
2010 """
2009 with repo.wlock(), repo.lock():
2011 with repo.wlock(), repo.lock():
2010 return _docommit(ui, repo, *pats, **opts)
2012 return _docommit(ui, repo, *pats, **opts)
2011
2013
2012
2014
2013 def _docommit(ui, repo, *pats, **opts):
2015 def _docommit(ui, repo, *pats, **opts):
2014 if opts.get('interactive'):
2016 if opts.get('interactive'):
2015 opts.pop('interactive')
2017 opts.pop('interactive')
2016 ret = cmdutil.dorecord(
2018 ret = cmdutil.dorecord(
2017 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2019 ui, repo, commit, None, False, cmdutil.recordfilter, *pats, **opts
2018 )
2020 )
2019 # ret can be 0 (no changes to record) or the value returned by
2021 # ret can be 0 (no changes to record) or the value returned by
2020 # commit(), 1 if nothing changed or None on success.
2022 # commit(), 1 if nothing changed or None on success.
2021 return 1 if ret == 0 else ret
2023 return 1 if ret == 0 else ret
2022
2024
2023 opts = pycompat.byteskwargs(opts)
2025 opts = pycompat.byteskwargs(opts)
2024 if opts.get(b'subrepos'):
2026 if opts.get(b'subrepos'):
2025 if opts.get(b'amend'):
2027 if opts.get(b'amend'):
2026 raise error.Abort(_(b'cannot amend with --subrepos'))
2028 raise error.Abort(_(b'cannot amend with --subrepos'))
2027 # Let --subrepos on the command line override config setting.
2029 # Let --subrepos on the command line override config setting.
2028 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2030 ui.setconfig(b'ui', b'commitsubrepos', True, b'commit')
2029
2031
2030 cmdutil.checkunfinished(repo, commit=True)
2032 cmdutil.checkunfinished(repo, commit=True)
2031
2033
2032 branch = repo[None].branch()
2034 branch = repo[None].branch()
2033 bheads = repo.branchheads(branch)
2035 bheads = repo.branchheads(branch)
2034
2036
2035 extra = {}
2037 extra = {}
2036 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2038 if opts.get(b'close_branch') or opts.get(b'force_close_branch'):
2037 extra[b'close'] = b'1'
2039 extra[b'close'] = b'1'
2038
2040
2039 if repo[b'.'].closesbranch():
2041 if repo[b'.'].closesbranch():
2040 raise error.Abort(
2042 raise error.Abort(
2041 _(b'current revision is already a branch closing head')
2043 _(b'current revision is already a branch closing head')
2042 )
2044 )
2043 elif not bheads:
2045 elif not bheads:
2044 raise error.Abort(_(b'branch "%s" has no heads to close') % branch)
2046 raise error.Abort(_(b'branch "%s" has no heads to close') % branch)
2045 elif (
2047 elif (
2046 branch == repo[b'.'].branch()
2048 branch == repo[b'.'].branch()
2047 and repo[b'.'].node() not in bheads
2049 and repo[b'.'].node() not in bheads
2048 and not opts.get(b'force_close_branch')
2050 and not opts.get(b'force_close_branch')
2049 ):
2051 ):
2050 hint = _(
2052 hint = _(
2051 b'use --force-close-branch to close branch from a non-head'
2053 b'use --force-close-branch to close branch from a non-head'
2052 b' changeset'
2054 b' changeset'
2053 )
2055 )
2054 raise error.Abort(_(b'can only close branch heads'), hint=hint)
2056 raise error.Abort(_(b'can only close branch heads'), hint=hint)
2055 elif opts.get(b'amend'):
2057 elif opts.get(b'amend'):
2056 if (
2058 if (
2057 repo[b'.'].p1().branch() != branch
2059 repo[b'.'].p1().branch() != branch
2058 and repo[b'.'].p2().branch() != branch
2060 and repo[b'.'].p2().branch() != branch
2059 ):
2061 ):
2060 raise error.Abort(_(b'can only close branch heads'))
2062 raise error.Abort(_(b'can only close branch heads'))
2061
2063
2062 if opts.get(b'amend'):
2064 if opts.get(b'amend'):
2063 if ui.configbool(b'ui', b'commitsubrepos'):
2065 if ui.configbool(b'ui', b'commitsubrepos'):
2064 raise error.Abort(_(b'cannot amend with ui.commitsubrepos enabled'))
2066 raise error.Abort(_(b'cannot amend with ui.commitsubrepos enabled'))
2065
2067
2066 old = repo[b'.']
2068 old = repo[b'.']
2067 rewriteutil.precheck(repo, [old.rev()], b'amend')
2069 rewriteutil.precheck(repo, [old.rev()], b'amend')
2068
2070
2069 # Currently histedit gets confused if an amend happens while histedit
2071 # Currently histedit gets confused if an amend happens while histedit
2070 # is in progress. Since we have a checkunfinished command, we are
2072 # is in progress. Since we have a checkunfinished command, we are
2071 # temporarily honoring it.
2073 # temporarily honoring it.
2072 #
2074 #
2073 # Note: eventually this guard will be removed. Please do not expect
2075 # Note: eventually this guard will be removed. Please do not expect
2074 # this behavior to remain.
2076 # this behavior to remain.
2075 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2077 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
2076 cmdutil.checkunfinished(repo)
2078 cmdutil.checkunfinished(repo)
2077
2079
2078 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2080 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
2079 if node == old.node():
2081 if node == old.node():
2080 ui.status(_(b"nothing changed\n"))
2082 ui.status(_(b"nothing changed\n"))
2081 return 1
2083 return 1
2082 else:
2084 else:
2083
2085
2084 def commitfunc(ui, repo, message, match, opts):
2086 def commitfunc(ui, repo, message, match, opts):
2085 overrides = {}
2087 overrides = {}
2086 if opts.get(b'secret'):
2088 if opts.get(b'secret'):
2087 overrides[(b'phases', b'new-commit')] = b'secret'
2089 overrides[(b'phases', b'new-commit')] = b'secret'
2088
2090
2089 baseui = repo.baseui
2091 baseui = repo.baseui
2090 with baseui.configoverride(overrides, b'commit'):
2092 with baseui.configoverride(overrides, b'commit'):
2091 with ui.configoverride(overrides, b'commit'):
2093 with ui.configoverride(overrides, b'commit'):
2092 editform = cmdutil.mergeeditform(
2094 editform = cmdutil.mergeeditform(
2093 repo[None], b'commit.normal'
2095 repo[None], b'commit.normal'
2094 )
2096 )
2095 editor = cmdutil.getcommiteditor(
2097 editor = cmdutil.getcommiteditor(
2096 editform=editform, **pycompat.strkwargs(opts)
2098 editform=editform, **pycompat.strkwargs(opts)
2097 )
2099 )
2098 return repo.commit(
2100 return repo.commit(
2099 message,
2101 message,
2100 opts.get(b'user'),
2102 opts.get(b'user'),
2101 opts.get(b'date'),
2103 opts.get(b'date'),
2102 match,
2104 match,
2103 editor=editor,
2105 editor=editor,
2104 extra=extra,
2106 extra=extra,
2105 )
2107 )
2106
2108
2107 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2109 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
2108
2110
2109 if not node:
2111 if not node:
2110 stat = cmdutil.postcommitstatus(repo, pats, opts)
2112 stat = cmdutil.postcommitstatus(repo, pats, opts)
2111 if stat.deleted:
2113 if stat.deleted:
2112 ui.status(
2114 ui.status(
2113 _(
2115 _(
2114 b"nothing changed (%d missing files, see "
2116 b"nothing changed (%d missing files, see "
2115 b"'hg status')\n"
2117 b"'hg status')\n"
2116 )
2118 )
2117 % len(stat.deleted)
2119 % len(stat.deleted)
2118 )
2120 )
2119 else:
2121 else:
2120 ui.status(_(b"nothing changed\n"))
2122 ui.status(_(b"nothing changed\n"))
2121 return 1
2123 return 1
2122
2124
2123 cmdutil.commitstatus(repo, node, branch, bheads, opts)
2125 cmdutil.commitstatus(repo, node, branch, bheads, opts)
2124
2126
2125 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2127 if not ui.quiet and ui.configbool(b'commands', b'commit.post-status'):
2126 status(
2128 status(
2127 ui,
2129 ui,
2128 repo,
2130 repo,
2129 modified=True,
2131 modified=True,
2130 added=True,
2132 added=True,
2131 removed=True,
2133 removed=True,
2132 deleted=True,
2134 deleted=True,
2133 unknown=True,
2135 unknown=True,
2134 subrepos=opts.get(b'subrepos'),
2136 subrepos=opts.get(b'subrepos'),
2135 )
2137 )
2136
2138
2137
2139
2138 @command(
2140 @command(
2139 b'config|showconfig|debugconfig',
2141 b'config|showconfig|debugconfig',
2140 [
2142 [
2141 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2143 (b'u', b'untrusted', None, _(b'show untrusted configuration options')),
2142 (b'e', b'edit', None, _(b'edit user config')),
2144 (b'e', b'edit', None, _(b'edit user config')),
2143 (b'l', b'local', None, _(b'edit repository config')),
2145 (b'l', b'local', None, _(b'edit repository config')),
2146 (
2147 b'',
2148 b'shared',
2149 None,
2150 _(b'edit shared source repository config (EXPERIMENTAL)'),
2151 ),
2144 (b'g', b'global', None, _(b'edit global config')),
2152 (b'g', b'global', None, _(b'edit global config')),
2145 ]
2153 ]
2146 + formatteropts,
2154 + formatteropts,
2147 _(b'[-u] [NAME]...'),
2155 _(b'[-u] [NAME]...'),
2148 helpcategory=command.CATEGORY_HELP,
2156 helpcategory=command.CATEGORY_HELP,
2149 optionalrepo=True,
2157 optionalrepo=True,
2150 intents={INTENT_READONLY},
2158 intents={INTENT_READONLY},
2151 )
2159 )
2152 def config(ui, repo, *values, **opts):
2160 def config(ui, repo, *values, **opts):
2153 """show combined config settings from all hgrc files
2161 """show combined config settings from all hgrc files
2154
2162
2155 With no arguments, print names and values of all config items.
2163 With no arguments, print names and values of all config items.
2156
2164
2157 With one argument of the form section.name, print just the value
2165 With one argument of the form section.name, print just the value
2158 of that config item.
2166 of that config item.
2159
2167
2160 With multiple arguments, print names and values of all config
2168 With multiple arguments, print names and values of all config
2161 items with matching section names or section.names.
2169 items with matching section names or section.names.
2162
2170
2163 With --edit, start an editor on the user-level config file. With
2171 With --edit, start an editor on the user-level config file. With
2164 --global, edit the system-wide config file. With --local, edit the
2172 --global, edit the system-wide config file. With --local, edit the
2165 repository-level config file.
2173 repository-level config file.
2166
2174
2167 With --debug, the source (filename and line number) is printed
2175 With --debug, the source (filename and line number) is printed
2168 for each config item.
2176 for each config item.
2169
2177
2170 See :hg:`help config` for more information about config files.
2178 See :hg:`help config` for more information about config files.
2171
2179
2172 .. container:: verbose
2180 .. container:: verbose
2173
2181
2174 Template:
2182 Template:
2175
2183
2176 The following keywords are supported. See also :hg:`help templates`.
2184 The following keywords are supported. See also :hg:`help templates`.
2177
2185
2178 :name: String. Config name.
2186 :name: String. Config name.
2179 :source: String. Filename and line number where the item is defined.
2187 :source: String. Filename and line number where the item is defined.
2180 :value: String. Config value.
2188 :value: String. Config value.
2181
2189
2190 The --shared flag can be used to edit the config file of shared source
2191 repository. It only works when you have shared using the experimental
2192 share safe feature.
2193
2182 Returns 0 on success, 1 if NAME does not exist.
2194 Returns 0 on success, 1 if NAME does not exist.
2183
2195
2184 """
2196 """
2185
2197
2186 opts = pycompat.byteskwargs(opts)
2198 opts = pycompat.byteskwargs(opts)
2187 editopts = (b'edit', b'local', b'global')
2199 editopts = (b'edit', b'local', b'global', b'shared')
2188 if any(opts.get(o) for o in editopts):
2200 if any(opts.get(o) for o in editopts):
2189 if opts.get(b'local') and opts.get(b'global'):
2201 cmdutil.check_at_most_one_arg(opts, *editopts[1:])
2190 raise error.Abort(_(b"can't use --local and --global together"))
2191
2192 if opts.get(b'local'):
2202 if opts.get(b'local'):
2193 if not repo:
2203 if not repo:
2194 raise error.Abort(_(b"can't use --local outside a repository"))
2204 raise error.Abort(_(b"can't use --local outside a repository"))
2195 paths = [repo.vfs.join(b'hgrc')]
2205 paths = [repo.vfs.join(b'hgrc')]
2196 elif opts.get(b'global'):
2206 elif opts.get(b'global'):
2197 paths = rcutil.systemrcpath()
2207 paths = rcutil.systemrcpath()
2208 elif opts.get(b'shared'):
2209 if not repo.shared():
2210 raise error.Abort(
2211 _(b"repository is not shared; can't use --shared")
2212 )
2213 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
2214 raise error.Abort(
2215 _(
2216 b"share safe feature not unabled; "
2217 b"unable to edit shared source repository config"
2218 )
2219 )
2220 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
2198 else:
2221 else:
2199 paths = rcutil.userrcpath()
2222 paths = rcutil.userrcpath()
2200
2223
2201 for f in paths:
2224 for f in paths:
2202 if os.path.exists(f):
2225 if os.path.exists(f):
2203 break
2226 break
2204 else:
2227 else:
2205 if opts.get(b'global'):
2228 if opts.get(b'global'):
2206 samplehgrc = uimod.samplehgrcs[b'global']
2229 samplehgrc = uimod.samplehgrcs[b'global']
2207 elif opts.get(b'local'):
2230 elif opts.get(b'local'):
2208 samplehgrc = uimod.samplehgrcs[b'local']
2231 samplehgrc = uimod.samplehgrcs[b'local']
2209 else:
2232 else:
2210 samplehgrc = uimod.samplehgrcs[b'user']
2233 samplehgrc = uimod.samplehgrcs[b'user']
2211
2234
2212 f = paths[0]
2235 f = paths[0]
2213 fp = open(f, b"wb")
2236 fp = open(f, b"wb")
2214 fp.write(util.tonativeeol(samplehgrc))
2237 fp.write(util.tonativeeol(samplehgrc))
2215 fp.close()
2238 fp.close()
2216
2239
2217 editor = ui.geteditor()
2240 editor = ui.geteditor()
2218 ui.system(
2241 ui.system(
2219 b"%s \"%s\"" % (editor, f),
2242 b"%s \"%s\"" % (editor, f),
2220 onerr=error.Abort,
2243 onerr=error.Abort,
2221 errprefix=_(b"edit failed"),
2244 errprefix=_(b"edit failed"),
2222 blockedtag=b'config_edit',
2245 blockedtag=b'config_edit',
2223 )
2246 )
2224 return
2247 return
2225 ui.pager(b'config')
2248 ui.pager(b'config')
2226 fm = ui.formatter(b'config', opts)
2249 fm = ui.formatter(b'config', opts)
2227 for t, f in rcutil.rccomponents():
2250 for t, f in rcutil.rccomponents():
2228 if t == b'path':
2251 if t == b'path':
2229 ui.debug(b'read config from: %s\n' % f)
2252 ui.debug(b'read config from: %s\n' % f)
2230 elif t == b'resource':
2253 elif t == b'resource':
2231 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2254 ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
2232 elif t == b'items':
2255 elif t == b'items':
2233 # Don't print anything for 'items'.
2256 # Don't print anything for 'items'.
2234 pass
2257 pass
2235 else:
2258 else:
2236 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2259 raise error.ProgrammingError(b'unknown rctype: %s' % t)
2237 untrusted = bool(opts.get(b'untrusted'))
2260 untrusted = bool(opts.get(b'untrusted'))
2238
2261
2239 selsections = selentries = []
2262 selsections = selentries = []
2240 if values:
2263 if values:
2241 selsections = [v for v in values if b'.' not in v]
2264 selsections = [v for v in values if b'.' not in v]
2242 selentries = [v for v in values if b'.' in v]
2265 selentries = [v for v in values if b'.' in v]
2243 uniquesel = len(selentries) == 1 and not selsections
2266 uniquesel = len(selentries) == 1 and not selsections
2244 selsections = set(selsections)
2267 selsections = set(selsections)
2245 selentries = set(selentries)
2268 selentries = set(selentries)
2246
2269
2247 matched = False
2270 matched = False
2248 for section, name, value in ui.walkconfig(untrusted=untrusted):
2271 for section, name, value in ui.walkconfig(untrusted=untrusted):
2249 source = ui.configsource(section, name, untrusted)
2272 source = ui.configsource(section, name, untrusted)
2250 value = pycompat.bytestr(value)
2273 value = pycompat.bytestr(value)
2251 defaultvalue = ui.configdefault(section, name)
2274 defaultvalue = ui.configdefault(section, name)
2252 if fm.isplain():
2275 if fm.isplain():
2253 source = source or b'none'
2276 source = source or b'none'
2254 value = value.replace(b'\n', b'\\n')
2277 value = value.replace(b'\n', b'\\n')
2255 entryname = section + b'.' + name
2278 entryname = section + b'.' + name
2256 if values and not (section in selsections or entryname in selentries):
2279 if values and not (section in selsections or entryname in selentries):
2257 continue
2280 continue
2258 fm.startitem()
2281 fm.startitem()
2259 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2282 fm.condwrite(ui.debugflag, b'source', b'%s: ', source)
2260 if uniquesel:
2283 if uniquesel:
2261 fm.data(name=entryname)
2284 fm.data(name=entryname)
2262 fm.write(b'value', b'%s\n', value)
2285 fm.write(b'value', b'%s\n', value)
2263 else:
2286 else:
2264 fm.write(b'name value', b'%s=%s\n', entryname, value)
2287 fm.write(b'name value', b'%s=%s\n', entryname, value)
2265 if formatter.isprintable(defaultvalue):
2288 if formatter.isprintable(defaultvalue):
2266 fm.data(defaultvalue=defaultvalue)
2289 fm.data(defaultvalue=defaultvalue)
2267 elif isinstance(defaultvalue, list) and all(
2290 elif isinstance(defaultvalue, list) and all(
2268 formatter.isprintable(e) for e in defaultvalue
2291 formatter.isprintable(e) for e in defaultvalue
2269 ):
2292 ):
2270 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2293 fm.data(defaultvalue=fm.formatlist(defaultvalue, name=b'value'))
2271 # TODO: no idea how to process unsupported defaultvalue types
2294 # TODO: no idea how to process unsupported defaultvalue types
2272 matched = True
2295 matched = True
2273 fm.end()
2296 fm.end()
2274 if matched:
2297 if matched:
2275 return 0
2298 return 0
2276 return 1
2299 return 1
2277
2300
2278
2301
2279 @command(
2302 @command(
2280 b'continue',
2303 b'continue',
2281 dryrunopts,
2304 dryrunopts,
2282 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2305 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2283 helpbasic=True,
2306 helpbasic=True,
2284 )
2307 )
2285 def continuecmd(ui, repo, **opts):
2308 def continuecmd(ui, repo, **opts):
2286 """resumes an interrupted operation (EXPERIMENTAL)
2309 """resumes an interrupted operation (EXPERIMENTAL)
2287
2310
2288 Finishes a multistep operation like graft, histedit, rebase, merge,
2311 Finishes a multistep operation like graft, histedit, rebase, merge,
2289 and unshelve if they are in an interrupted state.
2312 and unshelve if they are in an interrupted state.
2290
2313
2291 use --dry-run/-n to dry run the command.
2314 use --dry-run/-n to dry run the command.
2292 """
2315 """
2293 dryrun = opts.get('dry_run')
2316 dryrun = opts.get('dry_run')
2294 contstate = cmdutil.getunfinishedstate(repo)
2317 contstate = cmdutil.getunfinishedstate(repo)
2295 if not contstate:
2318 if not contstate:
2296 raise error.Abort(_(b'no operation in progress'))
2319 raise error.Abort(_(b'no operation in progress'))
2297 if not contstate.continuefunc:
2320 if not contstate.continuefunc:
2298 raise error.Abort(
2321 raise error.Abort(
2299 (
2322 (
2300 _(b"%s in progress but does not support 'hg continue'")
2323 _(b"%s in progress but does not support 'hg continue'")
2301 % (contstate._opname)
2324 % (contstate._opname)
2302 ),
2325 ),
2303 hint=contstate.continuemsg(),
2326 hint=contstate.continuemsg(),
2304 )
2327 )
2305 if dryrun:
2328 if dryrun:
2306 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2329 ui.status(_(b'%s in progress, will be resumed\n') % (contstate._opname))
2307 return
2330 return
2308 return contstate.continuefunc(ui, repo)
2331 return contstate.continuefunc(ui, repo)
2309
2332
2310
2333
2311 @command(
2334 @command(
2312 b'copy|cp',
2335 b'copy|cp',
2313 [
2336 [
2314 (b'', b'forget', None, _(b'unmark a file as copied')),
2337 (b'', b'forget', None, _(b'unmark a file as copied')),
2315 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2338 (b'A', b'after', None, _(b'record a copy that has already occurred')),
2316 (
2339 (
2317 b'',
2340 b'',
2318 b'at-rev',
2341 b'at-rev',
2319 b'',
2342 b'',
2320 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2343 _(b'(un)mark copies in the given revision (EXPERIMENTAL)'),
2321 _(b'REV'),
2344 _(b'REV'),
2322 ),
2345 ),
2323 (
2346 (
2324 b'f',
2347 b'f',
2325 b'force',
2348 b'force',
2326 None,
2349 None,
2327 _(b'forcibly copy over an existing managed file'),
2350 _(b'forcibly copy over an existing managed file'),
2328 ),
2351 ),
2329 ]
2352 ]
2330 + walkopts
2353 + walkopts
2331 + dryrunopts,
2354 + dryrunopts,
2332 _(b'[OPTION]... SOURCE... DEST'),
2355 _(b'[OPTION]... SOURCE... DEST'),
2333 helpcategory=command.CATEGORY_FILE_CONTENTS,
2356 helpcategory=command.CATEGORY_FILE_CONTENTS,
2334 )
2357 )
2335 def copy(ui, repo, *pats, **opts):
2358 def copy(ui, repo, *pats, **opts):
2336 """mark files as copied for the next commit
2359 """mark files as copied for the next commit
2337
2360
2338 Mark dest as having copies of source files. If dest is a
2361 Mark dest as having copies of source files. If dest is a
2339 directory, copies are put in that directory. If dest is a file,
2362 directory, copies are put in that directory. If dest is a file,
2340 the source must be a single file.
2363 the source must be a single file.
2341
2364
2342 By default, this command copies the contents of files as they
2365 By default, this command copies the contents of files as they
2343 exist in the working directory. If invoked with -A/--after, the
2366 exist in the working directory. If invoked with -A/--after, the
2344 operation is recorded, but no copying is performed.
2367 operation is recorded, but no copying is performed.
2345
2368
2346 To undo marking a file as copied, use --forget. With that option,
2369 To undo marking a file as copied, use --forget. With that option,
2347 all given (positional) arguments are unmarked as copies. The destination
2370 all given (positional) arguments are unmarked as copies. The destination
2348 file(s) will be left in place (still tracked).
2371 file(s) will be left in place (still tracked).
2349
2372
2350 This command takes effect with the next commit by default.
2373 This command takes effect with the next commit by default.
2351
2374
2352 Returns 0 on success, 1 if errors are encountered.
2375 Returns 0 on success, 1 if errors are encountered.
2353 """
2376 """
2354 opts = pycompat.byteskwargs(opts)
2377 opts = pycompat.byteskwargs(opts)
2355 with repo.wlock():
2378 with repo.wlock():
2356 return cmdutil.copy(ui, repo, pats, opts)
2379 return cmdutil.copy(ui, repo, pats, opts)
2357
2380
2358
2381
2359 @command(
2382 @command(
2360 b'debugcommands',
2383 b'debugcommands',
2361 [],
2384 [],
2362 _(b'[COMMAND]'),
2385 _(b'[COMMAND]'),
2363 helpcategory=command.CATEGORY_HELP,
2386 helpcategory=command.CATEGORY_HELP,
2364 norepo=True,
2387 norepo=True,
2365 )
2388 )
2366 def debugcommands(ui, cmd=b'', *args):
2389 def debugcommands(ui, cmd=b'', *args):
2367 """list all available commands and options"""
2390 """list all available commands and options"""
2368 for cmd, vals in sorted(pycompat.iteritems(table)):
2391 for cmd, vals in sorted(pycompat.iteritems(table)):
2369 cmd = cmd.split(b'|')[0]
2392 cmd = cmd.split(b'|')[0]
2370 opts = b', '.join([i[1] for i in vals[1]])
2393 opts = b', '.join([i[1] for i in vals[1]])
2371 ui.write(b'%s: %s\n' % (cmd, opts))
2394 ui.write(b'%s: %s\n' % (cmd, opts))
2372
2395
2373
2396
2374 @command(
2397 @command(
2375 b'debugcomplete',
2398 b'debugcomplete',
2376 [(b'o', b'options', None, _(b'show the command options'))],
2399 [(b'o', b'options', None, _(b'show the command options'))],
2377 _(b'[-o] CMD'),
2400 _(b'[-o] CMD'),
2378 helpcategory=command.CATEGORY_HELP,
2401 helpcategory=command.CATEGORY_HELP,
2379 norepo=True,
2402 norepo=True,
2380 )
2403 )
2381 def debugcomplete(ui, cmd=b'', **opts):
2404 def debugcomplete(ui, cmd=b'', **opts):
2382 """returns the completion list associated with the given command"""
2405 """returns the completion list associated with the given command"""
2383
2406
2384 if opts.get('options'):
2407 if opts.get('options'):
2385 options = []
2408 options = []
2386 otables = [globalopts]
2409 otables = [globalopts]
2387 if cmd:
2410 if cmd:
2388 aliases, entry = cmdutil.findcmd(cmd, table, False)
2411 aliases, entry = cmdutil.findcmd(cmd, table, False)
2389 otables.append(entry[1])
2412 otables.append(entry[1])
2390 for t in otables:
2413 for t in otables:
2391 for o in t:
2414 for o in t:
2392 if b"(DEPRECATED)" in o[3]:
2415 if b"(DEPRECATED)" in o[3]:
2393 continue
2416 continue
2394 if o[0]:
2417 if o[0]:
2395 options.append(b'-%s' % o[0])
2418 options.append(b'-%s' % o[0])
2396 options.append(b'--%s' % o[1])
2419 options.append(b'--%s' % o[1])
2397 ui.write(b"%s\n" % b"\n".join(options))
2420 ui.write(b"%s\n" % b"\n".join(options))
2398 return
2421 return
2399
2422
2400 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2423 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2401 if ui.verbose:
2424 if ui.verbose:
2402 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2425 cmdlist = [b' '.join(c[0]) for c in cmdlist.values()]
2403 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2426 ui.write(b"%s\n" % b"\n".join(sorted(cmdlist)))
2404
2427
2405
2428
2406 @command(
2429 @command(
2407 b'diff',
2430 b'diff',
2408 [
2431 [
2409 (b'r', b'rev', [], _(b'revision'), _(b'REV')),
2432 (b'r', b'rev', [], _(b'revision'), _(b'REV')),
2410 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2433 (b'c', b'change', b'', _(b'change made by revision'), _(b'REV')),
2411 ]
2434 ]
2412 + diffopts
2435 + diffopts
2413 + diffopts2
2436 + diffopts2
2414 + walkopts
2437 + walkopts
2415 + subrepoopts,
2438 + subrepoopts,
2416 _(b'[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2439 _(b'[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2417 helpcategory=command.CATEGORY_FILE_CONTENTS,
2440 helpcategory=command.CATEGORY_FILE_CONTENTS,
2418 helpbasic=True,
2441 helpbasic=True,
2419 inferrepo=True,
2442 inferrepo=True,
2420 intents={INTENT_READONLY},
2443 intents={INTENT_READONLY},
2421 )
2444 )
2422 def diff(ui, repo, *pats, **opts):
2445 def diff(ui, repo, *pats, **opts):
2423 """diff repository (or selected files)
2446 """diff repository (or selected files)
2424
2447
2425 Show differences between revisions for the specified files.
2448 Show differences between revisions for the specified files.
2426
2449
2427 Differences between files are shown using the unified diff format.
2450 Differences between files are shown using the unified diff format.
2428
2451
2429 .. note::
2452 .. note::
2430
2453
2431 :hg:`diff` may generate unexpected results for merges, as it will
2454 :hg:`diff` may generate unexpected results for merges, as it will
2432 default to comparing against the working directory's first
2455 default to comparing against the working directory's first
2433 parent changeset if no revisions are specified.
2456 parent changeset if no revisions are specified.
2434
2457
2435 When two revision arguments are given, then changes are shown
2458 When two revision arguments are given, then changes are shown
2436 between those revisions. If only one revision is specified then
2459 between those revisions. If only one revision is specified then
2437 that revision is compared to the working directory, and, when no
2460 that revision is compared to the working directory, and, when no
2438 revisions are specified, the working directory files are compared
2461 revisions are specified, the working directory files are compared
2439 to its first parent.
2462 to its first parent.
2440
2463
2441 Alternatively you can specify -c/--change with a revision to see
2464 Alternatively you can specify -c/--change with a revision to see
2442 the changes in that changeset relative to its first parent.
2465 the changes in that changeset relative to its first parent.
2443
2466
2444 Without the -a/--text option, diff will avoid generating diffs of
2467 Without the -a/--text option, diff will avoid generating diffs of
2445 files it detects as binary. With -a, diff will generate a diff
2468 files it detects as binary. With -a, diff will generate a diff
2446 anyway, probably with undesirable results.
2469 anyway, probably with undesirable results.
2447
2470
2448 Use the -g/--git option to generate diffs in the git extended diff
2471 Use the -g/--git option to generate diffs in the git extended diff
2449 format. For more information, read :hg:`help diffs`.
2472 format. For more information, read :hg:`help diffs`.
2450
2473
2451 .. container:: verbose
2474 .. container:: verbose
2452
2475
2453 Examples:
2476 Examples:
2454
2477
2455 - compare a file in the current working directory to its parent::
2478 - compare a file in the current working directory to its parent::
2456
2479
2457 hg diff foo.c
2480 hg diff foo.c
2458
2481
2459 - compare two historical versions of a directory, with rename info::
2482 - compare two historical versions of a directory, with rename info::
2460
2483
2461 hg diff --git -r 1.0:1.2 lib/
2484 hg diff --git -r 1.0:1.2 lib/
2462
2485
2463 - get change stats relative to the last change on some date::
2486 - get change stats relative to the last change on some date::
2464
2487
2465 hg diff --stat -r "date('may 2')"
2488 hg diff --stat -r "date('may 2')"
2466
2489
2467 - diff all newly-added files that contain a keyword::
2490 - diff all newly-added files that contain a keyword::
2468
2491
2469 hg diff "set:added() and grep(GNU)"
2492 hg diff "set:added() and grep(GNU)"
2470
2493
2471 - compare a revision and its parents::
2494 - compare a revision and its parents::
2472
2495
2473 hg diff -c 9353 # compare against first parent
2496 hg diff -c 9353 # compare against first parent
2474 hg diff -r 9353^:9353 # same using revset syntax
2497 hg diff -r 9353^:9353 # same using revset syntax
2475 hg diff -r 9353^2:9353 # compare against the second parent
2498 hg diff -r 9353^2:9353 # compare against the second parent
2476
2499
2477 Returns 0 on success.
2500 Returns 0 on success.
2478 """
2501 """
2479
2502
2480 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2503 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
2481 opts = pycompat.byteskwargs(opts)
2504 opts = pycompat.byteskwargs(opts)
2482 revs = opts.get(b'rev')
2505 revs = opts.get(b'rev')
2483 change = opts.get(b'change')
2506 change = opts.get(b'change')
2484 stat = opts.get(b'stat')
2507 stat = opts.get(b'stat')
2485 reverse = opts.get(b'reverse')
2508 reverse = opts.get(b'reverse')
2486
2509
2487 if change:
2510 if change:
2488 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2511 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
2489 ctx2 = scmutil.revsingle(repo, change, None)
2512 ctx2 = scmutil.revsingle(repo, change, None)
2490 ctx1 = ctx2.p1()
2513 ctx1 = ctx2.p1()
2491 else:
2514 else:
2492 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2515 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
2493 ctx1, ctx2 = scmutil.revpair(repo, revs)
2516 ctx1, ctx2 = scmutil.revpair(repo, revs)
2494
2517
2495 if reverse:
2518 if reverse:
2496 ctxleft = ctx2
2519 ctxleft = ctx2
2497 ctxright = ctx1
2520 ctxright = ctx1
2498 else:
2521 else:
2499 ctxleft = ctx1
2522 ctxleft = ctx1
2500 ctxright = ctx2
2523 ctxright = ctx2
2501
2524
2502 diffopts = patch.diffallopts(ui, opts)
2525 diffopts = patch.diffallopts(ui, opts)
2503 m = scmutil.match(ctx2, pats, opts)
2526 m = scmutil.match(ctx2, pats, opts)
2504 m = repo.narrowmatch(m)
2527 m = repo.narrowmatch(m)
2505 ui.pager(b'diff')
2528 ui.pager(b'diff')
2506 logcmdutil.diffordiffstat(
2529 logcmdutil.diffordiffstat(
2507 ui,
2530 ui,
2508 repo,
2531 repo,
2509 diffopts,
2532 diffopts,
2510 ctxleft,
2533 ctxleft,
2511 ctxright,
2534 ctxright,
2512 m,
2535 m,
2513 stat=stat,
2536 stat=stat,
2514 listsubrepos=opts.get(b'subrepos'),
2537 listsubrepos=opts.get(b'subrepos'),
2515 root=opts.get(b'root'),
2538 root=opts.get(b'root'),
2516 )
2539 )
2517
2540
2518
2541
2519 @command(
2542 @command(
2520 b'export',
2543 b'export',
2521 [
2544 [
2522 (
2545 (
2523 b'B',
2546 b'B',
2524 b'bookmark',
2547 b'bookmark',
2525 b'',
2548 b'',
2526 _(b'export changes only reachable by given bookmark'),
2549 _(b'export changes only reachable by given bookmark'),
2527 _(b'BOOKMARK'),
2550 _(b'BOOKMARK'),
2528 ),
2551 ),
2529 (
2552 (
2530 b'o',
2553 b'o',
2531 b'output',
2554 b'output',
2532 b'',
2555 b'',
2533 _(b'print output to file with formatted name'),
2556 _(b'print output to file with formatted name'),
2534 _(b'FORMAT'),
2557 _(b'FORMAT'),
2535 ),
2558 ),
2536 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2559 (b'', b'switch-parent', None, _(b'diff against the second parent')),
2537 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2560 (b'r', b'rev', [], _(b'revisions to export'), _(b'REV')),
2538 ]
2561 ]
2539 + diffopts
2562 + diffopts
2540 + formatteropts,
2563 + formatteropts,
2541 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2564 _(b'[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2542 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2565 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2543 helpbasic=True,
2566 helpbasic=True,
2544 intents={INTENT_READONLY},
2567 intents={INTENT_READONLY},
2545 )
2568 )
2546 def export(ui, repo, *changesets, **opts):
2569 def export(ui, repo, *changesets, **opts):
2547 """dump the header and diffs for one or more changesets
2570 """dump the header and diffs for one or more changesets
2548
2571
2549 Print the changeset header and diffs for one or more revisions.
2572 Print the changeset header and diffs for one or more revisions.
2550 If no revision is given, the parent of the working directory is used.
2573 If no revision is given, the parent of the working directory is used.
2551
2574
2552 The information shown in the changeset header is: author, date,
2575 The information shown in the changeset header is: author, date,
2553 branch name (if non-default), changeset hash, parent(s) and commit
2576 branch name (if non-default), changeset hash, parent(s) and commit
2554 comment.
2577 comment.
2555
2578
2556 .. note::
2579 .. note::
2557
2580
2558 :hg:`export` may generate unexpected diff output for merge
2581 :hg:`export` may generate unexpected diff output for merge
2559 changesets, as it will compare the merge changeset against its
2582 changesets, as it will compare the merge changeset against its
2560 first parent only.
2583 first parent only.
2561
2584
2562 Output may be to a file, in which case the name of the file is
2585 Output may be to a file, in which case the name of the file is
2563 given using a template string. See :hg:`help templates`. In addition
2586 given using a template string. See :hg:`help templates`. In addition
2564 to the common template keywords, the following formatting rules are
2587 to the common template keywords, the following formatting rules are
2565 supported:
2588 supported:
2566
2589
2567 :``%%``: literal "%" character
2590 :``%%``: literal "%" character
2568 :``%H``: changeset hash (40 hexadecimal digits)
2591 :``%H``: changeset hash (40 hexadecimal digits)
2569 :``%N``: number of patches being generated
2592 :``%N``: number of patches being generated
2570 :``%R``: changeset revision number
2593 :``%R``: changeset revision number
2571 :``%b``: basename of the exporting repository
2594 :``%b``: basename of the exporting repository
2572 :``%h``: short-form changeset hash (12 hexadecimal digits)
2595 :``%h``: short-form changeset hash (12 hexadecimal digits)
2573 :``%m``: first line of the commit message (only alphanumeric characters)
2596 :``%m``: first line of the commit message (only alphanumeric characters)
2574 :``%n``: zero-padded sequence number, starting at 1
2597 :``%n``: zero-padded sequence number, starting at 1
2575 :``%r``: zero-padded changeset revision number
2598 :``%r``: zero-padded changeset revision number
2576 :``\\``: literal "\\" character
2599 :``\\``: literal "\\" character
2577
2600
2578 Without the -a/--text option, export will avoid generating diffs
2601 Without the -a/--text option, export will avoid generating diffs
2579 of files it detects as binary. With -a, export will generate a
2602 of files it detects as binary. With -a, export will generate a
2580 diff anyway, probably with undesirable results.
2603 diff anyway, probably with undesirable results.
2581
2604
2582 With -B/--bookmark changesets reachable by the given bookmark are
2605 With -B/--bookmark changesets reachable by the given bookmark are
2583 selected.
2606 selected.
2584
2607
2585 Use the -g/--git option to generate diffs in the git extended diff
2608 Use the -g/--git option to generate diffs in the git extended diff
2586 format. See :hg:`help diffs` for more information.
2609 format. See :hg:`help diffs` for more information.
2587
2610
2588 With the --switch-parent option, the diff will be against the
2611 With the --switch-parent option, the diff will be against the
2589 second parent. It can be useful to review a merge.
2612 second parent. It can be useful to review a merge.
2590
2613
2591 .. container:: verbose
2614 .. container:: verbose
2592
2615
2593 Template:
2616 Template:
2594
2617
2595 The following keywords are supported in addition to the common template
2618 The following keywords are supported in addition to the common template
2596 keywords and functions. See also :hg:`help templates`.
2619 keywords and functions. See also :hg:`help templates`.
2597
2620
2598 :diff: String. Diff content.
2621 :diff: String. Diff content.
2599 :parents: List of strings. Parent nodes of the changeset.
2622 :parents: List of strings. Parent nodes of the changeset.
2600
2623
2601 Examples:
2624 Examples:
2602
2625
2603 - use export and import to transplant a bugfix to the current
2626 - use export and import to transplant a bugfix to the current
2604 branch::
2627 branch::
2605
2628
2606 hg export -r 9353 | hg import -
2629 hg export -r 9353 | hg import -
2607
2630
2608 - export all the changesets between two revisions to a file with
2631 - export all the changesets between two revisions to a file with
2609 rename information::
2632 rename information::
2610
2633
2611 hg export --git -r 123:150 > changes.txt
2634 hg export --git -r 123:150 > changes.txt
2612
2635
2613 - split outgoing changes into a series of patches with
2636 - split outgoing changes into a series of patches with
2614 descriptive names::
2637 descriptive names::
2615
2638
2616 hg export -r "outgoing()" -o "%n-%m.patch"
2639 hg export -r "outgoing()" -o "%n-%m.patch"
2617
2640
2618 Returns 0 on success.
2641 Returns 0 on success.
2619 """
2642 """
2620 opts = pycompat.byteskwargs(opts)
2643 opts = pycompat.byteskwargs(opts)
2621 bookmark = opts.get(b'bookmark')
2644 bookmark = opts.get(b'bookmark')
2622 changesets += tuple(opts.get(b'rev', []))
2645 changesets += tuple(opts.get(b'rev', []))
2623
2646
2624 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2647 cmdutil.check_at_most_one_arg(opts, b'rev', b'bookmark')
2625
2648
2626 if bookmark:
2649 if bookmark:
2627 if bookmark not in repo._bookmarks:
2650 if bookmark not in repo._bookmarks:
2628 raise error.Abort(_(b"bookmark '%s' not found") % bookmark)
2651 raise error.Abort(_(b"bookmark '%s' not found") % bookmark)
2629
2652
2630 revs = scmutil.bookmarkrevs(repo, bookmark)
2653 revs = scmutil.bookmarkrevs(repo, bookmark)
2631 else:
2654 else:
2632 if not changesets:
2655 if not changesets:
2633 changesets = [b'.']
2656 changesets = [b'.']
2634
2657
2635 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2658 repo = scmutil.unhidehashlikerevs(repo, changesets, b'nowarn')
2636 revs = scmutil.revrange(repo, changesets)
2659 revs = scmutil.revrange(repo, changesets)
2637
2660
2638 if not revs:
2661 if not revs:
2639 raise error.Abort(_(b"export requires at least one changeset"))
2662 raise error.Abort(_(b"export requires at least one changeset"))
2640 if len(revs) > 1:
2663 if len(revs) > 1:
2641 ui.note(_(b'exporting patches:\n'))
2664 ui.note(_(b'exporting patches:\n'))
2642 else:
2665 else:
2643 ui.note(_(b'exporting patch:\n'))
2666 ui.note(_(b'exporting patch:\n'))
2644
2667
2645 fntemplate = opts.get(b'output')
2668 fntemplate = opts.get(b'output')
2646 if cmdutil.isstdiofilename(fntemplate):
2669 if cmdutil.isstdiofilename(fntemplate):
2647 fntemplate = b''
2670 fntemplate = b''
2648
2671
2649 if fntemplate:
2672 if fntemplate:
2650 fm = formatter.nullformatter(ui, b'export', opts)
2673 fm = formatter.nullformatter(ui, b'export', opts)
2651 else:
2674 else:
2652 ui.pager(b'export')
2675 ui.pager(b'export')
2653 fm = ui.formatter(b'export', opts)
2676 fm = ui.formatter(b'export', opts)
2654 with fm:
2677 with fm:
2655 cmdutil.export(
2678 cmdutil.export(
2656 repo,
2679 repo,
2657 revs,
2680 revs,
2658 fm,
2681 fm,
2659 fntemplate=fntemplate,
2682 fntemplate=fntemplate,
2660 switch_parent=opts.get(b'switch_parent'),
2683 switch_parent=opts.get(b'switch_parent'),
2661 opts=patch.diffallopts(ui, opts),
2684 opts=patch.diffallopts(ui, opts),
2662 )
2685 )
2663
2686
2664
2687
2665 @command(
2688 @command(
2666 b'files',
2689 b'files',
2667 [
2690 [
2668 (
2691 (
2669 b'r',
2692 b'r',
2670 b'rev',
2693 b'rev',
2671 b'',
2694 b'',
2672 _(b'search the repository as it is in REV'),
2695 _(b'search the repository as it is in REV'),
2673 _(b'REV'),
2696 _(b'REV'),
2674 ),
2697 ),
2675 (
2698 (
2676 b'0',
2699 b'0',
2677 b'print0',
2700 b'print0',
2678 None,
2701 None,
2679 _(b'end filenames with NUL, for use with xargs'),
2702 _(b'end filenames with NUL, for use with xargs'),
2680 ),
2703 ),
2681 ]
2704 ]
2682 + walkopts
2705 + walkopts
2683 + formatteropts
2706 + formatteropts
2684 + subrepoopts,
2707 + subrepoopts,
2685 _(b'[OPTION]... [FILE]...'),
2708 _(b'[OPTION]... [FILE]...'),
2686 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2709 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2687 intents={INTENT_READONLY},
2710 intents={INTENT_READONLY},
2688 )
2711 )
2689 def files(ui, repo, *pats, **opts):
2712 def files(ui, repo, *pats, **opts):
2690 """list tracked files
2713 """list tracked files
2691
2714
2692 Print files under Mercurial control in the working directory or
2715 Print files under Mercurial control in the working directory or
2693 specified revision for given files (excluding removed files).
2716 specified revision for given files (excluding removed files).
2694 Files can be specified as filenames or filesets.
2717 Files can be specified as filenames or filesets.
2695
2718
2696 If no files are given to match, this command prints the names
2719 If no files are given to match, this command prints the names
2697 of all files under Mercurial control.
2720 of all files under Mercurial control.
2698
2721
2699 .. container:: verbose
2722 .. container:: verbose
2700
2723
2701 Template:
2724 Template:
2702
2725
2703 The following keywords are supported in addition to the common template
2726 The following keywords are supported in addition to the common template
2704 keywords and functions. See also :hg:`help templates`.
2727 keywords and functions. See also :hg:`help templates`.
2705
2728
2706 :flags: String. Character denoting file's symlink and executable bits.
2729 :flags: String. Character denoting file's symlink and executable bits.
2707 :path: String. Repository-absolute path of the file.
2730 :path: String. Repository-absolute path of the file.
2708 :size: Integer. Size of the file in bytes.
2731 :size: Integer. Size of the file in bytes.
2709
2732
2710 Examples:
2733 Examples:
2711
2734
2712 - list all files under the current directory::
2735 - list all files under the current directory::
2713
2736
2714 hg files .
2737 hg files .
2715
2738
2716 - shows sizes and flags for current revision::
2739 - shows sizes and flags for current revision::
2717
2740
2718 hg files -vr .
2741 hg files -vr .
2719
2742
2720 - list all files named README::
2743 - list all files named README::
2721
2744
2722 hg files -I "**/README"
2745 hg files -I "**/README"
2723
2746
2724 - list all binary files::
2747 - list all binary files::
2725
2748
2726 hg files "set:binary()"
2749 hg files "set:binary()"
2727
2750
2728 - find files containing a regular expression::
2751 - find files containing a regular expression::
2729
2752
2730 hg files "set:grep('bob')"
2753 hg files "set:grep('bob')"
2731
2754
2732 - search tracked file contents with xargs and grep::
2755 - search tracked file contents with xargs and grep::
2733
2756
2734 hg files -0 | xargs -0 grep foo
2757 hg files -0 | xargs -0 grep foo
2735
2758
2736 See :hg:`help patterns` and :hg:`help filesets` for more information
2759 See :hg:`help patterns` and :hg:`help filesets` for more information
2737 on specifying file patterns.
2760 on specifying file patterns.
2738
2761
2739 Returns 0 if a match is found, 1 otherwise.
2762 Returns 0 if a match is found, 1 otherwise.
2740
2763
2741 """
2764 """
2742
2765
2743 opts = pycompat.byteskwargs(opts)
2766 opts = pycompat.byteskwargs(opts)
2744 rev = opts.get(b'rev')
2767 rev = opts.get(b'rev')
2745 if rev:
2768 if rev:
2746 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2769 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
2747 ctx = scmutil.revsingle(repo, rev, None)
2770 ctx = scmutil.revsingle(repo, rev, None)
2748
2771
2749 end = b'\n'
2772 end = b'\n'
2750 if opts.get(b'print0'):
2773 if opts.get(b'print0'):
2751 end = b'\0'
2774 end = b'\0'
2752 fmt = b'%s' + end
2775 fmt = b'%s' + end
2753
2776
2754 m = scmutil.match(ctx, pats, opts)
2777 m = scmutil.match(ctx, pats, opts)
2755 ui.pager(b'files')
2778 ui.pager(b'files')
2756 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2779 uipathfn = scmutil.getuipathfn(ctx.repo(), legacyrelativevalue=True)
2757 with ui.formatter(b'files', opts) as fm:
2780 with ui.formatter(b'files', opts) as fm:
2758 return cmdutil.files(
2781 return cmdutil.files(
2759 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2782 ui, ctx, m, uipathfn, fm, fmt, opts.get(b'subrepos')
2760 )
2783 )
2761
2784
2762
2785
2763 @command(
2786 @command(
2764 b'forget',
2787 b'forget',
2765 [(b'i', b'interactive', None, _(b'use interactive mode')),]
2788 [(b'i', b'interactive', None, _(b'use interactive mode')),]
2766 + walkopts
2789 + walkopts
2767 + dryrunopts,
2790 + dryrunopts,
2768 _(b'[OPTION]... FILE...'),
2791 _(b'[OPTION]... FILE...'),
2769 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2792 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2770 helpbasic=True,
2793 helpbasic=True,
2771 inferrepo=True,
2794 inferrepo=True,
2772 )
2795 )
2773 def forget(ui, repo, *pats, **opts):
2796 def forget(ui, repo, *pats, **opts):
2774 """forget the specified files on the next commit
2797 """forget the specified files on the next commit
2775
2798
2776 Mark the specified files so they will no longer be tracked
2799 Mark the specified files so they will no longer be tracked
2777 after the next commit.
2800 after the next commit.
2778
2801
2779 This only removes files from the current branch, not from the
2802 This only removes files from the current branch, not from the
2780 entire project history, and it does not delete them from the
2803 entire project history, and it does not delete them from the
2781 working directory.
2804 working directory.
2782
2805
2783 To delete the file from the working directory, see :hg:`remove`.
2806 To delete the file from the working directory, see :hg:`remove`.
2784
2807
2785 To undo a forget before the next commit, see :hg:`add`.
2808 To undo a forget before the next commit, see :hg:`add`.
2786
2809
2787 .. container:: verbose
2810 .. container:: verbose
2788
2811
2789 Examples:
2812 Examples:
2790
2813
2791 - forget newly-added binary files::
2814 - forget newly-added binary files::
2792
2815
2793 hg forget "set:added() and binary()"
2816 hg forget "set:added() and binary()"
2794
2817
2795 - forget files that would be excluded by .hgignore::
2818 - forget files that would be excluded by .hgignore::
2796
2819
2797 hg forget "set:hgignore()"
2820 hg forget "set:hgignore()"
2798
2821
2799 Returns 0 on success.
2822 Returns 0 on success.
2800 """
2823 """
2801
2824
2802 opts = pycompat.byteskwargs(opts)
2825 opts = pycompat.byteskwargs(opts)
2803 if not pats:
2826 if not pats:
2804 raise error.Abort(_(b'no files specified'))
2827 raise error.Abort(_(b'no files specified'))
2805
2828
2806 m = scmutil.match(repo[None], pats, opts)
2829 m = scmutil.match(repo[None], pats, opts)
2807 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2830 dryrun, interactive = opts.get(b'dry_run'), opts.get(b'interactive')
2808 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2831 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
2809 rejected = cmdutil.forget(
2832 rejected = cmdutil.forget(
2810 ui,
2833 ui,
2811 repo,
2834 repo,
2812 m,
2835 m,
2813 prefix=b"",
2836 prefix=b"",
2814 uipathfn=uipathfn,
2837 uipathfn=uipathfn,
2815 explicitonly=False,
2838 explicitonly=False,
2816 dryrun=dryrun,
2839 dryrun=dryrun,
2817 interactive=interactive,
2840 interactive=interactive,
2818 )[0]
2841 )[0]
2819 return rejected and 1 or 0
2842 return rejected and 1 or 0
2820
2843
2821
2844
2822 @command(
2845 @command(
2823 b'graft',
2846 b'graft',
2824 [
2847 [
2825 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2848 (b'r', b'rev', [], _(b'revisions to graft'), _(b'REV')),
2826 (
2849 (
2827 b'',
2850 b'',
2828 b'base',
2851 b'base',
2829 b'',
2852 b'',
2830 _(b'base revision when doing the graft merge (ADVANCED)'),
2853 _(b'base revision when doing the graft merge (ADVANCED)'),
2831 _(b'REV'),
2854 _(b'REV'),
2832 ),
2855 ),
2833 (b'c', b'continue', False, _(b'resume interrupted graft')),
2856 (b'c', b'continue', False, _(b'resume interrupted graft')),
2834 (b'', b'stop', False, _(b'stop interrupted graft')),
2857 (b'', b'stop', False, _(b'stop interrupted graft')),
2835 (b'', b'abort', False, _(b'abort interrupted graft')),
2858 (b'', b'abort', False, _(b'abort interrupted graft')),
2836 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2859 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
2837 (b'', b'log', None, _(b'append graft info to log message')),
2860 (b'', b'log', None, _(b'append graft info to log message')),
2838 (
2861 (
2839 b'',
2862 b'',
2840 b'no-commit',
2863 b'no-commit',
2841 None,
2864 None,
2842 _(b"don't commit, just apply the changes in working directory"),
2865 _(b"don't commit, just apply the changes in working directory"),
2843 ),
2866 ),
2844 (b'f', b'force', False, _(b'force graft')),
2867 (b'f', b'force', False, _(b'force graft')),
2845 (
2868 (
2846 b'D',
2869 b'D',
2847 b'currentdate',
2870 b'currentdate',
2848 False,
2871 False,
2849 _(b'record the current date as commit date'),
2872 _(b'record the current date as commit date'),
2850 ),
2873 ),
2851 (
2874 (
2852 b'U',
2875 b'U',
2853 b'currentuser',
2876 b'currentuser',
2854 False,
2877 False,
2855 _(b'record the current user as committer'),
2878 _(b'record the current user as committer'),
2856 ),
2879 ),
2857 ]
2880 ]
2858 + commitopts2
2881 + commitopts2
2859 + mergetoolopts
2882 + mergetoolopts
2860 + dryrunopts,
2883 + dryrunopts,
2861 _(b'[OPTION]... [-r REV]... REV...'),
2884 _(b'[OPTION]... [-r REV]... REV...'),
2862 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2885 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
2863 )
2886 )
2864 def graft(ui, repo, *revs, **opts):
2887 def graft(ui, repo, *revs, **opts):
2865 '''copy changes from other branches onto the current branch
2888 '''copy changes from other branches onto the current branch
2866
2889
2867 This command uses Mercurial's merge logic to copy individual
2890 This command uses Mercurial's merge logic to copy individual
2868 changes from other branches without merging branches in the
2891 changes from other branches without merging branches in the
2869 history graph. This is sometimes known as 'backporting' or
2892 history graph. This is sometimes known as 'backporting' or
2870 'cherry-picking'. By default, graft will copy user, date, and
2893 'cherry-picking'. By default, graft will copy user, date, and
2871 description from the source changesets.
2894 description from the source changesets.
2872
2895
2873 Changesets that are ancestors of the current revision, that have
2896 Changesets that are ancestors of the current revision, that have
2874 already been grafted, or that are merges will be skipped.
2897 already been grafted, or that are merges will be skipped.
2875
2898
2876 If --log is specified, log messages will have a comment appended
2899 If --log is specified, log messages will have a comment appended
2877 of the form::
2900 of the form::
2878
2901
2879 (grafted from CHANGESETHASH)
2902 (grafted from CHANGESETHASH)
2880
2903
2881 If --force is specified, revisions will be grafted even if they
2904 If --force is specified, revisions will be grafted even if they
2882 are already ancestors of, or have been grafted to, the destination.
2905 are already ancestors of, or have been grafted to, the destination.
2883 This is useful when the revisions have since been backed out.
2906 This is useful when the revisions have since been backed out.
2884
2907
2885 If a graft merge results in conflicts, the graft process is
2908 If a graft merge results in conflicts, the graft process is
2886 interrupted so that the current merge can be manually resolved.
2909 interrupted so that the current merge can be manually resolved.
2887 Once all conflicts are addressed, the graft process can be
2910 Once all conflicts are addressed, the graft process can be
2888 continued with the -c/--continue option.
2911 continued with the -c/--continue option.
2889
2912
2890 The -c/--continue option reapplies all the earlier options.
2913 The -c/--continue option reapplies all the earlier options.
2891
2914
2892 .. container:: verbose
2915 .. container:: verbose
2893
2916
2894 The --base option exposes more of how graft internally uses merge with a
2917 The --base option exposes more of how graft internally uses merge with a
2895 custom base revision. --base can be used to specify another ancestor than
2918 custom base revision. --base can be used to specify another ancestor than
2896 the first and only parent.
2919 the first and only parent.
2897
2920
2898 The command::
2921 The command::
2899
2922
2900 hg graft -r 345 --base 234
2923 hg graft -r 345 --base 234
2901
2924
2902 is thus pretty much the same as::
2925 is thus pretty much the same as::
2903
2926
2904 hg diff -r 234 -r 345 | hg import
2927 hg diff -r 234 -r 345 | hg import
2905
2928
2906 but using merge to resolve conflicts and track moved files.
2929 but using merge to resolve conflicts and track moved files.
2907
2930
2908 The result of a merge can thus be backported as a single commit by
2931 The result of a merge can thus be backported as a single commit by
2909 specifying one of the merge parents as base, and thus effectively
2932 specifying one of the merge parents as base, and thus effectively
2910 grafting the changes from the other side.
2933 grafting the changes from the other side.
2911
2934
2912 It is also possible to collapse multiple changesets and clean up history
2935 It is also possible to collapse multiple changesets and clean up history
2913 by specifying another ancestor as base, much like rebase --collapse
2936 by specifying another ancestor as base, much like rebase --collapse
2914 --keep.
2937 --keep.
2915
2938
2916 The commit message can be tweaked after the fact using commit --amend .
2939 The commit message can be tweaked after the fact using commit --amend .
2917
2940
2918 For using non-ancestors as the base to backout changes, see the backout
2941 For using non-ancestors as the base to backout changes, see the backout
2919 command and the hidden --parent option.
2942 command and the hidden --parent option.
2920
2943
2921 .. container:: verbose
2944 .. container:: verbose
2922
2945
2923 Examples:
2946 Examples:
2924
2947
2925 - copy a single change to the stable branch and edit its description::
2948 - copy a single change to the stable branch and edit its description::
2926
2949
2927 hg update stable
2950 hg update stable
2928 hg graft --edit 9393
2951 hg graft --edit 9393
2929
2952
2930 - graft a range of changesets with one exception, updating dates::
2953 - graft a range of changesets with one exception, updating dates::
2931
2954
2932 hg graft -D "2085::2093 and not 2091"
2955 hg graft -D "2085::2093 and not 2091"
2933
2956
2934 - continue a graft after resolving conflicts::
2957 - continue a graft after resolving conflicts::
2935
2958
2936 hg graft -c
2959 hg graft -c
2937
2960
2938 - show the source of a grafted changeset::
2961 - show the source of a grafted changeset::
2939
2962
2940 hg log --debug -r .
2963 hg log --debug -r .
2941
2964
2942 - show revisions sorted by date::
2965 - show revisions sorted by date::
2943
2966
2944 hg log -r "sort(all(), date)"
2967 hg log -r "sort(all(), date)"
2945
2968
2946 - backport the result of a merge as a single commit::
2969 - backport the result of a merge as a single commit::
2947
2970
2948 hg graft -r 123 --base 123^
2971 hg graft -r 123 --base 123^
2949
2972
2950 - land a feature branch as one changeset::
2973 - land a feature branch as one changeset::
2951
2974
2952 hg up -cr default
2975 hg up -cr default
2953 hg graft -r featureX --base "ancestor('featureX', 'default')"
2976 hg graft -r featureX --base "ancestor('featureX', 'default')"
2954
2977
2955 See :hg:`help revisions` for more about specifying revisions.
2978 See :hg:`help revisions` for more about specifying revisions.
2956
2979
2957 Returns 0 on successful completion, 1 if there are unresolved files.
2980 Returns 0 on successful completion, 1 if there are unresolved files.
2958 '''
2981 '''
2959 with repo.wlock():
2982 with repo.wlock():
2960 return _dograft(ui, repo, *revs, **opts)
2983 return _dograft(ui, repo, *revs, **opts)
2961
2984
2962
2985
2963 def _dograft(ui, repo, *revs, **opts):
2986 def _dograft(ui, repo, *revs, **opts):
2964 opts = pycompat.byteskwargs(opts)
2987 opts = pycompat.byteskwargs(opts)
2965 if revs and opts.get(b'rev'):
2988 if revs and opts.get(b'rev'):
2966 ui.warn(
2989 ui.warn(
2967 _(
2990 _(
2968 b'warning: inconsistent use of --rev might give unexpected '
2991 b'warning: inconsistent use of --rev might give unexpected '
2969 b'revision ordering!\n'
2992 b'revision ordering!\n'
2970 )
2993 )
2971 )
2994 )
2972
2995
2973 revs = list(revs)
2996 revs = list(revs)
2974 revs.extend(opts.get(b'rev'))
2997 revs.extend(opts.get(b'rev'))
2975 # a dict of data to be stored in state file
2998 # a dict of data to be stored in state file
2976 statedata = {}
2999 statedata = {}
2977 # list of new nodes created by ongoing graft
3000 # list of new nodes created by ongoing graft
2978 statedata[b'newnodes'] = []
3001 statedata[b'newnodes'] = []
2979
3002
2980 cmdutil.resolvecommitoptions(ui, opts)
3003 cmdutil.resolvecommitoptions(ui, opts)
2981
3004
2982 editor = cmdutil.getcommiteditor(
3005 editor = cmdutil.getcommiteditor(
2983 editform=b'graft', **pycompat.strkwargs(opts)
3006 editform=b'graft', **pycompat.strkwargs(opts)
2984 )
3007 )
2985
3008
2986 cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
3009 cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
2987
3010
2988 cont = False
3011 cont = False
2989 if opts.get(b'no_commit'):
3012 if opts.get(b'no_commit'):
2990 cmdutil.check_incompatible_arguments(
3013 cmdutil.check_incompatible_arguments(
2991 opts,
3014 opts,
2992 b'no_commit',
3015 b'no_commit',
2993 [b'edit', b'currentuser', b'currentdate', b'log'],
3016 [b'edit', b'currentuser', b'currentdate', b'log'],
2994 )
3017 )
2995
3018
2996 graftstate = statemod.cmdstate(repo, b'graftstate')
3019 graftstate = statemod.cmdstate(repo, b'graftstate')
2997
3020
2998 if opts.get(b'stop'):
3021 if opts.get(b'stop'):
2999 cmdutil.check_incompatible_arguments(
3022 cmdutil.check_incompatible_arguments(
3000 opts,
3023 opts,
3001 b'stop',
3024 b'stop',
3002 [
3025 [
3003 b'edit',
3026 b'edit',
3004 b'log',
3027 b'log',
3005 b'user',
3028 b'user',
3006 b'date',
3029 b'date',
3007 b'currentdate',
3030 b'currentdate',
3008 b'currentuser',
3031 b'currentuser',
3009 b'rev',
3032 b'rev',
3010 ],
3033 ],
3011 )
3034 )
3012 return _stopgraft(ui, repo, graftstate)
3035 return _stopgraft(ui, repo, graftstate)
3013 elif opts.get(b'abort'):
3036 elif opts.get(b'abort'):
3014 cmdutil.check_incompatible_arguments(
3037 cmdutil.check_incompatible_arguments(
3015 opts,
3038 opts,
3016 b'abort',
3039 b'abort',
3017 [
3040 [
3018 b'edit',
3041 b'edit',
3019 b'log',
3042 b'log',
3020 b'user',
3043 b'user',
3021 b'date',
3044 b'date',
3022 b'currentdate',
3045 b'currentdate',
3023 b'currentuser',
3046 b'currentuser',
3024 b'rev',
3047 b'rev',
3025 ],
3048 ],
3026 )
3049 )
3027 return cmdutil.abortgraft(ui, repo, graftstate)
3050 return cmdutil.abortgraft(ui, repo, graftstate)
3028 elif opts.get(b'continue'):
3051 elif opts.get(b'continue'):
3029 cont = True
3052 cont = True
3030 if revs:
3053 if revs:
3031 raise error.Abort(_(b"can't specify --continue and revisions"))
3054 raise error.Abort(_(b"can't specify --continue and revisions"))
3032 # read in unfinished revisions
3055 # read in unfinished revisions
3033 if graftstate.exists():
3056 if graftstate.exists():
3034 statedata = cmdutil.readgraftstate(repo, graftstate)
3057 statedata = cmdutil.readgraftstate(repo, graftstate)
3035 if statedata.get(b'date'):
3058 if statedata.get(b'date'):
3036 opts[b'date'] = statedata[b'date']
3059 opts[b'date'] = statedata[b'date']
3037 if statedata.get(b'user'):
3060 if statedata.get(b'user'):
3038 opts[b'user'] = statedata[b'user']
3061 opts[b'user'] = statedata[b'user']
3039 if statedata.get(b'log'):
3062 if statedata.get(b'log'):
3040 opts[b'log'] = True
3063 opts[b'log'] = True
3041 if statedata.get(b'no_commit'):
3064 if statedata.get(b'no_commit'):
3042 opts[b'no_commit'] = statedata.get(b'no_commit')
3065 opts[b'no_commit'] = statedata.get(b'no_commit')
3043 if statedata.get(b'base'):
3066 if statedata.get(b'base'):
3044 opts[b'base'] = statedata.get(b'base')
3067 opts[b'base'] = statedata.get(b'base')
3045 nodes = statedata[b'nodes']
3068 nodes = statedata[b'nodes']
3046 revs = [repo[node].rev() for node in nodes]
3069 revs = [repo[node].rev() for node in nodes]
3047 else:
3070 else:
3048 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3071 cmdutil.wrongtooltocontinue(repo, _(b'graft'))
3049 else:
3072 else:
3050 if not revs:
3073 if not revs:
3051 raise error.Abort(_(b'no revisions specified'))
3074 raise error.Abort(_(b'no revisions specified'))
3052 cmdutil.checkunfinished(repo)
3075 cmdutil.checkunfinished(repo)
3053 cmdutil.bailifchanged(repo)
3076 cmdutil.bailifchanged(repo)
3054 revs = scmutil.revrange(repo, revs)
3077 revs = scmutil.revrange(repo, revs)
3055
3078
3056 skipped = set()
3079 skipped = set()
3057 basectx = None
3080 basectx = None
3058 if opts.get(b'base'):
3081 if opts.get(b'base'):
3059 basectx = scmutil.revsingle(repo, opts[b'base'], None)
3082 basectx = scmutil.revsingle(repo, opts[b'base'], None)
3060 if basectx is None:
3083 if basectx is None:
3061 # check for merges
3084 # check for merges
3062 for rev in repo.revs(b'%ld and merge()', revs):
3085 for rev in repo.revs(b'%ld and merge()', revs):
3063 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3086 ui.warn(_(b'skipping ungraftable merge revision %d\n') % rev)
3064 skipped.add(rev)
3087 skipped.add(rev)
3065 revs = [r for r in revs if r not in skipped]
3088 revs = [r for r in revs if r not in skipped]
3066 if not revs:
3089 if not revs:
3067 return -1
3090 return -1
3068 if basectx is not None and len(revs) != 1:
3091 if basectx is not None and len(revs) != 1:
3069 raise error.Abort(_(b'only one revision allowed with --base '))
3092 raise error.Abort(_(b'only one revision allowed with --base '))
3070
3093
3071 # Don't check in the --continue case, in effect retaining --force across
3094 # Don't check in the --continue case, in effect retaining --force across
3072 # --continues. That's because without --force, any revisions we decided to
3095 # --continues. That's because without --force, any revisions we decided to
3073 # skip would have been filtered out here, so they wouldn't have made their
3096 # skip would have been filtered out here, so they wouldn't have made their
3074 # way to the graftstate. With --force, any revisions we would have otherwise
3097 # way to the graftstate. With --force, any revisions we would have otherwise
3075 # skipped would not have been filtered out, and if they hadn't been applied
3098 # skipped would not have been filtered out, and if they hadn't been applied
3076 # already, they'd have been in the graftstate.
3099 # already, they'd have been in the graftstate.
3077 if not (cont or opts.get(b'force')) and basectx is None:
3100 if not (cont or opts.get(b'force')) and basectx is None:
3078 # check for ancestors of dest branch
3101 # check for ancestors of dest branch
3079 ancestors = repo.revs(b'%ld & (::.)', revs)
3102 ancestors = repo.revs(b'%ld & (::.)', revs)
3080 for rev in ancestors:
3103 for rev in ancestors:
3081 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3104 ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
3082
3105
3083 revs = [r for r in revs if r not in ancestors]
3106 revs = [r for r in revs if r not in ancestors]
3084
3107
3085 if not revs:
3108 if not revs:
3086 return -1
3109 return -1
3087
3110
3088 # analyze revs for earlier grafts
3111 # analyze revs for earlier grafts
3089 ids = {}
3112 ids = {}
3090 for ctx in repo.set(b"%ld", revs):
3113 for ctx in repo.set(b"%ld", revs):
3091 ids[ctx.hex()] = ctx.rev()
3114 ids[ctx.hex()] = ctx.rev()
3092 n = ctx.extra().get(b'source')
3115 n = ctx.extra().get(b'source')
3093 if n:
3116 if n:
3094 ids[n] = ctx.rev()
3117 ids[n] = ctx.rev()
3095
3118
3096 # check ancestors for earlier grafts
3119 # check ancestors for earlier grafts
3097 ui.debug(b'scanning for duplicate grafts\n')
3120 ui.debug(b'scanning for duplicate grafts\n')
3098
3121
3099 # The only changesets we can be sure doesn't contain grafts of any
3122 # The only changesets we can be sure doesn't contain grafts of any
3100 # revs, are the ones that are common ancestors of *all* revs:
3123 # revs, are the ones that are common ancestors of *all* revs:
3101 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3124 for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
3102 ctx = repo[rev]
3125 ctx = repo[rev]
3103 n = ctx.extra().get(b'source')
3126 n = ctx.extra().get(b'source')
3104 if n in ids:
3127 if n in ids:
3105 try:
3128 try:
3106 r = repo[n].rev()
3129 r = repo[n].rev()
3107 except error.RepoLookupError:
3130 except error.RepoLookupError:
3108 r = None
3131 r = None
3109 if r in revs:
3132 if r in revs:
3110 ui.warn(
3133 ui.warn(
3111 _(
3134 _(
3112 b'skipping revision %d:%s '
3135 b'skipping revision %d:%s '
3113 b'(already grafted to %d:%s)\n'
3136 b'(already grafted to %d:%s)\n'
3114 )
3137 )
3115 % (r, repo[r], rev, ctx)
3138 % (r, repo[r], rev, ctx)
3116 )
3139 )
3117 revs.remove(r)
3140 revs.remove(r)
3118 elif ids[n] in revs:
3141 elif ids[n] in revs:
3119 if r is None:
3142 if r is None:
3120 ui.warn(
3143 ui.warn(
3121 _(
3144 _(
3122 b'skipping already grafted revision %d:%s '
3145 b'skipping already grafted revision %d:%s '
3123 b'(%d:%s also has unknown origin %s)\n'
3146 b'(%d:%s also has unknown origin %s)\n'
3124 )
3147 )
3125 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3148 % (ids[n], repo[ids[n]], rev, ctx, n[:12])
3126 )
3149 )
3127 else:
3150 else:
3128 ui.warn(
3151 ui.warn(
3129 _(
3152 _(
3130 b'skipping already grafted revision %d:%s '
3153 b'skipping already grafted revision %d:%s '
3131 b'(%d:%s also has origin %d:%s)\n'
3154 b'(%d:%s also has origin %d:%s)\n'
3132 )
3155 )
3133 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3156 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12])
3134 )
3157 )
3135 revs.remove(ids[n])
3158 revs.remove(ids[n])
3136 elif ctx.hex() in ids:
3159 elif ctx.hex() in ids:
3137 r = ids[ctx.hex()]
3160 r = ids[ctx.hex()]
3138 if r in revs:
3161 if r in revs:
3139 ui.warn(
3162 ui.warn(
3140 _(
3163 _(
3141 b'skipping already grafted revision %d:%s '
3164 b'skipping already grafted revision %d:%s '
3142 b'(was grafted from %d:%s)\n'
3165 b'(was grafted from %d:%s)\n'
3143 )
3166 )
3144 % (r, repo[r], rev, ctx)
3167 % (r, repo[r], rev, ctx)
3145 )
3168 )
3146 revs.remove(r)
3169 revs.remove(r)
3147 if not revs:
3170 if not revs:
3148 return -1
3171 return -1
3149
3172
3150 if opts.get(b'no_commit'):
3173 if opts.get(b'no_commit'):
3151 statedata[b'no_commit'] = True
3174 statedata[b'no_commit'] = True
3152 if opts.get(b'base'):
3175 if opts.get(b'base'):
3153 statedata[b'base'] = opts[b'base']
3176 statedata[b'base'] = opts[b'base']
3154 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3177 for pos, ctx in enumerate(repo.set(b"%ld", revs)):
3155 desc = b'%d:%s "%s"' % (
3178 desc = b'%d:%s "%s"' % (
3156 ctx.rev(),
3179 ctx.rev(),
3157 ctx,
3180 ctx,
3158 ctx.description().split(b'\n', 1)[0],
3181 ctx.description().split(b'\n', 1)[0],
3159 )
3182 )
3160 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3183 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3161 if names:
3184 if names:
3162 desc += b' (%s)' % b' '.join(names)
3185 desc += b' (%s)' % b' '.join(names)
3163 ui.status(_(b'grafting %s\n') % desc)
3186 ui.status(_(b'grafting %s\n') % desc)
3164 if opts.get(b'dry_run'):
3187 if opts.get(b'dry_run'):
3165 continue
3188 continue
3166
3189
3167 source = ctx.extra().get(b'source')
3190 source = ctx.extra().get(b'source')
3168 extra = {}
3191 extra = {}
3169 if source:
3192 if source:
3170 extra[b'source'] = source
3193 extra[b'source'] = source
3171 extra[b'intermediate-source'] = ctx.hex()
3194 extra[b'intermediate-source'] = ctx.hex()
3172 else:
3195 else:
3173 extra[b'source'] = ctx.hex()
3196 extra[b'source'] = ctx.hex()
3174 user = ctx.user()
3197 user = ctx.user()
3175 if opts.get(b'user'):
3198 if opts.get(b'user'):
3176 user = opts[b'user']
3199 user = opts[b'user']
3177 statedata[b'user'] = user
3200 statedata[b'user'] = user
3178 date = ctx.date()
3201 date = ctx.date()
3179 if opts.get(b'date'):
3202 if opts.get(b'date'):
3180 date = opts[b'date']
3203 date = opts[b'date']
3181 statedata[b'date'] = date
3204 statedata[b'date'] = date
3182 message = ctx.description()
3205 message = ctx.description()
3183 if opts.get(b'log'):
3206 if opts.get(b'log'):
3184 message += b'\n(grafted from %s)' % ctx.hex()
3207 message += b'\n(grafted from %s)' % ctx.hex()
3185 statedata[b'log'] = True
3208 statedata[b'log'] = True
3186
3209
3187 # we don't merge the first commit when continuing
3210 # we don't merge the first commit when continuing
3188 if not cont:
3211 if not cont:
3189 # perform the graft merge with p1(rev) as 'ancestor'
3212 # perform the graft merge with p1(rev) as 'ancestor'
3190 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3213 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
3191 base = ctx.p1() if basectx is None else basectx
3214 base = ctx.p1() if basectx is None else basectx
3192 with ui.configoverride(overrides, b'graft'):
3215 with ui.configoverride(overrides, b'graft'):
3193 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3216 stats = mergemod.graft(repo, ctx, base, [b'local', b'graft'])
3194 # report any conflicts
3217 # report any conflicts
3195 if stats.unresolvedcount > 0:
3218 if stats.unresolvedcount > 0:
3196 # write out state for --continue
3219 # write out state for --continue
3197 nodes = [repo[rev].hex() for rev in revs[pos:]]
3220 nodes = [repo[rev].hex() for rev in revs[pos:]]
3198 statedata[b'nodes'] = nodes
3221 statedata[b'nodes'] = nodes
3199 stateversion = 1
3222 stateversion = 1
3200 graftstate.save(stateversion, statedata)
3223 graftstate.save(stateversion, statedata)
3201 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3224 ui.error(_(b"abort: unresolved conflicts, can't continue\n"))
3202 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3225 ui.error(_(b"(use 'hg resolve' and 'hg graft --continue')\n"))
3203 return 1
3226 return 1
3204 else:
3227 else:
3205 cont = False
3228 cont = False
3206
3229
3207 # commit if --no-commit is false
3230 # commit if --no-commit is false
3208 if not opts.get(b'no_commit'):
3231 if not opts.get(b'no_commit'):
3209 node = repo.commit(
3232 node = repo.commit(
3210 text=message, user=user, date=date, extra=extra, editor=editor
3233 text=message, user=user, date=date, extra=extra, editor=editor
3211 )
3234 )
3212 if node is None:
3235 if node is None:
3213 ui.warn(
3236 ui.warn(
3214 _(b'note: graft of %d:%s created no changes to commit\n')
3237 _(b'note: graft of %d:%s created no changes to commit\n')
3215 % (ctx.rev(), ctx)
3238 % (ctx.rev(), ctx)
3216 )
3239 )
3217 # checking that newnodes exist because old state files won't have it
3240 # checking that newnodes exist because old state files won't have it
3218 elif statedata.get(b'newnodes') is not None:
3241 elif statedata.get(b'newnodes') is not None:
3219 statedata[b'newnodes'].append(node)
3242 statedata[b'newnodes'].append(node)
3220
3243
3221 # remove state when we complete successfully
3244 # remove state when we complete successfully
3222 if not opts.get(b'dry_run'):
3245 if not opts.get(b'dry_run'):
3223 graftstate.delete()
3246 graftstate.delete()
3224
3247
3225 return 0
3248 return 0
3226
3249
3227
3250
3228 def _stopgraft(ui, repo, graftstate):
3251 def _stopgraft(ui, repo, graftstate):
3229 """stop the interrupted graft"""
3252 """stop the interrupted graft"""
3230 if not graftstate.exists():
3253 if not graftstate.exists():
3231 raise error.Abort(_(b"no interrupted graft found"))
3254 raise error.Abort(_(b"no interrupted graft found"))
3232 pctx = repo[b'.']
3255 pctx = repo[b'.']
3233 hg.updaterepo(repo, pctx.node(), overwrite=True)
3256 hg.updaterepo(repo, pctx.node(), overwrite=True)
3234 graftstate.delete()
3257 graftstate.delete()
3235 ui.status(_(b"stopped the interrupted graft\n"))
3258 ui.status(_(b"stopped the interrupted graft\n"))
3236 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3259 ui.status(_(b"working directory is now at %s\n") % pctx.hex()[:12])
3237 return 0
3260 return 0
3238
3261
3239
3262
3240 statemod.addunfinished(
3263 statemod.addunfinished(
3241 b'graft',
3264 b'graft',
3242 fname=b'graftstate',
3265 fname=b'graftstate',
3243 clearable=True,
3266 clearable=True,
3244 stopflag=True,
3267 stopflag=True,
3245 continueflag=True,
3268 continueflag=True,
3246 abortfunc=cmdutil.hgabortgraft,
3269 abortfunc=cmdutil.hgabortgraft,
3247 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3270 cmdhint=_(b"use 'hg graft --continue' or 'hg graft --stop' to stop"),
3248 )
3271 )
3249
3272
3250
3273
3251 @command(
3274 @command(
3252 b'grep',
3275 b'grep',
3253 [
3276 [
3254 (b'0', b'print0', None, _(b'end fields with NUL')),
3277 (b'0', b'print0', None, _(b'end fields with NUL')),
3255 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3278 (b'', b'all', None, _(b'an alias to --diff (DEPRECATED)')),
3256 (
3279 (
3257 b'',
3280 b'',
3258 b'diff',
3281 b'diff',
3259 None,
3282 None,
3260 _(
3283 _(
3261 b'search revision differences for when the pattern was added '
3284 b'search revision differences for when the pattern was added '
3262 b'or removed'
3285 b'or removed'
3263 ),
3286 ),
3264 ),
3287 ),
3265 (b'a', b'text', None, _(b'treat all files as text')),
3288 (b'a', b'text', None, _(b'treat all files as text')),
3266 (
3289 (
3267 b'f',
3290 b'f',
3268 b'follow',
3291 b'follow',
3269 None,
3292 None,
3270 _(
3293 _(
3271 b'follow changeset history,'
3294 b'follow changeset history,'
3272 b' or file history across copies and renames'
3295 b' or file history across copies and renames'
3273 ),
3296 ),
3274 ),
3297 ),
3275 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3298 (b'i', b'ignore-case', None, _(b'ignore case when matching')),
3276 (
3299 (
3277 b'l',
3300 b'l',
3278 b'files-with-matches',
3301 b'files-with-matches',
3279 None,
3302 None,
3280 _(b'print only filenames and revisions that match'),
3303 _(b'print only filenames and revisions that match'),
3281 ),
3304 ),
3282 (b'n', b'line-number', None, _(b'print matching line numbers')),
3305 (b'n', b'line-number', None, _(b'print matching line numbers')),
3283 (
3306 (
3284 b'r',
3307 b'r',
3285 b'rev',
3308 b'rev',
3286 [],
3309 [],
3287 _(b'search files changed within revision range'),
3310 _(b'search files changed within revision range'),
3288 _(b'REV'),
3311 _(b'REV'),
3289 ),
3312 ),
3290 (
3313 (
3291 b'',
3314 b'',
3292 b'all-files',
3315 b'all-files',
3293 None,
3316 None,
3294 _(
3317 _(
3295 b'include all files in the changeset while grepping (DEPRECATED)'
3318 b'include all files in the changeset while grepping (DEPRECATED)'
3296 ),
3319 ),
3297 ),
3320 ),
3298 (b'u', b'user', None, _(b'list the author (long with -v)')),
3321 (b'u', b'user', None, _(b'list the author (long with -v)')),
3299 (b'd', b'date', None, _(b'list the date (short with -q)')),
3322 (b'd', b'date', None, _(b'list the date (short with -q)')),
3300 ]
3323 ]
3301 + formatteropts
3324 + formatteropts
3302 + walkopts,
3325 + walkopts,
3303 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3326 _(b'[--diff] [OPTION]... PATTERN [FILE]...'),
3304 helpcategory=command.CATEGORY_FILE_CONTENTS,
3327 helpcategory=command.CATEGORY_FILE_CONTENTS,
3305 inferrepo=True,
3328 inferrepo=True,
3306 intents={INTENT_READONLY},
3329 intents={INTENT_READONLY},
3307 )
3330 )
3308 def grep(ui, repo, pattern, *pats, **opts):
3331 def grep(ui, repo, pattern, *pats, **opts):
3309 """search for a pattern in specified files
3332 """search for a pattern in specified files
3310
3333
3311 Search the working directory or revision history for a regular
3334 Search the working directory or revision history for a regular
3312 expression in the specified files for the entire repository.
3335 expression in the specified files for the entire repository.
3313
3336
3314 By default, grep searches the repository files in the working
3337 By default, grep searches the repository files in the working
3315 directory and prints the files where it finds a match. To specify
3338 directory and prints the files where it finds a match. To specify
3316 historical revisions instead of the working directory, use the
3339 historical revisions instead of the working directory, use the
3317 --rev flag.
3340 --rev flag.
3318
3341
3319 To search instead historical revision differences that contains a
3342 To search instead historical revision differences that contains a
3320 change in match status ("-" for a match that becomes a non-match,
3343 change in match status ("-" for a match that becomes a non-match,
3321 or "+" for a non-match that becomes a match), use the --diff flag.
3344 or "+" for a non-match that becomes a match), use the --diff flag.
3322
3345
3323 PATTERN can be any Python (roughly Perl-compatible) regular
3346 PATTERN can be any Python (roughly Perl-compatible) regular
3324 expression.
3347 expression.
3325
3348
3326 If no FILEs are specified and the --rev flag isn't supplied, all
3349 If no FILEs are specified and the --rev flag isn't supplied, all
3327 files in the working directory are searched. When using the --rev
3350 files in the working directory are searched. When using the --rev
3328 flag and specifying FILEs, use the --follow argument to also
3351 flag and specifying FILEs, use the --follow argument to also
3329 follow the specified FILEs across renames and copies.
3352 follow the specified FILEs across renames and copies.
3330
3353
3331 .. container:: verbose
3354 .. container:: verbose
3332
3355
3333 Template:
3356 Template:
3334
3357
3335 The following keywords are supported in addition to the common template
3358 The following keywords are supported in addition to the common template
3336 keywords and functions. See also :hg:`help templates`.
3359 keywords and functions. See also :hg:`help templates`.
3337
3360
3338 :change: String. Character denoting insertion ``+`` or removal ``-``.
3361 :change: String. Character denoting insertion ``+`` or removal ``-``.
3339 Available if ``--diff`` is specified.
3362 Available if ``--diff`` is specified.
3340 :lineno: Integer. Line number of the match.
3363 :lineno: Integer. Line number of the match.
3341 :path: String. Repository-absolute path of the file.
3364 :path: String. Repository-absolute path of the file.
3342 :texts: List of text chunks.
3365 :texts: List of text chunks.
3343
3366
3344 And each entry of ``{texts}`` provides the following sub-keywords.
3367 And each entry of ``{texts}`` provides the following sub-keywords.
3345
3368
3346 :matched: Boolean. True if the chunk matches the specified pattern.
3369 :matched: Boolean. True if the chunk matches the specified pattern.
3347 :text: String. Chunk content.
3370 :text: String. Chunk content.
3348
3371
3349 See :hg:`help templates.operators` for the list expansion syntax.
3372 See :hg:`help templates.operators` for the list expansion syntax.
3350
3373
3351 Returns 0 if a match is found, 1 otherwise.
3374 Returns 0 if a match is found, 1 otherwise.
3352
3375
3353 """
3376 """
3354 opts = pycompat.byteskwargs(opts)
3377 opts = pycompat.byteskwargs(opts)
3355 diff = opts.get(b'all') or opts.get(b'diff')
3378 diff = opts.get(b'all') or opts.get(b'diff')
3356 if diff and opts.get(b'all_files'):
3379 if diff and opts.get(b'all_files'):
3357 raise error.Abort(_(b'--diff and --all-files are mutually exclusive'))
3380 raise error.Abort(_(b'--diff and --all-files are mutually exclusive'))
3358 if opts.get(b'all_files') is None and not diff:
3381 if opts.get(b'all_files') is None and not diff:
3359 opts[b'all_files'] = True
3382 opts[b'all_files'] = True
3360 plaingrep = (
3383 plaingrep = (
3361 opts.get(b'all_files')
3384 opts.get(b'all_files')
3362 and not opts.get(b'rev')
3385 and not opts.get(b'rev')
3363 and not opts.get(b'follow')
3386 and not opts.get(b'follow')
3364 )
3387 )
3365 all_files = opts.get(b'all_files')
3388 all_files = opts.get(b'all_files')
3366 if plaingrep:
3389 if plaingrep:
3367 opts[b'rev'] = [b'wdir()']
3390 opts[b'rev'] = [b'wdir()']
3368
3391
3369 reflags = re.M
3392 reflags = re.M
3370 if opts.get(b'ignore_case'):
3393 if opts.get(b'ignore_case'):
3371 reflags |= re.I
3394 reflags |= re.I
3372 try:
3395 try:
3373 regexp = util.re.compile(pattern, reflags)
3396 regexp = util.re.compile(pattern, reflags)
3374 except re.error as inst:
3397 except re.error as inst:
3375 ui.warn(
3398 ui.warn(
3376 _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
3399 _(b"grep: invalid match pattern: %s\n") % pycompat.bytestr(inst)
3377 )
3400 )
3378 return 1
3401 return 1
3379 sep, eol = b':', b'\n'
3402 sep, eol = b':', b'\n'
3380 if opts.get(b'print0'):
3403 if opts.get(b'print0'):
3381 sep = eol = b'\0'
3404 sep = eol = b'\0'
3382
3405
3383 getfile = util.lrucachefunc(repo.file)
3406 getfile = util.lrucachefunc(repo.file)
3384
3407
3385 def matchlines(body):
3408 def matchlines(body):
3386 begin = 0
3409 begin = 0
3387 linenum = 0
3410 linenum = 0
3388 while begin < len(body):
3411 while begin < len(body):
3389 match = regexp.search(body, begin)
3412 match = regexp.search(body, begin)
3390 if not match:
3413 if not match:
3391 break
3414 break
3392 mstart, mend = match.span()
3415 mstart, mend = match.span()
3393 linenum += body.count(b'\n', begin, mstart) + 1
3416 linenum += body.count(b'\n', begin, mstart) + 1
3394 lstart = body.rfind(b'\n', begin, mstart) + 1 or begin
3417 lstart = body.rfind(b'\n', begin, mstart) + 1 or begin
3395 begin = body.find(b'\n', mend) + 1 or len(body) + 1
3418 begin = body.find(b'\n', mend) + 1 or len(body) + 1
3396 lend = begin - 1
3419 lend = begin - 1
3397 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3420 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3398
3421
3399 class linestate(object):
3422 class linestate(object):
3400 def __init__(self, line, linenum, colstart, colend):
3423 def __init__(self, line, linenum, colstart, colend):
3401 self.line = line
3424 self.line = line
3402 self.linenum = linenum
3425 self.linenum = linenum
3403 self.colstart = colstart
3426 self.colstart = colstart
3404 self.colend = colend
3427 self.colend = colend
3405
3428
3406 def __hash__(self):
3429 def __hash__(self):
3407 return hash(self.line)
3430 return hash(self.line)
3408
3431
3409 def __eq__(self, other):
3432 def __eq__(self, other):
3410 return self.line == other.line
3433 return self.line == other.line
3411
3434
3412 def findpos(self):
3435 def findpos(self):
3413 """Iterate all (start, end) indices of matches"""
3436 """Iterate all (start, end) indices of matches"""
3414 yield self.colstart, self.colend
3437 yield self.colstart, self.colend
3415 p = self.colend
3438 p = self.colend
3416 while p < len(self.line):
3439 while p < len(self.line):
3417 m = regexp.search(self.line, p)
3440 m = regexp.search(self.line, p)
3418 if not m:
3441 if not m:
3419 break
3442 break
3420 if m.end() == p:
3443 if m.end() == p:
3421 p += 1
3444 p += 1
3422 else:
3445 else:
3423 yield m.span()
3446 yield m.span()
3424 p = m.end()
3447 p = m.end()
3425
3448
3426 matches = {}
3449 matches = {}
3427 copies = {}
3450 copies = {}
3428
3451
3429 def grepbody(fn, rev, body):
3452 def grepbody(fn, rev, body):
3430 matches[rev].setdefault(fn, [])
3453 matches[rev].setdefault(fn, [])
3431 m = matches[rev][fn]
3454 m = matches[rev][fn]
3432 if body is None:
3455 if body is None:
3433 return
3456 return
3434
3457
3435 for lnum, cstart, cend, line in matchlines(body):
3458 for lnum, cstart, cend, line in matchlines(body):
3436 s = linestate(line, lnum, cstart, cend)
3459 s = linestate(line, lnum, cstart, cend)
3437 m.append(s)
3460 m.append(s)
3438
3461
3439 def difflinestates(a, b):
3462 def difflinestates(a, b):
3440 sm = difflib.SequenceMatcher(None, a, b)
3463 sm = difflib.SequenceMatcher(None, a, b)
3441 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3464 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3442 if tag == 'insert':
3465 if tag == 'insert':
3443 for i in pycompat.xrange(blo, bhi):
3466 for i in pycompat.xrange(blo, bhi):
3444 yield (b'+', b[i])
3467 yield (b'+', b[i])
3445 elif tag == 'delete':
3468 elif tag == 'delete':
3446 for i in pycompat.xrange(alo, ahi):
3469 for i in pycompat.xrange(alo, ahi):
3447 yield (b'-', a[i])
3470 yield (b'-', a[i])
3448 elif tag == 'replace':
3471 elif tag == 'replace':
3449 for i in pycompat.xrange(alo, ahi):
3472 for i in pycompat.xrange(alo, ahi):
3450 yield (b'-', a[i])
3473 yield (b'-', a[i])
3451 for i in pycompat.xrange(blo, bhi):
3474 for i in pycompat.xrange(blo, bhi):
3452 yield (b'+', b[i])
3475 yield (b'+', b[i])
3453
3476
3454 uipathfn = scmutil.getuipathfn(repo)
3477 uipathfn = scmutil.getuipathfn(repo)
3455
3478
3456 def display(fm, fn, ctx, pstates, states):
3479 def display(fm, fn, ctx, pstates, states):
3457 rev = scmutil.intrev(ctx)
3480 rev = scmutil.intrev(ctx)
3458 if fm.isplain():
3481 if fm.isplain():
3459 formatuser = ui.shortuser
3482 formatuser = ui.shortuser
3460 else:
3483 else:
3461 formatuser = pycompat.bytestr
3484 formatuser = pycompat.bytestr
3462 if ui.quiet:
3485 if ui.quiet:
3463 datefmt = b'%Y-%m-%d'
3486 datefmt = b'%Y-%m-%d'
3464 else:
3487 else:
3465 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3488 datefmt = b'%a %b %d %H:%M:%S %Y %1%2'
3466 found = False
3489 found = False
3467
3490
3468 @util.cachefunc
3491 @util.cachefunc
3469 def binary():
3492 def binary():
3470 flog = getfile(fn)
3493 flog = getfile(fn)
3471 try:
3494 try:
3472 return stringutil.binary(flog.read(ctx.filenode(fn)))
3495 return stringutil.binary(flog.read(ctx.filenode(fn)))
3473 except error.WdirUnsupported:
3496 except error.WdirUnsupported:
3474 return ctx[fn].isbinary()
3497 return ctx[fn].isbinary()
3475
3498
3476 fieldnamemap = {b'linenumber': b'lineno'}
3499 fieldnamemap = {b'linenumber': b'lineno'}
3477 if diff:
3500 if diff:
3478 iter = difflinestates(pstates, states)
3501 iter = difflinestates(pstates, states)
3479 else:
3502 else:
3480 iter = [(b'', l) for l in states]
3503 iter = [(b'', l) for l in states]
3481 for change, l in iter:
3504 for change, l in iter:
3482 fm.startitem()
3505 fm.startitem()
3483 fm.context(ctx=ctx)
3506 fm.context(ctx=ctx)
3484 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3507 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)), path=fn)
3485 fm.plain(uipathfn(fn), label=b'grep.filename')
3508 fm.plain(uipathfn(fn), label=b'grep.filename')
3486
3509
3487 cols = [
3510 cols = [
3488 (b'rev', b'%d', rev, not plaingrep, b''),
3511 (b'rev', b'%d', rev, not plaingrep, b''),
3489 (
3512 (
3490 b'linenumber',
3513 b'linenumber',
3491 b'%d',
3514 b'%d',
3492 l.linenum,
3515 l.linenum,
3493 opts.get(b'line_number'),
3516 opts.get(b'line_number'),
3494 b'',
3517 b'',
3495 ),
3518 ),
3496 ]
3519 ]
3497 if diff:
3520 if diff:
3498 cols.append(
3521 cols.append(
3499 (
3522 (
3500 b'change',
3523 b'change',
3501 b'%s',
3524 b'%s',
3502 change,
3525 change,
3503 True,
3526 True,
3504 b'grep.inserted '
3527 b'grep.inserted '
3505 if change == b'+'
3528 if change == b'+'
3506 else b'grep.deleted ',
3529 else b'grep.deleted ',
3507 )
3530 )
3508 )
3531 )
3509 cols.extend(
3532 cols.extend(
3510 [
3533 [
3511 (
3534 (
3512 b'user',
3535 b'user',
3513 b'%s',
3536 b'%s',
3514 formatuser(ctx.user()),
3537 formatuser(ctx.user()),
3515 opts.get(b'user'),
3538 opts.get(b'user'),
3516 b'',
3539 b'',
3517 ),
3540 ),
3518 (
3541 (
3519 b'date',
3542 b'date',
3520 b'%s',
3543 b'%s',
3521 fm.formatdate(ctx.date(), datefmt),
3544 fm.formatdate(ctx.date(), datefmt),
3522 opts.get(b'date'),
3545 opts.get(b'date'),
3523 b'',
3546 b'',
3524 ),
3547 ),
3525 ]
3548 ]
3526 )
3549 )
3527 for name, fmt, data, cond, extra_label in cols:
3550 for name, fmt, data, cond, extra_label in cols:
3528 if cond:
3551 if cond:
3529 fm.plain(sep, label=b'grep.sep')
3552 fm.plain(sep, label=b'grep.sep')
3530 field = fieldnamemap.get(name, name)
3553 field = fieldnamemap.get(name, name)
3531 label = extra_label + (b'grep.%s' % name)
3554 label = extra_label + (b'grep.%s' % name)
3532 fm.condwrite(cond, field, fmt, data, label=label)
3555 fm.condwrite(cond, field, fmt, data, label=label)
3533 if not opts.get(b'files_with_matches'):
3556 if not opts.get(b'files_with_matches'):
3534 fm.plain(sep, label=b'grep.sep')
3557 fm.plain(sep, label=b'grep.sep')
3535 if not opts.get(b'text') and binary():
3558 if not opts.get(b'text') and binary():
3536 fm.plain(_(b" Binary file matches"))
3559 fm.plain(_(b" Binary file matches"))
3537 else:
3560 else:
3538 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3561 displaymatches(fm.nested(b'texts', tmpl=b'{text}'), l)
3539 fm.plain(eol)
3562 fm.plain(eol)
3540 found = True
3563 found = True
3541 if opts.get(b'files_with_matches'):
3564 if opts.get(b'files_with_matches'):
3542 break
3565 break
3543 return found
3566 return found
3544
3567
3545 def displaymatches(fm, l):
3568 def displaymatches(fm, l):
3546 p = 0
3569 p = 0
3547 for s, e in l.findpos():
3570 for s, e in l.findpos():
3548 if p < s:
3571 if p < s:
3549 fm.startitem()
3572 fm.startitem()
3550 fm.write(b'text', b'%s', l.line[p:s])
3573 fm.write(b'text', b'%s', l.line[p:s])
3551 fm.data(matched=False)
3574 fm.data(matched=False)
3552 fm.startitem()
3575 fm.startitem()
3553 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3576 fm.write(b'text', b'%s', l.line[s:e], label=b'grep.match')
3554 fm.data(matched=True)
3577 fm.data(matched=True)
3555 p = e
3578 p = e
3556 if p < len(l.line):
3579 if p < len(l.line):
3557 fm.startitem()
3580 fm.startitem()
3558 fm.write(b'text', b'%s', l.line[p:])
3581 fm.write(b'text', b'%s', l.line[p:])
3559 fm.data(matched=False)
3582 fm.data(matched=False)
3560 fm.end()
3583 fm.end()
3561
3584
3562 skip = set()
3585 skip = set()
3563 revfiles = {}
3586 revfiles = {}
3564 match = scmutil.match(repo[None], pats, opts)
3587 match = scmutil.match(repo[None], pats, opts)
3565 found = False
3588 found = False
3566 follow = opts.get(b'follow')
3589 follow = opts.get(b'follow')
3567
3590
3568 getrenamed = scmutil.getrenamedfn(repo)
3591 getrenamed = scmutil.getrenamedfn(repo)
3569
3592
3570 def readfile(ctx, fn):
3593 def readfile(ctx, fn):
3571 rev = ctx.rev()
3594 rev = ctx.rev()
3572 if rev is None:
3595 if rev is None:
3573 fctx = ctx[fn]
3596 fctx = ctx[fn]
3574 try:
3597 try:
3575 return fctx.data()
3598 return fctx.data()
3576 except IOError as e:
3599 except IOError as e:
3577 if e.errno != errno.ENOENT:
3600 if e.errno != errno.ENOENT:
3578 raise
3601 raise
3579 else:
3602 else:
3580 flog = getfile(fn)
3603 flog = getfile(fn)
3581 fnode = ctx.filenode(fn)
3604 fnode = ctx.filenode(fn)
3582 try:
3605 try:
3583 return flog.read(fnode)
3606 return flog.read(fnode)
3584 except error.CensoredNodeError:
3607 except error.CensoredNodeError:
3585 ui.warn(
3608 ui.warn(
3586 _(
3609 _(
3587 b'cannot search in censored file: %(filename)s:%(revnum)s\n'
3610 b'cannot search in censored file: %(filename)s:%(revnum)s\n'
3588 )
3611 )
3589 % {b'filename': fn, b'revnum': pycompat.bytestr(rev),}
3612 % {b'filename': fn, b'revnum': pycompat.bytestr(rev),}
3590 )
3613 )
3591
3614
3592 def prep(ctx, fns):
3615 def prep(ctx, fns):
3593 rev = ctx.rev()
3616 rev = ctx.rev()
3594 pctx = ctx.p1()
3617 pctx = ctx.p1()
3595 matches.setdefault(rev, {})
3618 matches.setdefault(rev, {})
3596 if diff:
3619 if diff:
3597 parent = pctx.rev()
3620 parent = pctx.rev()
3598 matches.setdefault(parent, {})
3621 matches.setdefault(parent, {})
3599 files = revfiles.setdefault(rev, [])
3622 files = revfiles.setdefault(rev, [])
3600 if rev is None:
3623 if rev is None:
3601 # in `hg grep pattern`, 2/3 of the time is spent is spent in
3624 # in `hg grep pattern`, 2/3 of the time is spent is spent in
3602 # pathauditor checks without this in mozilla-central
3625 # pathauditor checks without this in mozilla-central
3603 contextmanager = repo.wvfs.audit.cached
3626 contextmanager = repo.wvfs.audit.cached
3604 else:
3627 else:
3605 contextmanager = util.nullcontextmanager
3628 contextmanager = util.nullcontextmanager
3606 with contextmanager():
3629 with contextmanager():
3607 for fn in fns:
3630 for fn in fns:
3608 # fn might not exist in the revision (could be a file removed by
3631 # fn might not exist in the revision (could be a file removed by
3609 # the revision). We could check `fn not in ctx` even when rev is
3632 # the revision). We could check `fn not in ctx` even when rev is
3610 # None, but it's less racy to protect againt that in readfile.
3633 # None, but it's less racy to protect againt that in readfile.
3611 if rev is not None and fn not in ctx:
3634 if rev is not None and fn not in ctx:
3612 continue
3635 continue
3613
3636
3614 copy = None
3637 copy = None
3615 if follow:
3638 if follow:
3616 copy = getrenamed(fn, rev)
3639 copy = getrenamed(fn, rev)
3617 if copy:
3640 if copy:
3618 copies.setdefault(rev, {})[fn] = copy
3641 copies.setdefault(rev, {})[fn] = copy
3619 if fn in skip:
3642 if fn in skip:
3620 skip.add(copy)
3643 skip.add(copy)
3621 if fn in skip:
3644 if fn in skip:
3622 continue
3645 continue
3623 files.append(fn)
3646 files.append(fn)
3624
3647
3625 if fn not in matches[rev]:
3648 if fn not in matches[rev]:
3626 grepbody(fn, rev, readfile(ctx, fn))
3649 grepbody(fn, rev, readfile(ctx, fn))
3627
3650
3628 if diff:
3651 if diff:
3629 pfn = copy or fn
3652 pfn = copy or fn
3630 if pfn not in matches[parent] and pfn in pctx:
3653 if pfn not in matches[parent] and pfn in pctx:
3631 grepbody(pfn, parent, readfile(pctx, pfn))
3654 grepbody(pfn, parent, readfile(pctx, pfn))
3632
3655
3633 ui.pager(b'grep')
3656 ui.pager(b'grep')
3634 fm = ui.formatter(b'grep', opts)
3657 fm = ui.formatter(b'grep', opts)
3635 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
3658 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
3636 rev = ctx.rev()
3659 rev = ctx.rev()
3637 parent = ctx.p1().rev()
3660 parent = ctx.p1().rev()
3638 for fn in sorted(revfiles.get(rev, [])):
3661 for fn in sorted(revfiles.get(rev, [])):
3639 states = matches[rev][fn]
3662 states = matches[rev][fn]
3640 copy = copies.get(rev, {}).get(fn)
3663 copy = copies.get(rev, {}).get(fn)
3641 if fn in skip:
3664 if fn in skip:
3642 if copy:
3665 if copy:
3643 skip.add(copy)
3666 skip.add(copy)
3644 continue
3667 continue
3645 pstates = matches.get(parent, {}).get(copy or fn, [])
3668 pstates = matches.get(parent, {}).get(copy or fn, [])
3646 if pstates or states:
3669 if pstates or states:
3647 r = display(fm, fn, ctx, pstates, states)
3670 r = display(fm, fn, ctx, pstates, states)
3648 found = found or r
3671 found = found or r
3649 if r and not diff and not all_files:
3672 if r and not diff and not all_files:
3650 skip.add(fn)
3673 skip.add(fn)
3651 if copy:
3674 if copy:
3652 skip.add(copy)
3675 skip.add(copy)
3653 del revfiles[rev]
3676 del revfiles[rev]
3654 # We will keep the matches dict for the duration of the window
3677 # We will keep the matches dict for the duration of the window
3655 # clear the matches dict once the window is over
3678 # clear the matches dict once the window is over
3656 if not revfiles:
3679 if not revfiles:
3657 matches.clear()
3680 matches.clear()
3658 fm.end()
3681 fm.end()
3659
3682
3660 return not found
3683 return not found
3661
3684
3662
3685
3663 @command(
3686 @command(
3664 b'heads',
3687 b'heads',
3665 [
3688 [
3666 (
3689 (
3667 b'r',
3690 b'r',
3668 b'rev',
3691 b'rev',
3669 b'',
3692 b'',
3670 _(b'show only heads which are descendants of STARTREV'),
3693 _(b'show only heads which are descendants of STARTREV'),
3671 _(b'STARTREV'),
3694 _(b'STARTREV'),
3672 ),
3695 ),
3673 (b't', b'topo', False, _(b'show topological heads only')),
3696 (b't', b'topo', False, _(b'show topological heads only')),
3674 (
3697 (
3675 b'a',
3698 b'a',
3676 b'active',
3699 b'active',
3677 False,
3700 False,
3678 _(b'show active branchheads only (DEPRECATED)'),
3701 _(b'show active branchheads only (DEPRECATED)'),
3679 ),
3702 ),
3680 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3703 (b'c', b'closed', False, _(b'show normal and closed branch heads')),
3681 ]
3704 ]
3682 + templateopts,
3705 + templateopts,
3683 _(b'[-ct] [-r STARTREV] [REV]...'),
3706 _(b'[-ct] [-r STARTREV] [REV]...'),
3684 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3707 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3685 intents={INTENT_READONLY},
3708 intents={INTENT_READONLY},
3686 )
3709 )
3687 def heads(ui, repo, *branchrevs, **opts):
3710 def heads(ui, repo, *branchrevs, **opts):
3688 """show branch heads
3711 """show branch heads
3689
3712
3690 With no arguments, show all open branch heads in the repository.
3713 With no arguments, show all open branch heads in the repository.
3691 Branch heads are changesets that have no descendants on the
3714 Branch heads are changesets that have no descendants on the
3692 same branch. They are where development generally takes place and
3715 same branch. They are where development generally takes place and
3693 are the usual targets for update and merge operations.
3716 are the usual targets for update and merge operations.
3694
3717
3695 If one or more REVs are given, only open branch heads on the
3718 If one or more REVs are given, only open branch heads on the
3696 branches associated with the specified changesets are shown. This
3719 branches associated with the specified changesets are shown. This
3697 means that you can use :hg:`heads .` to see the heads on the
3720 means that you can use :hg:`heads .` to see the heads on the
3698 currently checked-out branch.
3721 currently checked-out branch.
3699
3722
3700 If -c/--closed is specified, also show branch heads marked closed
3723 If -c/--closed is specified, also show branch heads marked closed
3701 (see :hg:`commit --close-branch`).
3724 (see :hg:`commit --close-branch`).
3702
3725
3703 If STARTREV is specified, only those heads that are descendants of
3726 If STARTREV is specified, only those heads that are descendants of
3704 STARTREV will be displayed.
3727 STARTREV will be displayed.
3705
3728
3706 If -t/--topo is specified, named branch mechanics will be ignored and only
3729 If -t/--topo is specified, named branch mechanics will be ignored and only
3707 topological heads (changesets with no children) will be shown.
3730 topological heads (changesets with no children) will be shown.
3708
3731
3709 Returns 0 if matching heads are found, 1 if not.
3732 Returns 0 if matching heads are found, 1 if not.
3710 """
3733 """
3711
3734
3712 opts = pycompat.byteskwargs(opts)
3735 opts = pycompat.byteskwargs(opts)
3713 start = None
3736 start = None
3714 rev = opts.get(b'rev')
3737 rev = opts.get(b'rev')
3715 if rev:
3738 if rev:
3716 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3739 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3717 start = scmutil.revsingle(repo, rev, None).node()
3740 start = scmutil.revsingle(repo, rev, None).node()
3718
3741
3719 if opts.get(b'topo'):
3742 if opts.get(b'topo'):
3720 heads = [repo[h] for h in repo.heads(start)]
3743 heads = [repo[h] for h in repo.heads(start)]
3721 else:
3744 else:
3722 heads = []
3745 heads = []
3723 for branch in repo.branchmap():
3746 for branch in repo.branchmap():
3724 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3747 heads += repo.branchheads(branch, start, opts.get(b'closed'))
3725 heads = [repo[h] for h in heads]
3748 heads = [repo[h] for h in heads]
3726
3749
3727 if branchrevs:
3750 if branchrevs:
3728 branches = {
3751 branches = {
3729 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3752 repo[r].branch() for r in scmutil.revrange(repo, branchrevs)
3730 }
3753 }
3731 heads = [h for h in heads if h.branch() in branches]
3754 heads = [h for h in heads if h.branch() in branches]
3732
3755
3733 if opts.get(b'active') and branchrevs:
3756 if opts.get(b'active') and branchrevs:
3734 dagheads = repo.heads(start)
3757 dagheads = repo.heads(start)
3735 heads = [h for h in heads if h.node() in dagheads]
3758 heads = [h for h in heads if h.node() in dagheads]
3736
3759
3737 if branchrevs:
3760 if branchrevs:
3738 haveheads = {h.branch() for h in heads}
3761 haveheads = {h.branch() for h in heads}
3739 if branches - haveheads:
3762 if branches - haveheads:
3740 headless = b', '.join(b for b in branches - haveheads)
3763 headless = b', '.join(b for b in branches - haveheads)
3741 msg = _(b'no open branch heads found on branches %s')
3764 msg = _(b'no open branch heads found on branches %s')
3742 if opts.get(b'rev'):
3765 if opts.get(b'rev'):
3743 msg += _(b' (started at %s)') % opts[b'rev']
3766 msg += _(b' (started at %s)') % opts[b'rev']
3744 ui.warn((msg + b'\n') % headless)
3767 ui.warn((msg + b'\n') % headless)
3745
3768
3746 if not heads:
3769 if not heads:
3747 return 1
3770 return 1
3748
3771
3749 ui.pager(b'heads')
3772 ui.pager(b'heads')
3750 heads = sorted(heads, key=lambda x: -(x.rev()))
3773 heads = sorted(heads, key=lambda x: -(x.rev()))
3751 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3774 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3752 for ctx in heads:
3775 for ctx in heads:
3753 displayer.show(ctx)
3776 displayer.show(ctx)
3754 displayer.close()
3777 displayer.close()
3755
3778
3756
3779
3757 @command(
3780 @command(
3758 b'help',
3781 b'help',
3759 [
3782 [
3760 (b'e', b'extension', None, _(b'show only help for extensions')),
3783 (b'e', b'extension', None, _(b'show only help for extensions')),
3761 (b'c', b'command', None, _(b'show only help for commands')),
3784 (b'c', b'command', None, _(b'show only help for commands')),
3762 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3785 (b'k', b'keyword', None, _(b'show topics matching keyword')),
3763 (
3786 (
3764 b's',
3787 b's',
3765 b'system',
3788 b'system',
3766 [],
3789 [],
3767 _(b'show help for specific platform(s)'),
3790 _(b'show help for specific platform(s)'),
3768 _(b'PLATFORM'),
3791 _(b'PLATFORM'),
3769 ),
3792 ),
3770 ],
3793 ],
3771 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3794 _(b'[-eck] [-s PLATFORM] [TOPIC]'),
3772 helpcategory=command.CATEGORY_HELP,
3795 helpcategory=command.CATEGORY_HELP,
3773 norepo=True,
3796 norepo=True,
3774 intents={INTENT_READONLY},
3797 intents={INTENT_READONLY},
3775 )
3798 )
3776 def help_(ui, name=None, **opts):
3799 def help_(ui, name=None, **opts):
3777 """show help for a given topic or a help overview
3800 """show help for a given topic or a help overview
3778
3801
3779 With no arguments, print a list of commands with short help messages.
3802 With no arguments, print a list of commands with short help messages.
3780
3803
3781 Given a topic, extension, or command name, print help for that
3804 Given a topic, extension, or command name, print help for that
3782 topic.
3805 topic.
3783
3806
3784 Returns 0 if successful.
3807 Returns 0 if successful.
3785 """
3808 """
3786
3809
3787 keep = opts.get('system') or []
3810 keep = opts.get('system') or []
3788 if len(keep) == 0:
3811 if len(keep) == 0:
3789 if pycompat.sysplatform.startswith(b'win'):
3812 if pycompat.sysplatform.startswith(b'win'):
3790 keep.append(b'windows')
3813 keep.append(b'windows')
3791 elif pycompat.sysplatform == b'OpenVMS':
3814 elif pycompat.sysplatform == b'OpenVMS':
3792 keep.append(b'vms')
3815 keep.append(b'vms')
3793 elif pycompat.sysplatform == b'plan9':
3816 elif pycompat.sysplatform == b'plan9':
3794 keep.append(b'plan9')
3817 keep.append(b'plan9')
3795 else:
3818 else:
3796 keep.append(b'unix')
3819 keep.append(b'unix')
3797 keep.append(pycompat.sysplatform.lower())
3820 keep.append(pycompat.sysplatform.lower())
3798 if ui.verbose:
3821 if ui.verbose:
3799 keep.append(b'verbose')
3822 keep.append(b'verbose')
3800
3823
3801 commands = sys.modules[__name__]
3824 commands = sys.modules[__name__]
3802 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3825 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3803 ui.pager(b'help')
3826 ui.pager(b'help')
3804 ui.write(formatted)
3827 ui.write(formatted)
3805
3828
3806
3829
3807 @command(
3830 @command(
3808 b'identify|id',
3831 b'identify|id',
3809 [
3832 [
3810 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3833 (b'r', b'rev', b'', _(b'identify the specified revision'), _(b'REV')),
3811 (b'n', b'num', None, _(b'show local revision number')),
3834 (b'n', b'num', None, _(b'show local revision number')),
3812 (b'i', b'id', None, _(b'show global revision id')),
3835 (b'i', b'id', None, _(b'show global revision id')),
3813 (b'b', b'branch', None, _(b'show branch')),
3836 (b'b', b'branch', None, _(b'show branch')),
3814 (b't', b'tags', None, _(b'show tags')),
3837 (b't', b'tags', None, _(b'show tags')),
3815 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3838 (b'B', b'bookmarks', None, _(b'show bookmarks')),
3816 ]
3839 ]
3817 + remoteopts
3840 + remoteopts
3818 + formatteropts,
3841 + formatteropts,
3819 _(b'[-nibtB] [-r REV] [SOURCE]'),
3842 _(b'[-nibtB] [-r REV] [SOURCE]'),
3820 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3843 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3821 optionalrepo=True,
3844 optionalrepo=True,
3822 intents={INTENT_READONLY},
3845 intents={INTENT_READONLY},
3823 )
3846 )
3824 def identify(
3847 def identify(
3825 ui,
3848 ui,
3826 repo,
3849 repo,
3827 source=None,
3850 source=None,
3828 rev=None,
3851 rev=None,
3829 num=None,
3852 num=None,
3830 id=None,
3853 id=None,
3831 branch=None,
3854 branch=None,
3832 tags=None,
3855 tags=None,
3833 bookmarks=None,
3856 bookmarks=None,
3834 **opts
3857 **opts
3835 ):
3858 ):
3836 """identify the working directory or specified revision
3859 """identify the working directory or specified revision
3837
3860
3838 Print a summary identifying the repository state at REV using one or
3861 Print a summary identifying the repository state at REV using one or
3839 two parent hash identifiers, followed by a "+" if the working
3862 two parent hash identifiers, followed by a "+" if the working
3840 directory has uncommitted changes, the branch name (if not default),
3863 directory has uncommitted changes, the branch name (if not default),
3841 a list of tags, and a list of bookmarks.
3864 a list of tags, and a list of bookmarks.
3842
3865
3843 When REV is not given, print a summary of the current state of the
3866 When REV is not given, print a summary of the current state of the
3844 repository including the working directory. Specify -r. to get information
3867 repository including the working directory. Specify -r. to get information
3845 of the working directory parent without scanning uncommitted changes.
3868 of the working directory parent without scanning uncommitted changes.
3846
3869
3847 Specifying a path to a repository root or Mercurial bundle will
3870 Specifying a path to a repository root or Mercurial bundle will
3848 cause lookup to operate on that repository/bundle.
3871 cause lookup to operate on that repository/bundle.
3849
3872
3850 .. container:: verbose
3873 .. container:: verbose
3851
3874
3852 Template:
3875 Template:
3853
3876
3854 The following keywords are supported in addition to the common template
3877 The following keywords are supported in addition to the common template
3855 keywords and functions. See also :hg:`help templates`.
3878 keywords and functions. See also :hg:`help templates`.
3856
3879
3857 :dirty: String. Character ``+`` denoting if the working directory has
3880 :dirty: String. Character ``+`` denoting if the working directory has
3858 uncommitted changes.
3881 uncommitted changes.
3859 :id: String. One or two nodes, optionally followed by ``+``.
3882 :id: String. One or two nodes, optionally followed by ``+``.
3860 :parents: List of strings. Parent nodes of the changeset.
3883 :parents: List of strings. Parent nodes of the changeset.
3861
3884
3862 Examples:
3885 Examples:
3863
3886
3864 - generate a build identifier for the working directory::
3887 - generate a build identifier for the working directory::
3865
3888
3866 hg id --id > build-id.dat
3889 hg id --id > build-id.dat
3867
3890
3868 - find the revision corresponding to a tag::
3891 - find the revision corresponding to a tag::
3869
3892
3870 hg id -n -r 1.3
3893 hg id -n -r 1.3
3871
3894
3872 - check the most recent revision of a remote repository::
3895 - check the most recent revision of a remote repository::
3873
3896
3874 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3897 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3875
3898
3876 See :hg:`log` for generating more information about specific revisions,
3899 See :hg:`log` for generating more information about specific revisions,
3877 including full hash identifiers.
3900 including full hash identifiers.
3878
3901
3879 Returns 0 if successful.
3902 Returns 0 if successful.
3880 """
3903 """
3881
3904
3882 opts = pycompat.byteskwargs(opts)
3905 opts = pycompat.byteskwargs(opts)
3883 if not repo and not source:
3906 if not repo and not source:
3884 raise error.Abort(
3907 raise error.Abort(
3885 _(b"there is no Mercurial repository here (.hg not found)")
3908 _(b"there is no Mercurial repository here (.hg not found)")
3886 )
3909 )
3887
3910
3888 default = not (num or id or branch or tags or bookmarks)
3911 default = not (num or id or branch or tags or bookmarks)
3889 output = []
3912 output = []
3890 revs = []
3913 revs = []
3891
3914
3892 if source:
3915 if source:
3893 source, branches = hg.parseurl(ui.expandpath(source))
3916 source, branches = hg.parseurl(ui.expandpath(source))
3894 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3917 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3895 repo = peer.local()
3918 repo = peer.local()
3896 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3919 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3897
3920
3898 fm = ui.formatter(b'identify', opts)
3921 fm = ui.formatter(b'identify', opts)
3899 fm.startitem()
3922 fm.startitem()
3900
3923
3901 if not repo:
3924 if not repo:
3902 if num or branch or tags:
3925 if num or branch or tags:
3903 raise error.Abort(
3926 raise error.Abort(
3904 _(b"can't query remote revision number, branch, or tags")
3927 _(b"can't query remote revision number, branch, or tags")
3905 )
3928 )
3906 if not rev and revs:
3929 if not rev and revs:
3907 rev = revs[0]
3930 rev = revs[0]
3908 if not rev:
3931 if not rev:
3909 rev = b"tip"
3932 rev = b"tip"
3910
3933
3911 remoterev = peer.lookup(rev)
3934 remoterev = peer.lookup(rev)
3912 hexrev = fm.hexfunc(remoterev)
3935 hexrev = fm.hexfunc(remoterev)
3913 if default or id:
3936 if default or id:
3914 output = [hexrev]
3937 output = [hexrev]
3915 fm.data(id=hexrev)
3938 fm.data(id=hexrev)
3916
3939
3917 @util.cachefunc
3940 @util.cachefunc
3918 def getbms():
3941 def getbms():
3919 bms = []
3942 bms = []
3920
3943
3921 if b'bookmarks' in peer.listkeys(b'namespaces'):
3944 if b'bookmarks' in peer.listkeys(b'namespaces'):
3922 hexremoterev = hex(remoterev)
3945 hexremoterev = hex(remoterev)
3923 bms = [
3946 bms = [
3924 bm
3947 bm
3925 for bm, bmr in pycompat.iteritems(
3948 for bm, bmr in pycompat.iteritems(
3926 peer.listkeys(b'bookmarks')
3949 peer.listkeys(b'bookmarks')
3927 )
3950 )
3928 if bmr == hexremoterev
3951 if bmr == hexremoterev
3929 ]
3952 ]
3930
3953
3931 return sorted(bms)
3954 return sorted(bms)
3932
3955
3933 if fm.isplain():
3956 if fm.isplain():
3934 if bookmarks:
3957 if bookmarks:
3935 output.extend(getbms())
3958 output.extend(getbms())
3936 elif default and not ui.quiet:
3959 elif default and not ui.quiet:
3937 # multiple bookmarks for a single parent separated by '/'
3960 # multiple bookmarks for a single parent separated by '/'
3938 bm = b'/'.join(getbms())
3961 bm = b'/'.join(getbms())
3939 if bm:
3962 if bm:
3940 output.append(bm)
3963 output.append(bm)
3941 else:
3964 else:
3942 fm.data(node=hex(remoterev))
3965 fm.data(node=hex(remoterev))
3943 if bookmarks or b'bookmarks' in fm.datahint():
3966 if bookmarks or b'bookmarks' in fm.datahint():
3944 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3967 fm.data(bookmarks=fm.formatlist(getbms(), name=b'bookmark'))
3945 else:
3968 else:
3946 if rev:
3969 if rev:
3947 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3970 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
3948 ctx = scmutil.revsingle(repo, rev, None)
3971 ctx = scmutil.revsingle(repo, rev, None)
3949
3972
3950 if ctx.rev() is None:
3973 if ctx.rev() is None:
3951 ctx = repo[None]
3974 ctx = repo[None]
3952 parents = ctx.parents()
3975 parents = ctx.parents()
3953 taglist = []
3976 taglist = []
3954 for p in parents:
3977 for p in parents:
3955 taglist.extend(p.tags())
3978 taglist.extend(p.tags())
3956
3979
3957 dirty = b""
3980 dirty = b""
3958 if ctx.dirty(missing=True, merge=False, branch=False):
3981 if ctx.dirty(missing=True, merge=False, branch=False):
3959 dirty = b'+'
3982 dirty = b'+'
3960 fm.data(dirty=dirty)
3983 fm.data(dirty=dirty)
3961
3984
3962 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3985 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3963 if default or id:
3986 if default or id:
3964 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3987 output = [b"%s%s" % (b'+'.join(hexoutput), dirty)]
3965 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3988 fm.data(id=b"%s%s" % (b'+'.join(hexoutput), dirty))
3966
3989
3967 if num:
3990 if num:
3968 numoutput = [b"%d" % p.rev() for p in parents]
3991 numoutput = [b"%d" % p.rev() for p in parents]
3969 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3992 output.append(b"%s%s" % (b'+'.join(numoutput), dirty))
3970
3993
3971 fm.data(
3994 fm.data(
3972 parents=fm.formatlist(
3995 parents=fm.formatlist(
3973 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3996 [fm.hexfunc(p.node()) for p in parents], name=b'node'
3974 )
3997 )
3975 )
3998 )
3976 else:
3999 else:
3977 hexoutput = fm.hexfunc(ctx.node())
4000 hexoutput = fm.hexfunc(ctx.node())
3978 if default or id:
4001 if default or id:
3979 output = [hexoutput]
4002 output = [hexoutput]
3980 fm.data(id=hexoutput)
4003 fm.data(id=hexoutput)
3981
4004
3982 if num:
4005 if num:
3983 output.append(pycompat.bytestr(ctx.rev()))
4006 output.append(pycompat.bytestr(ctx.rev()))
3984 taglist = ctx.tags()
4007 taglist = ctx.tags()
3985
4008
3986 if default and not ui.quiet:
4009 if default and not ui.quiet:
3987 b = ctx.branch()
4010 b = ctx.branch()
3988 if b != b'default':
4011 if b != b'default':
3989 output.append(b"(%s)" % b)
4012 output.append(b"(%s)" % b)
3990
4013
3991 # multiple tags for a single parent separated by '/'
4014 # multiple tags for a single parent separated by '/'
3992 t = b'/'.join(taglist)
4015 t = b'/'.join(taglist)
3993 if t:
4016 if t:
3994 output.append(t)
4017 output.append(t)
3995
4018
3996 # multiple bookmarks for a single parent separated by '/'
4019 # multiple bookmarks for a single parent separated by '/'
3997 bm = b'/'.join(ctx.bookmarks())
4020 bm = b'/'.join(ctx.bookmarks())
3998 if bm:
4021 if bm:
3999 output.append(bm)
4022 output.append(bm)
4000 else:
4023 else:
4001 if branch:
4024 if branch:
4002 output.append(ctx.branch())
4025 output.append(ctx.branch())
4003
4026
4004 if tags:
4027 if tags:
4005 output.extend(taglist)
4028 output.extend(taglist)
4006
4029
4007 if bookmarks:
4030 if bookmarks:
4008 output.extend(ctx.bookmarks())
4031 output.extend(ctx.bookmarks())
4009
4032
4010 fm.data(node=ctx.hex())
4033 fm.data(node=ctx.hex())
4011 fm.data(branch=ctx.branch())
4034 fm.data(branch=ctx.branch())
4012 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4035 fm.data(tags=fm.formatlist(taglist, name=b'tag', sep=b':'))
4013 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4036 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name=b'bookmark'))
4014 fm.context(ctx=ctx)
4037 fm.context(ctx=ctx)
4015
4038
4016 fm.plain(b"%s\n" % b' '.join(output))
4039 fm.plain(b"%s\n" % b' '.join(output))
4017 fm.end()
4040 fm.end()
4018
4041
4019
4042
4020 @command(
4043 @command(
4021 b'import|patch',
4044 b'import|patch',
4022 [
4045 [
4023 (
4046 (
4024 b'p',
4047 b'p',
4025 b'strip',
4048 b'strip',
4026 1,
4049 1,
4027 _(
4050 _(
4028 b'directory strip option for patch. This has the same '
4051 b'directory strip option for patch. This has the same '
4029 b'meaning as the corresponding patch option'
4052 b'meaning as the corresponding patch option'
4030 ),
4053 ),
4031 _(b'NUM'),
4054 _(b'NUM'),
4032 ),
4055 ),
4033 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4056 (b'b', b'base', b'', _(b'base path (DEPRECATED)'), _(b'PATH')),
4034 (b'', b'secret', None, _(b'use the secret phase for committing')),
4057 (b'', b'secret', None, _(b'use the secret phase for committing')),
4035 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4058 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
4036 (
4059 (
4037 b'f',
4060 b'f',
4038 b'force',
4061 b'force',
4039 None,
4062 None,
4040 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4063 _(b'skip check for outstanding uncommitted changes (DEPRECATED)'),
4041 ),
4064 ),
4042 (
4065 (
4043 b'',
4066 b'',
4044 b'no-commit',
4067 b'no-commit',
4045 None,
4068 None,
4046 _(b"don't commit, just update the working directory"),
4069 _(b"don't commit, just update the working directory"),
4047 ),
4070 ),
4048 (
4071 (
4049 b'',
4072 b'',
4050 b'bypass',
4073 b'bypass',
4051 None,
4074 None,
4052 _(b"apply patch without touching the working directory"),
4075 _(b"apply patch without touching the working directory"),
4053 ),
4076 ),
4054 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4077 (b'', b'partial', None, _(b'commit even if some hunks fail')),
4055 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4078 (b'', b'exact', None, _(b'abort if patch would apply lossily')),
4056 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4079 (b'', b'prefix', b'', _(b'apply patch to subdirectory'), _(b'DIR')),
4057 (
4080 (
4058 b'',
4081 b'',
4059 b'import-branch',
4082 b'import-branch',
4060 None,
4083 None,
4061 _(b'use any branch information in patch (implied by --exact)'),
4084 _(b'use any branch information in patch (implied by --exact)'),
4062 ),
4085 ),
4063 ]
4086 ]
4064 + commitopts
4087 + commitopts
4065 + commitopts2
4088 + commitopts2
4066 + similarityopts,
4089 + similarityopts,
4067 _(b'[OPTION]... PATCH...'),
4090 _(b'[OPTION]... PATCH...'),
4068 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4091 helpcategory=command.CATEGORY_IMPORT_EXPORT,
4069 )
4092 )
4070 def import_(ui, repo, patch1=None, *patches, **opts):
4093 def import_(ui, repo, patch1=None, *patches, **opts):
4071 """import an ordered set of patches
4094 """import an ordered set of patches
4072
4095
4073 Import a list of patches and commit them individually (unless
4096 Import a list of patches and commit them individually (unless
4074 --no-commit is specified).
4097 --no-commit is specified).
4075
4098
4076 To read a patch from standard input (stdin), use "-" as the patch
4099 To read a patch from standard input (stdin), use "-" as the patch
4077 name. If a URL is specified, the patch will be downloaded from
4100 name. If a URL is specified, the patch will be downloaded from
4078 there.
4101 there.
4079
4102
4080 Import first applies changes to the working directory (unless
4103 Import first applies changes to the working directory (unless
4081 --bypass is specified), import will abort if there are outstanding
4104 --bypass is specified), import will abort if there are outstanding
4082 changes.
4105 changes.
4083
4106
4084 Use --bypass to apply and commit patches directly to the
4107 Use --bypass to apply and commit patches directly to the
4085 repository, without affecting the working directory. Without
4108 repository, without affecting the working directory. Without
4086 --exact, patches will be applied on top of the working directory
4109 --exact, patches will be applied on top of the working directory
4087 parent revision.
4110 parent revision.
4088
4111
4089 You can import a patch straight from a mail message. Even patches
4112 You can import a patch straight from a mail message. Even patches
4090 as attachments work (to use the body part, it must have type
4113 as attachments work (to use the body part, it must have type
4091 text/plain or text/x-patch). From and Subject headers of email
4114 text/plain or text/x-patch). From and Subject headers of email
4092 message are used as default committer and commit message. All
4115 message are used as default committer and commit message. All
4093 text/plain body parts before first diff are added to the commit
4116 text/plain body parts before first diff are added to the commit
4094 message.
4117 message.
4095
4118
4096 If the imported patch was generated by :hg:`export`, user and
4119 If the imported patch was generated by :hg:`export`, user and
4097 description from patch override values from message headers and
4120 description from patch override values from message headers and
4098 body. Values given on command line with -m/--message and -u/--user
4121 body. Values given on command line with -m/--message and -u/--user
4099 override these.
4122 override these.
4100
4123
4101 If --exact is specified, import will set the working directory to
4124 If --exact is specified, import will set the working directory to
4102 the parent of each patch before applying it, and will abort if the
4125 the parent of each patch before applying it, and will abort if the
4103 resulting changeset has a different ID than the one recorded in
4126 resulting changeset has a different ID than the one recorded in
4104 the patch. This will guard against various ways that portable
4127 the patch. This will guard against various ways that portable
4105 patch formats and mail systems might fail to transfer Mercurial
4128 patch formats and mail systems might fail to transfer Mercurial
4106 data or metadata. See :hg:`bundle` for lossless transmission.
4129 data or metadata. See :hg:`bundle` for lossless transmission.
4107
4130
4108 Use --partial to ensure a changeset will be created from the patch
4131 Use --partial to ensure a changeset will be created from the patch
4109 even if some hunks fail to apply. Hunks that fail to apply will be
4132 even if some hunks fail to apply. Hunks that fail to apply will be
4110 written to a <target-file>.rej file. Conflicts can then be resolved
4133 written to a <target-file>.rej file. Conflicts can then be resolved
4111 by hand before :hg:`commit --amend` is run to update the created
4134 by hand before :hg:`commit --amend` is run to update the created
4112 changeset. This flag exists to let people import patches that
4135 changeset. This flag exists to let people import patches that
4113 partially apply without losing the associated metadata (author,
4136 partially apply without losing the associated metadata (author,
4114 date, description, ...).
4137 date, description, ...).
4115
4138
4116 .. note::
4139 .. note::
4117
4140
4118 When no hunks apply cleanly, :hg:`import --partial` will create
4141 When no hunks apply cleanly, :hg:`import --partial` will create
4119 an empty changeset, importing only the patch metadata.
4142 an empty changeset, importing only the patch metadata.
4120
4143
4121 With -s/--similarity, hg will attempt to discover renames and
4144 With -s/--similarity, hg will attempt to discover renames and
4122 copies in the patch in the same way as :hg:`addremove`.
4145 copies in the patch in the same way as :hg:`addremove`.
4123
4146
4124 It is possible to use external patch programs to perform the patch
4147 It is possible to use external patch programs to perform the patch
4125 by setting the ``ui.patch`` configuration option. For the default
4148 by setting the ``ui.patch`` configuration option. For the default
4126 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4149 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4127 See :hg:`help config` for more information about configuration
4150 See :hg:`help config` for more information about configuration
4128 files and how to use these options.
4151 files and how to use these options.
4129
4152
4130 See :hg:`help dates` for a list of formats valid for -d/--date.
4153 See :hg:`help dates` for a list of formats valid for -d/--date.
4131
4154
4132 .. container:: verbose
4155 .. container:: verbose
4133
4156
4134 Examples:
4157 Examples:
4135
4158
4136 - import a traditional patch from a website and detect renames::
4159 - import a traditional patch from a website and detect renames::
4137
4160
4138 hg import -s 80 http://example.com/bugfix.patch
4161 hg import -s 80 http://example.com/bugfix.patch
4139
4162
4140 - import a changeset from an hgweb server::
4163 - import a changeset from an hgweb server::
4141
4164
4142 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4165 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
4143
4166
4144 - import all the patches in an Unix-style mbox::
4167 - import all the patches in an Unix-style mbox::
4145
4168
4146 hg import incoming-patches.mbox
4169 hg import incoming-patches.mbox
4147
4170
4148 - import patches from stdin::
4171 - import patches from stdin::
4149
4172
4150 hg import -
4173 hg import -
4151
4174
4152 - attempt to exactly restore an exported changeset (not always
4175 - attempt to exactly restore an exported changeset (not always
4153 possible)::
4176 possible)::
4154
4177
4155 hg import --exact proposed-fix.patch
4178 hg import --exact proposed-fix.patch
4156
4179
4157 - use an external tool to apply a patch which is too fuzzy for
4180 - use an external tool to apply a patch which is too fuzzy for
4158 the default internal tool.
4181 the default internal tool.
4159
4182
4160 hg import --config ui.patch="patch --merge" fuzzy.patch
4183 hg import --config ui.patch="patch --merge" fuzzy.patch
4161
4184
4162 - change the default fuzzing from 2 to a less strict 7
4185 - change the default fuzzing from 2 to a less strict 7
4163
4186
4164 hg import --config ui.fuzz=7 fuzz.patch
4187 hg import --config ui.fuzz=7 fuzz.patch
4165
4188
4166 Returns 0 on success, 1 on partial success (see --partial).
4189 Returns 0 on success, 1 on partial success (see --partial).
4167 """
4190 """
4168
4191
4169 opts = pycompat.byteskwargs(opts)
4192 opts = pycompat.byteskwargs(opts)
4170 if not patch1:
4193 if not patch1:
4171 raise error.Abort(_(b'need at least one patch to import'))
4194 raise error.Abort(_(b'need at least one patch to import'))
4172
4195
4173 patches = (patch1,) + patches
4196 patches = (patch1,) + patches
4174
4197
4175 date = opts.get(b'date')
4198 date = opts.get(b'date')
4176 if date:
4199 if date:
4177 opts[b'date'] = dateutil.parsedate(date)
4200 opts[b'date'] = dateutil.parsedate(date)
4178
4201
4179 exact = opts.get(b'exact')
4202 exact = opts.get(b'exact')
4180 update = not opts.get(b'bypass')
4203 update = not opts.get(b'bypass')
4181 if not update and opts.get(b'no_commit'):
4204 if not update and opts.get(b'no_commit'):
4182 raise error.Abort(_(b'cannot use --no-commit with --bypass'))
4205 raise error.Abort(_(b'cannot use --no-commit with --bypass'))
4183 if opts.get(b'secret') and opts.get(b'no_commit'):
4206 if opts.get(b'secret') and opts.get(b'no_commit'):
4184 raise error.Abort(_(b'cannot use --no-commit with --secret'))
4207 raise error.Abort(_(b'cannot use --no-commit with --secret'))
4185 try:
4208 try:
4186 sim = float(opts.get(b'similarity') or 0)
4209 sim = float(opts.get(b'similarity') or 0)
4187 except ValueError:
4210 except ValueError:
4188 raise error.Abort(_(b'similarity must be a number'))
4211 raise error.Abort(_(b'similarity must be a number'))
4189 if sim < 0 or sim > 100:
4212 if sim < 0 or sim > 100:
4190 raise error.Abort(_(b'similarity must be between 0 and 100'))
4213 raise error.Abort(_(b'similarity must be between 0 and 100'))
4191 if sim and not update:
4214 if sim and not update:
4192 raise error.Abort(_(b'cannot use --similarity with --bypass'))
4215 raise error.Abort(_(b'cannot use --similarity with --bypass'))
4193 if exact:
4216 if exact:
4194 if opts.get(b'edit'):
4217 if opts.get(b'edit'):
4195 raise error.Abort(_(b'cannot use --exact with --edit'))
4218 raise error.Abort(_(b'cannot use --exact with --edit'))
4196 if opts.get(b'prefix'):
4219 if opts.get(b'prefix'):
4197 raise error.Abort(_(b'cannot use --exact with --prefix'))
4220 raise error.Abort(_(b'cannot use --exact with --prefix'))
4198
4221
4199 base = opts[b"base"]
4222 base = opts[b"base"]
4200 msgs = []
4223 msgs = []
4201 ret = 0
4224 ret = 0
4202
4225
4203 with repo.wlock():
4226 with repo.wlock():
4204 if update:
4227 if update:
4205 cmdutil.checkunfinished(repo)
4228 cmdutil.checkunfinished(repo)
4206 if exact or not opts.get(b'force'):
4229 if exact or not opts.get(b'force'):
4207 cmdutil.bailifchanged(repo)
4230 cmdutil.bailifchanged(repo)
4208
4231
4209 if not opts.get(b'no_commit'):
4232 if not opts.get(b'no_commit'):
4210 lock = repo.lock
4233 lock = repo.lock
4211 tr = lambda: repo.transaction(b'import')
4234 tr = lambda: repo.transaction(b'import')
4212 dsguard = util.nullcontextmanager
4235 dsguard = util.nullcontextmanager
4213 else:
4236 else:
4214 lock = util.nullcontextmanager
4237 lock = util.nullcontextmanager
4215 tr = util.nullcontextmanager
4238 tr = util.nullcontextmanager
4216 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4239 dsguard = lambda: dirstateguard.dirstateguard(repo, b'import')
4217 with lock(), tr(), dsguard():
4240 with lock(), tr(), dsguard():
4218 parents = repo[None].parents()
4241 parents = repo[None].parents()
4219 for patchurl in patches:
4242 for patchurl in patches:
4220 if patchurl == b'-':
4243 if patchurl == b'-':
4221 ui.status(_(b'applying patch from stdin\n'))
4244 ui.status(_(b'applying patch from stdin\n'))
4222 patchfile = ui.fin
4245 patchfile = ui.fin
4223 patchurl = b'stdin' # for error message
4246 patchurl = b'stdin' # for error message
4224 else:
4247 else:
4225 patchurl = os.path.join(base, patchurl)
4248 patchurl = os.path.join(base, patchurl)
4226 ui.status(_(b'applying %s\n') % patchurl)
4249 ui.status(_(b'applying %s\n') % patchurl)
4227 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4250 patchfile = hg.openpath(ui, patchurl, sendaccept=False)
4228
4251
4229 haspatch = False
4252 haspatch = False
4230 for hunk in patch.split(patchfile):
4253 for hunk in patch.split(patchfile):
4231 with patch.extract(ui, hunk) as patchdata:
4254 with patch.extract(ui, hunk) as patchdata:
4232 msg, node, rej = cmdutil.tryimportone(
4255 msg, node, rej = cmdutil.tryimportone(
4233 ui, repo, patchdata, parents, opts, msgs, hg.clean
4256 ui, repo, patchdata, parents, opts, msgs, hg.clean
4234 )
4257 )
4235 if msg:
4258 if msg:
4236 haspatch = True
4259 haspatch = True
4237 ui.note(msg + b'\n')
4260 ui.note(msg + b'\n')
4238 if update or exact:
4261 if update or exact:
4239 parents = repo[None].parents()
4262 parents = repo[None].parents()
4240 else:
4263 else:
4241 parents = [repo[node]]
4264 parents = [repo[node]]
4242 if rej:
4265 if rej:
4243 ui.write_err(_(b"patch applied partially\n"))
4266 ui.write_err(_(b"patch applied partially\n"))
4244 ui.write_err(
4267 ui.write_err(
4245 _(
4268 _(
4246 b"(fix the .rej files and run "
4269 b"(fix the .rej files and run "
4247 b"`hg commit --amend`)\n"
4270 b"`hg commit --amend`)\n"
4248 )
4271 )
4249 )
4272 )
4250 ret = 1
4273 ret = 1
4251 break
4274 break
4252
4275
4253 if not haspatch:
4276 if not haspatch:
4254 raise error.Abort(_(b'%s: no diffs found') % patchurl)
4277 raise error.Abort(_(b'%s: no diffs found') % patchurl)
4255
4278
4256 if msgs:
4279 if msgs:
4257 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4280 repo.savecommitmessage(b'\n* * *\n'.join(msgs))
4258 return ret
4281 return ret
4259
4282
4260
4283
4261 @command(
4284 @command(
4262 b'incoming|in',
4285 b'incoming|in',
4263 [
4286 [
4264 (
4287 (
4265 b'f',
4288 b'f',
4266 b'force',
4289 b'force',
4267 None,
4290 None,
4268 _(b'run even if remote repository is unrelated'),
4291 _(b'run even if remote repository is unrelated'),
4269 ),
4292 ),
4270 (b'n', b'newest-first', None, _(b'show newest record first')),
4293 (b'n', b'newest-first', None, _(b'show newest record first')),
4271 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4294 (b'', b'bundle', b'', _(b'file to store the bundles into'), _(b'FILE')),
4272 (
4295 (
4273 b'r',
4296 b'r',
4274 b'rev',
4297 b'rev',
4275 [],
4298 [],
4276 _(b'a remote changeset intended to be added'),
4299 _(b'a remote changeset intended to be added'),
4277 _(b'REV'),
4300 _(b'REV'),
4278 ),
4301 ),
4279 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4302 (b'B', b'bookmarks', False, _(b"compare bookmarks")),
4280 (
4303 (
4281 b'b',
4304 b'b',
4282 b'branch',
4305 b'branch',
4283 [],
4306 [],
4284 _(b'a specific branch you would like to pull'),
4307 _(b'a specific branch you would like to pull'),
4285 _(b'BRANCH'),
4308 _(b'BRANCH'),
4286 ),
4309 ),
4287 ]
4310 ]
4288 + logopts
4311 + logopts
4289 + remoteopts
4312 + remoteopts
4290 + subrepoopts,
4313 + subrepoopts,
4291 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4314 _(b'[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
4292 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4315 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4293 )
4316 )
4294 def incoming(ui, repo, source=b"default", **opts):
4317 def incoming(ui, repo, source=b"default", **opts):
4295 """show new changesets found in source
4318 """show new changesets found in source
4296
4319
4297 Show new changesets found in the specified path/URL or the default
4320 Show new changesets found in the specified path/URL or the default
4298 pull location. These are the changesets that would have been pulled
4321 pull location. These are the changesets that would have been pulled
4299 by :hg:`pull` at the time you issued this command.
4322 by :hg:`pull` at the time you issued this command.
4300
4323
4301 See pull for valid source format details.
4324 See pull for valid source format details.
4302
4325
4303 .. container:: verbose
4326 .. container:: verbose
4304
4327
4305 With -B/--bookmarks, the result of bookmark comparison between
4328 With -B/--bookmarks, the result of bookmark comparison between
4306 local and remote repositories is displayed. With -v/--verbose,
4329 local and remote repositories is displayed. With -v/--verbose,
4307 status is also displayed for each bookmark like below::
4330 status is also displayed for each bookmark like below::
4308
4331
4309 BM1 01234567890a added
4332 BM1 01234567890a added
4310 BM2 1234567890ab advanced
4333 BM2 1234567890ab advanced
4311 BM3 234567890abc diverged
4334 BM3 234567890abc diverged
4312 BM4 34567890abcd changed
4335 BM4 34567890abcd changed
4313
4336
4314 The action taken locally when pulling depends on the
4337 The action taken locally when pulling depends on the
4315 status of each bookmark:
4338 status of each bookmark:
4316
4339
4317 :``added``: pull will create it
4340 :``added``: pull will create it
4318 :``advanced``: pull will update it
4341 :``advanced``: pull will update it
4319 :``diverged``: pull will create a divergent bookmark
4342 :``diverged``: pull will create a divergent bookmark
4320 :``changed``: result depends on remote changesets
4343 :``changed``: result depends on remote changesets
4321
4344
4322 From the point of view of pulling behavior, bookmark
4345 From the point of view of pulling behavior, bookmark
4323 existing only in the remote repository are treated as ``added``,
4346 existing only in the remote repository are treated as ``added``,
4324 even if it is in fact locally deleted.
4347 even if it is in fact locally deleted.
4325
4348
4326 .. container:: verbose
4349 .. container:: verbose
4327
4350
4328 For remote repository, using --bundle avoids downloading the
4351 For remote repository, using --bundle avoids downloading the
4329 changesets twice if the incoming is followed by a pull.
4352 changesets twice if the incoming is followed by a pull.
4330
4353
4331 Examples:
4354 Examples:
4332
4355
4333 - show incoming changes with patches and full description::
4356 - show incoming changes with patches and full description::
4334
4357
4335 hg incoming -vp
4358 hg incoming -vp
4336
4359
4337 - show incoming changes excluding merges, store a bundle::
4360 - show incoming changes excluding merges, store a bundle::
4338
4361
4339 hg in -vpM --bundle incoming.hg
4362 hg in -vpM --bundle incoming.hg
4340 hg pull incoming.hg
4363 hg pull incoming.hg
4341
4364
4342 - briefly list changes inside a bundle::
4365 - briefly list changes inside a bundle::
4343
4366
4344 hg in changes.hg -T "{desc|firstline}\\n"
4367 hg in changes.hg -T "{desc|firstline}\\n"
4345
4368
4346 Returns 0 if there are incoming changes, 1 otherwise.
4369 Returns 0 if there are incoming changes, 1 otherwise.
4347 """
4370 """
4348 opts = pycompat.byteskwargs(opts)
4371 opts = pycompat.byteskwargs(opts)
4349 if opts.get(b'graph'):
4372 if opts.get(b'graph'):
4350 logcmdutil.checkunsupportedgraphflags([], opts)
4373 logcmdutil.checkunsupportedgraphflags([], opts)
4351
4374
4352 def display(other, chlist, displayer):
4375 def display(other, chlist, displayer):
4353 revdag = logcmdutil.graphrevs(other, chlist, opts)
4376 revdag = logcmdutil.graphrevs(other, chlist, opts)
4354 logcmdutil.displaygraph(
4377 logcmdutil.displaygraph(
4355 ui, repo, revdag, displayer, graphmod.asciiedges
4378 ui, repo, revdag, displayer, graphmod.asciiedges
4356 )
4379 )
4357
4380
4358 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4381 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4359 return 0
4382 return 0
4360
4383
4361 if opts.get(b'bundle') and opts.get(b'subrepos'):
4384 if opts.get(b'bundle') and opts.get(b'subrepos'):
4362 raise error.Abort(_(b'cannot combine --bundle and --subrepos'))
4385 raise error.Abort(_(b'cannot combine --bundle and --subrepos'))
4363
4386
4364 if opts.get(b'bookmarks'):
4387 if opts.get(b'bookmarks'):
4365 source, branches = hg.parseurl(
4388 source, branches = hg.parseurl(
4366 ui.expandpath(source), opts.get(b'branch')
4389 ui.expandpath(source), opts.get(b'branch')
4367 )
4390 )
4368 other = hg.peer(repo, opts, source)
4391 other = hg.peer(repo, opts, source)
4369 if b'bookmarks' not in other.listkeys(b'namespaces'):
4392 if b'bookmarks' not in other.listkeys(b'namespaces'):
4370 ui.warn(_(b"remote doesn't support bookmarks\n"))
4393 ui.warn(_(b"remote doesn't support bookmarks\n"))
4371 return 0
4394 return 0
4372 ui.pager(b'incoming')
4395 ui.pager(b'incoming')
4373 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4396 ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
4374 return bookmarks.incoming(ui, repo, other)
4397 return bookmarks.incoming(ui, repo, other)
4375
4398
4376 repo._subtoppath = ui.expandpath(source)
4399 repo._subtoppath = ui.expandpath(source)
4377 try:
4400 try:
4378 return hg.incoming(ui, repo, source, opts)
4401 return hg.incoming(ui, repo, source, opts)
4379 finally:
4402 finally:
4380 del repo._subtoppath
4403 del repo._subtoppath
4381
4404
4382
4405
4383 @command(
4406 @command(
4384 b'init',
4407 b'init',
4385 remoteopts,
4408 remoteopts,
4386 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4409 _(b'[-e CMD] [--remotecmd CMD] [DEST]'),
4387 helpcategory=command.CATEGORY_REPO_CREATION,
4410 helpcategory=command.CATEGORY_REPO_CREATION,
4388 helpbasic=True,
4411 helpbasic=True,
4389 norepo=True,
4412 norepo=True,
4390 )
4413 )
4391 def init(ui, dest=b".", **opts):
4414 def init(ui, dest=b".", **opts):
4392 """create a new repository in the given directory
4415 """create a new repository in the given directory
4393
4416
4394 Initialize a new repository in the given directory. If the given
4417 Initialize a new repository in the given directory. If the given
4395 directory does not exist, it will be created.
4418 directory does not exist, it will be created.
4396
4419
4397 If no directory is given, the current directory is used.
4420 If no directory is given, the current directory is used.
4398
4421
4399 It is possible to specify an ``ssh://`` URL as the destination.
4422 It is possible to specify an ``ssh://`` URL as the destination.
4400 See :hg:`help urls` for more information.
4423 See :hg:`help urls` for more information.
4401
4424
4402 Returns 0 on success.
4425 Returns 0 on success.
4403 """
4426 """
4404 opts = pycompat.byteskwargs(opts)
4427 opts = pycompat.byteskwargs(opts)
4405 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4428 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4406
4429
4407
4430
4408 @command(
4431 @command(
4409 b'locate',
4432 b'locate',
4410 [
4433 [
4411 (
4434 (
4412 b'r',
4435 b'r',
4413 b'rev',
4436 b'rev',
4414 b'',
4437 b'',
4415 _(b'search the repository as it is in REV'),
4438 _(b'search the repository as it is in REV'),
4416 _(b'REV'),
4439 _(b'REV'),
4417 ),
4440 ),
4418 (
4441 (
4419 b'0',
4442 b'0',
4420 b'print0',
4443 b'print0',
4421 None,
4444 None,
4422 _(b'end filenames with NUL, for use with xargs'),
4445 _(b'end filenames with NUL, for use with xargs'),
4423 ),
4446 ),
4424 (
4447 (
4425 b'f',
4448 b'f',
4426 b'fullpath',
4449 b'fullpath',
4427 None,
4450 None,
4428 _(b'print complete paths from the filesystem root'),
4451 _(b'print complete paths from the filesystem root'),
4429 ),
4452 ),
4430 ]
4453 ]
4431 + walkopts,
4454 + walkopts,
4432 _(b'[OPTION]... [PATTERN]...'),
4455 _(b'[OPTION]... [PATTERN]...'),
4433 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4456 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4434 )
4457 )
4435 def locate(ui, repo, *pats, **opts):
4458 def locate(ui, repo, *pats, **opts):
4436 """locate files matching specific patterns (DEPRECATED)
4459 """locate files matching specific patterns (DEPRECATED)
4437
4460
4438 Print files under Mercurial control in the working directory whose
4461 Print files under Mercurial control in the working directory whose
4439 names match the given patterns.
4462 names match the given patterns.
4440
4463
4441 By default, this command searches all directories in the working
4464 By default, this command searches all directories in the working
4442 directory. To search just the current directory and its
4465 directory. To search just the current directory and its
4443 subdirectories, use "--include .".
4466 subdirectories, use "--include .".
4444
4467
4445 If no patterns are given to match, this command prints the names
4468 If no patterns are given to match, this command prints the names
4446 of all files under Mercurial control in the working directory.
4469 of all files under Mercurial control in the working directory.
4447
4470
4448 If you want to feed the output of this command into the "xargs"
4471 If you want to feed the output of this command into the "xargs"
4449 command, use the -0 option to both this command and "xargs". This
4472 command, use the -0 option to both this command and "xargs". This
4450 will avoid the problem of "xargs" treating single filenames that
4473 will avoid the problem of "xargs" treating single filenames that
4451 contain whitespace as multiple filenames.
4474 contain whitespace as multiple filenames.
4452
4475
4453 See :hg:`help files` for a more versatile command.
4476 See :hg:`help files` for a more versatile command.
4454
4477
4455 Returns 0 if a match is found, 1 otherwise.
4478 Returns 0 if a match is found, 1 otherwise.
4456 """
4479 """
4457 opts = pycompat.byteskwargs(opts)
4480 opts = pycompat.byteskwargs(opts)
4458 if opts.get(b'print0'):
4481 if opts.get(b'print0'):
4459 end = b'\0'
4482 end = b'\0'
4460 else:
4483 else:
4461 end = b'\n'
4484 end = b'\n'
4462 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4485 ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
4463
4486
4464 ret = 1
4487 ret = 1
4465 m = scmutil.match(
4488 m = scmutil.match(
4466 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4489 ctx, pats, opts, default=b'relglob', badfn=lambda x, y: False
4467 )
4490 )
4468
4491
4469 ui.pager(b'locate')
4492 ui.pager(b'locate')
4470 if ctx.rev() is None:
4493 if ctx.rev() is None:
4471 # When run on the working copy, "locate" includes removed files, so
4494 # When run on the working copy, "locate" includes removed files, so
4472 # we get the list of files from the dirstate.
4495 # we get the list of files from the dirstate.
4473 filesgen = sorted(repo.dirstate.matches(m))
4496 filesgen = sorted(repo.dirstate.matches(m))
4474 else:
4497 else:
4475 filesgen = ctx.matches(m)
4498 filesgen = ctx.matches(m)
4476 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4499 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=bool(pats))
4477 for abs in filesgen:
4500 for abs in filesgen:
4478 if opts.get(b'fullpath'):
4501 if opts.get(b'fullpath'):
4479 ui.write(repo.wjoin(abs), end)
4502 ui.write(repo.wjoin(abs), end)
4480 else:
4503 else:
4481 ui.write(uipathfn(abs), end)
4504 ui.write(uipathfn(abs), end)
4482 ret = 0
4505 ret = 0
4483
4506
4484 return ret
4507 return ret
4485
4508
4486
4509
4487 @command(
4510 @command(
4488 b'log|history',
4511 b'log|history',
4489 [
4512 [
4490 (
4513 (
4491 b'f',
4514 b'f',
4492 b'follow',
4515 b'follow',
4493 None,
4516 None,
4494 _(
4517 _(
4495 b'follow changeset history, or file history across copies and renames'
4518 b'follow changeset history, or file history across copies and renames'
4496 ),
4519 ),
4497 ),
4520 ),
4498 (
4521 (
4499 b'',
4522 b'',
4500 b'follow-first',
4523 b'follow-first',
4501 None,
4524 None,
4502 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4525 _(b'only follow the first parent of merge changesets (DEPRECATED)'),
4503 ),
4526 ),
4504 (
4527 (
4505 b'd',
4528 b'd',
4506 b'date',
4529 b'date',
4507 b'',
4530 b'',
4508 _(b'show revisions matching date spec'),
4531 _(b'show revisions matching date spec'),
4509 _(b'DATE'),
4532 _(b'DATE'),
4510 ),
4533 ),
4511 (b'C', b'copies', None, _(b'show copied files')),
4534 (b'C', b'copies', None, _(b'show copied files')),
4512 (
4535 (
4513 b'k',
4536 b'k',
4514 b'keyword',
4537 b'keyword',
4515 [],
4538 [],
4516 _(b'do case-insensitive search for a given text'),
4539 _(b'do case-insensitive search for a given text'),
4517 _(b'TEXT'),
4540 _(b'TEXT'),
4518 ),
4541 ),
4519 (
4542 (
4520 b'r',
4543 b'r',
4521 b'rev',
4544 b'rev',
4522 [],
4545 [],
4523 _(b'show the specified revision or revset'),
4546 _(b'show the specified revision or revset'),
4524 _(b'REV'),
4547 _(b'REV'),
4525 ),
4548 ),
4526 (
4549 (
4527 b'L',
4550 b'L',
4528 b'line-range',
4551 b'line-range',
4529 [],
4552 [],
4530 _(b'follow line range of specified file (EXPERIMENTAL)'),
4553 _(b'follow line range of specified file (EXPERIMENTAL)'),
4531 _(b'FILE,RANGE'),
4554 _(b'FILE,RANGE'),
4532 ),
4555 ),
4533 (
4556 (
4534 b'',
4557 b'',
4535 b'removed',
4558 b'removed',
4536 None,
4559 None,
4537 _(b'include revisions where files were removed'),
4560 _(b'include revisions where files were removed'),
4538 ),
4561 ),
4539 (
4562 (
4540 b'm',
4563 b'm',
4541 b'only-merges',
4564 b'only-merges',
4542 None,
4565 None,
4543 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4566 _(b'show only merges (DEPRECATED) (use -r "merge()" instead)'),
4544 ),
4567 ),
4545 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4568 (b'u', b'user', [], _(b'revisions committed by user'), _(b'USER')),
4546 (
4569 (
4547 b'',
4570 b'',
4548 b'only-branch',
4571 b'only-branch',
4549 [],
4572 [],
4550 _(
4573 _(
4551 b'show only changesets within the given named branch (DEPRECATED)'
4574 b'show only changesets within the given named branch (DEPRECATED)'
4552 ),
4575 ),
4553 _(b'BRANCH'),
4576 _(b'BRANCH'),
4554 ),
4577 ),
4555 (
4578 (
4556 b'b',
4579 b'b',
4557 b'branch',
4580 b'branch',
4558 [],
4581 [],
4559 _(b'show changesets within the given named branch'),
4582 _(b'show changesets within the given named branch'),
4560 _(b'BRANCH'),
4583 _(b'BRANCH'),
4561 ),
4584 ),
4562 (
4585 (
4563 b'P',
4586 b'P',
4564 b'prune',
4587 b'prune',
4565 [],
4588 [],
4566 _(b'do not display revision or any of its ancestors'),
4589 _(b'do not display revision or any of its ancestors'),
4567 _(b'REV'),
4590 _(b'REV'),
4568 ),
4591 ),
4569 ]
4592 ]
4570 + logopts
4593 + logopts
4571 + walkopts,
4594 + walkopts,
4572 _(b'[OPTION]... [FILE]'),
4595 _(b'[OPTION]... [FILE]'),
4573 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4596 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4574 helpbasic=True,
4597 helpbasic=True,
4575 inferrepo=True,
4598 inferrepo=True,
4576 intents={INTENT_READONLY},
4599 intents={INTENT_READONLY},
4577 )
4600 )
4578 def log(ui, repo, *pats, **opts):
4601 def log(ui, repo, *pats, **opts):
4579 """show revision history of entire repository or files
4602 """show revision history of entire repository or files
4580
4603
4581 Print the revision history of the specified files or the entire
4604 Print the revision history of the specified files or the entire
4582 project.
4605 project.
4583
4606
4584 If no revision range is specified, the default is ``tip:0`` unless
4607 If no revision range is specified, the default is ``tip:0`` unless
4585 --follow is set, in which case the working directory parent is
4608 --follow is set, in which case the working directory parent is
4586 used as the starting revision.
4609 used as the starting revision.
4587
4610
4588 File history is shown without following rename or copy history of
4611 File history is shown without following rename or copy history of
4589 files. Use -f/--follow with a filename to follow history across
4612 files. Use -f/--follow with a filename to follow history across
4590 renames and copies. --follow without a filename will only show
4613 renames and copies. --follow without a filename will only show
4591 ancestors of the starting revision.
4614 ancestors of the starting revision.
4592
4615
4593 By default this command prints revision number and changeset id,
4616 By default this command prints revision number and changeset id,
4594 tags, non-trivial parents, user, date and time, and a summary for
4617 tags, non-trivial parents, user, date and time, and a summary for
4595 each commit. When the -v/--verbose switch is used, the list of
4618 each commit. When the -v/--verbose switch is used, the list of
4596 changed files and full commit message are shown.
4619 changed files and full commit message are shown.
4597
4620
4598 With --graph the revisions are shown as an ASCII art DAG with the most
4621 With --graph the revisions are shown as an ASCII art DAG with the most
4599 recent changeset at the top.
4622 recent changeset at the top.
4600 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4623 'o' is a changeset, '@' is a working directory parent, '%' is a changeset
4601 involved in an unresolved merge conflict, '_' closes a branch,
4624 involved in an unresolved merge conflict, '_' closes a branch,
4602 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4625 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
4603 changeset from the lines below is a parent of the 'o' merge on the same
4626 changeset from the lines below is a parent of the 'o' merge on the same
4604 line.
4627 line.
4605 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4628 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
4606 of a '|' indicates one or more revisions in a path are omitted.
4629 of a '|' indicates one or more revisions in a path are omitted.
4607
4630
4608 .. container:: verbose
4631 .. container:: verbose
4609
4632
4610 Use -L/--line-range FILE,M:N options to follow the history of lines
4633 Use -L/--line-range FILE,M:N options to follow the history of lines
4611 from M to N in FILE. With -p/--patch only diff hunks affecting
4634 from M to N in FILE. With -p/--patch only diff hunks affecting
4612 specified line range will be shown. This option requires --follow;
4635 specified line range will be shown. This option requires --follow;
4613 it can be specified multiple times. Currently, this option is not
4636 it can be specified multiple times. Currently, this option is not
4614 compatible with --graph. This option is experimental.
4637 compatible with --graph. This option is experimental.
4615
4638
4616 .. note::
4639 .. note::
4617
4640
4618 :hg:`log --patch` may generate unexpected diff output for merge
4641 :hg:`log --patch` may generate unexpected diff output for merge
4619 changesets, as it will only compare the merge changeset against
4642 changesets, as it will only compare the merge changeset against
4620 its first parent. Also, only files different from BOTH parents
4643 its first parent. Also, only files different from BOTH parents
4621 will appear in files:.
4644 will appear in files:.
4622
4645
4623 .. note::
4646 .. note::
4624
4647
4625 For performance reasons, :hg:`log FILE` may omit duplicate changes
4648 For performance reasons, :hg:`log FILE` may omit duplicate changes
4626 made on branches and will not show removals or mode changes. To
4649 made on branches and will not show removals or mode changes. To
4627 see all such changes, use the --removed switch.
4650 see all such changes, use the --removed switch.
4628
4651
4629 .. container:: verbose
4652 .. container:: verbose
4630
4653
4631 .. note::
4654 .. note::
4632
4655
4633 The history resulting from -L/--line-range options depends on diff
4656 The history resulting from -L/--line-range options depends on diff
4634 options; for instance if white-spaces are ignored, respective changes
4657 options; for instance if white-spaces are ignored, respective changes
4635 with only white-spaces in specified line range will not be listed.
4658 with only white-spaces in specified line range will not be listed.
4636
4659
4637 .. container:: verbose
4660 .. container:: verbose
4638
4661
4639 Some examples:
4662 Some examples:
4640
4663
4641 - changesets with full descriptions and file lists::
4664 - changesets with full descriptions and file lists::
4642
4665
4643 hg log -v
4666 hg log -v
4644
4667
4645 - changesets ancestral to the working directory::
4668 - changesets ancestral to the working directory::
4646
4669
4647 hg log -f
4670 hg log -f
4648
4671
4649 - last 10 commits on the current branch::
4672 - last 10 commits on the current branch::
4650
4673
4651 hg log -l 10 -b .
4674 hg log -l 10 -b .
4652
4675
4653 - changesets showing all modifications of a file, including removals::
4676 - changesets showing all modifications of a file, including removals::
4654
4677
4655 hg log --removed file.c
4678 hg log --removed file.c
4656
4679
4657 - all changesets that touch a directory, with diffs, excluding merges::
4680 - all changesets that touch a directory, with diffs, excluding merges::
4658
4681
4659 hg log -Mp lib/
4682 hg log -Mp lib/
4660
4683
4661 - all revision numbers that match a keyword::
4684 - all revision numbers that match a keyword::
4662
4685
4663 hg log -k bug --template "{rev}\\n"
4686 hg log -k bug --template "{rev}\\n"
4664
4687
4665 - the full hash identifier of the working directory parent::
4688 - the full hash identifier of the working directory parent::
4666
4689
4667 hg log -r . --template "{node}\\n"
4690 hg log -r . --template "{node}\\n"
4668
4691
4669 - list available log templates::
4692 - list available log templates::
4670
4693
4671 hg log -T list
4694 hg log -T list
4672
4695
4673 - check if a given changeset is included in a tagged release::
4696 - check if a given changeset is included in a tagged release::
4674
4697
4675 hg log -r "a21ccf and ancestor(1.9)"
4698 hg log -r "a21ccf and ancestor(1.9)"
4676
4699
4677 - find all changesets by some user in a date range::
4700 - find all changesets by some user in a date range::
4678
4701
4679 hg log -k alice -d "may 2008 to jul 2008"
4702 hg log -k alice -d "may 2008 to jul 2008"
4680
4703
4681 - summary of all changesets after the last tag::
4704 - summary of all changesets after the last tag::
4682
4705
4683 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4706 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4684
4707
4685 - changesets touching lines 13 to 23 for file.c::
4708 - changesets touching lines 13 to 23 for file.c::
4686
4709
4687 hg log -L file.c,13:23
4710 hg log -L file.c,13:23
4688
4711
4689 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4712 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
4690 main.c with patch::
4713 main.c with patch::
4691
4714
4692 hg log -L file.c,13:23 -L main.c,2:6 -p
4715 hg log -L file.c,13:23 -L main.c,2:6 -p
4693
4716
4694 See :hg:`help dates` for a list of formats valid for -d/--date.
4717 See :hg:`help dates` for a list of formats valid for -d/--date.
4695
4718
4696 See :hg:`help revisions` for more about specifying and ordering
4719 See :hg:`help revisions` for more about specifying and ordering
4697 revisions.
4720 revisions.
4698
4721
4699 See :hg:`help templates` for more about pre-packaged styles and
4722 See :hg:`help templates` for more about pre-packaged styles and
4700 specifying custom templates. The default template used by the log
4723 specifying custom templates. The default template used by the log
4701 command can be customized via the ``ui.logtemplate`` configuration
4724 command can be customized via the ``ui.logtemplate`` configuration
4702 setting.
4725 setting.
4703
4726
4704 Returns 0 on success.
4727 Returns 0 on success.
4705
4728
4706 """
4729 """
4707 opts = pycompat.byteskwargs(opts)
4730 opts = pycompat.byteskwargs(opts)
4708 linerange = opts.get(b'line_range')
4731 linerange = opts.get(b'line_range')
4709
4732
4710 if linerange and not opts.get(b'follow'):
4733 if linerange and not opts.get(b'follow'):
4711 raise error.Abort(_(b'--line-range requires --follow'))
4734 raise error.Abort(_(b'--line-range requires --follow'))
4712
4735
4713 if linerange and pats:
4736 if linerange and pats:
4714 # TODO: take pats as patterns with no line-range filter
4737 # TODO: take pats as patterns with no line-range filter
4715 raise error.Abort(
4738 raise error.Abort(
4716 _(b'FILE arguments are not compatible with --line-range option')
4739 _(b'FILE arguments are not compatible with --line-range option')
4717 )
4740 )
4718
4741
4719 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4742 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4720 revs, differ = logcmdutil.getrevs(repo, pats, opts)
4743 revs, differ = logcmdutil.getrevs(repo, pats, opts)
4721 if linerange:
4744 if linerange:
4722 # TODO: should follow file history from logcmdutil._initialrevs(),
4745 # TODO: should follow file history from logcmdutil._initialrevs(),
4723 # then filter the result by logcmdutil._makerevset() and --limit
4746 # then filter the result by logcmdutil._makerevset() and --limit
4724 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4747 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
4725
4748
4726 getcopies = None
4749 getcopies = None
4727 if opts.get(b'copies'):
4750 if opts.get(b'copies'):
4728 endrev = None
4751 endrev = None
4729 if revs:
4752 if revs:
4730 endrev = revs.max() + 1
4753 endrev = revs.max() + 1
4731 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4754 getcopies = scmutil.getcopiesfn(repo, endrev=endrev)
4732
4755
4733 ui.pager(b'log')
4756 ui.pager(b'log')
4734 displayer = logcmdutil.changesetdisplayer(
4757 displayer = logcmdutil.changesetdisplayer(
4735 ui, repo, opts, differ, buffered=True
4758 ui, repo, opts, differ, buffered=True
4736 )
4759 )
4737 if opts.get(b'graph'):
4760 if opts.get(b'graph'):
4738 displayfn = logcmdutil.displaygraphrevs
4761 displayfn = logcmdutil.displaygraphrevs
4739 else:
4762 else:
4740 displayfn = logcmdutil.displayrevs
4763 displayfn = logcmdutil.displayrevs
4741 displayfn(ui, repo, revs, displayer, getcopies)
4764 displayfn(ui, repo, revs, displayer, getcopies)
4742
4765
4743
4766
4744 @command(
4767 @command(
4745 b'manifest',
4768 b'manifest',
4746 [
4769 [
4747 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4770 (b'r', b'rev', b'', _(b'revision to display'), _(b'REV')),
4748 (b'', b'all', False, _(b"list files from all revisions")),
4771 (b'', b'all', False, _(b"list files from all revisions")),
4749 ]
4772 ]
4750 + formatteropts,
4773 + formatteropts,
4751 _(b'[-r REV]'),
4774 _(b'[-r REV]'),
4752 helpcategory=command.CATEGORY_MAINTENANCE,
4775 helpcategory=command.CATEGORY_MAINTENANCE,
4753 intents={INTENT_READONLY},
4776 intents={INTENT_READONLY},
4754 )
4777 )
4755 def manifest(ui, repo, node=None, rev=None, **opts):
4778 def manifest(ui, repo, node=None, rev=None, **opts):
4756 """output the current or given revision of the project manifest
4779 """output the current or given revision of the project manifest
4757
4780
4758 Print a list of version controlled files for the given revision.
4781 Print a list of version controlled files for the given revision.
4759 If no revision is given, the first parent of the working directory
4782 If no revision is given, the first parent of the working directory
4760 is used, or the null revision if no revision is checked out.
4783 is used, or the null revision if no revision is checked out.
4761
4784
4762 With -v, print file permissions, symlink and executable bits.
4785 With -v, print file permissions, symlink and executable bits.
4763 With --debug, print file revision hashes.
4786 With --debug, print file revision hashes.
4764
4787
4765 If option --all is specified, the list of all files from all revisions
4788 If option --all is specified, the list of all files from all revisions
4766 is printed. This includes deleted and renamed files.
4789 is printed. This includes deleted and renamed files.
4767
4790
4768 Returns 0 on success.
4791 Returns 0 on success.
4769 """
4792 """
4770 opts = pycompat.byteskwargs(opts)
4793 opts = pycompat.byteskwargs(opts)
4771 fm = ui.formatter(b'manifest', opts)
4794 fm = ui.formatter(b'manifest', opts)
4772
4795
4773 if opts.get(b'all'):
4796 if opts.get(b'all'):
4774 if rev or node:
4797 if rev or node:
4775 raise error.Abort(_(b"can't specify a revision with --all"))
4798 raise error.Abort(_(b"can't specify a revision with --all"))
4776
4799
4777 res = set()
4800 res = set()
4778 for rev in repo:
4801 for rev in repo:
4779 ctx = repo[rev]
4802 ctx = repo[rev]
4780 res |= set(ctx.files())
4803 res |= set(ctx.files())
4781
4804
4782 ui.pager(b'manifest')
4805 ui.pager(b'manifest')
4783 for f in sorted(res):
4806 for f in sorted(res):
4784 fm.startitem()
4807 fm.startitem()
4785 fm.write(b"path", b'%s\n', f)
4808 fm.write(b"path", b'%s\n', f)
4786 fm.end()
4809 fm.end()
4787 return
4810 return
4788
4811
4789 if rev and node:
4812 if rev and node:
4790 raise error.Abort(_(b"please specify just one revision"))
4813 raise error.Abort(_(b"please specify just one revision"))
4791
4814
4792 if not node:
4815 if not node:
4793 node = rev
4816 node = rev
4794
4817
4795 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4818 char = {b'l': b'@', b'x': b'*', b'': b'', b't': b'd'}
4796 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4819 mode = {b'l': b'644', b'x': b'755', b'': b'644', b't': b'755'}
4797 if node:
4820 if node:
4798 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4821 repo = scmutil.unhidehashlikerevs(repo, [node], b'nowarn')
4799 ctx = scmutil.revsingle(repo, node)
4822 ctx = scmutil.revsingle(repo, node)
4800 mf = ctx.manifest()
4823 mf = ctx.manifest()
4801 ui.pager(b'manifest')
4824 ui.pager(b'manifest')
4802 for f in ctx:
4825 for f in ctx:
4803 fm.startitem()
4826 fm.startitem()
4804 fm.context(ctx=ctx)
4827 fm.context(ctx=ctx)
4805 fl = ctx[f].flags()
4828 fl = ctx[f].flags()
4806 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4829 fm.condwrite(ui.debugflag, b'hash', b'%s ', hex(mf[f]))
4807 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4830 fm.condwrite(ui.verbose, b'mode type', b'%s %1s ', mode[fl], char[fl])
4808 fm.write(b'path', b'%s\n', f)
4831 fm.write(b'path', b'%s\n', f)
4809 fm.end()
4832 fm.end()
4810
4833
4811
4834
4812 @command(
4835 @command(
4813 b'merge',
4836 b'merge',
4814 [
4837 [
4815 (
4838 (
4816 b'f',
4839 b'f',
4817 b'force',
4840 b'force',
4818 None,
4841 None,
4819 _(b'force a merge including outstanding changes (DEPRECATED)'),
4842 _(b'force a merge including outstanding changes (DEPRECATED)'),
4820 ),
4843 ),
4821 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4844 (b'r', b'rev', b'', _(b'revision to merge'), _(b'REV')),
4822 (
4845 (
4823 b'P',
4846 b'P',
4824 b'preview',
4847 b'preview',
4825 None,
4848 None,
4826 _(b'review revisions to merge (no merge is performed)'),
4849 _(b'review revisions to merge (no merge is performed)'),
4827 ),
4850 ),
4828 (b'', b'abort', None, _(b'abort the ongoing merge')),
4851 (b'', b'abort', None, _(b'abort the ongoing merge')),
4829 ]
4852 ]
4830 + mergetoolopts,
4853 + mergetoolopts,
4831 _(b'[-P] [[-r] REV]'),
4854 _(b'[-P] [[-r] REV]'),
4832 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4855 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
4833 helpbasic=True,
4856 helpbasic=True,
4834 )
4857 )
4835 def merge(ui, repo, node=None, **opts):
4858 def merge(ui, repo, node=None, **opts):
4836 """merge another revision into working directory
4859 """merge another revision into working directory
4837
4860
4838 The current working directory is updated with all changes made in
4861 The current working directory is updated with all changes made in
4839 the requested revision since the last common predecessor revision.
4862 the requested revision since the last common predecessor revision.
4840
4863
4841 Files that changed between either parent are marked as changed for
4864 Files that changed between either parent are marked as changed for
4842 the next commit and a commit must be performed before any further
4865 the next commit and a commit must be performed before any further
4843 updates to the repository are allowed. The next commit will have
4866 updates to the repository are allowed. The next commit will have
4844 two parents.
4867 two parents.
4845
4868
4846 ``--tool`` can be used to specify the merge tool used for file
4869 ``--tool`` can be used to specify the merge tool used for file
4847 merges. It overrides the HGMERGE environment variable and your
4870 merges. It overrides the HGMERGE environment variable and your
4848 configuration files. See :hg:`help merge-tools` for options.
4871 configuration files. See :hg:`help merge-tools` for options.
4849
4872
4850 If no revision is specified, the working directory's parent is a
4873 If no revision is specified, the working directory's parent is a
4851 head revision, and the current branch contains exactly one other
4874 head revision, and the current branch contains exactly one other
4852 head, the other head is merged with by default. Otherwise, an
4875 head, the other head is merged with by default. Otherwise, an
4853 explicit revision with which to merge must be provided.
4876 explicit revision with which to merge must be provided.
4854
4877
4855 See :hg:`help resolve` for information on handling file conflicts.
4878 See :hg:`help resolve` for information on handling file conflicts.
4856
4879
4857 To undo an uncommitted merge, use :hg:`merge --abort` which
4880 To undo an uncommitted merge, use :hg:`merge --abort` which
4858 will check out a clean copy of the original merge parent, losing
4881 will check out a clean copy of the original merge parent, losing
4859 all changes.
4882 all changes.
4860
4883
4861 Returns 0 on success, 1 if there are unresolved files.
4884 Returns 0 on success, 1 if there are unresolved files.
4862 """
4885 """
4863
4886
4864 opts = pycompat.byteskwargs(opts)
4887 opts = pycompat.byteskwargs(opts)
4865 abort = opts.get(b'abort')
4888 abort = opts.get(b'abort')
4866 if abort and repo.dirstate.p2() == nullid:
4889 if abort and repo.dirstate.p2() == nullid:
4867 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4890 cmdutil.wrongtooltocontinue(repo, _(b'merge'))
4868 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4891 cmdutil.check_incompatible_arguments(opts, b'abort', [b'rev', b'preview'])
4869 if abort:
4892 if abort:
4870 state = cmdutil.getunfinishedstate(repo)
4893 state = cmdutil.getunfinishedstate(repo)
4871 if state and state._opname != b'merge':
4894 if state and state._opname != b'merge':
4872 raise error.Abort(
4895 raise error.Abort(
4873 _(b'cannot abort merge with %s in progress') % (state._opname),
4896 _(b'cannot abort merge with %s in progress') % (state._opname),
4874 hint=state.hint(),
4897 hint=state.hint(),
4875 )
4898 )
4876 if node:
4899 if node:
4877 raise error.Abort(_(b"cannot specify a node with --abort"))
4900 raise error.Abort(_(b"cannot specify a node with --abort"))
4878 return hg.abortmerge(repo.ui, repo)
4901 return hg.abortmerge(repo.ui, repo)
4879
4902
4880 if opts.get(b'rev') and node:
4903 if opts.get(b'rev') and node:
4881 raise error.Abort(_(b"please specify just one revision"))
4904 raise error.Abort(_(b"please specify just one revision"))
4882 if not node:
4905 if not node:
4883 node = opts.get(b'rev')
4906 node = opts.get(b'rev')
4884
4907
4885 if node:
4908 if node:
4886 ctx = scmutil.revsingle(repo, node)
4909 ctx = scmutil.revsingle(repo, node)
4887 else:
4910 else:
4888 if ui.configbool(b'commands', b'merge.require-rev'):
4911 if ui.configbool(b'commands', b'merge.require-rev'):
4889 raise error.Abort(
4912 raise error.Abort(
4890 _(
4913 _(
4891 b'configuration requires specifying revision to merge '
4914 b'configuration requires specifying revision to merge '
4892 b'with'
4915 b'with'
4893 )
4916 )
4894 )
4917 )
4895 ctx = repo[destutil.destmerge(repo)]
4918 ctx = repo[destutil.destmerge(repo)]
4896
4919
4897 if ctx.node() is None:
4920 if ctx.node() is None:
4898 raise error.Abort(_(b'merging with the working copy has no effect'))
4921 raise error.Abort(_(b'merging with the working copy has no effect'))
4899
4922
4900 if opts.get(b'preview'):
4923 if opts.get(b'preview'):
4901 # find nodes that are ancestors of p2 but not of p1
4924 # find nodes that are ancestors of p2 but not of p1
4902 p1 = repo[b'.'].node()
4925 p1 = repo[b'.'].node()
4903 p2 = ctx.node()
4926 p2 = ctx.node()
4904 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4927 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4905
4928
4906 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4929 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4907 for node in nodes:
4930 for node in nodes:
4908 displayer.show(repo[node])
4931 displayer.show(repo[node])
4909 displayer.close()
4932 displayer.close()
4910 return 0
4933 return 0
4911
4934
4912 # ui.forcemerge is an internal variable, do not document
4935 # ui.forcemerge is an internal variable, do not document
4913 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4936 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
4914 with ui.configoverride(overrides, b'merge'):
4937 with ui.configoverride(overrides, b'merge'):
4915 force = opts.get(b'force')
4938 force = opts.get(b'force')
4916 labels = [b'working copy', b'merge rev']
4939 labels = [b'working copy', b'merge rev']
4917 return hg.merge(ctx, force=force, labels=labels)
4940 return hg.merge(ctx, force=force, labels=labels)
4918
4941
4919
4942
4920 statemod.addunfinished(
4943 statemod.addunfinished(
4921 b'merge',
4944 b'merge',
4922 fname=None,
4945 fname=None,
4923 clearable=True,
4946 clearable=True,
4924 allowcommit=True,
4947 allowcommit=True,
4925 cmdmsg=_(b'outstanding uncommitted merge'),
4948 cmdmsg=_(b'outstanding uncommitted merge'),
4926 abortfunc=hg.abortmerge,
4949 abortfunc=hg.abortmerge,
4927 statushint=_(
4950 statushint=_(
4928 b'To continue: hg commit\nTo abort: hg merge --abort'
4951 b'To continue: hg commit\nTo abort: hg merge --abort'
4929 ),
4952 ),
4930 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4953 cmdhint=_(b"use 'hg commit' or 'hg merge --abort'"),
4931 )
4954 )
4932
4955
4933
4956
4934 @command(
4957 @command(
4935 b'outgoing|out',
4958 b'outgoing|out',
4936 [
4959 [
4937 (
4960 (
4938 b'f',
4961 b'f',
4939 b'force',
4962 b'force',
4940 None,
4963 None,
4941 _(b'run even when the destination is unrelated'),
4964 _(b'run even when the destination is unrelated'),
4942 ),
4965 ),
4943 (
4966 (
4944 b'r',
4967 b'r',
4945 b'rev',
4968 b'rev',
4946 [],
4969 [],
4947 _(b'a changeset intended to be included in the destination'),
4970 _(b'a changeset intended to be included in the destination'),
4948 _(b'REV'),
4971 _(b'REV'),
4949 ),
4972 ),
4950 (b'n', b'newest-first', None, _(b'show newest record first')),
4973 (b'n', b'newest-first', None, _(b'show newest record first')),
4951 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4974 (b'B', b'bookmarks', False, _(b'compare bookmarks')),
4952 (
4975 (
4953 b'b',
4976 b'b',
4954 b'branch',
4977 b'branch',
4955 [],
4978 [],
4956 _(b'a specific branch you would like to push'),
4979 _(b'a specific branch you would like to push'),
4957 _(b'BRANCH'),
4980 _(b'BRANCH'),
4958 ),
4981 ),
4959 ]
4982 ]
4960 + logopts
4983 + logopts
4961 + remoteopts
4984 + remoteopts
4962 + subrepoopts,
4985 + subrepoopts,
4963 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4986 _(b'[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4964 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4987 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4965 )
4988 )
4966 def outgoing(ui, repo, dest=None, **opts):
4989 def outgoing(ui, repo, dest=None, **opts):
4967 """show changesets not found in the destination
4990 """show changesets not found in the destination
4968
4991
4969 Show changesets not found in the specified destination repository
4992 Show changesets not found in the specified destination repository
4970 or the default push location. These are the changesets that would
4993 or the default push location. These are the changesets that would
4971 be pushed if a push was requested.
4994 be pushed if a push was requested.
4972
4995
4973 See pull for details of valid destination formats.
4996 See pull for details of valid destination formats.
4974
4997
4975 .. container:: verbose
4998 .. container:: verbose
4976
4999
4977 With -B/--bookmarks, the result of bookmark comparison between
5000 With -B/--bookmarks, the result of bookmark comparison between
4978 local and remote repositories is displayed. With -v/--verbose,
5001 local and remote repositories is displayed. With -v/--verbose,
4979 status is also displayed for each bookmark like below::
5002 status is also displayed for each bookmark like below::
4980
5003
4981 BM1 01234567890a added
5004 BM1 01234567890a added
4982 BM2 deleted
5005 BM2 deleted
4983 BM3 234567890abc advanced
5006 BM3 234567890abc advanced
4984 BM4 34567890abcd diverged
5007 BM4 34567890abcd diverged
4985 BM5 4567890abcde changed
5008 BM5 4567890abcde changed
4986
5009
4987 The action taken when pushing depends on the
5010 The action taken when pushing depends on the
4988 status of each bookmark:
5011 status of each bookmark:
4989
5012
4990 :``added``: push with ``-B`` will create it
5013 :``added``: push with ``-B`` will create it
4991 :``deleted``: push with ``-B`` will delete it
5014 :``deleted``: push with ``-B`` will delete it
4992 :``advanced``: push will update it
5015 :``advanced``: push will update it
4993 :``diverged``: push with ``-B`` will update it
5016 :``diverged``: push with ``-B`` will update it
4994 :``changed``: push with ``-B`` will update it
5017 :``changed``: push with ``-B`` will update it
4995
5018
4996 From the point of view of pushing behavior, bookmarks
5019 From the point of view of pushing behavior, bookmarks
4997 existing only in the remote repository are treated as
5020 existing only in the remote repository are treated as
4998 ``deleted``, even if it is in fact added remotely.
5021 ``deleted``, even if it is in fact added remotely.
4999
5022
5000 Returns 0 if there are outgoing changes, 1 otherwise.
5023 Returns 0 if there are outgoing changes, 1 otherwise.
5001 """
5024 """
5002 # hg._outgoing() needs to re-resolve the path in order to handle #branch
5025 # hg._outgoing() needs to re-resolve the path in order to handle #branch
5003 # style URLs, so don't overwrite dest.
5026 # style URLs, so don't overwrite dest.
5004 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5027 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5005 if not path:
5028 if not path:
5006 raise error.Abort(
5029 raise error.Abort(
5007 _(b'default repository not configured!'),
5030 _(b'default repository not configured!'),
5008 hint=_(b"see 'hg help config.paths'"),
5031 hint=_(b"see 'hg help config.paths'"),
5009 )
5032 )
5010
5033
5011 opts = pycompat.byteskwargs(opts)
5034 opts = pycompat.byteskwargs(opts)
5012 if opts.get(b'graph'):
5035 if opts.get(b'graph'):
5013 logcmdutil.checkunsupportedgraphflags([], opts)
5036 logcmdutil.checkunsupportedgraphflags([], opts)
5014 o, other = hg._outgoing(ui, repo, dest, opts)
5037 o, other = hg._outgoing(ui, repo, dest, opts)
5015 if not o:
5038 if not o:
5016 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5039 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5017 return
5040 return
5018
5041
5019 revdag = logcmdutil.graphrevs(repo, o, opts)
5042 revdag = logcmdutil.graphrevs(repo, o, opts)
5020 ui.pager(b'outgoing')
5043 ui.pager(b'outgoing')
5021 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
5044 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
5022 logcmdutil.displaygraph(
5045 logcmdutil.displaygraph(
5023 ui, repo, revdag, displayer, graphmod.asciiedges
5046 ui, repo, revdag, displayer, graphmod.asciiedges
5024 )
5047 )
5025 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5048 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5026 return 0
5049 return 0
5027
5050
5028 if opts.get(b'bookmarks'):
5051 if opts.get(b'bookmarks'):
5029 dest = path.pushloc or path.loc
5052 dest = path.pushloc or path.loc
5030 other = hg.peer(repo, opts, dest)
5053 other = hg.peer(repo, opts, dest)
5031 if b'bookmarks' not in other.listkeys(b'namespaces'):
5054 if b'bookmarks' not in other.listkeys(b'namespaces'):
5032 ui.warn(_(b"remote doesn't support bookmarks\n"))
5055 ui.warn(_(b"remote doesn't support bookmarks\n"))
5033 return 0
5056 return 0
5034 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
5057 ui.status(_(b'comparing with %s\n') % util.hidepassword(dest))
5035 ui.pager(b'outgoing')
5058 ui.pager(b'outgoing')
5036 return bookmarks.outgoing(ui, repo, other)
5059 return bookmarks.outgoing(ui, repo, other)
5037
5060
5038 repo._subtoppath = path.pushloc or path.loc
5061 repo._subtoppath = path.pushloc or path.loc
5039 try:
5062 try:
5040 return hg.outgoing(ui, repo, dest, opts)
5063 return hg.outgoing(ui, repo, dest, opts)
5041 finally:
5064 finally:
5042 del repo._subtoppath
5065 del repo._subtoppath
5043
5066
5044
5067
5045 @command(
5068 @command(
5046 b'parents',
5069 b'parents',
5047 [
5070 [
5048 (
5071 (
5049 b'r',
5072 b'r',
5050 b'rev',
5073 b'rev',
5051 b'',
5074 b'',
5052 _(b'show parents of the specified revision'),
5075 _(b'show parents of the specified revision'),
5053 _(b'REV'),
5076 _(b'REV'),
5054 ),
5077 ),
5055 ]
5078 ]
5056 + templateopts,
5079 + templateopts,
5057 _(b'[-r REV] [FILE]'),
5080 _(b'[-r REV] [FILE]'),
5058 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5081 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
5059 inferrepo=True,
5082 inferrepo=True,
5060 )
5083 )
5061 def parents(ui, repo, file_=None, **opts):
5084 def parents(ui, repo, file_=None, **opts):
5062 """show the parents of the working directory or revision (DEPRECATED)
5085 """show the parents of the working directory or revision (DEPRECATED)
5063
5086
5064 Print the working directory's parent revisions. If a revision is
5087 Print the working directory's parent revisions. If a revision is
5065 given via -r/--rev, the parent of that revision will be printed.
5088 given via -r/--rev, the parent of that revision will be printed.
5066 If a file argument is given, the revision in which the file was
5089 If a file argument is given, the revision in which the file was
5067 last changed (before the working directory revision or the
5090 last changed (before the working directory revision or the
5068 argument to --rev if given) is printed.
5091 argument to --rev if given) is printed.
5069
5092
5070 This command is equivalent to::
5093 This command is equivalent to::
5071
5094
5072 hg log -r "p1()+p2()" or
5095 hg log -r "p1()+p2()" or
5073 hg log -r "p1(REV)+p2(REV)" or
5096 hg log -r "p1(REV)+p2(REV)" or
5074 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5097 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5075 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5098 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5076
5099
5077 See :hg:`summary` and :hg:`help revsets` for related information.
5100 See :hg:`summary` and :hg:`help revsets` for related information.
5078
5101
5079 Returns 0 on success.
5102 Returns 0 on success.
5080 """
5103 """
5081
5104
5082 opts = pycompat.byteskwargs(opts)
5105 opts = pycompat.byteskwargs(opts)
5083 rev = opts.get(b'rev')
5106 rev = opts.get(b'rev')
5084 if rev:
5107 if rev:
5085 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5108 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
5086 ctx = scmutil.revsingle(repo, rev, None)
5109 ctx = scmutil.revsingle(repo, rev, None)
5087
5110
5088 if file_:
5111 if file_:
5089 m = scmutil.match(ctx, (file_,), opts)
5112 m = scmutil.match(ctx, (file_,), opts)
5090 if m.anypats() or len(m.files()) != 1:
5113 if m.anypats() or len(m.files()) != 1:
5091 raise error.Abort(_(b'can only specify an explicit filename'))
5114 raise error.Abort(_(b'can only specify an explicit filename'))
5092 file_ = m.files()[0]
5115 file_ = m.files()[0]
5093 filenodes = []
5116 filenodes = []
5094 for cp in ctx.parents():
5117 for cp in ctx.parents():
5095 if not cp:
5118 if not cp:
5096 continue
5119 continue
5097 try:
5120 try:
5098 filenodes.append(cp.filenode(file_))
5121 filenodes.append(cp.filenode(file_))
5099 except error.LookupError:
5122 except error.LookupError:
5100 pass
5123 pass
5101 if not filenodes:
5124 if not filenodes:
5102 raise error.Abort(_(b"'%s' not found in manifest!") % file_)
5125 raise error.Abort(_(b"'%s' not found in manifest!") % file_)
5103 p = []
5126 p = []
5104 for fn in filenodes:
5127 for fn in filenodes:
5105 fctx = repo.filectx(file_, fileid=fn)
5128 fctx = repo.filectx(file_, fileid=fn)
5106 p.append(fctx.node())
5129 p.append(fctx.node())
5107 else:
5130 else:
5108 p = [cp.node() for cp in ctx.parents()]
5131 p = [cp.node() for cp in ctx.parents()]
5109
5132
5110 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5133 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5111 for n in p:
5134 for n in p:
5112 if n != nullid:
5135 if n != nullid:
5113 displayer.show(repo[n])
5136 displayer.show(repo[n])
5114 displayer.close()
5137 displayer.close()
5115
5138
5116
5139
5117 @command(
5140 @command(
5118 b'paths',
5141 b'paths',
5119 formatteropts,
5142 formatteropts,
5120 _(b'[NAME]'),
5143 _(b'[NAME]'),
5121 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5144 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5122 optionalrepo=True,
5145 optionalrepo=True,
5123 intents={INTENT_READONLY},
5146 intents={INTENT_READONLY},
5124 )
5147 )
5125 def paths(ui, repo, search=None, **opts):
5148 def paths(ui, repo, search=None, **opts):
5126 """show aliases for remote repositories
5149 """show aliases for remote repositories
5127
5150
5128 Show definition of symbolic path name NAME. If no name is given,
5151 Show definition of symbolic path name NAME. If no name is given,
5129 show definition of all available names.
5152 show definition of all available names.
5130
5153
5131 Option -q/--quiet suppresses all output when searching for NAME
5154 Option -q/--quiet suppresses all output when searching for NAME
5132 and shows only the path names when listing all definitions.
5155 and shows only the path names when listing all definitions.
5133
5156
5134 Path names are defined in the [paths] section of your
5157 Path names are defined in the [paths] section of your
5135 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5158 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5136 repository, ``.hg/hgrc`` is used, too.
5159 repository, ``.hg/hgrc`` is used, too.
5137
5160
5138 The path names ``default`` and ``default-push`` have a special
5161 The path names ``default`` and ``default-push`` have a special
5139 meaning. When performing a push or pull operation, they are used
5162 meaning. When performing a push or pull operation, they are used
5140 as fallbacks if no location is specified on the command-line.
5163 as fallbacks if no location is specified on the command-line.
5141 When ``default-push`` is set, it will be used for push and
5164 When ``default-push`` is set, it will be used for push and
5142 ``default`` will be used for pull; otherwise ``default`` is used
5165 ``default`` will be used for pull; otherwise ``default`` is used
5143 as the fallback for both. When cloning a repository, the clone
5166 as the fallback for both. When cloning a repository, the clone
5144 source is written as ``default`` in ``.hg/hgrc``.
5167 source is written as ``default`` in ``.hg/hgrc``.
5145
5168
5146 .. note::
5169 .. note::
5147
5170
5148 ``default`` and ``default-push`` apply to all inbound (e.g.
5171 ``default`` and ``default-push`` apply to all inbound (e.g.
5149 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5172 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5150 and :hg:`bundle`) operations.
5173 and :hg:`bundle`) operations.
5151
5174
5152 See :hg:`help urls` for more information.
5175 See :hg:`help urls` for more information.
5153
5176
5154 .. container:: verbose
5177 .. container:: verbose
5155
5178
5156 Template:
5179 Template:
5157
5180
5158 The following keywords are supported. See also :hg:`help templates`.
5181 The following keywords are supported. See also :hg:`help templates`.
5159
5182
5160 :name: String. Symbolic name of the path alias.
5183 :name: String. Symbolic name of the path alias.
5161 :pushurl: String. URL for push operations.
5184 :pushurl: String. URL for push operations.
5162 :url: String. URL or directory path for the other operations.
5185 :url: String. URL or directory path for the other operations.
5163
5186
5164 Returns 0 on success.
5187 Returns 0 on success.
5165 """
5188 """
5166
5189
5167 opts = pycompat.byteskwargs(opts)
5190 opts = pycompat.byteskwargs(opts)
5168 ui.pager(b'paths')
5191 ui.pager(b'paths')
5169 if search:
5192 if search:
5170 pathitems = [
5193 pathitems = [
5171 (name, path)
5194 (name, path)
5172 for name, path in pycompat.iteritems(ui.paths)
5195 for name, path in pycompat.iteritems(ui.paths)
5173 if name == search
5196 if name == search
5174 ]
5197 ]
5175 else:
5198 else:
5176 pathitems = sorted(pycompat.iteritems(ui.paths))
5199 pathitems = sorted(pycompat.iteritems(ui.paths))
5177
5200
5178 fm = ui.formatter(b'paths', opts)
5201 fm = ui.formatter(b'paths', opts)
5179 if fm.isplain():
5202 if fm.isplain():
5180 hidepassword = util.hidepassword
5203 hidepassword = util.hidepassword
5181 else:
5204 else:
5182 hidepassword = bytes
5205 hidepassword = bytes
5183 if ui.quiet:
5206 if ui.quiet:
5184 namefmt = b'%s\n'
5207 namefmt = b'%s\n'
5185 else:
5208 else:
5186 namefmt = b'%s = '
5209 namefmt = b'%s = '
5187 showsubopts = not search and not ui.quiet
5210 showsubopts = not search and not ui.quiet
5188
5211
5189 for name, path in pathitems:
5212 for name, path in pathitems:
5190 fm.startitem()
5213 fm.startitem()
5191 fm.condwrite(not search, b'name', namefmt, name)
5214 fm.condwrite(not search, b'name', namefmt, name)
5192 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5215 fm.condwrite(not ui.quiet, b'url', b'%s\n', hidepassword(path.rawloc))
5193 for subopt, value in sorted(path.suboptions.items()):
5216 for subopt, value in sorted(path.suboptions.items()):
5194 assert subopt not in (b'name', b'url')
5217 assert subopt not in (b'name', b'url')
5195 if showsubopts:
5218 if showsubopts:
5196 fm.plain(b'%s:%s = ' % (name, subopt))
5219 fm.plain(b'%s:%s = ' % (name, subopt))
5197 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5220 fm.condwrite(showsubopts, subopt, b'%s\n', value)
5198
5221
5199 fm.end()
5222 fm.end()
5200
5223
5201 if search and not pathitems:
5224 if search and not pathitems:
5202 if not ui.quiet:
5225 if not ui.quiet:
5203 ui.warn(_(b"not found!\n"))
5226 ui.warn(_(b"not found!\n"))
5204 return 1
5227 return 1
5205 else:
5228 else:
5206 return 0
5229 return 0
5207
5230
5208
5231
5209 @command(
5232 @command(
5210 b'phase',
5233 b'phase',
5211 [
5234 [
5212 (b'p', b'public', False, _(b'set changeset phase to public')),
5235 (b'p', b'public', False, _(b'set changeset phase to public')),
5213 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5236 (b'd', b'draft', False, _(b'set changeset phase to draft')),
5214 (b's', b'secret', False, _(b'set changeset phase to secret')),
5237 (b's', b'secret', False, _(b'set changeset phase to secret')),
5215 (b'f', b'force', False, _(b'allow to move boundary backward')),
5238 (b'f', b'force', False, _(b'allow to move boundary backward')),
5216 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5239 (b'r', b'rev', [], _(b'target revision'), _(b'REV')),
5217 ],
5240 ],
5218 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5241 _(b'[-p|-d|-s] [-f] [-r] [REV...]'),
5219 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5242 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5220 )
5243 )
5221 def phase(ui, repo, *revs, **opts):
5244 def phase(ui, repo, *revs, **opts):
5222 """set or show the current phase name
5245 """set or show the current phase name
5223
5246
5224 With no argument, show the phase name of the current revision(s).
5247 With no argument, show the phase name of the current revision(s).
5225
5248
5226 With one of -p/--public, -d/--draft or -s/--secret, change the
5249 With one of -p/--public, -d/--draft or -s/--secret, change the
5227 phase value of the specified revisions.
5250 phase value of the specified revisions.
5228
5251
5229 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5252 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
5230 lower phase to a higher phase. Phases are ordered as follows::
5253 lower phase to a higher phase. Phases are ordered as follows::
5231
5254
5232 public < draft < secret
5255 public < draft < secret
5233
5256
5234 Returns 0 on success, 1 if some phases could not be changed.
5257 Returns 0 on success, 1 if some phases could not be changed.
5235
5258
5236 (For more information about the phases concept, see :hg:`help phases`.)
5259 (For more information about the phases concept, see :hg:`help phases`.)
5237 """
5260 """
5238 opts = pycompat.byteskwargs(opts)
5261 opts = pycompat.byteskwargs(opts)
5239 # search for a unique phase argument
5262 # search for a unique phase argument
5240 targetphase = None
5263 targetphase = None
5241 for idx, name in enumerate(phases.cmdphasenames):
5264 for idx, name in enumerate(phases.cmdphasenames):
5242 if opts[name]:
5265 if opts[name]:
5243 if targetphase is not None:
5266 if targetphase is not None:
5244 raise error.Abort(_(b'only one phase can be specified'))
5267 raise error.Abort(_(b'only one phase can be specified'))
5245 targetphase = idx
5268 targetphase = idx
5246
5269
5247 # look for specified revision
5270 # look for specified revision
5248 revs = list(revs)
5271 revs = list(revs)
5249 revs.extend(opts[b'rev'])
5272 revs.extend(opts[b'rev'])
5250 if not revs:
5273 if not revs:
5251 # display both parents as the second parent phase can influence
5274 # display both parents as the second parent phase can influence
5252 # the phase of a merge commit
5275 # the phase of a merge commit
5253 revs = [c.rev() for c in repo[None].parents()]
5276 revs = [c.rev() for c in repo[None].parents()]
5254
5277
5255 revs = scmutil.revrange(repo, revs)
5278 revs = scmutil.revrange(repo, revs)
5256
5279
5257 ret = 0
5280 ret = 0
5258 if targetphase is None:
5281 if targetphase is None:
5259 # display
5282 # display
5260 for r in revs:
5283 for r in revs:
5261 ctx = repo[r]
5284 ctx = repo[r]
5262 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5285 ui.write(b'%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5263 else:
5286 else:
5264 with repo.lock(), repo.transaction(b"phase") as tr:
5287 with repo.lock(), repo.transaction(b"phase") as tr:
5265 # set phase
5288 # set phase
5266 if not revs:
5289 if not revs:
5267 raise error.Abort(_(b'empty revision set'))
5290 raise error.Abort(_(b'empty revision set'))
5268 nodes = [repo[r].node() for r in revs]
5291 nodes = [repo[r].node() for r in revs]
5269 # moving revision from public to draft may hide them
5292 # moving revision from public to draft may hide them
5270 # We have to check result on an unfiltered repository
5293 # We have to check result on an unfiltered repository
5271 unfi = repo.unfiltered()
5294 unfi = repo.unfiltered()
5272 getphase = unfi._phasecache.phase
5295 getphase = unfi._phasecache.phase
5273 olddata = [getphase(unfi, r) for r in unfi]
5296 olddata = [getphase(unfi, r) for r in unfi]
5274 phases.advanceboundary(repo, tr, targetphase, nodes)
5297 phases.advanceboundary(repo, tr, targetphase, nodes)
5275 if opts[b'force']:
5298 if opts[b'force']:
5276 phases.retractboundary(repo, tr, targetphase, nodes)
5299 phases.retractboundary(repo, tr, targetphase, nodes)
5277 getphase = unfi._phasecache.phase
5300 getphase = unfi._phasecache.phase
5278 newdata = [getphase(unfi, r) for r in unfi]
5301 newdata = [getphase(unfi, r) for r in unfi]
5279 changes = sum(newdata[r] != olddata[r] for r in unfi)
5302 changes = sum(newdata[r] != olddata[r] for r in unfi)
5280 cl = unfi.changelog
5303 cl = unfi.changelog
5281 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5304 rejected = [n for n in nodes if newdata[cl.rev(n)] < targetphase]
5282 if rejected:
5305 if rejected:
5283 ui.warn(
5306 ui.warn(
5284 _(
5307 _(
5285 b'cannot move %i changesets to a higher '
5308 b'cannot move %i changesets to a higher '
5286 b'phase, use --force\n'
5309 b'phase, use --force\n'
5287 )
5310 )
5288 % len(rejected)
5311 % len(rejected)
5289 )
5312 )
5290 ret = 1
5313 ret = 1
5291 if changes:
5314 if changes:
5292 msg = _(b'phase changed for %i changesets\n') % changes
5315 msg = _(b'phase changed for %i changesets\n') % changes
5293 if ret:
5316 if ret:
5294 ui.status(msg)
5317 ui.status(msg)
5295 else:
5318 else:
5296 ui.note(msg)
5319 ui.note(msg)
5297 else:
5320 else:
5298 ui.warn(_(b'no phases changed\n'))
5321 ui.warn(_(b'no phases changed\n'))
5299 return ret
5322 return ret
5300
5323
5301
5324
5302 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5325 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
5303 """Run after a changegroup has been added via pull/unbundle
5326 """Run after a changegroup has been added via pull/unbundle
5304
5327
5305 This takes arguments below:
5328 This takes arguments below:
5306
5329
5307 :modheads: change of heads by pull/unbundle
5330 :modheads: change of heads by pull/unbundle
5308 :optupdate: updating working directory is needed or not
5331 :optupdate: updating working directory is needed or not
5309 :checkout: update destination revision (or None to default destination)
5332 :checkout: update destination revision (or None to default destination)
5310 :brev: a name, which might be a bookmark to be activated after updating
5333 :brev: a name, which might be a bookmark to be activated after updating
5311 """
5334 """
5312 if modheads == 0:
5335 if modheads == 0:
5313 return
5336 return
5314 if optupdate:
5337 if optupdate:
5315 try:
5338 try:
5316 return hg.updatetotally(ui, repo, checkout, brev)
5339 return hg.updatetotally(ui, repo, checkout, brev)
5317 except error.UpdateAbort as inst:
5340 except error.UpdateAbort as inst:
5318 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5341 msg = _(b"not updating: %s") % stringutil.forcebytestr(inst)
5319 hint = inst.hint
5342 hint = inst.hint
5320 raise error.UpdateAbort(msg, hint=hint)
5343 raise error.UpdateAbort(msg, hint=hint)
5321 if modheads is not None and modheads > 1:
5344 if modheads is not None and modheads > 1:
5322 currentbranchheads = len(repo.branchheads())
5345 currentbranchheads = len(repo.branchheads())
5323 if currentbranchheads == modheads:
5346 if currentbranchheads == modheads:
5324 ui.status(
5347 ui.status(
5325 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5348 _(b"(run 'hg heads' to see heads, 'hg merge' to merge)\n")
5326 )
5349 )
5327 elif currentbranchheads > 1:
5350 elif currentbranchheads > 1:
5328 ui.status(
5351 ui.status(
5329 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5352 _(b"(run 'hg heads .' to see heads, 'hg merge' to merge)\n")
5330 )
5353 )
5331 else:
5354 else:
5332 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5355 ui.status(_(b"(run 'hg heads' to see heads)\n"))
5333 elif not ui.configbool(b'commands', b'update.requiredest'):
5356 elif not ui.configbool(b'commands', b'update.requiredest'):
5334 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5357 ui.status(_(b"(run 'hg update' to get a working copy)\n"))
5335
5358
5336
5359
5337 @command(
5360 @command(
5338 b'pull',
5361 b'pull',
5339 [
5362 [
5340 (
5363 (
5341 b'u',
5364 b'u',
5342 b'update',
5365 b'update',
5343 None,
5366 None,
5344 _(b'update to new branch head if new descendants were pulled'),
5367 _(b'update to new branch head if new descendants were pulled'),
5345 ),
5368 ),
5346 (
5369 (
5347 b'f',
5370 b'f',
5348 b'force',
5371 b'force',
5349 None,
5372 None,
5350 _(b'run even when remote repository is unrelated'),
5373 _(b'run even when remote repository is unrelated'),
5351 ),
5374 ),
5352 (b'', b'confirm', None, _(b'confirm pull before applying changes'),),
5375 (b'', b'confirm', None, _(b'confirm pull before applying changes'),),
5353 (
5376 (
5354 b'r',
5377 b'r',
5355 b'rev',
5378 b'rev',
5356 [],
5379 [],
5357 _(b'a remote changeset intended to be added'),
5380 _(b'a remote changeset intended to be added'),
5358 _(b'REV'),
5381 _(b'REV'),
5359 ),
5382 ),
5360 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5383 (b'B', b'bookmark', [], _(b"bookmark to pull"), _(b'BOOKMARK')),
5361 (
5384 (
5362 b'b',
5385 b'b',
5363 b'branch',
5386 b'branch',
5364 [],
5387 [],
5365 _(b'a specific branch you would like to pull'),
5388 _(b'a specific branch you would like to pull'),
5366 _(b'BRANCH'),
5389 _(b'BRANCH'),
5367 ),
5390 ),
5368 ]
5391 ]
5369 + remoteopts,
5392 + remoteopts,
5370 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
5393 _(b'[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
5371 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5394 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5372 helpbasic=True,
5395 helpbasic=True,
5373 )
5396 )
5374 def pull(ui, repo, source=b"default", **opts):
5397 def pull(ui, repo, source=b"default", **opts):
5375 """pull changes from the specified source
5398 """pull changes from the specified source
5376
5399
5377 Pull changes from a remote repository to a local one.
5400 Pull changes from a remote repository to a local one.
5378
5401
5379 This finds all changes from the repository at the specified path
5402 This finds all changes from the repository at the specified path
5380 or URL and adds them to a local repository (the current one unless
5403 or URL and adds them to a local repository (the current one unless
5381 -R is specified). By default, this does not update the copy of the
5404 -R is specified). By default, this does not update the copy of the
5382 project in the working directory.
5405 project in the working directory.
5383
5406
5384 When cloning from servers that support it, Mercurial may fetch
5407 When cloning from servers that support it, Mercurial may fetch
5385 pre-generated data. When this is done, hooks operating on incoming
5408 pre-generated data. When this is done, hooks operating on incoming
5386 changesets and changegroups may fire more than once, once for each
5409 changesets and changegroups may fire more than once, once for each
5387 pre-generated bundle and as well as for any additional remaining
5410 pre-generated bundle and as well as for any additional remaining
5388 data. See :hg:`help -e clonebundles` for more.
5411 data. See :hg:`help -e clonebundles` for more.
5389
5412
5390 Use :hg:`incoming` if you want to see what would have been added
5413 Use :hg:`incoming` if you want to see what would have been added
5391 by a pull at the time you issued this command. If you then decide
5414 by a pull at the time you issued this command. If you then decide
5392 to add those changes to the repository, you should use :hg:`pull
5415 to add those changes to the repository, you should use :hg:`pull
5393 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5416 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5394
5417
5395 If SOURCE is omitted, the 'default' path will be used.
5418 If SOURCE is omitted, the 'default' path will be used.
5396 See :hg:`help urls` for more information.
5419 See :hg:`help urls` for more information.
5397
5420
5398 Specifying bookmark as ``.`` is equivalent to specifying the active
5421 Specifying bookmark as ``.`` is equivalent to specifying the active
5399 bookmark's name.
5422 bookmark's name.
5400
5423
5401 Returns 0 on success, 1 if an update had unresolved files.
5424 Returns 0 on success, 1 if an update had unresolved files.
5402 """
5425 """
5403
5426
5404 opts = pycompat.byteskwargs(opts)
5427 opts = pycompat.byteskwargs(opts)
5405 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5428 if ui.configbool(b'commands', b'update.requiredest') and opts.get(
5406 b'update'
5429 b'update'
5407 ):
5430 ):
5408 msg = _(b'update destination required by configuration')
5431 msg = _(b'update destination required by configuration')
5409 hint = _(b'use hg pull followed by hg update DEST')
5432 hint = _(b'use hg pull followed by hg update DEST')
5410 raise error.Abort(msg, hint=hint)
5433 raise error.Abort(msg, hint=hint)
5411
5434
5412 source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
5435 source, branches = hg.parseurl(ui.expandpath(source), opts.get(b'branch'))
5413 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5436 ui.status(_(b'pulling from %s\n') % util.hidepassword(source))
5414 other = hg.peer(repo, opts, source)
5437 other = hg.peer(repo, opts, source)
5415 try:
5438 try:
5416 revs, checkout = hg.addbranchrevs(
5439 revs, checkout = hg.addbranchrevs(
5417 repo, other, branches, opts.get(b'rev')
5440 repo, other, branches, opts.get(b'rev')
5418 )
5441 )
5419
5442
5420 pullopargs = {}
5443 pullopargs = {}
5421
5444
5422 nodes = None
5445 nodes = None
5423 if opts.get(b'bookmark') or revs:
5446 if opts.get(b'bookmark') or revs:
5424 # The list of bookmark used here is the same used to actually update
5447 # The list of bookmark used here is the same used to actually update
5425 # the bookmark names, to avoid the race from issue 4689 and we do
5448 # the bookmark names, to avoid the race from issue 4689 and we do
5426 # all lookup and bookmark queries in one go so they see the same
5449 # all lookup and bookmark queries in one go so they see the same
5427 # version of the server state (issue 4700).
5450 # version of the server state (issue 4700).
5428 nodes = []
5451 nodes = []
5429 fnodes = []
5452 fnodes = []
5430 revs = revs or []
5453 revs = revs or []
5431 if revs and not other.capable(b'lookup'):
5454 if revs and not other.capable(b'lookup'):
5432 err = _(
5455 err = _(
5433 b"other repository doesn't support revision lookup, "
5456 b"other repository doesn't support revision lookup, "
5434 b"so a rev cannot be specified."
5457 b"so a rev cannot be specified."
5435 )
5458 )
5436 raise error.Abort(err)
5459 raise error.Abort(err)
5437 with other.commandexecutor() as e:
5460 with other.commandexecutor() as e:
5438 fremotebookmarks = e.callcommand(
5461 fremotebookmarks = e.callcommand(
5439 b'listkeys', {b'namespace': b'bookmarks'}
5462 b'listkeys', {b'namespace': b'bookmarks'}
5440 )
5463 )
5441 for r in revs:
5464 for r in revs:
5442 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5465 fnodes.append(e.callcommand(b'lookup', {b'key': r}))
5443 remotebookmarks = fremotebookmarks.result()
5466 remotebookmarks = fremotebookmarks.result()
5444 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5467 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
5445 pullopargs[b'remotebookmarks'] = remotebookmarks
5468 pullopargs[b'remotebookmarks'] = remotebookmarks
5446 for b in opts.get(b'bookmark', []):
5469 for b in opts.get(b'bookmark', []):
5447 b = repo._bookmarks.expandname(b)
5470 b = repo._bookmarks.expandname(b)
5448 if b not in remotebookmarks:
5471 if b not in remotebookmarks:
5449 raise error.Abort(_(b'remote bookmark %s not found!') % b)
5472 raise error.Abort(_(b'remote bookmark %s not found!') % b)
5450 nodes.append(remotebookmarks[b])
5473 nodes.append(remotebookmarks[b])
5451 for i, rev in enumerate(revs):
5474 for i, rev in enumerate(revs):
5452 node = fnodes[i].result()
5475 node = fnodes[i].result()
5453 nodes.append(node)
5476 nodes.append(node)
5454 if rev == checkout:
5477 if rev == checkout:
5455 checkout = node
5478 checkout = node
5456
5479
5457 wlock = util.nullcontextmanager()
5480 wlock = util.nullcontextmanager()
5458 if opts.get(b'update'):
5481 if opts.get(b'update'):
5459 wlock = repo.wlock()
5482 wlock = repo.wlock()
5460 with wlock:
5483 with wlock:
5461 pullopargs.update(opts.get(b'opargs', {}))
5484 pullopargs.update(opts.get(b'opargs', {}))
5462 modheads = exchange.pull(
5485 modheads = exchange.pull(
5463 repo,
5486 repo,
5464 other,
5487 other,
5465 heads=nodes,
5488 heads=nodes,
5466 force=opts.get(b'force'),
5489 force=opts.get(b'force'),
5467 bookmarks=opts.get(b'bookmark', ()),
5490 bookmarks=opts.get(b'bookmark', ()),
5468 opargs=pullopargs,
5491 opargs=pullopargs,
5469 confirm=opts.get(b'confirm'),
5492 confirm=opts.get(b'confirm'),
5470 ).cgresult
5493 ).cgresult
5471
5494
5472 # brev is a name, which might be a bookmark to be activated at
5495 # brev is a name, which might be a bookmark to be activated at
5473 # the end of the update. In other words, it is an explicit
5496 # the end of the update. In other words, it is an explicit
5474 # destination of the update
5497 # destination of the update
5475 brev = None
5498 brev = None
5476
5499
5477 if checkout:
5500 if checkout:
5478 checkout = repo.unfiltered().changelog.rev(checkout)
5501 checkout = repo.unfiltered().changelog.rev(checkout)
5479
5502
5480 # order below depends on implementation of
5503 # order below depends on implementation of
5481 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5504 # hg.addbranchrevs(). opts['bookmark'] is ignored,
5482 # because 'checkout' is determined without it.
5505 # because 'checkout' is determined without it.
5483 if opts.get(b'rev'):
5506 if opts.get(b'rev'):
5484 brev = opts[b'rev'][0]
5507 brev = opts[b'rev'][0]
5485 elif opts.get(b'branch'):
5508 elif opts.get(b'branch'):
5486 brev = opts[b'branch'][0]
5509 brev = opts[b'branch'][0]
5487 else:
5510 else:
5488 brev = branches[0]
5511 brev = branches[0]
5489 repo._subtoppath = source
5512 repo._subtoppath = source
5490 try:
5513 try:
5491 ret = postincoming(
5514 ret = postincoming(
5492 ui, repo, modheads, opts.get(b'update'), checkout, brev
5515 ui, repo, modheads, opts.get(b'update'), checkout, brev
5493 )
5516 )
5494 except error.FilteredRepoLookupError as exc:
5517 except error.FilteredRepoLookupError as exc:
5495 msg = _(b'cannot update to target: %s') % exc.args[0]
5518 msg = _(b'cannot update to target: %s') % exc.args[0]
5496 exc.args = (msg,) + exc.args[1:]
5519 exc.args = (msg,) + exc.args[1:]
5497 raise
5520 raise
5498 finally:
5521 finally:
5499 del repo._subtoppath
5522 del repo._subtoppath
5500
5523
5501 finally:
5524 finally:
5502 other.close()
5525 other.close()
5503 return ret
5526 return ret
5504
5527
5505
5528
5506 @command(
5529 @command(
5507 b'push',
5530 b'push',
5508 [
5531 [
5509 (b'f', b'force', None, _(b'force push')),
5532 (b'f', b'force', None, _(b'force push')),
5510 (
5533 (
5511 b'r',
5534 b'r',
5512 b'rev',
5535 b'rev',
5513 [],
5536 [],
5514 _(b'a changeset intended to be included in the destination'),
5537 _(b'a changeset intended to be included in the destination'),
5515 _(b'REV'),
5538 _(b'REV'),
5516 ),
5539 ),
5517 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5540 (b'B', b'bookmark', [], _(b"bookmark to push"), _(b'BOOKMARK')),
5518 (
5541 (
5519 b'b',
5542 b'b',
5520 b'branch',
5543 b'branch',
5521 [],
5544 [],
5522 _(b'a specific branch you would like to push'),
5545 _(b'a specific branch you would like to push'),
5523 _(b'BRANCH'),
5546 _(b'BRANCH'),
5524 ),
5547 ),
5525 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5548 (b'', b'new-branch', False, _(b'allow pushing a new branch')),
5526 (
5549 (
5527 b'',
5550 b'',
5528 b'pushvars',
5551 b'pushvars',
5529 [],
5552 [],
5530 _(b'variables that can be sent to server (ADVANCED)'),
5553 _(b'variables that can be sent to server (ADVANCED)'),
5531 ),
5554 ),
5532 (
5555 (
5533 b'',
5556 b'',
5534 b'publish',
5557 b'publish',
5535 False,
5558 False,
5536 _(b'push the changeset as public (EXPERIMENTAL)'),
5559 _(b'push the changeset as public (EXPERIMENTAL)'),
5537 ),
5560 ),
5538 ]
5561 ]
5539 + remoteopts,
5562 + remoteopts,
5540 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
5563 _(b'[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
5541 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5564 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5542 helpbasic=True,
5565 helpbasic=True,
5543 )
5566 )
5544 def push(ui, repo, dest=None, **opts):
5567 def push(ui, repo, dest=None, **opts):
5545 """push changes to the specified destination
5568 """push changes to the specified destination
5546
5569
5547 Push changesets from the local repository to the specified
5570 Push changesets from the local repository to the specified
5548 destination.
5571 destination.
5549
5572
5550 This operation is symmetrical to pull: it is identical to a pull
5573 This operation is symmetrical to pull: it is identical to a pull
5551 in the destination repository from the current one.
5574 in the destination repository from the current one.
5552
5575
5553 By default, push will not allow creation of new heads at the
5576 By default, push will not allow creation of new heads at the
5554 destination, since multiple heads would make it unclear which head
5577 destination, since multiple heads would make it unclear which head
5555 to use. In this situation, it is recommended to pull and merge
5578 to use. In this situation, it is recommended to pull and merge
5556 before pushing.
5579 before pushing.
5557
5580
5558 Use --new-branch if you want to allow push to create a new named
5581 Use --new-branch if you want to allow push to create a new named
5559 branch that is not present at the destination. This allows you to
5582 branch that is not present at the destination. This allows you to
5560 only create a new branch without forcing other changes.
5583 only create a new branch without forcing other changes.
5561
5584
5562 .. note::
5585 .. note::
5563
5586
5564 Extra care should be taken with the -f/--force option,
5587 Extra care should be taken with the -f/--force option,
5565 which will push all new heads on all branches, an action which will
5588 which will push all new heads on all branches, an action which will
5566 almost always cause confusion for collaborators.
5589 almost always cause confusion for collaborators.
5567
5590
5568 If -r/--rev is used, the specified revision and all its ancestors
5591 If -r/--rev is used, the specified revision and all its ancestors
5569 will be pushed to the remote repository.
5592 will be pushed to the remote repository.
5570
5593
5571 If -B/--bookmark is used, the specified bookmarked revision, its
5594 If -B/--bookmark is used, the specified bookmarked revision, its
5572 ancestors, and the bookmark will be pushed to the remote
5595 ancestors, and the bookmark will be pushed to the remote
5573 repository. Specifying ``.`` is equivalent to specifying the active
5596 repository. Specifying ``.`` is equivalent to specifying the active
5574 bookmark's name.
5597 bookmark's name.
5575
5598
5576 Please see :hg:`help urls` for important details about ``ssh://``
5599 Please see :hg:`help urls` for important details about ``ssh://``
5577 URLs. If DESTINATION is omitted, a default path will be used.
5600 URLs. If DESTINATION is omitted, a default path will be used.
5578
5601
5579 .. container:: verbose
5602 .. container:: verbose
5580
5603
5581 The --pushvars option sends strings to the server that become
5604 The --pushvars option sends strings to the server that become
5582 environment variables prepended with ``HG_USERVAR_``. For example,
5605 environment variables prepended with ``HG_USERVAR_``. For example,
5583 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5606 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
5584 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5607 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
5585
5608
5586 pushvars can provide for user-overridable hooks as well as set debug
5609 pushvars can provide for user-overridable hooks as well as set debug
5587 levels. One example is having a hook that blocks commits containing
5610 levels. One example is having a hook that blocks commits containing
5588 conflict markers, but enables the user to override the hook if the file
5611 conflict markers, but enables the user to override the hook if the file
5589 is using conflict markers for testing purposes or the file format has
5612 is using conflict markers for testing purposes or the file format has
5590 strings that look like conflict markers.
5613 strings that look like conflict markers.
5591
5614
5592 By default, servers will ignore `--pushvars`. To enable it add the
5615 By default, servers will ignore `--pushvars`. To enable it add the
5593 following to your configuration file::
5616 following to your configuration file::
5594
5617
5595 [push]
5618 [push]
5596 pushvars.server = true
5619 pushvars.server = true
5597
5620
5598 Returns 0 if push was successful, 1 if nothing to push.
5621 Returns 0 if push was successful, 1 if nothing to push.
5599 """
5622 """
5600
5623
5601 opts = pycompat.byteskwargs(opts)
5624 opts = pycompat.byteskwargs(opts)
5602 if opts.get(b'bookmark'):
5625 if opts.get(b'bookmark'):
5603 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5626 ui.setconfig(b'bookmarks', b'pushing', opts[b'bookmark'], b'push')
5604 for b in opts[b'bookmark']:
5627 for b in opts[b'bookmark']:
5605 # translate -B options to -r so changesets get pushed
5628 # translate -B options to -r so changesets get pushed
5606 b = repo._bookmarks.expandname(b)
5629 b = repo._bookmarks.expandname(b)
5607 if b in repo._bookmarks:
5630 if b in repo._bookmarks:
5608 opts.setdefault(b'rev', []).append(b)
5631 opts.setdefault(b'rev', []).append(b)
5609 else:
5632 else:
5610 # if we try to push a deleted bookmark, translate it to null
5633 # if we try to push a deleted bookmark, translate it to null
5611 # this lets simultaneous -r, -b options continue working
5634 # this lets simultaneous -r, -b options continue working
5612 opts.setdefault(b'rev', []).append(b"null")
5635 opts.setdefault(b'rev', []).append(b"null")
5613
5636
5614 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5637 path = ui.paths.getpath(dest, default=(b'default-push', b'default'))
5615 if not path:
5638 if not path:
5616 raise error.Abort(
5639 raise error.Abort(
5617 _(b'default repository not configured!'),
5640 _(b'default repository not configured!'),
5618 hint=_(b"see 'hg help config.paths'"),
5641 hint=_(b"see 'hg help config.paths'"),
5619 )
5642 )
5620 dest = path.pushloc or path.loc
5643 dest = path.pushloc or path.loc
5621 branches = (path.branch, opts.get(b'branch') or [])
5644 branches = (path.branch, opts.get(b'branch') or [])
5622 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5645 ui.status(_(b'pushing to %s\n') % util.hidepassword(dest))
5623 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
5646 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get(b'rev'))
5624 other = hg.peer(repo, opts, dest)
5647 other = hg.peer(repo, opts, dest)
5625
5648
5626 if revs:
5649 if revs:
5627 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5650 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
5628 if not revs:
5651 if not revs:
5629 raise error.Abort(
5652 raise error.Abort(
5630 _(b"specified revisions evaluate to an empty set"),
5653 _(b"specified revisions evaluate to an empty set"),
5631 hint=_(b"use different revision arguments"),
5654 hint=_(b"use different revision arguments"),
5632 )
5655 )
5633 elif path.pushrev:
5656 elif path.pushrev:
5634 # It doesn't make any sense to specify ancestor revisions. So limit
5657 # It doesn't make any sense to specify ancestor revisions. So limit
5635 # to DAG heads to make discovery simpler.
5658 # to DAG heads to make discovery simpler.
5636 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5659 expr = revsetlang.formatspec(b'heads(%r)', path.pushrev)
5637 revs = scmutil.revrange(repo, [expr])
5660 revs = scmutil.revrange(repo, [expr])
5638 revs = [repo[rev].node() for rev in revs]
5661 revs = [repo[rev].node() for rev in revs]
5639 if not revs:
5662 if not revs:
5640 raise error.Abort(
5663 raise error.Abort(
5641 _(b'default push revset for path evaluates to an empty set')
5664 _(b'default push revset for path evaluates to an empty set')
5642 )
5665 )
5643 elif ui.configbool(b'commands', b'push.require-revs'):
5666 elif ui.configbool(b'commands', b'push.require-revs'):
5644 raise error.Abort(
5667 raise error.Abort(
5645 _(b'no revisions specified to push'),
5668 _(b'no revisions specified to push'),
5646 hint=_(b'did you mean "hg push -r ."?'),
5669 hint=_(b'did you mean "hg push -r ."?'),
5647 )
5670 )
5648
5671
5649 repo._subtoppath = dest
5672 repo._subtoppath = dest
5650 try:
5673 try:
5651 # push subrepos depth-first for coherent ordering
5674 # push subrepos depth-first for coherent ordering
5652 c = repo[b'.']
5675 c = repo[b'.']
5653 subs = c.substate # only repos that are committed
5676 subs = c.substate # only repos that are committed
5654 for s in sorted(subs):
5677 for s in sorted(subs):
5655 result = c.sub(s).push(opts)
5678 result = c.sub(s).push(opts)
5656 if result == 0:
5679 if result == 0:
5657 return not result
5680 return not result
5658 finally:
5681 finally:
5659 del repo._subtoppath
5682 del repo._subtoppath
5660
5683
5661 opargs = dict(opts.get(b'opargs', {})) # copy opargs since we may mutate it
5684 opargs = dict(opts.get(b'opargs', {})) # copy opargs since we may mutate it
5662 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5685 opargs.setdefault(b'pushvars', []).extend(opts.get(b'pushvars', []))
5663
5686
5664 pushop = exchange.push(
5687 pushop = exchange.push(
5665 repo,
5688 repo,
5666 other,
5689 other,
5667 opts.get(b'force'),
5690 opts.get(b'force'),
5668 revs=revs,
5691 revs=revs,
5669 newbranch=opts.get(b'new_branch'),
5692 newbranch=opts.get(b'new_branch'),
5670 bookmarks=opts.get(b'bookmark', ()),
5693 bookmarks=opts.get(b'bookmark', ()),
5671 publish=opts.get(b'publish'),
5694 publish=opts.get(b'publish'),
5672 opargs=opargs,
5695 opargs=opargs,
5673 )
5696 )
5674
5697
5675 result = not pushop.cgresult
5698 result = not pushop.cgresult
5676
5699
5677 if pushop.bkresult is not None:
5700 if pushop.bkresult is not None:
5678 if pushop.bkresult == 2:
5701 if pushop.bkresult == 2:
5679 result = 2
5702 result = 2
5680 elif not result and pushop.bkresult:
5703 elif not result and pushop.bkresult:
5681 result = 2
5704 result = 2
5682
5705
5683 return result
5706 return result
5684
5707
5685
5708
5686 @command(
5709 @command(
5687 b'recover',
5710 b'recover',
5688 [(b'', b'verify', False, b"run `hg verify` after successful recover"),],
5711 [(b'', b'verify', False, b"run `hg verify` after successful recover"),],
5689 helpcategory=command.CATEGORY_MAINTENANCE,
5712 helpcategory=command.CATEGORY_MAINTENANCE,
5690 )
5713 )
5691 def recover(ui, repo, **opts):
5714 def recover(ui, repo, **opts):
5692 """roll back an interrupted transaction
5715 """roll back an interrupted transaction
5693
5716
5694 Recover from an interrupted commit or pull.
5717 Recover from an interrupted commit or pull.
5695
5718
5696 This command tries to fix the repository status after an
5719 This command tries to fix the repository status after an
5697 interrupted operation. It should only be necessary when Mercurial
5720 interrupted operation. It should only be necessary when Mercurial
5698 suggests it.
5721 suggests it.
5699
5722
5700 Returns 0 if successful, 1 if nothing to recover or verify fails.
5723 Returns 0 if successful, 1 if nothing to recover or verify fails.
5701 """
5724 """
5702 ret = repo.recover()
5725 ret = repo.recover()
5703 if ret:
5726 if ret:
5704 if opts['verify']:
5727 if opts['verify']:
5705 return hg.verify(repo)
5728 return hg.verify(repo)
5706 else:
5729 else:
5707 msg = _(
5730 msg = _(
5708 b"(verify step skipped, run `hg verify` to check your "
5731 b"(verify step skipped, run `hg verify` to check your "
5709 b"repository content)\n"
5732 b"repository content)\n"
5710 )
5733 )
5711 ui.warn(msg)
5734 ui.warn(msg)
5712 return 0
5735 return 0
5713 return 1
5736 return 1
5714
5737
5715
5738
5716 @command(
5739 @command(
5717 b'remove|rm',
5740 b'remove|rm',
5718 [
5741 [
5719 (b'A', b'after', None, _(b'record delete for missing files')),
5742 (b'A', b'after', None, _(b'record delete for missing files')),
5720 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5743 (b'f', b'force', None, _(b'forget added files, delete modified files')),
5721 ]
5744 ]
5722 + subrepoopts
5745 + subrepoopts
5723 + walkopts
5746 + walkopts
5724 + dryrunopts,
5747 + dryrunopts,
5725 _(b'[OPTION]... FILE...'),
5748 _(b'[OPTION]... FILE...'),
5726 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5749 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5727 helpbasic=True,
5750 helpbasic=True,
5728 inferrepo=True,
5751 inferrepo=True,
5729 )
5752 )
5730 def remove(ui, repo, *pats, **opts):
5753 def remove(ui, repo, *pats, **opts):
5731 """remove the specified files on the next commit
5754 """remove the specified files on the next commit
5732
5755
5733 Schedule the indicated files for removal from the current branch.
5756 Schedule the indicated files for removal from the current branch.
5734
5757
5735 This command schedules the files to be removed at the next commit.
5758 This command schedules the files to be removed at the next commit.
5736 To undo a remove before that, see :hg:`revert`. To undo added
5759 To undo a remove before that, see :hg:`revert`. To undo added
5737 files, see :hg:`forget`.
5760 files, see :hg:`forget`.
5738
5761
5739 .. container:: verbose
5762 .. container:: verbose
5740
5763
5741 -A/--after can be used to remove only files that have already
5764 -A/--after can be used to remove only files that have already
5742 been deleted, -f/--force can be used to force deletion, and -Af
5765 been deleted, -f/--force can be used to force deletion, and -Af
5743 can be used to remove files from the next revision without
5766 can be used to remove files from the next revision without
5744 deleting them from the working directory.
5767 deleting them from the working directory.
5745
5768
5746 The following table details the behavior of remove for different
5769 The following table details the behavior of remove for different
5747 file states (columns) and option combinations (rows). The file
5770 file states (columns) and option combinations (rows). The file
5748 states are Added [A], Clean [C], Modified [M] and Missing [!]
5771 states are Added [A], Clean [C], Modified [M] and Missing [!]
5749 (as reported by :hg:`status`). The actions are Warn, Remove
5772 (as reported by :hg:`status`). The actions are Warn, Remove
5750 (from branch) and Delete (from disk):
5773 (from branch) and Delete (from disk):
5751
5774
5752 ========= == == == ==
5775 ========= == == == ==
5753 opt/state A C M !
5776 opt/state A C M !
5754 ========= == == == ==
5777 ========= == == == ==
5755 none W RD W R
5778 none W RD W R
5756 -f R RD RD R
5779 -f R RD RD R
5757 -A W W W R
5780 -A W W W R
5758 -Af R R R R
5781 -Af R R R R
5759 ========= == == == ==
5782 ========= == == == ==
5760
5783
5761 .. note::
5784 .. note::
5762
5785
5763 :hg:`remove` never deletes files in Added [A] state from the
5786 :hg:`remove` never deletes files in Added [A] state from the
5764 working directory, not even if ``--force`` is specified.
5787 working directory, not even if ``--force`` is specified.
5765
5788
5766 Returns 0 on success, 1 if any warnings encountered.
5789 Returns 0 on success, 1 if any warnings encountered.
5767 """
5790 """
5768
5791
5769 opts = pycompat.byteskwargs(opts)
5792 opts = pycompat.byteskwargs(opts)
5770 after, force = opts.get(b'after'), opts.get(b'force')
5793 after, force = opts.get(b'after'), opts.get(b'force')
5771 dryrun = opts.get(b'dry_run')
5794 dryrun = opts.get(b'dry_run')
5772 if not pats and not after:
5795 if not pats and not after:
5773 raise error.Abort(_(b'no files specified'))
5796 raise error.Abort(_(b'no files specified'))
5774
5797
5775 m = scmutil.match(repo[None], pats, opts)
5798 m = scmutil.match(repo[None], pats, opts)
5776 subrepos = opts.get(b'subrepos')
5799 subrepos = opts.get(b'subrepos')
5777 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5800 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
5778 return cmdutil.remove(
5801 return cmdutil.remove(
5779 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5802 ui, repo, m, b"", uipathfn, after, force, subrepos, dryrun=dryrun
5780 )
5803 )
5781
5804
5782
5805
5783 @command(
5806 @command(
5784 b'rename|move|mv',
5807 b'rename|move|mv',
5785 [
5808 [
5786 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5809 (b'A', b'after', None, _(b'record a rename that has already occurred')),
5787 (
5810 (
5788 b'',
5811 b'',
5789 b'at-rev',
5812 b'at-rev',
5790 b'',
5813 b'',
5791 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5814 _(b'(un)mark renames in the given revision (EXPERIMENTAL)'),
5792 _(b'REV'),
5815 _(b'REV'),
5793 ),
5816 ),
5794 (
5817 (
5795 b'f',
5818 b'f',
5796 b'force',
5819 b'force',
5797 None,
5820 None,
5798 _(b'forcibly move over an existing managed file'),
5821 _(b'forcibly move over an existing managed file'),
5799 ),
5822 ),
5800 ]
5823 ]
5801 + walkopts
5824 + walkopts
5802 + dryrunopts,
5825 + dryrunopts,
5803 _(b'[OPTION]... SOURCE... DEST'),
5826 _(b'[OPTION]... SOURCE... DEST'),
5804 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5827 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5805 )
5828 )
5806 def rename(ui, repo, *pats, **opts):
5829 def rename(ui, repo, *pats, **opts):
5807 """rename files; equivalent of copy + remove
5830 """rename files; equivalent of copy + remove
5808
5831
5809 Mark dest as copies of sources; mark sources for deletion. If dest
5832 Mark dest as copies of sources; mark sources for deletion. If dest
5810 is a directory, copies are put in that directory. If dest is a
5833 is a directory, copies are put in that directory. If dest is a
5811 file, there can only be one source.
5834 file, there can only be one source.
5812
5835
5813 By default, this command copies the contents of files as they
5836 By default, this command copies the contents of files as they
5814 exist in the working directory. If invoked with -A/--after, the
5837 exist in the working directory. If invoked with -A/--after, the
5815 operation is recorded, but no copying is performed.
5838 operation is recorded, but no copying is performed.
5816
5839
5817 This command takes effect at the next commit. To undo a rename
5840 This command takes effect at the next commit. To undo a rename
5818 before that, see :hg:`revert`.
5841 before that, see :hg:`revert`.
5819
5842
5820 Returns 0 on success, 1 if errors are encountered.
5843 Returns 0 on success, 1 if errors are encountered.
5821 """
5844 """
5822 opts = pycompat.byteskwargs(opts)
5845 opts = pycompat.byteskwargs(opts)
5823 with repo.wlock():
5846 with repo.wlock():
5824 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5847 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5825
5848
5826
5849
5827 @command(
5850 @command(
5828 b'resolve',
5851 b'resolve',
5829 [
5852 [
5830 (b'a', b'all', None, _(b'select all unresolved files')),
5853 (b'a', b'all', None, _(b'select all unresolved files')),
5831 (b'l', b'list', None, _(b'list state of files needing merge')),
5854 (b'l', b'list', None, _(b'list state of files needing merge')),
5832 (b'm', b'mark', None, _(b'mark files as resolved')),
5855 (b'm', b'mark', None, _(b'mark files as resolved')),
5833 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5856 (b'u', b'unmark', None, _(b'mark files as unresolved')),
5834 (b'n', b'no-status', None, _(b'hide status prefix')),
5857 (b'n', b'no-status', None, _(b'hide status prefix')),
5835 (b'', b're-merge', None, _(b're-merge files')),
5858 (b'', b're-merge', None, _(b're-merge files')),
5836 ]
5859 ]
5837 + mergetoolopts
5860 + mergetoolopts
5838 + walkopts
5861 + walkopts
5839 + formatteropts,
5862 + formatteropts,
5840 _(b'[OPTION]... [FILE]...'),
5863 _(b'[OPTION]... [FILE]...'),
5841 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5864 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5842 inferrepo=True,
5865 inferrepo=True,
5843 )
5866 )
5844 def resolve(ui, repo, *pats, **opts):
5867 def resolve(ui, repo, *pats, **opts):
5845 """redo merges or set/view the merge status of files
5868 """redo merges or set/view the merge status of files
5846
5869
5847 Merges with unresolved conflicts are often the result of
5870 Merges with unresolved conflicts are often the result of
5848 non-interactive merging using the ``internal:merge`` configuration
5871 non-interactive merging using the ``internal:merge`` configuration
5849 setting, or a command-line merge tool like ``diff3``. The resolve
5872 setting, or a command-line merge tool like ``diff3``. The resolve
5850 command is used to manage the files involved in a merge, after
5873 command is used to manage the files involved in a merge, after
5851 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5874 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5852 working directory must have two parents). See :hg:`help
5875 working directory must have two parents). See :hg:`help
5853 merge-tools` for information on configuring merge tools.
5876 merge-tools` for information on configuring merge tools.
5854
5877
5855 The resolve command can be used in the following ways:
5878 The resolve command can be used in the following ways:
5856
5879
5857 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5880 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
5858 the specified files, discarding any previous merge attempts. Re-merging
5881 the specified files, discarding any previous merge attempts. Re-merging
5859 is not performed for files already marked as resolved. Use ``--all/-a``
5882 is not performed for files already marked as resolved. Use ``--all/-a``
5860 to select all unresolved files. ``--tool`` can be used to specify
5883 to select all unresolved files. ``--tool`` can be used to specify
5861 the merge tool used for the given files. It overrides the HGMERGE
5884 the merge tool used for the given files. It overrides the HGMERGE
5862 environment variable and your configuration files. Previous file
5885 environment variable and your configuration files. Previous file
5863 contents are saved with a ``.orig`` suffix.
5886 contents are saved with a ``.orig`` suffix.
5864
5887
5865 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5888 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5866 (e.g. after having manually fixed-up the files). The default is
5889 (e.g. after having manually fixed-up the files). The default is
5867 to mark all unresolved files.
5890 to mark all unresolved files.
5868
5891
5869 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5892 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5870 default is to mark all resolved files.
5893 default is to mark all resolved files.
5871
5894
5872 - :hg:`resolve -l`: list files which had or still have conflicts.
5895 - :hg:`resolve -l`: list files which had or still have conflicts.
5873 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5896 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5874 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5897 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
5875 the list. See :hg:`help filesets` for details.
5898 the list. See :hg:`help filesets` for details.
5876
5899
5877 .. note::
5900 .. note::
5878
5901
5879 Mercurial will not let you commit files with unresolved merge
5902 Mercurial will not let you commit files with unresolved merge
5880 conflicts. You must use :hg:`resolve -m ...` before you can
5903 conflicts. You must use :hg:`resolve -m ...` before you can
5881 commit after a conflicting merge.
5904 commit after a conflicting merge.
5882
5905
5883 .. container:: verbose
5906 .. container:: verbose
5884
5907
5885 Template:
5908 Template:
5886
5909
5887 The following keywords are supported in addition to the common template
5910 The following keywords are supported in addition to the common template
5888 keywords and functions. See also :hg:`help templates`.
5911 keywords and functions. See also :hg:`help templates`.
5889
5912
5890 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
5913 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
5891 :path: String. Repository-absolute path of the file.
5914 :path: String. Repository-absolute path of the file.
5892
5915
5893 Returns 0 on success, 1 if any files fail a resolve attempt.
5916 Returns 0 on success, 1 if any files fail a resolve attempt.
5894 """
5917 """
5895
5918
5896 opts = pycompat.byteskwargs(opts)
5919 opts = pycompat.byteskwargs(opts)
5897 confirm = ui.configbool(b'commands', b'resolve.confirm')
5920 confirm = ui.configbool(b'commands', b'resolve.confirm')
5898 flaglist = b'all mark unmark list no_status re_merge'.split()
5921 flaglist = b'all mark unmark list no_status re_merge'.split()
5899 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
5922 all, mark, unmark, show, nostatus, remerge = [opts.get(o) for o in flaglist]
5900
5923
5901 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
5924 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
5902 if actioncount > 1:
5925 if actioncount > 1:
5903 raise error.Abort(_(b"too many actions specified"))
5926 raise error.Abort(_(b"too many actions specified"))
5904 elif actioncount == 0 and ui.configbool(
5927 elif actioncount == 0 and ui.configbool(
5905 b'commands', b'resolve.explicit-re-merge'
5928 b'commands', b'resolve.explicit-re-merge'
5906 ):
5929 ):
5907 hint = _(b'use --mark, --unmark, --list or --re-merge')
5930 hint = _(b'use --mark, --unmark, --list or --re-merge')
5908 raise error.Abort(_(b'no action specified'), hint=hint)
5931 raise error.Abort(_(b'no action specified'), hint=hint)
5909 if pats and all:
5932 if pats and all:
5910 raise error.Abort(_(b"can't specify --all and patterns"))
5933 raise error.Abort(_(b"can't specify --all and patterns"))
5911 if not (all or pats or show or mark or unmark):
5934 if not (all or pats or show or mark or unmark):
5912 raise error.Abort(
5935 raise error.Abort(
5913 _(b'no files or directories specified'),
5936 _(b'no files or directories specified'),
5914 hint=b'use --all to re-merge all unresolved files',
5937 hint=b'use --all to re-merge all unresolved files',
5915 )
5938 )
5916
5939
5917 if confirm:
5940 if confirm:
5918 if all:
5941 if all:
5919 if ui.promptchoice(
5942 if ui.promptchoice(
5920 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
5943 _(b're-merge all unresolved files (yn)?$$ &Yes $$ &No')
5921 ):
5944 ):
5922 raise error.Abort(_(b'user quit'))
5945 raise error.Abort(_(b'user quit'))
5923 if mark and not pats:
5946 if mark and not pats:
5924 if ui.promptchoice(
5947 if ui.promptchoice(
5925 _(
5948 _(
5926 b'mark all unresolved files as resolved (yn)?'
5949 b'mark all unresolved files as resolved (yn)?'
5927 b'$$ &Yes $$ &No'
5950 b'$$ &Yes $$ &No'
5928 )
5951 )
5929 ):
5952 ):
5930 raise error.Abort(_(b'user quit'))
5953 raise error.Abort(_(b'user quit'))
5931 if unmark and not pats:
5954 if unmark and not pats:
5932 if ui.promptchoice(
5955 if ui.promptchoice(
5933 _(
5956 _(
5934 b'mark all resolved files as unresolved (yn)?'
5957 b'mark all resolved files as unresolved (yn)?'
5935 b'$$ &Yes $$ &No'
5958 b'$$ &Yes $$ &No'
5936 )
5959 )
5937 ):
5960 ):
5938 raise error.Abort(_(b'user quit'))
5961 raise error.Abort(_(b'user quit'))
5939
5962
5940 uipathfn = scmutil.getuipathfn(repo)
5963 uipathfn = scmutil.getuipathfn(repo)
5941
5964
5942 if show:
5965 if show:
5943 ui.pager(b'resolve')
5966 ui.pager(b'resolve')
5944 fm = ui.formatter(b'resolve', opts)
5967 fm = ui.formatter(b'resolve', opts)
5945 ms = mergestatemod.mergestate.read(repo)
5968 ms = mergestatemod.mergestate.read(repo)
5946 wctx = repo[None]
5969 wctx = repo[None]
5947 m = scmutil.match(wctx, pats, opts)
5970 m = scmutil.match(wctx, pats, opts)
5948
5971
5949 # Labels and keys based on merge state. Unresolved path conflicts show
5972 # Labels and keys based on merge state. Unresolved path conflicts show
5950 # as 'P'. Resolved path conflicts show as 'R', the same as normal
5973 # as 'P'. Resolved path conflicts show as 'R', the same as normal
5951 # resolved conflicts.
5974 # resolved conflicts.
5952 mergestateinfo = {
5975 mergestateinfo = {
5953 mergestatemod.MERGE_RECORD_UNRESOLVED: (
5976 mergestatemod.MERGE_RECORD_UNRESOLVED: (
5954 b'resolve.unresolved',
5977 b'resolve.unresolved',
5955 b'U',
5978 b'U',
5956 ),
5979 ),
5957 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
5980 mergestatemod.MERGE_RECORD_RESOLVED: (b'resolve.resolved', b'R'),
5958 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
5981 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH: (
5959 b'resolve.unresolved',
5982 b'resolve.unresolved',
5960 b'P',
5983 b'P',
5961 ),
5984 ),
5962 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
5985 mergestatemod.MERGE_RECORD_RESOLVED_PATH: (
5963 b'resolve.resolved',
5986 b'resolve.resolved',
5964 b'R',
5987 b'R',
5965 ),
5988 ),
5966 mergestatemod.MERGE_RECORD_DRIVER_RESOLVED: (
5989 mergestatemod.MERGE_RECORD_DRIVER_RESOLVED: (
5967 b'resolve.driverresolved',
5990 b'resolve.driverresolved',
5968 b'D',
5991 b'D',
5969 ),
5992 ),
5970 }
5993 }
5971
5994
5972 for f in ms:
5995 for f in ms:
5973 if not m(f):
5996 if not m(f):
5974 continue
5997 continue
5975
5998
5976 label, key = mergestateinfo[ms[f]]
5999 label, key = mergestateinfo[ms[f]]
5977 fm.startitem()
6000 fm.startitem()
5978 fm.context(ctx=wctx)
6001 fm.context(ctx=wctx)
5979 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
6002 fm.condwrite(not nostatus, b'mergestatus', b'%s ', key, label=label)
5980 fm.data(path=f)
6003 fm.data(path=f)
5981 fm.plain(b'%s\n' % uipathfn(f), label=label)
6004 fm.plain(b'%s\n' % uipathfn(f), label=label)
5982 fm.end()
6005 fm.end()
5983 return 0
6006 return 0
5984
6007
5985 with repo.wlock():
6008 with repo.wlock():
5986 ms = mergestatemod.mergestate.read(repo)
6009 ms = mergestatemod.mergestate.read(repo)
5987
6010
5988 if not (ms.active() or repo.dirstate.p2() != nullid):
6011 if not (ms.active() or repo.dirstate.p2() != nullid):
5989 raise error.Abort(
6012 raise error.Abort(
5990 _(b'resolve command not applicable when not merging')
6013 _(b'resolve command not applicable when not merging')
5991 )
6014 )
5992
6015
5993 wctx = repo[None]
6016 wctx = repo[None]
5994
6017
5995 if (
6018 if (
5996 ms.mergedriver
6019 ms.mergedriver
5997 and ms.mdstate() == mergestatemod.MERGE_DRIVER_STATE_UNMARKED
6020 and ms.mdstate() == mergestatemod.MERGE_DRIVER_STATE_UNMARKED
5998 ):
6021 ):
5999 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6022 proceed = mergemod.driverpreprocess(repo, ms, wctx)
6000 ms.commit()
6023 ms.commit()
6001 # allow mark and unmark to go through
6024 # allow mark and unmark to go through
6002 if not mark and not unmark and not proceed:
6025 if not mark and not unmark and not proceed:
6003 return 1
6026 return 1
6004
6027
6005 m = scmutil.match(wctx, pats, opts)
6028 m = scmutil.match(wctx, pats, opts)
6006 ret = 0
6029 ret = 0
6007 didwork = False
6030 didwork = False
6008 runconclude = False
6031 runconclude = False
6009
6032
6010 tocomplete = []
6033 tocomplete = []
6011 hasconflictmarkers = []
6034 hasconflictmarkers = []
6012 if mark:
6035 if mark:
6013 markcheck = ui.config(b'commands', b'resolve.mark-check')
6036 markcheck = ui.config(b'commands', b'resolve.mark-check')
6014 if markcheck not in [b'warn', b'abort']:
6037 if markcheck not in [b'warn', b'abort']:
6015 # Treat all invalid / unrecognized values as 'none'.
6038 # Treat all invalid / unrecognized values as 'none'.
6016 markcheck = False
6039 markcheck = False
6017 for f in ms:
6040 for f in ms:
6018 if not m(f):
6041 if not m(f):
6019 continue
6042 continue
6020
6043
6021 didwork = True
6044 didwork = True
6022
6045
6023 # don't let driver-resolved files be marked, and run the conclude
6046 # don't let driver-resolved files be marked, and run the conclude
6024 # step if asked to resolve
6047 # step if asked to resolve
6025 if ms[f] == mergestatemod.MERGE_RECORD_DRIVER_RESOLVED:
6048 if ms[f] == mergestatemod.MERGE_RECORD_DRIVER_RESOLVED:
6026 exact = m.exact(f)
6049 exact = m.exact(f)
6027 if mark:
6050 if mark:
6028 if exact:
6051 if exact:
6029 ui.warn(
6052 ui.warn(
6030 _(b'not marking %s as it is driver-resolved\n')
6053 _(b'not marking %s as it is driver-resolved\n')
6031 % uipathfn(f)
6054 % uipathfn(f)
6032 )
6055 )
6033 elif unmark:
6056 elif unmark:
6034 if exact:
6057 if exact:
6035 ui.warn(
6058 ui.warn(
6036 _(b'not unmarking %s as it is driver-resolved\n')
6059 _(b'not unmarking %s as it is driver-resolved\n')
6037 % uipathfn(f)
6060 % uipathfn(f)
6038 )
6061 )
6039 else:
6062 else:
6040 runconclude = True
6063 runconclude = True
6041 continue
6064 continue
6042
6065
6043 # path conflicts must be resolved manually
6066 # path conflicts must be resolved manually
6044 if ms[f] in (
6067 if ms[f] in (
6045 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6068 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
6046 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6069 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
6047 ):
6070 ):
6048 if mark:
6071 if mark:
6049 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6072 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED_PATH)
6050 elif unmark:
6073 elif unmark:
6051 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6074 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED_PATH)
6052 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6075 elif ms[f] == mergestatemod.MERGE_RECORD_UNRESOLVED_PATH:
6053 ui.warn(
6076 ui.warn(
6054 _(b'%s: path conflict must be resolved manually\n')
6077 _(b'%s: path conflict must be resolved manually\n')
6055 % uipathfn(f)
6078 % uipathfn(f)
6056 )
6079 )
6057 continue
6080 continue
6058
6081
6059 if mark:
6082 if mark:
6060 if markcheck:
6083 if markcheck:
6061 fdata = repo.wvfs.tryread(f)
6084 fdata = repo.wvfs.tryread(f)
6062 if (
6085 if (
6063 filemerge.hasconflictmarkers(fdata)
6086 filemerge.hasconflictmarkers(fdata)
6064 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6087 and ms[f] != mergestatemod.MERGE_RECORD_RESOLVED
6065 ):
6088 ):
6066 hasconflictmarkers.append(f)
6089 hasconflictmarkers.append(f)
6067 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6090 ms.mark(f, mergestatemod.MERGE_RECORD_RESOLVED)
6068 elif unmark:
6091 elif unmark:
6069 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6092 ms.mark(f, mergestatemod.MERGE_RECORD_UNRESOLVED)
6070 else:
6093 else:
6071 # backup pre-resolve (merge uses .orig for its own purposes)
6094 # backup pre-resolve (merge uses .orig for its own purposes)
6072 a = repo.wjoin(f)
6095 a = repo.wjoin(f)
6073 try:
6096 try:
6074 util.copyfile(a, a + b".resolve")
6097 util.copyfile(a, a + b".resolve")
6075 except (IOError, OSError) as inst:
6098 except (IOError, OSError) as inst:
6076 if inst.errno != errno.ENOENT:
6099 if inst.errno != errno.ENOENT:
6077 raise
6100 raise
6078
6101
6079 try:
6102 try:
6080 # preresolve file
6103 # preresolve file
6081 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6104 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6082 with ui.configoverride(overrides, b'resolve'):
6105 with ui.configoverride(overrides, b'resolve'):
6083 complete, r = ms.preresolve(f, wctx)
6106 complete, r = ms.preresolve(f, wctx)
6084 if not complete:
6107 if not complete:
6085 tocomplete.append(f)
6108 tocomplete.append(f)
6086 elif r:
6109 elif r:
6087 ret = 1
6110 ret = 1
6088 finally:
6111 finally:
6089 ms.commit()
6112 ms.commit()
6090
6113
6091 # replace filemerge's .orig file with our resolve file, but only
6114 # replace filemerge's .orig file with our resolve file, but only
6092 # for merges that are complete
6115 # for merges that are complete
6093 if complete:
6116 if complete:
6094 try:
6117 try:
6095 util.rename(
6118 util.rename(
6096 a + b".resolve", scmutil.backuppath(ui, repo, f)
6119 a + b".resolve", scmutil.backuppath(ui, repo, f)
6097 )
6120 )
6098 except OSError as inst:
6121 except OSError as inst:
6099 if inst.errno != errno.ENOENT:
6122 if inst.errno != errno.ENOENT:
6100 raise
6123 raise
6101
6124
6102 if hasconflictmarkers:
6125 if hasconflictmarkers:
6103 ui.warn(
6126 ui.warn(
6104 _(
6127 _(
6105 b'warning: the following files still have conflict '
6128 b'warning: the following files still have conflict '
6106 b'markers:\n'
6129 b'markers:\n'
6107 )
6130 )
6108 + b''.join(
6131 + b''.join(
6109 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6132 b' ' + uipathfn(f) + b'\n' for f in hasconflictmarkers
6110 )
6133 )
6111 )
6134 )
6112 if markcheck == b'abort' and not all and not pats:
6135 if markcheck == b'abort' and not all and not pats:
6113 raise error.Abort(
6136 raise error.Abort(
6114 _(b'conflict markers detected'),
6137 _(b'conflict markers detected'),
6115 hint=_(b'use --all to mark anyway'),
6138 hint=_(b'use --all to mark anyway'),
6116 )
6139 )
6117
6140
6118 for f in tocomplete:
6141 for f in tocomplete:
6119 try:
6142 try:
6120 # resolve file
6143 # resolve file
6121 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6144 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
6122 with ui.configoverride(overrides, b'resolve'):
6145 with ui.configoverride(overrides, b'resolve'):
6123 r = ms.resolve(f, wctx)
6146 r = ms.resolve(f, wctx)
6124 if r:
6147 if r:
6125 ret = 1
6148 ret = 1
6126 finally:
6149 finally:
6127 ms.commit()
6150 ms.commit()
6128
6151
6129 # replace filemerge's .orig file with our resolve file
6152 # replace filemerge's .orig file with our resolve file
6130 a = repo.wjoin(f)
6153 a = repo.wjoin(f)
6131 try:
6154 try:
6132 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
6155 util.rename(a + b".resolve", scmutil.backuppath(ui, repo, f))
6133 except OSError as inst:
6156 except OSError as inst:
6134 if inst.errno != errno.ENOENT:
6157 if inst.errno != errno.ENOENT:
6135 raise
6158 raise
6136
6159
6137 ms.commit()
6160 ms.commit()
6138 branchmerge = repo.dirstate.p2() != nullid
6161 branchmerge = repo.dirstate.p2() != nullid
6139 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6162 mergestatemod.recordupdates(repo, ms.actions(), branchmerge, None)
6140
6163
6141 if not didwork and pats:
6164 if not didwork and pats:
6142 hint = None
6165 hint = None
6143 if not any([p for p in pats if p.find(b':') >= 0]):
6166 if not any([p for p in pats if p.find(b':') >= 0]):
6144 pats = [b'path:%s' % p for p in pats]
6167 pats = [b'path:%s' % p for p in pats]
6145 m = scmutil.match(wctx, pats, opts)
6168 m = scmutil.match(wctx, pats, opts)
6146 for f in ms:
6169 for f in ms:
6147 if not m(f):
6170 if not m(f):
6148 continue
6171 continue
6149
6172
6150 def flag(o):
6173 def flag(o):
6151 if o == b're_merge':
6174 if o == b're_merge':
6152 return b'--re-merge '
6175 return b'--re-merge '
6153 return b'-%s ' % o[0:1]
6176 return b'-%s ' % o[0:1]
6154
6177
6155 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6178 flags = b''.join([flag(o) for o in flaglist if opts.get(o)])
6156 hint = _(b"(try: hg resolve %s%s)\n") % (
6179 hint = _(b"(try: hg resolve %s%s)\n") % (
6157 flags,
6180 flags,
6158 b' '.join(pats),
6181 b' '.join(pats),
6159 )
6182 )
6160 break
6183 break
6161 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6184 ui.warn(_(b"arguments do not match paths that need resolving\n"))
6162 if hint:
6185 if hint:
6163 ui.warn(hint)
6186 ui.warn(hint)
6164 elif ms.mergedriver and ms.mdstate() != b's':
6187 elif ms.mergedriver and ms.mdstate() != b's':
6165 # run conclude step when either a driver-resolved file is requested
6188 # run conclude step when either a driver-resolved file is requested
6166 # or there are no driver-resolved files
6189 # or there are no driver-resolved files
6167 # we can't use 'ret' to determine whether any files are unresolved
6190 # we can't use 'ret' to determine whether any files are unresolved
6168 # because we might not have tried to resolve some
6191 # because we might not have tried to resolve some
6169 if (runconclude or not list(ms.driverresolved())) and not list(
6192 if (runconclude or not list(ms.driverresolved())) and not list(
6170 ms.unresolved()
6193 ms.unresolved()
6171 ):
6194 ):
6172 proceed = mergemod.driverconclude(repo, ms, wctx)
6195 proceed = mergemod.driverconclude(repo, ms, wctx)
6173 ms.commit()
6196 ms.commit()
6174 if not proceed:
6197 if not proceed:
6175 return 1
6198 return 1
6176
6199
6177 # Nudge users into finishing an unfinished operation
6200 # Nudge users into finishing an unfinished operation
6178 unresolvedf = list(ms.unresolved())
6201 unresolvedf = list(ms.unresolved())
6179 driverresolvedf = list(ms.driverresolved())
6202 driverresolvedf = list(ms.driverresolved())
6180 if not unresolvedf and not driverresolvedf:
6203 if not unresolvedf and not driverresolvedf:
6181 ui.status(_(b'(no more unresolved files)\n'))
6204 ui.status(_(b'(no more unresolved files)\n'))
6182 cmdutil.checkafterresolved(repo)
6205 cmdutil.checkafterresolved(repo)
6183 elif not unresolvedf:
6206 elif not unresolvedf:
6184 ui.status(
6207 ui.status(
6185 _(
6208 _(
6186 b'(no more unresolved files -- '
6209 b'(no more unresolved files -- '
6187 b'run "hg resolve --all" to conclude)\n'
6210 b'run "hg resolve --all" to conclude)\n'
6188 )
6211 )
6189 )
6212 )
6190
6213
6191 return ret
6214 return ret
6192
6215
6193
6216
6194 @command(
6217 @command(
6195 b'revert',
6218 b'revert',
6196 [
6219 [
6197 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6220 (b'a', b'all', None, _(b'revert all changes when no arguments given')),
6198 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6221 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
6199 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6222 (b'r', b'rev', b'', _(b'revert to the specified revision'), _(b'REV')),
6200 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6223 (b'C', b'no-backup', None, _(b'do not save backup copies of files')),
6201 (b'i', b'interactive', None, _(b'interactively select the changes')),
6224 (b'i', b'interactive', None, _(b'interactively select the changes')),
6202 ]
6225 ]
6203 + walkopts
6226 + walkopts
6204 + dryrunopts,
6227 + dryrunopts,
6205 _(b'[OPTION]... [-r REV] [NAME]...'),
6228 _(b'[OPTION]... [-r REV] [NAME]...'),
6206 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6229 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6207 )
6230 )
6208 def revert(ui, repo, *pats, **opts):
6231 def revert(ui, repo, *pats, **opts):
6209 """restore files to their checkout state
6232 """restore files to their checkout state
6210
6233
6211 .. note::
6234 .. note::
6212
6235
6213 To check out earlier revisions, you should use :hg:`update REV`.
6236 To check out earlier revisions, you should use :hg:`update REV`.
6214 To cancel an uncommitted merge (and lose your changes),
6237 To cancel an uncommitted merge (and lose your changes),
6215 use :hg:`merge --abort`.
6238 use :hg:`merge --abort`.
6216
6239
6217 With no revision specified, revert the specified files or directories
6240 With no revision specified, revert the specified files or directories
6218 to the contents they had in the parent of the working directory.
6241 to the contents they had in the parent of the working directory.
6219 This restores the contents of files to an unmodified
6242 This restores the contents of files to an unmodified
6220 state and unschedules adds, removes, copies, and renames. If the
6243 state and unschedules adds, removes, copies, and renames. If the
6221 working directory has two parents, you must explicitly specify a
6244 working directory has two parents, you must explicitly specify a
6222 revision.
6245 revision.
6223
6246
6224 Using the -r/--rev or -d/--date options, revert the given files or
6247 Using the -r/--rev or -d/--date options, revert the given files or
6225 directories to their states as of a specific revision. Because
6248 directories to their states as of a specific revision. Because
6226 revert does not change the working directory parents, this will
6249 revert does not change the working directory parents, this will
6227 cause these files to appear modified. This can be helpful to "back
6250 cause these files to appear modified. This can be helpful to "back
6228 out" some or all of an earlier change. See :hg:`backout` for a
6251 out" some or all of an earlier change. See :hg:`backout` for a
6229 related method.
6252 related method.
6230
6253
6231 Modified files are saved with a .orig suffix before reverting.
6254 Modified files are saved with a .orig suffix before reverting.
6232 To disable these backups, use --no-backup. It is possible to store
6255 To disable these backups, use --no-backup. It is possible to store
6233 the backup files in a custom directory relative to the root of the
6256 the backup files in a custom directory relative to the root of the
6234 repository by setting the ``ui.origbackuppath`` configuration
6257 repository by setting the ``ui.origbackuppath`` configuration
6235 option.
6258 option.
6236
6259
6237 See :hg:`help dates` for a list of formats valid for -d/--date.
6260 See :hg:`help dates` for a list of formats valid for -d/--date.
6238
6261
6239 See :hg:`help backout` for a way to reverse the effect of an
6262 See :hg:`help backout` for a way to reverse the effect of an
6240 earlier changeset.
6263 earlier changeset.
6241
6264
6242 Returns 0 on success.
6265 Returns 0 on success.
6243 """
6266 """
6244
6267
6245 opts = pycompat.byteskwargs(opts)
6268 opts = pycompat.byteskwargs(opts)
6246 if opts.get(b"date"):
6269 if opts.get(b"date"):
6247 if opts.get(b"rev"):
6270 if opts.get(b"rev"):
6248 raise error.Abort(_(b"you can't specify a revision and a date"))
6271 raise error.Abort(_(b"you can't specify a revision and a date"))
6249 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6272 opts[b"rev"] = cmdutil.finddate(ui, repo, opts[b"date"])
6250
6273
6251 parent, p2 = repo.dirstate.parents()
6274 parent, p2 = repo.dirstate.parents()
6252 if not opts.get(b'rev') and p2 != nullid:
6275 if not opts.get(b'rev') and p2 != nullid:
6253 # revert after merge is a trap for new users (issue2915)
6276 # revert after merge is a trap for new users (issue2915)
6254 raise error.Abort(
6277 raise error.Abort(
6255 _(b'uncommitted merge with no revision specified'),
6278 _(b'uncommitted merge with no revision specified'),
6256 hint=_(b"use 'hg update' or see 'hg help revert'"),
6279 hint=_(b"use 'hg update' or see 'hg help revert'"),
6257 )
6280 )
6258
6281
6259 rev = opts.get(b'rev')
6282 rev = opts.get(b'rev')
6260 if rev:
6283 if rev:
6261 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6284 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
6262 ctx = scmutil.revsingle(repo, rev)
6285 ctx = scmutil.revsingle(repo, rev)
6263
6286
6264 if not (
6287 if not (
6265 pats
6288 pats
6266 or opts.get(b'include')
6289 or opts.get(b'include')
6267 or opts.get(b'exclude')
6290 or opts.get(b'exclude')
6268 or opts.get(b'all')
6291 or opts.get(b'all')
6269 or opts.get(b'interactive')
6292 or opts.get(b'interactive')
6270 ):
6293 ):
6271 msg = _(b"no files or directories specified")
6294 msg = _(b"no files or directories specified")
6272 if p2 != nullid:
6295 if p2 != nullid:
6273 hint = _(
6296 hint = _(
6274 b"uncommitted merge, use --all to discard all changes,"
6297 b"uncommitted merge, use --all to discard all changes,"
6275 b" or 'hg update -C .' to abort the merge"
6298 b" or 'hg update -C .' to abort the merge"
6276 )
6299 )
6277 raise error.Abort(msg, hint=hint)
6300 raise error.Abort(msg, hint=hint)
6278 dirty = any(repo.status())
6301 dirty = any(repo.status())
6279 node = ctx.node()
6302 node = ctx.node()
6280 if node != parent:
6303 if node != parent:
6281 if dirty:
6304 if dirty:
6282 hint = (
6305 hint = (
6283 _(
6306 _(
6284 b"uncommitted changes, use --all to discard all"
6307 b"uncommitted changes, use --all to discard all"
6285 b" changes, or 'hg update %d' to update"
6308 b" changes, or 'hg update %d' to update"
6286 )
6309 )
6287 % ctx.rev()
6310 % ctx.rev()
6288 )
6311 )
6289 else:
6312 else:
6290 hint = (
6313 hint = (
6291 _(
6314 _(
6292 b"use --all to revert all files,"
6315 b"use --all to revert all files,"
6293 b" or 'hg update %d' to update"
6316 b" or 'hg update %d' to update"
6294 )
6317 )
6295 % ctx.rev()
6318 % ctx.rev()
6296 )
6319 )
6297 elif dirty:
6320 elif dirty:
6298 hint = _(b"uncommitted changes, use --all to discard all changes")
6321 hint = _(b"uncommitted changes, use --all to discard all changes")
6299 else:
6322 else:
6300 hint = _(b"use --all to revert all files")
6323 hint = _(b"use --all to revert all files")
6301 raise error.Abort(msg, hint=hint)
6324 raise error.Abort(msg, hint=hint)
6302
6325
6303 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6326 return cmdutil.revert(ui, repo, ctx, *pats, **pycompat.strkwargs(opts))
6304
6327
6305
6328
6306 @command(
6329 @command(
6307 b'rollback',
6330 b'rollback',
6308 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6331 dryrunopts + [(b'f', b'force', False, _(b'ignore safety measures'))],
6309 helpcategory=command.CATEGORY_MAINTENANCE,
6332 helpcategory=command.CATEGORY_MAINTENANCE,
6310 )
6333 )
6311 def rollback(ui, repo, **opts):
6334 def rollback(ui, repo, **opts):
6312 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6335 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6313
6336
6314 Please use :hg:`commit --amend` instead of rollback to correct
6337 Please use :hg:`commit --amend` instead of rollback to correct
6315 mistakes in the last commit.
6338 mistakes in the last commit.
6316
6339
6317 This command should be used with care. There is only one level of
6340 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
6341 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
6342 restore the dirstate at the time of the last transaction, losing
6320 any dirstate changes since that time. This command does not alter
6343 any dirstate changes since that time. This command does not alter
6321 the working directory.
6344 the working directory.
6322
6345
6323 Transactions are used to encapsulate the effects of all commands
6346 Transactions are used to encapsulate the effects of all commands
6324 that create new changesets or propagate existing changesets into a
6347 that create new changesets or propagate existing changesets into a
6325 repository.
6348 repository.
6326
6349
6327 .. container:: verbose
6350 .. container:: verbose
6328
6351
6329 For example, the following commands are transactional, and their
6352 For example, the following commands are transactional, and their
6330 effects can be rolled back:
6353 effects can be rolled back:
6331
6354
6332 - commit
6355 - commit
6333 - import
6356 - import
6334 - pull
6357 - pull
6335 - push (with this repository as the destination)
6358 - push (with this repository as the destination)
6336 - unbundle
6359 - unbundle
6337
6360
6338 To avoid permanent data loss, rollback will refuse to rollback a
6361 To avoid permanent data loss, rollback will refuse to rollback a
6339 commit transaction if it isn't checked out. Use --force to
6362 commit transaction if it isn't checked out. Use --force to
6340 override this protection.
6363 override this protection.
6341
6364
6342 The rollback command can be entirely disabled by setting the
6365 The rollback command can be entirely disabled by setting the
6343 ``ui.rollback`` configuration setting to false. If you're here
6366 ``ui.rollback`` configuration setting to false. If you're here
6344 because you want to use rollback and it's disabled, you can
6367 because you want to use rollback and it's disabled, you can
6345 re-enable the command by setting ``ui.rollback`` to true.
6368 re-enable the command by setting ``ui.rollback`` to true.
6346
6369
6347 This command is not intended for use on public repositories. Once
6370 This command is not intended for use on public repositories. Once
6348 changes are visible for pull by other users, rolling a transaction
6371 changes are visible for pull by other users, rolling a transaction
6349 back locally is ineffective (someone else may already have pulled
6372 back locally is ineffective (someone else may already have pulled
6350 the changes). Furthermore, a race is possible with readers of the
6373 the changes). Furthermore, a race is possible with readers of the
6351 repository; for example an in-progress pull from the repository
6374 repository; for example an in-progress pull from the repository
6352 may fail if a rollback is performed.
6375 may fail if a rollback is performed.
6353
6376
6354 Returns 0 on success, 1 if no rollback data is available.
6377 Returns 0 on success, 1 if no rollback data is available.
6355 """
6378 """
6356 if not ui.configbool(b'ui', b'rollback'):
6379 if not ui.configbool(b'ui', b'rollback'):
6357 raise error.Abort(
6380 raise error.Abort(
6358 _(b'rollback is disabled because it is unsafe'),
6381 _(b'rollback is disabled because it is unsafe'),
6359 hint=b'see `hg help -v rollback` for information',
6382 hint=b'see `hg help -v rollback` for information',
6360 )
6383 )
6361 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6384 return repo.rollback(dryrun=opts.get('dry_run'), force=opts.get('force'))
6362
6385
6363
6386
6364 @command(
6387 @command(
6365 b'root',
6388 b'root',
6366 [] + formatteropts,
6389 [] + formatteropts,
6367 intents={INTENT_READONLY},
6390 intents={INTENT_READONLY},
6368 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6391 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6369 )
6392 )
6370 def root(ui, repo, **opts):
6393 def root(ui, repo, **opts):
6371 """print the root (top) of the current working directory
6394 """print the root (top) of the current working directory
6372
6395
6373 Print the root directory of the current repository.
6396 Print the root directory of the current repository.
6374
6397
6375 .. container:: verbose
6398 .. container:: verbose
6376
6399
6377 Template:
6400 Template:
6378
6401
6379 The following keywords are supported in addition to the common template
6402 The following keywords are supported in addition to the common template
6380 keywords and functions. See also :hg:`help templates`.
6403 keywords and functions. See also :hg:`help templates`.
6381
6404
6382 :hgpath: String. Path to the .hg directory.
6405 :hgpath: String. Path to the .hg directory.
6383 :storepath: String. Path to the directory holding versioned data.
6406 :storepath: String. Path to the directory holding versioned data.
6384
6407
6385 Returns 0 on success.
6408 Returns 0 on success.
6386 """
6409 """
6387 opts = pycompat.byteskwargs(opts)
6410 opts = pycompat.byteskwargs(opts)
6388 with ui.formatter(b'root', opts) as fm:
6411 with ui.formatter(b'root', opts) as fm:
6389 fm.startitem()
6412 fm.startitem()
6390 fm.write(b'reporoot', b'%s\n', repo.root)
6413 fm.write(b'reporoot', b'%s\n', repo.root)
6391 fm.data(hgpath=repo.path, storepath=repo.spath)
6414 fm.data(hgpath=repo.path, storepath=repo.spath)
6392
6415
6393
6416
6394 @command(
6417 @command(
6395 b'serve',
6418 b'serve',
6396 [
6419 [
6397 (
6420 (
6398 b'A',
6421 b'A',
6399 b'accesslog',
6422 b'accesslog',
6400 b'',
6423 b'',
6401 _(b'name of access log file to write to'),
6424 _(b'name of access log file to write to'),
6402 _(b'FILE'),
6425 _(b'FILE'),
6403 ),
6426 ),
6404 (b'd', b'daemon', None, _(b'run server in background')),
6427 (b'd', b'daemon', None, _(b'run server in background')),
6405 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6428 (b'', b'daemon-postexec', [], _(b'used internally by daemon mode')),
6406 (
6429 (
6407 b'E',
6430 b'E',
6408 b'errorlog',
6431 b'errorlog',
6409 b'',
6432 b'',
6410 _(b'name of error log file to write to'),
6433 _(b'name of error log file to write to'),
6411 _(b'FILE'),
6434 _(b'FILE'),
6412 ),
6435 ),
6413 # use string type, then we can check if something was passed
6436 # use string type, then we can check if something was passed
6414 (
6437 (
6415 b'p',
6438 b'p',
6416 b'port',
6439 b'port',
6417 b'',
6440 b'',
6418 _(b'port to listen on (default: 8000)'),
6441 _(b'port to listen on (default: 8000)'),
6419 _(b'PORT'),
6442 _(b'PORT'),
6420 ),
6443 ),
6421 (
6444 (
6422 b'a',
6445 b'a',
6423 b'address',
6446 b'address',
6424 b'',
6447 b'',
6425 _(b'address to listen on (default: all interfaces)'),
6448 _(b'address to listen on (default: all interfaces)'),
6426 _(b'ADDR'),
6449 _(b'ADDR'),
6427 ),
6450 ),
6428 (
6451 (
6429 b'',
6452 b'',
6430 b'prefix',
6453 b'prefix',
6431 b'',
6454 b'',
6432 _(b'prefix path to serve from (default: server root)'),
6455 _(b'prefix path to serve from (default: server root)'),
6433 _(b'PREFIX'),
6456 _(b'PREFIX'),
6434 ),
6457 ),
6435 (
6458 (
6436 b'n',
6459 b'n',
6437 b'name',
6460 b'name',
6438 b'',
6461 b'',
6439 _(b'name to show in web pages (default: working directory)'),
6462 _(b'name to show in web pages (default: working directory)'),
6440 _(b'NAME'),
6463 _(b'NAME'),
6441 ),
6464 ),
6442 (
6465 (
6443 b'',
6466 b'',
6444 b'web-conf',
6467 b'web-conf',
6445 b'',
6468 b'',
6446 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6469 _(b"name of the hgweb config file (see 'hg help hgweb')"),
6447 _(b'FILE'),
6470 _(b'FILE'),
6448 ),
6471 ),
6449 (
6472 (
6450 b'',
6473 b'',
6451 b'webdir-conf',
6474 b'webdir-conf',
6452 b'',
6475 b'',
6453 _(b'name of the hgweb config file (DEPRECATED)'),
6476 _(b'name of the hgweb config file (DEPRECATED)'),
6454 _(b'FILE'),
6477 _(b'FILE'),
6455 ),
6478 ),
6456 (
6479 (
6457 b'',
6480 b'',
6458 b'pid-file',
6481 b'pid-file',
6459 b'',
6482 b'',
6460 _(b'name of file to write process ID to'),
6483 _(b'name of file to write process ID to'),
6461 _(b'FILE'),
6484 _(b'FILE'),
6462 ),
6485 ),
6463 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6486 (b'', b'stdio', None, _(b'for remote clients (ADVANCED)')),
6464 (
6487 (
6465 b'',
6488 b'',
6466 b'cmdserver',
6489 b'cmdserver',
6467 b'',
6490 b'',
6468 _(b'for remote clients (ADVANCED)'),
6491 _(b'for remote clients (ADVANCED)'),
6469 _(b'MODE'),
6492 _(b'MODE'),
6470 ),
6493 ),
6471 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6494 (b't', b'templates', b'', _(b'web templates to use'), _(b'TEMPLATE')),
6472 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6495 (b'', b'style', b'', _(b'template style to use'), _(b'STYLE')),
6473 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6496 (b'6', b'ipv6', None, _(b'use IPv6 in addition to IPv4')),
6474 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6497 (b'', b'certificate', b'', _(b'SSL certificate file'), _(b'FILE')),
6475 (b'', b'print-url', None, _(b'start and print only the URL')),
6498 (b'', b'print-url', None, _(b'start and print only the URL')),
6476 ]
6499 ]
6477 + subrepoopts,
6500 + subrepoopts,
6478 _(b'[OPTION]...'),
6501 _(b'[OPTION]...'),
6479 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6502 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
6480 helpbasic=True,
6503 helpbasic=True,
6481 optionalrepo=True,
6504 optionalrepo=True,
6482 )
6505 )
6483 def serve(ui, repo, **opts):
6506 def serve(ui, repo, **opts):
6484 """start stand-alone webserver
6507 """start stand-alone webserver
6485
6508
6486 Start a local HTTP repository browser and pull server. You can use
6509 Start a local HTTP repository browser and pull server. You can use
6487 this for ad-hoc sharing and browsing of repositories. It is
6510 this for ad-hoc sharing and browsing of repositories. It is
6488 recommended to use a real web server to serve a repository for
6511 recommended to use a real web server to serve a repository for
6489 longer periods of time.
6512 longer periods of time.
6490
6513
6491 Please note that the server does not implement access control.
6514 Please note that the server does not implement access control.
6492 This means that, by default, anybody can read from the server and
6515 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``
6516 nobody can write to it by default. Set the ``web.allow-push``
6494 option to ``*`` to allow everybody to push to the server. You
6517 option to ``*`` to allow everybody to push to the server. You
6495 should use a real web server if you need to authenticate users.
6518 should use a real web server if you need to authenticate users.
6496
6519
6497 By default, the server logs accesses to stdout and errors to
6520 By default, the server logs accesses to stdout and errors to
6498 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6521 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6499 files.
6522 files.
6500
6523
6501 To have the server choose a free port number to listen on, specify
6524 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
6525 a port number of 0; in this case, the server will print the port
6503 number it uses.
6526 number it uses.
6504
6527
6505 Returns 0 on success.
6528 Returns 0 on success.
6506 """
6529 """
6507
6530
6508 opts = pycompat.byteskwargs(opts)
6531 opts = pycompat.byteskwargs(opts)
6509 if opts[b"stdio"] and opts[b"cmdserver"]:
6532 if opts[b"stdio"] and opts[b"cmdserver"]:
6510 raise error.Abort(_(b"cannot use --stdio with --cmdserver"))
6533 raise error.Abort(_(b"cannot use --stdio with --cmdserver"))
6511 if opts[b"print_url"] and ui.verbose:
6534 if opts[b"print_url"] and ui.verbose:
6512 raise error.Abort(_(b"cannot use --print-url with --verbose"))
6535 raise error.Abort(_(b"cannot use --print-url with --verbose"))
6513
6536
6514 if opts[b"stdio"]:
6537 if opts[b"stdio"]:
6515 if repo is None:
6538 if repo is None:
6516 raise error.RepoError(
6539 raise error.RepoError(
6517 _(b"there is no Mercurial repository here (.hg not found)")
6540 _(b"there is no Mercurial repository here (.hg not found)")
6518 )
6541 )
6519 s = wireprotoserver.sshserver(ui, repo)
6542 s = wireprotoserver.sshserver(ui, repo)
6520 s.serve_forever()
6543 s.serve_forever()
6521
6544
6522 service = server.createservice(ui, repo, opts)
6545 service = server.createservice(ui, repo, opts)
6523 return server.runservice(opts, initfn=service.init, runfn=service.run)
6546 return server.runservice(opts, initfn=service.init, runfn=service.run)
6524
6547
6525
6548
6526 @command(
6549 @command(
6527 b'shelve',
6550 b'shelve',
6528 [
6551 [
6529 (
6552 (
6530 b'A',
6553 b'A',
6531 b'addremove',
6554 b'addremove',
6532 None,
6555 None,
6533 _(b'mark new/missing files as added/removed before shelving'),
6556 _(b'mark new/missing files as added/removed before shelving'),
6534 ),
6557 ),
6535 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6558 (b'u', b'unknown', None, _(b'store unknown files in the shelve')),
6536 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6559 (b'', b'cleanup', None, _(b'delete all shelved changes')),
6537 (
6560 (
6538 b'',
6561 b'',
6539 b'date',
6562 b'date',
6540 b'',
6563 b'',
6541 _(b'shelve with the specified commit date'),
6564 _(b'shelve with the specified commit date'),
6542 _(b'DATE'),
6565 _(b'DATE'),
6543 ),
6566 ),
6544 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6567 (b'd', b'delete', None, _(b'delete the named shelved change(s)')),
6545 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6568 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
6546 (
6569 (
6547 b'k',
6570 b'k',
6548 b'keep',
6571 b'keep',
6549 False,
6572 False,
6550 _(b'shelve, but keep changes in the working directory'),
6573 _(b'shelve, but keep changes in the working directory'),
6551 ),
6574 ),
6552 (b'l', b'list', None, _(b'list current shelves')),
6575 (b'l', b'list', None, _(b'list current shelves')),
6553 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6576 (b'm', b'message', b'', _(b'use text as shelve message'), _(b'TEXT')),
6554 (
6577 (
6555 b'n',
6578 b'n',
6556 b'name',
6579 b'name',
6557 b'',
6580 b'',
6558 _(b'use the given name for the shelved commit'),
6581 _(b'use the given name for the shelved commit'),
6559 _(b'NAME'),
6582 _(b'NAME'),
6560 ),
6583 ),
6561 (
6584 (
6562 b'p',
6585 b'p',
6563 b'patch',
6586 b'patch',
6564 None,
6587 None,
6565 _(
6588 _(
6566 b'output patches for changes (provide the names of the shelved '
6589 b'output patches for changes (provide the names of the shelved '
6567 b'changes as positional arguments)'
6590 b'changes as positional arguments)'
6568 ),
6591 ),
6569 ),
6592 ),
6570 (b'i', b'interactive', None, _(b'interactive mode')),
6593 (b'i', b'interactive', None, _(b'interactive mode')),
6571 (
6594 (
6572 b'',
6595 b'',
6573 b'stat',
6596 b'stat',
6574 None,
6597 None,
6575 _(
6598 _(
6576 b'output diffstat-style summary of changes (provide the names of '
6599 b'output diffstat-style summary of changes (provide the names of '
6577 b'the shelved changes as positional arguments)'
6600 b'the shelved changes as positional arguments)'
6578 ),
6601 ),
6579 ),
6602 ),
6580 ]
6603 ]
6581 + cmdutil.walkopts,
6604 + cmdutil.walkopts,
6582 _(b'hg shelve [OPTION]... [FILE]...'),
6605 _(b'hg shelve [OPTION]... [FILE]...'),
6583 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6606 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6584 )
6607 )
6585 def shelve(ui, repo, *pats, **opts):
6608 def shelve(ui, repo, *pats, **opts):
6586 '''save and set aside changes from the working directory
6609 '''save and set aside changes from the working directory
6587
6610
6588 Shelving takes files that "hg status" reports as not clean, saves
6611 Shelving takes files that "hg status" reports as not clean, saves
6589 the modifications to a bundle (a shelved change), and reverts the
6612 the modifications to a bundle (a shelved change), and reverts the
6590 files so that their state in the working directory becomes clean.
6613 files so that their state in the working directory becomes clean.
6591
6614
6592 To restore these changes to the working directory, using "hg
6615 To restore these changes to the working directory, using "hg
6593 unshelve"; this will work even if you switch to a different
6616 unshelve"; this will work even if you switch to a different
6594 commit.
6617 commit.
6595
6618
6596 When no files are specified, "hg shelve" saves all not-clean
6619 When no files are specified, "hg shelve" saves all not-clean
6597 files. If specific files or directories are named, only changes to
6620 files. If specific files or directories are named, only changes to
6598 those files are shelved.
6621 those files are shelved.
6599
6622
6600 In bare shelve (when no files are specified, without interactive,
6623 In bare shelve (when no files are specified, without interactive,
6601 include and exclude option), shelving remembers information if the
6624 include and exclude option), shelving remembers information if the
6602 working directory was on newly created branch, in other words working
6625 working directory was on newly created branch, in other words working
6603 directory was on different branch than its first parent. In this
6626 directory was on different branch than its first parent. In this
6604 situation unshelving restores branch information to the working directory.
6627 situation unshelving restores branch information to the working directory.
6605
6628
6606 Each shelved change has a name that makes it easier to find later.
6629 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
6630 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
6631 bookmark, or if there is no active bookmark, the current named
6609 branch. To specify a different name, use ``--name``.
6632 branch. To specify a different name, use ``--name``.
6610
6633
6611 To see a list of existing shelved changes, use the ``--list``
6634 To see a list of existing shelved changes, use the ``--list``
6612 option. For each shelved change, this will print its name, age,
6635 option. For each shelved change, this will print its name, age,
6613 and description; use ``--patch`` or ``--stat`` for more details.
6636 and description; use ``--patch`` or ``--stat`` for more details.
6614
6637
6615 To delete specific shelved changes, use ``--delete``. To delete
6638 To delete specific shelved changes, use ``--delete``. To delete
6616 all shelved changes, use ``--cleanup``.
6639 all shelved changes, use ``--cleanup``.
6617 '''
6640 '''
6618 opts = pycompat.byteskwargs(opts)
6641 opts = pycompat.byteskwargs(opts)
6619 allowables = [
6642 allowables = [
6620 (b'addremove', {b'create'}), # 'create' is pseudo action
6643 (b'addremove', {b'create'}), # 'create' is pseudo action
6621 (b'unknown', {b'create'}),
6644 (b'unknown', {b'create'}),
6622 (b'cleanup', {b'cleanup'}),
6645 (b'cleanup', {b'cleanup'}),
6623 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6646 # ('date', {'create'}), # ignored for passing '--date "0 0"' in tests
6624 (b'delete', {b'delete'}),
6647 (b'delete', {b'delete'}),
6625 (b'edit', {b'create'}),
6648 (b'edit', {b'create'}),
6626 (b'keep', {b'create'}),
6649 (b'keep', {b'create'}),
6627 (b'list', {b'list'}),
6650 (b'list', {b'list'}),
6628 (b'message', {b'create'}),
6651 (b'message', {b'create'}),
6629 (b'name', {b'create'}),
6652 (b'name', {b'create'}),
6630 (b'patch', {b'patch', b'list'}),
6653 (b'patch', {b'patch', b'list'}),
6631 (b'stat', {b'stat', b'list'}),
6654 (b'stat', {b'stat', b'list'}),
6632 ]
6655 ]
6633
6656
6634 def checkopt(opt):
6657 def checkopt(opt):
6635 if opts.get(opt):
6658 if opts.get(opt):
6636 for i, allowable in allowables:
6659 for i, allowable in allowables:
6637 if opts[i] and opt not in allowable:
6660 if opts[i] and opt not in allowable:
6638 raise error.Abort(
6661 raise error.Abort(
6639 _(
6662 _(
6640 b"options '--%s' and '--%s' may not be "
6663 b"options '--%s' and '--%s' may not be "
6641 b"used together"
6664 b"used together"
6642 )
6665 )
6643 % (opt, i)
6666 % (opt, i)
6644 )
6667 )
6645 return True
6668 return True
6646
6669
6647 if checkopt(b'cleanup'):
6670 if checkopt(b'cleanup'):
6648 if pats:
6671 if pats:
6649 raise error.Abort(_(b"cannot specify names when using '--cleanup'"))
6672 raise error.Abort(_(b"cannot specify names when using '--cleanup'"))
6650 return shelvemod.cleanupcmd(ui, repo)
6673 return shelvemod.cleanupcmd(ui, repo)
6651 elif checkopt(b'delete'):
6674 elif checkopt(b'delete'):
6652 return shelvemod.deletecmd(ui, repo, pats)
6675 return shelvemod.deletecmd(ui, repo, pats)
6653 elif checkopt(b'list'):
6676 elif checkopt(b'list'):
6654 return shelvemod.listcmd(ui, repo, pats, opts)
6677 return shelvemod.listcmd(ui, repo, pats, opts)
6655 elif checkopt(b'patch') or checkopt(b'stat'):
6678 elif checkopt(b'patch') or checkopt(b'stat'):
6656 return shelvemod.patchcmds(ui, repo, pats, opts)
6679 return shelvemod.patchcmds(ui, repo, pats, opts)
6657 else:
6680 else:
6658 return shelvemod.createcmd(ui, repo, pats, opts)
6681 return shelvemod.createcmd(ui, repo, pats, opts)
6659
6682
6660
6683
6661 _NOTTERSE = b'nothing'
6684 _NOTTERSE = b'nothing'
6662
6685
6663
6686
6664 @command(
6687 @command(
6665 b'status|st',
6688 b'status|st',
6666 [
6689 [
6667 (b'A', b'all', None, _(b'show status of all files')),
6690 (b'A', b'all', None, _(b'show status of all files')),
6668 (b'm', b'modified', None, _(b'show only modified files')),
6691 (b'm', b'modified', None, _(b'show only modified files')),
6669 (b'a', b'added', None, _(b'show only added files')),
6692 (b'a', b'added', None, _(b'show only added files')),
6670 (b'r', b'removed', None, _(b'show only removed files')),
6693 (b'r', b'removed', None, _(b'show only removed files')),
6671 (b'd', b'deleted', None, _(b'show only missing files')),
6694 (b'd', b'deleted', None, _(b'show only missing files')),
6672 (b'c', b'clean', None, _(b'show only files without changes')),
6695 (b'c', b'clean', None, _(b'show only files without changes')),
6673 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6696 (b'u', b'unknown', None, _(b'show only unknown (not tracked) files')),
6674 (b'i', b'ignored', None, _(b'show only ignored files')),
6697 (b'i', b'ignored', None, _(b'show only ignored files')),
6675 (b'n', b'no-status', None, _(b'hide status prefix')),
6698 (b'n', b'no-status', None, _(b'hide status prefix')),
6676 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6699 (b't', b'terse', _NOTTERSE, _(b'show the terse output (EXPERIMENTAL)')),
6677 (
6700 (
6678 b'C',
6701 b'C',
6679 b'copies',
6702 b'copies',
6680 None,
6703 None,
6681 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6704 _(b'show source of copied files (DEFAULT: ui.statuscopies)'),
6682 ),
6705 ),
6683 (
6706 (
6684 b'0',
6707 b'0',
6685 b'print0',
6708 b'print0',
6686 None,
6709 None,
6687 _(b'end filenames with NUL, for use with xargs'),
6710 _(b'end filenames with NUL, for use with xargs'),
6688 ),
6711 ),
6689 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6712 (b'', b'rev', [], _(b'show difference from revision'), _(b'REV')),
6690 (
6713 (
6691 b'',
6714 b'',
6692 b'change',
6715 b'change',
6693 b'',
6716 b'',
6694 _(b'list the changed files of a revision'),
6717 _(b'list the changed files of a revision'),
6695 _(b'REV'),
6718 _(b'REV'),
6696 ),
6719 ),
6697 ]
6720 ]
6698 + walkopts
6721 + walkopts
6699 + subrepoopts
6722 + subrepoopts
6700 + formatteropts,
6723 + formatteropts,
6701 _(b'[OPTION]... [FILE]...'),
6724 _(b'[OPTION]... [FILE]...'),
6702 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6725 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6703 helpbasic=True,
6726 helpbasic=True,
6704 inferrepo=True,
6727 inferrepo=True,
6705 intents={INTENT_READONLY},
6728 intents={INTENT_READONLY},
6706 )
6729 )
6707 def status(ui, repo, *pats, **opts):
6730 def status(ui, repo, *pats, **opts):
6708 """show changed files in the working directory
6731 """show changed files in the working directory
6709
6732
6710 Show status of files in the repository. If names are given, only
6733 Show status of files in the repository. If names are given, only
6711 files that match are shown. Files that are clean or ignored or
6734 files that match are shown. Files that are clean or ignored or
6712 the source of a copy/move operation, are not listed unless
6735 the source of a copy/move operation, are not listed unless
6713 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6736 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6714 Unless options described with "show only ..." are given, the
6737 Unless options described with "show only ..." are given, the
6715 options -mardu are used.
6738 options -mardu are used.
6716
6739
6717 Option -q/--quiet hides untracked (unknown and ignored) files
6740 Option -q/--quiet hides untracked (unknown and ignored) files
6718 unless explicitly requested with -u/--unknown or -i/--ignored.
6741 unless explicitly requested with -u/--unknown or -i/--ignored.
6719
6742
6720 .. note::
6743 .. note::
6721
6744
6722 :hg:`status` may appear to disagree with diff if permissions have
6745 :hg:`status` may appear to disagree with diff if permissions have
6723 changed or a merge has occurred. The standard diff format does
6746 changed or a merge has occurred. The standard diff format does
6724 not report permission changes and diff only reports changes
6747 not report permission changes and diff only reports changes
6725 relative to one merge parent.
6748 relative to one merge parent.
6726
6749
6727 If one revision is given, it is used as the base revision.
6750 If one revision is given, it is used as the base revision.
6728 If two revisions are given, the differences between them are
6751 If two revisions are given, the differences between them are
6729 shown. The --change option can also be used as a shortcut to list
6752 shown. The --change option can also be used as a shortcut to list
6730 the changed files of a revision from its first parent.
6753 the changed files of a revision from its first parent.
6731
6754
6732 The codes used to show the status of files are::
6755 The codes used to show the status of files are::
6733
6756
6734 M = modified
6757 M = modified
6735 A = added
6758 A = added
6736 R = removed
6759 R = removed
6737 C = clean
6760 C = clean
6738 ! = missing (deleted by non-hg command, but still tracked)
6761 ! = missing (deleted by non-hg command, but still tracked)
6739 ? = not tracked
6762 ? = not tracked
6740 I = ignored
6763 I = ignored
6741 = origin of the previous file (with --copies)
6764 = origin of the previous file (with --copies)
6742
6765
6743 .. container:: verbose
6766 .. container:: verbose
6744
6767
6745 The -t/--terse option abbreviates the output by showing only the directory
6768 The -t/--terse option abbreviates the output by showing only the directory
6746 name if all the files in it share the same status. The option takes an
6769 name if all the files in it share the same status. The option takes an
6747 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6770 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
6748 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6771 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
6749 for 'ignored' and 'c' for clean.
6772 for 'ignored' and 'c' for clean.
6750
6773
6751 It abbreviates only those statuses which are passed. Note that clean and
6774 It abbreviates only those statuses which are passed. Note that clean and
6752 ignored files are not displayed with '--terse ic' unless the -c/--clean
6775 ignored files are not displayed with '--terse ic' unless the -c/--clean
6753 and -i/--ignored options are also used.
6776 and -i/--ignored options are also used.
6754
6777
6755 The -v/--verbose option shows information when the repository is in an
6778 The -v/--verbose option shows information when the repository is in an
6756 unfinished merge, shelve, rebase state etc. You can have this behavior
6779 unfinished merge, shelve, rebase state etc. You can have this behavior
6757 turned on by default by enabling the ``commands.status.verbose`` option.
6780 turned on by default by enabling the ``commands.status.verbose`` option.
6758
6781
6759 You can skip displaying some of these states by setting
6782 You can skip displaying some of these states by setting
6760 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6783 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
6761 'histedit', 'merge', 'rebase', or 'unshelve'.
6784 'histedit', 'merge', 'rebase', or 'unshelve'.
6762
6785
6763 Template:
6786 Template:
6764
6787
6765 The following keywords are supported in addition to the common template
6788 The following keywords are supported in addition to the common template
6766 keywords and functions. See also :hg:`help templates`.
6789 keywords and functions. See also :hg:`help templates`.
6767
6790
6768 :path: String. Repository-absolute path of the file.
6791 :path: String. Repository-absolute path of the file.
6769 :source: String. Repository-absolute path of the file originated from.
6792 :source: String. Repository-absolute path of the file originated from.
6770 Available if ``--copies`` is specified.
6793 Available if ``--copies`` is specified.
6771 :status: String. Character denoting file's status.
6794 :status: String. Character denoting file's status.
6772
6795
6773 Examples:
6796 Examples:
6774
6797
6775 - show changes in the working directory relative to a
6798 - show changes in the working directory relative to a
6776 changeset::
6799 changeset::
6777
6800
6778 hg status --rev 9353
6801 hg status --rev 9353
6779
6802
6780 - show changes in the working directory relative to the
6803 - show changes in the working directory relative to the
6781 current directory (see :hg:`help patterns` for more information)::
6804 current directory (see :hg:`help patterns` for more information)::
6782
6805
6783 hg status re:
6806 hg status re:
6784
6807
6785 - show all changes including copies in an existing changeset::
6808 - show all changes including copies in an existing changeset::
6786
6809
6787 hg status --copies --change 9353
6810 hg status --copies --change 9353
6788
6811
6789 - get a NUL separated list of added files, suitable for xargs::
6812 - get a NUL separated list of added files, suitable for xargs::
6790
6813
6791 hg status -an0
6814 hg status -an0
6792
6815
6793 - show more information about the repository status, abbreviating
6816 - show more information about the repository status, abbreviating
6794 added, removed, modified, deleted, and untracked paths::
6817 added, removed, modified, deleted, and untracked paths::
6795
6818
6796 hg status -v -t mardu
6819 hg status -v -t mardu
6797
6820
6798 Returns 0 on success.
6821 Returns 0 on success.
6799
6822
6800 """
6823 """
6801
6824
6802 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6825 cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
6803 opts = pycompat.byteskwargs(opts)
6826 opts = pycompat.byteskwargs(opts)
6804 revs = opts.get(b'rev')
6827 revs = opts.get(b'rev')
6805 change = opts.get(b'change')
6828 change = opts.get(b'change')
6806 terse = opts.get(b'terse')
6829 terse = opts.get(b'terse')
6807 if terse is _NOTTERSE:
6830 if terse is _NOTTERSE:
6808 if revs:
6831 if revs:
6809 terse = b''
6832 terse = b''
6810 else:
6833 else:
6811 terse = ui.config(b'commands', b'status.terse')
6834 terse = ui.config(b'commands', b'status.terse')
6812
6835
6813 if revs and terse:
6836 if revs and terse:
6814 msg = _(b'cannot use --terse with --rev')
6837 msg = _(b'cannot use --terse with --rev')
6815 raise error.Abort(msg)
6838 raise error.Abort(msg)
6816 elif change:
6839 elif change:
6817 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6840 repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
6818 ctx2 = scmutil.revsingle(repo, change, None)
6841 ctx2 = scmutil.revsingle(repo, change, None)
6819 ctx1 = ctx2.p1()
6842 ctx1 = ctx2.p1()
6820 else:
6843 else:
6821 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6844 repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
6822 ctx1, ctx2 = scmutil.revpair(repo, revs)
6845 ctx1, ctx2 = scmutil.revpair(repo, revs)
6823
6846
6824 forcerelativevalue = None
6847 forcerelativevalue = None
6825 if ui.hasconfig(b'commands', b'status.relative'):
6848 if ui.hasconfig(b'commands', b'status.relative'):
6826 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6849 forcerelativevalue = ui.configbool(b'commands', b'status.relative')
6827 uipathfn = scmutil.getuipathfn(
6850 uipathfn = scmutil.getuipathfn(
6828 repo,
6851 repo,
6829 legacyrelativevalue=bool(pats),
6852 legacyrelativevalue=bool(pats),
6830 forcerelativevalue=forcerelativevalue,
6853 forcerelativevalue=forcerelativevalue,
6831 )
6854 )
6832
6855
6833 if opts.get(b'print0'):
6856 if opts.get(b'print0'):
6834 end = b'\0'
6857 end = b'\0'
6835 else:
6858 else:
6836 end = b'\n'
6859 end = b'\n'
6837 states = b'modified added removed deleted unknown ignored clean'.split()
6860 states = b'modified added removed deleted unknown ignored clean'.split()
6838 show = [k for k in states if opts.get(k)]
6861 show = [k for k in states if opts.get(k)]
6839 if opts.get(b'all'):
6862 if opts.get(b'all'):
6840 show += ui.quiet and (states[:4] + [b'clean']) or states
6863 show += ui.quiet and (states[:4] + [b'clean']) or states
6841
6864
6842 if not show:
6865 if not show:
6843 if ui.quiet:
6866 if ui.quiet:
6844 show = states[:4]
6867 show = states[:4]
6845 else:
6868 else:
6846 show = states[:5]
6869 show = states[:5]
6847
6870
6848 m = scmutil.match(ctx2, pats, opts)
6871 m = scmutil.match(ctx2, pats, opts)
6849 if terse:
6872 if terse:
6850 # we need to compute clean and unknown to terse
6873 # we need to compute clean and unknown to terse
6851 stat = repo.status(
6874 stat = repo.status(
6852 ctx1.node(),
6875 ctx1.node(),
6853 ctx2.node(),
6876 ctx2.node(),
6854 m,
6877 m,
6855 b'ignored' in show or b'i' in terse,
6878 b'ignored' in show or b'i' in terse,
6856 clean=True,
6879 clean=True,
6857 unknown=True,
6880 unknown=True,
6858 listsubrepos=opts.get(b'subrepos'),
6881 listsubrepos=opts.get(b'subrepos'),
6859 )
6882 )
6860
6883
6861 stat = cmdutil.tersedir(stat, terse)
6884 stat = cmdutil.tersedir(stat, terse)
6862 else:
6885 else:
6863 stat = repo.status(
6886 stat = repo.status(
6864 ctx1.node(),
6887 ctx1.node(),
6865 ctx2.node(),
6888 ctx2.node(),
6866 m,
6889 m,
6867 b'ignored' in show,
6890 b'ignored' in show,
6868 b'clean' in show,
6891 b'clean' in show,
6869 b'unknown' in show,
6892 b'unknown' in show,
6870 opts.get(b'subrepos'),
6893 opts.get(b'subrepos'),
6871 )
6894 )
6872
6895
6873 changestates = zip(
6896 changestates = zip(
6874 states,
6897 states,
6875 pycompat.iterbytestr(b'MAR!?IC'),
6898 pycompat.iterbytestr(b'MAR!?IC'),
6876 [getattr(stat, s.decode('utf8')) for s in states],
6899 [getattr(stat, s.decode('utf8')) for s in states],
6877 )
6900 )
6878
6901
6879 copy = {}
6902 copy = {}
6880 if (
6903 if (
6881 opts.get(b'all')
6904 opts.get(b'all')
6882 or opts.get(b'copies')
6905 or opts.get(b'copies')
6883 or ui.configbool(b'ui', b'statuscopies')
6906 or ui.configbool(b'ui', b'statuscopies')
6884 ) and not opts.get(b'no_status'):
6907 ) and not opts.get(b'no_status'):
6885 copy = copies.pathcopies(ctx1, ctx2, m)
6908 copy = copies.pathcopies(ctx1, ctx2, m)
6886
6909
6887 morestatus = None
6910 morestatus = None
6888 if (
6911 if (
6889 ui.verbose or ui.configbool(b'commands', b'status.verbose')
6912 ui.verbose or ui.configbool(b'commands', b'status.verbose')
6890 ) and not ui.plain():
6913 ) and not ui.plain():
6891 morestatus = cmdutil.readmorestatus(repo)
6914 morestatus = cmdutil.readmorestatus(repo)
6892
6915
6893 ui.pager(b'status')
6916 ui.pager(b'status')
6894 fm = ui.formatter(b'status', opts)
6917 fm = ui.formatter(b'status', opts)
6895 fmt = b'%s' + end
6918 fmt = b'%s' + end
6896 showchar = not opts.get(b'no_status')
6919 showchar = not opts.get(b'no_status')
6897
6920
6898 for state, char, files in changestates:
6921 for state, char, files in changestates:
6899 if state in show:
6922 if state in show:
6900 label = b'status.' + state
6923 label = b'status.' + state
6901 for f in files:
6924 for f in files:
6902 fm.startitem()
6925 fm.startitem()
6903 fm.context(ctx=ctx2)
6926 fm.context(ctx=ctx2)
6904 fm.data(itemtype=b'file', path=f)
6927 fm.data(itemtype=b'file', path=f)
6905 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6928 fm.condwrite(showchar, b'status', b'%s ', char, label=label)
6906 fm.plain(fmt % uipathfn(f), label=label)
6929 fm.plain(fmt % uipathfn(f), label=label)
6907 if f in copy:
6930 if f in copy:
6908 fm.data(source=copy[f])
6931 fm.data(source=copy[f])
6909 fm.plain(
6932 fm.plain(
6910 (b' %s' + end) % uipathfn(copy[f]),
6933 (b' %s' + end) % uipathfn(copy[f]),
6911 label=b'status.copied',
6934 label=b'status.copied',
6912 )
6935 )
6913 if morestatus:
6936 if morestatus:
6914 morestatus.formatfile(f, fm)
6937 morestatus.formatfile(f, fm)
6915
6938
6916 if morestatus:
6939 if morestatus:
6917 morestatus.formatfooter(fm)
6940 morestatus.formatfooter(fm)
6918 fm.end()
6941 fm.end()
6919
6942
6920
6943
6921 @command(
6944 @command(
6922 b'summary|sum',
6945 b'summary|sum',
6923 [(b'', b'remote', None, _(b'check for push and pull'))],
6946 [(b'', b'remote', None, _(b'check for push and pull'))],
6924 b'[--remote]',
6947 b'[--remote]',
6925 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6948 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6926 helpbasic=True,
6949 helpbasic=True,
6927 intents={INTENT_READONLY},
6950 intents={INTENT_READONLY},
6928 )
6951 )
6929 def summary(ui, repo, **opts):
6952 def summary(ui, repo, **opts):
6930 """summarize working directory state
6953 """summarize working directory state
6931
6954
6932 This generates a brief summary of the working directory state,
6955 This generates a brief summary of the working directory state,
6933 including parents, branch, commit status, phase and available updates.
6956 including parents, branch, commit status, phase and available updates.
6934
6957
6935 With the --remote option, this will check the default paths for
6958 With the --remote option, this will check the default paths for
6936 incoming and outgoing changes. This can be time-consuming.
6959 incoming and outgoing changes. This can be time-consuming.
6937
6960
6938 Returns 0 on success.
6961 Returns 0 on success.
6939 """
6962 """
6940
6963
6941 opts = pycompat.byteskwargs(opts)
6964 opts = pycompat.byteskwargs(opts)
6942 ui.pager(b'summary')
6965 ui.pager(b'summary')
6943 ctx = repo[None]
6966 ctx = repo[None]
6944 parents = ctx.parents()
6967 parents = ctx.parents()
6945 pnode = parents[0].node()
6968 pnode = parents[0].node()
6946 marks = []
6969 marks = []
6947
6970
6948 try:
6971 try:
6949 ms = mergestatemod.mergestate.read(repo)
6972 ms = mergestatemod.mergestate.read(repo)
6950 except error.UnsupportedMergeRecords as e:
6973 except error.UnsupportedMergeRecords as e:
6951 s = b' '.join(e.recordtypes)
6974 s = b' '.join(e.recordtypes)
6952 ui.warn(
6975 ui.warn(
6953 _(b'warning: merge state has unsupported record types: %s\n') % s
6976 _(b'warning: merge state has unsupported record types: %s\n') % s
6954 )
6977 )
6955 unresolved = []
6978 unresolved = []
6956 else:
6979 else:
6957 unresolved = list(ms.unresolved())
6980 unresolved = list(ms.unresolved())
6958
6981
6959 for p in parents:
6982 for p in parents:
6960 # label with log.changeset (instead of log.parent) since this
6983 # label with log.changeset (instead of log.parent) since this
6961 # shows a working directory parent *changeset*:
6984 # shows a working directory parent *changeset*:
6962 # i18n: column positioning for "hg summary"
6985 # i18n: column positioning for "hg summary"
6963 ui.write(
6986 ui.write(
6964 _(b'parent: %d:%s ') % (p.rev(), p),
6987 _(b'parent: %d:%s ') % (p.rev(), p),
6965 label=logcmdutil.changesetlabels(p),
6988 label=logcmdutil.changesetlabels(p),
6966 )
6989 )
6967 ui.write(b' '.join(p.tags()), label=b'log.tag')
6990 ui.write(b' '.join(p.tags()), label=b'log.tag')
6968 if p.bookmarks():
6991 if p.bookmarks():
6969 marks.extend(p.bookmarks())
6992 marks.extend(p.bookmarks())
6970 if p.rev() == -1:
6993 if p.rev() == -1:
6971 if not len(repo):
6994 if not len(repo):
6972 ui.write(_(b' (empty repository)'))
6995 ui.write(_(b' (empty repository)'))
6973 else:
6996 else:
6974 ui.write(_(b' (no revision checked out)'))
6997 ui.write(_(b' (no revision checked out)'))
6975 if p.obsolete():
6998 if p.obsolete():
6976 ui.write(_(b' (obsolete)'))
6999 ui.write(_(b' (obsolete)'))
6977 if p.isunstable():
7000 if p.isunstable():
6978 instabilities = (
7001 instabilities = (
6979 ui.label(instability, b'trouble.%s' % instability)
7002 ui.label(instability, b'trouble.%s' % instability)
6980 for instability in p.instabilities()
7003 for instability in p.instabilities()
6981 )
7004 )
6982 ui.write(b' (' + b', '.join(instabilities) + b')')
7005 ui.write(b' (' + b', '.join(instabilities) + b')')
6983 ui.write(b'\n')
7006 ui.write(b'\n')
6984 if p.description():
7007 if p.description():
6985 ui.status(
7008 ui.status(
6986 b' ' + p.description().splitlines()[0].strip() + b'\n',
7009 b' ' + p.description().splitlines()[0].strip() + b'\n',
6987 label=b'log.summary',
7010 label=b'log.summary',
6988 )
7011 )
6989
7012
6990 branch = ctx.branch()
7013 branch = ctx.branch()
6991 bheads = repo.branchheads(branch)
7014 bheads = repo.branchheads(branch)
6992 # i18n: column positioning for "hg summary"
7015 # i18n: column positioning for "hg summary"
6993 m = _(b'branch: %s\n') % branch
7016 m = _(b'branch: %s\n') % branch
6994 if branch != b'default':
7017 if branch != b'default':
6995 ui.write(m, label=b'log.branch')
7018 ui.write(m, label=b'log.branch')
6996 else:
7019 else:
6997 ui.status(m, label=b'log.branch')
7020 ui.status(m, label=b'log.branch')
6998
7021
6999 if marks:
7022 if marks:
7000 active = repo._activebookmark
7023 active = repo._activebookmark
7001 # i18n: column positioning for "hg summary"
7024 # i18n: column positioning for "hg summary"
7002 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7025 ui.write(_(b'bookmarks:'), label=b'log.bookmark')
7003 if active is not None:
7026 if active is not None:
7004 if active in marks:
7027 if active in marks:
7005 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7028 ui.write(b' *' + active, label=bookmarks.activebookmarklabel)
7006 marks.remove(active)
7029 marks.remove(active)
7007 else:
7030 else:
7008 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7031 ui.write(b' [%s]' % active, label=bookmarks.activebookmarklabel)
7009 for m in marks:
7032 for m in marks:
7010 ui.write(b' ' + m, label=b'log.bookmark')
7033 ui.write(b' ' + m, label=b'log.bookmark')
7011 ui.write(b'\n', label=b'log.bookmark')
7034 ui.write(b'\n', label=b'log.bookmark')
7012
7035
7013 status = repo.status(unknown=True)
7036 status = repo.status(unknown=True)
7014
7037
7015 c = repo.dirstate.copies()
7038 c = repo.dirstate.copies()
7016 copied, renamed = [], []
7039 copied, renamed = [], []
7017 for d, s in pycompat.iteritems(c):
7040 for d, s in pycompat.iteritems(c):
7018 if s in status.removed:
7041 if s in status.removed:
7019 status.removed.remove(s)
7042 status.removed.remove(s)
7020 renamed.append(d)
7043 renamed.append(d)
7021 else:
7044 else:
7022 copied.append(d)
7045 copied.append(d)
7023 if d in status.added:
7046 if d in status.added:
7024 status.added.remove(d)
7047 status.added.remove(d)
7025
7048
7026 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7049 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
7027
7050
7028 labels = [
7051 labels = [
7029 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7052 (ui.label(_(b'%d modified'), b'status.modified'), status.modified),
7030 (ui.label(_(b'%d added'), b'status.added'), status.added),
7053 (ui.label(_(b'%d added'), b'status.added'), status.added),
7031 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7054 (ui.label(_(b'%d removed'), b'status.removed'), status.removed),
7032 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7055 (ui.label(_(b'%d renamed'), b'status.copied'), renamed),
7033 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7056 (ui.label(_(b'%d copied'), b'status.copied'), copied),
7034 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7057 (ui.label(_(b'%d deleted'), b'status.deleted'), status.deleted),
7035 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7058 (ui.label(_(b'%d unknown'), b'status.unknown'), status.unknown),
7036 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7059 (ui.label(_(b'%d unresolved'), b'resolve.unresolved'), unresolved),
7037 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7060 (ui.label(_(b'%d subrepos'), b'status.modified'), subs),
7038 ]
7061 ]
7039 t = []
7062 t = []
7040 for l, s in labels:
7063 for l, s in labels:
7041 if s:
7064 if s:
7042 t.append(l % len(s))
7065 t.append(l % len(s))
7043
7066
7044 t = b', '.join(t)
7067 t = b', '.join(t)
7045 cleanworkdir = False
7068 cleanworkdir = False
7046
7069
7047 if repo.vfs.exists(b'graftstate'):
7070 if repo.vfs.exists(b'graftstate'):
7048 t += _(b' (graft in progress)')
7071 t += _(b' (graft in progress)')
7049 if repo.vfs.exists(b'updatestate'):
7072 if repo.vfs.exists(b'updatestate'):
7050 t += _(b' (interrupted update)')
7073 t += _(b' (interrupted update)')
7051 elif len(parents) > 1:
7074 elif len(parents) > 1:
7052 t += _(b' (merge)')
7075 t += _(b' (merge)')
7053 elif branch != parents[0].branch():
7076 elif branch != parents[0].branch():
7054 t += _(b' (new branch)')
7077 t += _(b' (new branch)')
7055 elif parents[0].closesbranch() and pnode in repo.branchheads(
7078 elif parents[0].closesbranch() and pnode in repo.branchheads(
7056 branch, closed=True
7079 branch, closed=True
7057 ):
7080 ):
7058 t += _(b' (head closed)')
7081 t += _(b' (head closed)')
7059 elif not (
7082 elif not (
7060 status.modified
7083 status.modified
7061 or status.added
7084 or status.added
7062 or status.removed
7085 or status.removed
7063 or renamed
7086 or renamed
7064 or copied
7087 or copied
7065 or subs
7088 or subs
7066 ):
7089 ):
7067 t += _(b' (clean)')
7090 t += _(b' (clean)')
7068 cleanworkdir = True
7091 cleanworkdir = True
7069 elif pnode not in bheads:
7092 elif pnode not in bheads:
7070 t += _(b' (new branch head)')
7093 t += _(b' (new branch head)')
7071
7094
7072 if parents:
7095 if parents:
7073 pendingphase = max(p.phase() for p in parents)
7096 pendingphase = max(p.phase() for p in parents)
7074 else:
7097 else:
7075 pendingphase = phases.public
7098 pendingphase = phases.public
7076
7099
7077 if pendingphase > phases.newcommitphase(ui):
7100 if pendingphase > phases.newcommitphase(ui):
7078 t += b' (%s)' % phases.phasenames[pendingphase]
7101 t += b' (%s)' % phases.phasenames[pendingphase]
7079
7102
7080 if cleanworkdir:
7103 if cleanworkdir:
7081 # i18n: column positioning for "hg summary"
7104 # i18n: column positioning for "hg summary"
7082 ui.status(_(b'commit: %s\n') % t.strip())
7105 ui.status(_(b'commit: %s\n') % t.strip())
7083 else:
7106 else:
7084 # i18n: column positioning for "hg summary"
7107 # i18n: column positioning for "hg summary"
7085 ui.write(_(b'commit: %s\n') % t.strip())
7108 ui.write(_(b'commit: %s\n') % t.strip())
7086
7109
7087 # all ancestors of branch heads - all ancestors of parent = new csets
7110 # all ancestors of branch heads - all ancestors of parent = new csets
7088 new = len(
7111 new = len(
7089 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7112 repo.changelog.findmissing([pctx.node() for pctx in parents], bheads)
7090 )
7113 )
7091
7114
7092 if new == 0:
7115 if new == 0:
7093 # i18n: column positioning for "hg summary"
7116 # i18n: column positioning for "hg summary"
7094 ui.status(_(b'update: (current)\n'))
7117 ui.status(_(b'update: (current)\n'))
7095 elif pnode not in bheads:
7118 elif pnode not in bheads:
7096 # i18n: column positioning for "hg summary"
7119 # i18n: column positioning for "hg summary"
7097 ui.write(_(b'update: %d new changesets (update)\n') % new)
7120 ui.write(_(b'update: %d new changesets (update)\n') % new)
7098 else:
7121 else:
7099 # i18n: column positioning for "hg summary"
7122 # i18n: column positioning for "hg summary"
7100 ui.write(
7123 ui.write(
7101 _(b'update: %d new changesets, %d branch heads (merge)\n')
7124 _(b'update: %d new changesets, %d branch heads (merge)\n')
7102 % (new, len(bheads))
7125 % (new, len(bheads))
7103 )
7126 )
7104
7127
7105 t = []
7128 t = []
7106 draft = len(repo.revs(b'draft()'))
7129 draft = len(repo.revs(b'draft()'))
7107 if draft:
7130 if draft:
7108 t.append(_(b'%d draft') % draft)
7131 t.append(_(b'%d draft') % draft)
7109 secret = len(repo.revs(b'secret()'))
7132 secret = len(repo.revs(b'secret()'))
7110 if secret:
7133 if secret:
7111 t.append(_(b'%d secret') % secret)
7134 t.append(_(b'%d secret') % secret)
7112
7135
7113 if draft or secret:
7136 if draft or secret:
7114 ui.status(_(b'phases: %s\n') % b', '.join(t))
7137 ui.status(_(b'phases: %s\n') % b', '.join(t))
7115
7138
7116 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7139 if obsolete.isenabled(repo, obsolete.createmarkersopt):
7117 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7140 for trouble in (b"orphan", b"contentdivergent", b"phasedivergent"):
7118 numtrouble = len(repo.revs(trouble + b"()"))
7141 numtrouble = len(repo.revs(trouble + b"()"))
7119 # We write all the possibilities to ease translation
7142 # We write all the possibilities to ease translation
7120 troublemsg = {
7143 troublemsg = {
7121 b"orphan": _(b"orphan: %d changesets"),
7144 b"orphan": _(b"orphan: %d changesets"),
7122 b"contentdivergent": _(b"content-divergent: %d changesets"),
7145 b"contentdivergent": _(b"content-divergent: %d changesets"),
7123 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7146 b"phasedivergent": _(b"phase-divergent: %d changesets"),
7124 }
7147 }
7125 if numtrouble > 0:
7148 if numtrouble > 0:
7126 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7149 ui.status(troublemsg[trouble] % numtrouble + b"\n")
7127
7150
7128 cmdutil.summaryhooks(ui, repo)
7151 cmdutil.summaryhooks(ui, repo)
7129
7152
7130 if opts.get(b'remote'):
7153 if opts.get(b'remote'):
7131 needsincoming, needsoutgoing = True, True
7154 needsincoming, needsoutgoing = True, True
7132 else:
7155 else:
7133 needsincoming, needsoutgoing = False, False
7156 needsincoming, needsoutgoing = False, False
7134 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7157 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
7135 if i:
7158 if i:
7136 needsincoming = True
7159 needsincoming = True
7137 if o:
7160 if o:
7138 needsoutgoing = True
7161 needsoutgoing = True
7139 if not needsincoming and not needsoutgoing:
7162 if not needsincoming and not needsoutgoing:
7140 return
7163 return
7141
7164
7142 def getincoming():
7165 def getincoming():
7143 source, branches = hg.parseurl(ui.expandpath(b'default'))
7166 source, branches = hg.parseurl(ui.expandpath(b'default'))
7144 sbranch = branches[0]
7167 sbranch = branches[0]
7145 try:
7168 try:
7146 other = hg.peer(repo, {}, source)
7169 other = hg.peer(repo, {}, source)
7147 except error.RepoError:
7170 except error.RepoError:
7148 if opts.get(b'remote'):
7171 if opts.get(b'remote'):
7149 raise
7172 raise
7150 return source, sbranch, None, None, None
7173 return source, sbranch, None, None, None
7151 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7174 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
7152 if revs:
7175 if revs:
7153 revs = [other.lookup(rev) for rev in revs]
7176 revs = [other.lookup(rev) for rev in revs]
7154 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
7177 ui.debug(b'comparing with %s\n' % util.hidepassword(source))
7155 repo.ui.pushbuffer()
7178 repo.ui.pushbuffer()
7156 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7179 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
7157 repo.ui.popbuffer()
7180 repo.ui.popbuffer()
7158 return source, sbranch, other, commoninc, commoninc[1]
7181 return source, sbranch, other, commoninc, commoninc[1]
7159
7182
7160 if needsincoming:
7183 if needsincoming:
7161 source, sbranch, sother, commoninc, incoming = getincoming()
7184 source, sbranch, sother, commoninc, incoming = getincoming()
7162 else:
7185 else:
7163 source = sbranch = sother = commoninc = incoming = None
7186 source = sbranch = sother = commoninc = incoming = None
7164
7187
7165 def getoutgoing():
7188 def getoutgoing():
7166 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
7189 dest, branches = hg.parseurl(ui.expandpath(b'default-push', b'default'))
7167 dbranch = branches[0]
7190 dbranch = branches[0]
7168 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
7191 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
7169 if source != dest:
7192 if source != dest:
7170 try:
7193 try:
7171 dother = hg.peer(repo, {}, dest)
7194 dother = hg.peer(repo, {}, dest)
7172 except error.RepoError:
7195 except error.RepoError:
7173 if opts.get(b'remote'):
7196 if opts.get(b'remote'):
7174 raise
7197 raise
7175 return dest, dbranch, None, None
7198 return dest, dbranch, None, None
7176 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7199 ui.debug(b'comparing with %s\n' % util.hidepassword(dest))
7177 elif sother is None:
7200 elif sother is None:
7178 # there is no explicit destination peer, but source one is invalid
7201 # there is no explicit destination peer, but source one is invalid
7179 return dest, dbranch, None, None
7202 return dest, dbranch, None, None
7180 else:
7203 else:
7181 dother = sother
7204 dother = sother
7182 if source != dest or (sbranch is not None and sbranch != dbranch):
7205 if source != dest or (sbranch is not None and sbranch != dbranch):
7183 common = None
7206 common = None
7184 else:
7207 else:
7185 common = commoninc
7208 common = commoninc
7186 if revs:
7209 if revs:
7187 revs = [repo.lookup(rev) for rev in revs]
7210 revs = [repo.lookup(rev) for rev in revs]
7188 repo.ui.pushbuffer()
7211 repo.ui.pushbuffer()
7189 outgoing = discovery.findcommonoutgoing(
7212 outgoing = discovery.findcommonoutgoing(
7190 repo, dother, onlyheads=revs, commoninc=common
7213 repo, dother, onlyheads=revs, commoninc=common
7191 )
7214 )
7192 repo.ui.popbuffer()
7215 repo.ui.popbuffer()
7193 return dest, dbranch, dother, outgoing
7216 return dest, dbranch, dother, outgoing
7194
7217
7195 if needsoutgoing:
7218 if needsoutgoing:
7196 dest, dbranch, dother, outgoing = getoutgoing()
7219 dest, dbranch, dother, outgoing = getoutgoing()
7197 else:
7220 else:
7198 dest = dbranch = dother = outgoing = None
7221 dest = dbranch = dother = outgoing = None
7199
7222
7200 if opts.get(b'remote'):
7223 if opts.get(b'remote'):
7201 t = []
7224 t = []
7202 if incoming:
7225 if incoming:
7203 t.append(_(b'1 or more incoming'))
7226 t.append(_(b'1 or more incoming'))
7204 o = outgoing.missing
7227 o = outgoing.missing
7205 if o:
7228 if o:
7206 t.append(_(b'%d outgoing') % len(o))
7229 t.append(_(b'%d outgoing') % len(o))
7207 other = dother or sother
7230 other = dother or sother
7208 if b'bookmarks' in other.listkeys(b'namespaces'):
7231 if b'bookmarks' in other.listkeys(b'namespaces'):
7209 counts = bookmarks.summary(repo, other)
7232 counts = bookmarks.summary(repo, other)
7210 if counts[0] > 0:
7233 if counts[0] > 0:
7211 t.append(_(b'%d incoming bookmarks') % counts[0])
7234 t.append(_(b'%d incoming bookmarks') % counts[0])
7212 if counts[1] > 0:
7235 if counts[1] > 0:
7213 t.append(_(b'%d outgoing bookmarks') % counts[1])
7236 t.append(_(b'%d outgoing bookmarks') % counts[1])
7214
7237
7215 if t:
7238 if t:
7216 # i18n: column positioning for "hg summary"
7239 # i18n: column positioning for "hg summary"
7217 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7240 ui.write(_(b'remote: %s\n') % (b', '.join(t)))
7218 else:
7241 else:
7219 # i18n: column positioning for "hg summary"
7242 # i18n: column positioning for "hg summary"
7220 ui.status(_(b'remote: (synced)\n'))
7243 ui.status(_(b'remote: (synced)\n'))
7221
7244
7222 cmdutil.summaryremotehooks(
7245 cmdutil.summaryremotehooks(
7223 ui,
7246 ui,
7224 repo,
7247 repo,
7225 opts,
7248 opts,
7226 (
7249 (
7227 (source, sbranch, sother, commoninc),
7250 (source, sbranch, sother, commoninc),
7228 (dest, dbranch, dother, outgoing),
7251 (dest, dbranch, dother, outgoing),
7229 ),
7252 ),
7230 )
7253 )
7231
7254
7232
7255
7233 @command(
7256 @command(
7234 b'tag',
7257 b'tag',
7235 [
7258 [
7236 (b'f', b'force', None, _(b'force tag')),
7259 (b'f', b'force', None, _(b'force tag')),
7237 (b'l', b'local', None, _(b'make the tag local')),
7260 (b'l', b'local', None, _(b'make the tag local')),
7238 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7261 (b'r', b'rev', b'', _(b'revision to tag'), _(b'REV')),
7239 (b'', b'remove', None, _(b'remove a tag')),
7262 (b'', b'remove', None, _(b'remove a tag')),
7240 # -l/--local is already there, commitopts cannot be used
7263 # -l/--local is already there, commitopts cannot be used
7241 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7264 (b'e', b'edit', None, _(b'invoke editor on commit messages')),
7242 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7265 (b'm', b'message', b'', _(b'use text as commit message'), _(b'TEXT')),
7243 ]
7266 ]
7244 + commitopts2,
7267 + commitopts2,
7245 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7268 _(b'[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
7246 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7269 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7247 )
7270 )
7248 def tag(ui, repo, name1, *names, **opts):
7271 def tag(ui, repo, name1, *names, **opts):
7249 """add one or more tags for the current or given revision
7272 """add one or more tags for the current or given revision
7250
7273
7251 Name a particular revision using <name>.
7274 Name a particular revision using <name>.
7252
7275
7253 Tags are used to name particular revisions of the repository and are
7276 Tags are used to name particular revisions of the repository and are
7254 very useful to compare different revisions, to go back to significant
7277 very useful to compare different revisions, to go back to significant
7255 earlier versions or to mark branch points as releases, etc. Changing
7278 earlier versions or to mark branch points as releases, etc. Changing
7256 an existing tag is normally disallowed; use -f/--force to override.
7279 an existing tag is normally disallowed; use -f/--force to override.
7257
7280
7258 If no revision is given, the parent of the working directory is
7281 If no revision is given, the parent of the working directory is
7259 used.
7282 used.
7260
7283
7261 To facilitate version control, distribution, and merging of tags,
7284 To facilitate version control, distribution, and merging of tags,
7262 they are stored as a file named ".hgtags" which is managed similarly
7285 they are stored as a file named ".hgtags" which is managed similarly
7263 to other project files and can be hand-edited if necessary. This
7286 to other project files and can be hand-edited if necessary. This
7264 also means that tagging creates a new commit. The file
7287 also means that tagging creates a new commit. The file
7265 ".hg/localtags" is used for local tags (not shared among
7288 ".hg/localtags" is used for local tags (not shared among
7266 repositories).
7289 repositories).
7267
7290
7268 Tag commits are usually made at the head of a branch. If the parent
7291 Tag commits are usually made at the head of a branch. If the parent
7269 of the working directory is not a branch head, :hg:`tag` aborts; use
7292 of the working directory is not a branch head, :hg:`tag` aborts; use
7270 -f/--force to force the tag commit to be based on a non-head
7293 -f/--force to force the tag commit to be based on a non-head
7271 changeset.
7294 changeset.
7272
7295
7273 See :hg:`help dates` for a list of formats valid for -d/--date.
7296 See :hg:`help dates` for a list of formats valid for -d/--date.
7274
7297
7275 Since tag names have priority over branch names during revision
7298 Since tag names have priority over branch names during revision
7276 lookup, using an existing branch name as a tag name is discouraged.
7299 lookup, using an existing branch name as a tag name is discouraged.
7277
7300
7278 Returns 0 on success.
7301 Returns 0 on success.
7279 """
7302 """
7280 opts = pycompat.byteskwargs(opts)
7303 opts = pycompat.byteskwargs(opts)
7281 with repo.wlock(), repo.lock():
7304 with repo.wlock(), repo.lock():
7282 rev_ = b"."
7305 rev_ = b"."
7283 names = [t.strip() for t in (name1,) + names]
7306 names = [t.strip() for t in (name1,) + names]
7284 if len(names) != len(set(names)):
7307 if len(names) != len(set(names)):
7285 raise error.Abort(_(b'tag names must be unique'))
7308 raise error.Abort(_(b'tag names must be unique'))
7286 for n in names:
7309 for n in names:
7287 scmutil.checknewlabel(repo, n, b'tag')
7310 scmutil.checknewlabel(repo, n, b'tag')
7288 if not n:
7311 if not n:
7289 raise error.Abort(
7312 raise error.Abort(
7290 _(b'tag names cannot consist entirely of whitespace')
7313 _(b'tag names cannot consist entirely of whitespace')
7291 )
7314 )
7292 if opts.get(b'rev') and opts.get(b'remove'):
7315 if opts.get(b'rev') and opts.get(b'remove'):
7293 raise error.Abort(_(b"--rev and --remove are incompatible"))
7316 raise error.Abort(_(b"--rev and --remove are incompatible"))
7294 if opts.get(b'rev'):
7317 if opts.get(b'rev'):
7295 rev_ = opts[b'rev']
7318 rev_ = opts[b'rev']
7296 message = opts.get(b'message')
7319 message = opts.get(b'message')
7297 if opts.get(b'remove'):
7320 if opts.get(b'remove'):
7298 if opts.get(b'local'):
7321 if opts.get(b'local'):
7299 expectedtype = b'local'
7322 expectedtype = b'local'
7300 else:
7323 else:
7301 expectedtype = b'global'
7324 expectedtype = b'global'
7302
7325
7303 for n in names:
7326 for n in names:
7304 if repo.tagtype(n) == b'global':
7327 if repo.tagtype(n) == b'global':
7305 alltags = tagsmod.findglobaltags(ui, repo)
7328 alltags = tagsmod.findglobaltags(ui, repo)
7306 if alltags[n][0] == nullid:
7329 if alltags[n][0] == nullid:
7307 raise error.Abort(_(b"tag '%s' is already removed") % n)
7330 raise error.Abort(_(b"tag '%s' is already removed") % n)
7308 if not repo.tagtype(n):
7331 if not repo.tagtype(n):
7309 raise error.Abort(_(b"tag '%s' does not exist") % n)
7332 raise error.Abort(_(b"tag '%s' does not exist") % n)
7310 if repo.tagtype(n) != expectedtype:
7333 if repo.tagtype(n) != expectedtype:
7311 if expectedtype == b'global':
7334 if expectedtype == b'global':
7312 raise error.Abort(
7335 raise error.Abort(
7313 _(b"tag '%s' is not a global tag") % n
7336 _(b"tag '%s' is not a global tag") % n
7314 )
7337 )
7315 else:
7338 else:
7316 raise error.Abort(_(b"tag '%s' is not a local tag") % n)
7339 raise error.Abort(_(b"tag '%s' is not a local tag") % n)
7317 rev_ = b'null'
7340 rev_ = b'null'
7318 if not message:
7341 if not message:
7319 # we don't translate commit messages
7342 # we don't translate commit messages
7320 message = b'Removed tag %s' % b', '.join(names)
7343 message = b'Removed tag %s' % b', '.join(names)
7321 elif not opts.get(b'force'):
7344 elif not opts.get(b'force'):
7322 for n in names:
7345 for n in names:
7323 if n in repo.tags():
7346 if n in repo.tags():
7324 raise error.Abort(
7347 raise error.Abort(
7325 _(b"tag '%s' already exists (use -f to force)") % n
7348 _(b"tag '%s' already exists (use -f to force)") % n
7326 )
7349 )
7327 if not opts.get(b'local'):
7350 if not opts.get(b'local'):
7328 p1, p2 = repo.dirstate.parents()
7351 p1, p2 = repo.dirstate.parents()
7329 if p2 != nullid:
7352 if p2 != nullid:
7330 raise error.Abort(_(b'uncommitted merge'))
7353 raise error.Abort(_(b'uncommitted merge'))
7331 bheads = repo.branchheads()
7354 bheads = repo.branchheads()
7332 if not opts.get(b'force') and bheads and p1 not in bheads:
7355 if not opts.get(b'force') and bheads and p1 not in bheads:
7333 raise error.Abort(
7356 raise error.Abort(
7334 _(
7357 _(
7335 b'working directory is not at a branch head '
7358 b'working directory is not at a branch head '
7336 b'(use -f to force)'
7359 b'(use -f to force)'
7337 )
7360 )
7338 )
7361 )
7339 node = scmutil.revsingle(repo, rev_).node()
7362 node = scmutil.revsingle(repo, rev_).node()
7340
7363
7341 if not message:
7364 if not message:
7342 # we don't translate commit messages
7365 # we don't translate commit messages
7343 message = b'Added tag %s for changeset %s' % (
7366 message = b'Added tag %s for changeset %s' % (
7344 b', '.join(names),
7367 b', '.join(names),
7345 short(node),
7368 short(node),
7346 )
7369 )
7347
7370
7348 date = opts.get(b'date')
7371 date = opts.get(b'date')
7349 if date:
7372 if date:
7350 date = dateutil.parsedate(date)
7373 date = dateutil.parsedate(date)
7351
7374
7352 if opts.get(b'remove'):
7375 if opts.get(b'remove'):
7353 editform = b'tag.remove'
7376 editform = b'tag.remove'
7354 else:
7377 else:
7355 editform = b'tag.add'
7378 editform = b'tag.add'
7356 editor = cmdutil.getcommiteditor(
7379 editor = cmdutil.getcommiteditor(
7357 editform=editform, **pycompat.strkwargs(opts)
7380 editform=editform, **pycompat.strkwargs(opts)
7358 )
7381 )
7359
7382
7360 # don't allow tagging the null rev
7383 # don't allow tagging the null rev
7361 if (
7384 if (
7362 not opts.get(b'remove')
7385 not opts.get(b'remove')
7363 and scmutil.revsingle(repo, rev_).rev() == nullrev
7386 and scmutil.revsingle(repo, rev_).rev() == nullrev
7364 ):
7387 ):
7365 raise error.Abort(_(b"cannot tag null revision"))
7388 raise error.Abort(_(b"cannot tag null revision"))
7366
7389
7367 tagsmod.tag(
7390 tagsmod.tag(
7368 repo,
7391 repo,
7369 names,
7392 names,
7370 node,
7393 node,
7371 message,
7394 message,
7372 opts.get(b'local'),
7395 opts.get(b'local'),
7373 opts.get(b'user'),
7396 opts.get(b'user'),
7374 date,
7397 date,
7375 editor=editor,
7398 editor=editor,
7376 )
7399 )
7377
7400
7378
7401
7379 @command(
7402 @command(
7380 b'tags',
7403 b'tags',
7381 formatteropts,
7404 formatteropts,
7382 b'',
7405 b'',
7383 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7406 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
7384 intents={INTENT_READONLY},
7407 intents={INTENT_READONLY},
7385 )
7408 )
7386 def tags(ui, repo, **opts):
7409 def tags(ui, repo, **opts):
7387 """list repository tags
7410 """list repository tags
7388
7411
7389 This lists both regular and local tags. When the -v/--verbose
7412 This lists both regular and local tags. When the -v/--verbose
7390 switch is used, a third column "local" is printed for local tags.
7413 switch is used, a third column "local" is printed for local tags.
7391 When the -q/--quiet switch is used, only the tag name is printed.
7414 When the -q/--quiet switch is used, only the tag name is printed.
7392
7415
7393 .. container:: verbose
7416 .. container:: verbose
7394
7417
7395 Template:
7418 Template:
7396
7419
7397 The following keywords are supported in addition to the common template
7420 The following keywords are supported in addition to the common template
7398 keywords and functions such as ``{tag}``. See also
7421 keywords and functions such as ``{tag}``. See also
7399 :hg:`help templates`.
7422 :hg:`help templates`.
7400
7423
7401 :type: String. ``local`` for local tags.
7424 :type: String. ``local`` for local tags.
7402
7425
7403 Returns 0 on success.
7426 Returns 0 on success.
7404 """
7427 """
7405
7428
7406 opts = pycompat.byteskwargs(opts)
7429 opts = pycompat.byteskwargs(opts)
7407 ui.pager(b'tags')
7430 ui.pager(b'tags')
7408 fm = ui.formatter(b'tags', opts)
7431 fm = ui.formatter(b'tags', opts)
7409 hexfunc = fm.hexfunc
7432 hexfunc = fm.hexfunc
7410
7433
7411 for t, n in reversed(repo.tagslist()):
7434 for t, n in reversed(repo.tagslist()):
7412 hn = hexfunc(n)
7435 hn = hexfunc(n)
7413 label = b'tags.normal'
7436 label = b'tags.normal'
7414 tagtype = b''
7437 tagtype = b''
7415 if repo.tagtype(t) == b'local':
7438 if repo.tagtype(t) == b'local':
7416 label = b'tags.local'
7439 label = b'tags.local'
7417 tagtype = b'local'
7440 tagtype = b'local'
7418
7441
7419 fm.startitem()
7442 fm.startitem()
7420 fm.context(repo=repo)
7443 fm.context(repo=repo)
7421 fm.write(b'tag', b'%s', t, label=label)
7444 fm.write(b'tag', b'%s', t, label=label)
7422 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7445 fmt = b" " * (30 - encoding.colwidth(t)) + b' %5d:%s'
7423 fm.condwrite(
7446 fm.condwrite(
7424 not ui.quiet,
7447 not ui.quiet,
7425 b'rev node',
7448 b'rev node',
7426 fmt,
7449 fmt,
7427 repo.changelog.rev(n),
7450 repo.changelog.rev(n),
7428 hn,
7451 hn,
7429 label=label,
7452 label=label,
7430 )
7453 )
7431 fm.condwrite(
7454 fm.condwrite(
7432 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7455 ui.verbose and tagtype, b'type', b' %s', tagtype, label=label
7433 )
7456 )
7434 fm.plain(b'\n')
7457 fm.plain(b'\n')
7435 fm.end()
7458 fm.end()
7436
7459
7437
7460
7438 @command(
7461 @command(
7439 b'tip',
7462 b'tip',
7440 [
7463 [
7441 (b'p', b'patch', None, _(b'show patch')),
7464 (b'p', b'patch', None, _(b'show patch')),
7442 (b'g', b'git', None, _(b'use git extended diff format')),
7465 (b'g', b'git', None, _(b'use git extended diff format')),
7443 ]
7466 ]
7444 + templateopts,
7467 + templateopts,
7445 _(b'[-p] [-g]'),
7468 _(b'[-p] [-g]'),
7446 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7469 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
7447 )
7470 )
7448 def tip(ui, repo, **opts):
7471 def tip(ui, repo, **opts):
7449 """show the tip revision (DEPRECATED)
7472 """show the tip revision (DEPRECATED)
7450
7473
7451 The tip revision (usually just called the tip) is the changeset
7474 The tip revision (usually just called the tip) is the changeset
7452 most recently added to the repository (and therefore the most
7475 most recently added to the repository (and therefore the most
7453 recently changed head).
7476 recently changed head).
7454
7477
7455 If you have just made a commit, that commit will be the tip. If
7478 If you have just made a commit, that commit will be the tip. If
7456 you have just pulled changes from another repository, the tip of
7479 you have just pulled changes from another repository, the tip of
7457 that repository becomes the current tip. The "tip" tag is special
7480 that repository becomes the current tip. The "tip" tag is special
7458 and cannot be renamed or assigned to a different changeset.
7481 and cannot be renamed or assigned to a different changeset.
7459
7482
7460 This command is deprecated, please use :hg:`heads` instead.
7483 This command is deprecated, please use :hg:`heads` instead.
7461
7484
7462 Returns 0 on success.
7485 Returns 0 on success.
7463 """
7486 """
7464 opts = pycompat.byteskwargs(opts)
7487 opts = pycompat.byteskwargs(opts)
7465 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7488 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
7466 displayer.show(repo[b'tip'])
7489 displayer.show(repo[b'tip'])
7467 displayer.close()
7490 displayer.close()
7468
7491
7469
7492
7470 @command(
7493 @command(
7471 b'unbundle',
7494 b'unbundle',
7472 [
7495 [
7473 (
7496 (
7474 b'u',
7497 b'u',
7475 b'update',
7498 b'update',
7476 None,
7499 None,
7477 _(b'update to new branch head if changesets were unbundled'),
7500 _(b'update to new branch head if changesets were unbundled'),
7478 )
7501 )
7479 ],
7502 ],
7480 _(b'[-u] FILE...'),
7503 _(b'[-u] FILE...'),
7481 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7504 helpcategory=command.CATEGORY_IMPORT_EXPORT,
7482 )
7505 )
7483 def unbundle(ui, repo, fname1, *fnames, **opts):
7506 def unbundle(ui, repo, fname1, *fnames, **opts):
7484 """apply one or more bundle files
7507 """apply one or more bundle files
7485
7508
7486 Apply one or more bundle files generated by :hg:`bundle`.
7509 Apply one or more bundle files generated by :hg:`bundle`.
7487
7510
7488 Returns 0 on success, 1 if an update has unresolved files.
7511 Returns 0 on success, 1 if an update has unresolved files.
7489 """
7512 """
7490 fnames = (fname1,) + fnames
7513 fnames = (fname1,) + fnames
7491
7514
7492 with repo.lock():
7515 with repo.lock():
7493 for fname in fnames:
7516 for fname in fnames:
7494 f = hg.openpath(ui, fname)
7517 f = hg.openpath(ui, fname)
7495 gen = exchange.readbundle(ui, f, fname)
7518 gen = exchange.readbundle(ui, f, fname)
7496 if isinstance(gen, streamclone.streamcloneapplier):
7519 if isinstance(gen, streamclone.streamcloneapplier):
7497 raise error.Abort(
7520 raise error.Abort(
7498 _(
7521 _(
7499 b'packed bundles cannot be applied with '
7522 b'packed bundles cannot be applied with '
7500 b'"hg unbundle"'
7523 b'"hg unbundle"'
7501 ),
7524 ),
7502 hint=_(b'use "hg debugapplystreamclonebundle"'),
7525 hint=_(b'use "hg debugapplystreamclonebundle"'),
7503 )
7526 )
7504 url = b'bundle:' + fname
7527 url = b'bundle:' + fname
7505 try:
7528 try:
7506 txnname = b'unbundle'
7529 txnname = b'unbundle'
7507 if not isinstance(gen, bundle2.unbundle20):
7530 if not isinstance(gen, bundle2.unbundle20):
7508 txnname = b'unbundle\n%s' % util.hidepassword(url)
7531 txnname = b'unbundle\n%s' % util.hidepassword(url)
7509 with repo.transaction(txnname) as tr:
7532 with repo.transaction(txnname) as tr:
7510 op = bundle2.applybundle(
7533 op = bundle2.applybundle(
7511 repo, gen, tr, source=b'unbundle', url=url
7534 repo, gen, tr, source=b'unbundle', url=url
7512 )
7535 )
7513 except error.BundleUnknownFeatureError as exc:
7536 except error.BundleUnknownFeatureError as exc:
7514 raise error.Abort(
7537 raise error.Abort(
7515 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7538 _(b'%s: unknown bundle feature, %s') % (fname, exc),
7516 hint=_(
7539 hint=_(
7517 b"see https://mercurial-scm.org/"
7540 b"see https://mercurial-scm.org/"
7518 b"wiki/BundleFeature for more "
7541 b"wiki/BundleFeature for more "
7519 b"information"
7542 b"information"
7520 ),
7543 ),
7521 )
7544 )
7522 modheads = bundle2.combinechangegroupresults(op)
7545 modheads = bundle2.combinechangegroupresults(op)
7523
7546
7524 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7547 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
7525
7548
7526
7549
7527 @command(
7550 @command(
7528 b'unshelve',
7551 b'unshelve',
7529 [
7552 [
7530 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7553 (b'a', b'abort', None, _(b'abort an incomplete unshelve operation')),
7531 (
7554 (
7532 b'c',
7555 b'c',
7533 b'continue',
7556 b'continue',
7534 None,
7557 None,
7535 _(b'continue an incomplete unshelve operation'),
7558 _(b'continue an incomplete unshelve operation'),
7536 ),
7559 ),
7537 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7560 (b'i', b'interactive', None, _(b'use interactive mode (EXPERIMENTAL)')),
7538 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7561 (b'k', b'keep', None, _(b'keep shelve after unshelving')),
7539 (
7562 (
7540 b'n',
7563 b'n',
7541 b'name',
7564 b'name',
7542 b'',
7565 b'',
7543 _(b'restore shelved change with given name'),
7566 _(b'restore shelved change with given name'),
7544 _(b'NAME'),
7567 _(b'NAME'),
7545 ),
7568 ),
7546 (b't', b'tool', b'', _(b'specify merge tool')),
7569 (b't', b'tool', b'', _(b'specify merge tool')),
7547 (
7570 (
7548 b'',
7571 b'',
7549 b'date',
7572 b'date',
7550 b'',
7573 b'',
7551 _(b'set date for temporary commits (DEPRECATED)'),
7574 _(b'set date for temporary commits (DEPRECATED)'),
7552 _(b'DATE'),
7575 _(b'DATE'),
7553 ),
7576 ),
7554 ],
7577 ],
7555 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7578 _(b'hg unshelve [OPTION]... [[-n] SHELVED]'),
7556 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7579 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7557 )
7580 )
7558 def unshelve(ui, repo, *shelved, **opts):
7581 def unshelve(ui, repo, *shelved, **opts):
7559 """restore a shelved change to the working directory
7582 """restore a shelved change to the working directory
7560
7583
7561 This command accepts an optional name of a shelved change to
7584 This command accepts an optional name of a shelved change to
7562 restore. If none is given, the most recent shelved change is used.
7585 restore. If none is given, the most recent shelved change is used.
7563
7586
7564 If a shelved change is applied successfully, the bundle that
7587 If a shelved change is applied successfully, the bundle that
7565 contains the shelved changes is moved to a backup location
7588 contains the shelved changes is moved to a backup location
7566 (.hg/shelve-backup).
7589 (.hg/shelve-backup).
7567
7590
7568 Since you can restore a shelved change on top of an arbitrary
7591 Since you can restore a shelved change on top of an arbitrary
7569 commit, it is possible that unshelving will result in a conflict
7592 commit, it is possible that unshelving will result in a conflict
7570 between your changes and the commits you are unshelving onto. If
7593 between your changes and the commits you are unshelving onto. If
7571 this occurs, you must resolve the conflict, then use
7594 this occurs, you must resolve the conflict, then use
7572 ``--continue`` to complete the unshelve operation. (The bundle
7595 ``--continue`` to complete the unshelve operation. (The bundle
7573 will not be moved until you successfully complete the unshelve.)
7596 will not be moved until you successfully complete the unshelve.)
7574
7597
7575 (Alternatively, you can use ``--abort`` to abandon an unshelve
7598 (Alternatively, you can use ``--abort`` to abandon an unshelve
7576 that causes a conflict. This reverts the unshelved changes, and
7599 that causes a conflict. This reverts the unshelved changes, and
7577 leaves the bundle in place.)
7600 leaves the bundle in place.)
7578
7601
7579 If bare shelved change (without interactive, include and exclude
7602 If bare shelved change (without interactive, include and exclude
7580 option) was done on newly created branch it would restore branch
7603 option) was done on newly created branch it would restore branch
7581 information to the working directory.
7604 information to the working directory.
7582
7605
7583 After a successful unshelve, the shelved changes are stored in a
7606 After a successful unshelve, the shelved changes are stored in a
7584 backup directory. Only the N most recent backups are kept. N
7607 backup directory. Only the N most recent backups are kept. N
7585 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7608 defaults to 10 but can be overridden using the ``shelve.maxbackups``
7586 configuration option.
7609 configuration option.
7587
7610
7588 .. container:: verbose
7611 .. container:: verbose
7589
7612
7590 Timestamp in seconds is used to decide order of backups. More
7613 Timestamp in seconds is used to decide order of backups. More
7591 than ``maxbackups`` backups are kept, if same timestamp
7614 than ``maxbackups`` backups are kept, if same timestamp
7592 prevents from deciding exact order of them, for safety.
7615 prevents from deciding exact order of them, for safety.
7593
7616
7594 Selected changes can be unshelved with ``--interactive`` flag.
7617 Selected changes can be unshelved with ``--interactive`` flag.
7595 The working directory is updated with the selected changes, and
7618 The working directory is updated with the selected changes, and
7596 only the unselected changes remain shelved.
7619 only the unselected changes remain shelved.
7597 Note: The whole shelve is applied to working directory first before
7620 Note: The whole shelve is applied to working directory first before
7598 running interactively. So, this will bring up all the conflicts between
7621 running interactively. So, this will bring up all the conflicts between
7599 working directory and the shelve, irrespective of which changes will be
7622 working directory and the shelve, irrespective of which changes will be
7600 unshelved.
7623 unshelved.
7601 """
7624 """
7602 with repo.wlock():
7625 with repo.wlock():
7603 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7626 return shelvemod.unshelvecmd(ui, repo, *shelved, **opts)
7604
7627
7605
7628
7606 statemod.addunfinished(
7629 statemod.addunfinished(
7607 b'unshelve',
7630 b'unshelve',
7608 fname=b'shelvedstate',
7631 fname=b'shelvedstate',
7609 continueflag=True,
7632 continueflag=True,
7610 abortfunc=shelvemod.hgabortunshelve,
7633 abortfunc=shelvemod.hgabortunshelve,
7611 continuefunc=shelvemod.hgcontinueunshelve,
7634 continuefunc=shelvemod.hgcontinueunshelve,
7612 cmdmsg=_(b'unshelve already in progress'),
7635 cmdmsg=_(b'unshelve already in progress'),
7613 )
7636 )
7614
7637
7615
7638
7616 @command(
7639 @command(
7617 b'update|up|checkout|co',
7640 b'update|up|checkout|co',
7618 [
7641 [
7619 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7642 (b'C', b'clean', None, _(b'discard uncommitted changes (no backup)')),
7620 (b'c', b'check', None, _(b'require clean working directory')),
7643 (b'c', b'check', None, _(b'require clean working directory')),
7621 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7644 (b'm', b'merge', None, _(b'merge uncommitted changes')),
7622 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7645 (b'd', b'date', b'', _(b'tipmost revision matching date'), _(b'DATE')),
7623 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7646 (b'r', b'rev', b'', _(b'revision'), _(b'REV')),
7624 ]
7647 ]
7625 + mergetoolopts,
7648 + mergetoolopts,
7626 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7649 _(b'[-C|-c|-m] [-d DATE] [[-r] REV]'),
7627 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7650 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
7628 helpbasic=True,
7651 helpbasic=True,
7629 )
7652 )
7630 def update(ui, repo, node=None, **opts):
7653 def update(ui, repo, node=None, **opts):
7631 """update working directory (or switch revisions)
7654 """update working directory (or switch revisions)
7632
7655
7633 Update the repository's working directory to the specified
7656 Update the repository's working directory to the specified
7634 changeset. If no changeset is specified, update to the tip of the
7657 changeset. If no changeset is specified, update to the tip of the
7635 current named branch and move the active bookmark (see :hg:`help
7658 current named branch and move the active bookmark (see :hg:`help
7636 bookmarks`).
7659 bookmarks`).
7637
7660
7638 Update sets the working directory's parent revision to the specified
7661 Update sets the working directory's parent revision to the specified
7639 changeset (see :hg:`help parents`).
7662 changeset (see :hg:`help parents`).
7640
7663
7641 If the changeset is not a descendant or ancestor of the working
7664 If the changeset is not a descendant or ancestor of the working
7642 directory's parent and there are uncommitted changes, the update is
7665 directory's parent and there are uncommitted changes, the update is
7643 aborted. With the -c/--check option, the working directory is checked
7666 aborted. With the -c/--check option, the working directory is checked
7644 for uncommitted changes; if none are found, the working directory is
7667 for uncommitted changes; if none are found, the working directory is
7645 updated to the specified changeset.
7668 updated to the specified changeset.
7646
7669
7647 .. container:: verbose
7670 .. container:: verbose
7648
7671
7649 The -C/--clean, -c/--check, and -m/--merge options control what
7672 The -C/--clean, -c/--check, and -m/--merge options control what
7650 happens if the working directory contains uncommitted changes.
7673 happens if the working directory contains uncommitted changes.
7651 At most of one of them can be specified.
7674 At most of one of them can be specified.
7652
7675
7653 1. If no option is specified, and if
7676 1. If no option is specified, and if
7654 the requested changeset is an ancestor or descendant of
7677 the requested changeset is an ancestor or descendant of
7655 the working directory's parent, the uncommitted changes
7678 the working directory's parent, the uncommitted changes
7656 are merged into the requested changeset and the merged
7679 are merged into the requested changeset and the merged
7657 result is left uncommitted. If the requested changeset is
7680 result is left uncommitted. If the requested changeset is
7658 not an ancestor or descendant (that is, it is on another
7681 not an ancestor or descendant (that is, it is on another
7659 branch), the update is aborted and the uncommitted changes
7682 branch), the update is aborted and the uncommitted changes
7660 are preserved.
7683 are preserved.
7661
7684
7662 2. With the -m/--merge option, the update is allowed even if the
7685 2. With the -m/--merge option, the update is allowed even if the
7663 requested changeset is not an ancestor or descendant of
7686 requested changeset is not an ancestor or descendant of
7664 the working directory's parent.
7687 the working directory's parent.
7665
7688
7666 3. With the -c/--check option, the update is aborted and the
7689 3. With the -c/--check option, the update is aborted and the
7667 uncommitted changes are preserved.
7690 uncommitted changes are preserved.
7668
7691
7669 4. With the -C/--clean option, uncommitted changes are discarded and
7692 4. With the -C/--clean option, uncommitted changes are discarded and
7670 the working directory is updated to the requested changeset.
7693 the working directory is updated to the requested changeset.
7671
7694
7672 To cancel an uncommitted merge (and lose your changes), use
7695 To cancel an uncommitted merge (and lose your changes), use
7673 :hg:`merge --abort`.
7696 :hg:`merge --abort`.
7674
7697
7675 Use null as the changeset to remove the working directory (like
7698 Use null as the changeset to remove the working directory (like
7676 :hg:`clone -U`).
7699 :hg:`clone -U`).
7677
7700
7678 If you want to revert just one file to an older revision, use
7701 If you want to revert just one file to an older revision, use
7679 :hg:`revert [-r REV] NAME`.
7702 :hg:`revert [-r REV] NAME`.
7680
7703
7681 See :hg:`help dates` for a list of formats valid for -d/--date.
7704 See :hg:`help dates` for a list of formats valid for -d/--date.
7682
7705
7683 Returns 0 on success, 1 if there are unresolved files.
7706 Returns 0 on success, 1 if there are unresolved files.
7684 """
7707 """
7685 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7708 cmdutil.check_at_most_one_arg(opts, 'clean', 'check', 'merge')
7686 rev = opts.get('rev')
7709 rev = opts.get('rev')
7687 date = opts.get('date')
7710 date = opts.get('date')
7688 clean = opts.get('clean')
7711 clean = opts.get('clean')
7689 check = opts.get('check')
7712 check = opts.get('check')
7690 merge = opts.get('merge')
7713 merge = opts.get('merge')
7691 if rev and node:
7714 if rev and node:
7692 raise error.Abort(_(b"please specify just one revision"))
7715 raise error.Abort(_(b"please specify just one revision"))
7693
7716
7694 if ui.configbool(b'commands', b'update.requiredest'):
7717 if ui.configbool(b'commands', b'update.requiredest'):
7695 if not node and not rev and not date:
7718 if not node and not rev and not date:
7696 raise error.Abort(
7719 raise error.Abort(
7697 _(b'you must specify a destination'),
7720 _(b'you must specify a destination'),
7698 hint=_(b'for example: hg update ".::"'),
7721 hint=_(b'for example: hg update ".::"'),
7699 )
7722 )
7700
7723
7701 if rev is None or rev == b'':
7724 if rev is None or rev == b'':
7702 rev = node
7725 rev = node
7703
7726
7704 if date and rev is not None:
7727 if date and rev is not None:
7705 raise error.Abort(_(b"you can't specify a revision and a date"))
7728 raise error.Abort(_(b"you can't specify a revision and a date"))
7706
7729
7707 updatecheck = None
7730 updatecheck = None
7708 if check:
7731 if check:
7709 updatecheck = b'abort'
7732 updatecheck = b'abort'
7710 elif merge:
7733 elif merge:
7711 updatecheck = b'none'
7734 updatecheck = b'none'
7712
7735
7713 with repo.wlock():
7736 with repo.wlock():
7714 cmdutil.clearunfinished(repo)
7737 cmdutil.clearunfinished(repo)
7715 if date:
7738 if date:
7716 rev = cmdutil.finddate(ui, repo, date)
7739 rev = cmdutil.finddate(ui, repo, date)
7717
7740
7718 # if we defined a bookmark, we have to remember the original name
7741 # if we defined a bookmark, we have to remember the original name
7719 brev = rev
7742 brev = rev
7720 if rev:
7743 if rev:
7721 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7744 repo = scmutil.unhidehashlikerevs(repo, [rev], b'nowarn')
7722 ctx = scmutil.revsingle(repo, rev, default=None)
7745 ctx = scmutil.revsingle(repo, rev, default=None)
7723 rev = ctx.rev()
7746 rev = ctx.rev()
7724 hidden = ctx.hidden()
7747 hidden = ctx.hidden()
7725 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7748 overrides = {(b'ui', b'forcemerge'): opts.get('tool', b'')}
7726 with ui.configoverride(overrides, b'update'):
7749 with ui.configoverride(overrides, b'update'):
7727 ret = hg.updatetotally(
7750 ret = hg.updatetotally(
7728 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7751 ui, repo, rev, brev, clean=clean, updatecheck=updatecheck
7729 )
7752 )
7730 if hidden:
7753 if hidden:
7731 ctxstr = ctx.hex()[:12]
7754 ctxstr = ctx.hex()[:12]
7732 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7755 ui.warn(_(b"updated to hidden changeset %s\n") % ctxstr)
7733
7756
7734 if ctx.obsolete():
7757 if ctx.obsolete():
7735 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7758 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
7736 ui.warn(b"(%s)\n" % obsfatemsg)
7759 ui.warn(b"(%s)\n" % obsfatemsg)
7737 return ret
7760 return ret
7738
7761
7739
7762
7740 @command(
7763 @command(
7741 b'verify',
7764 b'verify',
7742 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7765 [(b'', b'full', False, b'perform more checks (EXPERIMENTAL)')],
7743 helpcategory=command.CATEGORY_MAINTENANCE,
7766 helpcategory=command.CATEGORY_MAINTENANCE,
7744 )
7767 )
7745 def verify(ui, repo, **opts):
7768 def verify(ui, repo, **opts):
7746 """verify the integrity of the repository
7769 """verify the integrity of the repository
7747
7770
7748 Verify the integrity of the current repository.
7771 Verify the integrity of the current repository.
7749
7772
7750 This will perform an extensive check of the repository's
7773 This will perform an extensive check of the repository's
7751 integrity, validating the hashes and checksums of each entry in
7774 integrity, validating the hashes and checksums of each entry in
7752 the changelog, manifest, and tracked files, as well as the
7775 the changelog, manifest, and tracked files, as well as the
7753 integrity of their crosslinks and indices.
7776 integrity of their crosslinks and indices.
7754
7777
7755 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7778 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7756 for more information about recovery from corruption of the
7779 for more information about recovery from corruption of the
7757 repository.
7780 repository.
7758
7781
7759 Returns 0 on success, 1 if errors are encountered.
7782 Returns 0 on success, 1 if errors are encountered.
7760 """
7783 """
7761 opts = pycompat.byteskwargs(opts)
7784 opts = pycompat.byteskwargs(opts)
7762
7785
7763 level = None
7786 level = None
7764 if opts[b'full']:
7787 if opts[b'full']:
7765 level = verifymod.VERIFY_FULL
7788 level = verifymod.VERIFY_FULL
7766 return hg.verify(repo, level)
7789 return hg.verify(repo, level)
7767
7790
7768
7791
7769 @command(
7792 @command(
7770 b'version',
7793 b'version',
7771 [] + formatteropts,
7794 [] + formatteropts,
7772 helpcategory=command.CATEGORY_HELP,
7795 helpcategory=command.CATEGORY_HELP,
7773 norepo=True,
7796 norepo=True,
7774 intents={INTENT_READONLY},
7797 intents={INTENT_READONLY},
7775 )
7798 )
7776 def version_(ui, **opts):
7799 def version_(ui, **opts):
7777 """output version and copyright information
7800 """output version and copyright information
7778
7801
7779 .. container:: verbose
7802 .. container:: verbose
7780
7803
7781 Template:
7804 Template:
7782
7805
7783 The following keywords are supported. See also :hg:`help templates`.
7806 The following keywords are supported. See also :hg:`help templates`.
7784
7807
7785 :extensions: List of extensions.
7808 :extensions: List of extensions.
7786 :ver: String. Version number.
7809 :ver: String. Version number.
7787
7810
7788 And each entry of ``{extensions}`` provides the following sub-keywords
7811 And each entry of ``{extensions}`` provides the following sub-keywords
7789 in addition to ``{ver}``.
7812 in addition to ``{ver}``.
7790
7813
7791 :bundled: Boolean. True if included in the release.
7814 :bundled: Boolean. True if included in the release.
7792 :name: String. Extension name.
7815 :name: String. Extension name.
7793 """
7816 """
7794 opts = pycompat.byteskwargs(opts)
7817 opts = pycompat.byteskwargs(opts)
7795 if ui.verbose:
7818 if ui.verbose:
7796 ui.pager(b'version')
7819 ui.pager(b'version')
7797 fm = ui.formatter(b"version", opts)
7820 fm = ui.formatter(b"version", opts)
7798 fm.startitem()
7821 fm.startitem()
7799 fm.write(
7822 fm.write(
7800 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7823 b"ver", _(b"Mercurial Distributed SCM (version %s)\n"), util.version()
7801 )
7824 )
7802 license = _(
7825 license = _(
7803 b"(see https://mercurial-scm.org for more information)\n"
7826 b"(see https://mercurial-scm.org for more information)\n"
7804 b"\nCopyright (C) 2005-2020 Matt Mackall and others\n"
7827 b"\nCopyright (C) 2005-2020 Matt Mackall and others\n"
7805 b"This is free software; see the source for copying conditions. "
7828 b"This is free software; see the source for copying conditions. "
7806 b"There is NO\nwarranty; "
7829 b"There is NO\nwarranty; "
7807 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7830 b"not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7808 )
7831 )
7809 if not ui.quiet:
7832 if not ui.quiet:
7810 fm.plain(license)
7833 fm.plain(license)
7811
7834
7812 if ui.verbose:
7835 if ui.verbose:
7813 fm.plain(_(b"\nEnabled extensions:\n\n"))
7836 fm.plain(_(b"\nEnabled extensions:\n\n"))
7814 # format names and versions into columns
7837 # format names and versions into columns
7815 names = []
7838 names = []
7816 vers = []
7839 vers = []
7817 isinternals = []
7840 isinternals = []
7818 for name, module in sorted(extensions.extensions()):
7841 for name, module in sorted(extensions.extensions()):
7819 names.append(name)
7842 names.append(name)
7820 vers.append(extensions.moduleversion(module) or None)
7843 vers.append(extensions.moduleversion(module) or None)
7821 isinternals.append(extensions.ismoduleinternal(module))
7844 isinternals.append(extensions.ismoduleinternal(module))
7822 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7845 fn = fm.nested(b"extensions", tmpl=b'{name}\n')
7823 if names:
7846 if names:
7824 namefmt = b" %%-%ds " % max(len(n) for n in names)
7847 namefmt = b" %%-%ds " % max(len(n) for n in names)
7825 places = [_(b"external"), _(b"internal")]
7848 places = [_(b"external"), _(b"internal")]
7826 for n, v, p in zip(names, vers, isinternals):
7849 for n, v, p in zip(names, vers, isinternals):
7827 fn.startitem()
7850 fn.startitem()
7828 fn.condwrite(ui.verbose, b"name", namefmt, n)
7851 fn.condwrite(ui.verbose, b"name", namefmt, n)
7829 if ui.verbose:
7852 if ui.verbose:
7830 fn.plain(b"%s " % places[p])
7853 fn.plain(b"%s " % places[p])
7831 fn.data(bundled=p)
7854 fn.data(bundled=p)
7832 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7855 fn.condwrite(ui.verbose and v, b"ver", b"%s", v)
7833 if ui.verbose:
7856 if ui.verbose:
7834 fn.plain(b"\n")
7857 fn.plain(b"\n")
7835 fn.end()
7858 fn.end()
7836 fm.end()
7859 fm.end()
7837
7860
7838
7861
7839 def loadcmdtable(ui, name, cmdtable):
7862 def loadcmdtable(ui, name, cmdtable):
7840 """Load command functions from specified cmdtable
7863 """Load command functions from specified cmdtable
7841 """
7864 """
7842 overrides = [cmd for cmd in cmdtable if cmd in table]
7865 overrides = [cmd for cmd in cmdtable if cmd in table]
7843 if overrides:
7866 if overrides:
7844 ui.warn(
7867 ui.warn(
7845 _(b"extension '%s' overrides commands: %s\n")
7868 _(b"extension '%s' overrides commands: %s\n")
7846 % (name, b" ".join(overrides))
7869 % (name, b" ".join(overrides))
7847 )
7870 )
7848 table.update(cmdtable)
7871 table.update(cmdtable)
@@ -1,435 +1,435 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 abort
3 abort
4 add
4 add
5 addremove
5 addremove
6 annotate
6 annotate
7 archive
7 archive
8 backout
8 backout
9 bisect
9 bisect
10 bookmarks
10 bookmarks
11 branch
11 branch
12 branches
12 branches
13 bundle
13 bundle
14 cat
14 cat
15 clone
15 clone
16 commit
16 commit
17 config
17 config
18 continue
18 continue
19 copy
19 copy
20 diff
20 diff
21 export
21 export
22 files
22 files
23 forget
23 forget
24 graft
24 graft
25 grep
25 grep
26 heads
26 heads
27 help
27 help
28 identify
28 identify
29 import
29 import
30 incoming
30 incoming
31 init
31 init
32 locate
32 locate
33 log
33 log
34 manifest
34 manifest
35 merge
35 merge
36 outgoing
36 outgoing
37 parents
37 parents
38 paths
38 paths
39 phase
39 phase
40 pull
40 pull
41 push
41 push
42 recover
42 recover
43 remove
43 remove
44 rename
44 rename
45 resolve
45 resolve
46 revert
46 revert
47 rollback
47 rollback
48 root
48 root
49 serve
49 serve
50 shelve
50 shelve
51 status
51 status
52 summary
52 summary
53 tag
53 tag
54 tags
54 tags
55 tip
55 tip
56 unbundle
56 unbundle
57 unshelve
57 unshelve
58 update
58 update
59 verify
59 verify
60 version
60 version
61
61
62 Show all commands that start with "a"
62 Show all commands that start with "a"
63 $ hg debugcomplete a
63 $ hg debugcomplete a
64 abort
64 abort
65 add
65 add
66 addremove
66 addremove
67 annotate
67 annotate
68 archive
68 archive
69
69
70 Do not show debug commands if there are other candidates
70 Do not show debug commands if there are other candidates
71 $ hg debugcomplete d
71 $ hg debugcomplete d
72 diff
72 diff
73
73
74 Show debug commands if there are no other candidates
74 Show debug commands if there are no other candidates
75 $ hg debugcomplete debug
75 $ hg debugcomplete debug
76 debugancestor
76 debugancestor
77 debugantivirusrunning
77 debugantivirusrunning
78 debugapplystreamclonebundle
78 debugapplystreamclonebundle
79 debugbackupbundle
79 debugbackupbundle
80 debugbuilddag
80 debugbuilddag
81 debugbundle
81 debugbundle
82 debugcapabilities
82 debugcapabilities
83 debugcheckstate
83 debugcheckstate
84 debugcolor
84 debugcolor
85 debugcommands
85 debugcommands
86 debugcomplete
86 debugcomplete
87 debugconfig
87 debugconfig
88 debugcreatestreamclonebundle
88 debugcreatestreamclonebundle
89 debugdag
89 debugdag
90 debugdata
90 debugdata
91 debugdate
91 debugdate
92 debugdeltachain
92 debugdeltachain
93 debugdirstate
93 debugdirstate
94 debugdiscovery
94 debugdiscovery
95 debugdownload
95 debugdownload
96 debugextensions
96 debugextensions
97 debugfileset
97 debugfileset
98 debugformat
98 debugformat
99 debugfsinfo
99 debugfsinfo
100 debuggetbundle
100 debuggetbundle
101 debugignore
101 debugignore
102 debugindex
102 debugindex
103 debugindexdot
103 debugindexdot
104 debugindexstats
104 debugindexstats
105 debuginstall
105 debuginstall
106 debugknown
106 debugknown
107 debuglabelcomplete
107 debuglabelcomplete
108 debuglocks
108 debuglocks
109 debugmanifestfulltextcache
109 debugmanifestfulltextcache
110 debugmergestate
110 debugmergestate
111 debugnamecomplete
111 debugnamecomplete
112 debugnodemap
112 debugnodemap
113 debugobsolete
113 debugobsolete
114 debugp1copies
114 debugp1copies
115 debugp2copies
115 debugp2copies
116 debugpathcomplete
116 debugpathcomplete
117 debugpathcopies
117 debugpathcopies
118 debugpeer
118 debugpeer
119 debugpickmergetool
119 debugpickmergetool
120 debugpushkey
120 debugpushkey
121 debugpvec
121 debugpvec
122 debugrebuilddirstate
122 debugrebuilddirstate
123 debugrebuildfncache
123 debugrebuildfncache
124 debugrename
124 debugrename
125 debugrequires
125 debugrequires
126 debugrevlog
126 debugrevlog
127 debugrevlogindex
127 debugrevlogindex
128 debugrevspec
128 debugrevspec
129 debugserve
129 debugserve
130 debugsetparents
130 debugsetparents
131 debugsidedata
131 debugsidedata
132 debugssl
132 debugssl
133 debugsub
133 debugsub
134 debugsuccessorssets
134 debugsuccessorssets
135 debugtagscache
135 debugtagscache
136 debugtemplate
136 debugtemplate
137 debuguigetpass
137 debuguigetpass
138 debuguiprompt
138 debuguiprompt
139 debugupdatecaches
139 debugupdatecaches
140 debugupgraderepo
140 debugupgraderepo
141 debugwalk
141 debugwalk
142 debugwhyunstable
142 debugwhyunstable
143 debugwireargs
143 debugwireargs
144 debugwireproto
144 debugwireproto
145
145
146 Do not show the alias of a debug command if there are other candidates
146 Do not show the alias of a debug command if there are other candidates
147 (this should hide rawcommit)
147 (this should hide rawcommit)
148 $ hg debugcomplete r
148 $ hg debugcomplete r
149 recover
149 recover
150 remove
150 remove
151 rename
151 rename
152 resolve
152 resolve
153 revert
153 revert
154 rollback
154 rollback
155 root
155 root
156 Show the alias of a debug command if there are no other candidates
156 Show the alias of a debug command if there are no other candidates
157 $ hg debugcomplete rawc
157 $ hg debugcomplete rawc
158
158
159
159
160 Show the global options
160 Show the global options
161 $ hg debugcomplete --options | sort
161 $ hg debugcomplete --options | sort
162 --color
162 --color
163 --config
163 --config
164 --cwd
164 --cwd
165 --debug
165 --debug
166 --debugger
166 --debugger
167 --encoding
167 --encoding
168 --encodingmode
168 --encodingmode
169 --help
169 --help
170 --hidden
170 --hidden
171 --noninteractive
171 --noninteractive
172 --pager
172 --pager
173 --profile
173 --profile
174 --quiet
174 --quiet
175 --repository
175 --repository
176 --time
176 --time
177 --traceback
177 --traceback
178 --verbose
178 --verbose
179 --version
179 --version
180 -R
180 -R
181 -h
181 -h
182 -q
182 -q
183 -v
183 -v
184 -y
184 -y
185
185
186 Show the options for the "serve" command
186 Show the options for the "serve" command
187 $ hg debugcomplete --options serve | sort
187 $ hg debugcomplete --options serve | sort
188 --accesslog
188 --accesslog
189 --address
189 --address
190 --certificate
190 --certificate
191 --cmdserver
191 --cmdserver
192 --color
192 --color
193 --config
193 --config
194 --cwd
194 --cwd
195 --daemon
195 --daemon
196 --daemon-postexec
196 --daemon-postexec
197 --debug
197 --debug
198 --debugger
198 --debugger
199 --encoding
199 --encoding
200 --encodingmode
200 --encodingmode
201 --errorlog
201 --errorlog
202 --help
202 --help
203 --hidden
203 --hidden
204 --ipv6
204 --ipv6
205 --name
205 --name
206 --noninteractive
206 --noninteractive
207 --pager
207 --pager
208 --pid-file
208 --pid-file
209 --port
209 --port
210 --prefix
210 --prefix
211 --print-url
211 --print-url
212 --profile
212 --profile
213 --quiet
213 --quiet
214 --repository
214 --repository
215 --stdio
215 --stdio
216 --style
216 --style
217 --subrepos
217 --subrepos
218 --templates
218 --templates
219 --time
219 --time
220 --traceback
220 --traceback
221 --verbose
221 --verbose
222 --version
222 --version
223 --web-conf
223 --web-conf
224 -6
224 -6
225 -A
225 -A
226 -E
226 -E
227 -R
227 -R
228 -S
228 -S
229 -a
229 -a
230 -d
230 -d
231 -h
231 -h
232 -n
232 -n
233 -p
233 -p
234 -q
234 -q
235 -t
235 -t
236 -v
236 -v
237 -y
237 -y
238
238
239 Show an error if we use --options with an ambiguous abbreviation
239 Show an error if we use --options with an ambiguous abbreviation
240 $ hg debugcomplete --options s
240 $ hg debugcomplete --options s
241 hg: command 's' is ambiguous:
241 hg: command 's' is ambiguous:
242 serve shelve showconfig status summary
242 serve shelve showconfig status summary
243 [255]
243 [255]
244
244
245 Show all commands + options
245 Show all commands + options
246 $ hg debugcommands
246 $ hg debugcommands
247 abort: dry-run
247 abort: dry-run
248 add: include, exclude, subrepos, dry-run
248 add: include, exclude, subrepos, dry-run
249 addremove: similarity, subrepos, include, exclude, dry-run
249 addremove: similarity, subrepos, include, exclude, dry-run
250 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
250 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
251 archive: no-decode, prefix, rev, type, subrepos, include, exclude
251 archive: no-decode, prefix, rev, type, subrepos, include, exclude
252 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
252 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
253 bisect: reset, good, bad, skip, extend, command, noupdate
253 bisect: reset, good, bad, skip, extend, command, noupdate
254 bookmarks: force, rev, delete, rename, inactive, list, template
254 bookmarks: force, rev, delete, rename, inactive, list, template
255 branch: force, clean, rev
255 branch: force, clean, rev
256 branches: active, closed, rev, template
256 branches: active, closed, rev, template
257 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
257 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
258 cat: output, rev, decode, include, exclude, template
258 cat: output, rev, decode, include, exclude, template
259 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
259 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
260 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
260 commit: addremove, close-branch, amend, secret, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
261 config: untrusted, edit, local, global, template
261 config: untrusted, edit, local, shared, global, template
262 continue: dry-run
262 continue: dry-run
263 copy: forget, after, at-rev, force, include, exclude, dry-run
263 copy: forget, after, at-rev, force, include, exclude, dry-run
264 debugancestor:
264 debugancestor:
265 debugantivirusrunning:
265 debugantivirusrunning:
266 debugapplystreamclonebundle:
266 debugapplystreamclonebundle:
267 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
267 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
268 debugbuilddag: mergeable-file, overwritten-file, new-file
268 debugbuilddag: mergeable-file, overwritten-file, new-file
269 debugbundle: all, part-type, spec
269 debugbundle: all, part-type, spec
270 debugcapabilities:
270 debugcapabilities:
271 debugcheckstate:
271 debugcheckstate:
272 debugcolor: style
272 debugcolor: style
273 debugcommands:
273 debugcommands:
274 debugcomplete: options
274 debugcomplete: options
275 debugcreatestreamclonebundle:
275 debugcreatestreamclonebundle:
276 debugdag: tags, branches, dots, spaces
276 debugdag: tags, branches, dots, spaces
277 debugdata: changelog, manifest, dir
277 debugdata: changelog, manifest, dir
278 debugdate: extended
278 debugdate: extended
279 debugdeltachain: changelog, manifest, dir, template
279 debugdeltachain: changelog, manifest, dir, template
280 debugdirstate: nodates, dates, datesort
280 debugdirstate: nodates, dates, datesort
281 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
281 debugdiscovery: old, nonheads, rev, seed, ssh, remotecmd, insecure
282 debugdownload: output
282 debugdownload: output
283 debugextensions: template
283 debugextensions: template
284 debugfileset: rev, all-files, show-matcher, show-stage
284 debugfileset: rev, all-files, show-matcher, show-stage
285 debugformat: template
285 debugformat: template
286 debugfsinfo:
286 debugfsinfo:
287 debuggetbundle: head, common, type
287 debuggetbundle: head, common, type
288 debugignore:
288 debugignore:
289 debugindex: changelog, manifest, dir, template
289 debugindex: changelog, manifest, dir, template
290 debugindexdot: changelog, manifest, dir
290 debugindexdot: changelog, manifest, dir
291 debugindexstats:
291 debugindexstats:
292 debuginstall: template
292 debuginstall: template
293 debugknown:
293 debugknown:
294 debuglabelcomplete:
294 debuglabelcomplete:
295 debuglocks: force-lock, force-wlock, set-lock, set-wlock
295 debuglocks: force-lock, force-wlock, set-lock, set-wlock
296 debugmanifestfulltextcache: clear, add
296 debugmanifestfulltextcache: clear, add
297 debugmergestate: style, template
297 debugmergestate: style, template
298 debugnamecomplete:
298 debugnamecomplete:
299 debugnodemap: dump-new, dump-disk, check, metadata
299 debugnodemap: dump-new, dump-disk, check, metadata
300 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
300 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
301 debugp1copies: rev
301 debugp1copies: rev
302 debugp2copies: rev
302 debugp2copies: rev
303 debugpathcomplete: full, normal, added, removed
303 debugpathcomplete: full, normal, added, removed
304 debugpathcopies: include, exclude
304 debugpathcopies: include, exclude
305 debugpeer:
305 debugpeer:
306 debugpickmergetool: rev, changedelete, include, exclude, tool
306 debugpickmergetool: rev, changedelete, include, exclude, tool
307 debugpushkey:
307 debugpushkey:
308 debugpvec:
308 debugpvec:
309 debugrebuilddirstate: rev, minimal
309 debugrebuilddirstate: rev, minimal
310 debugrebuildfncache:
310 debugrebuildfncache:
311 debugrename: rev
311 debugrename: rev
312 debugrequires:
312 debugrequires:
313 debugrevlog: changelog, manifest, dir, dump
313 debugrevlog: changelog, manifest, dir, dump
314 debugrevlogindex: changelog, manifest, dir, format
314 debugrevlogindex: changelog, manifest, dir, format
315 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
315 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
316 debugserve: sshstdio, logiofd, logiofile
316 debugserve: sshstdio, logiofd, logiofile
317 debugsetparents:
317 debugsetparents:
318 debugsidedata: changelog, manifest, dir
318 debugsidedata: changelog, manifest, dir
319 debugssl:
319 debugssl:
320 debugsub: rev
320 debugsub: rev
321 debugsuccessorssets: closest
321 debugsuccessorssets: closest
322 debugtagscache:
322 debugtagscache:
323 debugtemplate: rev, define
323 debugtemplate: rev, define
324 debuguigetpass: prompt
324 debuguigetpass: prompt
325 debuguiprompt: prompt
325 debuguiprompt: prompt
326 debugupdatecaches:
326 debugupdatecaches:
327 debugupgraderepo: optimize, run, backup, changelog, manifest
327 debugupgraderepo: optimize, run, backup, changelog, manifest
328 debugwalk: include, exclude
328 debugwalk: include, exclude
329 debugwhyunstable:
329 debugwhyunstable:
330 debugwireargs: three, four, five, ssh, remotecmd, insecure
330 debugwireargs: three, four, five, ssh, remotecmd, insecure
331 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
331 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
332 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
332 diff: rev, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
333 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
333 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
334 files: rev, print0, include, exclude, template, subrepos
334 files: rev, print0, include, exclude, template, subrepos
335 forget: interactive, include, exclude, dry-run
335 forget: interactive, include, exclude, dry-run
336 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
336 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
337 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
337 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
338 heads: rev, topo, active, closed, style, template
338 heads: rev, topo, active, closed, style, template
339 help: extension, command, keyword, system
339 help: extension, command, keyword, system
340 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
340 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
341 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
341 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
342 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
342 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
343 init: ssh, remotecmd, insecure
343 init: ssh, remotecmd, insecure
344 locate: rev, print0, fullpath, include, exclude
344 locate: rev, print0, fullpath, include, exclude
345 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
345 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
346 manifest: rev, all, template
346 manifest: rev, all, template
347 merge: force, rev, preview, abort, tool
347 merge: force, rev, preview, abort, tool
348 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
348 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
349 parents: rev, style, template
349 parents: rev, style, template
350 paths: template
350 paths: template
351 phase: public, draft, secret, force, rev
351 phase: public, draft, secret, force, rev
352 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
352 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
353 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
353 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
354 recover: verify
354 recover: verify
355 remove: after, force, subrepos, include, exclude, dry-run
355 remove: after, force, subrepos, include, exclude, dry-run
356 rename: after, at-rev, force, include, exclude, dry-run
356 rename: after, at-rev, force, include, exclude, dry-run
357 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
357 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
358 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
358 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
359 rollback: dry-run, force
359 rollback: dry-run, force
360 root: template
360 root: template
361 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
361 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
362 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
362 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
363 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
363 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
364 summary: remote
364 summary: remote
365 tag: force, local, rev, remove, edit, message, date, user
365 tag: force, local, rev, remove, edit, message, date, user
366 tags: template
366 tags: template
367 tip: patch, git, style, template
367 tip: patch, git, style, template
368 unbundle: update
368 unbundle: update
369 unshelve: abort, continue, interactive, keep, name, tool, date
369 unshelve: abort, continue, interactive, keep, name, tool, date
370 update: clean, check, merge, date, rev, tool
370 update: clean, check, merge, date, rev, tool
371 verify: full
371 verify: full
372 version: template
372 version: template
373
373
374 $ hg init a
374 $ hg init a
375 $ cd a
375 $ cd a
376 $ echo fee > fee
376 $ echo fee > fee
377 $ hg ci -q -Amfee
377 $ hg ci -q -Amfee
378 $ hg tag fee
378 $ hg tag fee
379 $ mkdir fie
379 $ mkdir fie
380 $ echo dead > fie/dead
380 $ echo dead > fie/dead
381 $ echo live > fie/live
381 $ echo live > fie/live
382 $ hg bookmark fo
382 $ hg bookmark fo
383 $ hg branch -q fie
383 $ hg branch -q fie
384 $ hg ci -q -Amfie
384 $ hg ci -q -Amfie
385 $ echo fo > fo
385 $ echo fo > fo
386 $ hg branch -qf default
386 $ hg branch -qf default
387 $ hg ci -q -Amfo
387 $ hg ci -q -Amfo
388 $ echo Fum > Fum
388 $ echo Fum > Fum
389 $ hg ci -q -AmFum
389 $ hg ci -q -AmFum
390 $ hg bookmark Fum
390 $ hg bookmark Fum
391
391
392 Test debugpathcomplete
392 Test debugpathcomplete
393
393
394 $ hg debugpathcomplete f
394 $ hg debugpathcomplete f
395 fee
395 fee
396 fie
396 fie
397 fo
397 fo
398 $ hg debugpathcomplete -f f
398 $ hg debugpathcomplete -f f
399 fee
399 fee
400 fie/dead
400 fie/dead
401 fie/live
401 fie/live
402 fo
402 fo
403
403
404 $ hg rm Fum
404 $ hg rm Fum
405 $ hg debugpathcomplete -r F
405 $ hg debugpathcomplete -r F
406 Fum
406 Fum
407
407
408 Test debugnamecomplete
408 Test debugnamecomplete
409
409
410 $ hg debugnamecomplete
410 $ hg debugnamecomplete
411 Fum
411 Fum
412 default
412 default
413 fee
413 fee
414 fie
414 fie
415 fo
415 fo
416 tip
416 tip
417 $ hg debugnamecomplete f
417 $ hg debugnamecomplete f
418 fee
418 fee
419 fie
419 fie
420 fo
420 fo
421
421
422 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
422 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
423 used for completions in some shells.
423 used for completions in some shells.
424
424
425 $ hg debuglabelcomplete
425 $ hg debuglabelcomplete
426 Fum
426 Fum
427 default
427 default
428 fee
428 fee
429 fie
429 fie
430 fo
430 fo
431 tip
431 tip
432 $ hg debuglabelcomplete f
432 $ hg debuglabelcomplete f
433 fee
433 fee
434 fie
434 fie
435 fo
435 fo
@@ -1,177 +1,189 b''
1 setup
1 setup
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > share =
5 > share =
6 > [format]
6 > [format]
7 > exp-share-safe = True
7 > exp-share-safe = True
8 > EOF
8 > EOF
9
9
10 prepare source repo
10 prepare source repo
11
11
12 $ hg init source
12 $ hg init source
13 $ cd source
13 $ cd source
14 $ cat .hg/requires
14 $ cat .hg/requires
15 exp-sharesafe
15 exp-sharesafe
16 $ cat .hg/store/requires
16 $ cat .hg/store/requires
17 dotencode
17 dotencode
18 fncache
18 fncache
19 generaldelta
19 generaldelta
20 revlogv1
20 revlogv1
21 sparserevlog
21 sparserevlog
22 store
22 store
23 $ hg debugrequirements
23 $ hg debugrequirements
24 dotencode
24 dotencode
25 exp-sharesafe
25 exp-sharesafe
26 fncache
26 fncache
27 generaldelta
27 generaldelta
28 revlogv1
28 revlogv1
29 sparserevlog
29 sparserevlog
30 store
30 store
31
31
32 $ echo a > a
32 $ echo a > a
33 $ hg ci -Aqm "added a"
33 $ hg ci -Aqm "added a"
34 $ echo b > b
34 $ echo b > b
35 $ hg ci -Aqm "added b"
35 $ hg ci -Aqm "added b"
36
37 $ HGEDITOR=cat hg config --shared
38 abort: repository is not shared; can't use --shared
39 [255]
36 $ cd ..
40 $ cd ..
37
41
38 Create a shared repo and check the requirements are shared and read correctly
42 Create a shared repo and check the requirements are shared and read correctly
39 $ hg share source shared1
43 $ hg share source shared1
40 updating working directory
44 updating working directory
41 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 $ cd shared1
46 $ cd shared1
43 $ cat .hg/requires
47 $ cat .hg/requires
44 exp-sharesafe
48 exp-sharesafe
45 shared
49 shared
46
50
47 $ hg debugrequirements -R ../source
51 $ hg debugrequirements -R ../source
48 dotencode
52 dotencode
49 exp-sharesafe
53 exp-sharesafe
50 fncache
54 fncache
51 generaldelta
55 generaldelta
52 revlogv1
56 revlogv1
53 sparserevlog
57 sparserevlog
54 store
58 store
55
59
56 $ hg debugrequirements
60 $ hg debugrequirements
57 dotencode
61 dotencode
58 exp-sharesafe
62 exp-sharesafe
59 fncache
63 fncache
60 generaldelta
64 generaldelta
61 revlogv1
65 revlogv1
62 shared
66 shared
63 sparserevlog
67 sparserevlog
64 store
68 store
65
69
66 $ echo c > c
70 $ echo c > c
67 $ hg ci -Aqm "added c"
71 $ hg ci -Aqm "added c"
68
72
69 Check that config of the source repository is also loaded
73 Check that config of the source repository is also loaded
70
74
71 $ hg showconfig ui.curses
75 $ hg showconfig ui.curses
72 [1]
76 [1]
73
77
74 $ echo "[ui]" >> ../source/.hg/hgrc
78 $ echo "[ui]" >> ../source/.hg/hgrc
75 $ echo "curses=true" >> ../source/.hg/hgrc
79 $ echo "curses=true" >> ../source/.hg/hgrc
76
80
77 $ hg showconfig ui.curses
81 $ hg showconfig ui.curses
78 true
82 true
79
83
80 However, local .hg/hgrc should override the config set by share source
84 However, local .hg/hgrc should override the config set by share source
81
85
82 $ echo "[ui]" >> .hg/hgrc
86 $ echo "[ui]" >> .hg/hgrc
83 $ echo "curses=false" >> .hg/hgrc
87 $ echo "curses=false" >> .hg/hgrc
84
88
85 $ hg showconfig ui.curses
89 $ hg showconfig ui.curses
86 false
90 false
87
91
92 $ HGEDITOR=cat hg config --shared
93 [ui]
94 curses=true
95
96 $ HGEDITOR=cat hg config --local
97 [ui]
98 curses=false
99
88 Testing that hooks set in source repository also runs in shared repo
100 Testing that hooks set in source repository also runs in shared repo
89
101
90 $ cd ../source
102 $ cd ../source
91 $ cat <<EOF >> .hg/hgrc
103 $ cat <<EOF >> .hg/hgrc
92 > [extensions]
104 > [extensions]
93 > hooklib=
105 > hooklib=
94 > [hooks]
106 > [hooks]
95 > pretxnchangegroup.reject_merge_commits = \
107 > pretxnchangegroup.reject_merge_commits = \
96 > python:hgext.hooklib.reject_merge_commits.hook
108 > python:hgext.hooklib.reject_merge_commits.hook
97 > EOF
109 > EOF
98
110
99 $ cd ..
111 $ cd ..
100 $ hg clone source cloned
112 $ hg clone source cloned
101 updating to branch default
113 updating to branch default
102 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
114 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 $ cd cloned
115 $ cd cloned
104 $ hg up 0
116 $ hg up 0
105 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
117 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
106 $ echo bar > bar
118 $ echo bar > bar
107 $ hg ci -Aqm "added bar"
119 $ hg ci -Aqm "added bar"
108 $ hg merge
120 $ hg merge
109 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 (branch merge, don't forget to commit)
122 (branch merge, don't forget to commit)
111 $ hg ci -m "merge commit"
123 $ hg ci -m "merge commit"
112
124
113 $ hg push ../source
125 $ hg push ../source
114 pushing to ../source
126 pushing to ../source
115 searching for changes
127 searching for changes
116 adding changesets
128 adding changesets
117 adding manifests
129 adding manifests
118 adding file changes
130 adding file changes
119 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
131 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
120 transaction abort!
132 transaction abort!
121 rollback completed
133 rollback completed
122 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
134 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
123 [255]
135 [255]
124
136
125 $ hg push ../shared1
137 $ hg push ../shared1
126 pushing to ../shared1
138 pushing to ../shared1
127 searching for changes
139 searching for changes
128 adding changesets
140 adding changesets
129 adding manifests
141 adding manifests
130 adding file changes
142 adding file changes
131 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
143 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
132 transaction abort!
144 transaction abort!
133 rollback completed
145 rollback completed
134 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
146 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
135 [255]
147 [255]
136
148
137 Test that if share source config is untrusted, we dont read it
149 Test that if share source config is untrusted, we dont read it
138
150
139 $ cd ../shared1
151 $ cd ../shared1
140
152
141 $ cat << EOF > $TESTTMP/untrusted.py
153 $ cat << EOF > $TESTTMP/untrusted.py
142 > from mercurial import scmutil, util
154 > from mercurial import scmutil, util
143 > def uisetup(ui):
155 > def uisetup(ui):
144 > class untrustedui(ui.__class__):
156 > class untrustedui(ui.__class__):
145 > def _trusted(self, fp, f):
157 > def _trusted(self, fp, f):
146 > if util.normpath(fp.name).endswith(b'source/.hg/hgrc'):
158 > if util.normpath(fp.name).endswith(b'source/.hg/hgrc'):
147 > return False
159 > return False
148 > return super(untrustedui, self)._trusted(fp, f)
160 > return super(untrustedui, self)._trusted(fp, f)
149 > ui.__class__ = untrustedui
161 > ui.__class__ = untrustedui
150 > EOF
162 > EOF
151
163
152 $ hg showconfig hooks
164 $ hg showconfig hooks
153 hooks.pretxnchangegroup.reject_merge_commits=python:hgext.hooklib.reject_merge_commits.hook
165 hooks.pretxnchangegroup.reject_merge_commits=python:hgext.hooklib.reject_merge_commits.hook
154
166
155 $ hg showconfig hooks --config extensions.untrusted=$TESTTMP/untrusted.py
167 $ hg showconfig hooks --config extensions.untrusted=$TESTTMP/untrusted.py
156 [1]
168 [1]
157
169
158 Unsharing works
170 Unsharing works
159
171
160 $ hg unshare
172 $ hg unshare
161
173
162 Test that source config is added to the shared one after unshare, and the config
174 Test that source config is added to the shared one after unshare, and the config
163 of current repo is still respected over the config which came from source config
175 of current repo is still respected over the config which came from source config
164 $ cd ../cloned
176 $ cd ../cloned
165 $ hg push ../shared1
177 $ hg push ../shared1
166 pushing to ../shared1
178 pushing to ../shared1
167 searching for changes
179 searching for changes
168 adding changesets
180 adding changesets
169 adding manifests
181 adding manifests
170 adding file changes
182 adding file changes
171 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
183 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
172 transaction abort!
184 transaction abort!
173 rollback completed
185 rollback completed
174 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
186 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
175 [255]
187 [255]
176 $ hg showconfig ui.curses -R ../shared1
188 $ hg showconfig ui.curses -R ../shared1
177 false
189 false
General Comments 0
You need to be logged in to leave comments. Login now