##// END OF EJS Templates
branches: add -r option to show branch name(s) of a given rev (issue5948)...
Navaneeth Suresh -
r41094:4506f801 default
parent child Browse files
Show More
@@ -1,6207 +1,6217 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 . import (
25 from . import (
26 archival,
26 archival,
27 bookmarks,
27 bookmarks,
28 bundle2,
28 bundle2,
29 changegroup,
29 changegroup,
30 cmdutil,
30 cmdutil,
31 copies,
31 copies,
32 debugcommands as debugcommandsmod,
32 debugcommands as debugcommandsmod,
33 destutil,
33 destutil,
34 dirstateguard,
34 dirstateguard,
35 discovery,
35 discovery,
36 encoding,
36 encoding,
37 error,
37 error,
38 exchange,
38 exchange,
39 extensions,
39 extensions,
40 filemerge,
40 filemerge,
41 formatter,
41 formatter,
42 graphmod,
42 graphmod,
43 hbisect,
43 hbisect,
44 help,
44 help,
45 hg,
45 hg,
46 logcmdutil,
46 logcmdutil,
47 merge as mergemod,
47 merge as mergemod,
48 narrowspec,
48 narrowspec,
49 obsolete,
49 obsolete,
50 obsutil,
50 obsutil,
51 patch,
51 patch,
52 phases,
52 phases,
53 pycompat,
53 pycompat,
54 rcutil,
54 rcutil,
55 registrar,
55 registrar,
56 repair,
56 repair,
57 revsetlang,
57 revsetlang,
58 rewriteutil,
58 rewriteutil,
59 scmutil,
59 scmutil,
60 server,
60 server,
61 state as statemod,
61 state as statemod,
62 streamclone,
62 streamclone,
63 tags as tagsmod,
63 tags as tagsmod,
64 templatekw,
64 templatekw,
65 ui as uimod,
65 ui as uimod,
66 util,
66 util,
67 wireprotoserver,
67 wireprotoserver,
68 )
68 )
69 from .utils import (
69 from .utils import (
70 dateutil,
70 dateutil,
71 stringutil,
71 stringutil,
72 )
72 )
73
73
74 table = {}
74 table = {}
75 table.update(debugcommandsmod.command._table)
75 table.update(debugcommandsmod.command._table)
76
76
77 command = registrar.command(table)
77 command = registrar.command(table)
78 INTENT_READONLY = registrar.INTENT_READONLY
78 INTENT_READONLY = registrar.INTENT_READONLY
79
79
80 # common command options
80 # common command options
81
81
82 globalopts = [
82 globalopts = [
83 ('R', 'repository', '',
83 ('R', 'repository', '',
84 _('repository root directory or name of overlay bundle file'),
84 _('repository root directory or name of overlay bundle file'),
85 _('REPO')),
85 _('REPO')),
86 ('', 'cwd', '',
86 ('', 'cwd', '',
87 _('change working directory'), _('DIR')),
87 _('change working directory'), _('DIR')),
88 ('y', 'noninteractive', None,
88 ('y', 'noninteractive', None,
89 _('do not prompt, automatically pick the first choice for all prompts')),
89 _('do not prompt, automatically pick the first choice for all prompts')),
90 ('q', 'quiet', None, _('suppress output')),
90 ('q', 'quiet', None, _('suppress output')),
91 ('v', 'verbose', None, _('enable additional output')),
91 ('v', 'verbose', None, _('enable additional output')),
92 ('', 'color', '',
92 ('', 'color', '',
93 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
93 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
94 # and should not be translated
94 # and should not be translated
95 _("when to colorize (boolean, always, auto, never, or debug)"),
95 _("when to colorize (boolean, always, auto, never, or debug)"),
96 _('TYPE')),
96 _('TYPE')),
97 ('', 'config', [],
97 ('', 'config', [],
98 _('set/override config option (use \'section.name=value\')'),
98 _('set/override config option (use \'section.name=value\')'),
99 _('CONFIG')),
99 _('CONFIG')),
100 ('', 'debug', None, _('enable debugging output')),
100 ('', 'debug', None, _('enable debugging output')),
101 ('', 'debugger', None, _('start debugger')),
101 ('', 'debugger', None, _('start debugger')),
102 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
102 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
103 _('ENCODE')),
103 _('ENCODE')),
104 ('', 'encodingmode', encoding.encodingmode,
104 ('', 'encodingmode', encoding.encodingmode,
105 _('set the charset encoding mode'), _('MODE')),
105 _('set the charset encoding mode'), _('MODE')),
106 ('', 'traceback', None, _('always print a traceback on exception')),
106 ('', 'traceback', None, _('always print a traceback on exception')),
107 ('', 'time', None, _('time how long the command takes')),
107 ('', 'time', None, _('time how long the command takes')),
108 ('', 'profile', None, _('print command execution profile')),
108 ('', 'profile', None, _('print command execution profile')),
109 ('', 'version', None, _('output version information and exit')),
109 ('', 'version', None, _('output version information and exit')),
110 ('h', 'help', None, _('display help and exit')),
110 ('h', 'help', None, _('display help and exit')),
111 ('', 'hidden', False, _('consider hidden changesets')),
111 ('', 'hidden', False, _('consider hidden changesets')),
112 ('', 'pager', 'auto',
112 ('', 'pager', 'auto',
113 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
113 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
114 ]
114 ]
115
115
116 dryrunopts = cmdutil.dryrunopts
116 dryrunopts = cmdutil.dryrunopts
117 remoteopts = cmdutil.remoteopts
117 remoteopts = cmdutil.remoteopts
118 walkopts = cmdutil.walkopts
118 walkopts = cmdutil.walkopts
119 commitopts = cmdutil.commitopts
119 commitopts = cmdutil.commitopts
120 commitopts2 = cmdutil.commitopts2
120 commitopts2 = cmdutil.commitopts2
121 formatteropts = cmdutil.formatteropts
121 formatteropts = cmdutil.formatteropts
122 templateopts = cmdutil.templateopts
122 templateopts = cmdutil.templateopts
123 logopts = cmdutil.logopts
123 logopts = cmdutil.logopts
124 diffopts = cmdutil.diffopts
124 diffopts = cmdutil.diffopts
125 diffwsopts = cmdutil.diffwsopts
125 diffwsopts = cmdutil.diffwsopts
126 diffopts2 = cmdutil.diffopts2
126 diffopts2 = cmdutil.diffopts2
127 mergetoolopts = cmdutil.mergetoolopts
127 mergetoolopts = cmdutil.mergetoolopts
128 similarityopts = cmdutil.similarityopts
128 similarityopts = cmdutil.similarityopts
129 subrepoopts = cmdutil.subrepoopts
129 subrepoopts = cmdutil.subrepoopts
130 debugrevlogopts = cmdutil.debugrevlogopts
130 debugrevlogopts = cmdutil.debugrevlogopts
131
131
132 # Commands start here, listed alphabetically
132 # Commands start here, listed alphabetically
133
133
134 @command('add',
134 @command('add',
135 walkopts + subrepoopts + dryrunopts,
135 walkopts + subrepoopts + dryrunopts,
136 _('[OPTION]... [FILE]...'),
136 _('[OPTION]... [FILE]...'),
137 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
137 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
138 helpbasic=True, inferrepo=True)
138 helpbasic=True, inferrepo=True)
139 def add(ui, repo, *pats, **opts):
139 def add(ui, repo, *pats, **opts):
140 """add the specified files on the next commit
140 """add the specified files on the next commit
141
141
142 Schedule files to be version controlled and added to the
142 Schedule files to be version controlled and added to the
143 repository.
143 repository.
144
144
145 The files will be added to the repository at the next commit. To
145 The files will be added to the repository at the next commit. To
146 undo an add before that, see :hg:`forget`.
146 undo an add before that, see :hg:`forget`.
147
147
148 If no names are given, add all files to the repository (except
148 If no names are given, add all files to the repository (except
149 files matching ``.hgignore``).
149 files matching ``.hgignore``).
150
150
151 .. container:: verbose
151 .. container:: verbose
152
152
153 Examples:
153 Examples:
154
154
155 - New (unknown) files are added
155 - New (unknown) files are added
156 automatically by :hg:`add`::
156 automatically by :hg:`add`::
157
157
158 $ ls
158 $ ls
159 foo.c
159 foo.c
160 $ hg status
160 $ hg status
161 ? foo.c
161 ? foo.c
162 $ hg add
162 $ hg add
163 adding foo.c
163 adding foo.c
164 $ hg status
164 $ hg status
165 A foo.c
165 A foo.c
166
166
167 - Specific files to be added can be specified::
167 - Specific files to be added can be specified::
168
168
169 $ ls
169 $ ls
170 bar.c foo.c
170 bar.c foo.c
171 $ hg status
171 $ hg status
172 ? bar.c
172 ? bar.c
173 ? foo.c
173 ? foo.c
174 $ hg add bar.c
174 $ hg add bar.c
175 $ hg status
175 $ hg status
176 A bar.c
176 A bar.c
177 ? foo.c
177 ? foo.c
178
178
179 Returns 0 if all files are successfully added.
179 Returns 0 if all files are successfully added.
180 """
180 """
181
181
182 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
182 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
183 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
183 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
184 return rejected and 1 or 0
184 return rejected and 1 or 0
185
185
186 @command('addremove',
186 @command('addremove',
187 similarityopts + subrepoopts + walkopts + dryrunopts,
187 similarityopts + subrepoopts + walkopts + dryrunopts,
188 _('[OPTION]... [FILE]...'),
188 _('[OPTION]... [FILE]...'),
189 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
189 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
190 inferrepo=True)
190 inferrepo=True)
191 def addremove(ui, repo, *pats, **opts):
191 def addremove(ui, repo, *pats, **opts):
192 """add all new files, delete all missing files
192 """add all new files, delete all missing files
193
193
194 Add all new files and remove all missing files from the
194 Add all new files and remove all missing files from the
195 repository.
195 repository.
196
196
197 Unless names are given, new files are ignored if they match any of
197 Unless names are given, new files are ignored if they match any of
198 the patterns in ``.hgignore``. As with add, these changes take
198 the patterns in ``.hgignore``. As with add, these changes take
199 effect at the next commit.
199 effect at the next commit.
200
200
201 Use the -s/--similarity option to detect renamed files. This
201 Use the -s/--similarity option to detect renamed files. This
202 option takes a percentage between 0 (disabled) and 100 (files must
202 option takes a percentage between 0 (disabled) and 100 (files must
203 be identical) as its parameter. With a parameter greater than 0,
203 be identical) as its parameter. With a parameter greater than 0,
204 this compares every removed file with every added file and records
204 this compares every removed file with every added file and records
205 those similar enough as renames. Detecting renamed files this way
205 those similar enough as renames. Detecting renamed files this way
206 can be expensive. After using this option, :hg:`status -C` can be
206 can be expensive. After using this option, :hg:`status -C` can be
207 used to check which files were identified as moved or renamed. If
207 used to check which files were identified as moved or renamed. If
208 not specified, -s/--similarity defaults to 100 and only renames of
208 not specified, -s/--similarity defaults to 100 and only renames of
209 identical files are detected.
209 identical files are detected.
210
210
211 .. container:: verbose
211 .. container:: verbose
212
212
213 Examples:
213 Examples:
214
214
215 - A number of files (bar.c and foo.c) are new,
215 - A number of files (bar.c and foo.c) are new,
216 while foobar.c has been removed (without using :hg:`remove`)
216 while foobar.c has been removed (without using :hg:`remove`)
217 from the repository::
217 from the repository::
218
218
219 $ ls
219 $ ls
220 bar.c foo.c
220 bar.c foo.c
221 $ hg status
221 $ hg status
222 ! foobar.c
222 ! foobar.c
223 ? bar.c
223 ? bar.c
224 ? foo.c
224 ? foo.c
225 $ hg addremove
225 $ hg addremove
226 adding bar.c
226 adding bar.c
227 adding foo.c
227 adding foo.c
228 removing foobar.c
228 removing foobar.c
229 $ hg status
229 $ hg status
230 A bar.c
230 A bar.c
231 A foo.c
231 A foo.c
232 R foobar.c
232 R foobar.c
233
233
234 - A file foobar.c was moved to foo.c without using :hg:`rename`.
234 - A file foobar.c was moved to foo.c without using :hg:`rename`.
235 Afterwards, it was edited slightly::
235 Afterwards, it was edited slightly::
236
236
237 $ ls
237 $ ls
238 foo.c
238 foo.c
239 $ hg status
239 $ hg status
240 ! foobar.c
240 ! foobar.c
241 ? foo.c
241 ? foo.c
242 $ hg addremove --similarity 90
242 $ hg addremove --similarity 90
243 removing foobar.c
243 removing foobar.c
244 adding foo.c
244 adding foo.c
245 recording removal of foobar.c as rename to foo.c (94% similar)
245 recording removal of foobar.c as rename to foo.c (94% similar)
246 $ hg status -C
246 $ hg status -C
247 A foo.c
247 A foo.c
248 foobar.c
248 foobar.c
249 R foobar.c
249 R foobar.c
250
250
251 Returns 0 if all files are successfully added.
251 Returns 0 if all files are successfully added.
252 """
252 """
253 opts = pycompat.byteskwargs(opts)
253 opts = pycompat.byteskwargs(opts)
254 if not opts.get('similarity'):
254 if not opts.get('similarity'):
255 opts['similarity'] = '100'
255 opts['similarity'] = '100'
256 matcher = scmutil.match(repo[None], pats, opts)
256 matcher = scmutil.match(repo[None], pats, opts)
257 return scmutil.addremove(repo, matcher, "", opts)
257 return scmutil.addremove(repo, matcher, "", opts)
258
258
259 @command('annotate|blame',
259 @command('annotate|blame',
260 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
260 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
261 ('', 'follow', None,
261 ('', 'follow', None,
262 _('follow copies/renames and list the filename (DEPRECATED)')),
262 _('follow copies/renames and list the filename (DEPRECATED)')),
263 ('', 'no-follow', None, _("don't follow copies and renames")),
263 ('', 'no-follow', None, _("don't follow copies and renames")),
264 ('a', 'text', None, _('treat all files as text')),
264 ('a', 'text', None, _('treat all files as text')),
265 ('u', 'user', None, _('list the author (long with -v)')),
265 ('u', 'user', None, _('list the author (long with -v)')),
266 ('f', 'file', None, _('list the filename')),
266 ('f', 'file', None, _('list the filename')),
267 ('d', 'date', None, _('list the date (short with -q)')),
267 ('d', 'date', None, _('list the date (short with -q)')),
268 ('n', 'number', None, _('list the revision number (default)')),
268 ('n', 'number', None, _('list the revision number (default)')),
269 ('c', 'changeset', None, _('list the changeset')),
269 ('c', 'changeset', None, _('list the changeset')),
270 ('l', 'line-number', None, _('show line number at the first appearance')),
270 ('l', 'line-number', None, _('show line number at the first appearance')),
271 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
271 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
272 ] + diffwsopts + walkopts + formatteropts,
272 ] + diffwsopts + walkopts + formatteropts,
273 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
273 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
274 helpcategory=command.CATEGORY_FILE_CONTENTS,
274 helpcategory=command.CATEGORY_FILE_CONTENTS,
275 helpbasic=True, inferrepo=True)
275 helpbasic=True, inferrepo=True)
276 def annotate(ui, repo, *pats, **opts):
276 def annotate(ui, repo, *pats, **opts):
277 """show changeset information by line for each file
277 """show changeset information by line for each file
278
278
279 List changes in files, showing the revision id responsible for
279 List changes in files, showing the revision id responsible for
280 each line.
280 each line.
281
281
282 This command is useful for discovering when a change was made and
282 This command is useful for discovering when a change was made and
283 by whom.
283 by whom.
284
284
285 If you include --file, --user, or --date, the revision number is
285 If you include --file, --user, or --date, the revision number is
286 suppressed unless you also include --number.
286 suppressed unless you also include --number.
287
287
288 Without the -a/--text option, annotate will avoid processing files
288 Without the -a/--text option, annotate will avoid processing files
289 it detects as binary. With -a, annotate will annotate the file
289 it detects as binary. With -a, annotate will annotate the file
290 anyway, although the results will probably be neither useful
290 anyway, although the results will probably be neither useful
291 nor desirable.
291 nor desirable.
292
292
293 .. container:: verbose
293 .. container:: verbose
294
294
295 Template:
295 Template:
296
296
297 The following keywords are supported in addition to the common template
297 The following keywords are supported in addition to the common template
298 keywords and functions. See also :hg:`help templates`.
298 keywords and functions. See also :hg:`help templates`.
299
299
300 :lines: List of lines with annotation data.
300 :lines: List of lines with annotation data.
301 :path: String. Repository-absolute path of the specified file.
301 :path: String. Repository-absolute path of the specified file.
302
302
303 And each entry of ``{lines}`` provides the following sub-keywords in
303 And each entry of ``{lines}`` provides the following sub-keywords in
304 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
304 addition to ``{date}``, ``{node}``, ``{rev}``, ``{user}``, etc.
305
305
306 :line: String. Line content.
306 :line: String. Line content.
307 :lineno: Integer. Line number at that revision.
307 :lineno: Integer. Line number at that revision.
308 :path: String. Repository-absolute path of the file at that revision.
308 :path: String. Repository-absolute path of the file at that revision.
309
309
310 See :hg:`help templates.operators` for the list expansion syntax.
310 See :hg:`help templates.operators` for the list expansion syntax.
311
311
312 Returns 0 on success.
312 Returns 0 on success.
313 """
313 """
314 opts = pycompat.byteskwargs(opts)
314 opts = pycompat.byteskwargs(opts)
315 if not pats:
315 if not pats:
316 raise error.Abort(_('at least one filename or pattern is required'))
316 raise error.Abort(_('at least one filename or pattern is required'))
317
317
318 if opts.get('follow'):
318 if opts.get('follow'):
319 # --follow is deprecated and now just an alias for -f/--file
319 # --follow is deprecated and now just an alias for -f/--file
320 # to mimic the behavior of Mercurial before version 1.5
320 # to mimic the behavior of Mercurial before version 1.5
321 opts['file'] = True
321 opts['file'] = True
322
322
323 if (not opts.get('user') and not opts.get('changeset')
323 if (not opts.get('user') and not opts.get('changeset')
324 and not opts.get('date') and not opts.get('file')):
324 and not opts.get('date') and not opts.get('file')):
325 opts['number'] = True
325 opts['number'] = True
326
326
327 linenumber = opts.get('line_number') is not None
327 linenumber = opts.get('line_number') is not None
328 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
328 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
329 raise error.Abort(_('at least one of -n/-c is required for -l'))
329 raise error.Abort(_('at least one of -n/-c is required for -l'))
330
330
331 rev = opts.get('rev')
331 rev = opts.get('rev')
332 if rev:
332 if rev:
333 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
333 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
334 ctx = scmutil.revsingle(repo, rev)
334 ctx = scmutil.revsingle(repo, rev)
335
335
336 ui.pager('annotate')
336 ui.pager('annotate')
337 rootfm = ui.formatter('annotate', opts)
337 rootfm = ui.formatter('annotate', opts)
338 if ui.debugflag:
338 if ui.debugflag:
339 shorthex = pycompat.identity
339 shorthex = pycompat.identity
340 else:
340 else:
341 def shorthex(h):
341 def shorthex(h):
342 return h[:12]
342 return h[:12]
343 if ui.quiet:
343 if ui.quiet:
344 datefunc = dateutil.shortdate
344 datefunc = dateutil.shortdate
345 else:
345 else:
346 datefunc = dateutil.datestr
346 datefunc = dateutil.datestr
347 if ctx.rev() is None:
347 if ctx.rev() is None:
348 if opts.get('changeset'):
348 if opts.get('changeset'):
349 # omit "+" suffix which is appended to node hex
349 # omit "+" suffix which is appended to node hex
350 def formatrev(rev):
350 def formatrev(rev):
351 if rev == wdirrev:
351 if rev == wdirrev:
352 return '%d' % ctx.p1().rev()
352 return '%d' % ctx.p1().rev()
353 else:
353 else:
354 return '%d' % rev
354 return '%d' % rev
355 else:
355 else:
356 def formatrev(rev):
356 def formatrev(rev):
357 if rev == wdirrev:
357 if rev == wdirrev:
358 return '%d+' % ctx.p1().rev()
358 return '%d+' % ctx.p1().rev()
359 else:
359 else:
360 return '%d ' % rev
360 return '%d ' % rev
361 def formathex(h):
361 def formathex(h):
362 if h == wdirhex:
362 if h == wdirhex:
363 return '%s+' % shorthex(hex(ctx.p1().node()))
363 return '%s+' % shorthex(hex(ctx.p1().node()))
364 else:
364 else:
365 return '%s ' % shorthex(h)
365 return '%s ' % shorthex(h)
366 else:
366 else:
367 formatrev = b'%d'.__mod__
367 formatrev = b'%d'.__mod__
368 formathex = shorthex
368 formathex = shorthex
369
369
370 opmap = [
370 opmap = [
371 ('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
371 ('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
372 ('rev', ' ', lambda x: scmutil.intrev(x.fctx), formatrev),
372 ('rev', ' ', lambda x: scmutil.intrev(x.fctx), formatrev),
373 ('node', ' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
373 ('node', ' ', lambda x: hex(scmutil.binnode(x.fctx)), formathex),
374 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
374 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
375 ('path', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
375 ('path', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
376 ('lineno', ':', lambda x: x.lineno, pycompat.bytestr),
376 ('lineno', ':', lambda x: x.lineno, pycompat.bytestr),
377 ]
377 ]
378 opnamemap = {
378 opnamemap = {
379 'rev': 'number',
379 'rev': 'number',
380 'node': 'changeset',
380 'node': 'changeset',
381 'path': 'file',
381 'path': 'file',
382 'lineno': 'line_number',
382 'lineno': 'line_number',
383 }
383 }
384
384
385 if rootfm.isplain():
385 if rootfm.isplain():
386 def makefunc(get, fmt):
386 def makefunc(get, fmt):
387 return lambda x: fmt(get(x))
387 return lambda x: fmt(get(x))
388 else:
388 else:
389 def makefunc(get, fmt):
389 def makefunc(get, fmt):
390 return get
390 return get
391 datahint = rootfm.datahint()
391 datahint = rootfm.datahint()
392 funcmap = [(makefunc(get, fmt), sep) for fn, sep, get, fmt in opmap
392 funcmap = [(makefunc(get, fmt), sep) for fn, sep, get, fmt in opmap
393 if opts.get(opnamemap.get(fn, fn)) or fn in datahint]
393 if opts.get(opnamemap.get(fn, fn)) or fn in datahint]
394 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
394 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
395 fields = ' '.join(fn for fn, sep, get, fmt in opmap
395 fields = ' '.join(fn for fn, sep, get, fmt in opmap
396 if opts.get(opnamemap.get(fn, fn)) or fn in datahint)
396 if opts.get(opnamemap.get(fn, fn)) or fn in datahint)
397
397
398 def bad(x, y):
398 def bad(x, y):
399 raise error.Abort("%s: %s" % (x, y))
399 raise error.Abort("%s: %s" % (x, y))
400
400
401 m = scmutil.match(ctx, pats, opts, badfn=bad)
401 m = scmutil.match(ctx, pats, opts, badfn=bad)
402
402
403 follow = not opts.get('no_follow')
403 follow = not opts.get('no_follow')
404 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
404 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
405 whitespace=True)
405 whitespace=True)
406 skiprevs = opts.get('skip')
406 skiprevs = opts.get('skip')
407 if skiprevs:
407 if skiprevs:
408 skiprevs = scmutil.revrange(repo, skiprevs)
408 skiprevs = scmutil.revrange(repo, skiprevs)
409
409
410 for abs in ctx.walk(m):
410 for abs in ctx.walk(m):
411 fctx = ctx[abs]
411 fctx = ctx[abs]
412 rootfm.startitem()
412 rootfm.startitem()
413 rootfm.data(path=abs)
413 rootfm.data(path=abs)
414 if not opts.get('text') and fctx.isbinary():
414 if not opts.get('text') and fctx.isbinary():
415 rootfm.plain(_("%s: binary file\n") % m.rel(abs))
415 rootfm.plain(_("%s: binary file\n") % m.rel(abs))
416 continue
416 continue
417
417
418 fm = rootfm.nested('lines', tmpl='{rev}: {line}')
418 fm = rootfm.nested('lines', tmpl='{rev}: {line}')
419 lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
419 lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
420 diffopts=diffopts)
420 diffopts=diffopts)
421 if not lines:
421 if not lines:
422 fm.end()
422 fm.end()
423 continue
423 continue
424 formats = []
424 formats = []
425 pieces = []
425 pieces = []
426
426
427 for f, sep in funcmap:
427 for f, sep in funcmap:
428 l = [f(n) for n in lines]
428 l = [f(n) for n in lines]
429 if fm.isplain():
429 if fm.isplain():
430 sizes = [encoding.colwidth(x) for x in l]
430 sizes = [encoding.colwidth(x) for x in l]
431 ml = max(sizes)
431 ml = max(sizes)
432 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
432 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
433 else:
433 else:
434 formats.append(['%s' for x in l])
434 formats.append(['%s' for x in l])
435 pieces.append(l)
435 pieces.append(l)
436
436
437 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
437 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
438 fm.startitem()
438 fm.startitem()
439 fm.context(fctx=n.fctx)
439 fm.context(fctx=n.fctx)
440 fm.write(fields, "".join(f), *p)
440 fm.write(fields, "".join(f), *p)
441 if n.skip:
441 if n.skip:
442 fmt = "* %s"
442 fmt = "* %s"
443 else:
443 else:
444 fmt = ": %s"
444 fmt = ": %s"
445 fm.write('line', fmt, n.text)
445 fm.write('line', fmt, n.text)
446
446
447 if not lines[-1].text.endswith('\n'):
447 if not lines[-1].text.endswith('\n'):
448 fm.plain('\n')
448 fm.plain('\n')
449 fm.end()
449 fm.end()
450
450
451 rootfm.end()
451 rootfm.end()
452
452
453 @command('archive',
453 @command('archive',
454 [('', 'no-decode', None, _('do not pass files through decoders')),
454 [('', 'no-decode', None, _('do not pass files through decoders')),
455 ('p', 'prefix', '', _('directory prefix for files in archive'),
455 ('p', 'prefix', '', _('directory prefix for files in archive'),
456 _('PREFIX')),
456 _('PREFIX')),
457 ('r', 'rev', '', _('revision to distribute'), _('REV')),
457 ('r', 'rev', '', _('revision to distribute'), _('REV')),
458 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
458 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
459 ] + subrepoopts + walkopts,
459 ] + subrepoopts + walkopts,
460 _('[OPTION]... DEST'),
460 _('[OPTION]... DEST'),
461 helpcategory=command.CATEGORY_IMPORT_EXPORT)
461 helpcategory=command.CATEGORY_IMPORT_EXPORT)
462 def archive(ui, repo, dest, **opts):
462 def archive(ui, repo, dest, **opts):
463 '''create an unversioned archive of a repository revision
463 '''create an unversioned archive of a repository revision
464
464
465 By default, the revision used is the parent of the working
465 By default, the revision used is the parent of the working
466 directory; use -r/--rev to specify a different revision.
466 directory; use -r/--rev to specify a different revision.
467
467
468 The archive type is automatically detected based on file
468 The archive type is automatically detected based on file
469 extension (to override, use -t/--type).
469 extension (to override, use -t/--type).
470
470
471 .. container:: verbose
471 .. container:: verbose
472
472
473 Examples:
473 Examples:
474
474
475 - create a zip file containing the 1.0 release::
475 - create a zip file containing the 1.0 release::
476
476
477 hg archive -r 1.0 project-1.0.zip
477 hg archive -r 1.0 project-1.0.zip
478
478
479 - create a tarball excluding .hg files::
479 - create a tarball excluding .hg files::
480
480
481 hg archive project.tar.gz -X ".hg*"
481 hg archive project.tar.gz -X ".hg*"
482
482
483 Valid types are:
483 Valid types are:
484
484
485 :``files``: a directory full of files (default)
485 :``files``: a directory full of files (default)
486 :``tar``: tar archive, uncompressed
486 :``tar``: tar archive, uncompressed
487 :``tbz2``: tar archive, compressed using bzip2
487 :``tbz2``: tar archive, compressed using bzip2
488 :``tgz``: tar archive, compressed using gzip
488 :``tgz``: tar archive, compressed using gzip
489 :``uzip``: zip archive, uncompressed
489 :``uzip``: zip archive, uncompressed
490 :``zip``: zip archive, compressed using deflate
490 :``zip``: zip archive, compressed using deflate
491
491
492 The exact name of the destination archive or directory is given
492 The exact name of the destination archive or directory is given
493 using a format string; see :hg:`help export` for details.
493 using a format string; see :hg:`help export` for details.
494
494
495 Each member added to an archive file has a directory prefix
495 Each member added to an archive file has a directory prefix
496 prepended. Use -p/--prefix to specify a format string for the
496 prepended. Use -p/--prefix to specify a format string for the
497 prefix. The default is the basename of the archive, with suffixes
497 prefix. The default is the basename of the archive, with suffixes
498 removed.
498 removed.
499
499
500 Returns 0 on success.
500 Returns 0 on success.
501 '''
501 '''
502
502
503 opts = pycompat.byteskwargs(opts)
503 opts = pycompat.byteskwargs(opts)
504 rev = opts.get('rev')
504 rev = opts.get('rev')
505 if rev:
505 if rev:
506 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
506 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
507 ctx = scmutil.revsingle(repo, rev)
507 ctx = scmutil.revsingle(repo, rev)
508 if not ctx:
508 if not ctx:
509 raise error.Abort(_('no working directory: please specify a revision'))
509 raise error.Abort(_('no working directory: please specify a revision'))
510 node = ctx.node()
510 node = ctx.node()
511 dest = cmdutil.makefilename(ctx, dest)
511 dest = cmdutil.makefilename(ctx, dest)
512 if os.path.realpath(dest) == repo.root:
512 if os.path.realpath(dest) == repo.root:
513 raise error.Abort(_('repository root cannot be destination'))
513 raise error.Abort(_('repository root cannot be destination'))
514
514
515 kind = opts.get('type') or archival.guesskind(dest) or 'files'
515 kind = opts.get('type') or archival.guesskind(dest) or 'files'
516 prefix = opts.get('prefix')
516 prefix = opts.get('prefix')
517
517
518 if dest == '-':
518 if dest == '-':
519 if kind == 'files':
519 if kind == 'files':
520 raise error.Abort(_('cannot archive plain files to stdout'))
520 raise error.Abort(_('cannot archive plain files to stdout'))
521 dest = cmdutil.makefileobj(ctx, dest)
521 dest = cmdutil.makefileobj(ctx, dest)
522 if not prefix:
522 if not prefix:
523 prefix = os.path.basename(repo.root) + '-%h'
523 prefix = os.path.basename(repo.root) + '-%h'
524
524
525 prefix = cmdutil.makefilename(ctx, prefix)
525 prefix = cmdutil.makefilename(ctx, prefix)
526 match = scmutil.match(ctx, [], opts)
526 match = scmutil.match(ctx, [], opts)
527 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
527 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
528 match, prefix, subrepos=opts.get('subrepos'))
528 match, prefix, subrepos=opts.get('subrepos'))
529
529
530 @command('backout',
530 @command('backout',
531 [('', 'merge', None, _('merge with old dirstate parent after backout')),
531 [('', 'merge', None, _('merge with old dirstate parent after backout')),
532 ('', 'commit', None,
532 ('', 'commit', None,
533 _('commit if no conflicts were encountered (DEPRECATED)')),
533 _('commit if no conflicts were encountered (DEPRECATED)')),
534 ('', 'no-commit', None, _('do not commit')),
534 ('', 'no-commit', None, _('do not commit')),
535 ('', 'parent', '',
535 ('', 'parent', '',
536 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
536 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
537 ('r', 'rev', '', _('revision to backout'), _('REV')),
537 ('r', 'rev', '', _('revision to backout'), _('REV')),
538 ('e', 'edit', False, _('invoke editor on commit messages')),
538 ('e', 'edit', False, _('invoke editor on commit messages')),
539 ] + mergetoolopts + walkopts + commitopts + commitopts2,
539 ] + mergetoolopts + walkopts + commitopts + commitopts2,
540 _('[OPTION]... [-r] REV'),
540 _('[OPTION]... [-r] REV'),
541 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
541 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
542 def backout(ui, repo, node=None, rev=None, **opts):
542 def backout(ui, repo, node=None, rev=None, **opts):
543 '''reverse effect of earlier changeset
543 '''reverse effect of earlier changeset
544
544
545 Prepare a new changeset with the effect of REV undone in the
545 Prepare a new changeset with the effect of REV undone in the
546 current working directory. If no conflicts were encountered,
546 current working directory. If no conflicts were encountered,
547 it will be committed immediately.
547 it will be committed immediately.
548
548
549 If REV is the parent of the working directory, then this new changeset
549 If REV is the parent of the working directory, then this new changeset
550 is committed automatically (unless --no-commit is specified).
550 is committed automatically (unless --no-commit is specified).
551
551
552 .. note::
552 .. note::
553
553
554 :hg:`backout` cannot be used to fix either an unwanted or
554 :hg:`backout` cannot be used to fix either an unwanted or
555 incorrect merge.
555 incorrect merge.
556
556
557 .. container:: verbose
557 .. container:: verbose
558
558
559 Examples:
559 Examples:
560
560
561 - Reverse the effect of the parent of the working directory.
561 - Reverse the effect of the parent of the working directory.
562 This backout will be committed immediately::
562 This backout will be committed immediately::
563
563
564 hg backout -r .
564 hg backout -r .
565
565
566 - Reverse the effect of previous bad revision 23::
566 - Reverse the effect of previous bad revision 23::
567
567
568 hg backout -r 23
568 hg backout -r 23
569
569
570 - Reverse the effect of previous bad revision 23 and
570 - Reverse the effect of previous bad revision 23 and
571 leave changes uncommitted::
571 leave changes uncommitted::
572
572
573 hg backout -r 23 --no-commit
573 hg backout -r 23 --no-commit
574 hg commit -m "Backout revision 23"
574 hg commit -m "Backout revision 23"
575
575
576 By default, the pending changeset will have one parent,
576 By default, the pending changeset will have one parent,
577 maintaining a linear history. With --merge, the pending
577 maintaining a linear history. With --merge, the pending
578 changeset will instead have two parents: the old parent of the
578 changeset will instead have two parents: the old parent of the
579 working directory and a new child of REV that simply undoes REV.
579 working directory and a new child of REV that simply undoes REV.
580
580
581 Before version 1.7, the behavior without --merge was equivalent
581 Before version 1.7, the behavior without --merge was equivalent
582 to specifying --merge followed by :hg:`update --clean .` to
582 to specifying --merge followed by :hg:`update --clean .` to
583 cancel the merge and leave the child of REV as a head to be
583 cancel the merge and leave the child of REV as a head to be
584 merged separately.
584 merged separately.
585
585
586 See :hg:`help dates` for a list of formats valid for -d/--date.
586 See :hg:`help dates` for a list of formats valid for -d/--date.
587
587
588 See :hg:`help revert` for a way to restore files to the state
588 See :hg:`help revert` for a way to restore files to the state
589 of another revision.
589 of another revision.
590
590
591 Returns 0 on success, 1 if nothing to backout or there are unresolved
591 Returns 0 on success, 1 if nothing to backout or there are unresolved
592 files.
592 files.
593 '''
593 '''
594 with repo.wlock(), repo.lock():
594 with repo.wlock(), repo.lock():
595 return _dobackout(ui, repo, node, rev, **opts)
595 return _dobackout(ui, repo, node, rev, **opts)
596
596
597 def _dobackout(ui, repo, node=None, rev=None, **opts):
597 def _dobackout(ui, repo, node=None, rev=None, **opts):
598 opts = pycompat.byteskwargs(opts)
598 opts = pycompat.byteskwargs(opts)
599 if opts.get('commit') and opts.get('no_commit'):
599 if opts.get('commit') and opts.get('no_commit'):
600 raise error.Abort(_("cannot use --commit with --no-commit"))
600 raise error.Abort(_("cannot use --commit with --no-commit"))
601 if opts.get('merge') and opts.get('no_commit'):
601 if opts.get('merge') and opts.get('no_commit'):
602 raise error.Abort(_("cannot use --merge with --no-commit"))
602 raise error.Abort(_("cannot use --merge with --no-commit"))
603
603
604 if rev and node:
604 if rev and node:
605 raise error.Abort(_("please specify just one revision"))
605 raise error.Abort(_("please specify just one revision"))
606
606
607 if not rev:
607 if not rev:
608 rev = node
608 rev = node
609
609
610 if not rev:
610 if not rev:
611 raise error.Abort(_("please specify a revision to backout"))
611 raise error.Abort(_("please specify a revision to backout"))
612
612
613 date = opts.get('date')
613 date = opts.get('date')
614 if date:
614 if date:
615 opts['date'] = dateutil.parsedate(date)
615 opts['date'] = dateutil.parsedate(date)
616
616
617 cmdutil.checkunfinished(repo)
617 cmdutil.checkunfinished(repo)
618 cmdutil.bailifchanged(repo)
618 cmdutil.bailifchanged(repo)
619 node = scmutil.revsingle(repo, rev).node()
619 node = scmutil.revsingle(repo, rev).node()
620
620
621 op1, op2 = repo.dirstate.parents()
621 op1, op2 = repo.dirstate.parents()
622 if not repo.changelog.isancestor(node, op1):
622 if not repo.changelog.isancestor(node, op1):
623 raise error.Abort(_('cannot backout change that is not an ancestor'))
623 raise error.Abort(_('cannot backout change that is not an ancestor'))
624
624
625 p1, p2 = repo.changelog.parents(node)
625 p1, p2 = repo.changelog.parents(node)
626 if p1 == nullid:
626 if p1 == nullid:
627 raise error.Abort(_('cannot backout a change with no parents'))
627 raise error.Abort(_('cannot backout a change with no parents'))
628 if p2 != nullid:
628 if p2 != nullid:
629 if not opts.get('parent'):
629 if not opts.get('parent'):
630 raise error.Abort(_('cannot backout a merge changeset'))
630 raise error.Abort(_('cannot backout a merge changeset'))
631 p = repo.lookup(opts['parent'])
631 p = repo.lookup(opts['parent'])
632 if p not in (p1, p2):
632 if p not in (p1, p2):
633 raise error.Abort(_('%s is not a parent of %s') %
633 raise error.Abort(_('%s is not a parent of %s') %
634 (short(p), short(node)))
634 (short(p), short(node)))
635 parent = p
635 parent = p
636 else:
636 else:
637 if opts.get('parent'):
637 if opts.get('parent'):
638 raise error.Abort(_('cannot use --parent on non-merge changeset'))
638 raise error.Abort(_('cannot use --parent on non-merge changeset'))
639 parent = p1
639 parent = p1
640
640
641 # the backout should appear on the same branch
641 # the backout should appear on the same branch
642 branch = repo.dirstate.branch()
642 branch = repo.dirstate.branch()
643 bheads = repo.branchheads(branch)
643 bheads = repo.branchheads(branch)
644 rctx = scmutil.revsingle(repo, hex(parent))
644 rctx = scmutil.revsingle(repo, hex(parent))
645 if not opts.get('merge') and op1 != node:
645 if not opts.get('merge') and op1 != node:
646 with dirstateguard.dirstateguard(repo, 'backout'):
646 with dirstateguard.dirstateguard(repo, 'backout'):
647 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
647 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
648 with ui.configoverride(overrides, 'backout'):
648 with ui.configoverride(overrides, 'backout'):
649 stats = mergemod.update(repo, parent, branchmerge=True,
649 stats = mergemod.update(repo, parent, branchmerge=True,
650 force=True, ancestor=node,
650 force=True, ancestor=node,
651 mergeancestor=False)
651 mergeancestor=False)
652 repo.setparents(op1, op2)
652 repo.setparents(op1, op2)
653 hg._showstats(repo, stats)
653 hg._showstats(repo, stats)
654 if stats.unresolvedcount:
654 if stats.unresolvedcount:
655 repo.ui.status(_("use 'hg resolve' to retry unresolved "
655 repo.ui.status(_("use 'hg resolve' to retry unresolved "
656 "file merges\n"))
656 "file merges\n"))
657 return 1
657 return 1
658 else:
658 else:
659 hg.clean(repo, node, show_stats=False)
659 hg.clean(repo, node, show_stats=False)
660 repo.dirstate.setbranch(branch)
660 repo.dirstate.setbranch(branch)
661 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
661 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
662
662
663 if opts.get('no_commit'):
663 if opts.get('no_commit'):
664 msg = _("changeset %s backed out, "
664 msg = _("changeset %s backed out, "
665 "don't forget to commit.\n")
665 "don't forget to commit.\n")
666 ui.status(msg % short(node))
666 ui.status(msg % short(node))
667 return 0
667 return 0
668
668
669 def commitfunc(ui, repo, message, match, opts):
669 def commitfunc(ui, repo, message, match, opts):
670 editform = 'backout'
670 editform = 'backout'
671 e = cmdutil.getcommiteditor(editform=editform,
671 e = cmdutil.getcommiteditor(editform=editform,
672 **pycompat.strkwargs(opts))
672 **pycompat.strkwargs(opts))
673 if not message:
673 if not message:
674 # we don't translate commit messages
674 # we don't translate commit messages
675 message = "Backed out changeset %s" % short(node)
675 message = "Backed out changeset %s" % short(node)
676 e = cmdutil.getcommiteditor(edit=True, editform=editform)
676 e = cmdutil.getcommiteditor(edit=True, editform=editform)
677 return repo.commit(message, opts.get('user'), opts.get('date'),
677 return repo.commit(message, opts.get('user'), opts.get('date'),
678 match, editor=e)
678 match, editor=e)
679 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
679 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
680 if not newnode:
680 if not newnode:
681 ui.status(_("nothing changed\n"))
681 ui.status(_("nothing changed\n"))
682 return 1
682 return 1
683 cmdutil.commitstatus(repo, newnode, branch, bheads)
683 cmdutil.commitstatus(repo, newnode, branch, bheads)
684
684
685 def nice(node):
685 def nice(node):
686 return '%d:%s' % (repo.changelog.rev(node), short(node))
686 return '%d:%s' % (repo.changelog.rev(node), short(node))
687 ui.status(_('changeset %s backs out changeset %s\n') %
687 ui.status(_('changeset %s backs out changeset %s\n') %
688 (nice(repo.changelog.tip()), nice(node)))
688 (nice(repo.changelog.tip()), nice(node)))
689 if opts.get('merge') and op1 != node:
689 if opts.get('merge') and op1 != node:
690 hg.clean(repo, op1, show_stats=False)
690 hg.clean(repo, op1, show_stats=False)
691 ui.status(_('merging with changeset %s\n')
691 ui.status(_('merging with changeset %s\n')
692 % nice(repo.changelog.tip()))
692 % nice(repo.changelog.tip()))
693 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
693 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
694 with ui.configoverride(overrides, 'backout'):
694 with ui.configoverride(overrides, 'backout'):
695 return hg.merge(repo, hex(repo.changelog.tip()))
695 return hg.merge(repo, hex(repo.changelog.tip()))
696 return 0
696 return 0
697
697
698 @command('bisect',
698 @command('bisect',
699 [('r', 'reset', False, _('reset bisect state')),
699 [('r', 'reset', False, _('reset bisect state')),
700 ('g', 'good', False, _('mark changeset good')),
700 ('g', 'good', False, _('mark changeset good')),
701 ('b', 'bad', False, _('mark changeset bad')),
701 ('b', 'bad', False, _('mark changeset bad')),
702 ('s', 'skip', False, _('skip testing changeset')),
702 ('s', 'skip', False, _('skip testing changeset')),
703 ('e', 'extend', False, _('extend the bisect range')),
703 ('e', 'extend', False, _('extend the bisect range')),
704 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
704 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
705 ('U', 'noupdate', False, _('do not update to target'))],
705 ('U', 'noupdate', False, _('do not update to target'))],
706 _("[-gbsr] [-U] [-c CMD] [REV]"),
706 _("[-gbsr] [-U] [-c CMD] [REV]"),
707 helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
707 helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
708 def bisect(ui, repo, rev=None, extra=None, command=None,
708 def bisect(ui, repo, rev=None, extra=None, command=None,
709 reset=None, good=None, bad=None, skip=None, extend=None,
709 reset=None, good=None, bad=None, skip=None, extend=None,
710 noupdate=None):
710 noupdate=None):
711 """subdivision search of changesets
711 """subdivision search of changesets
712
712
713 This command helps to find changesets which introduce problems. To
713 This command helps to find changesets which introduce problems. To
714 use, mark the earliest changeset you know exhibits the problem as
714 use, mark the earliest changeset you know exhibits the problem as
715 bad, then mark the latest changeset which is free from the problem
715 bad, then mark the latest changeset which is free from the problem
716 as good. Bisect will update your working directory to a revision
716 as good. Bisect will update your working directory to a revision
717 for testing (unless the -U/--noupdate option is specified). Once
717 for testing (unless the -U/--noupdate option is specified). Once
718 you have performed tests, mark the working directory as good or
718 you have performed tests, mark the working directory as good or
719 bad, and bisect will either update to another candidate changeset
719 bad, and bisect will either update to another candidate changeset
720 or announce that it has found the bad revision.
720 or announce that it has found the bad revision.
721
721
722 As a shortcut, you can also use the revision argument to mark a
722 As a shortcut, you can also use the revision argument to mark a
723 revision as good or bad without checking it out first.
723 revision as good or bad without checking it out first.
724
724
725 If you supply a command, it will be used for automatic bisection.
725 If you supply a command, it will be used for automatic bisection.
726 The environment variable HG_NODE will contain the ID of the
726 The environment variable HG_NODE will contain the ID of the
727 changeset being tested. The exit status of the command will be
727 changeset being tested. The exit status of the command will be
728 used to mark revisions as good or bad: status 0 means good, 125
728 used to mark revisions as good or bad: status 0 means good, 125
729 means to skip the revision, 127 (command not found) will abort the
729 means to skip the revision, 127 (command not found) will abort the
730 bisection, and any other non-zero exit status means the revision
730 bisection, and any other non-zero exit status means the revision
731 is bad.
731 is bad.
732
732
733 .. container:: verbose
733 .. container:: verbose
734
734
735 Some examples:
735 Some examples:
736
736
737 - start a bisection with known bad revision 34, and good revision 12::
737 - start a bisection with known bad revision 34, and good revision 12::
738
738
739 hg bisect --bad 34
739 hg bisect --bad 34
740 hg bisect --good 12
740 hg bisect --good 12
741
741
742 - advance the current bisection by marking current revision as good or
742 - advance the current bisection by marking current revision as good or
743 bad::
743 bad::
744
744
745 hg bisect --good
745 hg bisect --good
746 hg bisect --bad
746 hg bisect --bad
747
747
748 - mark the current revision, or a known revision, to be skipped (e.g. if
748 - mark the current revision, or a known revision, to be skipped (e.g. if
749 that revision is not usable because of another issue)::
749 that revision is not usable because of another issue)::
750
750
751 hg bisect --skip
751 hg bisect --skip
752 hg bisect --skip 23
752 hg bisect --skip 23
753
753
754 - skip all revisions that do not touch directories ``foo`` or ``bar``::
754 - skip all revisions that do not touch directories ``foo`` or ``bar``::
755
755
756 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
756 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
757
757
758 - forget the current bisection::
758 - forget the current bisection::
759
759
760 hg bisect --reset
760 hg bisect --reset
761
761
762 - use 'make && make tests' to automatically find the first broken
762 - use 'make && make tests' to automatically find the first broken
763 revision::
763 revision::
764
764
765 hg bisect --reset
765 hg bisect --reset
766 hg bisect --bad 34
766 hg bisect --bad 34
767 hg bisect --good 12
767 hg bisect --good 12
768 hg bisect --command "make && make tests"
768 hg bisect --command "make && make tests"
769
769
770 - see all changesets whose states are already known in the current
770 - see all changesets whose states are already known in the current
771 bisection::
771 bisection::
772
772
773 hg log -r "bisect(pruned)"
773 hg log -r "bisect(pruned)"
774
774
775 - see the changeset currently being bisected (especially useful
775 - see the changeset currently being bisected (especially useful
776 if running with -U/--noupdate)::
776 if running with -U/--noupdate)::
777
777
778 hg log -r "bisect(current)"
778 hg log -r "bisect(current)"
779
779
780 - see all changesets that took part in the current bisection::
780 - see all changesets that took part in the current bisection::
781
781
782 hg log -r "bisect(range)"
782 hg log -r "bisect(range)"
783
783
784 - you can even get a nice graph::
784 - you can even get a nice graph::
785
785
786 hg log --graph -r "bisect(range)"
786 hg log --graph -r "bisect(range)"
787
787
788 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
788 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
789
789
790 Returns 0 on success.
790 Returns 0 on success.
791 """
791 """
792 # backward compatibility
792 # backward compatibility
793 if rev in "good bad reset init".split():
793 if rev in "good bad reset init".split():
794 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
794 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
795 cmd, rev, extra = rev, extra, None
795 cmd, rev, extra = rev, extra, None
796 if cmd == "good":
796 if cmd == "good":
797 good = True
797 good = True
798 elif cmd == "bad":
798 elif cmd == "bad":
799 bad = True
799 bad = True
800 else:
800 else:
801 reset = True
801 reset = True
802 elif extra:
802 elif extra:
803 raise error.Abort(_('incompatible arguments'))
803 raise error.Abort(_('incompatible arguments'))
804
804
805 incompatibles = {
805 incompatibles = {
806 '--bad': bad,
806 '--bad': bad,
807 '--command': bool(command),
807 '--command': bool(command),
808 '--extend': extend,
808 '--extend': extend,
809 '--good': good,
809 '--good': good,
810 '--reset': reset,
810 '--reset': reset,
811 '--skip': skip,
811 '--skip': skip,
812 }
812 }
813
813
814 enabled = [x for x in incompatibles if incompatibles[x]]
814 enabled = [x for x in incompatibles if incompatibles[x]]
815
815
816 if len(enabled) > 1:
816 if len(enabled) > 1:
817 raise error.Abort(_('%s and %s are incompatible') %
817 raise error.Abort(_('%s and %s are incompatible') %
818 tuple(sorted(enabled)[0:2]))
818 tuple(sorted(enabled)[0:2]))
819
819
820 if reset:
820 if reset:
821 hbisect.resetstate(repo)
821 hbisect.resetstate(repo)
822 return
822 return
823
823
824 state = hbisect.load_state(repo)
824 state = hbisect.load_state(repo)
825
825
826 # update state
826 # update state
827 if good or bad or skip:
827 if good or bad or skip:
828 if rev:
828 if rev:
829 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
829 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
830 else:
830 else:
831 nodes = [repo.lookup('.')]
831 nodes = [repo.lookup('.')]
832 if good:
832 if good:
833 state['good'] += nodes
833 state['good'] += nodes
834 elif bad:
834 elif bad:
835 state['bad'] += nodes
835 state['bad'] += nodes
836 elif skip:
836 elif skip:
837 state['skip'] += nodes
837 state['skip'] += nodes
838 hbisect.save_state(repo, state)
838 hbisect.save_state(repo, state)
839 if not (state['good'] and state['bad']):
839 if not (state['good'] and state['bad']):
840 return
840 return
841
841
842 def mayupdate(repo, node, show_stats=True):
842 def mayupdate(repo, node, show_stats=True):
843 """common used update sequence"""
843 """common used update sequence"""
844 if noupdate:
844 if noupdate:
845 return
845 return
846 cmdutil.checkunfinished(repo)
846 cmdutil.checkunfinished(repo)
847 cmdutil.bailifchanged(repo)
847 cmdutil.bailifchanged(repo)
848 return hg.clean(repo, node, show_stats=show_stats)
848 return hg.clean(repo, node, show_stats=show_stats)
849
849
850 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
850 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
851
851
852 if command:
852 if command:
853 changesets = 1
853 changesets = 1
854 if noupdate:
854 if noupdate:
855 try:
855 try:
856 node = state['current'][0]
856 node = state['current'][0]
857 except LookupError:
857 except LookupError:
858 raise error.Abort(_('current bisect revision is unknown - '
858 raise error.Abort(_('current bisect revision is unknown - '
859 'start a new bisect to fix'))
859 'start a new bisect to fix'))
860 else:
860 else:
861 node, p2 = repo.dirstate.parents()
861 node, p2 = repo.dirstate.parents()
862 if p2 != nullid:
862 if p2 != nullid:
863 raise error.Abort(_('current bisect revision is a merge'))
863 raise error.Abort(_('current bisect revision is a merge'))
864 if rev:
864 if rev:
865 node = repo[scmutil.revsingle(repo, rev, node)].node()
865 node = repo[scmutil.revsingle(repo, rev, node)].node()
866 try:
866 try:
867 while changesets:
867 while changesets:
868 # update state
868 # update state
869 state['current'] = [node]
869 state['current'] = [node]
870 hbisect.save_state(repo, state)
870 hbisect.save_state(repo, state)
871 status = ui.system(command, environ={'HG_NODE': hex(node)},
871 status = ui.system(command, environ={'HG_NODE': hex(node)},
872 blockedtag='bisect_check')
872 blockedtag='bisect_check')
873 if status == 125:
873 if status == 125:
874 transition = "skip"
874 transition = "skip"
875 elif status == 0:
875 elif status == 0:
876 transition = "good"
876 transition = "good"
877 # status < 0 means process was killed
877 # status < 0 means process was killed
878 elif status == 127:
878 elif status == 127:
879 raise error.Abort(_("failed to execute %s") % command)
879 raise error.Abort(_("failed to execute %s") % command)
880 elif status < 0:
880 elif status < 0:
881 raise error.Abort(_("%s killed") % command)
881 raise error.Abort(_("%s killed") % command)
882 else:
882 else:
883 transition = "bad"
883 transition = "bad"
884 state[transition].append(node)
884 state[transition].append(node)
885 ctx = repo[node]
885 ctx = repo[node]
886 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
886 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
887 transition))
887 transition))
888 hbisect.checkstate(state)
888 hbisect.checkstate(state)
889 # bisect
889 # bisect
890 nodes, changesets, bgood = hbisect.bisect(repo, state)
890 nodes, changesets, bgood = hbisect.bisect(repo, state)
891 # update to next check
891 # update to next check
892 node = nodes[0]
892 node = nodes[0]
893 mayupdate(repo, node, show_stats=False)
893 mayupdate(repo, node, show_stats=False)
894 finally:
894 finally:
895 state['current'] = [node]
895 state['current'] = [node]
896 hbisect.save_state(repo, state)
896 hbisect.save_state(repo, state)
897 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
897 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
898 return
898 return
899
899
900 hbisect.checkstate(state)
900 hbisect.checkstate(state)
901
901
902 # actually bisect
902 # actually bisect
903 nodes, changesets, good = hbisect.bisect(repo, state)
903 nodes, changesets, good = hbisect.bisect(repo, state)
904 if extend:
904 if extend:
905 if not changesets:
905 if not changesets:
906 extendnode = hbisect.extendrange(repo, state, nodes, good)
906 extendnode = hbisect.extendrange(repo, state, nodes, good)
907 if extendnode is not None:
907 if extendnode is not None:
908 ui.write(_("Extending search to changeset %d:%s\n")
908 ui.write(_("Extending search to changeset %d:%s\n")
909 % (extendnode.rev(), extendnode))
909 % (extendnode.rev(), extendnode))
910 state['current'] = [extendnode.node()]
910 state['current'] = [extendnode.node()]
911 hbisect.save_state(repo, state)
911 hbisect.save_state(repo, state)
912 return mayupdate(repo, extendnode.node())
912 return mayupdate(repo, extendnode.node())
913 raise error.Abort(_("nothing to extend"))
913 raise error.Abort(_("nothing to extend"))
914
914
915 if changesets == 0:
915 if changesets == 0:
916 hbisect.printresult(ui, repo, state, displayer, nodes, good)
916 hbisect.printresult(ui, repo, state, displayer, nodes, good)
917 else:
917 else:
918 assert len(nodes) == 1 # only a single node can be tested next
918 assert len(nodes) == 1 # only a single node can be tested next
919 node = nodes[0]
919 node = nodes[0]
920 # compute the approximate number of remaining tests
920 # compute the approximate number of remaining tests
921 tests, size = 0, 2
921 tests, size = 0, 2
922 while size <= changesets:
922 while size <= changesets:
923 tests, size = tests + 1, size * 2
923 tests, size = tests + 1, size * 2
924 rev = repo.changelog.rev(node)
924 rev = repo.changelog.rev(node)
925 ui.write(_("Testing changeset %d:%s "
925 ui.write(_("Testing changeset %d:%s "
926 "(%d changesets remaining, ~%d tests)\n")
926 "(%d changesets remaining, ~%d tests)\n")
927 % (rev, short(node), changesets, tests))
927 % (rev, short(node), changesets, tests))
928 state['current'] = [node]
928 state['current'] = [node]
929 hbisect.save_state(repo, state)
929 hbisect.save_state(repo, state)
930 return mayupdate(repo, node)
930 return mayupdate(repo, node)
931
931
932 @command('bookmarks|bookmark',
932 @command('bookmarks|bookmark',
933 [('f', 'force', False, _('force')),
933 [('f', 'force', False, _('force')),
934 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
934 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
935 ('d', 'delete', False, _('delete a given bookmark')),
935 ('d', 'delete', False, _('delete a given bookmark')),
936 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
936 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
937 ('i', 'inactive', False, _('mark a bookmark inactive')),
937 ('i', 'inactive', False, _('mark a bookmark inactive')),
938 ('l', 'list', False, _('list existing bookmarks')),
938 ('l', 'list', False, _('list existing bookmarks')),
939 ] + formatteropts,
939 ] + formatteropts,
940 _('hg bookmarks [OPTIONS]... [NAME]...'),
940 _('hg bookmarks [OPTIONS]... [NAME]...'),
941 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
941 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
942 def bookmark(ui, repo, *names, **opts):
942 def bookmark(ui, repo, *names, **opts):
943 '''create a new bookmark or list existing bookmarks
943 '''create a new bookmark or list existing bookmarks
944
944
945 Bookmarks are labels on changesets to help track lines of development.
945 Bookmarks are labels on changesets to help track lines of development.
946 Bookmarks are unversioned and can be moved, renamed and deleted.
946 Bookmarks are unversioned and can be moved, renamed and deleted.
947 Deleting or moving a bookmark has no effect on the associated changesets.
947 Deleting or moving a bookmark has no effect on the associated changesets.
948
948
949 Creating or updating to a bookmark causes it to be marked as 'active'.
949 Creating or updating to a bookmark causes it to be marked as 'active'.
950 The active bookmark is indicated with a '*'.
950 The active bookmark is indicated with a '*'.
951 When a commit is made, the active bookmark will advance to the new commit.
951 When a commit is made, the active bookmark will advance to the new commit.
952 A plain :hg:`update` will also advance an active bookmark, if possible.
952 A plain :hg:`update` will also advance an active bookmark, if possible.
953 Updating away from a bookmark will cause it to be deactivated.
953 Updating away from a bookmark will cause it to be deactivated.
954
954
955 Bookmarks can be pushed and pulled between repositories (see
955 Bookmarks can be pushed and pulled between repositories (see
956 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
956 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
957 diverged, a new 'divergent bookmark' of the form 'name@path' will
957 diverged, a new 'divergent bookmark' of the form 'name@path' will
958 be created. Using :hg:`merge` will resolve the divergence.
958 be created. Using :hg:`merge` will resolve the divergence.
959
959
960 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
960 Specifying bookmark as '.' to -m/-d/-l options is equivalent to specifying
961 the active bookmark's name.
961 the active bookmark's name.
962
962
963 A bookmark named '@' has the special property that :hg:`clone` will
963 A bookmark named '@' has the special property that :hg:`clone` will
964 check it out by default if it exists.
964 check it out by default if it exists.
965
965
966 .. container:: verbose
966 .. container:: verbose
967
967
968 Template:
968 Template:
969
969
970 The following keywords are supported in addition to the common template
970 The following keywords are supported in addition to the common template
971 keywords and functions such as ``{bookmark}``. See also
971 keywords and functions such as ``{bookmark}``. See also
972 :hg:`help templates`.
972 :hg:`help templates`.
973
973
974 :active: Boolean. True if the bookmark is active.
974 :active: Boolean. True if the bookmark is active.
975
975
976 Examples:
976 Examples:
977
977
978 - create an active bookmark for a new line of development::
978 - create an active bookmark for a new line of development::
979
979
980 hg book new-feature
980 hg book new-feature
981
981
982 - create an inactive bookmark as a place marker::
982 - create an inactive bookmark as a place marker::
983
983
984 hg book -i reviewed
984 hg book -i reviewed
985
985
986 - create an inactive bookmark on another changeset::
986 - create an inactive bookmark on another changeset::
987
987
988 hg book -r .^ tested
988 hg book -r .^ tested
989
989
990 - rename bookmark turkey to dinner::
990 - rename bookmark turkey to dinner::
991
991
992 hg book -m turkey dinner
992 hg book -m turkey dinner
993
993
994 - move the '@' bookmark from another branch::
994 - move the '@' bookmark from another branch::
995
995
996 hg book -f @
996 hg book -f @
997
997
998 - print only the active bookmark name::
998 - print only the active bookmark name::
999
999
1000 hg book -ql .
1000 hg book -ql .
1001 '''
1001 '''
1002 opts = pycompat.byteskwargs(opts)
1002 opts = pycompat.byteskwargs(opts)
1003 force = opts.get('force')
1003 force = opts.get('force')
1004 rev = opts.get('rev')
1004 rev = opts.get('rev')
1005 inactive = opts.get('inactive') # meaning add/rename to inactive bookmark
1005 inactive = opts.get('inactive') # meaning add/rename to inactive bookmark
1006
1006
1007 selactions = [k for k in ['delete', 'rename', 'list'] if opts.get(k)]
1007 selactions = [k for k in ['delete', 'rename', 'list'] if opts.get(k)]
1008 if len(selactions) > 1:
1008 if len(selactions) > 1:
1009 raise error.Abort(_('--%s and --%s are incompatible')
1009 raise error.Abort(_('--%s and --%s are incompatible')
1010 % tuple(selactions[:2]))
1010 % tuple(selactions[:2]))
1011 if selactions:
1011 if selactions:
1012 action = selactions[0]
1012 action = selactions[0]
1013 elif names or rev:
1013 elif names or rev:
1014 action = 'add'
1014 action = 'add'
1015 elif inactive:
1015 elif inactive:
1016 action = 'inactive' # meaning deactivate
1016 action = 'inactive' # meaning deactivate
1017 else:
1017 else:
1018 action = 'list'
1018 action = 'list'
1019
1019
1020 if rev and action in {'delete', 'rename', 'list'}:
1020 if rev and action in {'delete', 'rename', 'list'}:
1021 raise error.Abort(_("--rev is incompatible with --%s") % action)
1021 raise error.Abort(_("--rev is incompatible with --%s") % action)
1022 if inactive and action in {'delete', 'list'}:
1022 if inactive and action in {'delete', 'list'}:
1023 raise error.Abort(_("--inactive is incompatible with --%s") % action)
1023 raise error.Abort(_("--inactive is incompatible with --%s") % action)
1024 if not names and action in {'add', 'delete'}:
1024 if not names and action in {'add', 'delete'}:
1025 raise error.Abort(_("bookmark name required"))
1025 raise error.Abort(_("bookmark name required"))
1026
1026
1027 if action in {'add', 'delete', 'rename', 'inactive'}:
1027 if action in {'add', 'delete', 'rename', 'inactive'}:
1028 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
1028 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
1029 if action == 'delete':
1029 if action == 'delete':
1030 names = pycompat.maplist(repo._bookmarks.expandname, names)
1030 names = pycompat.maplist(repo._bookmarks.expandname, names)
1031 bookmarks.delete(repo, tr, names)
1031 bookmarks.delete(repo, tr, names)
1032 elif action == 'rename':
1032 elif action == 'rename':
1033 if not names:
1033 if not names:
1034 raise error.Abort(_("new bookmark name required"))
1034 raise error.Abort(_("new bookmark name required"))
1035 elif len(names) > 1:
1035 elif len(names) > 1:
1036 raise error.Abort(_("only one new bookmark name allowed"))
1036 raise error.Abort(_("only one new bookmark name allowed"))
1037 oldname = repo._bookmarks.expandname(opts['rename'])
1037 oldname = repo._bookmarks.expandname(opts['rename'])
1038 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1038 bookmarks.rename(repo, tr, oldname, names[0], force, inactive)
1039 elif action == 'add':
1039 elif action == 'add':
1040 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1040 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
1041 elif action == 'inactive':
1041 elif action == 'inactive':
1042 if len(repo._bookmarks) == 0:
1042 if len(repo._bookmarks) == 0:
1043 ui.status(_("no bookmarks set\n"))
1043 ui.status(_("no bookmarks set\n"))
1044 elif not repo._activebookmark:
1044 elif not repo._activebookmark:
1045 ui.status(_("no active bookmark\n"))
1045 ui.status(_("no active bookmark\n"))
1046 else:
1046 else:
1047 bookmarks.deactivate(repo)
1047 bookmarks.deactivate(repo)
1048 elif action == 'list':
1048 elif action == 'list':
1049 names = pycompat.maplist(repo._bookmarks.expandname, names)
1049 names = pycompat.maplist(repo._bookmarks.expandname, names)
1050 with ui.formatter('bookmarks', opts) as fm:
1050 with ui.formatter('bookmarks', opts) as fm:
1051 bookmarks.printbookmarks(ui, repo, fm, names)
1051 bookmarks.printbookmarks(ui, repo, fm, names)
1052 else:
1052 else:
1053 raise error.ProgrammingError('invalid action: %s' % action)
1053 raise error.ProgrammingError('invalid action: %s' % action)
1054
1054
1055 @command('branch',
1055 @command('branch',
1056 [('f', 'force', None,
1056 [('f', 'force', None,
1057 _('set branch name even if it shadows an existing branch')),
1057 _('set branch name even if it shadows an existing branch')),
1058 ('C', 'clean', None, _('reset branch name to parent branch name')),
1058 ('C', 'clean', None, _('reset branch name to parent branch name')),
1059 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1059 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1060 ],
1060 ],
1061 _('[-fC] [NAME]'),
1061 _('[-fC] [NAME]'),
1062 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
1062 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
1063 def branch(ui, repo, label=None, **opts):
1063 def branch(ui, repo, label=None, **opts):
1064 """set or show the current branch name
1064 """set or show the current branch name
1065
1065
1066 .. note::
1066 .. note::
1067
1067
1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1069 light-weight bookmark instead. See :hg:`help glossary` for more
1069 light-weight bookmark instead. See :hg:`help glossary` for more
1070 information about named branches and bookmarks.
1070 information about named branches and bookmarks.
1071
1071
1072 With no argument, show the current branch name. With one argument,
1072 With no argument, show the current branch name. With one argument,
1073 set the working directory branch name (the branch will not exist
1073 set the working directory branch name (the branch will not exist
1074 in the repository until the next commit). Standard practice
1074 in the repository until the next commit). Standard practice
1075 recommends that primary development take place on the 'default'
1075 recommends that primary development take place on the 'default'
1076 branch.
1076 branch.
1077
1077
1078 Unless -f/--force is specified, branch will not let you set a
1078 Unless -f/--force is specified, branch will not let you set a
1079 branch name that already exists.
1079 branch name that already exists.
1080
1080
1081 Use -C/--clean to reset the working directory branch to that of
1081 Use -C/--clean to reset the working directory branch to that of
1082 the parent of the working directory, negating a previous branch
1082 the parent of the working directory, negating a previous branch
1083 change.
1083 change.
1084
1084
1085 Use the command :hg:`update` to switch to an existing branch. Use
1085 Use the command :hg:`update` to switch to an existing branch. Use
1086 :hg:`commit --close-branch` to mark this branch head as closed.
1086 :hg:`commit --close-branch` to mark this branch head as closed.
1087 When all heads of a branch are closed, the branch will be
1087 When all heads of a branch are closed, the branch will be
1088 considered closed.
1088 considered closed.
1089
1089
1090 Returns 0 on success.
1090 Returns 0 on success.
1091 """
1091 """
1092 opts = pycompat.byteskwargs(opts)
1092 opts = pycompat.byteskwargs(opts)
1093 revs = opts.get('rev')
1093 revs = opts.get('rev')
1094 if label:
1094 if label:
1095 label = label.strip()
1095 label = label.strip()
1096
1096
1097 if not opts.get('clean') and not label:
1097 if not opts.get('clean') and not label:
1098 if revs:
1098 if revs:
1099 raise error.Abort(_("no branch name specified for the revisions"))
1099 raise error.Abort(_("no branch name specified for the revisions"))
1100 ui.write("%s\n" % repo.dirstate.branch())
1100 ui.write("%s\n" % repo.dirstate.branch())
1101 return
1101 return
1102
1102
1103 with repo.wlock():
1103 with repo.wlock():
1104 if opts.get('clean'):
1104 if opts.get('clean'):
1105 label = repo[None].p1().branch()
1105 label = repo[None].p1().branch()
1106 repo.dirstate.setbranch(label)
1106 repo.dirstate.setbranch(label)
1107 ui.status(_('reset working directory to branch %s\n') % label)
1107 ui.status(_('reset working directory to branch %s\n') % label)
1108 elif label:
1108 elif label:
1109
1109
1110 scmutil.checknewlabel(repo, label, 'branch')
1110 scmutil.checknewlabel(repo, label, 'branch')
1111 if revs:
1111 if revs:
1112 return cmdutil.changebranch(ui, repo, revs, label)
1112 return cmdutil.changebranch(ui, repo, revs, label)
1113
1113
1114 if not opts.get('force') and label in repo.branchmap():
1114 if not opts.get('force') and label in repo.branchmap():
1115 if label not in [p.branch() for p in repo[None].parents()]:
1115 if label not in [p.branch() for p in repo[None].parents()]:
1116 raise error.Abort(_('a branch of the same name already'
1116 raise error.Abort(_('a branch of the same name already'
1117 ' exists'),
1117 ' exists'),
1118 # i18n: "it" refers to an existing branch
1118 # i18n: "it" refers to an existing branch
1119 hint=_("use 'hg update' to switch to it"))
1119 hint=_("use 'hg update' to switch to it"))
1120
1120
1121 repo.dirstate.setbranch(label)
1121 repo.dirstate.setbranch(label)
1122 ui.status(_('marked working directory as branch %s\n') % label)
1122 ui.status(_('marked working directory as branch %s\n') % label)
1123
1123
1124 # find any open named branches aside from default
1124 # find any open named branches aside from default
1125 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1125 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1126 if n != "default" and not c]
1126 if n != "default" and not c]
1127 if not others:
1127 if not others:
1128 ui.status(_('(branches are permanent and global, '
1128 ui.status(_('(branches are permanent and global, '
1129 'did you want a bookmark?)\n'))
1129 'did you want a bookmark?)\n'))
1130
1130
1131 @command('branches',
1131 @command('branches',
1132 [('a', 'active', False,
1132 [('a', 'active', False,
1133 _('show only branches that have unmerged heads (DEPRECATED)')),
1133 _('show only branches that have unmerged heads (DEPRECATED)')),
1134 ('c', 'closed', False, _('show normal and closed branches')),
1134 ('c', 'closed', False, _('show normal and closed branches')),
1135 ('r', 'rev', [], _('show branch name(s) of the given rev'))
1135 ] + formatteropts,
1136 ] + formatteropts,
1136 _('[-c]'),
1137 _('[-c]'),
1137 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1138 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
1138 intents={INTENT_READONLY})
1139 intents={INTENT_READONLY})
1139 def branches(ui, repo, active=False, closed=False, **opts):
1140 def branches(ui, repo, active=False, closed=False, **opts):
1140 """list repository named branches
1141 """list repository named branches
1141
1142
1142 List the repository's named branches, indicating which ones are
1143 List the repository's named branches, indicating which ones are
1143 inactive. If -c/--closed is specified, also list branches which have
1144 inactive. If -c/--closed is specified, also list branches which have
1144 been marked closed (see :hg:`commit --close-branch`).
1145 been marked closed (see :hg:`commit --close-branch`).
1145
1146
1146 Use the command :hg:`update` to switch to an existing branch.
1147 Use the command :hg:`update` to switch to an existing branch.
1147
1148
1148 .. container:: verbose
1149 .. container:: verbose
1149
1150
1150 Template:
1151 Template:
1151
1152
1152 The following keywords are supported in addition to the common template
1153 The following keywords are supported in addition to the common template
1153 keywords and functions such as ``{branch}``. See also
1154 keywords and functions such as ``{branch}``. See also
1154 :hg:`help templates`.
1155 :hg:`help templates`.
1155
1156
1156 :active: Boolean. True if the branch is active.
1157 :active: Boolean. True if the branch is active.
1157 :closed: Boolean. True if the branch is closed.
1158 :closed: Boolean. True if the branch is closed.
1158 :current: Boolean. True if it is the current branch.
1159 :current: Boolean. True if it is the current branch.
1159
1160
1160 Returns 0.
1161 Returns 0.
1161 """
1162 """
1162
1163
1163 opts = pycompat.byteskwargs(opts)
1164 opts = pycompat.byteskwargs(opts)
1165 revs = opts.get('rev')
1166 selectedbranches = None
1167 if revs:
1168 revs = scmutil.revrange(repo, revs)
1169 getbi = repo.revbranchcache().branchinfo
1170 selectedbranches = {getbi(r)[0] for r in revs}
1171
1164 ui.pager('branches')
1172 ui.pager('branches')
1165 fm = ui.formatter('branches', opts)
1173 fm = ui.formatter('branches', opts)
1166 hexfunc = fm.hexfunc
1174 hexfunc = fm.hexfunc
1167
1175
1168 allheads = set(repo.heads())
1176 allheads = set(repo.heads())
1169 branches = []
1177 branches = []
1170 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1178 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1179 if selectedbranches is not None and tag not in selectedbranches:
1180 continue
1171 isactive = False
1181 isactive = False
1172 if not isclosed:
1182 if not isclosed:
1173 openheads = set(repo.branchmap().iteropen(heads))
1183 openheads = set(repo.branchmap().iteropen(heads))
1174 isactive = bool(openheads & allheads)
1184 isactive = bool(openheads & allheads)
1175 branches.append((tag, repo[tip], isactive, not isclosed))
1185 branches.append((tag, repo[tip], isactive, not isclosed))
1176 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1186 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1177 reverse=True)
1187 reverse=True)
1178
1188
1179 for tag, ctx, isactive, isopen in branches:
1189 for tag, ctx, isactive, isopen in branches:
1180 if active and not isactive:
1190 if active and not isactive:
1181 continue
1191 continue
1182 if isactive:
1192 if isactive:
1183 label = 'branches.active'
1193 label = 'branches.active'
1184 notice = ''
1194 notice = ''
1185 elif not isopen:
1195 elif not isopen:
1186 if not closed:
1196 if not closed:
1187 continue
1197 continue
1188 label = 'branches.closed'
1198 label = 'branches.closed'
1189 notice = _(' (closed)')
1199 notice = _(' (closed)')
1190 else:
1200 else:
1191 label = 'branches.inactive'
1201 label = 'branches.inactive'
1192 notice = _(' (inactive)')
1202 notice = _(' (inactive)')
1193 current = (tag == repo.dirstate.branch())
1203 current = (tag == repo.dirstate.branch())
1194 if current:
1204 if current:
1195 label = 'branches.current'
1205 label = 'branches.current'
1196
1206
1197 fm.startitem()
1207 fm.startitem()
1198 fm.write('branch', '%s', tag, label=label)
1208 fm.write('branch', '%s', tag, label=label)
1199 rev = ctx.rev()
1209 rev = ctx.rev()
1200 padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0)
1210 padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0)
1201 fmt = ' ' * padsize + ' %d:%s'
1211 fmt = ' ' * padsize + ' %d:%s'
1202 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1212 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1203 label='log.changeset changeset.%s' % ctx.phasestr())
1213 label='log.changeset changeset.%s' % ctx.phasestr())
1204 fm.context(ctx=ctx)
1214 fm.context(ctx=ctx)
1205 fm.data(active=isactive, closed=not isopen, current=current)
1215 fm.data(active=isactive, closed=not isopen, current=current)
1206 if not ui.quiet:
1216 if not ui.quiet:
1207 fm.plain(notice)
1217 fm.plain(notice)
1208 fm.plain('\n')
1218 fm.plain('\n')
1209 fm.end()
1219 fm.end()
1210
1220
1211 @command('bundle',
1221 @command('bundle',
1212 [('f', 'force', None, _('run even when the destination is unrelated')),
1222 [('f', 'force', None, _('run even when the destination is unrelated')),
1213 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1223 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1214 _('REV')),
1224 _('REV')),
1215 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1225 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1216 _('BRANCH')),
1226 _('BRANCH')),
1217 ('', 'base', [],
1227 ('', 'base', [],
1218 _('a base changeset assumed to be available at the destination'),
1228 _('a base changeset assumed to be available at the destination'),
1219 _('REV')),
1229 _('REV')),
1220 ('a', 'all', None, _('bundle all changesets in the repository')),
1230 ('a', 'all', None, _('bundle all changesets in the repository')),
1221 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1231 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1222 ] + remoteopts,
1232 ] + remoteopts,
1223 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1233 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
1224 helpcategory=command.CATEGORY_IMPORT_EXPORT)
1234 helpcategory=command.CATEGORY_IMPORT_EXPORT)
1225 def bundle(ui, repo, fname, dest=None, **opts):
1235 def bundle(ui, repo, fname, dest=None, **opts):
1226 """create a bundle file
1236 """create a bundle file
1227
1237
1228 Generate a bundle file containing data to be transferred to another
1238 Generate a bundle file containing data to be transferred to another
1229 repository.
1239 repository.
1230
1240
1231 To create a bundle containing all changesets, use -a/--all
1241 To create a bundle containing all changesets, use -a/--all
1232 (or --base null). Otherwise, hg assumes the destination will have
1242 (or --base null). Otherwise, hg assumes the destination will have
1233 all the nodes you specify with --base parameters. Otherwise, hg
1243 all the nodes you specify with --base parameters. Otherwise, hg
1234 will assume the repository has all the nodes in destination, or
1244 will assume the repository has all the nodes in destination, or
1235 default-push/default if no destination is specified, where destination
1245 default-push/default if no destination is specified, where destination
1236 is the repository you provide through DEST option.
1246 is the repository you provide through DEST option.
1237
1247
1238 You can change bundle format with the -t/--type option. See
1248 You can change bundle format with the -t/--type option. See
1239 :hg:`help bundlespec` for documentation on this format. By default,
1249 :hg:`help bundlespec` for documentation on this format. By default,
1240 the most appropriate format is used and compression defaults to
1250 the most appropriate format is used and compression defaults to
1241 bzip2.
1251 bzip2.
1242
1252
1243 The bundle file can then be transferred using conventional means
1253 The bundle file can then be transferred using conventional means
1244 and applied to another repository with the unbundle or pull
1254 and applied to another repository with the unbundle or pull
1245 command. This is useful when direct push and pull are not
1255 command. This is useful when direct push and pull are not
1246 available or when exporting an entire repository is undesirable.
1256 available or when exporting an entire repository is undesirable.
1247
1257
1248 Applying bundles preserves all changeset contents including
1258 Applying bundles preserves all changeset contents including
1249 permissions, copy/rename information, and revision history.
1259 permissions, copy/rename information, and revision history.
1250
1260
1251 Returns 0 on success, 1 if no changes found.
1261 Returns 0 on success, 1 if no changes found.
1252 """
1262 """
1253 opts = pycompat.byteskwargs(opts)
1263 opts = pycompat.byteskwargs(opts)
1254 revs = None
1264 revs = None
1255 if 'rev' in opts:
1265 if 'rev' in opts:
1256 revstrings = opts['rev']
1266 revstrings = opts['rev']
1257 revs = scmutil.revrange(repo, revstrings)
1267 revs = scmutil.revrange(repo, revstrings)
1258 if revstrings and not revs:
1268 if revstrings and not revs:
1259 raise error.Abort(_('no commits to bundle'))
1269 raise error.Abort(_('no commits to bundle'))
1260
1270
1261 bundletype = opts.get('type', 'bzip2').lower()
1271 bundletype = opts.get('type', 'bzip2').lower()
1262 try:
1272 try:
1263 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1273 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1264 except error.UnsupportedBundleSpecification as e:
1274 except error.UnsupportedBundleSpecification as e:
1265 raise error.Abort(pycompat.bytestr(e),
1275 raise error.Abort(pycompat.bytestr(e),
1266 hint=_("see 'hg help bundlespec' for supported "
1276 hint=_("see 'hg help bundlespec' for supported "
1267 "values for --type"))
1277 "values for --type"))
1268 cgversion = bundlespec.contentopts["cg.version"]
1278 cgversion = bundlespec.contentopts["cg.version"]
1269
1279
1270 # Packed bundles are a pseudo bundle format for now.
1280 # Packed bundles are a pseudo bundle format for now.
1271 if cgversion == 's1':
1281 if cgversion == 's1':
1272 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1282 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1273 hint=_("use 'hg debugcreatestreamclonebundle'"))
1283 hint=_("use 'hg debugcreatestreamclonebundle'"))
1274
1284
1275 if opts.get('all'):
1285 if opts.get('all'):
1276 if dest:
1286 if dest:
1277 raise error.Abort(_("--all is incompatible with specifying "
1287 raise error.Abort(_("--all is incompatible with specifying "
1278 "a destination"))
1288 "a destination"))
1279 if opts.get('base'):
1289 if opts.get('base'):
1280 ui.warn(_("ignoring --base because --all was specified\n"))
1290 ui.warn(_("ignoring --base because --all was specified\n"))
1281 base = [nullrev]
1291 base = [nullrev]
1282 else:
1292 else:
1283 base = scmutil.revrange(repo, opts.get('base'))
1293 base = scmutil.revrange(repo, opts.get('base'))
1284 if cgversion not in changegroup.supportedoutgoingversions(repo):
1294 if cgversion not in changegroup.supportedoutgoingversions(repo):
1285 raise error.Abort(_("repository does not support bundle version %s") %
1295 raise error.Abort(_("repository does not support bundle version %s") %
1286 cgversion)
1296 cgversion)
1287
1297
1288 if base:
1298 if base:
1289 if dest:
1299 if dest:
1290 raise error.Abort(_("--base is incompatible with specifying "
1300 raise error.Abort(_("--base is incompatible with specifying "
1291 "a destination"))
1301 "a destination"))
1292 common = [repo[rev].node() for rev in base]
1302 common = [repo[rev].node() for rev in base]
1293 heads = [repo[r].node() for r in revs] if revs else None
1303 heads = [repo[r].node() for r in revs] if revs else None
1294 outgoing = discovery.outgoing(repo, common, heads)
1304 outgoing = discovery.outgoing(repo, common, heads)
1295 else:
1305 else:
1296 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1306 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1297 dest, branches = hg.parseurl(dest, opts.get('branch'))
1307 dest, branches = hg.parseurl(dest, opts.get('branch'))
1298 other = hg.peer(repo, opts, dest)
1308 other = hg.peer(repo, opts, dest)
1299 revs = [repo[r].hex() for r in revs]
1309 revs = [repo[r].hex() for r in revs]
1300 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1310 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1301 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1311 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1302 outgoing = discovery.findcommonoutgoing(repo, other,
1312 outgoing = discovery.findcommonoutgoing(repo, other,
1303 onlyheads=heads,
1313 onlyheads=heads,
1304 force=opts.get('force'),
1314 force=opts.get('force'),
1305 portable=True)
1315 portable=True)
1306
1316
1307 if not outgoing.missing:
1317 if not outgoing.missing:
1308 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1318 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1309 return 1
1319 return 1
1310
1320
1311 if cgversion == '01': #bundle1
1321 if cgversion == '01': #bundle1
1312 bversion = 'HG10' + bundlespec.wirecompression
1322 bversion = 'HG10' + bundlespec.wirecompression
1313 bcompression = None
1323 bcompression = None
1314 elif cgversion in ('02', '03'):
1324 elif cgversion in ('02', '03'):
1315 bversion = 'HG20'
1325 bversion = 'HG20'
1316 bcompression = bundlespec.wirecompression
1326 bcompression = bundlespec.wirecompression
1317 else:
1327 else:
1318 raise error.ProgrammingError(
1328 raise error.ProgrammingError(
1319 'bundle: unexpected changegroup version %s' % cgversion)
1329 'bundle: unexpected changegroup version %s' % cgversion)
1320
1330
1321 # TODO compression options should be derived from bundlespec parsing.
1331 # TODO compression options should be derived from bundlespec parsing.
1322 # This is a temporary hack to allow adjusting bundle compression
1332 # This is a temporary hack to allow adjusting bundle compression
1323 # level without a) formalizing the bundlespec changes to declare it
1333 # level without a) formalizing the bundlespec changes to declare it
1324 # b) introducing a command flag.
1334 # b) introducing a command flag.
1325 compopts = {}
1335 compopts = {}
1326 complevel = ui.configint('experimental',
1336 complevel = ui.configint('experimental',
1327 'bundlecomplevel.' + bundlespec.compression)
1337 'bundlecomplevel.' + bundlespec.compression)
1328 if complevel is None:
1338 if complevel is None:
1329 complevel = ui.configint('experimental', 'bundlecomplevel')
1339 complevel = ui.configint('experimental', 'bundlecomplevel')
1330 if complevel is not None:
1340 if complevel is not None:
1331 compopts['level'] = complevel
1341 compopts['level'] = complevel
1332
1342
1333 # Allow overriding the bundling of obsmarker in phases through
1343 # Allow overriding the bundling of obsmarker in phases through
1334 # configuration while we don't have a bundle version that include them
1344 # configuration while we don't have a bundle version that include them
1335 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1345 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1336 bundlespec.contentopts['obsolescence'] = True
1346 bundlespec.contentopts['obsolescence'] = True
1337 if repo.ui.configbool('experimental', 'bundle-phases'):
1347 if repo.ui.configbool('experimental', 'bundle-phases'):
1338 bundlespec.contentopts['phases'] = True
1348 bundlespec.contentopts['phases'] = True
1339
1349
1340 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1350 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1341 bundlespec.contentopts, compression=bcompression,
1351 bundlespec.contentopts, compression=bcompression,
1342 compopts=compopts)
1352 compopts=compopts)
1343
1353
1344 @command('cat',
1354 @command('cat',
1345 [('o', 'output', '',
1355 [('o', 'output', '',
1346 _('print output to file with formatted name'), _('FORMAT')),
1356 _('print output to file with formatted name'), _('FORMAT')),
1347 ('r', 'rev', '', _('print the given revision'), _('REV')),
1357 ('r', 'rev', '', _('print the given revision'), _('REV')),
1348 ('', 'decode', None, _('apply any matching decode filter')),
1358 ('', 'decode', None, _('apply any matching decode filter')),
1349 ] + walkopts + formatteropts,
1359 ] + walkopts + formatteropts,
1350 _('[OPTION]... FILE...'),
1360 _('[OPTION]... FILE...'),
1351 helpcategory=command.CATEGORY_FILE_CONTENTS,
1361 helpcategory=command.CATEGORY_FILE_CONTENTS,
1352 inferrepo=True,
1362 inferrepo=True,
1353 intents={INTENT_READONLY})
1363 intents={INTENT_READONLY})
1354 def cat(ui, repo, file1, *pats, **opts):
1364 def cat(ui, repo, file1, *pats, **opts):
1355 """output the current or given revision of files
1365 """output the current or given revision of files
1356
1366
1357 Print the specified files as they were at the given revision. If
1367 Print the specified files as they were at the given revision. If
1358 no revision is given, the parent of the working directory is used.
1368 no revision is given, the parent of the working directory is used.
1359
1369
1360 Output may be to a file, in which case the name of the file is
1370 Output may be to a file, in which case the name of the file is
1361 given using a template string. See :hg:`help templates`. In addition
1371 given using a template string. See :hg:`help templates`. In addition
1362 to the common template keywords, the following formatting rules are
1372 to the common template keywords, the following formatting rules are
1363 supported:
1373 supported:
1364
1374
1365 :``%%``: literal "%" character
1375 :``%%``: literal "%" character
1366 :``%s``: basename of file being printed
1376 :``%s``: basename of file being printed
1367 :``%d``: dirname of file being printed, or '.' if in repository root
1377 :``%d``: dirname of file being printed, or '.' if in repository root
1368 :``%p``: root-relative path name of file being printed
1378 :``%p``: root-relative path name of file being printed
1369 :``%H``: changeset hash (40 hexadecimal digits)
1379 :``%H``: changeset hash (40 hexadecimal digits)
1370 :``%R``: changeset revision number
1380 :``%R``: changeset revision number
1371 :``%h``: short-form changeset hash (12 hexadecimal digits)
1381 :``%h``: short-form changeset hash (12 hexadecimal digits)
1372 :``%r``: zero-padded changeset revision number
1382 :``%r``: zero-padded changeset revision number
1373 :``%b``: basename of the exporting repository
1383 :``%b``: basename of the exporting repository
1374 :``\\``: literal "\\" character
1384 :``\\``: literal "\\" character
1375
1385
1376 .. container:: verbose
1386 .. container:: verbose
1377
1387
1378 Template:
1388 Template:
1379
1389
1380 The following keywords are supported in addition to the common template
1390 The following keywords are supported in addition to the common template
1381 keywords and functions. See also :hg:`help templates`.
1391 keywords and functions. See also :hg:`help templates`.
1382
1392
1383 :data: String. File content.
1393 :data: String. File content.
1384 :path: String. Repository-absolute path of the file.
1394 :path: String. Repository-absolute path of the file.
1385
1395
1386 Returns 0 on success.
1396 Returns 0 on success.
1387 """
1397 """
1388 opts = pycompat.byteskwargs(opts)
1398 opts = pycompat.byteskwargs(opts)
1389 rev = opts.get('rev')
1399 rev = opts.get('rev')
1390 if rev:
1400 if rev:
1391 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1401 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1392 ctx = scmutil.revsingle(repo, rev)
1402 ctx = scmutil.revsingle(repo, rev)
1393 m = scmutil.match(ctx, (file1,) + pats, opts)
1403 m = scmutil.match(ctx, (file1,) + pats, opts)
1394 fntemplate = opts.pop('output', '')
1404 fntemplate = opts.pop('output', '')
1395 if cmdutil.isstdiofilename(fntemplate):
1405 if cmdutil.isstdiofilename(fntemplate):
1396 fntemplate = ''
1406 fntemplate = ''
1397
1407
1398 if fntemplate:
1408 if fntemplate:
1399 fm = formatter.nullformatter(ui, 'cat', opts)
1409 fm = formatter.nullformatter(ui, 'cat', opts)
1400 else:
1410 else:
1401 ui.pager('cat')
1411 ui.pager('cat')
1402 fm = ui.formatter('cat', opts)
1412 fm = ui.formatter('cat', opts)
1403 with fm:
1413 with fm:
1404 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1414 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1405 **pycompat.strkwargs(opts))
1415 **pycompat.strkwargs(opts))
1406
1416
1407 @command('clone',
1417 @command('clone',
1408 [('U', 'noupdate', None, _('the clone will include an empty working '
1418 [('U', 'noupdate', None, _('the clone will include an empty working '
1409 'directory (only a repository)')),
1419 'directory (only a repository)')),
1410 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1420 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1411 _('REV')),
1421 _('REV')),
1412 ('r', 'rev', [], _('do not clone everything, but include this changeset'
1422 ('r', 'rev', [], _('do not clone everything, but include this changeset'
1413 ' and its ancestors'), _('REV')),
1423 ' and its ancestors'), _('REV')),
1414 ('b', 'branch', [], _('do not clone everything, but include this branch\'s'
1424 ('b', 'branch', [], _('do not clone everything, but include this branch\'s'
1415 ' changesets and their ancestors'), _('BRANCH')),
1425 ' changesets and their ancestors'), _('BRANCH')),
1416 ('', 'pull', None, _('use pull protocol to copy metadata')),
1426 ('', 'pull', None, _('use pull protocol to copy metadata')),
1417 ('', 'uncompressed', None,
1427 ('', 'uncompressed', None,
1418 _('an alias to --stream (DEPRECATED)')),
1428 _('an alias to --stream (DEPRECATED)')),
1419 ('', 'stream', None,
1429 ('', 'stream', None,
1420 _('clone with minimal data processing')),
1430 _('clone with minimal data processing')),
1421 ] + remoteopts,
1431 ] + remoteopts,
1422 _('[OPTION]... SOURCE [DEST]'),
1432 _('[OPTION]... SOURCE [DEST]'),
1423 helpcategory=command.CATEGORY_REPO_CREATION,
1433 helpcategory=command.CATEGORY_REPO_CREATION,
1424 helpbasic=True, norepo=True)
1434 helpbasic=True, norepo=True)
1425 def clone(ui, source, dest=None, **opts):
1435 def clone(ui, source, dest=None, **opts):
1426 """make a copy of an existing repository
1436 """make a copy of an existing repository
1427
1437
1428 Create a copy of an existing repository in a new directory.
1438 Create a copy of an existing repository in a new directory.
1429
1439
1430 If no destination directory name is specified, it defaults to the
1440 If no destination directory name is specified, it defaults to the
1431 basename of the source.
1441 basename of the source.
1432
1442
1433 The location of the source is added to the new repository's
1443 The location of the source is added to the new repository's
1434 ``.hg/hgrc`` file, as the default to be used for future pulls.
1444 ``.hg/hgrc`` file, as the default to be used for future pulls.
1435
1445
1436 Only local paths and ``ssh://`` URLs are supported as
1446 Only local paths and ``ssh://`` URLs are supported as
1437 destinations. For ``ssh://`` destinations, no working directory or
1447 destinations. For ``ssh://`` destinations, no working directory or
1438 ``.hg/hgrc`` will be created on the remote side.
1448 ``.hg/hgrc`` will be created on the remote side.
1439
1449
1440 If the source repository has a bookmark called '@' set, that
1450 If the source repository has a bookmark called '@' set, that
1441 revision will be checked out in the new repository by default.
1451 revision will be checked out in the new repository by default.
1442
1452
1443 To check out a particular version, use -u/--update, or
1453 To check out a particular version, use -u/--update, or
1444 -U/--noupdate to create a clone with no working directory.
1454 -U/--noupdate to create a clone with no working directory.
1445
1455
1446 To pull only a subset of changesets, specify one or more revisions
1456 To pull only a subset of changesets, specify one or more revisions
1447 identifiers with -r/--rev or branches with -b/--branch. The
1457 identifiers with -r/--rev or branches with -b/--branch. The
1448 resulting clone will contain only the specified changesets and
1458 resulting clone will contain only the specified changesets and
1449 their ancestors. These options (or 'clone src#rev dest') imply
1459 their ancestors. These options (or 'clone src#rev dest') imply
1450 --pull, even for local source repositories.
1460 --pull, even for local source repositories.
1451
1461
1452 In normal clone mode, the remote normalizes repository data into a common
1462 In normal clone mode, the remote normalizes repository data into a common
1453 exchange format and the receiving end translates this data into its local
1463 exchange format and the receiving end translates this data into its local
1454 storage format. --stream activates a different clone mode that essentially
1464 storage format. --stream activates a different clone mode that essentially
1455 copies repository files from the remote with minimal data processing. This
1465 copies repository files from the remote with minimal data processing. This
1456 significantly reduces the CPU cost of a clone both remotely and locally.
1466 significantly reduces the CPU cost of a clone both remotely and locally.
1457 However, it often increases the transferred data size by 30-40%. This can
1467 However, it often increases the transferred data size by 30-40%. This can
1458 result in substantially faster clones where I/O throughput is plentiful,
1468 result in substantially faster clones where I/O throughput is plentiful,
1459 especially for larger repositories. A side-effect of --stream clones is
1469 especially for larger repositories. A side-effect of --stream clones is
1460 that storage settings and requirements on the remote are applied locally:
1470 that storage settings and requirements on the remote are applied locally:
1461 a modern client may inherit legacy or inefficient storage used by the
1471 a modern client may inherit legacy or inefficient storage used by the
1462 remote or a legacy Mercurial client may not be able to clone from a
1472 remote or a legacy Mercurial client may not be able to clone from a
1463 modern Mercurial remote.
1473 modern Mercurial remote.
1464
1474
1465 .. note::
1475 .. note::
1466
1476
1467 Specifying a tag will include the tagged changeset but not the
1477 Specifying a tag will include the tagged changeset but not the
1468 changeset containing the tag.
1478 changeset containing the tag.
1469
1479
1470 .. container:: verbose
1480 .. container:: verbose
1471
1481
1472 For efficiency, hardlinks are used for cloning whenever the
1482 For efficiency, hardlinks are used for cloning whenever the
1473 source and destination are on the same filesystem (note this
1483 source and destination are on the same filesystem (note this
1474 applies only to the repository data, not to the working
1484 applies only to the repository data, not to the working
1475 directory). Some filesystems, such as AFS, implement hardlinking
1485 directory). Some filesystems, such as AFS, implement hardlinking
1476 incorrectly, but do not report errors. In these cases, use the
1486 incorrectly, but do not report errors. In these cases, use the
1477 --pull option to avoid hardlinking.
1487 --pull option to avoid hardlinking.
1478
1488
1479 Mercurial will update the working directory to the first applicable
1489 Mercurial will update the working directory to the first applicable
1480 revision from this list:
1490 revision from this list:
1481
1491
1482 a) null if -U or the source repository has no changesets
1492 a) null if -U or the source repository has no changesets
1483 b) if -u . and the source repository is local, the first parent of
1493 b) if -u . and the source repository is local, the first parent of
1484 the source repository's working directory
1494 the source repository's working directory
1485 c) the changeset specified with -u (if a branch name, this means the
1495 c) the changeset specified with -u (if a branch name, this means the
1486 latest head of that branch)
1496 latest head of that branch)
1487 d) the changeset specified with -r
1497 d) the changeset specified with -r
1488 e) the tipmost head specified with -b
1498 e) the tipmost head specified with -b
1489 f) the tipmost head specified with the url#branch source syntax
1499 f) the tipmost head specified with the url#branch source syntax
1490 g) the revision marked with the '@' bookmark, if present
1500 g) the revision marked with the '@' bookmark, if present
1491 h) the tipmost head of the default branch
1501 h) the tipmost head of the default branch
1492 i) tip
1502 i) tip
1493
1503
1494 When cloning from servers that support it, Mercurial may fetch
1504 When cloning from servers that support it, Mercurial may fetch
1495 pre-generated data from a server-advertised URL or inline from the
1505 pre-generated data from a server-advertised URL or inline from the
1496 same stream. When this is done, hooks operating on incoming changesets
1506 same stream. When this is done, hooks operating on incoming changesets
1497 and changegroups may fire more than once, once for each pre-generated
1507 and changegroups may fire more than once, once for each pre-generated
1498 bundle and as well as for any additional remaining data. In addition,
1508 bundle and as well as for any additional remaining data. In addition,
1499 if an error occurs, the repository may be rolled back to a partial
1509 if an error occurs, the repository may be rolled back to a partial
1500 clone. This behavior may change in future releases.
1510 clone. This behavior may change in future releases.
1501 See :hg:`help -e clonebundles` for more.
1511 See :hg:`help -e clonebundles` for more.
1502
1512
1503 Examples:
1513 Examples:
1504
1514
1505 - clone a remote repository to a new directory named hg/::
1515 - clone a remote repository to a new directory named hg/::
1506
1516
1507 hg clone https://www.mercurial-scm.org/repo/hg/
1517 hg clone https://www.mercurial-scm.org/repo/hg/
1508
1518
1509 - create a lightweight local clone::
1519 - create a lightweight local clone::
1510
1520
1511 hg clone project/ project-feature/
1521 hg clone project/ project-feature/
1512
1522
1513 - clone from an absolute path on an ssh server (note double-slash)::
1523 - clone from an absolute path on an ssh server (note double-slash)::
1514
1524
1515 hg clone ssh://user@server//home/projects/alpha/
1525 hg clone ssh://user@server//home/projects/alpha/
1516
1526
1517 - do a streaming clone while checking out a specified version::
1527 - do a streaming clone while checking out a specified version::
1518
1528
1519 hg clone --stream http://server/repo -u 1.5
1529 hg clone --stream http://server/repo -u 1.5
1520
1530
1521 - create a repository without changesets after a particular revision::
1531 - create a repository without changesets after a particular revision::
1522
1532
1523 hg clone -r 04e544 experimental/ good/
1533 hg clone -r 04e544 experimental/ good/
1524
1534
1525 - clone (and track) a particular named branch::
1535 - clone (and track) a particular named branch::
1526
1536
1527 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1537 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1528
1538
1529 See :hg:`help urls` for details on specifying URLs.
1539 See :hg:`help urls` for details on specifying URLs.
1530
1540
1531 Returns 0 on success.
1541 Returns 0 on success.
1532 """
1542 """
1533 opts = pycompat.byteskwargs(opts)
1543 opts = pycompat.byteskwargs(opts)
1534 if opts.get('noupdate') and opts.get('updaterev'):
1544 if opts.get('noupdate') and opts.get('updaterev'):
1535 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1545 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1536
1546
1537 # --include/--exclude can come from narrow or sparse.
1547 # --include/--exclude can come from narrow or sparse.
1538 includepats, excludepats = None, None
1548 includepats, excludepats = None, None
1539
1549
1540 # hg.clone() differentiates between None and an empty set. So make sure
1550 # hg.clone() differentiates between None and an empty set. So make sure
1541 # patterns are sets if narrow is requested without patterns.
1551 # patterns are sets if narrow is requested without patterns.
1542 if opts.get('narrow'):
1552 if opts.get('narrow'):
1543 includepats = set()
1553 includepats = set()
1544 excludepats = set()
1554 excludepats = set()
1545
1555
1546 if opts.get('include'):
1556 if opts.get('include'):
1547 includepats = narrowspec.parsepatterns(opts.get('include'))
1557 includepats = narrowspec.parsepatterns(opts.get('include'))
1548 if opts.get('exclude'):
1558 if opts.get('exclude'):
1549 excludepats = narrowspec.parsepatterns(opts.get('exclude'))
1559 excludepats = narrowspec.parsepatterns(opts.get('exclude'))
1550
1560
1551 r = hg.clone(ui, opts, source, dest,
1561 r = hg.clone(ui, opts, source, dest,
1552 pull=opts.get('pull'),
1562 pull=opts.get('pull'),
1553 stream=opts.get('stream') or opts.get('uncompressed'),
1563 stream=opts.get('stream') or opts.get('uncompressed'),
1554 revs=opts.get('rev'),
1564 revs=opts.get('rev'),
1555 update=opts.get('updaterev') or not opts.get('noupdate'),
1565 update=opts.get('updaterev') or not opts.get('noupdate'),
1556 branch=opts.get('branch'),
1566 branch=opts.get('branch'),
1557 shareopts=opts.get('shareopts'),
1567 shareopts=opts.get('shareopts'),
1558 storeincludepats=includepats,
1568 storeincludepats=includepats,
1559 storeexcludepats=excludepats,
1569 storeexcludepats=excludepats,
1560 depth=opts.get('depth') or None)
1570 depth=opts.get('depth') or None)
1561
1571
1562 return r is None
1572 return r is None
1563
1573
1564 @command('commit|ci',
1574 @command('commit|ci',
1565 [('A', 'addremove', None,
1575 [('A', 'addremove', None,
1566 _('mark new/missing files as added/removed before committing')),
1576 _('mark new/missing files as added/removed before committing')),
1567 ('', 'close-branch', None,
1577 ('', 'close-branch', None,
1568 _('mark a branch head as closed')),
1578 _('mark a branch head as closed')),
1569 ('', 'amend', None, _('amend the parent of the working directory')),
1579 ('', 'amend', None, _('amend the parent of the working directory')),
1570 ('s', 'secret', None, _('use the secret phase for committing')),
1580 ('s', 'secret', None, _('use the secret phase for committing')),
1571 ('e', 'edit', None, _('invoke editor on commit messages')),
1581 ('e', 'edit', None, _('invoke editor on commit messages')),
1572 ('i', 'interactive', None, _('use interactive mode')),
1582 ('i', 'interactive', None, _('use interactive mode')),
1573 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1583 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1574 _('[OPTION]... [FILE]...'),
1584 _('[OPTION]... [FILE]...'),
1575 helpcategory=command.CATEGORY_COMMITTING, helpbasic=True,
1585 helpcategory=command.CATEGORY_COMMITTING, helpbasic=True,
1576 inferrepo=True)
1586 inferrepo=True)
1577 def commit(ui, repo, *pats, **opts):
1587 def commit(ui, repo, *pats, **opts):
1578 """commit the specified files or all outstanding changes
1588 """commit the specified files or all outstanding changes
1579
1589
1580 Commit changes to the given files into the repository. Unlike a
1590 Commit changes to the given files into the repository. Unlike a
1581 centralized SCM, this operation is a local operation. See
1591 centralized SCM, this operation is a local operation. See
1582 :hg:`push` for a way to actively distribute your changes.
1592 :hg:`push` for a way to actively distribute your changes.
1583
1593
1584 If a list of files is omitted, all changes reported by :hg:`status`
1594 If a list of files is omitted, all changes reported by :hg:`status`
1585 will be committed.
1595 will be committed.
1586
1596
1587 If you are committing the result of a merge, do not provide any
1597 If you are committing the result of a merge, do not provide any
1588 filenames or -I/-X filters.
1598 filenames or -I/-X filters.
1589
1599
1590 If no commit message is specified, Mercurial starts your
1600 If no commit message is specified, Mercurial starts your
1591 configured editor where you can enter a message. In case your
1601 configured editor where you can enter a message. In case your
1592 commit fails, you will find a backup of your message in
1602 commit fails, you will find a backup of your message in
1593 ``.hg/last-message.txt``.
1603 ``.hg/last-message.txt``.
1594
1604
1595 The --close-branch flag can be used to mark the current branch
1605 The --close-branch flag can be used to mark the current branch
1596 head closed. When all heads of a branch are closed, the branch
1606 head closed. When all heads of a branch are closed, the branch
1597 will be considered closed and no longer listed.
1607 will be considered closed and no longer listed.
1598
1608
1599 The --amend flag can be used to amend the parent of the
1609 The --amend flag can be used to amend the parent of the
1600 working directory with a new commit that contains the changes
1610 working directory with a new commit that contains the changes
1601 in the parent in addition to those currently reported by :hg:`status`,
1611 in the parent in addition to those currently reported by :hg:`status`,
1602 if there are any. The old commit is stored in a backup bundle in
1612 if there are any. The old commit is stored in a backup bundle in
1603 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1613 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1604 on how to restore it).
1614 on how to restore it).
1605
1615
1606 Message, user and date are taken from the amended commit unless
1616 Message, user and date are taken from the amended commit unless
1607 specified. When a message isn't specified on the command line,
1617 specified. When a message isn't specified on the command line,
1608 the editor will open with the message of the amended commit.
1618 the editor will open with the message of the amended commit.
1609
1619
1610 It is not possible to amend public changesets (see :hg:`help phases`)
1620 It is not possible to amend public changesets (see :hg:`help phases`)
1611 or changesets that have children.
1621 or changesets that have children.
1612
1622
1613 See :hg:`help dates` for a list of formats valid for -d/--date.
1623 See :hg:`help dates` for a list of formats valid for -d/--date.
1614
1624
1615 Returns 0 on success, 1 if nothing changed.
1625 Returns 0 on success, 1 if nothing changed.
1616
1626
1617 .. container:: verbose
1627 .. container:: verbose
1618
1628
1619 Examples:
1629 Examples:
1620
1630
1621 - commit all files ending in .py::
1631 - commit all files ending in .py::
1622
1632
1623 hg commit --include "set:**.py"
1633 hg commit --include "set:**.py"
1624
1634
1625 - commit all non-binary files::
1635 - commit all non-binary files::
1626
1636
1627 hg commit --exclude "set:binary()"
1637 hg commit --exclude "set:binary()"
1628
1638
1629 - amend the current commit and set the date to now::
1639 - amend the current commit and set the date to now::
1630
1640
1631 hg commit --amend --date now
1641 hg commit --amend --date now
1632 """
1642 """
1633 with repo.wlock(), repo.lock():
1643 with repo.wlock(), repo.lock():
1634 return _docommit(ui, repo, *pats, **opts)
1644 return _docommit(ui, repo, *pats, **opts)
1635
1645
1636 def _docommit(ui, repo, *pats, **opts):
1646 def _docommit(ui, repo, *pats, **opts):
1637 if opts.get(r'interactive'):
1647 if opts.get(r'interactive'):
1638 opts.pop(r'interactive')
1648 opts.pop(r'interactive')
1639 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1649 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1640 cmdutil.recordfilter, *pats,
1650 cmdutil.recordfilter, *pats,
1641 **opts)
1651 **opts)
1642 # ret can be 0 (no changes to record) or the value returned by
1652 # ret can be 0 (no changes to record) or the value returned by
1643 # commit(), 1 if nothing changed or None on success.
1653 # commit(), 1 if nothing changed or None on success.
1644 return 1 if ret == 0 else ret
1654 return 1 if ret == 0 else ret
1645
1655
1646 opts = pycompat.byteskwargs(opts)
1656 opts = pycompat.byteskwargs(opts)
1647 if opts.get('subrepos'):
1657 if opts.get('subrepos'):
1648 if opts.get('amend'):
1658 if opts.get('amend'):
1649 raise error.Abort(_('cannot amend with --subrepos'))
1659 raise error.Abort(_('cannot amend with --subrepos'))
1650 # Let --subrepos on the command line override config setting.
1660 # Let --subrepos on the command line override config setting.
1651 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1661 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1652
1662
1653 cmdutil.checkunfinished(repo, commit=True)
1663 cmdutil.checkunfinished(repo, commit=True)
1654
1664
1655 branch = repo[None].branch()
1665 branch = repo[None].branch()
1656 bheads = repo.branchheads(branch)
1666 bheads = repo.branchheads(branch)
1657
1667
1658 extra = {}
1668 extra = {}
1659 if opts.get('close_branch'):
1669 if opts.get('close_branch'):
1660 extra['close'] = '1'
1670 extra['close'] = '1'
1661
1671
1662 if not bheads:
1672 if not bheads:
1663 raise error.Abort(_('can only close branch heads'))
1673 raise error.Abort(_('can only close branch heads'))
1664 elif opts.get('amend'):
1674 elif opts.get('amend'):
1665 if repo[None].parents()[0].p1().branch() != branch and \
1675 if repo[None].parents()[0].p1().branch() != branch and \
1666 repo[None].parents()[0].p2().branch() != branch:
1676 repo[None].parents()[0].p2().branch() != branch:
1667 raise error.Abort(_('can only close branch heads'))
1677 raise error.Abort(_('can only close branch heads'))
1668
1678
1669 if opts.get('amend'):
1679 if opts.get('amend'):
1670 if ui.configbool('ui', 'commitsubrepos'):
1680 if ui.configbool('ui', 'commitsubrepos'):
1671 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1681 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1672
1682
1673 old = repo['.']
1683 old = repo['.']
1674 rewriteutil.precheck(repo, [old.rev()], 'amend')
1684 rewriteutil.precheck(repo, [old.rev()], 'amend')
1675
1685
1676 # Currently histedit gets confused if an amend happens while histedit
1686 # Currently histedit gets confused if an amend happens while histedit
1677 # is in progress. Since we have a checkunfinished command, we are
1687 # is in progress. Since we have a checkunfinished command, we are
1678 # temporarily honoring it.
1688 # temporarily honoring it.
1679 #
1689 #
1680 # Note: eventually this guard will be removed. Please do not expect
1690 # Note: eventually this guard will be removed. Please do not expect
1681 # this behavior to remain.
1691 # this behavior to remain.
1682 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1692 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1683 cmdutil.checkunfinished(repo)
1693 cmdutil.checkunfinished(repo)
1684
1694
1685 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1695 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1686 if node == old.node():
1696 if node == old.node():
1687 ui.status(_("nothing changed\n"))
1697 ui.status(_("nothing changed\n"))
1688 return 1
1698 return 1
1689 else:
1699 else:
1690 def commitfunc(ui, repo, message, match, opts):
1700 def commitfunc(ui, repo, message, match, opts):
1691 overrides = {}
1701 overrides = {}
1692 if opts.get('secret'):
1702 if opts.get('secret'):
1693 overrides[('phases', 'new-commit')] = 'secret'
1703 overrides[('phases', 'new-commit')] = 'secret'
1694
1704
1695 baseui = repo.baseui
1705 baseui = repo.baseui
1696 with baseui.configoverride(overrides, 'commit'):
1706 with baseui.configoverride(overrides, 'commit'):
1697 with ui.configoverride(overrides, 'commit'):
1707 with ui.configoverride(overrides, 'commit'):
1698 editform = cmdutil.mergeeditform(repo[None],
1708 editform = cmdutil.mergeeditform(repo[None],
1699 'commit.normal')
1709 'commit.normal')
1700 editor = cmdutil.getcommiteditor(
1710 editor = cmdutil.getcommiteditor(
1701 editform=editform, **pycompat.strkwargs(opts))
1711 editform=editform, **pycompat.strkwargs(opts))
1702 return repo.commit(message,
1712 return repo.commit(message,
1703 opts.get('user'),
1713 opts.get('user'),
1704 opts.get('date'),
1714 opts.get('date'),
1705 match,
1715 match,
1706 editor=editor,
1716 editor=editor,
1707 extra=extra)
1717 extra=extra)
1708
1718
1709 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1719 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1710
1720
1711 if not node:
1721 if not node:
1712 stat = cmdutil.postcommitstatus(repo, pats, opts)
1722 stat = cmdutil.postcommitstatus(repo, pats, opts)
1713 if stat[3]:
1723 if stat[3]:
1714 ui.status(_("nothing changed (%d missing files, see "
1724 ui.status(_("nothing changed (%d missing files, see "
1715 "'hg status')\n") % len(stat[3]))
1725 "'hg status')\n") % len(stat[3]))
1716 else:
1726 else:
1717 ui.status(_("nothing changed\n"))
1727 ui.status(_("nothing changed\n"))
1718 return 1
1728 return 1
1719
1729
1720 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1730 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1721
1731
1722 @command('config|showconfig|debugconfig',
1732 @command('config|showconfig|debugconfig',
1723 [('u', 'untrusted', None, _('show untrusted configuration options')),
1733 [('u', 'untrusted', None, _('show untrusted configuration options')),
1724 ('e', 'edit', None, _('edit user config')),
1734 ('e', 'edit', None, _('edit user config')),
1725 ('l', 'local', None, _('edit repository config')),
1735 ('l', 'local', None, _('edit repository config')),
1726 ('g', 'global', None, _('edit global config'))] + formatteropts,
1736 ('g', 'global', None, _('edit global config'))] + formatteropts,
1727 _('[-u] [NAME]...'),
1737 _('[-u] [NAME]...'),
1728 helpcategory=command.CATEGORY_HELP,
1738 helpcategory=command.CATEGORY_HELP,
1729 optionalrepo=True,
1739 optionalrepo=True,
1730 intents={INTENT_READONLY})
1740 intents={INTENT_READONLY})
1731 def config(ui, repo, *values, **opts):
1741 def config(ui, repo, *values, **opts):
1732 """show combined config settings from all hgrc files
1742 """show combined config settings from all hgrc files
1733
1743
1734 With no arguments, print names and values of all config items.
1744 With no arguments, print names and values of all config items.
1735
1745
1736 With one argument of the form section.name, print just the value
1746 With one argument of the form section.name, print just the value
1737 of that config item.
1747 of that config item.
1738
1748
1739 With multiple arguments, print names and values of all config
1749 With multiple arguments, print names and values of all config
1740 items with matching section names or section.names.
1750 items with matching section names or section.names.
1741
1751
1742 With --edit, start an editor on the user-level config file. With
1752 With --edit, start an editor on the user-level config file. With
1743 --global, edit the system-wide config file. With --local, edit the
1753 --global, edit the system-wide config file. With --local, edit the
1744 repository-level config file.
1754 repository-level config file.
1745
1755
1746 With --debug, the source (filename and line number) is printed
1756 With --debug, the source (filename and line number) is printed
1747 for each config item.
1757 for each config item.
1748
1758
1749 See :hg:`help config` for more information about config files.
1759 See :hg:`help config` for more information about config files.
1750
1760
1751 .. container:: verbose
1761 .. container:: verbose
1752
1762
1753 Template:
1763 Template:
1754
1764
1755 The following keywords are supported. See also :hg:`help templates`.
1765 The following keywords are supported. See also :hg:`help templates`.
1756
1766
1757 :name: String. Config name.
1767 :name: String. Config name.
1758 :source: String. Filename and line number where the item is defined.
1768 :source: String. Filename and line number where the item is defined.
1759 :value: String. Config value.
1769 :value: String. Config value.
1760
1770
1761 Returns 0 on success, 1 if NAME does not exist.
1771 Returns 0 on success, 1 if NAME does not exist.
1762
1772
1763 """
1773 """
1764
1774
1765 opts = pycompat.byteskwargs(opts)
1775 opts = pycompat.byteskwargs(opts)
1766 if opts.get('edit') or opts.get('local') or opts.get('global'):
1776 if opts.get('edit') or opts.get('local') or opts.get('global'):
1767 if opts.get('local') and opts.get('global'):
1777 if opts.get('local') and opts.get('global'):
1768 raise error.Abort(_("can't use --local and --global together"))
1778 raise error.Abort(_("can't use --local and --global together"))
1769
1779
1770 if opts.get('local'):
1780 if opts.get('local'):
1771 if not repo:
1781 if not repo:
1772 raise error.Abort(_("can't use --local outside a repository"))
1782 raise error.Abort(_("can't use --local outside a repository"))
1773 paths = [repo.vfs.join('hgrc')]
1783 paths = [repo.vfs.join('hgrc')]
1774 elif opts.get('global'):
1784 elif opts.get('global'):
1775 paths = rcutil.systemrcpath()
1785 paths = rcutil.systemrcpath()
1776 else:
1786 else:
1777 paths = rcutil.userrcpath()
1787 paths = rcutil.userrcpath()
1778
1788
1779 for f in paths:
1789 for f in paths:
1780 if os.path.exists(f):
1790 if os.path.exists(f):
1781 break
1791 break
1782 else:
1792 else:
1783 if opts.get('global'):
1793 if opts.get('global'):
1784 samplehgrc = uimod.samplehgrcs['global']
1794 samplehgrc = uimod.samplehgrcs['global']
1785 elif opts.get('local'):
1795 elif opts.get('local'):
1786 samplehgrc = uimod.samplehgrcs['local']
1796 samplehgrc = uimod.samplehgrcs['local']
1787 else:
1797 else:
1788 samplehgrc = uimod.samplehgrcs['user']
1798 samplehgrc = uimod.samplehgrcs['user']
1789
1799
1790 f = paths[0]
1800 f = paths[0]
1791 fp = open(f, "wb")
1801 fp = open(f, "wb")
1792 fp.write(util.tonativeeol(samplehgrc))
1802 fp.write(util.tonativeeol(samplehgrc))
1793 fp.close()
1803 fp.close()
1794
1804
1795 editor = ui.geteditor()
1805 editor = ui.geteditor()
1796 ui.system("%s \"%s\"" % (editor, f),
1806 ui.system("%s \"%s\"" % (editor, f),
1797 onerr=error.Abort, errprefix=_("edit failed"),
1807 onerr=error.Abort, errprefix=_("edit failed"),
1798 blockedtag='config_edit')
1808 blockedtag='config_edit')
1799 return
1809 return
1800 ui.pager('config')
1810 ui.pager('config')
1801 fm = ui.formatter('config', opts)
1811 fm = ui.formatter('config', opts)
1802 for t, f in rcutil.rccomponents():
1812 for t, f in rcutil.rccomponents():
1803 if t == 'path':
1813 if t == 'path':
1804 ui.debug('read config from: %s\n' % f)
1814 ui.debug('read config from: %s\n' % f)
1805 elif t == 'items':
1815 elif t == 'items':
1806 for section, name, value, source in f:
1816 for section, name, value, source in f:
1807 ui.debug('set config by: %s\n' % source)
1817 ui.debug('set config by: %s\n' % source)
1808 else:
1818 else:
1809 raise error.ProgrammingError('unknown rctype: %s' % t)
1819 raise error.ProgrammingError('unknown rctype: %s' % t)
1810 untrusted = bool(opts.get('untrusted'))
1820 untrusted = bool(opts.get('untrusted'))
1811
1821
1812 selsections = selentries = []
1822 selsections = selentries = []
1813 if values:
1823 if values:
1814 selsections = [v for v in values if '.' not in v]
1824 selsections = [v for v in values if '.' not in v]
1815 selentries = [v for v in values if '.' in v]
1825 selentries = [v for v in values if '.' in v]
1816 uniquesel = (len(selentries) == 1 and not selsections)
1826 uniquesel = (len(selentries) == 1 and not selsections)
1817 selsections = set(selsections)
1827 selsections = set(selsections)
1818 selentries = set(selentries)
1828 selentries = set(selentries)
1819
1829
1820 matched = False
1830 matched = False
1821 for section, name, value in ui.walkconfig(untrusted=untrusted):
1831 for section, name, value in ui.walkconfig(untrusted=untrusted):
1822 source = ui.configsource(section, name, untrusted)
1832 source = ui.configsource(section, name, untrusted)
1823 value = pycompat.bytestr(value)
1833 value = pycompat.bytestr(value)
1824 if fm.isplain():
1834 if fm.isplain():
1825 source = source or 'none'
1835 source = source or 'none'
1826 value = value.replace('\n', '\\n')
1836 value = value.replace('\n', '\\n')
1827 entryname = section + '.' + name
1837 entryname = section + '.' + name
1828 if values and not (section in selsections or entryname in selentries):
1838 if values and not (section in selsections or entryname in selentries):
1829 continue
1839 continue
1830 fm.startitem()
1840 fm.startitem()
1831 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1841 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1832 if uniquesel:
1842 if uniquesel:
1833 fm.data(name=entryname)
1843 fm.data(name=entryname)
1834 fm.write('value', '%s\n', value)
1844 fm.write('value', '%s\n', value)
1835 else:
1845 else:
1836 fm.write('name value', '%s=%s\n', entryname, value)
1846 fm.write('name value', '%s=%s\n', entryname, value)
1837 matched = True
1847 matched = True
1838 fm.end()
1848 fm.end()
1839 if matched:
1849 if matched:
1840 return 0
1850 return 0
1841 return 1
1851 return 1
1842
1852
1843 @command('copy|cp',
1853 @command('copy|cp',
1844 [('A', 'after', None, _('record a copy that has already occurred')),
1854 [('A', 'after', None, _('record a copy that has already occurred')),
1845 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1855 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1846 ] + walkopts + dryrunopts,
1856 ] + walkopts + dryrunopts,
1847 _('[OPTION]... [SOURCE]... DEST'),
1857 _('[OPTION]... [SOURCE]... DEST'),
1848 helpcategory=command.CATEGORY_FILE_CONTENTS)
1858 helpcategory=command.CATEGORY_FILE_CONTENTS)
1849 def copy(ui, repo, *pats, **opts):
1859 def copy(ui, repo, *pats, **opts):
1850 """mark files as copied for the next commit
1860 """mark files as copied for the next commit
1851
1861
1852 Mark dest as having copies of source files. If dest is a
1862 Mark dest as having copies of source files. If dest is a
1853 directory, copies are put in that directory. If dest is a file,
1863 directory, copies are put in that directory. If dest is a file,
1854 the source must be a single file.
1864 the source must be a single file.
1855
1865
1856 By default, this command copies the contents of files as they
1866 By default, this command copies the contents of files as they
1857 exist in the working directory. If invoked with -A/--after, the
1867 exist in the working directory. If invoked with -A/--after, the
1858 operation is recorded, but no copying is performed.
1868 operation is recorded, but no copying is performed.
1859
1869
1860 This command takes effect with the next commit. To undo a copy
1870 This command takes effect with the next commit. To undo a copy
1861 before that, see :hg:`revert`.
1871 before that, see :hg:`revert`.
1862
1872
1863 Returns 0 on success, 1 if errors are encountered.
1873 Returns 0 on success, 1 if errors are encountered.
1864 """
1874 """
1865 opts = pycompat.byteskwargs(opts)
1875 opts = pycompat.byteskwargs(opts)
1866 with repo.wlock(False):
1876 with repo.wlock(False):
1867 return cmdutil.copy(ui, repo, pats, opts)
1877 return cmdutil.copy(ui, repo, pats, opts)
1868
1878
1869 @command(
1879 @command(
1870 'debugcommands', [], _('[COMMAND]'),
1880 'debugcommands', [], _('[COMMAND]'),
1871 helpcategory=command.CATEGORY_HELP,
1881 helpcategory=command.CATEGORY_HELP,
1872 norepo=True)
1882 norepo=True)
1873 def debugcommands(ui, cmd='', *args):
1883 def debugcommands(ui, cmd='', *args):
1874 """list all available commands and options"""
1884 """list all available commands and options"""
1875 for cmd, vals in sorted(table.iteritems()):
1885 for cmd, vals in sorted(table.iteritems()):
1876 cmd = cmd.split('|')[0]
1886 cmd = cmd.split('|')[0]
1877 opts = ', '.join([i[1] for i in vals[1]])
1887 opts = ', '.join([i[1] for i in vals[1]])
1878 ui.write('%s: %s\n' % (cmd, opts))
1888 ui.write('%s: %s\n' % (cmd, opts))
1879
1889
1880 @command('debugcomplete',
1890 @command('debugcomplete',
1881 [('o', 'options', None, _('show the command options'))],
1891 [('o', 'options', None, _('show the command options'))],
1882 _('[-o] CMD'),
1892 _('[-o] CMD'),
1883 helpcategory=command.CATEGORY_HELP,
1893 helpcategory=command.CATEGORY_HELP,
1884 norepo=True)
1894 norepo=True)
1885 def debugcomplete(ui, cmd='', **opts):
1895 def debugcomplete(ui, cmd='', **opts):
1886 """returns the completion list associated with the given command"""
1896 """returns the completion list associated with the given command"""
1887
1897
1888 if opts.get(r'options'):
1898 if opts.get(r'options'):
1889 options = []
1899 options = []
1890 otables = [globalopts]
1900 otables = [globalopts]
1891 if cmd:
1901 if cmd:
1892 aliases, entry = cmdutil.findcmd(cmd, table, False)
1902 aliases, entry = cmdutil.findcmd(cmd, table, False)
1893 otables.append(entry[1])
1903 otables.append(entry[1])
1894 for t in otables:
1904 for t in otables:
1895 for o in t:
1905 for o in t:
1896 if "(DEPRECATED)" in o[3]:
1906 if "(DEPRECATED)" in o[3]:
1897 continue
1907 continue
1898 if o[0]:
1908 if o[0]:
1899 options.append('-%s' % o[0])
1909 options.append('-%s' % o[0])
1900 options.append('--%s' % o[1])
1910 options.append('--%s' % o[1])
1901 ui.write("%s\n" % "\n".join(options))
1911 ui.write("%s\n" % "\n".join(options))
1902 return
1912 return
1903
1913
1904 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1914 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1905 if ui.verbose:
1915 if ui.verbose:
1906 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1916 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1907 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1917 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1908
1918
1909 @command('diff',
1919 @command('diff',
1910 [('r', 'rev', [], _('revision'), _('REV')),
1920 [('r', 'rev', [], _('revision'), _('REV')),
1911 ('c', 'change', '', _('change made by revision'), _('REV'))
1921 ('c', 'change', '', _('change made by revision'), _('REV'))
1912 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1922 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1913 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1923 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1914 helpcategory=command.CATEGORY_FILE_CONTENTS,
1924 helpcategory=command.CATEGORY_FILE_CONTENTS,
1915 helpbasic=True, inferrepo=True, intents={INTENT_READONLY})
1925 helpbasic=True, inferrepo=True, intents={INTENT_READONLY})
1916 def diff(ui, repo, *pats, **opts):
1926 def diff(ui, repo, *pats, **opts):
1917 """diff repository (or selected files)
1927 """diff repository (or selected files)
1918
1928
1919 Show differences between revisions for the specified files.
1929 Show differences between revisions for the specified files.
1920
1930
1921 Differences between files are shown using the unified diff format.
1931 Differences between files are shown using the unified diff format.
1922
1932
1923 .. note::
1933 .. note::
1924
1934
1925 :hg:`diff` may generate unexpected results for merges, as it will
1935 :hg:`diff` may generate unexpected results for merges, as it will
1926 default to comparing against the working directory's first
1936 default to comparing against the working directory's first
1927 parent changeset if no revisions are specified.
1937 parent changeset if no revisions are specified.
1928
1938
1929 When two revision arguments are given, then changes are shown
1939 When two revision arguments are given, then changes are shown
1930 between those revisions. If only one revision is specified then
1940 between those revisions. If only one revision is specified then
1931 that revision is compared to the working directory, and, when no
1941 that revision is compared to the working directory, and, when no
1932 revisions are specified, the working directory files are compared
1942 revisions are specified, the working directory files are compared
1933 to its first parent.
1943 to its first parent.
1934
1944
1935 Alternatively you can specify -c/--change with a revision to see
1945 Alternatively you can specify -c/--change with a revision to see
1936 the changes in that changeset relative to its first parent.
1946 the changes in that changeset relative to its first parent.
1937
1947
1938 Without the -a/--text option, diff will avoid generating diffs of
1948 Without the -a/--text option, diff will avoid generating diffs of
1939 files it detects as binary. With -a, diff will generate a diff
1949 files it detects as binary. With -a, diff will generate a diff
1940 anyway, probably with undesirable results.
1950 anyway, probably with undesirable results.
1941
1951
1942 Use the -g/--git option to generate diffs in the git extended diff
1952 Use the -g/--git option to generate diffs in the git extended diff
1943 format. For more information, read :hg:`help diffs`.
1953 format. For more information, read :hg:`help diffs`.
1944
1954
1945 .. container:: verbose
1955 .. container:: verbose
1946
1956
1947 Examples:
1957 Examples:
1948
1958
1949 - compare a file in the current working directory to its parent::
1959 - compare a file in the current working directory to its parent::
1950
1960
1951 hg diff foo.c
1961 hg diff foo.c
1952
1962
1953 - compare two historical versions of a directory, with rename info::
1963 - compare two historical versions of a directory, with rename info::
1954
1964
1955 hg diff --git -r 1.0:1.2 lib/
1965 hg diff --git -r 1.0:1.2 lib/
1956
1966
1957 - get change stats relative to the last change on some date::
1967 - get change stats relative to the last change on some date::
1958
1968
1959 hg diff --stat -r "date('may 2')"
1969 hg diff --stat -r "date('may 2')"
1960
1970
1961 - diff all newly-added files that contain a keyword::
1971 - diff all newly-added files that contain a keyword::
1962
1972
1963 hg diff "set:added() and grep(GNU)"
1973 hg diff "set:added() and grep(GNU)"
1964
1974
1965 - compare a revision and its parents::
1975 - compare a revision and its parents::
1966
1976
1967 hg diff -c 9353 # compare against first parent
1977 hg diff -c 9353 # compare against first parent
1968 hg diff -r 9353^:9353 # same using revset syntax
1978 hg diff -r 9353^:9353 # same using revset syntax
1969 hg diff -r 9353^2:9353 # compare against the second parent
1979 hg diff -r 9353^2:9353 # compare against the second parent
1970
1980
1971 Returns 0 on success.
1981 Returns 0 on success.
1972 """
1982 """
1973
1983
1974 opts = pycompat.byteskwargs(opts)
1984 opts = pycompat.byteskwargs(opts)
1975 revs = opts.get('rev')
1985 revs = opts.get('rev')
1976 change = opts.get('change')
1986 change = opts.get('change')
1977 stat = opts.get('stat')
1987 stat = opts.get('stat')
1978 reverse = opts.get('reverse')
1988 reverse = opts.get('reverse')
1979
1989
1980 if revs and change:
1990 if revs and change:
1981 msg = _('cannot specify --rev and --change at the same time')
1991 msg = _('cannot specify --rev and --change at the same time')
1982 raise error.Abort(msg)
1992 raise error.Abort(msg)
1983 elif change:
1993 elif change:
1984 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1994 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1985 ctx2 = scmutil.revsingle(repo, change, None)
1995 ctx2 = scmutil.revsingle(repo, change, None)
1986 ctx1 = ctx2.p1()
1996 ctx1 = ctx2.p1()
1987 else:
1997 else:
1988 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1998 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1989 ctx1, ctx2 = scmutil.revpair(repo, revs)
1999 ctx1, ctx2 = scmutil.revpair(repo, revs)
1990 node1, node2 = ctx1.node(), ctx2.node()
2000 node1, node2 = ctx1.node(), ctx2.node()
1991
2001
1992 if reverse:
2002 if reverse:
1993 node1, node2 = node2, node1
2003 node1, node2 = node2, node1
1994
2004
1995 diffopts = patch.diffallopts(ui, opts)
2005 diffopts = patch.diffallopts(ui, opts)
1996 m = scmutil.match(ctx2, pats, opts)
2006 m = scmutil.match(ctx2, pats, opts)
1997 m = repo.narrowmatch(m)
2007 m = repo.narrowmatch(m)
1998 ui.pager('diff')
2008 ui.pager('diff')
1999 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2009 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2000 listsubrepos=opts.get('subrepos'),
2010 listsubrepos=opts.get('subrepos'),
2001 root=opts.get('root'))
2011 root=opts.get('root'))
2002
2012
2003 @command('export',
2013 @command('export',
2004 [('B', 'bookmark', '',
2014 [('B', 'bookmark', '',
2005 _('export changes only reachable by given bookmark'), _('BOOKMARK')),
2015 _('export changes only reachable by given bookmark'), _('BOOKMARK')),
2006 ('o', 'output', '',
2016 ('o', 'output', '',
2007 _('print output to file with formatted name'), _('FORMAT')),
2017 _('print output to file with formatted name'), _('FORMAT')),
2008 ('', 'switch-parent', None, _('diff against the second parent')),
2018 ('', 'switch-parent', None, _('diff against the second parent')),
2009 ('r', 'rev', [], _('revisions to export'), _('REV')),
2019 ('r', 'rev', [], _('revisions to export'), _('REV')),
2010 ] + diffopts + formatteropts,
2020 ] + diffopts + formatteropts,
2011 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2021 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
2012 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2022 helpcategory=command.CATEGORY_IMPORT_EXPORT,
2013 helpbasic=True, intents={INTENT_READONLY})
2023 helpbasic=True, intents={INTENT_READONLY})
2014 def export(ui, repo, *changesets, **opts):
2024 def export(ui, repo, *changesets, **opts):
2015 """dump the header and diffs for one or more changesets
2025 """dump the header and diffs for one or more changesets
2016
2026
2017 Print the changeset header and diffs for one or more revisions.
2027 Print the changeset header and diffs for one or more revisions.
2018 If no revision is given, the parent of the working directory is used.
2028 If no revision is given, the parent of the working directory is used.
2019
2029
2020 The information shown in the changeset header is: author, date,
2030 The information shown in the changeset header is: author, date,
2021 branch name (if non-default), changeset hash, parent(s) and commit
2031 branch name (if non-default), changeset hash, parent(s) and commit
2022 comment.
2032 comment.
2023
2033
2024 .. note::
2034 .. note::
2025
2035
2026 :hg:`export` may generate unexpected diff output for merge
2036 :hg:`export` may generate unexpected diff output for merge
2027 changesets, as it will compare the merge changeset against its
2037 changesets, as it will compare the merge changeset against its
2028 first parent only.
2038 first parent only.
2029
2039
2030 Output may be to a file, in which case the name of the file is
2040 Output may be to a file, in which case the name of the file is
2031 given using a template string. See :hg:`help templates`. In addition
2041 given using a template string. See :hg:`help templates`. In addition
2032 to the common template keywords, the following formatting rules are
2042 to the common template keywords, the following formatting rules are
2033 supported:
2043 supported:
2034
2044
2035 :``%%``: literal "%" character
2045 :``%%``: literal "%" character
2036 :``%H``: changeset hash (40 hexadecimal digits)
2046 :``%H``: changeset hash (40 hexadecimal digits)
2037 :``%N``: number of patches being generated
2047 :``%N``: number of patches being generated
2038 :``%R``: changeset revision number
2048 :``%R``: changeset revision number
2039 :``%b``: basename of the exporting repository
2049 :``%b``: basename of the exporting repository
2040 :``%h``: short-form changeset hash (12 hexadecimal digits)
2050 :``%h``: short-form changeset hash (12 hexadecimal digits)
2041 :``%m``: first line of the commit message (only alphanumeric characters)
2051 :``%m``: first line of the commit message (only alphanumeric characters)
2042 :``%n``: zero-padded sequence number, starting at 1
2052 :``%n``: zero-padded sequence number, starting at 1
2043 :``%r``: zero-padded changeset revision number
2053 :``%r``: zero-padded changeset revision number
2044 :``\\``: literal "\\" character
2054 :``\\``: literal "\\" character
2045
2055
2046 Without the -a/--text option, export will avoid generating diffs
2056 Without the -a/--text option, export will avoid generating diffs
2047 of files it detects as binary. With -a, export will generate a
2057 of files it detects as binary. With -a, export will generate a
2048 diff anyway, probably with undesirable results.
2058 diff anyway, probably with undesirable results.
2049
2059
2050 With -B/--bookmark changesets reachable by the given bookmark are
2060 With -B/--bookmark changesets reachable by the given bookmark are
2051 selected.
2061 selected.
2052
2062
2053 Use the -g/--git option to generate diffs in the git extended diff
2063 Use the -g/--git option to generate diffs in the git extended diff
2054 format. See :hg:`help diffs` for more information.
2064 format. See :hg:`help diffs` for more information.
2055
2065
2056 With the --switch-parent option, the diff will be against the
2066 With the --switch-parent option, the diff will be against the
2057 second parent. It can be useful to review a merge.
2067 second parent. It can be useful to review a merge.
2058
2068
2059 .. container:: verbose
2069 .. container:: verbose
2060
2070
2061 Template:
2071 Template:
2062
2072
2063 The following keywords are supported in addition to the common template
2073 The following keywords are supported in addition to the common template
2064 keywords and functions. See also :hg:`help templates`.
2074 keywords and functions. See also :hg:`help templates`.
2065
2075
2066 :diff: String. Diff content.
2076 :diff: String. Diff content.
2067 :parents: List of strings. Parent nodes of the changeset.
2077 :parents: List of strings. Parent nodes of the changeset.
2068
2078
2069 Examples:
2079 Examples:
2070
2080
2071 - use export and import to transplant a bugfix to the current
2081 - use export and import to transplant a bugfix to the current
2072 branch::
2082 branch::
2073
2083
2074 hg export -r 9353 | hg import -
2084 hg export -r 9353 | hg import -
2075
2085
2076 - export all the changesets between two revisions to a file with
2086 - export all the changesets between two revisions to a file with
2077 rename information::
2087 rename information::
2078
2088
2079 hg export --git -r 123:150 > changes.txt
2089 hg export --git -r 123:150 > changes.txt
2080
2090
2081 - split outgoing changes into a series of patches with
2091 - split outgoing changes into a series of patches with
2082 descriptive names::
2092 descriptive names::
2083
2093
2084 hg export -r "outgoing()" -o "%n-%m.patch"
2094 hg export -r "outgoing()" -o "%n-%m.patch"
2085
2095
2086 Returns 0 on success.
2096 Returns 0 on success.
2087 """
2097 """
2088 opts = pycompat.byteskwargs(opts)
2098 opts = pycompat.byteskwargs(opts)
2089 bookmark = opts.get('bookmark')
2099 bookmark = opts.get('bookmark')
2090 changesets += tuple(opts.get('rev', []))
2100 changesets += tuple(opts.get('rev', []))
2091
2101
2092 if bookmark and changesets:
2102 if bookmark and changesets:
2093 raise error.Abort(_("-r and -B are mutually exclusive"))
2103 raise error.Abort(_("-r and -B are mutually exclusive"))
2094
2104
2095 if bookmark:
2105 if bookmark:
2096 if bookmark not in repo._bookmarks:
2106 if bookmark not in repo._bookmarks:
2097 raise error.Abort(_("bookmark '%s' not found") % bookmark)
2107 raise error.Abort(_("bookmark '%s' not found") % bookmark)
2098
2108
2099 revs = scmutil.bookmarkrevs(repo, bookmark)
2109 revs = scmutil.bookmarkrevs(repo, bookmark)
2100 else:
2110 else:
2101 if not changesets:
2111 if not changesets:
2102 changesets = ['.']
2112 changesets = ['.']
2103
2113
2104 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
2114 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
2105 revs = scmutil.revrange(repo, changesets)
2115 revs = scmutil.revrange(repo, changesets)
2106
2116
2107 if not revs:
2117 if not revs:
2108 raise error.Abort(_("export requires at least one changeset"))
2118 raise error.Abort(_("export requires at least one changeset"))
2109 if len(revs) > 1:
2119 if len(revs) > 1:
2110 ui.note(_('exporting patches:\n'))
2120 ui.note(_('exporting patches:\n'))
2111 else:
2121 else:
2112 ui.note(_('exporting patch:\n'))
2122 ui.note(_('exporting patch:\n'))
2113
2123
2114 fntemplate = opts.get('output')
2124 fntemplate = opts.get('output')
2115 if cmdutil.isstdiofilename(fntemplate):
2125 if cmdutil.isstdiofilename(fntemplate):
2116 fntemplate = ''
2126 fntemplate = ''
2117
2127
2118 if fntemplate:
2128 if fntemplate:
2119 fm = formatter.nullformatter(ui, 'export', opts)
2129 fm = formatter.nullformatter(ui, 'export', opts)
2120 else:
2130 else:
2121 ui.pager('export')
2131 ui.pager('export')
2122 fm = ui.formatter('export', opts)
2132 fm = ui.formatter('export', opts)
2123 with fm:
2133 with fm:
2124 cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
2134 cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
2125 switch_parent=opts.get('switch_parent'),
2135 switch_parent=opts.get('switch_parent'),
2126 opts=patch.diffallopts(ui, opts))
2136 opts=patch.diffallopts(ui, opts))
2127
2137
2128 @command('files',
2138 @command('files',
2129 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2139 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2130 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2140 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2131 ] + walkopts + formatteropts + subrepoopts,
2141 ] + walkopts + formatteropts + subrepoopts,
2132 _('[OPTION]... [FILE]...'),
2142 _('[OPTION]... [FILE]...'),
2133 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2143 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2134 intents={INTENT_READONLY})
2144 intents={INTENT_READONLY})
2135 def files(ui, repo, *pats, **opts):
2145 def files(ui, repo, *pats, **opts):
2136 """list tracked files
2146 """list tracked files
2137
2147
2138 Print files under Mercurial control in the working directory or
2148 Print files under Mercurial control in the working directory or
2139 specified revision for given files (excluding removed files).
2149 specified revision for given files (excluding removed files).
2140 Files can be specified as filenames or filesets.
2150 Files can be specified as filenames or filesets.
2141
2151
2142 If no files are given to match, this command prints the names
2152 If no files are given to match, this command prints the names
2143 of all files under Mercurial control.
2153 of all files under Mercurial control.
2144
2154
2145 .. container:: verbose
2155 .. container:: verbose
2146
2156
2147 Template:
2157 Template:
2148
2158
2149 The following keywords are supported in addition to the common template
2159 The following keywords are supported in addition to the common template
2150 keywords and functions. See also :hg:`help templates`.
2160 keywords and functions. See also :hg:`help templates`.
2151
2161
2152 :flags: String. Character denoting file's symlink and executable bits.
2162 :flags: String. Character denoting file's symlink and executable bits.
2153 :path: String. Repository-absolute path of the file.
2163 :path: String. Repository-absolute path of the file.
2154 :size: Integer. Size of the file in bytes.
2164 :size: Integer. Size of the file in bytes.
2155
2165
2156 Examples:
2166 Examples:
2157
2167
2158 - list all files under the current directory::
2168 - list all files under the current directory::
2159
2169
2160 hg files .
2170 hg files .
2161
2171
2162 - shows sizes and flags for current revision::
2172 - shows sizes and flags for current revision::
2163
2173
2164 hg files -vr .
2174 hg files -vr .
2165
2175
2166 - list all files named README::
2176 - list all files named README::
2167
2177
2168 hg files -I "**/README"
2178 hg files -I "**/README"
2169
2179
2170 - list all binary files::
2180 - list all binary files::
2171
2181
2172 hg files "set:binary()"
2182 hg files "set:binary()"
2173
2183
2174 - find files containing a regular expression::
2184 - find files containing a regular expression::
2175
2185
2176 hg files "set:grep('bob')"
2186 hg files "set:grep('bob')"
2177
2187
2178 - search tracked file contents with xargs and grep::
2188 - search tracked file contents with xargs and grep::
2179
2189
2180 hg files -0 | xargs -0 grep foo
2190 hg files -0 | xargs -0 grep foo
2181
2191
2182 See :hg:`help patterns` and :hg:`help filesets` for more information
2192 See :hg:`help patterns` and :hg:`help filesets` for more information
2183 on specifying file patterns.
2193 on specifying file patterns.
2184
2194
2185 Returns 0 if a match is found, 1 otherwise.
2195 Returns 0 if a match is found, 1 otherwise.
2186
2196
2187 """
2197 """
2188
2198
2189 opts = pycompat.byteskwargs(opts)
2199 opts = pycompat.byteskwargs(opts)
2190 rev = opts.get('rev')
2200 rev = opts.get('rev')
2191 if rev:
2201 if rev:
2192 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2202 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2193 ctx = scmutil.revsingle(repo, rev, None)
2203 ctx = scmutil.revsingle(repo, rev, None)
2194
2204
2195 end = '\n'
2205 end = '\n'
2196 if opts.get('print0'):
2206 if opts.get('print0'):
2197 end = '\0'
2207 end = '\0'
2198 fmt = '%s' + end
2208 fmt = '%s' + end
2199
2209
2200 m = scmutil.match(ctx, pats, opts)
2210 m = scmutil.match(ctx, pats, opts)
2201 ui.pager('files')
2211 ui.pager('files')
2202 with ui.formatter('files', opts) as fm:
2212 with ui.formatter('files', opts) as fm:
2203 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2213 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2204
2214
2205 @command(
2215 @command(
2206 'forget',
2216 'forget',
2207 [('i', 'interactive', None, _('use interactive mode')),
2217 [('i', 'interactive', None, _('use interactive mode')),
2208 ] + walkopts + dryrunopts,
2218 ] + walkopts + dryrunopts,
2209 _('[OPTION]... FILE...'),
2219 _('[OPTION]... FILE...'),
2210 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2220 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
2211 helpbasic=True, inferrepo=True)
2221 helpbasic=True, inferrepo=True)
2212 def forget(ui, repo, *pats, **opts):
2222 def forget(ui, repo, *pats, **opts):
2213 """forget the specified files on the next commit
2223 """forget the specified files on the next commit
2214
2224
2215 Mark the specified files so they will no longer be tracked
2225 Mark the specified files so they will no longer be tracked
2216 after the next commit.
2226 after the next commit.
2217
2227
2218 This only removes files from the current branch, not from the
2228 This only removes files from the current branch, not from the
2219 entire project history, and it does not delete them from the
2229 entire project history, and it does not delete them from the
2220 working directory.
2230 working directory.
2221
2231
2222 To delete the file from the working directory, see :hg:`remove`.
2232 To delete the file from the working directory, see :hg:`remove`.
2223
2233
2224 To undo a forget before the next commit, see :hg:`add`.
2234 To undo a forget before the next commit, see :hg:`add`.
2225
2235
2226 .. container:: verbose
2236 .. container:: verbose
2227
2237
2228 Examples:
2238 Examples:
2229
2239
2230 - forget newly-added binary files::
2240 - forget newly-added binary files::
2231
2241
2232 hg forget "set:added() and binary()"
2242 hg forget "set:added() and binary()"
2233
2243
2234 - forget files that would be excluded by .hgignore::
2244 - forget files that would be excluded by .hgignore::
2235
2245
2236 hg forget "set:hgignore()"
2246 hg forget "set:hgignore()"
2237
2247
2238 Returns 0 on success.
2248 Returns 0 on success.
2239 """
2249 """
2240
2250
2241 opts = pycompat.byteskwargs(opts)
2251 opts = pycompat.byteskwargs(opts)
2242 if not pats:
2252 if not pats:
2243 raise error.Abort(_('no files specified'))
2253 raise error.Abort(_('no files specified'))
2244
2254
2245 m = scmutil.match(repo[None], pats, opts)
2255 m = scmutil.match(repo[None], pats, opts)
2246 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
2256 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
2247 rejected = cmdutil.forget(ui, repo, m, prefix="",
2257 rejected = cmdutil.forget(ui, repo, m, prefix="",
2248 explicitonly=False, dryrun=dryrun,
2258 explicitonly=False, dryrun=dryrun,
2249 interactive=interactive)[0]
2259 interactive=interactive)[0]
2250 return rejected and 1 or 0
2260 return rejected and 1 or 0
2251
2261
2252 @command(
2262 @command(
2253 'graft',
2263 'graft',
2254 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2264 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2255 ('', 'base', '',
2265 ('', 'base', '',
2256 _('base revision when doing the graft merge (ADVANCED)'), _('REV')),
2266 _('base revision when doing the graft merge (ADVANCED)'), _('REV')),
2257 ('c', 'continue', False, _('resume interrupted graft')),
2267 ('c', 'continue', False, _('resume interrupted graft')),
2258 ('', 'stop', False, _('stop interrupted graft')),
2268 ('', 'stop', False, _('stop interrupted graft')),
2259 ('', 'abort', False, _('abort interrupted graft')),
2269 ('', 'abort', False, _('abort interrupted graft')),
2260 ('e', 'edit', False, _('invoke editor on commit messages')),
2270 ('e', 'edit', False, _('invoke editor on commit messages')),
2261 ('', 'log', None, _('append graft info to log message')),
2271 ('', 'log', None, _('append graft info to log message')),
2262 ('', 'no-commit', None,
2272 ('', 'no-commit', None,
2263 _("don't commit, just apply the changes in working directory")),
2273 _("don't commit, just apply the changes in working directory")),
2264 ('f', 'force', False, _('force graft')),
2274 ('f', 'force', False, _('force graft')),
2265 ('D', 'currentdate', False,
2275 ('D', 'currentdate', False,
2266 _('record the current date as commit date')),
2276 _('record the current date as commit date')),
2267 ('U', 'currentuser', False,
2277 ('U', 'currentuser', False,
2268 _('record the current user as committer'))]
2278 _('record the current user as committer'))]
2269 + commitopts2 + mergetoolopts + dryrunopts,
2279 + commitopts2 + mergetoolopts + dryrunopts,
2270 _('[OPTION]... [-r REV]... REV...'),
2280 _('[OPTION]... [-r REV]... REV...'),
2271 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
2281 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
2272 def graft(ui, repo, *revs, **opts):
2282 def graft(ui, repo, *revs, **opts):
2273 '''copy changes from other branches onto the current branch
2283 '''copy changes from other branches onto the current branch
2274
2284
2275 This command uses Mercurial's merge logic to copy individual
2285 This command uses Mercurial's merge logic to copy individual
2276 changes from other branches without merging branches in the
2286 changes from other branches without merging branches in the
2277 history graph. This is sometimes known as 'backporting' or
2287 history graph. This is sometimes known as 'backporting' or
2278 'cherry-picking'. By default, graft will copy user, date, and
2288 'cherry-picking'. By default, graft will copy user, date, and
2279 description from the source changesets.
2289 description from the source changesets.
2280
2290
2281 Changesets that are ancestors of the current revision, that have
2291 Changesets that are ancestors of the current revision, that have
2282 already been grafted, or that are merges will be skipped.
2292 already been grafted, or that are merges will be skipped.
2283
2293
2284 If --log is specified, log messages will have a comment appended
2294 If --log is specified, log messages will have a comment appended
2285 of the form::
2295 of the form::
2286
2296
2287 (grafted from CHANGESETHASH)
2297 (grafted from CHANGESETHASH)
2288
2298
2289 If --force is specified, revisions will be grafted even if they
2299 If --force is specified, revisions will be grafted even if they
2290 are already ancestors of, or have been grafted to, the destination.
2300 are already ancestors of, or have been grafted to, the destination.
2291 This is useful when the revisions have since been backed out.
2301 This is useful when the revisions have since been backed out.
2292
2302
2293 If a graft merge results in conflicts, the graft process is
2303 If a graft merge results in conflicts, the graft process is
2294 interrupted so that the current merge can be manually resolved.
2304 interrupted so that the current merge can be manually resolved.
2295 Once all conflicts are addressed, the graft process can be
2305 Once all conflicts are addressed, the graft process can be
2296 continued with the -c/--continue option.
2306 continued with the -c/--continue option.
2297
2307
2298 The -c/--continue option reapplies all the earlier options.
2308 The -c/--continue option reapplies all the earlier options.
2299
2309
2300 .. container:: verbose
2310 .. container:: verbose
2301
2311
2302 The --base option exposes more of how graft internally uses merge with a
2312 The --base option exposes more of how graft internally uses merge with a
2303 custom base revision. --base can be used to specify another ancestor than
2313 custom base revision. --base can be used to specify another ancestor than
2304 the first and only parent.
2314 the first and only parent.
2305
2315
2306 The command::
2316 The command::
2307
2317
2308 hg graft -r 345 --base 234
2318 hg graft -r 345 --base 234
2309
2319
2310 is thus pretty much the same as::
2320 is thus pretty much the same as::
2311
2321
2312 hg diff -r 234 -r 345 | hg import
2322 hg diff -r 234 -r 345 | hg import
2313
2323
2314 but using merge to resolve conflicts and track moved files.
2324 but using merge to resolve conflicts and track moved files.
2315
2325
2316 The result of a merge can thus be backported as a single commit by
2326 The result of a merge can thus be backported as a single commit by
2317 specifying one of the merge parents as base, and thus effectively
2327 specifying one of the merge parents as base, and thus effectively
2318 grafting the changes from the other side.
2328 grafting the changes from the other side.
2319
2329
2320 It is also possible to collapse multiple changesets and clean up history
2330 It is also possible to collapse multiple changesets and clean up history
2321 by specifying another ancestor as base, much like rebase --collapse
2331 by specifying another ancestor as base, much like rebase --collapse
2322 --keep.
2332 --keep.
2323
2333
2324 The commit message can be tweaked after the fact using commit --amend .
2334 The commit message can be tweaked after the fact using commit --amend .
2325
2335
2326 For using non-ancestors as the base to backout changes, see the backout
2336 For using non-ancestors as the base to backout changes, see the backout
2327 command and the hidden --parent option.
2337 command and the hidden --parent option.
2328
2338
2329 .. container:: verbose
2339 .. container:: verbose
2330
2340
2331 Examples:
2341 Examples:
2332
2342
2333 - copy a single change to the stable branch and edit its description::
2343 - copy a single change to the stable branch and edit its description::
2334
2344
2335 hg update stable
2345 hg update stable
2336 hg graft --edit 9393
2346 hg graft --edit 9393
2337
2347
2338 - graft a range of changesets with one exception, updating dates::
2348 - graft a range of changesets with one exception, updating dates::
2339
2349
2340 hg graft -D "2085::2093 and not 2091"
2350 hg graft -D "2085::2093 and not 2091"
2341
2351
2342 - continue a graft after resolving conflicts::
2352 - continue a graft after resolving conflicts::
2343
2353
2344 hg graft -c
2354 hg graft -c
2345
2355
2346 - show the source of a grafted changeset::
2356 - show the source of a grafted changeset::
2347
2357
2348 hg log --debug -r .
2358 hg log --debug -r .
2349
2359
2350 - show revisions sorted by date::
2360 - show revisions sorted by date::
2351
2361
2352 hg log -r "sort(all(), date)"
2362 hg log -r "sort(all(), date)"
2353
2363
2354 - backport the result of a merge as a single commit::
2364 - backport the result of a merge as a single commit::
2355
2365
2356 hg graft -r 123 --base 123^
2366 hg graft -r 123 --base 123^
2357
2367
2358 - land a feature branch as one changeset::
2368 - land a feature branch as one changeset::
2359
2369
2360 hg up -cr default
2370 hg up -cr default
2361 hg graft -r featureX --base "ancestor('featureX', 'default')"
2371 hg graft -r featureX --base "ancestor('featureX', 'default')"
2362
2372
2363 See :hg:`help revisions` for more about specifying revisions.
2373 See :hg:`help revisions` for more about specifying revisions.
2364
2374
2365 Returns 0 on successful completion.
2375 Returns 0 on successful completion.
2366 '''
2376 '''
2367 with repo.wlock():
2377 with repo.wlock():
2368 return _dograft(ui, repo, *revs, **opts)
2378 return _dograft(ui, repo, *revs, **opts)
2369
2379
2370 def _dograft(ui, repo, *revs, **opts):
2380 def _dograft(ui, repo, *revs, **opts):
2371 opts = pycompat.byteskwargs(opts)
2381 opts = pycompat.byteskwargs(opts)
2372 if revs and opts.get('rev'):
2382 if revs and opts.get('rev'):
2373 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2383 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2374 'revision ordering!\n'))
2384 'revision ordering!\n'))
2375
2385
2376 revs = list(revs)
2386 revs = list(revs)
2377 revs.extend(opts.get('rev'))
2387 revs.extend(opts.get('rev'))
2378 basectx = None
2388 basectx = None
2379 if opts.get('base'):
2389 if opts.get('base'):
2380 basectx = scmutil.revsingle(repo, opts['base'], None)
2390 basectx = scmutil.revsingle(repo, opts['base'], None)
2381 # a dict of data to be stored in state file
2391 # a dict of data to be stored in state file
2382 statedata = {}
2392 statedata = {}
2383 # list of new nodes created by ongoing graft
2393 # list of new nodes created by ongoing graft
2384 statedata['newnodes'] = []
2394 statedata['newnodes'] = []
2385
2395
2386 if not opts.get('user') and opts.get('currentuser'):
2396 if not opts.get('user') and opts.get('currentuser'):
2387 opts['user'] = ui.username()
2397 opts['user'] = ui.username()
2388 if not opts.get('date') and opts.get('currentdate'):
2398 if not opts.get('date') and opts.get('currentdate'):
2389 opts['date'] = "%d %d" % dateutil.makedate()
2399 opts['date'] = "%d %d" % dateutil.makedate()
2390
2400
2391 editor = cmdutil.getcommiteditor(editform='graft',
2401 editor = cmdutil.getcommiteditor(editform='graft',
2392 **pycompat.strkwargs(opts))
2402 **pycompat.strkwargs(opts))
2393
2403
2394 cont = False
2404 cont = False
2395 if opts.get('no_commit'):
2405 if opts.get('no_commit'):
2396 if opts.get('edit'):
2406 if opts.get('edit'):
2397 raise error.Abort(_("cannot specify --no-commit and "
2407 raise error.Abort(_("cannot specify --no-commit and "
2398 "--edit together"))
2408 "--edit together"))
2399 if opts.get('currentuser'):
2409 if opts.get('currentuser'):
2400 raise error.Abort(_("cannot specify --no-commit and "
2410 raise error.Abort(_("cannot specify --no-commit and "
2401 "--currentuser together"))
2411 "--currentuser together"))
2402 if opts.get('currentdate'):
2412 if opts.get('currentdate'):
2403 raise error.Abort(_("cannot specify --no-commit and "
2413 raise error.Abort(_("cannot specify --no-commit and "
2404 "--currentdate together"))
2414 "--currentdate together"))
2405 if opts.get('log'):
2415 if opts.get('log'):
2406 raise error.Abort(_("cannot specify --no-commit and "
2416 raise error.Abort(_("cannot specify --no-commit and "
2407 "--log together"))
2417 "--log together"))
2408
2418
2409 graftstate = statemod.cmdstate(repo, 'graftstate')
2419 graftstate = statemod.cmdstate(repo, 'graftstate')
2410
2420
2411 if opts.get('stop'):
2421 if opts.get('stop'):
2412 if opts.get('continue'):
2422 if opts.get('continue'):
2413 raise error.Abort(_("cannot use '--continue' and "
2423 raise error.Abort(_("cannot use '--continue' and "
2414 "'--stop' together"))
2424 "'--stop' together"))
2415 if opts.get('abort'):
2425 if opts.get('abort'):
2416 raise error.Abort(_("cannot use '--abort' and '--stop' together"))
2426 raise error.Abort(_("cannot use '--abort' and '--stop' together"))
2417
2427
2418 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2428 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2419 opts.get('date'), opts.get('currentdate'),
2429 opts.get('date'), opts.get('currentdate'),
2420 opts.get('currentuser'), opts.get('rev'))):
2430 opts.get('currentuser'), opts.get('rev'))):
2421 raise error.Abort(_("cannot specify any other flag with '--stop'"))
2431 raise error.Abort(_("cannot specify any other flag with '--stop'"))
2422 return _stopgraft(ui, repo, graftstate)
2432 return _stopgraft(ui, repo, graftstate)
2423 elif opts.get('abort'):
2433 elif opts.get('abort'):
2424 if opts.get('continue'):
2434 if opts.get('continue'):
2425 raise error.Abort(_("cannot use '--continue' and "
2435 raise error.Abort(_("cannot use '--continue' and "
2426 "'--abort' together"))
2436 "'--abort' together"))
2427 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2437 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2428 opts.get('date'), opts.get('currentdate'),
2438 opts.get('date'), opts.get('currentdate'),
2429 opts.get('currentuser'), opts.get('rev'))):
2439 opts.get('currentuser'), opts.get('rev'))):
2430 raise error.Abort(_("cannot specify any other flag with '--abort'"))
2440 raise error.Abort(_("cannot specify any other flag with '--abort'"))
2431
2441
2432 return _abortgraft(ui, repo, graftstate)
2442 return _abortgraft(ui, repo, graftstate)
2433 elif opts.get('continue'):
2443 elif opts.get('continue'):
2434 cont = True
2444 cont = True
2435 if revs:
2445 if revs:
2436 raise error.Abort(_("can't specify --continue and revisions"))
2446 raise error.Abort(_("can't specify --continue and revisions"))
2437 # read in unfinished revisions
2447 # read in unfinished revisions
2438 if graftstate.exists():
2448 if graftstate.exists():
2439 statedata = _readgraftstate(repo, graftstate)
2449 statedata = _readgraftstate(repo, graftstate)
2440 if statedata.get('date'):
2450 if statedata.get('date'):
2441 opts['date'] = statedata['date']
2451 opts['date'] = statedata['date']
2442 if statedata.get('user'):
2452 if statedata.get('user'):
2443 opts['user'] = statedata['user']
2453 opts['user'] = statedata['user']
2444 if statedata.get('log'):
2454 if statedata.get('log'):
2445 opts['log'] = True
2455 opts['log'] = True
2446 if statedata.get('no_commit'):
2456 if statedata.get('no_commit'):
2447 opts['no_commit'] = statedata.get('no_commit')
2457 opts['no_commit'] = statedata.get('no_commit')
2448 nodes = statedata['nodes']
2458 nodes = statedata['nodes']
2449 revs = [repo[node].rev() for node in nodes]
2459 revs = [repo[node].rev() for node in nodes]
2450 else:
2460 else:
2451 cmdutil.wrongtooltocontinue(repo, _('graft'))
2461 cmdutil.wrongtooltocontinue(repo, _('graft'))
2452 else:
2462 else:
2453 if not revs:
2463 if not revs:
2454 raise error.Abort(_('no revisions specified'))
2464 raise error.Abort(_('no revisions specified'))
2455 cmdutil.checkunfinished(repo)
2465 cmdutil.checkunfinished(repo)
2456 cmdutil.bailifchanged(repo)
2466 cmdutil.bailifchanged(repo)
2457 revs = scmutil.revrange(repo, revs)
2467 revs = scmutil.revrange(repo, revs)
2458
2468
2459 skipped = set()
2469 skipped = set()
2460 if basectx is None:
2470 if basectx is None:
2461 # check for merges
2471 # check for merges
2462 for rev in repo.revs('%ld and merge()', revs):
2472 for rev in repo.revs('%ld and merge()', revs):
2463 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2473 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2464 skipped.add(rev)
2474 skipped.add(rev)
2465 revs = [r for r in revs if r not in skipped]
2475 revs = [r for r in revs if r not in skipped]
2466 if not revs:
2476 if not revs:
2467 return -1
2477 return -1
2468 if basectx is not None and len(revs) != 1:
2478 if basectx is not None and len(revs) != 1:
2469 raise error.Abort(_('only one revision allowed with --base '))
2479 raise error.Abort(_('only one revision allowed with --base '))
2470
2480
2471 # Don't check in the --continue case, in effect retaining --force across
2481 # Don't check in the --continue case, in effect retaining --force across
2472 # --continues. That's because without --force, any revisions we decided to
2482 # --continues. That's because without --force, any revisions we decided to
2473 # skip would have been filtered out here, so they wouldn't have made their
2483 # skip would have been filtered out here, so they wouldn't have made their
2474 # way to the graftstate. With --force, any revisions we would have otherwise
2484 # way to the graftstate. With --force, any revisions we would have otherwise
2475 # skipped would not have been filtered out, and if they hadn't been applied
2485 # skipped would not have been filtered out, and if they hadn't been applied
2476 # already, they'd have been in the graftstate.
2486 # already, they'd have been in the graftstate.
2477 if not (cont or opts.get('force')) and basectx is None:
2487 if not (cont or opts.get('force')) and basectx is None:
2478 # check for ancestors of dest branch
2488 # check for ancestors of dest branch
2479 crev = repo['.'].rev()
2489 crev = repo['.'].rev()
2480 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2490 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2481 # XXX make this lazy in the future
2491 # XXX make this lazy in the future
2482 # don't mutate while iterating, create a copy
2492 # don't mutate while iterating, create a copy
2483 for rev in list(revs):
2493 for rev in list(revs):
2484 if rev in ancestors:
2494 if rev in ancestors:
2485 ui.warn(_('skipping ancestor revision %d:%s\n') %
2495 ui.warn(_('skipping ancestor revision %d:%s\n') %
2486 (rev, repo[rev]))
2496 (rev, repo[rev]))
2487 # XXX remove on list is slow
2497 # XXX remove on list is slow
2488 revs.remove(rev)
2498 revs.remove(rev)
2489 if not revs:
2499 if not revs:
2490 return -1
2500 return -1
2491
2501
2492 # analyze revs for earlier grafts
2502 # analyze revs for earlier grafts
2493 ids = {}
2503 ids = {}
2494 for ctx in repo.set("%ld", revs):
2504 for ctx in repo.set("%ld", revs):
2495 ids[ctx.hex()] = ctx.rev()
2505 ids[ctx.hex()] = ctx.rev()
2496 n = ctx.extra().get('source')
2506 n = ctx.extra().get('source')
2497 if n:
2507 if n:
2498 ids[n] = ctx.rev()
2508 ids[n] = ctx.rev()
2499
2509
2500 # check ancestors for earlier grafts
2510 # check ancestors for earlier grafts
2501 ui.debug('scanning for duplicate grafts\n')
2511 ui.debug('scanning for duplicate grafts\n')
2502
2512
2503 # The only changesets we can be sure doesn't contain grafts of any
2513 # The only changesets we can be sure doesn't contain grafts of any
2504 # revs, are the ones that are common ancestors of *all* revs:
2514 # revs, are the ones that are common ancestors of *all* revs:
2505 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2515 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2506 ctx = repo[rev]
2516 ctx = repo[rev]
2507 n = ctx.extra().get('source')
2517 n = ctx.extra().get('source')
2508 if n in ids:
2518 if n in ids:
2509 try:
2519 try:
2510 r = repo[n].rev()
2520 r = repo[n].rev()
2511 except error.RepoLookupError:
2521 except error.RepoLookupError:
2512 r = None
2522 r = None
2513 if r in revs:
2523 if r in revs:
2514 ui.warn(_('skipping revision %d:%s '
2524 ui.warn(_('skipping revision %d:%s '
2515 '(already grafted to %d:%s)\n')
2525 '(already grafted to %d:%s)\n')
2516 % (r, repo[r], rev, ctx))
2526 % (r, repo[r], rev, ctx))
2517 revs.remove(r)
2527 revs.remove(r)
2518 elif ids[n] in revs:
2528 elif ids[n] in revs:
2519 if r is None:
2529 if r is None:
2520 ui.warn(_('skipping already grafted revision %d:%s '
2530 ui.warn(_('skipping already grafted revision %d:%s '
2521 '(%d:%s also has unknown origin %s)\n')
2531 '(%d:%s also has unknown origin %s)\n')
2522 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2532 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2523 else:
2533 else:
2524 ui.warn(_('skipping already grafted revision %d:%s '
2534 ui.warn(_('skipping already grafted revision %d:%s '
2525 '(%d:%s also has origin %d:%s)\n')
2535 '(%d:%s also has origin %d:%s)\n')
2526 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2536 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2527 revs.remove(ids[n])
2537 revs.remove(ids[n])
2528 elif ctx.hex() in ids:
2538 elif ctx.hex() in ids:
2529 r = ids[ctx.hex()]
2539 r = ids[ctx.hex()]
2530 if r in revs:
2540 if r in revs:
2531 ui.warn(_('skipping already grafted revision %d:%s '
2541 ui.warn(_('skipping already grafted revision %d:%s '
2532 '(was grafted from %d:%s)\n') %
2542 '(was grafted from %d:%s)\n') %
2533 (r, repo[r], rev, ctx))
2543 (r, repo[r], rev, ctx))
2534 revs.remove(r)
2544 revs.remove(r)
2535 if not revs:
2545 if not revs:
2536 return -1
2546 return -1
2537
2547
2538 if opts.get('no_commit'):
2548 if opts.get('no_commit'):
2539 statedata['no_commit'] = True
2549 statedata['no_commit'] = True
2540 for pos, ctx in enumerate(repo.set("%ld", revs)):
2550 for pos, ctx in enumerate(repo.set("%ld", revs)):
2541 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2551 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2542 ctx.description().split('\n', 1)[0])
2552 ctx.description().split('\n', 1)[0])
2543 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2553 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2544 if names:
2554 if names:
2545 desc += ' (%s)' % ' '.join(names)
2555 desc += ' (%s)' % ' '.join(names)
2546 ui.status(_('grafting %s\n') % desc)
2556 ui.status(_('grafting %s\n') % desc)
2547 if opts.get('dry_run'):
2557 if opts.get('dry_run'):
2548 continue
2558 continue
2549
2559
2550 source = ctx.extra().get('source')
2560 source = ctx.extra().get('source')
2551 extra = {}
2561 extra = {}
2552 if source:
2562 if source:
2553 extra['source'] = source
2563 extra['source'] = source
2554 extra['intermediate-source'] = ctx.hex()
2564 extra['intermediate-source'] = ctx.hex()
2555 else:
2565 else:
2556 extra['source'] = ctx.hex()
2566 extra['source'] = ctx.hex()
2557 user = ctx.user()
2567 user = ctx.user()
2558 if opts.get('user'):
2568 if opts.get('user'):
2559 user = opts['user']
2569 user = opts['user']
2560 statedata['user'] = user
2570 statedata['user'] = user
2561 date = ctx.date()
2571 date = ctx.date()
2562 if opts.get('date'):
2572 if opts.get('date'):
2563 date = opts['date']
2573 date = opts['date']
2564 statedata['date'] = date
2574 statedata['date'] = date
2565 message = ctx.description()
2575 message = ctx.description()
2566 if opts.get('log'):
2576 if opts.get('log'):
2567 message += '\n(grafted from %s)' % ctx.hex()
2577 message += '\n(grafted from %s)' % ctx.hex()
2568 statedata['log'] = True
2578 statedata['log'] = True
2569
2579
2570 # we don't merge the first commit when continuing
2580 # we don't merge the first commit when continuing
2571 if not cont:
2581 if not cont:
2572 # perform the graft merge with p1(rev) as 'ancestor'
2582 # perform the graft merge with p1(rev) as 'ancestor'
2573 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
2583 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
2574 base = ctx.p1() if basectx is None else basectx
2584 base = ctx.p1() if basectx is None else basectx
2575 with ui.configoverride(overrides, 'graft'):
2585 with ui.configoverride(overrides, 'graft'):
2576 stats = mergemod.graft(repo, ctx, base, ['local', 'graft'])
2586 stats = mergemod.graft(repo, ctx, base, ['local', 'graft'])
2577 # report any conflicts
2587 # report any conflicts
2578 if stats.unresolvedcount > 0:
2588 if stats.unresolvedcount > 0:
2579 # write out state for --continue
2589 # write out state for --continue
2580 nodes = [repo[rev].hex() for rev in revs[pos:]]
2590 nodes = [repo[rev].hex() for rev in revs[pos:]]
2581 statedata['nodes'] = nodes
2591 statedata['nodes'] = nodes
2582 stateversion = 1
2592 stateversion = 1
2583 graftstate.save(stateversion, statedata)
2593 graftstate.save(stateversion, statedata)
2584 hint = _("use 'hg resolve' and 'hg graft --continue'")
2594 hint = _("use 'hg resolve' and 'hg graft --continue'")
2585 raise error.Abort(
2595 raise error.Abort(
2586 _("unresolved conflicts, can't continue"),
2596 _("unresolved conflicts, can't continue"),
2587 hint=hint)
2597 hint=hint)
2588 else:
2598 else:
2589 cont = False
2599 cont = False
2590
2600
2591 # commit if --no-commit is false
2601 # commit if --no-commit is false
2592 if not opts.get('no_commit'):
2602 if not opts.get('no_commit'):
2593 node = repo.commit(text=message, user=user, date=date, extra=extra,
2603 node = repo.commit(text=message, user=user, date=date, extra=extra,
2594 editor=editor)
2604 editor=editor)
2595 if node is None:
2605 if node is None:
2596 ui.warn(
2606 ui.warn(
2597 _('note: graft of %d:%s created no changes to commit\n') %
2607 _('note: graft of %d:%s created no changes to commit\n') %
2598 (ctx.rev(), ctx))
2608 (ctx.rev(), ctx))
2599 # checking that newnodes exist because old state files won't have it
2609 # checking that newnodes exist because old state files won't have it
2600 elif statedata.get('newnodes') is not None:
2610 elif statedata.get('newnodes') is not None:
2601 statedata['newnodes'].append(node)
2611 statedata['newnodes'].append(node)
2602
2612
2603 # remove state when we complete successfully
2613 # remove state when we complete successfully
2604 if not opts.get('dry_run'):
2614 if not opts.get('dry_run'):
2605 graftstate.delete()
2615 graftstate.delete()
2606
2616
2607 return 0
2617 return 0
2608
2618
2609 def _abortgraft(ui, repo, graftstate):
2619 def _abortgraft(ui, repo, graftstate):
2610 """abort the interrupted graft and rollbacks to the state before interrupted
2620 """abort the interrupted graft and rollbacks to the state before interrupted
2611 graft"""
2621 graft"""
2612 if not graftstate.exists():
2622 if not graftstate.exists():
2613 raise error.Abort(_("no interrupted graft to abort"))
2623 raise error.Abort(_("no interrupted graft to abort"))
2614 statedata = _readgraftstate(repo, graftstate)
2624 statedata = _readgraftstate(repo, graftstate)
2615 newnodes = statedata.get('newnodes')
2625 newnodes = statedata.get('newnodes')
2616 if newnodes is None:
2626 if newnodes is None:
2617 # and old graft state which does not have all the data required to abort
2627 # and old graft state which does not have all the data required to abort
2618 # the graft
2628 # the graft
2619 raise error.Abort(_("cannot abort using an old graftstate"))
2629 raise error.Abort(_("cannot abort using an old graftstate"))
2620
2630
2621 # changeset from which graft operation was started
2631 # changeset from which graft operation was started
2622 startctx = None
2632 startctx = None
2623 if len(newnodes) > 0:
2633 if len(newnodes) > 0:
2624 startctx = repo[newnodes[0]].p1()
2634 startctx = repo[newnodes[0]].p1()
2625 else:
2635 else:
2626 startctx = repo['.']
2636 startctx = repo['.']
2627 # whether to strip or not
2637 # whether to strip or not
2628 cleanup = False
2638 cleanup = False
2629 if newnodes:
2639 if newnodes:
2630 newnodes = [repo[r].rev() for r in newnodes]
2640 newnodes = [repo[r].rev() for r in newnodes]
2631 cleanup = True
2641 cleanup = True
2632 # checking that none of the newnodes turned public or is public
2642 # checking that none of the newnodes turned public or is public
2633 immutable = [c for c in newnodes if not repo[c].mutable()]
2643 immutable = [c for c in newnodes if not repo[c].mutable()]
2634 if immutable:
2644 if immutable:
2635 repo.ui.warn(_("cannot clean up public changesets %s\n")
2645 repo.ui.warn(_("cannot clean up public changesets %s\n")
2636 % ', '.join(bytes(repo[r]) for r in immutable),
2646 % ', '.join(bytes(repo[r]) for r in immutable),
2637 hint=_("see 'hg help phases' for details"))
2647 hint=_("see 'hg help phases' for details"))
2638 cleanup = False
2648 cleanup = False
2639
2649
2640 # checking that no new nodes are created on top of grafted revs
2650 # checking that no new nodes are created on top of grafted revs
2641 desc = set(repo.changelog.descendants(newnodes))
2651 desc = set(repo.changelog.descendants(newnodes))
2642 if desc - set(newnodes):
2652 if desc - set(newnodes):
2643 repo.ui.warn(_("new changesets detected on destination "
2653 repo.ui.warn(_("new changesets detected on destination "
2644 "branch, can't strip\n"))
2654 "branch, can't strip\n"))
2645 cleanup = False
2655 cleanup = False
2646
2656
2647 if cleanup:
2657 if cleanup:
2648 with repo.wlock(), repo.lock():
2658 with repo.wlock(), repo.lock():
2649 hg.updaterepo(repo, startctx.node(), overwrite=True)
2659 hg.updaterepo(repo, startctx.node(), overwrite=True)
2650 # stripping the new nodes created
2660 # stripping the new nodes created
2651 strippoints = [c.node() for c in repo.set("roots(%ld)",
2661 strippoints = [c.node() for c in repo.set("roots(%ld)",
2652 newnodes)]
2662 newnodes)]
2653 repair.strip(repo.ui, repo, strippoints, backup=False)
2663 repair.strip(repo.ui, repo, strippoints, backup=False)
2654
2664
2655 if not cleanup:
2665 if not cleanup:
2656 # we don't update to the startnode if we can't strip
2666 # we don't update to the startnode if we can't strip
2657 startctx = repo['.']
2667 startctx = repo['.']
2658 hg.updaterepo(repo, startctx.node(), overwrite=True)
2668 hg.updaterepo(repo, startctx.node(), overwrite=True)
2659
2669
2660 ui.status(_("graft aborted\n"))
2670 ui.status(_("graft aborted\n"))
2661 ui.status(_("working directory is now at %s\n") % startctx.hex()[:12])
2671 ui.status(_("working directory is now at %s\n") % startctx.hex()[:12])
2662 graftstate.delete()
2672 graftstate.delete()
2663 return 0
2673 return 0
2664
2674
2665 def _readgraftstate(repo, graftstate):
2675 def _readgraftstate(repo, graftstate):
2666 """read the graft state file and return a dict of the data stored in it"""
2676 """read the graft state file and return a dict of the data stored in it"""
2667 try:
2677 try:
2668 return graftstate.read()
2678 return graftstate.read()
2669 except error.CorruptedState:
2679 except error.CorruptedState:
2670 nodes = repo.vfs.read('graftstate').splitlines()
2680 nodes = repo.vfs.read('graftstate').splitlines()
2671 return {'nodes': nodes}
2681 return {'nodes': nodes}
2672
2682
2673 def _stopgraft(ui, repo, graftstate):
2683 def _stopgraft(ui, repo, graftstate):
2674 """stop the interrupted graft"""
2684 """stop the interrupted graft"""
2675 if not graftstate.exists():
2685 if not graftstate.exists():
2676 raise error.Abort(_("no interrupted graft found"))
2686 raise error.Abort(_("no interrupted graft found"))
2677 pctx = repo['.']
2687 pctx = repo['.']
2678 hg.updaterepo(repo, pctx.node(), overwrite=True)
2688 hg.updaterepo(repo, pctx.node(), overwrite=True)
2679 graftstate.delete()
2689 graftstate.delete()
2680 ui.status(_("stopped the interrupted graft\n"))
2690 ui.status(_("stopped the interrupted graft\n"))
2681 ui.status(_("working directory is now at %s\n") % pctx.hex()[:12])
2691 ui.status(_("working directory is now at %s\n") % pctx.hex()[:12])
2682 return 0
2692 return 0
2683
2693
2684 @command('grep',
2694 @command('grep',
2685 [('0', 'print0', None, _('end fields with NUL')),
2695 [('0', 'print0', None, _('end fields with NUL')),
2686 ('', 'all', None, _('print all revisions that match (DEPRECATED) ')),
2696 ('', 'all', None, _('print all revisions that match (DEPRECATED) ')),
2687 ('', 'diff', None, _('print all revisions when the term was introduced '
2697 ('', 'diff', None, _('print all revisions when the term was introduced '
2688 'or removed')),
2698 'or removed')),
2689 ('a', 'text', None, _('treat all files as text')),
2699 ('a', 'text', None, _('treat all files as text')),
2690 ('f', 'follow', None,
2700 ('f', 'follow', None,
2691 _('follow changeset history,'
2701 _('follow changeset history,'
2692 ' or file history across copies and renames')),
2702 ' or file history across copies and renames')),
2693 ('i', 'ignore-case', None, _('ignore case when matching')),
2703 ('i', 'ignore-case', None, _('ignore case when matching')),
2694 ('l', 'files-with-matches', None,
2704 ('l', 'files-with-matches', None,
2695 _('print only filenames and revisions that match')),
2705 _('print only filenames and revisions that match')),
2696 ('n', 'line-number', None, _('print matching line numbers')),
2706 ('n', 'line-number', None, _('print matching line numbers')),
2697 ('r', 'rev', [],
2707 ('r', 'rev', [],
2698 _('only search files changed within revision range'), _('REV')),
2708 _('only search files changed within revision range'), _('REV')),
2699 ('', 'all-files', None,
2709 ('', 'all-files', None,
2700 _('include all files in the changeset while grepping (EXPERIMENTAL)')),
2710 _('include all files in the changeset while grepping (EXPERIMENTAL)')),
2701 ('u', 'user', None, _('list the author (long with -v)')),
2711 ('u', 'user', None, _('list the author (long with -v)')),
2702 ('d', 'date', None, _('list the date (short with -q)')),
2712 ('d', 'date', None, _('list the date (short with -q)')),
2703 ] + formatteropts + walkopts,
2713 ] + formatteropts + walkopts,
2704 _('[OPTION]... PATTERN [FILE]...'),
2714 _('[OPTION]... PATTERN [FILE]...'),
2705 helpcategory=command.CATEGORY_FILE_CONTENTS,
2715 helpcategory=command.CATEGORY_FILE_CONTENTS,
2706 inferrepo=True,
2716 inferrepo=True,
2707 intents={INTENT_READONLY})
2717 intents={INTENT_READONLY})
2708 def grep(ui, repo, pattern, *pats, **opts):
2718 def grep(ui, repo, pattern, *pats, **opts):
2709 """search revision history for a pattern in specified files
2719 """search revision history for a pattern in specified files
2710
2720
2711 Search revision history for a regular expression in the specified
2721 Search revision history for a regular expression in the specified
2712 files or the entire project.
2722 files or the entire project.
2713
2723
2714 By default, grep prints the most recent revision number for each
2724 By default, grep prints the most recent revision number for each
2715 file in which it finds a match. To get it to print every revision
2725 file in which it finds a match. To get it to print every revision
2716 that contains a change in match status ("-" for a match that becomes
2726 that contains a change in match status ("-" for a match that becomes
2717 a non-match, or "+" for a non-match that becomes a match), use the
2727 a non-match, or "+" for a non-match that becomes a match), use the
2718 --diff flag.
2728 --diff flag.
2719
2729
2720 PATTERN can be any Python (roughly Perl-compatible) regular
2730 PATTERN can be any Python (roughly Perl-compatible) regular
2721 expression.
2731 expression.
2722
2732
2723 If no FILEs are specified (and -f/--follow isn't set), all files in
2733 If no FILEs are specified (and -f/--follow isn't set), all files in
2724 the repository are searched, including those that don't exist in the
2734 the repository are searched, including those that don't exist in the
2725 current branch or have been deleted in a prior changeset.
2735 current branch or have been deleted in a prior changeset.
2726
2736
2727 .. container:: verbose
2737 .. container:: verbose
2728
2738
2729 Template:
2739 Template:
2730
2740
2731 The following keywords are supported in addition to the common template
2741 The following keywords are supported in addition to the common template
2732 keywords and functions. See also :hg:`help templates`.
2742 keywords and functions. See also :hg:`help templates`.
2733
2743
2734 :change: String. Character denoting insertion ``+`` or removal ``-``.
2744 :change: String. Character denoting insertion ``+`` or removal ``-``.
2735 Available if ``--diff`` is specified.
2745 Available if ``--diff`` is specified.
2736 :lineno: Integer. Line number of the match.
2746 :lineno: Integer. Line number of the match.
2737 :path: String. Repository-absolute path of the file.
2747 :path: String. Repository-absolute path of the file.
2738 :texts: List of text chunks.
2748 :texts: List of text chunks.
2739
2749
2740 And each entry of ``{texts}`` provides the following sub-keywords.
2750 And each entry of ``{texts}`` provides the following sub-keywords.
2741
2751
2742 :matched: Boolean. True if the chunk matches the specified pattern.
2752 :matched: Boolean. True if the chunk matches the specified pattern.
2743 :text: String. Chunk content.
2753 :text: String. Chunk content.
2744
2754
2745 See :hg:`help templates.operators` for the list expansion syntax.
2755 See :hg:`help templates.operators` for the list expansion syntax.
2746
2756
2747 Returns 0 if a match is found, 1 otherwise.
2757 Returns 0 if a match is found, 1 otherwise.
2748 """
2758 """
2749 opts = pycompat.byteskwargs(opts)
2759 opts = pycompat.byteskwargs(opts)
2750 diff = opts.get('all') or opts.get('diff')
2760 diff = opts.get('all') or opts.get('diff')
2751 all_files = opts.get('all_files')
2761 all_files = opts.get('all_files')
2752 if diff and opts.get('all_files'):
2762 if diff and opts.get('all_files'):
2753 raise error.Abort(_('--diff and --all-files are mutually exclusive'))
2763 raise error.Abort(_('--diff and --all-files are mutually exclusive'))
2754 # TODO: remove "not opts.get('rev')" if --all-files -rMULTIREV gets working
2764 # TODO: remove "not opts.get('rev')" if --all-files -rMULTIREV gets working
2755 if opts.get('all_files') is None and not opts.get('rev') and not diff:
2765 if opts.get('all_files') is None and not opts.get('rev') and not diff:
2756 # experimental config: commands.grep.all-files
2766 # experimental config: commands.grep.all-files
2757 opts['all_files'] = ui.configbool('commands', 'grep.all-files')
2767 opts['all_files'] = ui.configbool('commands', 'grep.all-files')
2758 plaingrep = opts.get('all_files') and not opts.get('rev')
2768 plaingrep = opts.get('all_files') and not opts.get('rev')
2759 if plaingrep:
2769 if plaingrep:
2760 opts['rev'] = ['wdir()']
2770 opts['rev'] = ['wdir()']
2761
2771
2762 reflags = re.M
2772 reflags = re.M
2763 if opts.get('ignore_case'):
2773 if opts.get('ignore_case'):
2764 reflags |= re.I
2774 reflags |= re.I
2765 try:
2775 try:
2766 regexp = util.re.compile(pattern, reflags)
2776 regexp = util.re.compile(pattern, reflags)
2767 except re.error as inst:
2777 except re.error as inst:
2768 ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst))
2778 ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst))
2769 return 1
2779 return 1
2770 sep, eol = ':', '\n'
2780 sep, eol = ':', '\n'
2771 if opts.get('print0'):
2781 if opts.get('print0'):
2772 sep = eol = '\0'
2782 sep = eol = '\0'
2773
2783
2774 getfile = util.lrucachefunc(repo.file)
2784 getfile = util.lrucachefunc(repo.file)
2775
2785
2776 def matchlines(body):
2786 def matchlines(body):
2777 begin = 0
2787 begin = 0
2778 linenum = 0
2788 linenum = 0
2779 while begin < len(body):
2789 while begin < len(body):
2780 match = regexp.search(body, begin)
2790 match = regexp.search(body, begin)
2781 if not match:
2791 if not match:
2782 break
2792 break
2783 mstart, mend = match.span()
2793 mstart, mend = match.span()
2784 linenum += body.count('\n', begin, mstart) + 1
2794 linenum += body.count('\n', begin, mstart) + 1
2785 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2795 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2786 begin = body.find('\n', mend) + 1 or len(body) + 1
2796 begin = body.find('\n', mend) + 1 or len(body) + 1
2787 lend = begin - 1
2797 lend = begin - 1
2788 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2798 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2789
2799
2790 class linestate(object):
2800 class linestate(object):
2791 def __init__(self, line, linenum, colstart, colend):
2801 def __init__(self, line, linenum, colstart, colend):
2792 self.line = line
2802 self.line = line
2793 self.linenum = linenum
2803 self.linenum = linenum
2794 self.colstart = colstart
2804 self.colstart = colstart
2795 self.colend = colend
2805 self.colend = colend
2796
2806
2797 def __hash__(self):
2807 def __hash__(self):
2798 return hash((self.linenum, self.line))
2808 return hash((self.linenum, self.line))
2799
2809
2800 def __eq__(self, other):
2810 def __eq__(self, other):
2801 return self.line == other.line
2811 return self.line == other.line
2802
2812
2803 def findpos(self):
2813 def findpos(self):
2804 """Iterate all (start, end) indices of matches"""
2814 """Iterate all (start, end) indices of matches"""
2805 yield self.colstart, self.colend
2815 yield self.colstart, self.colend
2806 p = self.colend
2816 p = self.colend
2807 while p < len(self.line):
2817 while p < len(self.line):
2808 m = regexp.search(self.line, p)
2818 m = regexp.search(self.line, p)
2809 if not m:
2819 if not m:
2810 break
2820 break
2811 yield m.span()
2821 yield m.span()
2812 p = m.end()
2822 p = m.end()
2813
2823
2814 matches = {}
2824 matches = {}
2815 copies = {}
2825 copies = {}
2816 def grepbody(fn, rev, body):
2826 def grepbody(fn, rev, body):
2817 matches[rev].setdefault(fn, [])
2827 matches[rev].setdefault(fn, [])
2818 m = matches[rev][fn]
2828 m = matches[rev][fn]
2819 for lnum, cstart, cend, line in matchlines(body):
2829 for lnum, cstart, cend, line in matchlines(body):
2820 s = linestate(line, lnum, cstart, cend)
2830 s = linestate(line, lnum, cstart, cend)
2821 m.append(s)
2831 m.append(s)
2822
2832
2823 def difflinestates(a, b):
2833 def difflinestates(a, b):
2824 sm = difflib.SequenceMatcher(None, a, b)
2834 sm = difflib.SequenceMatcher(None, a, b)
2825 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2835 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2826 if tag == r'insert':
2836 if tag == r'insert':
2827 for i in pycompat.xrange(blo, bhi):
2837 for i in pycompat.xrange(blo, bhi):
2828 yield ('+', b[i])
2838 yield ('+', b[i])
2829 elif tag == r'delete':
2839 elif tag == r'delete':
2830 for i in pycompat.xrange(alo, ahi):
2840 for i in pycompat.xrange(alo, ahi):
2831 yield ('-', a[i])
2841 yield ('-', a[i])
2832 elif tag == r'replace':
2842 elif tag == r'replace':
2833 for i in pycompat.xrange(alo, ahi):
2843 for i in pycompat.xrange(alo, ahi):
2834 yield ('-', a[i])
2844 yield ('-', a[i])
2835 for i in pycompat.xrange(blo, bhi):
2845 for i in pycompat.xrange(blo, bhi):
2836 yield ('+', b[i])
2846 yield ('+', b[i])
2837
2847
2838 def display(fm, fn, ctx, pstates, states):
2848 def display(fm, fn, ctx, pstates, states):
2839 rev = scmutil.intrev(ctx)
2849 rev = scmutil.intrev(ctx)
2840 if fm.isplain():
2850 if fm.isplain():
2841 formatuser = ui.shortuser
2851 formatuser = ui.shortuser
2842 else:
2852 else:
2843 formatuser = pycompat.bytestr
2853 formatuser = pycompat.bytestr
2844 if ui.quiet:
2854 if ui.quiet:
2845 datefmt = '%Y-%m-%d'
2855 datefmt = '%Y-%m-%d'
2846 else:
2856 else:
2847 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2857 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2848 found = False
2858 found = False
2849 @util.cachefunc
2859 @util.cachefunc
2850 def binary():
2860 def binary():
2851 flog = getfile(fn)
2861 flog = getfile(fn)
2852 try:
2862 try:
2853 return stringutil.binary(flog.read(ctx.filenode(fn)))
2863 return stringutil.binary(flog.read(ctx.filenode(fn)))
2854 except error.WdirUnsupported:
2864 except error.WdirUnsupported:
2855 return ctx[fn].isbinary()
2865 return ctx[fn].isbinary()
2856
2866
2857 fieldnamemap = {'filename': 'path', 'linenumber': 'lineno'}
2867 fieldnamemap = {'filename': 'path', 'linenumber': 'lineno'}
2858 if diff:
2868 if diff:
2859 iter = difflinestates(pstates, states)
2869 iter = difflinestates(pstates, states)
2860 else:
2870 else:
2861 iter = [('', l) for l in states]
2871 iter = [('', l) for l in states]
2862 for change, l in iter:
2872 for change, l in iter:
2863 fm.startitem()
2873 fm.startitem()
2864 fm.context(ctx=ctx)
2874 fm.context(ctx=ctx)
2865 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)))
2875 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)))
2866
2876
2867 cols = [
2877 cols = [
2868 ('filename', '%s', fn, True),
2878 ('filename', '%s', fn, True),
2869 ('rev', '%d', rev, not plaingrep),
2879 ('rev', '%d', rev, not plaingrep),
2870 ('linenumber', '%d', l.linenum, opts.get('line_number')),
2880 ('linenumber', '%d', l.linenum, opts.get('line_number')),
2871 ]
2881 ]
2872 if diff:
2882 if diff:
2873 cols.append(('change', '%s', change, True))
2883 cols.append(('change', '%s', change, True))
2874 cols.extend([
2884 cols.extend([
2875 ('user', '%s', formatuser(ctx.user()), opts.get('user')),
2885 ('user', '%s', formatuser(ctx.user()), opts.get('user')),
2876 ('date', '%s', fm.formatdate(ctx.date(), datefmt),
2886 ('date', '%s', fm.formatdate(ctx.date(), datefmt),
2877 opts.get('date')),
2887 opts.get('date')),
2878 ])
2888 ])
2879 lastcol = next(
2889 lastcol = next(
2880 name for name, fmt, data, cond in reversed(cols) if cond)
2890 name for name, fmt, data, cond in reversed(cols) if cond)
2881 for name, fmt, data, cond in cols:
2891 for name, fmt, data, cond in cols:
2882 field = fieldnamemap.get(name, name)
2892 field = fieldnamemap.get(name, name)
2883 fm.condwrite(cond, field, fmt, data, label='grep.%s' % name)
2893 fm.condwrite(cond, field, fmt, data, label='grep.%s' % name)
2884 if cond and name != lastcol:
2894 if cond and name != lastcol:
2885 fm.plain(sep, label='grep.sep')
2895 fm.plain(sep, label='grep.sep')
2886 if not opts.get('files_with_matches'):
2896 if not opts.get('files_with_matches'):
2887 fm.plain(sep, label='grep.sep')
2897 fm.plain(sep, label='grep.sep')
2888 if not opts.get('text') and binary():
2898 if not opts.get('text') and binary():
2889 fm.plain(_(" Binary file matches"))
2899 fm.plain(_(" Binary file matches"))
2890 else:
2900 else:
2891 displaymatches(fm.nested('texts', tmpl='{text}'), l)
2901 displaymatches(fm.nested('texts', tmpl='{text}'), l)
2892 fm.plain(eol)
2902 fm.plain(eol)
2893 found = True
2903 found = True
2894 if opts.get('files_with_matches'):
2904 if opts.get('files_with_matches'):
2895 break
2905 break
2896 return found
2906 return found
2897
2907
2898 def displaymatches(fm, l):
2908 def displaymatches(fm, l):
2899 p = 0
2909 p = 0
2900 for s, e in l.findpos():
2910 for s, e in l.findpos():
2901 if p < s:
2911 if p < s:
2902 fm.startitem()
2912 fm.startitem()
2903 fm.write('text', '%s', l.line[p:s])
2913 fm.write('text', '%s', l.line[p:s])
2904 fm.data(matched=False)
2914 fm.data(matched=False)
2905 fm.startitem()
2915 fm.startitem()
2906 fm.write('text', '%s', l.line[s:e], label='grep.match')
2916 fm.write('text', '%s', l.line[s:e], label='grep.match')
2907 fm.data(matched=True)
2917 fm.data(matched=True)
2908 p = e
2918 p = e
2909 if p < len(l.line):
2919 if p < len(l.line):
2910 fm.startitem()
2920 fm.startitem()
2911 fm.write('text', '%s', l.line[p:])
2921 fm.write('text', '%s', l.line[p:])
2912 fm.data(matched=False)
2922 fm.data(matched=False)
2913 fm.end()
2923 fm.end()
2914
2924
2915 skip = {}
2925 skip = {}
2916 revfiles = {}
2926 revfiles = {}
2917 match = scmutil.match(repo[None], pats, opts)
2927 match = scmutil.match(repo[None], pats, opts)
2918 found = False
2928 found = False
2919 follow = opts.get('follow')
2929 follow = opts.get('follow')
2920
2930
2921 def prep(ctx, fns):
2931 def prep(ctx, fns):
2922 rev = ctx.rev()
2932 rev = ctx.rev()
2923 pctx = ctx.p1()
2933 pctx = ctx.p1()
2924 parent = pctx.rev()
2934 parent = pctx.rev()
2925 matches.setdefault(rev, {})
2935 matches.setdefault(rev, {})
2926 matches.setdefault(parent, {})
2936 matches.setdefault(parent, {})
2927 files = revfiles.setdefault(rev, [])
2937 files = revfiles.setdefault(rev, [])
2928 for fn in fns:
2938 for fn in fns:
2929 flog = getfile(fn)
2939 flog = getfile(fn)
2930 try:
2940 try:
2931 fnode = ctx.filenode(fn)
2941 fnode = ctx.filenode(fn)
2932 except error.LookupError:
2942 except error.LookupError:
2933 continue
2943 continue
2934 try:
2944 try:
2935 copied = flog.renamed(fnode)
2945 copied = flog.renamed(fnode)
2936 except error.WdirUnsupported:
2946 except error.WdirUnsupported:
2937 copied = ctx[fn].renamed()
2947 copied = ctx[fn].renamed()
2938 copy = follow and copied and copied[0]
2948 copy = follow and copied and copied[0]
2939 if copy:
2949 if copy:
2940 copies.setdefault(rev, {})[fn] = copy
2950 copies.setdefault(rev, {})[fn] = copy
2941 if fn in skip:
2951 if fn in skip:
2942 if copy:
2952 if copy:
2943 skip[copy] = True
2953 skip[copy] = True
2944 continue
2954 continue
2945 files.append(fn)
2955 files.append(fn)
2946
2956
2947 if fn not in matches[rev]:
2957 if fn not in matches[rev]:
2948 try:
2958 try:
2949 content = flog.read(fnode)
2959 content = flog.read(fnode)
2950 except error.WdirUnsupported:
2960 except error.WdirUnsupported:
2951 content = ctx[fn].data()
2961 content = ctx[fn].data()
2952 grepbody(fn, rev, content)
2962 grepbody(fn, rev, content)
2953
2963
2954 pfn = copy or fn
2964 pfn = copy or fn
2955 if pfn not in matches[parent]:
2965 if pfn not in matches[parent]:
2956 try:
2966 try:
2957 fnode = pctx.filenode(pfn)
2967 fnode = pctx.filenode(pfn)
2958 grepbody(pfn, parent, flog.read(fnode))
2968 grepbody(pfn, parent, flog.read(fnode))
2959 except error.LookupError:
2969 except error.LookupError:
2960 pass
2970 pass
2961
2971
2962 ui.pager('grep')
2972 ui.pager('grep')
2963 fm = ui.formatter('grep', opts)
2973 fm = ui.formatter('grep', opts)
2964 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2974 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2965 rev = ctx.rev()
2975 rev = ctx.rev()
2966 parent = ctx.p1().rev()
2976 parent = ctx.p1().rev()
2967 for fn in sorted(revfiles.get(rev, [])):
2977 for fn in sorted(revfiles.get(rev, [])):
2968 states = matches[rev][fn]
2978 states = matches[rev][fn]
2969 copy = copies.get(rev, {}).get(fn)
2979 copy = copies.get(rev, {}).get(fn)
2970 if fn in skip:
2980 if fn in skip:
2971 if copy:
2981 if copy:
2972 skip[copy] = True
2982 skip[copy] = True
2973 continue
2983 continue
2974 pstates = matches.get(parent, {}).get(copy or fn, [])
2984 pstates = matches.get(parent, {}).get(copy or fn, [])
2975 if pstates or states:
2985 if pstates or states:
2976 r = display(fm, fn, ctx, pstates, states)
2986 r = display(fm, fn, ctx, pstates, states)
2977 found = found or r
2987 found = found or r
2978 if r and not diff and not all_files:
2988 if r and not diff and not all_files:
2979 skip[fn] = True
2989 skip[fn] = True
2980 if copy:
2990 if copy:
2981 skip[copy] = True
2991 skip[copy] = True
2982 del revfiles[rev]
2992 del revfiles[rev]
2983 # We will keep the matches dict for the duration of the window
2993 # We will keep the matches dict for the duration of the window
2984 # clear the matches dict once the window is over
2994 # clear the matches dict once the window is over
2985 if not revfiles:
2995 if not revfiles:
2986 matches.clear()
2996 matches.clear()
2987 fm.end()
2997 fm.end()
2988
2998
2989 return not found
2999 return not found
2990
3000
2991 @command('heads',
3001 @command('heads',
2992 [('r', 'rev', '',
3002 [('r', 'rev', '',
2993 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3003 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2994 ('t', 'topo', False, _('show topological heads only')),
3004 ('t', 'topo', False, _('show topological heads only')),
2995 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3005 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2996 ('c', 'closed', False, _('show normal and closed branch heads')),
3006 ('c', 'closed', False, _('show normal and closed branch heads')),
2997 ] + templateopts,
3007 ] + templateopts,
2998 _('[-ct] [-r STARTREV] [REV]...'),
3008 _('[-ct] [-r STARTREV] [REV]...'),
2999 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3009 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3000 intents={INTENT_READONLY})
3010 intents={INTENT_READONLY})
3001 def heads(ui, repo, *branchrevs, **opts):
3011 def heads(ui, repo, *branchrevs, **opts):
3002 """show branch heads
3012 """show branch heads
3003
3013
3004 With no arguments, show all open branch heads in the repository.
3014 With no arguments, show all open branch heads in the repository.
3005 Branch heads are changesets that have no descendants on the
3015 Branch heads are changesets that have no descendants on the
3006 same branch. They are where development generally takes place and
3016 same branch. They are where development generally takes place and
3007 are the usual targets for update and merge operations.
3017 are the usual targets for update and merge operations.
3008
3018
3009 If one or more REVs are given, only open branch heads on the
3019 If one or more REVs are given, only open branch heads on the
3010 branches associated with the specified changesets are shown. This
3020 branches associated with the specified changesets are shown. This
3011 means that you can use :hg:`heads .` to see the heads on the
3021 means that you can use :hg:`heads .` to see the heads on the
3012 currently checked-out branch.
3022 currently checked-out branch.
3013
3023
3014 If -c/--closed is specified, also show branch heads marked closed
3024 If -c/--closed is specified, also show branch heads marked closed
3015 (see :hg:`commit --close-branch`).
3025 (see :hg:`commit --close-branch`).
3016
3026
3017 If STARTREV is specified, only those heads that are descendants of
3027 If STARTREV is specified, only those heads that are descendants of
3018 STARTREV will be displayed.
3028 STARTREV will be displayed.
3019
3029
3020 If -t/--topo is specified, named branch mechanics will be ignored and only
3030 If -t/--topo is specified, named branch mechanics will be ignored and only
3021 topological heads (changesets with no children) will be shown.
3031 topological heads (changesets with no children) will be shown.
3022
3032
3023 Returns 0 if matching heads are found, 1 if not.
3033 Returns 0 if matching heads are found, 1 if not.
3024 """
3034 """
3025
3035
3026 opts = pycompat.byteskwargs(opts)
3036 opts = pycompat.byteskwargs(opts)
3027 start = None
3037 start = None
3028 rev = opts.get('rev')
3038 rev = opts.get('rev')
3029 if rev:
3039 if rev:
3030 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3040 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3031 start = scmutil.revsingle(repo, rev, None).node()
3041 start = scmutil.revsingle(repo, rev, None).node()
3032
3042
3033 if opts.get('topo'):
3043 if opts.get('topo'):
3034 heads = [repo[h] for h in repo.heads(start)]
3044 heads = [repo[h] for h in repo.heads(start)]
3035 else:
3045 else:
3036 heads = []
3046 heads = []
3037 for branch in repo.branchmap():
3047 for branch in repo.branchmap():
3038 heads += repo.branchheads(branch, start, opts.get('closed'))
3048 heads += repo.branchheads(branch, start, opts.get('closed'))
3039 heads = [repo[h] for h in heads]
3049 heads = [repo[h] for h in heads]
3040
3050
3041 if branchrevs:
3051 if branchrevs:
3042 branches = set(repo[r].branch()
3052 branches = set(repo[r].branch()
3043 for r in scmutil.revrange(repo, branchrevs))
3053 for r in scmutil.revrange(repo, branchrevs))
3044 heads = [h for h in heads if h.branch() in branches]
3054 heads = [h for h in heads if h.branch() in branches]
3045
3055
3046 if opts.get('active') and branchrevs:
3056 if opts.get('active') and branchrevs:
3047 dagheads = repo.heads(start)
3057 dagheads = repo.heads(start)
3048 heads = [h for h in heads if h.node() in dagheads]
3058 heads = [h for h in heads if h.node() in dagheads]
3049
3059
3050 if branchrevs:
3060 if branchrevs:
3051 haveheads = set(h.branch() for h in heads)
3061 haveheads = set(h.branch() for h in heads)
3052 if branches - haveheads:
3062 if branches - haveheads:
3053 headless = ', '.join(b for b in branches - haveheads)
3063 headless = ', '.join(b for b in branches - haveheads)
3054 msg = _('no open branch heads found on branches %s')
3064 msg = _('no open branch heads found on branches %s')
3055 if opts.get('rev'):
3065 if opts.get('rev'):
3056 msg += _(' (started at %s)') % opts['rev']
3066 msg += _(' (started at %s)') % opts['rev']
3057 ui.warn((msg + '\n') % headless)
3067 ui.warn((msg + '\n') % headless)
3058
3068
3059 if not heads:
3069 if not heads:
3060 return 1
3070 return 1
3061
3071
3062 ui.pager('heads')
3072 ui.pager('heads')
3063 heads = sorted(heads, key=lambda x: -x.rev())
3073 heads = sorted(heads, key=lambda x: -x.rev())
3064 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3074 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3065 for ctx in heads:
3075 for ctx in heads:
3066 displayer.show(ctx)
3076 displayer.show(ctx)
3067 displayer.close()
3077 displayer.close()
3068
3078
3069 @command('help',
3079 @command('help',
3070 [('e', 'extension', None, _('show only help for extensions')),
3080 [('e', 'extension', None, _('show only help for extensions')),
3071 ('c', 'command', None, _('show only help for commands')),
3081 ('c', 'command', None, _('show only help for commands')),
3072 ('k', 'keyword', None, _('show topics matching keyword')),
3082 ('k', 'keyword', None, _('show topics matching keyword')),
3073 ('s', 'system', [],
3083 ('s', 'system', [],
3074 _('show help for specific platform(s)'), _('PLATFORM')),
3084 _('show help for specific platform(s)'), _('PLATFORM')),
3075 ],
3085 ],
3076 _('[-eck] [-s PLATFORM] [TOPIC]'),
3086 _('[-eck] [-s PLATFORM] [TOPIC]'),
3077 helpcategory=command.CATEGORY_HELP,
3087 helpcategory=command.CATEGORY_HELP,
3078 norepo=True,
3088 norepo=True,
3079 intents={INTENT_READONLY})
3089 intents={INTENT_READONLY})
3080 def help_(ui, name=None, **opts):
3090 def help_(ui, name=None, **opts):
3081 """show help for a given topic or a help overview
3091 """show help for a given topic or a help overview
3082
3092
3083 With no arguments, print a list of commands with short help messages.
3093 With no arguments, print a list of commands with short help messages.
3084
3094
3085 Given a topic, extension, or command name, print help for that
3095 Given a topic, extension, or command name, print help for that
3086 topic.
3096 topic.
3087
3097
3088 Returns 0 if successful.
3098 Returns 0 if successful.
3089 """
3099 """
3090
3100
3091 keep = opts.get(r'system') or []
3101 keep = opts.get(r'system') or []
3092 if len(keep) == 0:
3102 if len(keep) == 0:
3093 if pycompat.sysplatform.startswith('win'):
3103 if pycompat.sysplatform.startswith('win'):
3094 keep.append('windows')
3104 keep.append('windows')
3095 elif pycompat.sysplatform == 'OpenVMS':
3105 elif pycompat.sysplatform == 'OpenVMS':
3096 keep.append('vms')
3106 keep.append('vms')
3097 elif pycompat.sysplatform == 'plan9':
3107 elif pycompat.sysplatform == 'plan9':
3098 keep.append('plan9')
3108 keep.append('plan9')
3099 else:
3109 else:
3100 keep.append('unix')
3110 keep.append('unix')
3101 keep.append(pycompat.sysplatform.lower())
3111 keep.append(pycompat.sysplatform.lower())
3102 if ui.verbose:
3112 if ui.verbose:
3103 keep.append('verbose')
3113 keep.append('verbose')
3104
3114
3105 commands = sys.modules[__name__]
3115 commands = sys.modules[__name__]
3106 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3116 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
3107 ui.pager('help')
3117 ui.pager('help')
3108 ui.write(formatted)
3118 ui.write(formatted)
3109
3119
3110
3120
3111 @command('identify|id',
3121 @command('identify|id',
3112 [('r', 'rev', '',
3122 [('r', 'rev', '',
3113 _('identify the specified revision'), _('REV')),
3123 _('identify the specified revision'), _('REV')),
3114 ('n', 'num', None, _('show local revision number')),
3124 ('n', 'num', None, _('show local revision number')),
3115 ('i', 'id', None, _('show global revision id')),
3125 ('i', 'id', None, _('show global revision id')),
3116 ('b', 'branch', None, _('show branch')),
3126 ('b', 'branch', None, _('show branch')),
3117 ('t', 'tags', None, _('show tags')),
3127 ('t', 'tags', None, _('show tags')),
3118 ('B', 'bookmarks', None, _('show bookmarks')),
3128 ('B', 'bookmarks', None, _('show bookmarks')),
3119 ] + remoteopts + formatteropts,
3129 ] + remoteopts + formatteropts,
3120 _('[-nibtB] [-r REV] [SOURCE]'),
3130 _('[-nibtB] [-r REV] [SOURCE]'),
3121 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3131 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3122 optionalrepo=True,
3132 optionalrepo=True,
3123 intents={INTENT_READONLY})
3133 intents={INTENT_READONLY})
3124 def identify(ui, repo, source=None, rev=None,
3134 def identify(ui, repo, source=None, rev=None,
3125 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3135 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3126 """identify the working directory or specified revision
3136 """identify the working directory or specified revision
3127
3137
3128 Print a summary identifying the repository state at REV using one or
3138 Print a summary identifying the repository state at REV using one or
3129 two parent hash identifiers, followed by a "+" if the working
3139 two parent hash identifiers, followed by a "+" if the working
3130 directory has uncommitted changes, the branch name (if not default),
3140 directory has uncommitted changes, the branch name (if not default),
3131 a list of tags, and a list of bookmarks.
3141 a list of tags, and a list of bookmarks.
3132
3142
3133 When REV is not given, print a summary of the current state of the
3143 When REV is not given, print a summary of the current state of the
3134 repository including the working directory. Specify -r. to get information
3144 repository including the working directory. Specify -r. to get information
3135 of the working directory parent without scanning uncommitted changes.
3145 of the working directory parent without scanning uncommitted changes.
3136
3146
3137 Specifying a path to a repository root or Mercurial bundle will
3147 Specifying a path to a repository root or Mercurial bundle will
3138 cause lookup to operate on that repository/bundle.
3148 cause lookup to operate on that repository/bundle.
3139
3149
3140 .. container:: verbose
3150 .. container:: verbose
3141
3151
3142 Template:
3152 Template:
3143
3153
3144 The following keywords are supported in addition to the common template
3154 The following keywords are supported in addition to the common template
3145 keywords and functions. See also :hg:`help templates`.
3155 keywords and functions. See also :hg:`help templates`.
3146
3156
3147 :dirty: String. Character ``+`` denoting if the working directory has
3157 :dirty: String. Character ``+`` denoting if the working directory has
3148 uncommitted changes.
3158 uncommitted changes.
3149 :id: String. One or two nodes, optionally followed by ``+``.
3159 :id: String. One or two nodes, optionally followed by ``+``.
3150 :parents: List of strings. Parent nodes of the changeset.
3160 :parents: List of strings. Parent nodes of the changeset.
3151
3161
3152 Examples:
3162 Examples:
3153
3163
3154 - generate a build identifier for the working directory::
3164 - generate a build identifier for the working directory::
3155
3165
3156 hg id --id > build-id.dat
3166 hg id --id > build-id.dat
3157
3167
3158 - find the revision corresponding to a tag::
3168 - find the revision corresponding to a tag::
3159
3169
3160 hg id -n -r 1.3
3170 hg id -n -r 1.3
3161
3171
3162 - check the most recent revision of a remote repository::
3172 - check the most recent revision of a remote repository::
3163
3173
3164 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3174 hg id -r tip https://www.mercurial-scm.org/repo/hg/
3165
3175
3166 See :hg:`log` for generating more information about specific revisions,
3176 See :hg:`log` for generating more information about specific revisions,
3167 including full hash identifiers.
3177 including full hash identifiers.
3168
3178
3169 Returns 0 if successful.
3179 Returns 0 if successful.
3170 """
3180 """
3171
3181
3172 opts = pycompat.byteskwargs(opts)
3182 opts = pycompat.byteskwargs(opts)
3173 if not repo and not source:
3183 if not repo and not source:
3174 raise error.Abort(_("there is no Mercurial repository here "
3184 raise error.Abort(_("there is no Mercurial repository here "
3175 "(.hg not found)"))
3185 "(.hg not found)"))
3176
3186
3177 default = not (num or id or branch or tags or bookmarks)
3187 default = not (num or id or branch or tags or bookmarks)
3178 output = []
3188 output = []
3179 revs = []
3189 revs = []
3180
3190
3181 if source:
3191 if source:
3182 source, branches = hg.parseurl(ui.expandpath(source))
3192 source, branches = hg.parseurl(ui.expandpath(source))
3183 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3193 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3184 repo = peer.local()
3194 repo = peer.local()
3185 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3195 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3186
3196
3187 fm = ui.formatter('identify', opts)
3197 fm = ui.formatter('identify', opts)
3188 fm.startitem()
3198 fm.startitem()
3189
3199
3190 if not repo:
3200 if not repo:
3191 if num or branch or tags:
3201 if num or branch or tags:
3192 raise error.Abort(
3202 raise error.Abort(
3193 _("can't query remote revision number, branch, or tags"))
3203 _("can't query remote revision number, branch, or tags"))
3194 if not rev and revs:
3204 if not rev and revs:
3195 rev = revs[0]
3205 rev = revs[0]
3196 if not rev:
3206 if not rev:
3197 rev = "tip"
3207 rev = "tip"
3198
3208
3199 remoterev = peer.lookup(rev)
3209 remoterev = peer.lookup(rev)
3200 hexrev = fm.hexfunc(remoterev)
3210 hexrev = fm.hexfunc(remoterev)
3201 if default or id:
3211 if default or id:
3202 output = [hexrev]
3212 output = [hexrev]
3203 fm.data(id=hexrev)
3213 fm.data(id=hexrev)
3204
3214
3205 @util.cachefunc
3215 @util.cachefunc
3206 def getbms():
3216 def getbms():
3207 bms = []
3217 bms = []
3208
3218
3209 if 'bookmarks' in peer.listkeys('namespaces'):
3219 if 'bookmarks' in peer.listkeys('namespaces'):
3210 hexremoterev = hex(remoterev)
3220 hexremoterev = hex(remoterev)
3211 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3221 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3212 if bmr == hexremoterev]
3222 if bmr == hexremoterev]
3213
3223
3214 return sorted(bms)
3224 return sorted(bms)
3215
3225
3216 if fm.isplain():
3226 if fm.isplain():
3217 if bookmarks:
3227 if bookmarks:
3218 output.extend(getbms())
3228 output.extend(getbms())
3219 elif default and not ui.quiet:
3229 elif default and not ui.quiet:
3220 # multiple bookmarks for a single parent separated by '/'
3230 # multiple bookmarks for a single parent separated by '/'
3221 bm = '/'.join(getbms())
3231 bm = '/'.join(getbms())
3222 if bm:
3232 if bm:
3223 output.append(bm)
3233 output.append(bm)
3224 else:
3234 else:
3225 fm.data(node=hex(remoterev))
3235 fm.data(node=hex(remoterev))
3226 if bookmarks or 'bookmarks' in fm.datahint():
3236 if bookmarks or 'bookmarks' in fm.datahint():
3227 fm.data(bookmarks=fm.formatlist(getbms(), name='bookmark'))
3237 fm.data(bookmarks=fm.formatlist(getbms(), name='bookmark'))
3228 else:
3238 else:
3229 if rev:
3239 if rev:
3230 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3240 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3231 ctx = scmutil.revsingle(repo, rev, None)
3241 ctx = scmutil.revsingle(repo, rev, None)
3232
3242
3233 if ctx.rev() is None:
3243 if ctx.rev() is None:
3234 ctx = repo[None]
3244 ctx = repo[None]
3235 parents = ctx.parents()
3245 parents = ctx.parents()
3236 taglist = []
3246 taglist = []
3237 for p in parents:
3247 for p in parents:
3238 taglist.extend(p.tags())
3248 taglist.extend(p.tags())
3239
3249
3240 dirty = ""
3250 dirty = ""
3241 if ctx.dirty(missing=True, merge=False, branch=False):
3251 if ctx.dirty(missing=True, merge=False, branch=False):
3242 dirty = '+'
3252 dirty = '+'
3243 fm.data(dirty=dirty)
3253 fm.data(dirty=dirty)
3244
3254
3245 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3255 hexoutput = [fm.hexfunc(p.node()) for p in parents]
3246 if default or id:
3256 if default or id:
3247 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
3257 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
3248 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
3258 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
3249
3259
3250 if num:
3260 if num:
3251 numoutput = ["%d" % p.rev() for p in parents]
3261 numoutput = ["%d" % p.rev() for p in parents]
3252 output.append("%s%s" % ('+'.join(numoutput), dirty))
3262 output.append("%s%s" % ('+'.join(numoutput), dirty))
3253
3263
3254 fm.data(parents=fm.formatlist([fm.hexfunc(p.node())
3264 fm.data(parents=fm.formatlist([fm.hexfunc(p.node())
3255 for p in parents], name='node'))
3265 for p in parents], name='node'))
3256 else:
3266 else:
3257 hexoutput = fm.hexfunc(ctx.node())
3267 hexoutput = fm.hexfunc(ctx.node())
3258 if default or id:
3268 if default or id:
3259 output = [hexoutput]
3269 output = [hexoutput]
3260 fm.data(id=hexoutput)
3270 fm.data(id=hexoutput)
3261
3271
3262 if num:
3272 if num:
3263 output.append(pycompat.bytestr(ctx.rev()))
3273 output.append(pycompat.bytestr(ctx.rev()))
3264 taglist = ctx.tags()
3274 taglist = ctx.tags()
3265
3275
3266 if default and not ui.quiet:
3276 if default and not ui.quiet:
3267 b = ctx.branch()
3277 b = ctx.branch()
3268 if b != 'default':
3278 if b != 'default':
3269 output.append("(%s)" % b)
3279 output.append("(%s)" % b)
3270
3280
3271 # multiple tags for a single parent separated by '/'
3281 # multiple tags for a single parent separated by '/'
3272 t = '/'.join(taglist)
3282 t = '/'.join(taglist)
3273 if t:
3283 if t:
3274 output.append(t)
3284 output.append(t)
3275
3285
3276 # multiple bookmarks for a single parent separated by '/'
3286 # multiple bookmarks for a single parent separated by '/'
3277 bm = '/'.join(ctx.bookmarks())
3287 bm = '/'.join(ctx.bookmarks())
3278 if bm:
3288 if bm:
3279 output.append(bm)
3289 output.append(bm)
3280 else:
3290 else:
3281 if branch:
3291 if branch:
3282 output.append(ctx.branch())
3292 output.append(ctx.branch())
3283
3293
3284 if tags:
3294 if tags:
3285 output.extend(taglist)
3295 output.extend(taglist)
3286
3296
3287 if bookmarks:
3297 if bookmarks:
3288 output.extend(ctx.bookmarks())
3298 output.extend(ctx.bookmarks())
3289
3299
3290 fm.data(node=ctx.hex())
3300 fm.data(node=ctx.hex())
3291 fm.data(branch=ctx.branch())
3301 fm.data(branch=ctx.branch())
3292 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
3302 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
3293 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
3303 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
3294 fm.context(ctx=ctx)
3304 fm.context(ctx=ctx)
3295
3305
3296 fm.plain("%s\n" % ' '.join(output))
3306 fm.plain("%s\n" % ' '.join(output))
3297 fm.end()
3307 fm.end()
3298
3308
3299 @command('import|patch',
3309 @command('import|patch',
3300 [('p', 'strip', 1,
3310 [('p', 'strip', 1,
3301 _('directory strip option for patch. This has the same '
3311 _('directory strip option for patch. This has the same '
3302 'meaning as the corresponding patch option'), _('NUM')),
3312 'meaning as the corresponding patch option'), _('NUM')),
3303 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3313 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3304 ('e', 'edit', False, _('invoke editor on commit messages')),
3314 ('e', 'edit', False, _('invoke editor on commit messages')),
3305 ('f', 'force', None,
3315 ('f', 'force', None,
3306 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3316 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3307 ('', 'no-commit', None,
3317 ('', 'no-commit', None,
3308 _("don't commit, just update the working directory")),
3318 _("don't commit, just update the working directory")),
3309 ('', 'bypass', None,
3319 ('', 'bypass', None,
3310 _("apply patch without touching the working directory")),
3320 _("apply patch without touching the working directory")),
3311 ('', 'partial', None,
3321 ('', 'partial', None,
3312 _('commit even if some hunks fail')),
3322 _('commit even if some hunks fail')),
3313 ('', 'exact', None,
3323 ('', 'exact', None,
3314 _('abort if patch would apply lossily')),
3324 _('abort if patch would apply lossily')),
3315 ('', 'prefix', '',
3325 ('', 'prefix', '',
3316 _('apply patch to subdirectory'), _('DIR')),
3326 _('apply patch to subdirectory'), _('DIR')),
3317 ('', 'import-branch', None,
3327 ('', 'import-branch', None,
3318 _('use any branch information in patch (implied by --exact)'))] +
3328 _('use any branch information in patch (implied by --exact)'))] +
3319 commitopts + commitopts2 + similarityopts,
3329 commitopts + commitopts2 + similarityopts,
3320 _('[OPTION]... PATCH...'),
3330 _('[OPTION]... PATCH...'),
3321 helpcategory=command.CATEGORY_IMPORT_EXPORT)
3331 helpcategory=command.CATEGORY_IMPORT_EXPORT)
3322 def import_(ui, repo, patch1=None, *patches, **opts):
3332 def import_(ui, repo, patch1=None, *patches, **opts):
3323 """import an ordered set of patches
3333 """import an ordered set of patches
3324
3334
3325 Import a list of patches and commit them individually (unless
3335 Import a list of patches and commit them individually (unless
3326 --no-commit is specified).
3336 --no-commit is specified).
3327
3337
3328 To read a patch from standard input (stdin), use "-" as the patch
3338 To read a patch from standard input (stdin), use "-" as the patch
3329 name. If a URL is specified, the patch will be downloaded from
3339 name. If a URL is specified, the patch will be downloaded from
3330 there.
3340 there.
3331
3341
3332 Import first applies changes to the working directory (unless
3342 Import first applies changes to the working directory (unless
3333 --bypass is specified), import will abort if there are outstanding
3343 --bypass is specified), import will abort if there are outstanding
3334 changes.
3344 changes.
3335
3345
3336 Use --bypass to apply and commit patches directly to the
3346 Use --bypass to apply and commit patches directly to the
3337 repository, without affecting the working directory. Without
3347 repository, without affecting the working directory. Without
3338 --exact, patches will be applied on top of the working directory
3348 --exact, patches will be applied on top of the working directory
3339 parent revision.
3349 parent revision.
3340
3350
3341 You can import a patch straight from a mail message. Even patches
3351 You can import a patch straight from a mail message. Even patches
3342 as attachments work (to use the body part, it must have type
3352 as attachments work (to use the body part, it must have type
3343 text/plain or text/x-patch). From and Subject headers of email
3353 text/plain or text/x-patch). From and Subject headers of email
3344 message are used as default committer and commit message. All
3354 message are used as default committer and commit message. All
3345 text/plain body parts before first diff are added to the commit
3355 text/plain body parts before first diff are added to the commit
3346 message.
3356 message.
3347
3357
3348 If the imported patch was generated by :hg:`export`, user and
3358 If the imported patch was generated by :hg:`export`, user and
3349 description from patch override values from message headers and
3359 description from patch override values from message headers and
3350 body. Values given on command line with -m/--message and -u/--user
3360 body. Values given on command line with -m/--message and -u/--user
3351 override these.
3361 override these.
3352
3362
3353 If --exact is specified, import will set the working directory to
3363 If --exact is specified, import will set the working directory to
3354 the parent of each patch before applying it, and will abort if the
3364 the parent of each patch before applying it, and will abort if the
3355 resulting changeset has a different ID than the one recorded in
3365 resulting changeset has a different ID than the one recorded in
3356 the patch. This will guard against various ways that portable
3366 the patch. This will guard against various ways that portable
3357 patch formats and mail systems might fail to transfer Mercurial
3367 patch formats and mail systems might fail to transfer Mercurial
3358 data or metadata. See :hg:`bundle` for lossless transmission.
3368 data or metadata. See :hg:`bundle` for lossless transmission.
3359
3369
3360 Use --partial to ensure a changeset will be created from the patch
3370 Use --partial to ensure a changeset will be created from the patch
3361 even if some hunks fail to apply. Hunks that fail to apply will be
3371 even if some hunks fail to apply. Hunks that fail to apply will be
3362 written to a <target-file>.rej file. Conflicts can then be resolved
3372 written to a <target-file>.rej file. Conflicts can then be resolved
3363 by hand before :hg:`commit --amend` is run to update the created
3373 by hand before :hg:`commit --amend` is run to update the created
3364 changeset. This flag exists to let people import patches that
3374 changeset. This flag exists to let people import patches that
3365 partially apply without losing the associated metadata (author,
3375 partially apply without losing the associated metadata (author,
3366 date, description, ...).
3376 date, description, ...).
3367
3377
3368 .. note::
3378 .. note::
3369
3379
3370 When no hunks apply cleanly, :hg:`import --partial` will create
3380 When no hunks apply cleanly, :hg:`import --partial` will create
3371 an empty changeset, importing only the patch metadata.
3381 an empty changeset, importing only the patch metadata.
3372
3382
3373 With -s/--similarity, hg will attempt to discover renames and
3383 With -s/--similarity, hg will attempt to discover renames and
3374 copies in the patch in the same way as :hg:`addremove`.
3384 copies in the patch in the same way as :hg:`addremove`.
3375
3385
3376 It is possible to use external patch programs to perform the patch
3386 It is possible to use external patch programs to perform the patch
3377 by setting the ``ui.patch`` configuration option. For the default
3387 by setting the ``ui.patch`` configuration option. For the default
3378 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3388 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3379 See :hg:`help config` for more information about configuration
3389 See :hg:`help config` for more information about configuration
3380 files and how to use these options.
3390 files and how to use these options.
3381
3391
3382 See :hg:`help dates` for a list of formats valid for -d/--date.
3392 See :hg:`help dates` for a list of formats valid for -d/--date.
3383
3393
3384 .. container:: verbose
3394 .. container:: verbose
3385
3395
3386 Examples:
3396 Examples:
3387
3397
3388 - import a traditional patch from a website and detect renames::
3398 - import a traditional patch from a website and detect renames::
3389
3399
3390 hg import -s 80 http://example.com/bugfix.patch
3400 hg import -s 80 http://example.com/bugfix.patch
3391
3401
3392 - import a changeset from an hgweb server::
3402 - import a changeset from an hgweb server::
3393
3403
3394 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3404 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3395
3405
3396 - import all the patches in an Unix-style mbox::
3406 - import all the patches in an Unix-style mbox::
3397
3407
3398 hg import incoming-patches.mbox
3408 hg import incoming-patches.mbox
3399
3409
3400 - import patches from stdin::
3410 - import patches from stdin::
3401
3411
3402 hg import -
3412 hg import -
3403
3413
3404 - attempt to exactly restore an exported changeset (not always
3414 - attempt to exactly restore an exported changeset (not always
3405 possible)::
3415 possible)::
3406
3416
3407 hg import --exact proposed-fix.patch
3417 hg import --exact proposed-fix.patch
3408
3418
3409 - use an external tool to apply a patch which is too fuzzy for
3419 - use an external tool to apply a patch which is too fuzzy for
3410 the default internal tool.
3420 the default internal tool.
3411
3421
3412 hg import --config ui.patch="patch --merge" fuzzy.patch
3422 hg import --config ui.patch="patch --merge" fuzzy.patch
3413
3423
3414 - change the default fuzzing from 2 to a less strict 7
3424 - change the default fuzzing from 2 to a less strict 7
3415
3425
3416 hg import --config ui.fuzz=7 fuzz.patch
3426 hg import --config ui.fuzz=7 fuzz.patch
3417
3427
3418 Returns 0 on success, 1 on partial success (see --partial).
3428 Returns 0 on success, 1 on partial success (see --partial).
3419 """
3429 """
3420
3430
3421 opts = pycompat.byteskwargs(opts)
3431 opts = pycompat.byteskwargs(opts)
3422 if not patch1:
3432 if not patch1:
3423 raise error.Abort(_('need at least one patch to import'))
3433 raise error.Abort(_('need at least one patch to import'))
3424
3434
3425 patches = (patch1,) + patches
3435 patches = (patch1,) + patches
3426
3436
3427 date = opts.get('date')
3437 date = opts.get('date')
3428 if date:
3438 if date:
3429 opts['date'] = dateutil.parsedate(date)
3439 opts['date'] = dateutil.parsedate(date)
3430
3440
3431 exact = opts.get('exact')
3441 exact = opts.get('exact')
3432 update = not opts.get('bypass')
3442 update = not opts.get('bypass')
3433 if not update and opts.get('no_commit'):
3443 if not update and opts.get('no_commit'):
3434 raise error.Abort(_('cannot use --no-commit with --bypass'))
3444 raise error.Abort(_('cannot use --no-commit with --bypass'))
3435 try:
3445 try:
3436 sim = float(opts.get('similarity') or 0)
3446 sim = float(opts.get('similarity') or 0)
3437 except ValueError:
3447 except ValueError:
3438 raise error.Abort(_('similarity must be a number'))
3448 raise error.Abort(_('similarity must be a number'))
3439 if sim < 0 or sim > 100:
3449 if sim < 0 or sim > 100:
3440 raise error.Abort(_('similarity must be between 0 and 100'))
3450 raise error.Abort(_('similarity must be between 0 and 100'))
3441 if sim and not update:
3451 if sim and not update:
3442 raise error.Abort(_('cannot use --similarity with --bypass'))
3452 raise error.Abort(_('cannot use --similarity with --bypass'))
3443 if exact:
3453 if exact:
3444 if opts.get('edit'):
3454 if opts.get('edit'):
3445 raise error.Abort(_('cannot use --exact with --edit'))
3455 raise error.Abort(_('cannot use --exact with --edit'))
3446 if opts.get('prefix'):
3456 if opts.get('prefix'):
3447 raise error.Abort(_('cannot use --exact with --prefix'))
3457 raise error.Abort(_('cannot use --exact with --prefix'))
3448
3458
3449 base = opts["base"]
3459 base = opts["base"]
3450 msgs = []
3460 msgs = []
3451 ret = 0
3461 ret = 0
3452
3462
3453 with repo.wlock():
3463 with repo.wlock():
3454 if update:
3464 if update:
3455 cmdutil.checkunfinished(repo)
3465 cmdutil.checkunfinished(repo)
3456 if (exact or not opts.get('force')):
3466 if (exact or not opts.get('force')):
3457 cmdutil.bailifchanged(repo)
3467 cmdutil.bailifchanged(repo)
3458
3468
3459 if not opts.get('no_commit'):
3469 if not opts.get('no_commit'):
3460 lock = repo.lock
3470 lock = repo.lock
3461 tr = lambda: repo.transaction('import')
3471 tr = lambda: repo.transaction('import')
3462 dsguard = util.nullcontextmanager
3472 dsguard = util.nullcontextmanager
3463 else:
3473 else:
3464 lock = util.nullcontextmanager
3474 lock = util.nullcontextmanager
3465 tr = util.nullcontextmanager
3475 tr = util.nullcontextmanager
3466 dsguard = lambda: dirstateguard.dirstateguard(repo, 'import')
3476 dsguard = lambda: dirstateguard.dirstateguard(repo, 'import')
3467 with lock(), tr(), dsguard():
3477 with lock(), tr(), dsguard():
3468 parents = repo[None].parents()
3478 parents = repo[None].parents()
3469 for patchurl in patches:
3479 for patchurl in patches:
3470 if patchurl == '-':
3480 if patchurl == '-':
3471 ui.status(_('applying patch from stdin\n'))
3481 ui.status(_('applying patch from stdin\n'))
3472 patchfile = ui.fin
3482 patchfile = ui.fin
3473 patchurl = 'stdin' # for error message
3483 patchurl = 'stdin' # for error message
3474 else:
3484 else:
3475 patchurl = os.path.join(base, patchurl)
3485 patchurl = os.path.join(base, patchurl)
3476 ui.status(_('applying %s\n') % patchurl)
3486 ui.status(_('applying %s\n') % patchurl)
3477 patchfile = hg.openpath(ui, patchurl)
3487 patchfile = hg.openpath(ui, patchurl)
3478
3488
3479 haspatch = False
3489 haspatch = False
3480 for hunk in patch.split(patchfile):
3490 for hunk in patch.split(patchfile):
3481 with patch.extract(ui, hunk) as patchdata:
3491 with patch.extract(ui, hunk) as patchdata:
3482 msg, node, rej = cmdutil.tryimportone(ui, repo,
3492 msg, node, rej = cmdutil.tryimportone(ui, repo,
3483 patchdata,
3493 patchdata,
3484 parents, opts,
3494 parents, opts,
3485 msgs, hg.clean)
3495 msgs, hg.clean)
3486 if msg:
3496 if msg:
3487 haspatch = True
3497 haspatch = True
3488 ui.note(msg + '\n')
3498 ui.note(msg + '\n')
3489 if update or exact:
3499 if update or exact:
3490 parents = repo[None].parents()
3500 parents = repo[None].parents()
3491 else:
3501 else:
3492 parents = [repo[node]]
3502 parents = [repo[node]]
3493 if rej:
3503 if rej:
3494 ui.write_err(_("patch applied partially\n"))
3504 ui.write_err(_("patch applied partially\n"))
3495 ui.write_err(_("(fix the .rej files and run "
3505 ui.write_err(_("(fix the .rej files and run "
3496 "`hg commit --amend`)\n"))
3506 "`hg commit --amend`)\n"))
3497 ret = 1
3507 ret = 1
3498 break
3508 break
3499
3509
3500 if not haspatch:
3510 if not haspatch:
3501 raise error.Abort(_('%s: no diffs found') % patchurl)
3511 raise error.Abort(_('%s: no diffs found') % patchurl)
3502
3512
3503 if msgs:
3513 if msgs:
3504 repo.savecommitmessage('\n* * *\n'.join(msgs))
3514 repo.savecommitmessage('\n* * *\n'.join(msgs))
3505 return ret
3515 return ret
3506
3516
3507 @command('incoming|in',
3517 @command('incoming|in',
3508 [('f', 'force', None,
3518 [('f', 'force', None,
3509 _('run even if remote repository is unrelated')),
3519 _('run even if remote repository is unrelated')),
3510 ('n', 'newest-first', None, _('show newest record first')),
3520 ('n', 'newest-first', None, _('show newest record first')),
3511 ('', 'bundle', '',
3521 ('', 'bundle', '',
3512 _('file to store the bundles into'), _('FILE')),
3522 _('file to store the bundles into'), _('FILE')),
3513 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3523 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3514 ('B', 'bookmarks', False, _("compare bookmarks")),
3524 ('B', 'bookmarks', False, _("compare bookmarks")),
3515 ('b', 'branch', [],
3525 ('b', 'branch', [],
3516 _('a specific branch you would like to pull'), _('BRANCH')),
3526 _('a specific branch you would like to pull'), _('BRANCH')),
3517 ] + logopts + remoteopts + subrepoopts,
3527 ] + logopts + remoteopts + subrepoopts,
3518 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
3528 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
3519 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
3529 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
3520 def incoming(ui, repo, source="default", **opts):
3530 def incoming(ui, repo, source="default", **opts):
3521 """show new changesets found in source
3531 """show new changesets found in source
3522
3532
3523 Show new changesets found in the specified path/URL or the default
3533 Show new changesets found in the specified path/URL or the default
3524 pull location. These are the changesets that would have been pulled
3534 pull location. These are the changesets that would have been pulled
3525 by :hg:`pull` at the time you issued this command.
3535 by :hg:`pull` at the time you issued this command.
3526
3536
3527 See pull for valid source format details.
3537 See pull for valid source format details.
3528
3538
3529 .. container:: verbose
3539 .. container:: verbose
3530
3540
3531 With -B/--bookmarks, the result of bookmark comparison between
3541 With -B/--bookmarks, the result of bookmark comparison between
3532 local and remote repositories is displayed. With -v/--verbose,
3542 local and remote repositories is displayed. With -v/--verbose,
3533 status is also displayed for each bookmark like below::
3543 status is also displayed for each bookmark like below::
3534
3544
3535 BM1 01234567890a added
3545 BM1 01234567890a added
3536 BM2 1234567890ab advanced
3546 BM2 1234567890ab advanced
3537 BM3 234567890abc diverged
3547 BM3 234567890abc diverged
3538 BM4 34567890abcd changed
3548 BM4 34567890abcd changed
3539
3549
3540 The action taken locally when pulling depends on the
3550 The action taken locally when pulling depends on the
3541 status of each bookmark:
3551 status of each bookmark:
3542
3552
3543 :``added``: pull will create it
3553 :``added``: pull will create it
3544 :``advanced``: pull will update it
3554 :``advanced``: pull will update it
3545 :``diverged``: pull will create a divergent bookmark
3555 :``diverged``: pull will create a divergent bookmark
3546 :``changed``: result depends on remote changesets
3556 :``changed``: result depends on remote changesets
3547
3557
3548 From the point of view of pulling behavior, bookmark
3558 From the point of view of pulling behavior, bookmark
3549 existing only in the remote repository are treated as ``added``,
3559 existing only in the remote repository are treated as ``added``,
3550 even if it is in fact locally deleted.
3560 even if it is in fact locally deleted.
3551
3561
3552 .. container:: verbose
3562 .. container:: verbose
3553
3563
3554 For remote repository, using --bundle avoids downloading the
3564 For remote repository, using --bundle avoids downloading the
3555 changesets twice if the incoming is followed by a pull.
3565 changesets twice if the incoming is followed by a pull.
3556
3566
3557 Examples:
3567 Examples:
3558
3568
3559 - show incoming changes with patches and full description::
3569 - show incoming changes with patches and full description::
3560
3570
3561 hg incoming -vp
3571 hg incoming -vp
3562
3572
3563 - show incoming changes excluding merges, store a bundle::
3573 - show incoming changes excluding merges, store a bundle::
3564
3574
3565 hg in -vpM --bundle incoming.hg
3575 hg in -vpM --bundle incoming.hg
3566 hg pull incoming.hg
3576 hg pull incoming.hg
3567
3577
3568 - briefly list changes inside a bundle::
3578 - briefly list changes inside a bundle::
3569
3579
3570 hg in changes.hg -T "{desc|firstline}\\n"
3580 hg in changes.hg -T "{desc|firstline}\\n"
3571
3581
3572 Returns 0 if there are incoming changes, 1 otherwise.
3582 Returns 0 if there are incoming changes, 1 otherwise.
3573 """
3583 """
3574 opts = pycompat.byteskwargs(opts)
3584 opts = pycompat.byteskwargs(opts)
3575 if opts.get('graph'):
3585 if opts.get('graph'):
3576 logcmdutil.checkunsupportedgraphflags([], opts)
3586 logcmdutil.checkunsupportedgraphflags([], opts)
3577 def display(other, chlist, displayer):
3587 def display(other, chlist, displayer):
3578 revdag = logcmdutil.graphrevs(other, chlist, opts)
3588 revdag = logcmdutil.graphrevs(other, chlist, opts)
3579 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3589 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3580 graphmod.asciiedges)
3590 graphmod.asciiedges)
3581
3591
3582 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3592 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3583 return 0
3593 return 0
3584
3594
3585 if opts.get('bundle') and opts.get('subrepos'):
3595 if opts.get('bundle') and opts.get('subrepos'):
3586 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3596 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3587
3597
3588 if opts.get('bookmarks'):
3598 if opts.get('bookmarks'):
3589 source, branches = hg.parseurl(ui.expandpath(source),
3599 source, branches = hg.parseurl(ui.expandpath(source),
3590 opts.get('branch'))
3600 opts.get('branch'))
3591 other = hg.peer(repo, opts, source)
3601 other = hg.peer(repo, opts, source)
3592 if 'bookmarks' not in other.listkeys('namespaces'):
3602 if 'bookmarks' not in other.listkeys('namespaces'):
3593 ui.warn(_("remote doesn't support bookmarks\n"))
3603 ui.warn(_("remote doesn't support bookmarks\n"))
3594 return 0
3604 return 0
3595 ui.pager('incoming')
3605 ui.pager('incoming')
3596 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3606 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3597 return bookmarks.incoming(ui, repo, other)
3607 return bookmarks.incoming(ui, repo, other)
3598
3608
3599 repo._subtoppath = ui.expandpath(source)
3609 repo._subtoppath = ui.expandpath(source)
3600 try:
3610 try:
3601 return hg.incoming(ui, repo, source, opts)
3611 return hg.incoming(ui, repo, source, opts)
3602 finally:
3612 finally:
3603 del repo._subtoppath
3613 del repo._subtoppath
3604
3614
3605
3615
3606 @command('init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3616 @command('init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3607 helpcategory=command.CATEGORY_REPO_CREATION,
3617 helpcategory=command.CATEGORY_REPO_CREATION,
3608 helpbasic=True, norepo=True)
3618 helpbasic=True, norepo=True)
3609 def init(ui, dest=".", **opts):
3619 def init(ui, dest=".", **opts):
3610 """create a new repository in the given directory
3620 """create a new repository in the given directory
3611
3621
3612 Initialize a new repository in the given directory. If the given
3622 Initialize a new repository in the given directory. If the given
3613 directory does not exist, it will be created.
3623 directory does not exist, it will be created.
3614
3624
3615 If no directory is given, the current directory is used.
3625 If no directory is given, the current directory is used.
3616
3626
3617 It is possible to specify an ``ssh://`` URL as the destination.
3627 It is possible to specify an ``ssh://`` URL as the destination.
3618 See :hg:`help urls` for more information.
3628 See :hg:`help urls` for more information.
3619
3629
3620 Returns 0 on success.
3630 Returns 0 on success.
3621 """
3631 """
3622 opts = pycompat.byteskwargs(opts)
3632 opts = pycompat.byteskwargs(opts)
3623 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3633 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3624
3634
3625 @command('locate',
3635 @command('locate',
3626 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3636 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3627 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3637 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3628 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3638 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3629 ] + walkopts,
3639 ] + walkopts,
3630 _('[OPTION]... [PATTERN]...'),
3640 _('[OPTION]... [PATTERN]...'),
3631 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
3641 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
3632 def locate(ui, repo, *pats, **opts):
3642 def locate(ui, repo, *pats, **opts):
3633 """locate files matching specific patterns (DEPRECATED)
3643 """locate files matching specific patterns (DEPRECATED)
3634
3644
3635 Print files under Mercurial control in the working directory whose
3645 Print files under Mercurial control in the working directory whose
3636 names match the given patterns.
3646 names match the given patterns.
3637
3647
3638 By default, this command searches all directories in the working
3648 By default, this command searches all directories in the working
3639 directory. To search just the current directory and its
3649 directory. To search just the current directory and its
3640 subdirectories, use "--include .".
3650 subdirectories, use "--include .".
3641
3651
3642 If no patterns are given to match, this command prints the names
3652 If no patterns are given to match, this command prints the names
3643 of all files under Mercurial control in the working directory.
3653 of all files under Mercurial control in the working directory.
3644
3654
3645 If you want to feed the output of this command into the "xargs"
3655 If you want to feed the output of this command into the "xargs"
3646 command, use the -0 option to both this command and "xargs". This
3656 command, use the -0 option to both this command and "xargs". This
3647 will avoid the problem of "xargs" treating single filenames that
3657 will avoid the problem of "xargs" treating single filenames that
3648 contain whitespace as multiple filenames.
3658 contain whitespace as multiple filenames.
3649
3659
3650 See :hg:`help files` for a more versatile command.
3660 See :hg:`help files` for a more versatile command.
3651
3661
3652 Returns 0 if a match is found, 1 otherwise.
3662 Returns 0 if a match is found, 1 otherwise.
3653 """
3663 """
3654 opts = pycompat.byteskwargs(opts)
3664 opts = pycompat.byteskwargs(opts)
3655 if opts.get('print0'):
3665 if opts.get('print0'):
3656 end = '\0'
3666 end = '\0'
3657 else:
3667 else:
3658 end = '\n'
3668 end = '\n'
3659 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3669 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3660
3670
3661 ret = 1
3671 ret = 1
3662 m = scmutil.match(ctx, pats, opts, default='relglob',
3672 m = scmutil.match(ctx, pats, opts, default='relglob',
3663 badfn=lambda x, y: False)
3673 badfn=lambda x, y: False)
3664
3674
3665 ui.pager('locate')
3675 ui.pager('locate')
3666 if ctx.rev() is None:
3676 if ctx.rev() is None:
3667 # When run on the working copy, "locate" includes removed files, so
3677 # When run on the working copy, "locate" includes removed files, so
3668 # we get the list of files from the dirstate.
3678 # we get the list of files from the dirstate.
3669 filesgen = sorted(repo.dirstate.matches(m))
3679 filesgen = sorted(repo.dirstate.matches(m))
3670 else:
3680 else:
3671 filesgen = ctx.matches(m)
3681 filesgen = ctx.matches(m)
3672 for abs in filesgen:
3682 for abs in filesgen:
3673 if opts.get('fullpath'):
3683 if opts.get('fullpath'):
3674 ui.write(repo.wjoin(abs), end)
3684 ui.write(repo.wjoin(abs), end)
3675 else:
3685 else:
3676 ui.write(((pats and m.rel(abs)) or abs), end)
3686 ui.write(((pats and m.rel(abs)) or abs), end)
3677 ret = 0
3687 ret = 0
3678
3688
3679 return ret
3689 return ret
3680
3690
3681 @command('log|history',
3691 @command('log|history',
3682 [('f', 'follow', None,
3692 [('f', 'follow', None,
3683 _('follow changeset history, or file history across copies and renames')),
3693 _('follow changeset history, or file history across copies and renames')),
3684 ('', 'follow-first', None,
3694 ('', 'follow-first', None,
3685 _('only follow the first parent of merge changesets (DEPRECATED)')),
3695 _('only follow the first parent of merge changesets (DEPRECATED)')),
3686 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3696 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3687 ('C', 'copies', None, _('show copied files')),
3697 ('C', 'copies', None, _('show copied files')),
3688 ('k', 'keyword', [],
3698 ('k', 'keyword', [],
3689 _('do case-insensitive search for a given text'), _('TEXT')),
3699 _('do case-insensitive search for a given text'), _('TEXT')),
3690 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3700 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3691 ('L', 'line-range', [],
3701 ('L', 'line-range', [],
3692 _('follow line range of specified file (EXPERIMENTAL)'),
3702 _('follow line range of specified file (EXPERIMENTAL)'),
3693 _('FILE,RANGE')),
3703 _('FILE,RANGE')),
3694 ('', 'removed', None, _('include revisions where files were removed')),
3704 ('', 'removed', None, _('include revisions where files were removed')),
3695 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3705 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3696 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3706 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3697 ('', 'only-branch', [],
3707 ('', 'only-branch', [],
3698 _('show only changesets within the given named branch (DEPRECATED)'),
3708 _('show only changesets within the given named branch (DEPRECATED)'),
3699 _('BRANCH')),
3709 _('BRANCH')),
3700 ('b', 'branch', [],
3710 ('b', 'branch', [],
3701 _('show changesets within the given named branch'), _('BRANCH')),
3711 _('show changesets within the given named branch'), _('BRANCH')),
3702 ('P', 'prune', [],
3712 ('P', 'prune', [],
3703 _('do not display revision or any of its ancestors'), _('REV')),
3713 _('do not display revision or any of its ancestors'), _('REV')),
3704 ] + logopts + walkopts,
3714 ] + logopts + walkopts,
3705 _('[OPTION]... [FILE]'),
3715 _('[OPTION]... [FILE]'),
3706 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3716 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
3707 helpbasic=True, inferrepo=True,
3717 helpbasic=True, inferrepo=True,
3708 intents={INTENT_READONLY})
3718 intents={INTENT_READONLY})
3709 def log(ui, repo, *pats, **opts):
3719 def log(ui, repo, *pats, **opts):
3710 """show revision history of entire repository or files
3720 """show revision history of entire repository or files
3711
3721
3712 Print the revision history of the specified files or the entire
3722 Print the revision history of the specified files or the entire
3713 project.
3723 project.
3714
3724
3715 If no revision range is specified, the default is ``tip:0`` unless
3725 If no revision range is specified, the default is ``tip:0`` unless
3716 --follow is set, in which case the working directory parent is
3726 --follow is set, in which case the working directory parent is
3717 used as the starting revision.
3727 used as the starting revision.
3718
3728
3719 File history is shown without following rename or copy history of
3729 File history is shown without following rename or copy history of
3720 files. Use -f/--follow with a filename to follow history across
3730 files. Use -f/--follow with a filename to follow history across
3721 renames and copies. --follow without a filename will only show
3731 renames and copies. --follow without a filename will only show
3722 ancestors of the starting revision.
3732 ancestors of the starting revision.
3723
3733
3724 By default this command prints revision number and changeset id,
3734 By default this command prints revision number and changeset id,
3725 tags, non-trivial parents, user, date and time, and a summary for
3735 tags, non-trivial parents, user, date and time, and a summary for
3726 each commit. When the -v/--verbose switch is used, the list of
3736 each commit. When the -v/--verbose switch is used, the list of
3727 changed files and full commit message are shown.
3737 changed files and full commit message are shown.
3728
3738
3729 With --graph the revisions are shown as an ASCII art DAG with the most
3739 With --graph the revisions are shown as an ASCII art DAG with the most
3730 recent changeset at the top.
3740 recent changeset at the top.
3731 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3741 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3732 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3742 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3733 changeset from the lines below is a parent of the 'o' merge on the same
3743 changeset from the lines below is a parent of the 'o' merge on the same
3734 line.
3744 line.
3735 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3745 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3736 of a '|' indicates one or more revisions in a path are omitted.
3746 of a '|' indicates one or more revisions in a path are omitted.
3737
3747
3738 .. container:: verbose
3748 .. container:: verbose
3739
3749
3740 Use -L/--line-range FILE,M:N options to follow the history of lines
3750 Use -L/--line-range FILE,M:N options to follow the history of lines
3741 from M to N in FILE. With -p/--patch only diff hunks affecting
3751 from M to N in FILE. With -p/--patch only diff hunks affecting
3742 specified line range will be shown. This option requires --follow;
3752 specified line range will be shown. This option requires --follow;
3743 it can be specified multiple times. Currently, this option is not
3753 it can be specified multiple times. Currently, this option is not
3744 compatible with --graph. This option is experimental.
3754 compatible with --graph. This option is experimental.
3745
3755
3746 .. note::
3756 .. note::
3747
3757
3748 :hg:`log --patch` may generate unexpected diff output for merge
3758 :hg:`log --patch` may generate unexpected diff output for merge
3749 changesets, as it will only compare the merge changeset against
3759 changesets, as it will only compare the merge changeset against
3750 its first parent. Also, only files different from BOTH parents
3760 its first parent. Also, only files different from BOTH parents
3751 will appear in files:.
3761 will appear in files:.
3752
3762
3753 .. note::
3763 .. note::
3754
3764
3755 For performance reasons, :hg:`log FILE` may omit duplicate changes
3765 For performance reasons, :hg:`log FILE` may omit duplicate changes
3756 made on branches and will not show removals or mode changes. To
3766 made on branches and will not show removals or mode changes. To
3757 see all such changes, use the --removed switch.
3767 see all such changes, use the --removed switch.
3758
3768
3759 .. container:: verbose
3769 .. container:: verbose
3760
3770
3761 .. note::
3771 .. note::
3762
3772
3763 The history resulting from -L/--line-range options depends on diff
3773 The history resulting from -L/--line-range options depends on diff
3764 options; for instance if white-spaces are ignored, respective changes
3774 options; for instance if white-spaces are ignored, respective changes
3765 with only white-spaces in specified line range will not be listed.
3775 with only white-spaces in specified line range will not be listed.
3766
3776
3767 .. container:: verbose
3777 .. container:: verbose
3768
3778
3769 Some examples:
3779 Some examples:
3770
3780
3771 - changesets with full descriptions and file lists::
3781 - changesets with full descriptions and file lists::
3772
3782
3773 hg log -v
3783 hg log -v
3774
3784
3775 - changesets ancestral to the working directory::
3785 - changesets ancestral to the working directory::
3776
3786
3777 hg log -f
3787 hg log -f
3778
3788
3779 - last 10 commits on the current branch::
3789 - last 10 commits on the current branch::
3780
3790
3781 hg log -l 10 -b .
3791 hg log -l 10 -b .
3782
3792
3783 - changesets showing all modifications of a file, including removals::
3793 - changesets showing all modifications of a file, including removals::
3784
3794
3785 hg log --removed file.c
3795 hg log --removed file.c
3786
3796
3787 - all changesets that touch a directory, with diffs, excluding merges::
3797 - all changesets that touch a directory, with diffs, excluding merges::
3788
3798
3789 hg log -Mp lib/
3799 hg log -Mp lib/
3790
3800
3791 - all revision numbers that match a keyword::
3801 - all revision numbers that match a keyword::
3792
3802
3793 hg log -k bug --template "{rev}\\n"
3803 hg log -k bug --template "{rev}\\n"
3794
3804
3795 - the full hash identifier of the working directory parent::
3805 - the full hash identifier of the working directory parent::
3796
3806
3797 hg log -r . --template "{node}\\n"
3807 hg log -r . --template "{node}\\n"
3798
3808
3799 - list available log templates::
3809 - list available log templates::
3800
3810
3801 hg log -T list
3811 hg log -T list
3802
3812
3803 - check if a given changeset is included in a tagged release::
3813 - check if a given changeset is included in a tagged release::
3804
3814
3805 hg log -r "a21ccf and ancestor(1.9)"
3815 hg log -r "a21ccf and ancestor(1.9)"
3806
3816
3807 - find all changesets by some user in a date range::
3817 - find all changesets by some user in a date range::
3808
3818
3809 hg log -k alice -d "may 2008 to jul 2008"
3819 hg log -k alice -d "may 2008 to jul 2008"
3810
3820
3811 - summary of all changesets after the last tag::
3821 - summary of all changesets after the last tag::
3812
3822
3813 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3823 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3814
3824
3815 - changesets touching lines 13 to 23 for file.c::
3825 - changesets touching lines 13 to 23 for file.c::
3816
3826
3817 hg log -L file.c,13:23
3827 hg log -L file.c,13:23
3818
3828
3819 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3829 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3820 main.c with patch::
3830 main.c with patch::
3821
3831
3822 hg log -L file.c,13:23 -L main.c,2:6 -p
3832 hg log -L file.c,13:23 -L main.c,2:6 -p
3823
3833
3824 See :hg:`help dates` for a list of formats valid for -d/--date.
3834 See :hg:`help dates` for a list of formats valid for -d/--date.
3825
3835
3826 See :hg:`help revisions` for more about specifying and ordering
3836 See :hg:`help revisions` for more about specifying and ordering
3827 revisions.
3837 revisions.
3828
3838
3829 See :hg:`help templates` for more about pre-packaged styles and
3839 See :hg:`help templates` for more about pre-packaged styles and
3830 specifying custom templates. The default template used by the log
3840 specifying custom templates. The default template used by the log
3831 command can be customized via the ``ui.logtemplate`` configuration
3841 command can be customized via the ``ui.logtemplate`` configuration
3832 setting.
3842 setting.
3833
3843
3834 Returns 0 on success.
3844 Returns 0 on success.
3835
3845
3836 """
3846 """
3837 opts = pycompat.byteskwargs(opts)
3847 opts = pycompat.byteskwargs(opts)
3838 linerange = opts.get('line_range')
3848 linerange = opts.get('line_range')
3839
3849
3840 if linerange and not opts.get('follow'):
3850 if linerange and not opts.get('follow'):
3841 raise error.Abort(_('--line-range requires --follow'))
3851 raise error.Abort(_('--line-range requires --follow'))
3842
3852
3843 if linerange and pats:
3853 if linerange and pats:
3844 # TODO: take pats as patterns with no line-range filter
3854 # TODO: take pats as patterns with no line-range filter
3845 raise error.Abort(
3855 raise error.Abort(
3846 _('FILE arguments are not compatible with --line-range option')
3856 _('FILE arguments are not compatible with --line-range option')
3847 )
3857 )
3848
3858
3849 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3859 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3850 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3860 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3851 if linerange:
3861 if linerange:
3852 # TODO: should follow file history from logcmdutil._initialrevs(),
3862 # TODO: should follow file history from logcmdutil._initialrevs(),
3853 # then filter the result by logcmdutil._makerevset() and --limit
3863 # then filter the result by logcmdutil._makerevset() and --limit
3854 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3864 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3855
3865
3856 getrenamed = None
3866 getrenamed = None
3857 if opts.get('copies'):
3867 if opts.get('copies'):
3858 endrev = None
3868 endrev = None
3859 if revs:
3869 if revs:
3860 endrev = revs.max() + 1
3870 endrev = revs.max() + 1
3861 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3871 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3862
3872
3863 ui.pager('log')
3873 ui.pager('log')
3864 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3874 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3865 buffered=True)
3875 buffered=True)
3866 if opts.get('graph'):
3876 if opts.get('graph'):
3867 displayfn = logcmdutil.displaygraphrevs
3877 displayfn = logcmdutil.displaygraphrevs
3868 else:
3878 else:
3869 displayfn = logcmdutil.displayrevs
3879 displayfn = logcmdutil.displayrevs
3870 displayfn(ui, repo, revs, displayer, getrenamed)
3880 displayfn(ui, repo, revs, displayer, getrenamed)
3871
3881
3872 @command('manifest',
3882 @command('manifest',
3873 [('r', 'rev', '', _('revision to display'), _('REV')),
3883 [('r', 'rev', '', _('revision to display'), _('REV')),
3874 ('', 'all', False, _("list files from all revisions"))]
3884 ('', 'all', False, _("list files from all revisions"))]
3875 + formatteropts,
3885 + formatteropts,
3876 _('[-r REV]'),
3886 _('[-r REV]'),
3877 helpcategory=command.CATEGORY_MAINTENANCE,
3887 helpcategory=command.CATEGORY_MAINTENANCE,
3878 intents={INTENT_READONLY})
3888 intents={INTENT_READONLY})
3879 def manifest(ui, repo, node=None, rev=None, **opts):
3889 def manifest(ui, repo, node=None, rev=None, **opts):
3880 """output the current or given revision of the project manifest
3890 """output the current or given revision of the project manifest
3881
3891
3882 Print a list of version controlled files for the given revision.
3892 Print a list of version controlled files for the given revision.
3883 If no revision is given, the first parent of the working directory
3893 If no revision is given, the first parent of the working directory
3884 is used, or the null revision if no revision is checked out.
3894 is used, or the null revision if no revision is checked out.
3885
3895
3886 With -v, print file permissions, symlink and executable bits.
3896 With -v, print file permissions, symlink and executable bits.
3887 With --debug, print file revision hashes.
3897 With --debug, print file revision hashes.
3888
3898
3889 If option --all is specified, the list of all files from all revisions
3899 If option --all is specified, the list of all files from all revisions
3890 is printed. This includes deleted and renamed files.
3900 is printed. This includes deleted and renamed files.
3891
3901
3892 Returns 0 on success.
3902 Returns 0 on success.
3893 """
3903 """
3894 opts = pycompat.byteskwargs(opts)
3904 opts = pycompat.byteskwargs(opts)
3895 fm = ui.formatter('manifest', opts)
3905 fm = ui.formatter('manifest', opts)
3896
3906
3897 if opts.get('all'):
3907 if opts.get('all'):
3898 if rev or node:
3908 if rev or node:
3899 raise error.Abort(_("can't specify a revision with --all"))
3909 raise error.Abort(_("can't specify a revision with --all"))
3900
3910
3901 res = set()
3911 res = set()
3902 for rev in repo:
3912 for rev in repo:
3903 ctx = repo[rev]
3913 ctx = repo[rev]
3904 res |= set(ctx.files())
3914 res |= set(ctx.files())
3905
3915
3906 ui.pager('manifest')
3916 ui.pager('manifest')
3907 for f in sorted(res):
3917 for f in sorted(res):
3908 fm.startitem()
3918 fm.startitem()
3909 fm.write("path", '%s\n', f)
3919 fm.write("path", '%s\n', f)
3910 fm.end()
3920 fm.end()
3911 return
3921 return
3912
3922
3913 if rev and node:
3923 if rev and node:
3914 raise error.Abort(_("please specify just one revision"))
3924 raise error.Abort(_("please specify just one revision"))
3915
3925
3916 if not node:
3926 if not node:
3917 node = rev
3927 node = rev
3918
3928
3919 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3929 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3920 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3930 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3921 if node:
3931 if node:
3922 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3932 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3923 ctx = scmutil.revsingle(repo, node)
3933 ctx = scmutil.revsingle(repo, node)
3924 mf = ctx.manifest()
3934 mf = ctx.manifest()
3925 ui.pager('manifest')
3935 ui.pager('manifest')
3926 for f in ctx:
3936 for f in ctx:
3927 fm.startitem()
3937 fm.startitem()
3928 fm.context(ctx=ctx)
3938 fm.context(ctx=ctx)
3929 fl = ctx[f].flags()
3939 fl = ctx[f].flags()
3930 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3940 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3931 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3941 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3932 fm.write('path', '%s\n', f)
3942 fm.write('path', '%s\n', f)
3933 fm.end()
3943 fm.end()
3934
3944
3935 @command('merge',
3945 @command('merge',
3936 [('f', 'force', None,
3946 [('f', 'force', None,
3937 _('force a merge including outstanding changes (DEPRECATED)')),
3947 _('force a merge including outstanding changes (DEPRECATED)')),
3938 ('r', 'rev', '', _('revision to merge'), _('REV')),
3948 ('r', 'rev', '', _('revision to merge'), _('REV')),
3939 ('P', 'preview', None,
3949 ('P', 'preview', None,
3940 _('review revisions to merge (no merge is performed)')),
3950 _('review revisions to merge (no merge is performed)')),
3941 ('', 'abort', None, _('abort the ongoing merge')),
3951 ('', 'abort', None, _('abort the ongoing merge')),
3942 ] + mergetoolopts,
3952 ] + mergetoolopts,
3943 _('[-P] [[-r] REV]'),
3953 _('[-P] [[-r] REV]'),
3944 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True)
3954 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT, helpbasic=True)
3945 def merge(ui, repo, node=None, **opts):
3955 def merge(ui, repo, node=None, **opts):
3946 """merge another revision into working directory
3956 """merge another revision into working directory
3947
3957
3948 The current working directory is updated with all changes made in
3958 The current working directory is updated with all changes made in
3949 the requested revision since the last common predecessor revision.
3959 the requested revision since the last common predecessor revision.
3950
3960
3951 Files that changed between either parent are marked as changed for
3961 Files that changed between either parent are marked as changed for
3952 the next commit and a commit must be performed before any further
3962 the next commit and a commit must be performed before any further
3953 updates to the repository are allowed. The next commit will have
3963 updates to the repository are allowed. The next commit will have
3954 two parents.
3964 two parents.
3955
3965
3956 ``--tool`` can be used to specify the merge tool used for file
3966 ``--tool`` can be used to specify the merge tool used for file
3957 merges. It overrides the HGMERGE environment variable and your
3967 merges. It overrides the HGMERGE environment variable and your
3958 configuration files. See :hg:`help merge-tools` for options.
3968 configuration files. See :hg:`help merge-tools` for options.
3959
3969
3960 If no revision is specified, the working directory's parent is a
3970 If no revision is specified, the working directory's parent is a
3961 head revision, and the current branch contains exactly one other
3971 head revision, and the current branch contains exactly one other
3962 head, the other head is merged with by default. Otherwise, an
3972 head, the other head is merged with by default. Otherwise, an
3963 explicit revision with which to merge with must be provided.
3973 explicit revision with which to merge with must be provided.
3964
3974
3965 See :hg:`help resolve` for information on handling file conflicts.
3975 See :hg:`help resolve` for information on handling file conflicts.
3966
3976
3967 To undo an uncommitted merge, use :hg:`merge --abort` which
3977 To undo an uncommitted merge, use :hg:`merge --abort` which
3968 will check out a clean copy of the original merge parent, losing
3978 will check out a clean copy of the original merge parent, losing
3969 all changes.
3979 all changes.
3970
3980
3971 Returns 0 on success, 1 if there are unresolved files.
3981 Returns 0 on success, 1 if there are unresolved files.
3972 """
3982 """
3973
3983
3974 opts = pycompat.byteskwargs(opts)
3984 opts = pycompat.byteskwargs(opts)
3975 abort = opts.get('abort')
3985 abort = opts.get('abort')
3976 if abort and repo.dirstate.p2() == nullid:
3986 if abort and repo.dirstate.p2() == nullid:
3977 cmdutil.wrongtooltocontinue(repo, _('merge'))
3987 cmdutil.wrongtooltocontinue(repo, _('merge'))
3978 if abort:
3988 if abort:
3979 if node:
3989 if node:
3980 raise error.Abort(_("cannot specify a node with --abort"))
3990 raise error.Abort(_("cannot specify a node with --abort"))
3981 if opts.get('rev'):
3991 if opts.get('rev'):
3982 raise error.Abort(_("cannot specify both --rev and --abort"))
3992 raise error.Abort(_("cannot specify both --rev and --abort"))
3983 if opts.get('preview'):
3993 if opts.get('preview'):
3984 raise error.Abort(_("cannot specify --preview with --abort"))
3994 raise error.Abort(_("cannot specify --preview with --abort"))
3985 if opts.get('rev') and node:
3995 if opts.get('rev') and node:
3986 raise error.Abort(_("please specify just one revision"))
3996 raise error.Abort(_("please specify just one revision"))
3987 if not node:
3997 if not node:
3988 node = opts.get('rev')
3998 node = opts.get('rev')
3989
3999
3990 if node:
4000 if node:
3991 node = scmutil.revsingle(repo, node).node()
4001 node = scmutil.revsingle(repo, node).node()
3992
4002
3993 if not node and not abort:
4003 if not node and not abort:
3994 node = repo[destutil.destmerge(repo)].node()
4004 node = repo[destutil.destmerge(repo)].node()
3995
4005
3996 if opts.get('preview'):
4006 if opts.get('preview'):
3997 # find nodes that are ancestors of p2 but not of p1
4007 # find nodes that are ancestors of p2 but not of p1
3998 p1 = repo.lookup('.')
4008 p1 = repo.lookup('.')
3999 p2 = node
4009 p2 = node
4000 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4010 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4001
4011
4002 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4012 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4003 for node in nodes:
4013 for node in nodes:
4004 displayer.show(repo[node])
4014 displayer.show(repo[node])
4005 displayer.close()
4015 displayer.close()
4006 return 0
4016 return 0
4007
4017
4008 # ui.forcemerge is an internal variable, do not document
4018 # ui.forcemerge is an internal variable, do not document
4009 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4019 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4010 with ui.configoverride(overrides, 'merge'):
4020 with ui.configoverride(overrides, 'merge'):
4011 force = opts.get('force')
4021 force = opts.get('force')
4012 labels = ['working copy', 'merge rev']
4022 labels = ['working copy', 'merge rev']
4013 return hg.merge(repo, node, force=force, mergeforce=force,
4023 return hg.merge(repo, node, force=force, mergeforce=force,
4014 labels=labels, abort=abort)
4024 labels=labels, abort=abort)
4015
4025
4016 @command('outgoing|out',
4026 @command('outgoing|out',
4017 [('f', 'force', None, _('run even when the destination is unrelated')),
4027 [('f', 'force', None, _('run even when the destination is unrelated')),
4018 ('r', 'rev', [],
4028 ('r', 'rev', [],
4019 _('a changeset intended to be included in the destination'), _('REV')),
4029 _('a changeset intended to be included in the destination'), _('REV')),
4020 ('n', 'newest-first', None, _('show newest record first')),
4030 ('n', 'newest-first', None, _('show newest record first')),
4021 ('B', 'bookmarks', False, _('compare bookmarks')),
4031 ('B', 'bookmarks', False, _('compare bookmarks')),
4022 ('b', 'branch', [], _('a specific branch you would like to push'),
4032 ('b', 'branch', [], _('a specific branch you would like to push'),
4023 _('BRANCH')),
4033 _('BRANCH')),
4024 ] + logopts + remoteopts + subrepoopts,
4034 ] + logopts + remoteopts + subrepoopts,
4025 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4035 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
4026 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
4036 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
4027 def outgoing(ui, repo, dest=None, **opts):
4037 def outgoing(ui, repo, dest=None, **opts):
4028 """show changesets not found in the destination
4038 """show changesets not found in the destination
4029
4039
4030 Show changesets not found in the specified destination repository
4040 Show changesets not found in the specified destination repository
4031 or the default push location. These are the changesets that would
4041 or the default push location. These are the changesets that would
4032 be pushed if a push was requested.
4042 be pushed if a push was requested.
4033
4043
4034 See pull for details of valid destination formats.
4044 See pull for details of valid destination formats.
4035
4045
4036 .. container:: verbose
4046 .. container:: verbose
4037
4047
4038 With -B/--bookmarks, the result of bookmark comparison between
4048 With -B/--bookmarks, the result of bookmark comparison between
4039 local and remote repositories is displayed. With -v/--verbose,
4049 local and remote repositories is displayed. With -v/--verbose,
4040 status is also displayed for each bookmark like below::
4050 status is also displayed for each bookmark like below::
4041
4051
4042 BM1 01234567890a added
4052 BM1 01234567890a added
4043 BM2 deleted
4053 BM2 deleted
4044 BM3 234567890abc advanced
4054 BM3 234567890abc advanced
4045 BM4 34567890abcd diverged
4055 BM4 34567890abcd diverged
4046 BM5 4567890abcde changed
4056 BM5 4567890abcde changed
4047
4057
4048 The action taken when pushing depends on the
4058 The action taken when pushing depends on the
4049 status of each bookmark:
4059 status of each bookmark:
4050
4060
4051 :``added``: push with ``-B`` will create it
4061 :``added``: push with ``-B`` will create it
4052 :``deleted``: push with ``-B`` will delete it
4062 :``deleted``: push with ``-B`` will delete it
4053 :``advanced``: push will update it
4063 :``advanced``: push will update it
4054 :``diverged``: push with ``-B`` will update it
4064 :``diverged``: push with ``-B`` will update it
4055 :``changed``: push with ``-B`` will update it
4065 :``changed``: push with ``-B`` will update it
4056
4066
4057 From the point of view of pushing behavior, bookmarks
4067 From the point of view of pushing behavior, bookmarks
4058 existing only in the remote repository are treated as
4068 existing only in the remote repository are treated as
4059 ``deleted``, even if it is in fact added remotely.
4069 ``deleted``, even if it is in fact added remotely.
4060
4070
4061 Returns 0 if there are outgoing changes, 1 otherwise.
4071 Returns 0 if there are outgoing changes, 1 otherwise.
4062 """
4072 """
4063 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4073 # hg._outgoing() needs to re-resolve the path in order to handle #branch
4064 # style URLs, so don't overwrite dest.
4074 # style URLs, so don't overwrite dest.
4065 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4075 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4066 if not path:
4076 if not path:
4067 raise error.Abort(_('default repository not configured!'),
4077 raise error.Abort(_('default repository not configured!'),
4068 hint=_("see 'hg help config.paths'"))
4078 hint=_("see 'hg help config.paths'"))
4069
4079
4070 opts = pycompat.byteskwargs(opts)
4080 opts = pycompat.byteskwargs(opts)
4071 if opts.get('graph'):
4081 if opts.get('graph'):
4072 logcmdutil.checkunsupportedgraphflags([], opts)
4082 logcmdutil.checkunsupportedgraphflags([], opts)
4073 o, other = hg._outgoing(ui, repo, dest, opts)
4083 o, other = hg._outgoing(ui, repo, dest, opts)
4074 if not o:
4084 if not o:
4075 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4085 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4076 return
4086 return
4077
4087
4078 revdag = logcmdutil.graphrevs(repo, o, opts)
4088 revdag = logcmdutil.graphrevs(repo, o, opts)
4079 ui.pager('outgoing')
4089 ui.pager('outgoing')
4080 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4090 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
4081 logcmdutil.displaygraph(ui, repo, revdag, displayer,
4091 logcmdutil.displaygraph(ui, repo, revdag, displayer,
4082 graphmod.asciiedges)
4092 graphmod.asciiedges)
4083 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4093 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4084 return 0
4094 return 0
4085
4095
4086 if opts.get('bookmarks'):
4096 if opts.get('bookmarks'):
4087 dest = path.pushloc or path.loc
4097 dest = path.pushloc or path.loc
4088 other = hg.peer(repo, opts, dest)
4098 other = hg.peer(repo, opts, dest)
4089 if 'bookmarks' not in other.listkeys('namespaces'):
4099 if 'bookmarks' not in other.listkeys('namespaces'):
4090 ui.warn(_("remote doesn't support bookmarks\n"))
4100 ui.warn(_("remote doesn't support bookmarks\n"))
4091 return 0
4101 return 0
4092 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4102 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4093 ui.pager('outgoing')
4103 ui.pager('outgoing')
4094 return bookmarks.outgoing(ui, repo, other)
4104 return bookmarks.outgoing(ui, repo, other)
4095
4105
4096 repo._subtoppath = path.pushloc or path.loc
4106 repo._subtoppath = path.pushloc or path.loc
4097 try:
4107 try:
4098 return hg.outgoing(ui, repo, dest, opts)
4108 return hg.outgoing(ui, repo, dest, opts)
4099 finally:
4109 finally:
4100 del repo._subtoppath
4110 del repo._subtoppath
4101
4111
4102 @command('parents',
4112 @command('parents',
4103 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4113 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4104 ] + templateopts,
4114 ] + templateopts,
4105 _('[-r REV] [FILE]'),
4115 _('[-r REV] [FILE]'),
4106 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4116 helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
4107 inferrepo=True)
4117 inferrepo=True)
4108 def parents(ui, repo, file_=None, **opts):
4118 def parents(ui, repo, file_=None, **opts):
4109 """show the parents of the working directory or revision (DEPRECATED)
4119 """show the parents of the working directory or revision (DEPRECATED)
4110
4120
4111 Print the working directory's parent revisions. If a revision is
4121 Print the working directory's parent revisions. If a revision is
4112 given via -r/--rev, the parent of that revision will be printed.
4122 given via -r/--rev, the parent of that revision will be printed.
4113 If a file argument is given, the revision in which the file was
4123 If a file argument is given, the revision in which the file was
4114 last changed (before the working directory revision or the
4124 last changed (before the working directory revision or the
4115 argument to --rev if given) is printed.
4125 argument to --rev if given) is printed.
4116
4126
4117 This command is equivalent to::
4127 This command is equivalent to::
4118
4128
4119 hg log -r "p1()+p2()" or
4129 hg log -r "p1()+p2()" or
4120 hg log -r "p1(REV)+p2(REV)" or
4130 hg log -r "p1(REV)+p2(REV)" or
4121 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
4131 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
4122 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
4132 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
4123
4133
4124 See :hg:`summary` and :hg:`help revsets` for related information.
4134 See :hg:`summary` and :hg:`help revsets` for related information.
4125
4135
4126 Returns 0 on success.
4136 Returns 0 on success.
4127 """
4137 """
4128
4138
4129 opts = pycompat.byteskwargs(opts)
4139 opts = pycompat.byteskwargs(opts)
4130 rev = opts.get('rev')
4140 rev = opts.get('rev')
4131 if rev:
4141 if rev:
4132 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4142 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4133 ctx = scmutil.revsingle(repo, rev, None)
4143 ctx = scmutil.revsingle(repo, rev, None)
4134
4144
4135 if file_:
4145 if file_:
4136 m = scmutil.match(ctx, (file_,), opts)
4146 m = scmutil.match(ctx, (file_,), opts)
4137 if m.anypats() or len(m.files()) != 1:
4147 if m.anypats() or len(m.files()) != 1:
4138 raise error.Abort(_('can only specify an explicit filename'))
4148 raise error.Abort(_('can only specify an explicit filename'))
4139 file_ = m.files()[0]
4149 file_ = m.files()[0]
4140 filenodes = []
4150 filenodes = []
4141 for cp in ctx.parents():
4151 for cp in ctx.parents():
4142 if not cp:
4152 if not cp:
4143 continue
4153 continue
4144 try:
4154 try:
4145 filenodes.append(cp.filenode(file_))
4155 filenodes.append(cp.filenode(file_))
4146 except error.LookupError:
4156 except error.LookupError:
4147 pass
4157 pass
4148 if not filenodes:
4158 if not filenodes:
4149 raise error.Abort(_("'%s' not found in manifest!") % file_)
4159 raise error.Abort(_("'%s' not found in manifest!") % file_)
4150 p = []
4160 p = []
4151 for fn in filenodes:
4161 for fn in filenodes:
4152 fctx = repo.filectx(file_, fileid=fn)
4162 fctx = repo.filectx(file_, fileid=fn)
4153 p.append(fctx.node())
4163 p.append(fctx.node())
4154 else:
4164 else:
4155 p = [cp.node() for cp in ctx.parents()]
4165 p = [cp.node() for cp in ctx.parents()]
4156
4166
4157 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4167 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
4158 for n in p:
4168 for n in p:
4159 if n != nullid:
4169 if n != nullid:
4160 displayer.show(repo[n])
4170 displayer.show(repo[n])
4161 displayer.close()
4171 displayer.close()
4162
4172
4163 @command('paths', formatteropts, _('[NAME]'),
4173 @command('paths', formatteropts, _('[NAME]'),
4164 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4174 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4165 optionalrepo=True, intents={INTENT_READONLY})
4175 optionalrepo=True, intents={INTENT_READONLY})
4166 def paths(ui, repo, search=None, **opts):
4176 def paths(ui, repo, search=None, **opts):
4167 """show aliases for remote repositories
4177 """show aliases for remote repositories
4168
4178
4169 Show definition of symbolic path name NAME. If no name is given,
4179 Show definition of symbolic path name NAME. If no name is given,
4170 show definition of all available names.
4180 show definition of all available names.
4171
4181
4172 Option -q/--quiet suppresses all output when searching for NAME
4182 Option -q/--quiet suppresses all output when searching for NAME
4173 and shows only the path names when listing all definitions.
4183 and shows only the path names when listing all definitions.
4174
4184
4175 Path names are defined in the [paths] section of your
4185 Path names are defined in the [paths] section of your
4176 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4186 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4177 repository, ``.hg/hgrc`` is used, too.
4187 repository, ``.hg/hgrc`` is used, too.
4178
4188
4179 The path names ``default`` and ``default-push`` have a special
4189 The path names ``default`` and ``default-push`` have a special
4180 meaning. When performing a push or pull operation, they are used
4190 meaning. When performing a push or pull operation, they are used
4181 as fallbacks if no location is specified on the command-line.
4191 as fallbacks if no location is specified on the command-line.
4182 When ``default-push`` is set, it will be used for push and
4192 When ``default-push`` is set, it will be used for push and
4183 ``default`` will be used for pull; otherwise ``default`` is used
4193 ``default`` will be used for pull; otherwise ``default`` is used
4184 as the fallback for both. When cloning a repository, the clone
4194 as the fallback for both. When cloning a repository, the clone
4185 source is written as ``default`` in ``.hg/hgrc``.
4195 source is written as ``default`` in ``.hg/hgrc``.
4186
4196
4187 .. note::
4197 .. note::
4188
4198
4189 ``default`` and ``default-push`` apply to all inbound (e.g.
4199 ``default`` and ``default-push`` apply to all inbound (e.g.
4190 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
4200 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
4191 and :hg:`bundle`) operations.
4201 and :hg:`bundle`) operations.
4192
4202
4193 See :hg:`help urls` for more information.
4203 See :hg:`help urls` for more information.
4194
4204
4195 .. container:: verbose
4205 .. container:: verbose
4196
4206
4197 Template:
4207 Template:
4198
4208
4199 The following keywords are supported. See also :hg:`help templates`.
4209 The following keywords are supported. See also :hg:`help templates`.
4200
4210
4201 :name: String. Symbolic name of the path alias.
4211 :name: String. Symbolic name of the path alias.
4202 :pushurl: String. URL for push operations.
4212 :pushurl: String. URL for push operations.
4203 :url: String. URL or directory path for the other operations.
4213 :url: String. URL or directory path for the other operations.
4204
4214
4205 Returns 0 on success.
4215 Returns 0 on success.
4206 """
4216 """
4207
4217
4208 opts = pycompat.byteskwargs(opts)
4218 opts = pycompat.byteskwargs(opts)
4209 ui.pager('paths')
4219 ui.pager('paths')
4210 if search:
4220 if search:
4211 pathitems = [(name, path) for name, path in ui.paths.iteritems()
4221 pathitems = [(name, path) for name, path in ui.paths.iteritems()
4212 if name == search]
4222 if name == search]
4213 else:
4223 else:
4214 pathitems = sorted(ui.paths.iteritems())
4224 pathitems = sorted(ui.paths.iteritems())
4215
4225
4216 fm = ui.formatter('paths', opts)
4226 fm = ui.formatter('paths', opts)
4217 if fm.isplain():
4227 if fm.isplain():
4218 hidepassword = util.hidepassword
4228 hidepassword = util.hidepassword
4219 else:
4229 else:
4220 hidepassword = bytes
4230 hidepassword = bytes
4221 if ui.quiet:
4231 if ui.quiet:
4222 namefmt = '%s\n'
4232 namefmt = '%s\n'
4223 else:
4233 else:
4224 namefmt = '%s = '
4234 namefmt = '%s = '
4225 showsubopts = not search and not ui.quiet
4235 showsubopts = not search and not ui.quiet
4226
4236
4227 for name, path in pathitems:
4237 for name, path in pathitems:
4228 fm.startitem()
4238 fm.startitem()
4229 fm.condwrite(not search, 'name', namefmt, name)
4239 fm.condwrite(not search, 'name', namefmt, name)
4230 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
4240 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
4231 for subopt, value in sorted(path.suboptions.items()):
4241 for subopt, value in sorted(path.suboptions.items()):
4232 assert subopt not in ('name', 'url')
4242 assert subopt not in ('name', 'url')
4233 if showsubopts:
4243 if showsubopts:
4234 fm.plain('%s:%s = ' % (name, subopt))
4244 fm.plain('%s:%s = ' % (name, subopt))
4235 fm.condwrite(showsubopts, subopt, '%s\n', value)
4245 fm.condwrite(showsubopts, subopt, '%s\n', value)
4236
4246
4237 fm.end()
4247 fm.end()
4238
4248
4239 if search and not pathitems:
4249 if search and not pathitems:
4240 if not ui.quiet:
4250 if not ui.quiet:
4241 ui.warn(_("not found!\n"))
4251 ui.warn(_("not found!\n"))
4242 return 1
4252 return 1
4243 else:
4253 else:
4244 return 0
4254 return 0
4245
4255
4246 @command('phase',
4256 @command('phase',
4247 [('p', 'public', False, _('set changeset phase to public')),
4257 [('p', 'public', False, _('set changeset phase to public')),
4248 ('d', 'draft', False, _('set changeset phase to draft')),
4258 ('d', 'draft', False, _('set changeset phase to draft')),
4249 ('s', 'secret', False, _('set changeset phase to secret')),
4259 ('s', 'secret', False, _('set changeset phase to secret')),
4250 ('f', 'force', False, _('allow to move boundary backward')),
4260 ('f', 'force', False, _('allow to move boundary backward')),
4251 ('r', 'rev', [], _('target revision'), _('REV')),
4261 ('r', 'rev', [], _('target revision'), _('REV')),
4252 ],
4262 ],
4253 _('[-p|-d|-s] [-f] [-r] [REV...]'),
4263 _('[-p|-d|-s] [-f] [-r] [REV...]'),
4254 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
4264 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
4255 def phase(ui, repo, *revs, **opts):
4265 def phase(ui, repo, *revs, **opts):
4256 """set or show the current phase name
4266 """set or show the current phase name
4257
4267
4258 With no argument, show the phase name of the current revision(s).
4268 With no argument, show the phase name of the current revision(s).
4259
4269
4260 With one of -p/--public, -d/--draft or -s/--secret, change the
4270 With one of -p/--public, -d/--draft or -s/--secret, change the
4261 phase value of the specified revisions.
4271 phase value of the specified revisions.
4262
4272
4263 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
4273 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
4264 lower phase to a higher phase. Phases are ordered as follows::
4274 lower phase to a higher phase. Phases are ordered as follows::
4265
4275
4266 public < draft < secret
4276 public < draft < secret
4267
4277
4268 Returns 0 on success, 1 if some phases could not be changed.
4278 Returns 0 on success, 1 if some phases could not be changed.
4269
4279
4270 (For more information about the phases concept, see :hg:`help phases`.)
4280 (For more information about the phases concept, see :hg:`help phases`.)
4271 """
4281 """
4272 opts = pycompat.byteskwargs(opts)
4282 opts = pycompat.byteskwargs(opts)
4273 # search for a unique phase argument
4283 # search for a unique phase argument
4274 targetphase = None
4284 targetphase = None
4275 for idx, name in enumerate(phases.cmdphasenames):
4285 for idx, name in enumerate(phases.cmdphasenames):
4276 if opts[name]:
4286 if opts[name]:
4277 if targetphase is not None:
4287 if targetphase is not None:
4278 raise error.Abort(_('only one phase can be specified'))
4288 raise error.Abort(_('only one phase can be specified'))
4279 targetphase = idx
4289 targetphase = idx
4280
4290
4281 # look for specified revision
4291 # look for specified revision
4282 revs = list(revs)
4292 revs = list(revs)
4283 revs.extend(opts['rev'])
4293 revs.extend(opts['rev'])
4284 if not revs:
4294 if not revs:
4285 # display both parents as the second parent phase can influence
4295 # display both parents as the second parent phase can influence
4286 # the phase of a merge commit
4296 # the phase of a merge commit
4287 revs = [c.rev() for c in repo[None].parents()]
4297 revs = [c.rev() for c in repo[None].parents()]
4288
4298
4289 revs = scmutil.revrange(repo, revs)
4299 revs = scmutil.revrange(repo, revs)
4290
4300
4291 ret = 0
4301 ret = 0
4292 if targetphase is None:
4302 if targetphase is None:
4293 # display
4303 # display
4294 for r in revs:
4304 for r in revs:
4295 ctx = repo[r]
4305 ctx = repo[r]
4296 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4306 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4297 else:
4307 else:
4298 with repo.lock(), repo.transaction("phase") as tr:
4308 with repo.lock(), repo.transaction("phase") as tr:
4299 # set phase
4309 # set phase
4300 if not revs:
4310 if not revs:
4301 raise error.Abort(_('empty revision set'))
4311 raise error.Abort(_('empty revision set'))
4302 nodes = [repo[r].node() for r in revs]
4312 nodes = [repo[r].node() for r in revs]
4303 # moving revision from public to draft may hide them
4313 # moving revision from public to draft may hide them
4304 # We have to check result on an unfiltered repository
4314 # We have to check result on an unfiltered repository
4305 unfi = repo.unfiltered()
4315 unfi = repo.unfiltered()
4306 getphase = unfi._phasecache.phase
4316 getphase = unfi._phasecache.phase
4307 olddata = [getphase(unfi, r) for r in unfi]
4317 olddata = [getphase(unfi, r) for r in unfi]
4308 phases.advanceboundary(repo, tr, targetphase, nodes)
4318 phases.advanceboundary(repo, tr, targetphase, nodes)
4309 if opts['force']:
4319 if opts['force']:
4310 phases.retractboundary(repo, tr, targetphase, nodes)
4320 phases.retractboundary(repo, tr, targetphase, nodes)
4311 getphase = unfi._phasecache.phase
4321 getphase = unfi._phasecache.phase
4312 newdata = [getphase(unfi, r) for r in unfi]
4322 newdata = [getphase(unfi, r) for r in unfi]
4313 changes = sum(newdata[r] != olddata[r] for r in unfi)
4323 changes = sum(newdata[r] != olddata[r] for r in unfi)
4314 cl = unfi.changelog
4324 cl = unfi.changelog
4315 rejected = [n for n in nodes
4325 rejected = [n for n in nodes
4316 if newdata[cl.rev(n)] < targetphase]
4326 if newdata[cl.rev(n)] < targetphase]
4317 if rejected:
4327 if rejected:
4318 ui.warn(_('cannot move %i changesets to a higher '
4328 ui.warn(_('cannot move %i changesets to a higher '
4319 'phase, use --force\n') % len(rejected))
4329 'phase, use --force\n') % len(rejected))
4320 ret = 1
4330 ret = 1
4321 if changes:
4331 if changes:
4322 msg = _('phase changed for %i changesets\n') % changes
4332 msg = _('phase changed for %i changesets\n') % changes
4323 if ret:
4333 if ret:
4324 ui.status(msg)
4334 ui.status(msg)
4325 else:
4335 else:
4326 ui.note(msg)
4336 ui.note(msg)
4327 else:
4337 else:
4328 ui.warn(_('no phases changed\n'))
4338 ui.warn(_('no phases changed\n'))
4329 return ret
4339 return ret
4330
4340
4331 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
4341 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
4332 """Run after a changegroup has been added via pull/unbundle
4342 """Run after a changegroup has been added via pull/unbundle
4333
4343
4334 This takes arguments below:
4344 This takes arguments below:
4335
4345
4336 :modheads: change of heads by pull/unbundle
4346 :modheads: change of heads by pull/unbundle
4337 :optupdate: updating working directory is needed or not
4347 :optupdate: updating working directory is needed or not
4338 :checkout: update destination revision (or None to default destination)
4348 :checkout: update destination revision (or None to default destination)
4339 :brev: a name, which might be a bookmark to be activated after updating
4349 :brev: a name, which might be a bookmark to be activated after updating
4340 """
4350 """
4341 if modheads == 0:
4351 if modheads == 0:
4342 return
4352 return
4343 if optupdate:
4353 if optupdate:
4344 try:
4354 try:
4345 return hg.updatetotally(ui, repo, checkout, brev)
4355 return hg.updatetotally(ui, repo, checkout, brev)
4346 except error.UpdateAbort as inst:
4356 except error.UpdateAbort as inst:
4347 msg = _("not updating: %s") % stringutil.forcebytestr(inst)
4357 msg = _("not updating: %s") % stringutil.forcebytestr(inst)
4348 hint = inst.hint
4358 hint = inst.hint
4349 raise error.UpdateAbort(msg, hint=hint)
4359 raise error.UpdateAbort(msg, hint=hint)
4350 if modheads > 1:
4360 if modheads > 1:
4351 currentbranchheads = len(repo.branchheads())
4361 currentbranchheads = len(repo.branchheads())
4352 if currentbranchheads == modheads:
4362 if currentbranchheads == modheads:
4353 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4363 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4354 elif currentbranchheads > 1:
4364 elif currentbranchheads > 1:
4355 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4365 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4356 "merge)\n"))
4366 "merge)\n"))
4357 else:
4367 else:
4358 ui.status(_("(run 'hg heads' to see heads)\n"))
4368 ui.status(_("(run 'hg heads' to see heads)\n"))
4359 elif not ui.configbool('commands', 'update.requiredest'):
4369 elif not ui.configbool('commands', 'update.requiredest'):
4360 ui.status(_("(run 'hg update' to get a working copy)\n"))
4370 ui.status(_("(run 'hg update' to get a working copy)\n"))
4361
4371
4362 @command('pull',
4372 @command('pull',
4363 [('u', 'update', None,
4373 [('u', 'update', None,
4364 _('update to new branch head if new descendants were pulled')),
4374 _('update to new branch head if new descendants were pulled')),
4365 ('f', 'force', None, _('run even when remote repository is unrelated')),
4375 ('f', 'force', None, _('run even when remote repository is unrelated')),
4366 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4376 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4367 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4377 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4368 ('b', 'branch', [], _('a specific branch you would like to pull'),
4378 ('b', 'branch', [], _('a specific branch you would like to pull'),
4369 _('BRANCH')),
4379 _('BRANCH')),
4370 ] + remoteopts,
4380 ] + remoteopts,
4371 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
4381 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
4372 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4382 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4373 helpbasic=True)
4383 helpbasic=True)
4374 def pull(ui, repo, source="default", **opts):
4384 def pull(ui, repo, source="default", **opts):
4375 """pull changes from the specified source
4385 """pull changes from the specified source
4376
4386
4377 Pull changes from a remote repository to a local one.
4387 Pull changes from a remote repository to a local one.
4378
4388
4379 This finds all changes from the repository at the specified path
4389 This finds all changes from the repository at the specified path
4380 or URL and adds them to a local repository (the current one unless
4390 or URL and adds them to a local repository (the current one unless
4381 -R is specified). By default, this does not update the copy of the
4391 -R is specified). By default, this does not update the copy of the
4382 project in the working directory.
4392 project in the working directory.
4383
4393
4384 When cloning from servers that support it, Mercurial may fetch
4394 When cloning from servers that support it, Mercurial may fetch
4385 pre-generated data. When this is done, hooks operating on incoming
4395 pre-generated data. When this is done, hooks operating on incoming
4386 changesets and changegroups may fire more than once, once for each
4396 changesets and changegroups may fire more than once, once for each
4387 pre-generated bundle and as well as for any additional remaining
4397 pre-generated bundle and as well as for any additional remaining
4388 data. See :hg:`help -e clonebundles` for more.
4398 data. See :hg:`help -e clonebundles` for more.
4389
4399
4390 Use :hg:`incoming` if you want to see what would have been added
4400 Use :hg:`incoming` if you want to see what would have been added
4391 by a pull at the time you issued this command. If you then decide
4401 by a pull at the time you issued this command. If you then decide
4392 to add those changes to the repository, you should use :hg:`pull
4402 to add those changes to the repository, you should use :hg:`pull
4393 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4403 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4394
4404
4395 If SOURCE is omitted, the 'default' path will be used.
4405 If SOURCE is omitted, the 'default' path will be used.
4396 See :hg:`help urls` for more information.
4406 See :hg:`help urls` for more information.
4397
4407
4398 Specifying bookmark as ``.`` is equivalent to specifying the active
4408 Specifying bookmark as ``.`` is equivalent to specifying the active
4399 bookmark's name.
4409 bookmark's name.
4400
4410
4401 Returns 0 on success, 1 if an update had unresolved files.
4411 Returns 0 on success, 1 if an update had unresolved files.
4402 """
4412 """
4403
4413
4404 opts = pycompat.byteskwargs(opts)
4414 opts = pycompat.byteskwargs(opts)
4405 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
4415 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
4406 msg = _('update destination required by configuration')
4416 msg = _('update destination required by configuration')
4407 hint = _('use hg pull followed by hg update DEST')
4417 hint = _('use hg pull followed by hg update DEST')
4408 raise error.Abort(msg, hint=hint)
4418 raise error.Abort(msg, hint=hint)
4409
4419
4410 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4420 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4411 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4421 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4412 other = hg.peer(repo, opts, source)
4422 other = hg.peer(repo, opts, source)
4413 try:
4423 try:
4414 revs, checkout = hg.addbranchrevs(repo, other, branches,
4424 revs, checkout = hg.addbranchrevs(repo, other, branches,
4415 opts.get('rev'))
4425 opts.get('rev'))
4416
4426
4417 pullopargs = {}
4427 pullopargs = {}
4418
4428
4419 nodes = None
4429 nodes = None
4420 if opts['bookmark'] or revs:
4430 if opts['bookmark'] or revs:
4421 # The list of bookmark used here is the same used to actually update
4431 # The list of bookmark used here is the same used to actually update
4422 # the bookmark names, to avoid the race from issue 4689 and we do
4432 # the bookmark names, to avoid the race from issue 4689 and we do
4423 # all lookup and bookmark queries in one go so they see the same
4433 # all lookup and bookmark queries in one go so they see the same
4424 # version of the server state (issue 4700).
4434 # version of the server state (issue 4700).
4425 nodes = []
4435 nodes = []
4426 fnodes = []
4436 fnodes = []
4427 revs = revs or []
4437 revs = revs or []
4428 if revs and not other.capable('lookup'):
4438 if revs and not other.capable('lookup'):
4429 err = _("other repository doesn't support revision lookup, "
4439 err = _("other repository doesn't support revision lookup, "
4430 "so a rev cannot be specified.")
4440 "so a rev cannot be specified.")
4431 raise error.Abort(err)
4441 raise error.Abort(err)
4432 with other.commandexecutor() as e:
4442 with other.commandexecutor() as e:
4433 fremotebookmarks = e.callcommand('listkeys', {
4443 fremotebookmarks = e.callcommand('listkeys', {
4434 'namespace': 'bookmarks'
4444 'namespace': 'bookmarks'
4435 })
4445 })
4436 for r in revs:
4446 for r in revs:
4437 fnodes.append(e.callcommand('lookup', {'key': r}))
4447 fnodes.append(e.callcommand('lookup', {'key': r}))
4438 remotebookmarks = fremotebookmarks.result()
4448 remotebookmarks = fremotebookmarks.result()
4439 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4449 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4440 pullopargs['remotebookmarks'] = remotebookmarks
4450 pullopargs['remotebookmarks'] = remotebookmarks
4441 for b in opts['bookmark']:
4451 for b in opts['bookmark']:
4442 b = repo._bookmarks.expandname(b)
4452 b = repo._bookmarks.expandname(b)
4443 if b not in remotebookmarks:
4453 if b not in remotebookmarks:
4444 raise error.Abort(_('remote bookmark %s not found!') % b)
4454 raise error.Abort(_('remote bookmark %s not found!') % b)
4445 nodes.append(remotebookmarks[b])
4455 nodes.append(remotebookmarks[b])
4446 for i, rev in enumerate(revs):
4456 for i, rev in enumerate(revs):
4447 node = fnodes[i].result()
4457 node = fnodes[i].result()
4448 nodes.append(node)
4458 nodes.append(node)
4449 if rev == checkout:
4459 if rev == checkout:
4450 checkout = node
4460 checkout = node
4451
4461
4452 wlock = util.nullcontextmanager()
4462 wlock = util.nullcontextmanager()
4453 if opts.get('update'):
4463 if opts.get('update'):
4454 wlock = repo.wlock()
4464 wlock = repo.wlock()
4455 with wlock:
4465 with wlock:
4456 pullopargs.update(opts.get('opargs', {}))
4466 pullopargs.update(opts.get('opargs', {}))
4457 modheads = exchange.pull(repo, other, heads=nodes,
4467 modheads = exchange.pull(repo, other, heads=nodes,
4458 force=opts.get('force'),
4468 force=opts.get('force'),
4459 bookmarks=opts.get('bookmark', ()),
4469 bookmarks=opts.get('bookmark', ()),
4460 opargs=pullopargs).cgresult
4470 opargs=pullopargs).cgresult
4461
4471
4462 # brev is a name, which might be a bookmark to be activated at
4472 # brev is a name, which might be a bookmark to be activated at
4463 # the end of the update. In other words, it is an explicit
4473 # the end of the update. In other words, it is an explicit
4464 # destination of the update
4474 # destination of the update
4465 brev = None
4475 brev = None
4466
4476
4467 if checkout:
4477 if checkout:
4468 checkout = repo.changelog.rev(checkout)
4478 checkout = repo.changelog.rev(checkout)
4469
4479
4470 # order below depends on implementation of
4480 # order below depends on implementation of
4471 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4481 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4472 # because 'checkout' is determined without it.
4482 # because 'checkout' is determined without it.
4473 if opts.get('rev'):
4483 if opts.get('rev'):
4474 brev = opts['rev'][0]
4484 brev = opts['rev'][0]
4475 elif opts.get('branch'):
4485 elif opts.get('branch'):
4476 brev = opts['branch'][0]
4486 brev = opts['branch'][0]
4477 else:
4487 else:
4478 brev = branches[0]
4488 brev = branches[0]
4479 repo._subtoppath = source
4489 repo._subtoppath = source
4480 try:
4490 try:
4481 ret = postincoming(ui, repo, modheads, opts.get('update'),
4491 ret = postincoming(ui, repo, modheads, opts.get('update'),
4482 checkout, brev)
4492 checkout, brev)
4483
4493
4484 finally:
4494 finally:
4485 del repo._subtoppath
4495 del repo._subtoppath
4486
4496
4487 finally:
4497 finally:
4488 other.close()
4498 other.close()
4489 return ret
4499 return ret
4490
4500
4491 @command('push',
4501 @command('push',
4492 [('f', 'force', None, _('force push')),
4502 [('f', 'force', None, _('force push')),
4493 ('r', 'rev', [],
4503 ('r', 'rev', [],
4494 _('a changeset intended to be included in the destination'),
4504 _('a changeset intended to be included in the destination'),
4495 _('REV')),
4505 _('REV')),
4496 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4506 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4497 ('b', 'branch', [],
4507 ('b', 'branch', [],
4498 _('a specific branch you would like to push'), _('BRANCH')),
4508 _('a specific branch you would like to push'), _('BRANCH')),
4499 ('', 'new-branch', False, _('allow pushing a new branch')),
4509 ('', 'new-branch', False, _('allow pushing a new branch')),
4500 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4510 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4501 ('', 'publish', False, _('push the changeset as public (EXPERIMENTAL)')),
4511 ('', 'publish', False, _('push the changeset as public (EXPERIMENTAL)')),
4502 ] + remoteopts,
4512 ] + remoteopts,
4503 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
4513 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
4504 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4514 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
4505 helpbasic=True)
4515 helpbasic=True)
4506 def push(ui, repo, dest=None, **opts):
4516 def push(ui, repo, dest=None, **opts):
4507 """push changes to the specified destination
4517 """push changes to the specified destination
4508
4518
4509 Push changesets from the local repository to the specified
4519 Push changesets from the local repository to the specified
4510 destination.
4520 destination.
4511
4521
4512 This operation is symmetrical to pull: it is identical to a pull
4522 This operation is symmetrical to pull: it is identical to a pull
4513 in the destination repository from the current one.
4523 in the destination repository from the current one.
4514
4524
4515 By default, push will not allow creation of new heads at the
4525 By default, push will not allow creation of new heads at the
4516 destination, since multiple heads would make it unclear which head
4526 destination, since multiple heads would make it unclear which head
4517 to use. In this situation, it is recommended to pull and merge
4527 to use. In this situation, it is recommended to pull and merge
4518 before pushing.
4528 before pushing.
4519
4529
4520 Use --new-branch if you want to allow push to create a new named
4530 Use --new-branch if you want to allow push to create a new named
4521 branch that is not present at the destination. This allows you to
4531 branch that is not present at the destination. This allows you to
4522 only create a new branch without forcing other changes.
4532 only create a new branch without forcing other changes.
4523
4533
4524 .. note::
4534 .. note::
4525
4535
4526 Extra care should be taken with the -f/--force option,
4536 Extra care should be taken with the -f/--force option,
4527 which will push all new heads on all branches, an action which will
4537 which will push all new heads on all branches, an action which will
4528 almost always cause confusion for collaborators.
4538 almost always cause confusion for collaborators.
4529
4539
4530 If -r/--rev is used, the specified revision and all its ancestors
4540 If -r/--rev is used, the specified revision and all its ancestors
4531 will be pushed to the remote repository.
4541 will be pushed to the remote repository.
4532
4542
4533 If -B/--bookmark is used, the specified bookmarked revision, its
4543 If -B/--bookmark is used, the specified bookmarked revision, its
4534 ancestors, and the bookmark will be pushed to the remote
4544 ancestors, and the bookmark will be pushed to the remote
4535 repository. Specifying ``.`` is equivalent to specifying the active
4545 repository. Specifying ``.`` is equivalent to specifying the active
4536 bookmark's name.
4546 bookmark's name.
4537
4547
4538 Please see :hg:`help urls` for important details about ``ssh://``
4548 Please see :hg:`help urls` for important details about ``ssh://``
4539 URLs. If DESTINATION is omitted, a default path will be used.
4549 URLs. If DESTINATION is omitted, a default path will be used.
4540
4550
4541 .. container:: verbose
4551 .. container:: verbose
4542
4552
4543 The --pushvars option sends strings to the server that become
4553 The --pushvars option sends strings to the server that become
4544 environment variables prepended with ``HG_USERVAR_``. For example,
4554 environment variables prepended with ``HG_USERVAR_``. For example,
4545 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4555 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4546 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4556 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4547
4557
4548 pushvars can provide for user-overridable hooks as well as set debug
4558 pushvars can provide for user-overridable hooks as well as set debug
4549 levels. One example is having a hook that blocks commits containing
4559 levels. One example is having a hook that blocks commits containing
4550 conflict markers, but enables the user to override the hook if the file
4560 conflict markers, but enables the user to override the hook if the file
4551 is using conflict markers for testing purposes or the file format has
4561 is using conflict markers for testing purposes or the file format has
4552 strings that look like conflict markers.
4562 strings that look like conflict markers.
4553
4563
4554 By default, servers will ignore `--pushvars`. To enable it add the
4564 By default, servers will ignore `--pushvars`. To enable it add the
4555 following to your configuration file::
4565 following to your configuration file::
4556
4566
4557 [push]
4567 [push]
4558 pushvars.server = true
4568 pushvars.server = true
4559
4569
4560 Returns 0 if push was successful, 1 if nothing to push.
4570 Returns 0 if push was successful, 1 if nothing to push.
4561 """
4571 """
4562
4572
4563 opts = pycompat.byteskwargs(opts)
4573 opts = pycompat.byteskwargs(opts)
4564 if opts.get('bookmark'):
4574 if opts.get('bookmark'):
4565 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4575 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4566 for b in opts['bookmark']:
4576 for b in opts['bookmark']:
4567 # translate -B options to -r so changesets get pushed
4577 # translate -B options to -r so changesets get pushed
4568 b = repo._bookmarks.expandname(b)
4578 b = repo._bookmarks.expandname(b)
4569 if b in repo._bookmarks:
4579 if b in repo._bookmarks:
4570 opts.setdefault('rev', []).append(b)
4580 opts.setdefault('rev', []).append(b)
4571 else:
4581 else:
4572 # if we try to push a deleted bookmark, translate it to null
4582 # if we try to push a deleted bookmark, translate it to null
4573 # this lets simultaneous -r, -b options continue working
4583 # this lets simultaneous -r, -b options continue working
4574 opts.setdefault('rev', []).append("null")
4584 opts.setdefault('rev', []).append("null")
4575
4585
4576 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4586 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4577 if not path:
4587 if not path:
4578 raise error.Abort(_('default repository not configured!'),
4588 raise error.Abort(_('default repository not configured!'),
4579 hint=_("see 'hg help config.paths'"))
4589 hint=_("see 'hg help config.paths'"))
4580 dest = path.pushloc or path.loc
4590 dest = path.pushloc or path.loc
4581 branches = (path.branch, opts.get('branch') or [])
4591 branches = (path.branch, opts.get('branch') or [])
4582 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4592 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4583 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4593 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4584 other = hg.peer(repo, opts, dest)
4594 other = hg.peer(repo, opts, dest)
4585
4595
4586 if revs:
4596 if revs:
4587 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
4597 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
4588 if not revs:
4598 if not revs:
4589 raise error.Abort(_("specified revisions evaluate to an empty set"),
4599 raise error.Abort(_("specified revisions evaluate to an empty set"),
4590 hint=_("use different revision arguments"))
4600 hint=_("use different revision arguments"))
4591 elif path.pushrev:
4601 elif path.pushrev:
4592 # It doesn't make any sense to specify ancestor revisions. So limit
4602 # It doesn't make any sense to specify ancestor revisions. So limit
4593 # to DAG heads to make discovery simpler.
4603 # to DAG heads to make discovery simpler.
4594 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4604 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4595 revs = scmutil.revrange(repo, [expr])
4605 revs = scmutil.revrange(repo, [expr])
4596 revs = [repo[rev].node() for rev in revs]
4606 revs = [repo[rev].node() for rev in revs]
4597 if not revs:
4607 if not revs:
4598 raise error.Abort(_('default push revset for path evaluates to an '
4608 raise error.Abort(_('default push revset for path evaluates to an '
4599 'empty set'))
4609 'empty set'))
4600
4610
4601 repo._subtoppath = dest
4611 repo._subtoppath = dest
4602 try:
4612 try:
4603 # push subrepos depth-first for coherent ordering
4613 # push subrepos depth-first for coherent ordering
4604 c = repo['.']
4614 c = repo['.']
4605 subs = c.substate # only repos that are committed
4615 subs = c.substate # only repos that are committed
4606 for s in sorted(subs):
4616 for s in sorted(subs):
4607 result = c.sub(s).push(opts)
4617 result = c.sub(s).push(opts)
4608 if result == 0:
4618 if result == 0:
4609 return not result
4619 return not result
4610 finally:
4620 finally:
4611 del repo._subtoppath
4621 del repo._subtoppath
4612
4622
4613 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4623 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4614 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4624 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4615
4625
4616 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4626 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4617 newbranch=opts.get('new_branch'),
4627 newbranch=opts.get('new_branch'),
4618 bookmarks=opts.get('bookmark', ()),
4628 bookmarks=opts.get('bookmark', ()),
4619 publish=opts.get('publish'),
4629 publish=opts.get('publish'),
4620 opargs=opargs)
4630 opargs=opargs)
4621
4631
4622 result = not pushop.cgresult
4632 result = not pushop.cgresult
4623
4633
4624 if pushop.bkresult is not None:
4634 if pushop.bkresult is not None:
4625 if pushop.bkresult == 2:
4635 if pushop.bkresult == 2:
4626 result = 2
4636 result = 2
4627 elif not result and pushop.bkresult:
4637 elif not result and pushop.bkresult:
4628 result = 2
4638 result = 2
4629
4639
4630 return result
4640 return result
4631
4641
4632 @command('recover', [], helpcategory=command.CATEGORY_MAINTENANCE)
4642 @command('recover', [], helpcategory=command.CATEGORY_MAINTENANCE)
4633 def recover(ui, repo):
4643 def recover(ui, repo):
4634 """roll back an interrupted transaction
4644 """roll back an interrupted transaction
4635
4645
4636 Recover from an interrupted commit or pull.
4646 Recover from an interrupted commit or pull.
4637
4647
4638 This command tries to fix the repository status after an
4648 This command tries to fix the repository status after an
4639 interrupted operation. It should only be necessary when Mercurial
4649 interrupted operation. It should only be necessary when Mercurial
4640 suggests it.
4650 suggests it.
4641
4651
4642 Returns 0 if successful, 1 if nothing to recover or verify fails.
4652 Returns 0 if successful, 1 if nothing to recover or verify fails.
4643 """
4653 """
4644 if repo.recover():
4654 if repo.recover():
4645 return hg.verify(repo)
4655 return hg.verify(repo)
4646 return 1
4656 return 1
4647
4657
4648 @command('remove|rm',
4658 @command('remove|rm',
4649 [('A', 'after', None, _('record delete for missing files')),
4659 [('A', 'after', None, _('record delete for missing files')),
4650 ('f', 'force', None,
4660 ('f', 'force', None,
4651 _('forget added files, delete modified files')),
4661 _('forget added files, delete modified files')),
4652 ] + subrepoopts + walkopts + dryrunopts,
4662 ] + subrepoopts + walkopts + dryrunopts,
4653 _('[OPTION]... FILE...'),
4663 _('[OPTION]... FILE...'),
4654 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4664 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4655 helpbasic=True, inferrepo=True)
4665 helpbasic=True, inferrepo=True)
4656 def remove(ui, repo, *pats, **opts):
4666 def remove(ui, repo, *pats, **opts):
4657 """remove the specified files on the next commit
4667 """remove the specified files on the next commit
4658
4668
4659 Schedule the indicated files for removal from the current branch.
4669 Schedule the indicated files for removal from the current branch.
4660
4670
4661 This command schedules the files to be removed at the next commit.
4671 This command schedules the files to be removed at the next commit.
4662 To undo a remove before that, see :hg:`revert`. To undo added
4672 To undo a remove before that, see :hg:`revert`. To undo added
4663 files, see :hg:`forget`.
4673 files, see :hg:`forget`.
4664
4674
4665 .. container:: verbose
4675 .. container:: verbose
4666
4676
4667 -A/--after can be used to remove only files that have already
4677 -A/--after can be used to remove only files that have already
4668 been deleted, -f/--force can be used to force deletion, and -Af
4678 been deleted, -f/--force can be used to force deletion, and -Af
4669 can be used to remove files from the next revision without
4679 can be used to remove files from the next revision without
4670 deleting them from the working directory.
4680 deleting them from the working directory.
4671
4681
4672 The following table details the behavior of remove for different
4682 The following table details the behavior of remove for different
4673 file states (columns) and option combinations (rows). The file
4683 file states (columns) and option combinations (rows). The file
4674 states are Added [A], Clean [C], Modified [M] and Missing [!]
4684 states are Added [A], Clean [C], Modified [M] and Missing [!]
4675 (as reported by :hg:`status`). The actions are Warn, Remove
4685 (as reported by :hg:`status`). The actions are Warn, Remove
4676 (from branch) and Delete (from disk):
4686 (from branch) and Delete (from disk):
4677
4687
4678 ========= == == == ==
4688 ========= == == == ==
4679 opt/state A C M !
4689 opt/state A C M !
4680 ========= == == == ==
4690 ========= == == == ==
4681 none W RD W R
4691 none W RD W R
4682 -f R RD RD R
4692 -f R RD RD R
4683 -A W W W R
4693 -A W W W R
4684 -Af R R R R
4694 -Af R R R R
4685 ========= == == == ==
4695 ========= == == == ==
4686
4696
4687 .. note::
4697 .. note::
4688
4698
4689 :hg:`remove` never deletes files in Added [A] state from the
4699 :hg:`remove` never deletes files in Added [A] state from the
4690 working directory, not even if ``--force`` is specified.
4700 working directory, not even if ``--force`` is specified.
4691
4701
4692 Returns 0 on success, 1 if any warnings encountered.
4702 Returns 0 on success, 1 if any warnings encountered.
4693 """
4703 """
4694
4704
4695 opts = pycompat.byteskwargs(opts)
4705 opts = pycompat.byteskwargs(opts)
4696 after, force = opts.get('after'), opts.get('force')
4706 after, force = opts.get('after'), opts.get('force')
4697 dryrun = opts.get('dry_run')
4707 dryrun = opts.get('dry_run')
4698 if not pats and not after:
4708 if not pats and not after:
4699 raise error.Abort(_('no files specified'))
4709 raise error.Abort(_('no files specified'))
4700
4710
4701 m = scmutil.match(repo[None], pats, opts)
4711 m = scmutil.match(repo[None], pats, opts)
4702 subrepos = opts.get('subrepos')
4712 subrepos = opts.get('subrepos')
4703 return cmdutil.remove(ui, repo, m, "", after, force, subrepos,
4713 return cmdutil.remove(ui, repo, m, "", after, force, subrepos,
4704 dryrun=dryrun)
4714 dryrun=dryrun)
4705
4715
4706 @command('rename|move|mv',
4716 @command('rename|move|mv',
4707 [('A', 'after', None, _('record a rename that has already occurred')),
4717 [('A', 'after', None, _('record a rename that has already occurred')),
4708 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4718 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4709 ] + walkopts + dryrunopts,
4719 ] + walkopts + dryrunopts,
4710 _('[OPTION]... SOURCE... DEST'),
4720 _('[OPTION]... SOURCE... DEST'),
4711 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
4721 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
4712 def rename(ui, repo, *pats, **opts):
4722 def rename(ui, repo, *pats, **opts):
4713 """rename files; equivalent of copy + remove
4723 """rename files; equivalent of copy + remove
4714
4724
4715 Mark dest as copies of sources; mark sources for deletion. If dest
4725 Mark dest as copies of sources; mark sources for deletion. If dest
4716 is a directory, copies are put in that directory. If dest is a
4726 is a directory, copies are put in that directory. If dest is a
4717 file, there can only be one source.
4727 file, there can only be one source.
4718
4728
4719 By default, this command copies the contents of files as they
4729 By default, this command copies the contents of files as they
4720 exist in the working directory. If invoked with -A/--after, the
4730 exist in the working directory. If invoked with -A/--after, the
4721 operation is recorded, but no copying is performed.
4731 operation is recorded, but no copying is performed.
4722
4732
4723 This command takes effect at the next commit. To undo a rename
4733 This command takes effect at the next commit. To undo a rename
4724 before that, see :hg:`revert`.
4734 before that, see :hg:`revert`.
4725
4735
4726 Returns 0 on success, 1 if errors are encountered.
4736 Returns 0 on success, 1 if errors are encountered.
4727 """
4737 """
4728 opts = pycompat.byteskwargs(opts)
4738 opts = pycompat.byteskwargs(opts)
4729 with repo.wlock(False):
4739 with repo.wlock(False):
4730 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4740 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4731
4741
4732 @command('resolve',
4742 @command('resolve',
4733 [('a', 'all', None, _('select all unresolved files')),
4743 [('a', 'all', None, _('select all unresolved files')),
4734 ('l', 'list', None, _('list state of files needing merge')),
4744 ('l', 'list', None, _('list state of files needing merge')),
4735 ('m', 'mark', None, _('mark files as resolved')),
4745 ('m', 'mark', None, _('mark files as resolved')),
4736 ('u', 'unmark', None, _('mark files as unresolved')),
4746 ('u', 'unmark', None, _('mark files as unresolved')),
4737 ('n', 'no-status', None, _('hide status prefix')),
4747 ('n', 'no-status', None, _('hide status prefix')),
4738 ('', 're-merge', None, _('re-merge files'))]
4748 ('', 're-merge', None, _('re-merge files'))]
4739 + mergetoolopts + walkopts + formatteropts,
4749 + mergetoolopts + walkopts + formatteropts,
4740 _('[OPTION]... [FILE]...'),
4750 _('[OPTION]... [FILE]...'),
4741 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4751 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
4742 inferrepo=True)
4752 inferrepo=True)
4743 def resolve(ui, repo, *pats, **opts):
4753 def resolve(ui, repo, *pats, **opts):
4744 """redo merges or set/view the merge status of files
4754 """redo merges or set/view the merge status of files
4745
4755
4746 Merges with unresolved conflicts are often the result of
4756 Merges with unresolved conflicts are often the result of
4747 non-interactive merging using the ``internal:merge`` configuration
4757 non-interactive merging using the ``internal:merge`` configuration
4748 setting, or a command-line merge tool like ``diff3``. The resolve
4758 setting, or a command-line merge tool like ``diff3``. The resolve
4749 command is used to manage the files involved in a merge, after
4759 command is used to manage the files involved in a merge, after
4750 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4760 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4751 working directory must have two parents). See :hg:`help
4761 working directory must have two parents). See :hg:`help
4752 merge-tools` for information on configuring merge tools.
4762 merge-tools` for information on configuring merge tools.
4753
4763
4754 The resolve command can be used in the following ways:
4764 The resolve command can be used in the following ways:
4755
4765
4756 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
4766 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
4757 the specified files, discarding any previous merge attempts. Re-merging
4767 the specified files, discarding any previous merge attempts. Re-merging
4758 is not performed for files already marked as resolved. Use ``--all/-a``
4768 is not performed for files already marked as resolved. Use ``--all/-a``
4759 to select all unresolved files. ``--tool`` can be used to specify
4769 to select all unresolved files. ``--tool`` can be used to specify
4760 the merge tool used for the given files. It overrides the HGMERGE
4770 the merge tool used for the given files. It overrides the HGMERGE
4761 environment variable and your configuration files. Previous file
4771 environment variable and your configuration files. Previous file
4762 contents are saved with a ``.orig`` suffix.
4772 contents are saved with a ``.orig`` suffix.
4763
4773
4764 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4774 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4765 (e.g. after having manually fixed-up the files). The default is
4775 (e.g. after having manually fixed-up the files). The default is
4766 to mark all unresolved files.
4776 to mark all unresolved files.
4767
4777
4768 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4778 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4769 default is to mark all resolved files.
4779 default is to mark all resolved files.
4770
4780
4771 - :hg:`resolve -l`: list files which had or still have conflicts.
4781 - :hg:`resolve -l`: list files which had or still have conflicts.
4772 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4782 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4773 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4783 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4774 the list. See :hg:`help filesets` for details.
4784 the list. See :hg:`help filesets` for details.
4775
4785
4776 .. note::
4786 .. note::
4777
4787
4778 Mercurial will not let you commit files with unresolved merge
4788 Mercurial will not let you commit files with unresolved merge
4779 conflicts. You must use :hg:`resolve -m ...` before you can
4789 conflicts. You must use :hg:`resolve -m ...` before you can
4780 commit after a conflicting merge.
4790 commit after a conflicting merge.
4781
4791
4782 .. container:: verbose
4792 .. container:: verbose
4783
4793
4784 Template:
4794 Template:
4785
4795
4786 The following keywords are supported in addition to the common template
4796 The following keywords are supported in addition to the common template
4787 keywords and functions. See also :hg:`help templates`.
4797 keywords and functions. See also :hg:`help templates`.
4788
4798
4789 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
4799 :mergestatus: String. Character denoting merge conflicts, ``U`` or ``R``.
4790 :path: String. Repository-absolute path of the file.
4800 :path: String. Repository-absolute path of the file.
4791
4801
4792 Returns 0 on success, 1 if any files fail a resolve attempt.
4802 Returns 0 on success, 1 if any files fail a resolve attempt.
4793 """
4803 """
4794
4804
4795 opts = pycompat.byteskwargs(opts)
4805 opts = pycompat.byteskwargs(opts)
4796 confirm = ui.configbool('commands', 'resolve.confirm')
4806 confirm = ui.configbool('commands', 'resolve.confirm')
4797 flaglist = 'all mark unmark list no_status re_merge'.split()
4807 flaglist = 'all mark unmark list no_status re_merge'.split()
4798 all, mark, unmark, show, nostatus, remerge = \
4808 all, mark, unmark, show, nostatus, remerge = \
4799 [opts.get(o) for o in flaglist]
4809 [opts.get(o) for o in flaglist]
4800
4810
4801 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
4811 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
4802 if actioncount > 1:
4812 if actioncount > 1:
4803 raise error.Abort(_("too many actions specified"))
4813 raise error.Abort(_("too many actions specified"))
4804 elif (actioncount == 0
4814 elif (actioncount == 0
4805 and ui.configbool('commands', 'resolve.explicit-re-merge')):
4815 and ui.configbool('commands', 'resolve.explicit-re-merge')):
4806 hint = _('use --mark, --unmark, --list or --re-merge')
4816 hint = _('use --mark, --unmark, --list or --re-merge')
4807 raise error.Abort(_('no action specified'), hint=hint)
4817 raise error.Abort(_('no action specified'), hint=hint)
4808 if pats and all:
4818 if pats and all:
4809 raise error.Abort(_("can't specify --all and patterns"))
4819 raise error.Abort(_("can't specify --all and patterns"))
4810 if not (all or pats or show or mark or unmark):
4820 if not (all or pats or show or mark or unmark):
4811 raise error.Abort(_('no files or directories specified'),
4821 raise error.Abort(_('no files or directories specified'),
4812 hint=('use --all to re-merge all unresolved files'))
4822 hint=('use --all to re-merge all unresolved files'))
4813
4823
4814 if confirm:
4824 if confirm:
4815 if all:
4825 if all:
4816 if ui.promptchoice(_(b're-merge all unresolved files (yn)?'
4826 if ui.promptchoice(_(b're-merge all unresolved files (yn)?'
4817 b'$$ &Yes $$ &No')):
4827 b'$$ &Yes $$ &No')):
4818 raise error.Abort(_('user quit'))
4828 raise error.Abort(_('user quit'))
4819 if mark and not pats:
4829 if mark and not pats:
4820 if ui.promptchoice(_(b'mark all unresolved files as resolved (yn)?'
4830 if ui.promptchoice(_(b'mark all unresolved files as resolved (yn)?'
4821 b'$$ &Yes $$ &No')):
4831 b'$$ &Yes $$ &No')):
4822 raise error.Abort(_('user quit'))
4832 raise error.Abort(_('user quit'))
4823 if unmark and not pats:
4833 if unmark and not pats:
4824 if ui.promptchoice(_(b'mark all resolved files as unresolved (yn)?'
4834 if ui.promptchoice(_(b'mark all resolved files as unresolved (yn)?'
4825 b'$$ &Yes $$ &No')):
4835 b'$$ &Yes $$ &No')):
4826 raise error.Abort(_('user quit'))
4836 raise error.Abort(_('user quit'))
4827
4837
4828 if show:
4838 if show:
4829 ui.pager('resolve')
4839 ui.pager('resolve')
4830 fm = ui.formatter('resolve', opts)
4840 fm = ui.formatter('resolve', opts)
4831 ms = mergemod.mergestate.read(repo)
4841 ms = mergemod.mergestate.read(repo)
4832 wctx = repo[None]
4842 wctx = repo[None]
4833 m = scmutil.match(wctx, pats, opts)
4843 m = scmutil.match(wctx, pats, opts)
4834
4844
4835 # Labels and keys based on merge state. Unresolved path conflicts show
4845 # Labels and keys based on merge state. Unresolved path conflicts show
4836 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4846 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4837 # resolved conflicts.
4847 # resolved conflicts.
4838 mergestateinfo = {
4848 mergestateinfo = {
4839 mergemod.MERGE_RECORD_UNRESOLVED: ('resolve.unresolved', 'U'),
4849 mergemod.MERGE_RECORD_UNRESOLVED: ('resolve.unresolved', 'U'),
4840 mergemod.MERGE_RECORD_RESOLVED: ('resolve.resolved', 'R'),
4850 mergemod.MERGE_RECORD_RESOLVED: ('resolve.resolved', 'R'),
4841 mergemod.MERGE_RECORD_UNRESOLVED_PATH: ('resolve.unresolved', 'P'),
4851 mergemod.MERGE_RECORD_UNRESOLVED_PATH: ('resolve.unresolved', 'P'),
4842 mergemod.MERGE_RECORD_RESOLVED_PATH: ('resolve.resolved', 'R'),
4852 mergemod.MERGE_RECORD_RESOLVED_PATH: ('resolve.resolved', 'R'),
4843 mergemod.MERGE_RECORD_DRIVER_RESOLVED: ('resolve.driverresolved',
4853 mergemod.MERGE_RECORD_DRIVER_RESOLVED: ('resolve.driverresolved',
4844 'D'),
4854 'D'),
4845 }
4855 }
4846
4856
4847 for f in ms:
4857 for f in ms:
4848 if not m(f):
4858 if not m(f):
4849 continue
4859 continue
4850
4860
4851 label, key = mergestateinfo[ms[f]]
4861 label, key = mergestateinfo[ms[f]]
4852 fm.startitem()
4862 fm.startitem()
4853 fm.context(ctx=wctx)
4863 fm.context(ctx=wctx)
4854 fm.condwrite(not nostatus, 'mergestatus', '%s ', key, label=label)
4864 fm.condwrite(not nostatus, 'mergestatus', '%s ', key, label=label)
4855 fm.write('path', '%s\n', f, label=label)
4865 fm.write('path', '%s\n', f, label=label)
4856 fm.end()
4866 fm.end()
4857 return 0
4867 return 0
4858
4868
4859 with repo.wlock():
4869 with repo.wlock():
4860 ms = mergemod.mergestate.read(repo)
4870 ms = mergemod.mergestate.read(repo)
4861
4871
4862 if not (ms.active() or repo.dirstate.p2() != nullid):
4872 if not (ms.active() or repo.dirstate.p2() != nullid):
4863 raise error.Abort(
4873 raise error.Abort(
4864 _('resolve command not applicable when not merging'))
4874 _('resolve command not applicable when not merging'))
4865
4875
4866 wctx = repo[None]
4876 wctx = repo[None]
4867
4877
4868 if (ms.mergedriver
4878 if (ms.mergedriver
4869 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED):
4879 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED):
4870 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4880 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4871 ms.commit()
4881 ms.commit()
4872 # allow mark and unmark to go through
4882 # allow mark and unmark to go through
4873 if not mark and not unmark and not proceed:
4883 if not mark and not unmark and not proceed:
4874 return 1
4884 return 1
4875
4885
4876 m = scmutil.match(wctx, pats, opts)
4886 m = scmutil.match(wctx, pats, opts)
4877 ret = 0
4887 ret = 0
4878 didwork = False
4888 didwork = False
4879 runconclude = False
4889 runconclude = False
4880
4890
4881 tocomplete = []
4891 tocomplete = []
4882 hasconflictmarkers = []
4892 hasconflictmarkers = []
4883 if mark:
4893 if mark:
4884 markcheck = ui.config('commands', 'resolve.mark-check')
4894 markcheck = ui.config('commands', 'resolve.mark-check')
4885 if markcheck not in ['warn', 'abort']:
4895 if markcheck not in ['warn', 'abort']:
4886 # Treat all invalid / unrecognized values as 'none'.
4896 # Treat all invalid / unrecognized values as 'none'.
4887 markcheck = False
4897 markcheck = False
4888 for f in ms:
4898 for f in ms:
4889 if not m(f):
4899 if not m(f):
4890 continue
4900 continue
4891
4901
4892 didwork = True
4902 didwork = True
4893
4903
4894 # don't let driver-resolved files be marked, and run the conclude
4904 # don't let driver-resolved files be marked, and run the conclude
4895 # step if asked to resolve
4905 # step if asked to resolve
4896 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
4906 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
4897 exact = m.exact(f)
4907 exact = m.exact(f)
4898 if mark:
4908 if mark:
4899 if exact:
4909 if exact:
4900 ui.warn(_('not marking %s as it is driver-resolved\n')
4910 ui.warn(_('not marking %s as it is driver-resolved\n')
4901 % f)
4911 % f)
4902 elif unmark:
4912 elif unmark:
4903 if exact:
4913 if exact:
4904 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4914 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4905 % f)
4915 % f)
4906 else:
4916 else:
4907 runconclude = True
4917 runconclude = True
4908 continue
4918 continue
4909
4919
4910 # path conflicts must be resolved manually
4920 # path conflicts must be resolved manually
4911 if ms[f] in (mergemod.MERGE_RECORD_UNRESOLVED_PATH,
4921 if ms[f] in (mergemod.MERGE_RECORD_UNRESOLVED_PATH,
4912 mergemod.MERGE_RECORD_RESOLVED_PATH):
4922 mergemod.MERGE_RECORD_RESOLVED_PATH):
4913 if mark:
4923 if mark:
4914 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
4924 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
4915 elif unmark:
4925 elif unmark:
4916 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
4926 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
4917 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
4927 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
4918 ui.warn(_('%s: path conflict must be resolved manually\n')
4928 ui.warn(_('%s: path conflict must be resolved manually\n')
4919 % f)
4929 % f)
4920 continue
4930 continue
4921
4931
4922 if mark:
4932 if mark:
4923 if markcheck:
4933 if markcheck:
4924 with repo.wvfs(f) as fobj:
4934 with repo.wvfs(f) as fobj:
4925 fdata = fobj.read()
4935 fdata = fobj.read()
4926 if filemerge.hasconflictmarkers(fdata) and \
4936 if filemerge.hasconflictmarkers(fdata) and \
4927 ms[f] != mergemod.MERGE_RECORD_RESOLVED:
4937 ms[f] != mergemod.MERGE_RECORD_RESOLVED:
4928 hasconflictmarkers.append(f)
4938 hasconflictmarkers.append(f)
4929 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
4939 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
4930 elif unmark:
4940 elif unmark:
4931 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
4941 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
4932 else:
4942 else:
4933 # backup pre-resolve (merge uses .orig for its own purposes)
4943 # backup pre-resolve (merge uses .orig for its own purposes)
4934 a = repo.wjoin(f)
4944 a = repo.wjoin(f)
4935 try:
4945 try:
4936 util.copyfile(a, a + ".resolve")
4946 util.copyfile(a, a + ".resolve")
4937 except (IOError, OSError) as inst:
4947 except (IOError, OSError) as inst:
4938 if inst.errno != errno.ENOENT:
4948 if inst.errno != errno.ENOENT:
4939 raise
4949 raise
4940
4950
4941 try:
4951 try:
4942 # preresolve file
4952 # preresolve file
4943 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4953 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4944 with ui.configoverride(overrides, 'resolve'):
4954 with ui.configoverride(overrides, 'resolve'):
4945 complete, r = ms.preresolve(f, wctx)
4955 complete, r = ms.preresolve(f, wctx)
4946 if not complete:
4956 if not complete:
4947 tocomplete.append(f)
4957 tocomplete.append(f)
4948 elif r:
4958 elif r:
4949 ret = 1
4959 ret = 1
4950 finally:
4960 finally:
4951 ms.commit()
4961 ms.commit()
4952
4962
4953 # replace filemerge's .orig file with our resolve file, but only
4963 # replace filemerge's .orig file with our resolve file, but only
4954 # for merges that are complete
4964 # for merges that are complete
4955 if complete:
4965 if complete:
4956 try:
4966 try:
4957 util.rename(a + ".resolve",
4967 util.rename(a + ".resolve",
4958 scmutil.origpath(ui, repo, a))
4968 scmutil.origpath(ui, repo, a))
4959 except OSError as inst:
4969 except OSError as inst:
4960 if inst.errno != errno.ENOENT:
4970 if inst.errno != errno.ENOENT:
4961 raise
4971 raise
4962
4972
4963 if hasconflictmarkers:
4973 if hasconflictmarkers:
4964 ui.warn(_('warning: the following files still have conflict '
4974 ui.warn(_('warning: the following files still have conflict '
4965 'markers:\n ') + '\n '.join(hasconflictmarkers) + '\n')
4975 'markers:\n ') + '\n '.join(hasconflictmarkers) + '\n')
4966 if markcheck == 'abort' and not all and not pats:
4976 if markcheck == 'abort' and not all and not pats:
4967 raise error.Abort(_('conflict markers detected'),
4977 raise error.Abort(_('conflict markers detected'),
4968 hint=_('use --all to mark anyway'))
4978 hint=_('use --all to mark anyway'))
4969
4979
4970 for f in tocomplete:
4980 for f in tocomplete:
4971 try:
4981 try:
4972 # resolve file
4982 # resolve file
4973 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4983 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4974 with ui.configoverride(overrides, 'resolve'):
4984 with ui.configoverride(overrides, 'resolve'):
4975 r = ms.resolve(f, wctx)
4985 r = ms.resolve(f, wctx)
4976 if r:
4986 if r:
4977 ret = 1
4987 ret = 1
4978 finally:
4988 finally:
4979 ms.commit()
4989 ms.commit()
4980
4990
4981 # replace filemerge's .orig file with our resolve file
4991 # replace filemerge's .orig file with our resolve file
4982 a = repo.wjoin(f)
4992 a = repo.wjoin(f)
4983 try:
4993 try:
4984 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4994 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4985 except OSError as inst:
4995 except OSError as inst:
4986 if inst.errno != errno.ENOENT:
4996 if inst.errno != errno.ENOENT:
4987 raise
4997 raise
4988
4998
4989 ms.commit()
4999 ms.commit()
4990 ms.recordactions()
5000 ms.recordactions()
4991
5001
4992 if not didwork and pats:
5002 if not didwork and pats:
4993 hint = None
5003 hint = None
4994 if not any([p for p in pats if p.find(':') >= 0]):
5004 if not any([p for p in pats if p.find(':') >= 0]):
4995 pats = ['path:%s' % p for p in pats]
5005 pats = ['path:%s' % p for p in pats]
4996 m = scmutil.match(wctx, pats, opts)
5006 m = scmutil.match(wctx, pats, opts)
4997 for f in ms:
5007 for f in ms:
4998 if not m(f):
5008 if not m(f):
4999 continue
5009 continue
5000 def flag(o):
5010 def flag(o):
5001 if o == 're_merge':
5011 if o == 're_merge':
5002 return '--re-merge '
5012 return '--re-merge '
5003 return '-%s ' % o[0:1]
5013 return '-%s ' % o[0:1]
5004 flags = ''.join([flag(o) for o in flaglist if opts.get(o)])
5014 flags = ''.join([flag(o) for o in flaglist if opts.get(o)])
5005 hint = _("(try: hg resolve %s%s)\n") % (
5015 hint = _("(try: hg resolve %s%s)\n") % (
5006 flags,
5016 flags,
5007 ' '.join(pats))
5017 ' '.join(pats))
5008 break
5018 break
5009 ui.warn(_("arguments do not match paths that need resolving\n"))
5019 ui.warn(_("arguments do not match paths that need resolving\n"))
5010 if hint:
5020 if hint:
5011 ui.warn(hint)
5021 ui.warn(hint)
5012 elif ms.mergedriver and ms.mdstate() != 's':
5022 elif ms.mergedriver and ms.mdstate() != 's':
5013 # run conclude step when either a driver-resolved file is requested
5023 # run conclude step when either a driver-resolved file is requested
5014 # or there are no driver-resolved files
5024 # or there are no driver-resolved files
5015 # we can't use 'ret' to determine whether any files are unresolved
5025 # we can't use 'ret' to determine whether any files are unresolved
5016 # because we might not have tried to resolve some
5026 # because we might not have tried to resolve some
5017 if ((runconclude or not list(ms.driverresolved()))
5027 if ((runconclude or not list(ms.driverresolved()))
5018 and not list(ms.unresolved())):
5028 and not list(ms.unresolved())):
5019 proceed = mergemod.driverconclude(repo, ms, wctx)
5029 proceed = mergemod.driverconclude(repo, ms, wctx)
5020 ms.commit()
5030 ms.commit()
5021 if not proceed:
5031 if not proceed:
5022 return 1
5032 return 1
5023
5033
5024 # Nudge users into finishing an unfinished operation
5034 # Nudge users into finishing an unfinished operation
5025 unresolvedf = list(ms.unresolved())
5035 unresolvedf = list(ms.unresolved())
5026 driverresolvedf = list(ms.driverresolved())
5036 driverresolvedf = list(ms.driverresolved())
5027 if not unresolvedf and not driverresolvedf:
5037 if not unresolvedf and not driverresolvedf:
5028 ui.status(_('(no more unresolved files)\n'))
5038 ui.status(_('(no more unresolved files)\n'))
5029 cmdutil.checkafterresolved(repo)
5039 cmdutil.checkafterresolved(repo)
5030 elif not unresolvedf:
5040 elif not unresolvedf:
5031 ui.status(_('(no more unresolved files -- '
5041 ui.status(_('(no more unresolved files -- '
5032 'run "hg resolve --all" to conclude)\n'))
5042 'run "hg resolve --all" to conclude)\n'))
5033
5043
5034 return ret
5044 return ret
5035
5045
5036 @command('revert',
5046 @command('revert',
5037 [('a', 'all', None, _('revert all changes when no arguments given')),
5047 [('a', 'all', None, _('revert all changes when no arguments given')),
5038 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5048 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5039 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5049 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5040 ('C', 'no-backup', None, _('do not save backup copies of files')),
5050 ('C', 'no-backup', None, _('do not save backup copies of files')),
5041 ('i', 'interactive', None, _('interactively select the changes')),
5051 ('i', 'interactive', None, _('interactively select the changes')),
5042 ] + walkopts + dryrunopts,
5052 ] + walkopts + dryrunopts,
5043 _('[OPTION]... [-r REV] [NAME]...'),
5053 _('[OPTION]... [-r REV] [NAME]...'),
5044 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5054 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5045 def revert(ui, repo, *pats, **opts):
5055 def revert(ui, repo, *pats, **opts):
5046 """restore files to their checkout state
5056 """restore files to their checkout state
5047
5057
5048 .. note::
5058 .. note::
5049
5059
5050 To check out earlier revisions, you should use :hg:`update REV`.
5060 To check out earlier revisions, you should use :hg:`update REV`.
5051 To cancel an uncommitted merge (and lose your changes),
5061 To cancel an uncommitted merge (and lose your changes),
5052 use :hg:`merge --abort`.
5062 use :hg:`merge --abort`.
5053
5063
5054 With no revision specified, revert the specified files or directories
5064 With no revision specified, revert the specified files or directories
5055 to the contents they had in the parent of the working directory.
5065 to the contents they had in the parent of the working directory.
5056 This restores the contents of files to an unmodified
5066 This restores the contents of files to an unmodified
5057 state and unschedules adds, removes, copies, and renames. If the
5067 state and unschedules adds, removes, copies, and renames. If the
5058 working directory has two parents, you must explicitly specify a
5068 working directory has two parents, you must explicitly specify a
5059 revision.
5069 revision.
5060
5070
5061 Using the -r/--rev or -d/--date options, revert the given files or
5071 Using the -r/--rev or -d/--date options, revert the given files or
5062 directories to their states as of a specific revision. Because
5072 directories to their states as of a specific revision. Because
5063 revert does not change the working directory parents, this will
5073 revert does not change the working directory parents, this will
5064 cause these files to appear modified. This can be helpful to "back
5074 cause these files to appear modified. This can be helpful to "back
5065 out" some or all of an earlier change. See :hg:`backout` for a
5075 out" some or all of an earlier change. See :hg:`backout` for a
5066 related method.
5076 related method.
5067
5077
5068 Modified files are saved with a .orig suffix before reverting.
5078 Modified files are saved with a .orig suffix before reverting.
5069 To disable these backups, use --no-backup. It is possible to store
5079 To disable these backups, use --no-backup. It is possible to store
5070 the backup files in a custom directory relative to the root of the
5080 the backup files in a custom directory relative to the root of the
5071 repository by setting the ``ui.origbackuppath`` configuration
5081 repository by setting the ``ui.origbackuppath`` configuration
5072 option.
5082 option.
5073
5083
5074 See :hg:`help dates` for a list of formats valid for -d/--date.
5084 See :hg:`help dates` for a list of formats valid for -d/--date.
5075
5085
5076 See :hg:`help backout` for a way to reverse the effect of an
5086 See :hg:`help backout` for a way to reverse the effect of an
5077 earlier changeset.
5087 earlier changeset.
5078
5088
5079 Returns 0 on success.
5089 Returns 0 on success.
5080 """
5090 """
5081
5091
5082 opts = pycompat.byteskwargs(opts)
5092 opts = pycompat.byteskwargs(opts)
5083 if opts.get("date"):
5093 if opts.get("date"):
5084 if opts.get("rev"):
5094 if opts.get("rev"):
5085 raise error.Abort(_("you can't specify a revision and a date"))
5095 raise error.Abort(_("you can't specify a revision and a date"))
5086 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5096 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5087
5097
5088 parent, p2 = repo.dirstate.parents()
5098 parent, p2 = repo.dirstate.parents()
5089 if not opts.get('rev') and p2 != nullid:
5099 if not opts.get('rev') and p2 != nullid:
5090 # revert after merge is a trap for new users (issue2915)
5100 # revert after merge is a trap for new users (issue2915)
5091 raise error.Abort(_('uncommitted merge with no revision specified'),
5101 raise error.Abort(_('uncommitted merge with no revision specified'),
5092 hint=_("use 'hg update' or see 'hg help revert'"))
5102 hint=_("use 'hg update' or see 'hg help revert'"))
5093
5103
5094 rev = opts.get('rev')
5104 rev = opts.get('rev')
5095 if rev:
5105 if rev:
5096 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5106 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5097 ctx = scmutil.revsingle(repo, rev)
5107 ctx = scmutil.revsingle(repo, rev)
5098
5108
5099 if (not (pats or opts.get('include') or opts.get('exclude') or
5109 if (not (pats or opts.get('include') or opts.get('exclude') or
5100 opts.get('all') or opts.get('interactive'))):
5110 opts.get('all') or opts.get('interactive'))):
5101 msg = _("no files or directories specified")
5111 msg = _("no files or directories specified")
5102 if p2 != nullid:
5112 if p2 != nullid:
5103 hint = _("uncommitted merge, use --all to discard all changes,"
5113 hint = _("uncommitted merge, use --all to discard all changes,"
5104 " or 'hg update -C .' to abort the merge")
5114 " or 'hg update -C .' to abort the merge")
5105 raise error.Abort(msg, hint=hint)
5115 raise error.Abort(msg, hint=hint)
5106 dirty = any(repo.status())
5116 dirty = any(repo.status())
5107 node = ctx.node()
5117 node = ctx.node()
5108 if node != parent:
5118 if node != parent:
5109 if dirty:
5119 if dirty:
5110 hint = _("uncommitted changes, use --all to discard all"
5120 hint = _("uncommitted changes, use --all to discard all"
5111 " changes, or 'hg update %d' to update") % ctx.rev()
5121 " changes, or 'hg update %d' to update") % ctx.rev()
5112 else:
5122 else:
5113 hint = _("use --all to revert all files,"
5123 hint = _("use --all to revert all files,"
5114 " or 'hg update %d' to update") % ctx.rev()
5124 " or 'hg update %d' to update") % ctx.rev()
5115 elif dirty:
5125 elif dirty:
5116 hint = _("uncommitted changes, use --all to discard all changes")
5126 hint = _("uncommitted changes, use --all to discard all changes")
5117 else:
5127 else:
5118 hint = _("use --all to revert all files")
5128 hint = _("use --all to revert all files")
5119 raise error.Abort(msg, hint=hint)
5129 raise error.Abort(msg, hint=hint)
5120
5130
5121 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
5131 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
5122 **pycompat.strkwargs(opts))
5132 **pycompat.strkwargs(opts))
5123
5133
5124 @command(
5134 @command(
5125 'rollback',
5135 'rollback',
5126 dryrunopts + [('f', 'force', False, _('ignore safety measures'))],
5136 dryrunopts + [('f', 'force', False, _('ignore safety measures'))],
5127 helpcategory=command.CATEGORY_MAINTENANCE)
5137 helpcategory=command.CATEGORY_MAINTENANCE)
5128 def rollback(ui, repo, **opts):
5138 def rollback(ui, repo, **opts):
5129 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5139 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5130
5140
5131 Please use :hg:`commit --amend` instead of rollback to correct
5141 Please use :hg:`commit --amend` instead of rollback to correct
5132 mistakes in the last commit.
5142 mistakes in the last commit.
5133
5143
5134 This command should be used with care. There is only one level of
5144 This command should be used with care. There is only one level of
5135 rollback, and there is no way to undo a rollback. It will also
5145 rollback, and there is no way to undo a rollback. It will also
5136 restore the dirstate at the time of the last transaction, losing
5146 restore the dirstate at the time of the last transaction, losing
5137 any dirstate changes since that time. This command does not alter
5147 any dirstate changes since that time. This command does not alter
5138 the working directory.
5148 the working directory.
5139
5149
5140 Transactions are used to encapsulate the effects of all commands
5150 Transactions are used to encapsulate the effects of all commands
5141 that create new changesets or propagate existing changesets into a
5151 that create new changesets or propagate existing changesets into a
5142 repository.
5152 repository.
5143
5153
5144 .. container:: verbose
5154 .. container:: verbose
5145
5155
5146 For example, the following commands are transactional, and their
5156 For example, the following commands are transactional, and their
5147 effects can be rolled back:
5157 effects can be rolled back:
5148
5158
5149 - commit
5159 - commit
5150 - import
5160 - import
5151 - pull
5161 - pull
5152 - push (with this repository as the destination)
5162 - push (with this repository as the destination)
5153 - unbundle
5163 - unbundle
5154
5164
5155 To avoid permanent data loss, rollback will refuse to rollback a
5165 To avoid permanent data loss, rollback will refuse to rollback a
5156 commit transaction if it isn't checked out. Use --force to
5166 commit transaction if it isn't checked out. Use --force to
5157 override this protection.
5167 override this protection.
5158
5168
5159 The rollback command can be entirely disabled by setting the
5169 The rollback command can be entirely disabled by setting the
5160 ``ui.rollback`` configuration setting to false. If you're here
5170 ``ui.rollback`` configuration setting to false. If you're here
5161 because you want to use rollback and it's disabled, you can
5171 because you want to use rollback and it's disabled, you can
5162 re-enable the command by setting ``ui.rollback`` to true.
5172 re-enable the command by setting ``ui.rollback`` to true.
5163
5173
5164 This command is not intended for use on public repositories. Once
5174 This command is not intended for use on public repositories. Once
5165 changes are visible for pull by other users, rolling a transaction
5175 changes are visible for pull by other users, rolling a transaction
5166 back locally is ineffective (someone else may already have pulled
5176 back locally is ineffective (someone else may already have pulled
5167 the changes). Furthermore, a race is possible with readers of the
5177 the changes). Furthermore, a race is possible with readers of the
5168 repository; for example an in-progress pull from the repository
5178 repository; for example an in-progress pull from the repository
5169 may fail if a rollback is performed.
5179 may fail if a rollback is performed.
5170
5180
5171 Returns 0 on success, 1 if no rollback data is available.
5181 Returns 0 on success, 1 if no rollback data is available.
5172 """
5182 """
5173 if not ui.configbool('ui', 'rollback'):
5183 if not ui.configbool('ui', 'rollback'):
5174 raise error.Abort(_('rollback is disabled because it is unsafe'),
5184 raise error.Abort(_('rollback is disabled because it is unsafe'),
5175 hint=('see `hg help -v rollback` for information'))
5185 hint=('see `hg help -v rollback` for information'))
5176 return repo.rollback(dryrun=opts.get(r'dry_run'),
5186 return repo.rollback(dryrun=opts.get(r'dry_run'),
5177 force=opts.get(r'force'))
5187 force=opts.get(r'force'))
5178
5188
5179 @command(
5189 @command(
5180 'root', [], intents={INTENT_READONLY},
5190 'root', [], intents={INTENT_READONLY},
5181 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5191 helpcategory=command.CATEGORY_WORKING_DIRECTORY)
5182 def root(ui, repo):
5192 def root(ui, repo):
5183 """print the root (top) of the current working directory
5193 """print the root (top) of the current working directory
5184
5194
5185 Print the root directory of the current repository.
5195 Print the root directory of the current repository.
5186
5196
5187 Returns 0 on success.
5197 Returns 0 on success.
5188 """
5198 """
5189 ui.write(repo.root + "\n")
5199 ui.write(repo.root + "\n")
5190
5200
5191 @command('serve',
5201 @command('serve',
5192 [('A', 'accesslog', '', _('name of access log file to write to'),
5202 [('A', 'accesslog', '', _('name of access log file to write to'),
5193 _('FILE')),
5203 _('FILE')),
5194 ('d', 'daemon', None, _('run server in background')),
5204 ('d', 'daemon', None, _('run server in background')),
5195 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
5205 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
5196 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5206 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5197 # use string type, then we can check if something was passed
5207 # use string type, then we can check if something was passed
5198 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5208 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5199 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5209 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5200 _('ADDR')),
5210 _('ADDR')),
5201 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5211 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5202 _('PREFIX')),
5212 _('PREFIX')),
5203 ('n', 'name', '',
5213 ('n', 'name', '',
5204 _('name to show in web pages (default: working directory)'), _('NAME')),
5214 _('name to show in web pages (default: working directory)'), _('NAME')),
5205 ('', 'web-conf', '',
5215 ('', 'web-conf', '',
5206 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
5216 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
5207 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5217 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5208 _('FILE')),
5218 _('FILE')),
5209 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5219 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5210 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
5220 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
5211 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
5221 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
5212 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5222 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5213 ('', 'style', '', _('template style to use'), _('STYLE')),
5223 ('', 'style', '', _('template style to use'), _('STYLE')),
5214 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5224 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5215 ('', 'certificate', '', _('SSL certificate file'), _('FILE')),
5225 ('', 'certificate', '', _('SSL certificate file'), _('FILE')),
5216 ('', 'print-url', None, _('start and print only the URL'))]
5226 ('', 'print-url', None, _('start and print only the URL'))]
5217 + subrepoopts,
5227 + subrepoopts,
5218 _('[OPTION]...'),
5228 _('[OPTION]...'),
5219 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5229 helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
5220 helpbasic=True, optionalrepo=True)
5230 helpbasic=True, optionalrepo=True)
5221 def serve(ui, repo, **opts):
5231 def serve(ui, repo, **opts):
5222 """start stand-alone webserver
5232 """start stand-alone webserver
5223
5233
5224 Start a local HTTP repository browser and pull server. You can use
5234 Start a local HTTP repository browser and pull server. You can use
5225 this for ad-hoc sharing and browsing of repositories. It is
5235 this for ad-hoc sharing and browsing of repositories. It is
5226 recommended to use a real web server to serve a repository for
5236 recommended to use a real web server to serve a repository for
5227 longer periods of time.
5237 longer periods of time.
5228
5238
5229 Please note that the server does not implement access control.
5239 Please note that the server does not implement access control.
5230 This means that, by default, anybody can read from the server and
5240 This means that, by default, anybody can read from the server and
5231 nobody can write to it by default. Set the ``web.allow-push``
5241 nobody can write to it by default. Set the ``web.allow-push``
5232 option to ``*`` to allow everybody to push to the server. You
5242 option to ``*`` to allow everybody to push to the server. You
5233 should use a real web server if you need to authenticate users.
5243 should use a real web server if you need to authenticate users.
5234
5244
5235 By default, the server logs accesses to stdout and errors to
5245 By default, the server logs accesses to stdout and errors to
5236 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5246 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5237 files.
5247 files.
5238
5248
5239 To have the server choose a free port number to listen on, specify
5249 To have the server choose a free port number to listen on, specify
5240 a port number of 0; in this case, the server will print the port
5250 a port number of 0; in this case, the server will print the port
5241 number it uses.
5251 number it uses.
5242
5252
5243 Returns 0 on success.
5253 Returns 0 on success.
5244 """
5254 """
5245
5255
5246 opts = pycompat.byteskwargs(opts)
5256 opts = pycompat.byteskwargs(opts)
5247 if opts["stdio"] and opts["cmdserver"]:
5257 if opts["stdio"] and opts["cmdserver"]:
5248 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5258 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5249 if opts["print_url"] and ui.verbose:
5259 if opts["print_url"] and ui.verbose:
5250 raise error.Abort(_("cannot use --print-url with --verbose"))
5260 raise error.Abort(_("cannot use --print-url with --verbose"))
5251
5261
5252 if opts["stdio"]:
5262 if opts["stdio"]:
5253 if repo is None:
5263 if repo is None:
5254 raise error.RepoError(_("there is no Mercurial repository here"
5264 raise error.RepoError(_("there is no Mercurial repository here"
5255 " (.hg not found)"))
5265 " (.hg not found)"))
5256 s = wireprotoserver.sshserver(ui, repo)
5266 s = wireprotoserver.sshserver(ui, repo)
5257 s.serve_forever()
5267 s.serve_forever()
5258
5268
5259 service = server.createservice(ui, repo, opts)
5269 service = server.createservice(ui, repo, opts)
5260 return server.runservice(opts, initfn=service.init, runfn=service.run)
5270 return server.runservice(opts, initfn=service.init, runfn=service.run)
5261
5271
5262 _NOTTERSE = 'nothing'
5272 _NOTTERSE = 'nothing'
5263
5273
5264 @command('status|st',
5274 @command('status|st',
5265 [('A', 'all', None, _('show status of all files')),
5275 [('A', 'all', None, _('show status of all files')),
5266 ('m', 'modified', None, _('show only modified files')),
5276 ('m', 'modified', None, _('show only modified files')),
5267 ('a', 'added', None, _('show only added files')),
5277 ('a', 'added', None, _('show only added files')),
5268 ('r', 'removed', None, _('show only removed files')),
5278 ('r', 'removed', None, _('show only removed files')),
5269 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5279 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5270 ('c', 'clean', None, _('show only files without changes')),
5280 ('c', 'clean', None, _('show only files without changes')),
5271 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5281 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5272 ('i', 'ignored', None, _('show only ignored files')),
5282 ('i', 'ignored', None, _('show only ignored files')),
5273 ('n', 'no-status', None, _('hide status prefix')),
5283 ('n', 'no-status', None, _('hide status prefix')),
5274 ('t', 'terse', _NOTTERSE, _('show the terse output (EXPERIMENTAL)')),
5284 ('t', 'terse', _NOTTERSE, _('show the terse output (EXPERIMENTAL)')),
5275 ('C', 'copies', None, _('show source of copied files')),
5285 ('C', 'copies', None, _('show source of copied files')),
5276 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5286 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5277 ('', 'rev', [], _('show difference from revision'), _('REV')),
5287 ('', 'rev', [], _('show difference from revision'), _('REV')),
5278 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5288 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5279 ] + walkopts + subrepoopts + formatteropts,
5289 ] + walkopts + subrepoopts + formatteropts,
5280 _('[OPTION]... [FILE]...'),
5290 _('[OPTION]... [FILE]...'),
5281 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5291 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5282 helpbasic=True, inferrepo=True,
5292 helpbasic=True, inferrepo=True,
5283 intents={INTENT_READONLY})
5293 intents={INTENT_READONLY})
5284 def status(ui, repo, *pats, **opts):
5294 def status(ui, repo, *pats, **opts):
5285 """show changed files in the working directory
5295 """show changed files in the working directory
5286
5296
5287 Show status of files in the repository. If names are given, only
5297 Show status of files in the repository. If names are given, only
5288 files that match are shown. Files that are clean or ignored or
5298 files that match are shown. Files that are clean or ignored or
5289 the source of a copy/move operation, are not listed unless
5299 the source of a copy/move operation, are not listed unless
5290 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5300 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5291 Unless options described with "show only ..." are given, the
5301 Unless options described with "show only ..." are given, the
5292 options -mardu are used.
5302 options -mardu are used.
5293
5303
5294 Option -q/--quiet hides untracked (unknown and ignored) files
5304 Option -q/--quiet hides untracked (unknown and ignored) files
5295 unless explicitly requested with -u/--unknown or -i/--ignored.
5305 unless explicitly requested with -u/--unknown or -i/--ignored.
5296
5306
5297 .. note::
5307 .. note::
5298
5308
5299 :hg:`status` may appear to disagree with diff if permissions have
5309 :hg:`status` may appear to disagree with diff if permissions have
5300 changed or a merge has occurred. The standard diff format does
5310 changed or a merge has occurred. The standard diff format does
5301 not report permission changes and diff only reports changes
5311 not report permission changes and diff only reports changes
5302 relative to one merge parent.
5312 relative to one merge parent.
5303
5313
5304 If one revision is given, it is used as the base revision.
5314 If one revision is given, it is used as the base revision.
5305 If two revisions are given, the differences between them are
5315 If two revisions are given, the differences between them are
5306 shown. The --change option can also be used as a shortcut to list
5316 shown. The --change option can also be used as a shortcut to list
5307 the changed files of a revision from its first parent.
5317 the changed files of a revision from its first parent.
5308
5318
5309 The codes used to show the status of files are::
5319 The codes used to show the status of files are::
5310
5320
5311 M = modified
5321 M = modified
5312 A = added
5322 A = added
5313 R = removed
5323 R = removed
5314 C = clean
5324 C = clean
5315 ! = missing (deleted by non-hg command, but still tracked)
5325 ! = missing (deleted by non-hg command, but still tracked)
5316 ? = not tracked
5326 ? = not tracked
5317 I = ignored
5327 I = ignored
5318 = origin of the previous file (with --copies)
5328 = origin of the previous file (with --copies)
5319
5329
5320 .. container:: verbose
5330 .. container:: verbose
5321
5331
5322 The -t/--terse option abbreviates the output by showing only the directory
5332 The -t/--terse option abbreviates the output by showing only the directory
5323 name if all the files in it share the same status. The option takes an
5333 name if all the files in it share the same status. The option takes an
5324 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
5334 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
5325 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
5335 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
5326 for 'ignored' and 'c' for clean.
5336 for 'ignored' and 'c' for clean.
5327
5337
5328 It abbreviates only those statuses which are passed. Note that clean and
5338 It abbreviates only those statuses which are passed. Note that clean and
5329 ignored files are not displayed with '--terse ic' unless the -c/--clean
5339 ignored files are not displayed with '--terse ic' unless the -c/--clean
5330 and -i/--ignored options are also used.
5340 and -i/--ignored options are also used.
5331
5341
5332 The -v/--verbose option shows information when the repository is in an
5342 The -v/--verbose option shows information when the repository is in an
5333 unfinished merge, shelve, rebase state etc. You can have this behavior
5343 unfinished merge, shelve, rebase state etc. You can have this behavior
5334 turned on by default by enabling the ``commands.status.verbose`` option.
5344 turned on by default by enabling the ``commands.status.verbose`` option.
5335
5345
5336 You can skip displaying some of these states by setting
5346 You can skip displaying some of these states by setting
5337 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
5347 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
5338 'histedit', 'merge', 'rebase', or 'unshelve'.
5348 'histedit', 'merge', 'rebase', or 'unshelve'.
5339
5349
5340 Template:
5350 Template:
5341
5351
5342 The following keywords are supported in addition to the common template
5352 The following keywords are supported in addition to the common template
5343 keywords and functions. See also :hg:`help templates`.
5353 keywords and functions. See also :hg:`help templates`.
5344
5354
5345 :path: String. Repository-absolute path of the file.
5355 :path: String. Repository-absolute path of the file.
5346 :source: String. Repository-absolute path of the file originated from.
5356 :source: String. Repository-absolute path of the file originated from.
5347 Available if ``--copies`` is specified.
5357 Available if ``--copies`` is specified.
5348 :status: String. Character denoting file's status.
5358 :status: String. Character denoting file's status.
5349
5359
5350 Examples:
5360 Examples:
5351
5361
5352 - show changes in the working directory relative to a
5362 - show changes in the working directory relative to a
5353 changeset::
5363 changeset::
5354
5364
5355 hg status --rev 9353
5365 hg status --rev 9353
5356
5366
5357 - show changes in the working directory relative to the
5367 - show changes in the working directory relative to the
5358 current directory (see :hg:`help patterns` for more information)::
5368 current directory (see :hg:`help patterns` for more information)::
5359
5369
5360 hg status re:
5370 hg status re:
5361
5371
5362 - show all changes including copies in an existing changeset::
5372 - show all changes including copies in an existing changeset::
5363
5373
5364 hg status --copies --change 9353
5374 hg status --copies --change 9353
5365
5375
5366 - get a NUL separated list of added files, suitable for xargs::
5376 - get a NUL separated list of added files, suitable for xargs::
5367
5377
5368 hg status -an0
5378 hg status -an0
5369
5379
5370 - show more information about the repository status, abbreviating
5380 - show more information about the repository status, abbreviating
5371 added, removed, modified, deleted, and untracked paths::
5381 added, removed, modified, deleted, and untracked paths::
5372
5382
5373 hg status -v -t mardu
5383 hg status -v -t mardu
5374
5384
5375 Returns 0 on success.
5385 Returns 0 on success.
5376
5386
5377 """
5387 """
5378
5388
5379 opts = pycompat.byteskwargs(opts)
5389 opts = pycompat.byteskwargs(opts)
5380 revs = opts.get('rev')
5390 revs = opts.get('rev')
5381 change = opts.get('change')
5391 change = opts.get('change')
5382 terse = opts.get('terse')
5392 terse = opts.get('terse')
5383 if terse is _NOTTERSE:
5393 if terse is _NOTTERSE:
5384 if revs:
5394 if revs:
5385 terse = ''
5395 terse = ''
5386 else:
5396 else:
5387 terse = ui.config('commands', 'status.terse')
5397 terse = ui.config('commands', 'status.terse')
5388
5398
5389 if revs and change:
5399 if revs and change:
5390 msg = _('cannot specify --rev and --change at the same time')
5400 msg = _('cannot specify --rev and --change at the same time')
5391 raise error.Abort(msg)
5401 raise error.Abort(msg)
5392 elif revs and terse:
5402 elif revs and terse:
5393 msg = _('cannot use --terse with --rev')
5403 msg = _('cannot use --terse with --rev')
5394 raise error.Abort(msg)
5404 raise error.Abort(msg)
5395 elif change:
5405 elif change:
5396 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
5406 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
5397 ctx2 = scmutil.revsingle(repo, change, None)
5407 ctx2 = scmutil.revsingle(repo, change, None)
5398 ctx1 = ctx2.p1()
5408 ctx1 = ctx2.p1()
5399 else:
5409 else:
5400 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
5410 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
5401 ctx1, ctx2 = scmutil.revpair(repo, revs)
5411 ctx1, ctx2 = scmutil.revpair(repo, revs)
5402
5412
5403 if pats or ui.configbool('commands', 'status.relative'):
5413 if pats or ui.configbool('commands', 'status.relative'):
5404 cwd = repo.getcwd()
5414 cwd = repo.getcwd()
5405 else:
5415 else:
5406 cwd = ''
5416 cwd = ''
5407
5417
5408 if opts.get('print0'):
5418 if opts.get('print0'):
5409 end = '\0'
5419 end = '\0'
5410 else:
5420 else:
5411 end = '\n'
5421 end = '\n'
5412 copy = {}
5422 copy = {}
5413 states = 'modified added removed deleted unknown ignored clean'.split()
5423 states = 'modified added removed deleted unknown ignored clean'.split()
5414 show = [k for k in states if opts.get(k)]
5424 show = [k for k in states if opts.get(k)]
5415 if opts.get('all'):
5425 if opts.get('all'):
5416 show += ui.quiet and (states[:4] + ['clean']) or states
5426 show += ui.quiet and (states[:4] + ['clean']) or states
5417
5427
5418 if not show:
5428 if not show:
5419 if ui.quiet:
5429 if ui.quiet:
5420 show = states[:4]
5430 show = states[:4]
5421 else:
5431 else:
5422 show = states[:5]
5432 show = states[:5]
5423
5433
5424 m = scmutil.match(ctx2, pats, opts)
5434 m = scmutil.match(ctx2, pats, opts)
5425 if terse:
5435 if terse:
5426 # we need to compute clean and unknown to terse
5436 # we need to compute clean and unknown to terse
5427 stat = repo.status(ctx1.node(), ctx2.node(), m,
5437 stat = repo.status(ctx1.node(), ctx2.node(), m,
5428 'ignored' in show or 'i' in terse,
5438 'ignored' in show or 'i' in terse,
5429 clean=True, unknown=True,
5439 clean=True, unknown=True,
5430 listsubrepos=opts.get('subrepos'))
5440 listsubrepos=opts.get('subrepos'))
5431
5441
5432 stat = cmdutil.tersedir(stat, terse)
5442 stat = cmdutil.tersedir(stat, terse)
5433 else:
5443 else:
5434 stat = repo.status(ctx1.node(), ctx2.node(), m,
5444 stat = repo.status(ctx1.node(), ctx2.node(), m,
5435 'ignored' in show, 'clean' in show,
5445 'ignored' in show, 'clean' in show,
5436 'unknown' in show, opts.get('subrepos'))
5446 'unknown' in show, opts.get('subrepos'))
5437
5447
5438 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
5448 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
5439
5449
5440 if (opts.get('all') or opts.get('copies')
5450 if (opts.get('all') or opts.get('copies')
5441 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5451 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5442 copy = copies.pathcopies(ctx1, ctx2, m)
5452 copy = copies.pathcopies(ctx1, ctx2, m)
5443
5453
5444 ui.pager('status')
5454 ui.pager('status')
5445 fm = ui.formatter('status', opts)
5455 fm = ui.formatter('status', opts)
5446 fmt = '%s' + end
5456 fmt = '%s' + end
5447 showchar = not opts.get('no_status')
5457 showchar = not opts.get('no_status')
5448
5458
5449 for state, char, files in changestates:
5459 for state, char, files in changestates:
5450 if state in show:
5460 if state in show:
5451 label = 'status.' + state
5461 label = 'status.' + state
5452 for f in files:
5462 for f in files:
5453 fm.startitem()
5463 fm.startitem()
5454 fm.context(ctx=ctx2)
5464 fm.context(ctx=ctx2)
5455 fm.data(path=f)
5465 fm.data(path=f)
5456 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5466 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5457 fm.plain(fmt % repo.pathto(f, cwd), label=label)
5467 fm.plain(fmt % repo.pathto(f, cwd), label=label)
5458 if f in copy:
5468 if f in copy:
5459 fm.data(source=copy[f])
5469 fm.data(source=copy[f])
5460 fm.plain((' %s' + end) % repo.pathto(copy[f], cwd),
5470 fm.plain((' %s' + end) % repo.pathto(copy[f], cwd),
5461 label='status.copied')
5471 label='status.copied')
5462
5472
5463 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
5473 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
5464 and not ui.plain()):
5474 and not ui.plain()):
5465 cmdutil.morestatus(repo, fm)
5475 cmdutil.morestatus(repo, fm)
5466 fm.end()
5476 fm.end()
5467
5477
5468 @command('summary|sum',
5478 @command('summary|sum',
5469 [('', 'remote', None, _('check for push and pull'))],
5479 [('', 'remote', None, _('check for push and pull'))],
5470 '[--remote]',
5480 '[--remote]',
5471 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5481 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5472 helpbasic=True,
5482 helpbasic=True,
5473 intents={INTENT_READONLY})
5483 intents={INTENT_READONLY})
5474 def summary(ui, repo, **opts):
5484 def summary(ui, repo, **opts):
5475 """summarize working directory state
5485 """summarize working directory state
5476
5486
5477 This generates a brief summary of the working directory state,
5487 This generates a brief summary of the working directory state,
5478 including parents, branch, commit status, phase and available updates.
5488 including parents, branch, commit status, phase and available updates.
5479
5489
5480 With the --remote option, this will check the default paths for
5490 With the --remote option, this will check the default paths for
5481 incoming and outgoing changes. This can be time-consuming.
5491 incoming and outgoing changes. This can be time-consuming.
5482
5492
5483 Returns 0 on success.
5493 Returns 0 on success.
5484 """
5494 """
5485
5495
5486 opts = pycompat.byteskwargs(opts)
5496 opts = pycompat.byteskwargs(opts)
5487 ui.pager('summary')
5497 ui.pager('summary')
5488 ctx = repo[None]
5498 ctx = repo[None]
5489 parents = ctx.parents()
5499 parents = ctx.parents()
5490 pnode = parents[0].node()
5500 pnode = parents[0].node()
5491 marks = []
5501 marks = []
5492
5502
5493 ms = None
5503 ms = None
5494 try:
5504 try:
5495 ms = mergemod.mergestate.read(repo)
5505 ms = mergemod.mergestate.read(repo)
5496 except error.UnsupportedMergeRecords as e:
5506 except error.UnsupportedMergeRecords as e:
5497 s = ' '.join(e.recordtypes)
5507 s = ' '.join(e.recordtypes)
5498 ui.warn(
5508 ui.warn(
5499 _('warning: merge state has unsupported record types: %s\n') % s)
5509 _('warning: merge state has unsupported record types: %s\n') % s)
5500 unresolved = []
5510 unresolved = []
5501 else:
5511 else:
5502 unresolved = list(ms.unresolved())
5512 unresolved = list(ms.unresolved())
5503
5513
5504 for p in parents:
5514 for p in parents:
5505 # label with log.changeset (instead of log.parent) since this
5515 # label with log.changeset (instead of log.parent) since this
5506 # shows a working directory parent *changeset*:
5516 # shows a working directory parent *changeset*:
5507 # i18n: column positioning for "hg summary"
5517 # i18n: column positioning for "hg summary"
5508 ui.write(_('parent: %d:%s ') % (p.rev(), p),
5518 ui.write(_('parent: %d:%s ') % (p.rev(), p),
5509 label=logcmdutil.changesetlabels(p))
5519 label=logcmdutil.changesetlabels(p))
5510 ui.write(' '.join(p.tags()), label='log.tag')
5520 ui.write(' '.join(p.tags()), label='log.tag')
5511 if p.bookmarks():
5521 if p.bookmarks():
5512 marks.extend(p.bookmarks())
5522 marks.extend(p.bookmarks())
5513 if p.rev() == -1:
5523 if p.rev() == -1:
5514 if not len(repo):
5524 if not len(repo):
5515 ui.write(_(' (empty repository)'))
5525 ui.write(_(' (empty repository)'))
5516 else:
5526 else:
5517 ui.write(_(' (no revision checked out)'))
5527 ui.write(_(' (no revision checked out)'))
5518 if p.obsolete():
5528 if p.obsolete():
5519 ui.write(_(' (obsolete)'))
5529 ui.write(_(' (obsolete)'))
5520 if p.isunstable():
5530 if p.isunstable():
5521 instabilities = (ui.label(instability, 'trouble.%s' % instability)
5531 instabilities = (ui.label(instability, 'trouble.%s' % instability)
5522 for instability in p.instabilities())
5532 for instability in p.instabilities())
5523 ui.write(' ('
5533 ui.write(' ('
5524 + ', '.join(instabilities)
5534 + ', '.join(instabilities)
5525 + ')')
5535 + ')')
5526 ui.write('\n')
5536 ui.write('\n')
5527 if p.description():
5537 if p.description():
5528 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5538 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5529 label='log.summary')
5539 label='log.summary')
5530
5540
5531 branch = ctx.branch()
5541 branch = ctx.branch()
5532 bheads = repo.branchheads(branch)
5542 bheads = repo.branchheads(branch)
5533 # i18n: column positioning for "hg summary"
5543 # i18n: column positioning for "hg summary"
5534 m = _('branch: %s\n') % branch
5544 m = _('branch: %s\n') % branch
5535 if branch != 'default':
5545 if branch != 'default':
5536 ui.write(m, label='log.branch')
5546 ui.write(m, label='log.branch')
5537 else:
5547 else:
5538 ui.status(m, label='log.branch')
5548 ui.status(m, label='log.branch')
5539
5549
5540 if marks:
5550 if marks:
5541 active = repo._activebookmark
5551 active = repo._activebookmark
5542 # i18n: column positioning for "hg summary"
5552 # i18n: column positioning for "hg summary"
5543 ui.write(_('bookmarks:'), label='log.bookmark')
5553 ui.write(_('bookmarks:'), label='log.bookmark')
5544 if active is not None:
5554 if active is not None:
5545 if active in marks:
5555 if active in marks:
5546 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5556 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5547 marks.remove(active)
5557 marks.remove(active)
5548 else:
5558 else:
5549 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5559 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5550 for m in marks:
5560 for m in marks:
5551 ui.write(' ' + m, label='log.bookmark')
5561 ui.write(' ' + m, label='log.bookmark')
5552 ui.write('\n', label='log.bookmark')
5562 ui.write('\n', label='log.bookmark')
5553
5563
5554 status = repo.status(unknown=True)
5564 status = repo.status(unknown=True)
5555
5565
5556 c = repo.dirstate.copies()
5566 c = repo.dirstate.copies()
5557 copied, renamed = [], []
5567 copied, renamed = [], []
5558 for d, s in c.iteritems():
5568 for d, s in c.iteritems():
5559 if s in status.removed:
5569 if s in status.removed:
5560 status.removed.remove(s)
5570 status.removed.remove(s)
5561 renamed.append(d)
5571 renamed.append(d)
5562 else:
5572 else:
5563 copied.append(d)
5573 copied.append(d)
5564 if d in status.added:
5574 if d in status.added:
5565 status.added.remove(d)
5575 status.added.remove(d)
5566
5576
5567 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5577 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5568
5578
5569 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5579 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5570 (ui.label(_('%d added'), 'status.added'), status.added),
5580 (ui.label(_('%d added'), 'status.added'), status.added),
5571 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5581 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5572 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5582 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5573 (ui.label(_('%d copied'), 'status.copied'), copied),
5583 (ui.label(_('%d copied'), 'status.copied'), copied),
5574 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5584 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5575 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5585 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5576 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5586 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5577 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5587 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5578 t = []
5588 t = []
5579 for l, s in labels:
5589 for l, s in labels:
5580 if s:
5590 if s:
5581 t.append(l % len(s))
5591 t.append(l % len(s))
5582
5592
5583 t = ', '.join(t)
5593 t = ', '.join(t)
5584 cleanworkdir = False
5594 cleanworkdir = False
5585
5595
5586 if repo.vfs.exists('graftstate'):
5596 if repo.vfs.exists('graftstate'):
5587 t += _(' (graft in progress)')
5597 t += _(' (graft in progress)')
5588 if repo.vfs.exists('updatestate'):
5598 if repo.vfs.exists('updatestate'):
5589 t += _(' (interrupted update)')
5599 t += _(' (interrupted update)')
5590 elif len(parents) > 1:
5600 elif len(parents) > 1:
5591 t += _(' (merge)')
5601 t += _(' (merge)')
5592 elif branch != parents[0].branch():
5602 elif branch != parents[0].branch():
5593 t += _(' (new branch)')
5603 t += _(' (new branch)')
5594 elif (parents[0].closesbranch() and
5604 elif (parents[0].closesbranch() and
5595 pnode in repo.branchheads(branch, closed=True)):
5605 pnode in repo.branchheads(branch, closed=True)):
5596 t += _(' (head closed)')
5606 t += _(' (head closed)')
5597 elif not (status.modified or status.added or status.removed or renamed or
5607 elif not (status.modified or status.added or status.removed or renamed or
5598 copied or subs):
5608 copied or subs):
5599 t += _(' (clean)')
5609 t += _(' (clean)')
5600 cleanworkdir = True
5610 cleanworkdir = True
5601 elif pnode not in bheads:
5611 elif pnode not in bheads:
5602 t += _(' (new branch head)')
5612 t += _(' (new branch head)')
5603
5613
5604 if parents:
5614 if parents:
5605 pendingphase = max(p.phase() for p in parents)
5615 pendingphase = max(p.phase() for p in parents)
5606 else:
5616 else:
5607 pendingphase = phases.public
5617 pendingphase = phases.public
5608
5618
5609 if pendingphase > phases.newcommitphase(ui):
5619 if pendingphase > phases.newcommitphase(ui):
5610 t += ' (%s)' % phases.phasenames[pendingphase]
5620 t += ' (%s)' % phases.phasenames[pendingphase]
5611
5621
5612 if cleanworkdir:
5622 if cleanworkdir:
5613 # i18n: column positioning for "hg summary"
5623 # i18n: column positioning for "hg summary"
5614 ui.status(_('commit: %s\n') % t.strip())
5624 ui.status(_('commit: %s\n') % t.strip())
5615 else:
5625 else:
5616 # i18n: column positioning for "hg summary"
5626 # i18n: column positioning for "hg summary"
5617 ui.write(_('commit: %s\n') % t.strip())
5627 ui.write(_('commit: %s\n') % t.strip())
5618
5628
5619 # all ancestors of branch heads - all ancestors of parent = new csets
5629 # all ancestors of branch heads - all ancestors of parent = new csets
5620 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5630 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5621 bheads))
5631 bheads))
5622
5632
5623 if new == 0:
5633 if new == 0:
5624 # i18n: column positioning for "hg summary"
5634 # i18n: column positioning for "hg summary"
5625 ui.status(_('update: (current)\n'))
5635 ui.status(_('update: (current)\n'))
5626 elif pnode not in bheads:
5636 elif pnode not in bheads:
5627 # i18n: column positioning for "hg summary"
5637 # i18n: column positioning for "hg summary"
5628 ui.write(_('update: %d new changesets (update)\n') % new)
5638 ui.write(_('update: %d new changesets (update)\n') % new)
5629 else:
5639 else:
5630 # i18n: column positioning for "hg summary"
5640 # i18n: column positioning for "hg summary"
5631 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5641 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5632 (new, len(bheads)))
5642 (new, len(bheads)))
5633
5643
5634 t = []
5644 t = []
5635 draft = len(repo.revs('draft()'))
5645 draft = len(repo.revs('draft()'))
5636 if draft:
5646 if draft:
5637 t.append(_('%d draft') % draft)
5647 t.append(_('%d draft') % draft)
5638 secret = len(repo.revs('secret()'))
5648 secret = len(repo.revs('secret()'))
5639 if secret:
5649 if secret:
5640 t.append(_('%d secret') % secret)
5650 t.append(_('%d secret') % secret)
5641
5651
5642 if draft or secret:
5652 if draft or secret:
5643 ui.status(_('phases: %s\n') % ', '.join(t))
5653 ui.status(_('phases: %s\n') % ', '.join(t))
5644
5654
5645 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5655 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5646 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5656 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5647 numtrouble = len(repo.revs(trouble + "()"))
5657 numtrouble = len(repo.revs(trouble + "()"))
5648 # We write all the possibilities to ease translation
5658 # We write all the possibilities to ease translation
5649 troublemsg = {
5659 troublemsg = {
5650 "orphan": _("orphan: %d changesets"),
5660 "orphan": _("orphan: %d changesets"),
5651 "contentdivergent": _("content-divergent: %d changesets"),
5661 "contentdivergent": _("content-divergent: %d changesets"),
5652 "phasedivergent": _("phase-divergent: %d changesets"),
5662 "phasedivergent": _("phase-divergent: %d changesets"),
5653 }
5663 }
5654 if numtrouble > 0:
5664 if numtrouble > 0:
5655 ui.status(troublemsg[trouble] % numtrouble + "\n")
5665 ui.status(troublemsg[trouble] % numtrouble + "\n")
5656
5666
5657 cmdutil.summaryhooks(ui, repo)
5667 cmdutil.summaryhooks(ui, repo)
5658
5668
5659 if opts.get('remote'):
5669 if opts.get('remote'):
5660 needsincoming, needsoutgoing = True, True
5670 needsincoming, needsoutgoing = True, True
5661 else:
5671 else:
5662 needsincoming, needsoutgoing = False, False
5672 needsincoming, needsoutgoing = False, False
5663 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5673 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5664 if i:
5674 if i:
5665 needsincoming = True
5675 needsincoming = True
5666 if o:
5676 if o:
5667 needsoutgoing = True
5677 needsoutgoing = True
5668 if not needsincoming and not needsoutgoing:
5678 if not needsincoming and not needsoutgoing:
5669 return
5679 return
5670
5680
5671 def getincoming():
5681 def getincoming():
5672 source, branches = hg.parseurl(ui.expandpath('default'))
5682 source, branches = hg.parseurl(ui.expandpath('default'))
5673 sbranch = branches[0]
5683 sbranch = branches[0]
5674 try:
5684 try:
5675 other = hg.peer(repo, {}, source)
5685 other = hg.peer(repo, {}, source)
5676 except error.RepoError:
5686 except error.RepoError:
5677 if opts.get('remote'):
5687 if opts.get('remote'):
5678 raise
5688 raise
5679 return source, sbranch, None, None, None
5689 return source, sbranch, None, None, None
5680 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5690 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5681 if revs:
5691 if revs:
5682 revs = [other.lookup(rev) for rev in revs]
5692 revs = [other.lookup(rev) for rev in revs]
5683 ui.debug('comparing with %s\n' % util.hidepassword(source))
5693 ui.debug('comparing with %s\n' % util.hidepassword(source))
5684 repo.ui.pushbuffer()
5694 repo.ui.pushbuffer()
5685 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5695 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5686 repo.ui.popbuffer()
5696 repo.ui.popbuffer()
5687 return source, sbranch, other, commoninc, commoninc[1]
5697 return source, sbranch, other, commoninc, commoninc[1]
5688
5698
5689 if needsincoming:
5699 if needsincoming:
5690 source, sbranch, sother, commoninc, incoming = getincoming()
5700 source, sbranch, sother, commoninc, incoming = getincoming()
5691 else:
5701 else:
5692 source = sbranch = sother = commoninc = incoming = None
5702 source = sbranch = sother = commoninc = incoming = None
5693
5703
5694 def getoutgoing():
5704 def getoutgoing():
5695 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5705 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5696 dbranch = branches[0]
5706 dbranch = branches[0]
5697 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5707 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5698 if source != dest:
5708 if source != dest:
5699 try:
5709 try:
5700 dother = hg.peer(repo, {}, dest)
5710 dother = hg.peer(repo, {}, dest)
5701 except error.RepoError:
5711 except error.RepoError:
5702 if opts.get('remote'):
5712 if opts.get('remote'):
5703 raise
5713 raise
5704 return dest, dbranch, None, None
5714 return dest, dbranch, None, None
5705 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5715 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5706 elif sother is None:
5716 elif sother is None:
5707 # there is no explicit destination peer, but source one is invalid
5717 # there is no explicit destination peer, but source one is invalid
5708 return dest, dbranch, None, None
5718 return dest, dbranch, None, None
5709 else:
5719 else:
5710 dother = sother
5720 dother = sother
5711 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5721 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5712 common = None
5722 common = None
5713 else:
5723 else:
5714 common = commoninc
5724 common = commoninc
5715 if revs:
5725 if revs:
5716 revs = [repo.lookup(rev) for rev in revs]
5726 revs = [repo.lookup(rev) for rev in revs]
5717 repo.ui.pushbuffer()
5727 repo.ui.pushbuffer()
5718 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5728 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5719 commoninc=common)
5729 commoninc=common)
5720 repo.ui.popbuffer()
5730 repo.ui.popbuffer()
5721 return dest, dbranch, dother, outgoing
5731 return dest, dbranch, dother, outgoing
5722
5732
5723 if needsoutgoing:
5733 if needsoutgoing:
5724 dest, dbranch, dother, outgoing = getoutgoing()
5734 dest, dbranch, dother, outgoing = getoutgoing()
5725 else:
5735 else:
5726 dest = dbranch = dother = outgoing = None
5736 dest = dbranch = dother = outgoing = None
5727
5737
5728 if opts.get('remote'):
5738 if opts.get('remote'):
5729 t = []
5739 t = []
5730 if incoming:
5740 if incoming:
5731 t.append(_('1 or more incoming'))
5741 t.append(_('1 or more incoming'))
5732 o = outgoing.missing
5742 o = outgoing.missing
5733 if o:
5743 if o:
5734 t.append(_('%d outgoing') % len(o))
5744 t.append(_('%d outgoing') % len(o))
5735 other = dother or sother
5745 other = dother or sother
5736 if 'bookmarks' in other.listkeys('namespaces'):
5746 if 'bookmarks' in other.listkeys('namespaces'):
5737 counts = bookmarks.summary(repo, other)
5747 counts = bookmarks.summary(repo, other)
5738 if counts[0] > 0:
5748 if counts[0] > 0:
5739 t.append(_('%d incoming bookmarks') % counts[0])
5749 t.append(_('%d incoming bookmarks') % counts[0])
5740 if counts[1] > 0:
5750 if counts[1] > 0:
5741 t.append(_('%d outgoing bookmarks') % counts[1])
5751 t.append(_('%d outgoing bookmarks') % counts[1])
5742
5752
5743 if t:
5753 if t:
5744 # i18n: column positioning for "hg summary"
5754 # i18n: column positioning for "hg summary"
5745 ui.write(_('remote: %s\n') % (', '.join(t)))
5755 ui.write(_('remote: %s\n') % (', '.join(t)))
5746 else:
5756 else:
5747 # i18n: column positioning for "hg summary"
5757 # i18n: column positioning for "hg summary"
5748 ui.status(_('remote: (synced)\n'))
5758 ui.status(_('remote: (synced)\n'))
5749
5759
5750 cmdutil.summaryremotehooks(ui, repo, opts,
5760 cmdutil.summaryremotehooks(ui, repo, opts,
5751 ((source, sbranch, sother, commoninc),
5761 ((source, sbranch, sother, commoninc),
5752 (dest, dbranch, dother, outgoing)))
5762 (dest, dbranch, dother, outgoing)))
5753
5763
5754 @command('tag',
5764 @command('tag',
5755 [('f', 'force', None, _('force tag')),
5765 [('f', 'force', None, _('force tag')),
5756 ('l', 'local', None, _('make the tag local')),
5766 ('l', 'local', None, _('make the tag local')),
5757 ('r', 'rev', '', _('revision to tag'), _('REV')),
5767 ('r', 'rev', '', _('revision to tag'), _('REV')),
5758 ('', 'remove', None, _('remove a tag')),
5768 ('', 'remove', None, _('remove a tag')),
5759 # -l/--local is already there, commitopts cannot be used
5769 # -l/--local is already there, commitopts cannot be used
5760 ('e', 'edit', None, _('invoke editor on commit messages')),
5770 ('e', 'edit', None, _('invoke editor on commit messages')),
5761 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5771 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5762 ] + commitopts2,
5772 ] + commitopts2,
5763 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
5773 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
5764 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
5774 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
5765 def tag(ui, repo, name1, *names, **opts):
5775 def tag(ui, repo, name1, *names, **opts):
5766 """add one or more tags for the current or given revision
5776 """add one or more tags for the current or given revision
5767
5777
5768 Name a particular revision using <name>.
5778 Name a particular revision using <name>.
5769
5779
5770 Tags are used to name particular revisions of the repository and are
5780 Tags are used to name particular revisions of the repository and are
5771 very useful to compare different revisions, to go back to significant
5781 very useful to compare different revisions, to go back to significant
5772 earlier versions or to mark branch points as releases, etc. Changing
5782 earlier versions or to mark branch points as releases, etc. Changing
5773 an existing tag is normally disallowed; use -f/--force to override.
5783 an existing tag is normally disallowed; use -f/--force to override.
5774
5784
5775 If no revision is given, the parent of the working directory is
5785 If no revision is given, the parent of the working directory is
5776 used.
5786 used.
5777
5787
5778 To facilitate version control, distribution, and merging of tags,
5788 To facilitate version control, distribution, and merging of tags,
5779 they are stored as a file named ".hgtags" which is managed similarly
5789 they are stored as a file named ".hgtags" which is managed similarly
5780 to other project files and can be hand-edited if necessary. This
5790 to other project files and can be hand-edited if necessary. This
5781 also means that tagging creates a new commit. The file
5791 also means that tagging creates a new commit. The file
5782 ".hg/localtags" is used for local tags (not shared among
5792 ".hg/localtags" is used for local tags (not shared among
5783 repositories).
5793 repositories).
5784
5794
5785 Tag commits are usually made at the head of a branch. If the parent
5795 Tag commits are usually made at the head of a branch. If the parent
5786 of the working directory is not a branch head, :hg:`tag` aborts; use
5796 of the working directory is not a branch head, :hg:`tag` aborts; use
5787 -f/--force to force the tag commit to be based on a non-head
5797 -f/--force to force the tag commit to be based on a non-head
5788 changeset.
5798 changeset.
5789
5799
5790 See :hg:`help dates` for a list of formats valid for -d/--date.
5800 See :hg:`help dates` for a list of formats valid for -d/--date.
5791
5801
5792 Since tag names have priority over branch names during revision
5802 Since tag names have priority over branch names during revision
5793 lookup, using an existing branch name as a tag name is discouraged.
5803 lookup, using an existing branch name as a tag name is discouraged.
5794
5804
5795 Returns 0 on success.
5805 Returns 0 on success.
5796 """
5806 """
5797 opts = pycompat.byteskwargs(opts)
5807 opts = pycompat.byteskwargs(opts)
5798 with repo.wlock(), repo.lock():
5808 with repo.wlock(), repo.lock():
5799 rev_ = "."
5809 rev_ = "."
5800 names = [t.strip() for t in (name1,) + names]
5810 names = [t.strip() for t in (name1,) + names]
5801 if len(names) != len(set(names)):
5811 if len(names) != len(set(names)):
5802 raise error.Abort(_('tag names must be unique'))
5812 raise error.Abort(_('tag names must be unique'))
5803 for n in names:
5813 for n in names:
5804 scmutil.checknewlabel(repo, n, 'tag')
5814 scmutil.checknewlabel(repo, n, 'tag')
5805 if not n:
5815 if not n:
5806 raise error.Abort(_('tag names cannot consist entirely of '
5816 raise error.Abort(_('tag names cannot consist entirely of '
5807 'whitespace'))
5817 'whitespace'))
5808 if opts.get('rev') and opts.get('remove'):
5818 if opts.get('rev') and opts.get('remove'):
5809 raise error.Abort(_("--rev and --remove are incompatible"))
5819 raise error.Abort(_("--rev and --remove are incompatible"))
5810 if opts.get('rev'):
5820 if opts.get('rev'):
5811 rev_ = opts['rev']
5821 rev_ = opts['rev']
5812 message = opts.get('message')
5822 message = opts.get('message')
5813 if opts.get('remove'):
5823 if opts.get('remove'):
5814 if opts.get('local'):
5824 if opts.get('local'):
5815 expectedtype = 'local'
5825 expectedtype = 'local'
5816 else:
5826 else:
5817 expectedtype = 'global'
5827 expectedtype = 'global'
5818
5828
5819 for n in names:
5829 for n in names:
5820 if not repo.tagtype(n):
5830 if not repo.tagtype(n):
5821 raise error.Abort(_("tag '%s' does not exist") % n)
5831 raise error.Abort(_("tag '%s' does not exist") % n)
5822 if repo.tagtype(n) != expectedtype:
5832 if repo.tagtype(n) != expectedtype:
5823 if expectedtype == 'global':
5833 if expectedtype == 'global':
5824 raise error.Abort(_("tag '%s' is not a global tag") % n)
5834 raise error.Abort(_("tag '%s' is not a global tag") % n)
5825 else:
5835 else:
5826 raise error.Abort(_("tag '%s' is not a local tag") % n)
5836 raise error.Abort(_("tag '%s' is not a local tag") % n)
5827 rev_ = 'null'
5837 rev_ = 'null'
5828 if not message:
5838 if not message:
5829 # we don't translate commit messages
5839 # we don't translate commit messages
5830 message = 'Removed tag %s' % ', '.join(names)
5840 message = 'Removed tag %s' % ', '.join(names)
5831 elif not opts.get('force'):
5841 elif not opts.get('force'):
5832 for n in names:
5842 for n in names:
5833 if n in repo.tags():
5843 if n in repo.tags():
5834 raise error.Abort(_("tag '%s' already exists "
5844 raise error.Abort(_("tag '%s' already exists "
5835 "(use -f to force)") % n)
5845 "(use -f to force)") % n)
5836 if not opts.get('local'):
5846 if not opts.get('local'):
5837 p1, p2 = repo.dirstate.parents()
5847 p1, p2 = repo.dirstate.parents()
5838 if p2 != nullid:
5848 if p2 != nullid:
5839 raise error.Abort(_('uncommitted merge'))
5849 raise error.Abort(_('uncommitted merge'))
5840 bheads = repo.branchheads()
5850 bheads = repo.branchheads()
5841 if not opts.get('force') and bheads and p1 not in bheads:
5851 if not opts.get('force') and bheads and p1 not in bheads:
5842 raise error.Abort(_('working directory is not at a branch head '
5852 raise error.Abort(_('working directory is not at a branch head '
5843 '(use -f to force)'))
5853 '(use -f to force)'))
5844 node = scmutil.revsingle(repo, rev_).node()
5854 node = scmutil.revsingle(repo, rev_).node()
5845
5855
5846 if not message:
5856 if not message:
5847 # we don't translate commit messages
5857 # we don't translate commit messages
5848 message = ('Added tag %s for changeset %s' %
5858 message = ('Added tag %s for changeset %s' %
5849 (', '.join(names), short(node)))
5859 (', '.join(names), short(node)))
5850
5860
5851 date = opts.get('date')
5861 date = opts.get('date')
5852 if date:
5862 if date:
5853 date = dateutil.parsedate(date)
5863 date = dateutil.parsedate(date)
5854
5864
5855 if opts.get('remove'):
5865 if opts.get('remove'):
5856 editform = 'tag.remove'
5866 editform = 'tag.remove'
5857 else:
5867 else:
5858 editform = 'tag.add'
5868 editform = 'tag.add'
5859 editor = cmdutil.getcommiteditor(editform=editform,
5869 editor = cmdutil.getcommiteditor(editform=editform,
5860 **pycompat.strkwargs(opts))
5870 **pycompat.strkwargs(opts))
5861
5871
5862 # don't allow tagging the null rev
5872 # don't allow tagging the null rev
5863 if (not opts.get('remove') and
5873 if (not opts.get('remove') and
5864 scmutil.revsingle(repo, rev_).rev() == nullrev):
5874 scmutil.revsingle(repo, rev_).rev() == nullrev):
5865 raise error.Abort(_("cannot tag null revision"))
5875 raise error.Abort(_("cannot tag null revision"))
5866
5876
5867 tagsmod.tag(repo, names, node, message, opts.get('local'),
5877 tagsmod.tag(repo, names, node, message, opts.get('local'),
5868 opts.get('user'), date, editor=editor)
5878 opts.get('user'), date, editor=editor)
5869
5879
5870 @command(
5880 @command(
5871 'tags', formatteropts, '',
5881 'tags', formatteropts, '',
5872 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5882 helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
5873 intents={INTENT_READONLY})
5883 intents={INTENT_READONLY})
5874 def tags(ui, repo, **opts):
5884 def tags(ui, repo, **opts):
5875 """list repository tags
5885 """list repository tags
5876
5886
5877 This lists both regular and local tags. When the -v/--verbose
5887 This lists both regular and local tags. When the -v/--verbose
5878 switch is used, a third column "local" is printed for local tags.
5888 switch is used, a third column "local" is printed for local tags.
5879 When the -q/--quiet switch is used, only the tag name is printed.
5889 When the -q/--quiet switch is used, only the tag name is printed.
5880
5890
5881 .. container:: verbose
5891 .. container:: verbose
5882
5892
5883 Template:
5893 Template:
5884
5894
5885 The following keywords are supported in addition to the common template
5895 The following keywords are supported in addition to the common template
5886 keywords and functions such as ``{tag}``. See also
5896 keywords and functions such as ``{tag}``. See also
5887 :hg:`help templates`.
5897 :hg:`help templates`.
5888
5898
5889 :type: String. ``local`` for local tags.
5899 :type: String. ``local`` for local tags.
5890
5900
5891 Returns 0 on success.
5901 Returns 0 on success.
5892 """
5902 """
5893
5903
5894 opts = pycompat.byteskwargs(opts)
5904 opts = pycompat.byteskwargs(opts)
5895 ui.pager('tags')
5905 ui.pager('tags')
5896 fm = ui.formatter('tags', opts)
5906 fm = ui.formatter('tags', opts)
5897 hexfunc = fm.hexfunc
5907 hexfunc = fm.hexfunc
5898 tagtype = ""
5908 tagtype = ""
5899
5909
5900 for t, n in reversed(repo.tagslist()):
5910 for t, n in reversed(repo.tagslist()):
5901 hn = hexfunc(n)
5911 hn = hexfunc(n)
5902 label = 'tags.normal'
5912 label = 'tags.normal'
5903 tagtype = ''
5913 tagtype = ''
5904 if repo.tagtype(t) == 'local':
5914 if repo.tagtype(t) == 'local':
5905 label = 'tags.local'
5915 label = 'tags.local'
5906 tagtype = 'local'
5916 tagtype = 'local'
5907
5917
5908 fm.startitem()
5918 fm.startitem()
5909 fm.context(repo=repo)
5919 fm.context(repo=repo)
5910 fm.write('tag', '%s', t, label=label)
5920 fm.write('tag', '%s', t, label=label)
5911 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5921 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5912 fm.condwrite(not ui.quiet, 'rev node', fmt,
5922 fm.condwrite(not ui.quiet, 'rev node', fmt,
5913 repo.changelog.rev(n), hn, label=label)
5923 repo.changelog.rev(n), hn, label=label)
5914 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5924 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5915 tagtype, label=label)
5925 tagtype, label=label)
5916 fm.plain('\n')
5926 fm.plain('\n')
5917 fm.end()
5927 fm.end()
5918
5928
5919 @command('tip',
5929 @command('tip',
5920 [('p', 'patch', None, _('show patch')),
5930 [('p', 'patch', None, _('show patch')),
5921 ('g', 'git', None, _('use git extended diff format')),
5931 ('g', 'git', None, _('use git extended diff format')),
5922 ] + templateopts,
5932 ] + templateopts,
5923 _('[-p] [-g]'),
5933 _('[-p] [-g]'),
5924 helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
5934 helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
5925 def tip(ui, repo, **opts):
5935 def tip(ui, repo, **opts):
5926 """show the tip revision (DEPRECATED)
5936 """show the tip revision (DEPRECATED)
5927
5937
5928 The tip revision (usually just called the tip) is the changeset
5938 The tip revision (usually just called the tip) is the changeset
5929 most recently added to the repository (and therefore the most
5939 most recently added to the repository (and therefore the most
5930 recently changed head).
5940 recently changed head).
5931
5941
5932 If you have just made a commit, that commit will be the tip. If
5942 If you have just made a commit, that commit will be the tip. If
5933 you have just pulled changes from another repository, the tip of
5943 you have just pulled changes from another repository, the tip of
5934 that repository becomes the current tip. The "tip" tag is special
5944 that repository becomes the current tip. The "tip" tag is special
5935 and cannot be renamed or assigned to a different changeset.
5945 and cannot be renamed or assigned to a different changeset.
5936
5946
5937 This command is deprecated, please use :hg:`heads` instead.
5947 This command is deprecated, please use :hg:`heads` instead.
5938
5948
5939 Returns 0 on success.
5949 Returns 0 on success.
5940 """
5950 """
5941 opts = pycompat.byteskwargs(opts)
5951 opts = pycompat.byteskwargs(opts)
5942 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5952 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5943 displayer.show(repo['tip'])
5953 displayer.show(repo['tip'])
5944 displayer.close()
5954 displayer.close()
5945
5955
5946 @command('unbundle',
5956 @command('unbundle',
5947 [('u', 'update', None,
5957 [('u', 'update', None,
5948 _('update to new branch head if changesets were unbundled'))],
5958 _('update to new branch head if changesets were unbundled'))],
5949 _('[-u] FILE...'),
5959 _('[-u] FILE...'),
5950 helpcategory=command.CATEGORY_IMPORT_EXPORT)
5960 helpcategory=command.CATEGORY_IMPORT_EXPORT)
5951 def unbundle(ui, repo, fname1, *fnames, **opts):
5961 def unbundle(ui, repo, fname1, *fnames, **opts):
5952 """apply one or more bundle files
5962 """apply one or more bundle files
5953
5963
5954 Apply one or more bundle files generated by :hg:`bundle`.
5964 Apply one or more bundle files generated by :hg:`bundle`.
5955
5965
5956 Returns 0 on success, 1 if an update has unresolved files.
5966 Returns 0 on success, 1 if an update has unresolved files.
5957 """
5967 """
5958 fnames = (fname1,) + fnames
5968 fnames = (fname1,) + fnames
5959
5969
5960 with repo.lock():
5970 with repo.lock():
5961 for fname in fnames:
5971 for fname in fnames:
5962 f = hg.openpath(ui, fname)
5972 f = hg.openpath(ui, fname)
5963 gen = exchange.readbundle(ui, f, fname)
5973 gen = exchange.readbundle(ui, f, fname)
5964 if isinstance(gen, streamclone.streamcloneapplier):
5974 if isinstance(gen, streamclone.streamcloneapplier):
5965 raise error.Abort(
5975 raise error.Abort(
5966 _('packed bundles cannot be applied with '
5976 _('packed bundles cannot be applied with '
5967 '"hg unbundle"'),
5977 '"hg unbundle"'),
5968 hint=_('use "hg debugapplystreamclonebundle"'))
5978 hint=_('use "hg debugapplystreamclonebundle"'))
5969 url = 'bundle:' + fname
5979 url = 'bundle:' + fname
5970 try:
5980 try:
5971 txnname = 'unbundle'
5981 txnname = 'unbundle'
5972 if not isinstance(gen, bundle2.unbundle20):
5982 if not isinstance(gen, bundle2.unbundle20):
5973 txnname = 'unbundle\n%s' % util.hidepassword(url)
5983 txnname = 'unbundle\n%s' % util.hidepassword(url)
5974 with repo.transaction(txnname) as tr:
5984 with repo.transaction(txnname) as tr:
5975 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5985 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5976 url=url)
5986 url=url)
5977 except error.BundleUnknownFeatureError as exc:
5987 except error.BundleUnknownFeatureError as exc:
5978 raise error.Abort(
5988 raise error.Abort(
5979 _('%s: unknown bundle feature, %s') % (fname, exc),
5989 _('%s: unknown bundle feature, %s') % (fname, exc),
5980 hint=_("see https://mercurial-scm.org/"
5990 hint=_("see https://mercurial-scm.org/"
5981 "wiki/BundleFeature for more "
5991 "wiki/BundleFeature for more "
5982 "information"))
5992 "information"))
5983 modheads = bundle2.combinechangegroupresults(op)
5993 modheads = bundle2.combinechangegroupresults(op)
5984
5994
5985 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5995 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5986
5996
5987 @command('update|up|checkout|co',
5997 @command('update|up|checkout|co',
5988 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5998 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5989 ('c', 'check', None, _('require clean working directory')),
5999 ('c', 'check', None, _('require clean working directory')),
5990 ('m', 'merge', None, _('merge uncommitted changes')),
6000 ('m', 'merge', None, _('merge uncommitted changes')),
5991 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6001 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5992 ('r', 'rev', '', _('revision'), _('REV'))
6002 ('r', 'rev', '', _('revision'), _('REV'))
5993 ] + mergetoolopts,
6003 ] + mergetoolopts,
5994 _('[-C|-c|-m] [-d DATE] [[-r] REV]'),
6004 _('[-C|-c|-m] [-d DATE] [[-r] REV]'),
5995 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
6005 helpcategory=command.CATEGORY_WORKING_DIRECTORY,
5996 helpbasic=True)
6006 helpbasic=True)
5997 def update(ui, repo, node=None, **opts):
6007 def update(ui, repo, node=None, **opts):
5998 """update working directory (or switch revisions)
6008 """update working directory (or switch revisions)
5999
6009
6000 Update the repository's working directory to the specified
6010 Update the repository's working directory to the specified
6001 changeset. If no changeset is specified, update to the tip of the
6011 changeset. If no changeset is specified, update to the tip of the
6002 current named branch and move the active bookmark (see :hg:`help
6012 current named branch and move the active bookmark (see :hg:`help
6003 bookmarks`).
6013 bookmarks`).
6004
6014
6005 Update sets the working directory's parent revision to the specified
6015 Update sets the working directory's parent revision to the specified
6006 changeset (see :hg:`help parents`).
6016 changeset (see :hg:`help parents`).
6007
6017
6008 If the changeset is not a descendant or ancestor of the working
6018 If the changeset is not a descendant or ancestor of the working
6009 directory's parent and there are uncommitted changes, the update is
6019 directory's parent and there are uncommitted changes, the update is
6010 aborted. With the -c/--check option, the working directory is checked
6020 aborted. With the -c/--check option, the working directory is checked
6011 for uncommitted changes; if none are found, the working directory is
6021 for uncommitted changes; if none are found, the working directory is
6012 updated to the specified changeset.
6022 updated to the specified changeset.
6013
6023
6014 .. container:: verbose
6024 .. container:: verbose
6015
6025
6016 The -C/--clean, -c/--check, and -m/--merge options control what
6026 The -C/--clean, -c/--check, and -m/--merge options control what
6017 happens if the working directory contains uncommitted changes.
6027 happens if the working directory contains uncommitted changes.
6018 At most of one of them can be specified.
6028 At most of one of them can be specified.
6019
6029
6020 1. If no option is specified, and if
6030 1. If no option is specified, and if
6021 the requested changeset is an ancestor or descendant of
6031 the requested changeset is an ancestor or descendant of
6022 the working directory's parent, the uncommitted changes
6032 the working directory's parent, the uncommitted changes
6023 are merged into the requested changeset and the merged
6033 are merged into the requested changeset and the merged
6024 result is left uncommitted. If the requested changeset is
6034 result is left uncommitted. If the requested changeset is
6025 not an ancestor or descendant (that is, it is on another
6035 not an ancestor or descendant (that is, it is on another
6026 branch), the update is aborted and the uncommitted changes
6036 branch), the update is aborted and the uncommitted changes
6027 are preserved.
6037 are preserved.
6028
6038
6029 2. With the -m/--merge option, the update is allowed even if the
6039 2. With the -m/--merge option, the update is allowed even if the
6030 requested changeset is not an ancestor or descendant of
6040 requested changeset is not an ancestor or descendant of
6031 the working directory's parent.
6041 the working directory's parent.
6032
6042
6033 3. With the -c/--check option, the update is aborted and the
6043 3. With the -c/--check option, the update is aborted and the
6034 uncommitted changes are preserved.
6044 uncommitted changes are preserved.
6035
6045
6036 4. With the -C/--clean option, uncommitted changes are discarded and
6046 4. With the -C/--clean option, uncommitted changes are discarded and
6037 the working directory is updated to the requested changeset.
6047 the working directory is updated to the requested changeset.
6038
6048
6039 To cancel an uncommitted merge (and lose your changes), use
6049 To cancel an uncommitted merge (and lose your changes), use
6040 :hg:`merge --abort`.
6050 :hg:`merge --abort`.
6041
6051
6042 Use null as the changeset to remove the working directory (like
6052 Use null as the changeset to remove the working directory (like
6043 :hg:`clone -U`).
6053 :hg:`clone -U`).
6044
6054
6045 If you want to revert just one file to an older revision, use
6055 If you want to revert just one file to an older revision, use
6046 :hg:`revert [-r REV] NAME`.
6056 :hg:`revert [-r REV] NAME`.
6047
6057
6048 See :hg:`help dates` for a list of formats valid for -d/--date.
6058 See :hg:`help dates` for a list of formats valid for -d/--date.
6049
6059
6050 Returns 0 on success, 1 if there are unresolved files.
6060 Returns 0 on success, 1 if there are unresolved files.
6051 """
6061 """
6052 rev = opts.get(r'rev')
6062 rev = opts.get(r'rev')
6053 date = opts.get(r'date')
6063 date = opts.get(r'date')
6054 clean = opts.get(r'clean')
6064 clean = opts.get(r'clean')
6055 check = opts.get(r'check')
6065 check = opts.get(r'check')
6056 merge = opts.get(r'merge')
6066 merge = opts.get(r'merge')
6057 if rev and node:
6067 if rev and node:
6058 raise error.Abort(_("please specify just one revision"))
6068 raise error.Abort(_("please specify just one revision"))
6059
6069
6060 if ui.configbool('commands', 'update.requiredest'):
6070 if ui.configbool('commands', 'update.requiredest'):
6061 if not node and not rev and not date:
6071 if not node and not rev and not date:
6062 raise error.Abort(_('you must specify a destination'),
6072 raise error.Abort(_('you must specify a destination'),
6063 hint=_('for example: hg update ".::"'))
6073 hint=_('for example: hg update ".::"'))
6064
6074
6065 if rev is None or rev == '':
6075 if rev is None or rev == '':
6066 rev = node
6076 rev = node
6067
6077
6068 if date and rev is not None:
6078 if date and rev is not None:
6069 raise error.Abort(_("you can't specify a revision and a date"))
6079 raise error.Abort(_("you can't specify a revision and a date"))
6070
6080
6071 if len([x for x in (clean, check, merge) if x]) > 1:
6081 if len([x for x in (clean, check, merge) if x]) > 1:
6072 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
6082 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
6073 "or -m/--merge"))
6083 "or -m/--merge"))
6074
6084
6075 updatecheck = None
6085 updatecheck = None
6076 if check:
6086 if check:
6077 updatecheck = 'abort'
6087 updatecheck = 'abort'
6078 elif merge:
6088 elif merge:
6079 updatecheck = 'none'
6089 updatecheck = 'none'
6080
6090
6081 with repo.wlock():
6091 with repo.wlock():
6082 cmdutil.clearunfinished(repo)
6092 cmdutil.clearunfinished(repo)
6083
6093
6084 if date:
6094 if date:
6085 rev = cmdutil.finddate(ui, repo, date)
6095 rev = cmdutil.finddate(ui, repo, date)
6086
6096
6087 # if we defined a bookmark, we have to remember the original name
6097 # if we defined a bookmark, we have to remember the original name
6088 brev = rev
6098 brev = rev
6089 if rev:
6099 if rev:
6090 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
6100 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
6091 ctx = scmutil.revsingle(repo, rev, rev)
6101 ctx = scmutil.revsingle(repo, rev, rev)
6092 rev = ctx.rev()
6102 rev = ctx.rev()
6093 hidden = ctx.hidden()
6103 hidden = ctx.hidden()
6094 overrides = {('ui', 'forcemerge'): opts.get(r'tool', '')}
6104 overrides = {('ui', 'forcemerge'): opts.get(r'tool', '')}
6095 with ui.configoverride(overrides, 'update'):
6105 with ui.configoverride(overrides, 'update'):
6096 ret = hg.updatetotally(ui, repo, rev, brev, clean=clean,
6106 ret = hg.updatetotally(ui, repo, rev, brev, clean=clean,
6097 updatecheck=updatecheck)
6107 updatecheck=updatecheck)
6098 if hidden:
6108 if hidden:
6099 ctxstr = ctx.hex()[:12]
6109 ctxstr = ctx.hex()[:12]
6100 ui.warn(_("updated to hidden changeset %s\n") % ctxstr)
6110 ui.warn(_("updated to hidden changeset %s\n") % ctxstr)
6101
6111
6102 if ctx.obsolete():
6112 if ctx.obsolete():
6103 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
6113 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
6104 ui.warn("(%s)\n" % obsfatemsg)
6114 ui.warn("(%s)\n" % obsfatemsg)
6105 return ret
6115 return ret
6106
6116
6107 @command('verify', [], helpcategory=command.CATEGORY_MAINTENANCE)
6117 @command('verify', [], helpcategory=command.CATEGORY_MAINTENANCE)
6108 def verify(ui, repo):
6118 def verify(ui, repo):
6109 """verify the integrity of the repository
6119 """verify the integrity of the repository
6110
6120
6111 Verify the integrity of the current repository.
6121 Verify the integrity of the current repository.
6112
6122
6113 This will perform an extensive check of the repository's
6123 This will perform an extensive check of the repository's
6114 integrity, validating the hashes and checksums of each entry in
6124 integrity, validating the hashes and checksums of each entry in
6115 the changelog, manifest, and tracked files, as well as the
6125 the changelog, manifest, and tracked files, as well as the
6116 integrity of their crosslinks and indices.
6126 integrity of their crosslinks and indices.
6117
6127
6118 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6128 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6119 for more information about recovery from corruption of the
6129 for more information about recovery from corruption of the
6120 repository.
6130 repository.
6121
6131
6122 Returns 0 on success, 1 if errors are encountered.
6132 Returns 0 on success, 1 if errors are encountered.
6123 """
6133 """
6124 return hg.verify(repo)
6134 return hg.verify(repo)
6125
6135
6126 @command(
6136 @command(
6127 'version', [] + formatteropts, helpcategory=command.CATEGORY_HELP,
6137 'version', [] + formatteropts, helpcategory=command.CATEGORY_HELP,
6128 norepo=True, intents={INTENT_READONLY})
6138 norepo=True, intents={INTENT_READONLY})
6129 def version_(ui, **opts):
6139 def version_(ui, **opts):
6130 """output version and copyright information
6140 """output version and copyright information
6131
6141
6132 .. container:: verbose
6142 .. container:: verbose
6133
6143
6134 Template:
6144 Template:
6135
6145
6136 The following keywords are supported. See also :hg:`help templates`.
6146 The following keywords are supported. See also :hg:`help templates`.
6137
6147
6138 :extensions: List of extensions.
6148 :extensions: List of extensions.
6139 :ver: String. Version number.
6149 :ver: String. Version number.
6140
6150
6141 And each entry of ``{extensions}`` provides the following sub-keywords
6151 And each entry of ``{extensions}`` provides the following sub-keywords
6142 in addition to ``{ver}``.
6152 in addition to ``{ver}``.
6143
6153
6144 :bundled: Boolean. True if included in the release.
6154 :bundled: Boolean. True if included in the release.
6145 :name: String. Extension name.
6155 :name: String. Extension name.
6146 """
6156 """
6147 opts = pycompat.byteskwargs(opts)
6157 opts = pycompat.byteskwargs(opts)
6148 if ui.verbose:
6158 if ui.verbose:
6149 ui.pager('version')
6159 ui.pager('version')
6150 fm = ui.formatter("version", opts)
6160 fm = ui.formatter("version", opts)
6151 fm.startitem()
6161 fm.startitem()
6152 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
6162 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
6153 util.version())
6163 util.version())
6154 license = _(
6164 license = _(
6155 "(see https://mercurial-scm.org for more information)\n"
6165 "(see https://mercurial-scm.org for more information)\n"
6156 "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
6166 "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
6157 "This is free software; see the source for copying conditions. "
6167 "This is free software; see the source for copying conditions. "
6158 "There is NO\nwarranty; "
6168 "There is NO\nwarranty; "
6159 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6169 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6160 )
6170 )
6161 if not ui.quiet:
6171 if not ui.quiet:
6162 fm.plain(license)
6172 fm.plain(license)
6163
6173
6164 if ui.verbose:
6174 if ui.verbose:
6165 fm.plain(_("\nEnabled extensions:\n\n"))
6175 fm.plain(_("\nEnabled extensions:\n\n"))
6166 # format names and versions into columns
6176 # format names and versions into columns
6167 names = []
6177 names = []
6168 vers = []
6178 vers = []
6169 isinternals = []
6179 isinternals = []
6170 for name, module in extensions.extensions():
6180 for name, module in extensions.extensions():
6171 names.append(name)
6181 names.append(name)
6172 vers.append(extensions.moduleversion(module) or None)
6182 vers.append(extensions.moduleversion(module) or None)
6173 isinternals.append(extensions.ismoduleinternal(module))
6183 isinternals.append(extensions.ismoduleinternal(module))
6174 fn = fm.nested("extensions", tmpl='{name}\n')
6184 fn = fm.nested("extensions", tmpl='{name}\n')
6175 if names:
6185 if names:
6176 namefmt = " %%-%ds " % max(len(n) for n in names)
6186 namefmt = " %%-%ds " % max(len(n) for n in names)
6177 places = [_("external"), _("internal")]
6187 places = [_("external"), _("internal")]
6178 for n, v, p in zip(names, vers, isinternals):
6188 for n, v, p in zip(names, vers, isinternals):
6179 fn.startitem()
6189 fn.startitem()
6180 fn.condwrite(ui.verbose, "name", namefmt, n)
6190 fn.condwrite(ui.verbose, "name", namefmt, n)
6181 if ui.verbose:
6191 if ui.verbose:
6182 fn.plain("%s " % places[p])
6192 fn.plain("%s " % places[p])
6183 fn.data(bundled=p)
6193 fn.data(bundled=p)
6184 fn.condwrite(ui.verbose and v, "ver", "%s", v)
6194 fn.condwrite(ui.verbose and v, "ver", "%s", v)
6185 if ui.verbose:
6195 if ui.verbose:
6186 fn.plain("\n")
6196 fn.plain("\n")
6187 fn.end()
6197 fn.end()
6188 fm.end()
6198 fm.end()
6189
6199
6190 def loadcmdtable(ui, name, cmdtable):
6200 def loadcmdtable(ui, name, cmdtable):
6191 """Load command functions from specified cmdtable
6201 """Load command functions from specified cmdtable
6192 """
6202 """
6193 cmdtable = cmdtable.copy()
6203 cmdtable = cmdtable.copy()
6194 for cmd in list(cmdtable):
6204 for cmd in list(cmdtable):
6195 if not cmd.startswith('^'):
6205 if not cmd.startswith('^'):
6196 continue
6206 continue
6197 ui.deprecwarn("old-style command registration '%s' in extension '%s'"
6207 ui.deprecwarn("old-style command registration '%s' in extension '%s'"
6198 % (cmd, name), '4.8')
6208 % (cmd, name), '4.8')
6199 entry = cmdtable.pop(cmd)
6209 entry = cmdtable.pop(cmd)
6200 entry[0].helpbasic = True
6210 entry[0].helpbasic = True
6201 cmdtable[cmd[1:]] = entry
6211 cmdtable[cmd[1:]] = entry
6202
6212
6203 overrides = [cmd for cmd in cmdtable if cmd in table]
6213 overrides = [cmd for cmd in cmdtable if cmd in table]
6204 if overrides:
6214 if overrides:
6205 ui.warn(_("extension '%s' overrides commands: %s\n")
6215 ui.warn(_("extension '%s' overrides commands: %s\n")
6206 % (name, " ".join(overrides)))
6216 % (name, " ".join(overrides)))
6207 table.update(cmdtable)
6217 table.update(cmdtable)
@@ -1,930 +1,942 b''
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3
3
4 Verify checking branch of nullrev before the cache is created doesnt crash
4 Verify checking branch of nullrev before the cache is created doesnt crash
5 $ hg log -r 'branch(.)' -T '{branch}\n'
5 $ hg log -r 'branch(.)' -T '{branch}\n'
6
6
7 Basic test
7 Basic test
8 $ echo 'root' >root
8 $ echo 'root' >root
9 $ hg add root
9 $ hg add root
10 $ hg commit -d '0 0' -m "Adding root node"
10 $ hg commit -d '0 0' -m "Adding root node"
11
11
12 $ echo 'a' >a
12 $ echo 'a' >a
13 $ hg add a
13 $ hg add a
14 $ hg branch a
14 $ hg branch a
15 marked working directory as branch a
15 marked working directory as branch a
16 (branches are permanent and global, did you want a bookmark?)
16 (branches are permanent and global, did you want a bookmark?)
17 $ hg commit -d '1 0' -m "Adding a branch"
17 $ hg commit -d '1 0' -m "Adding a branch"
18
18
19 $ hg branch q
19 $ hg branch q
20 marked working directory as branch q
20 marked working directory as branch q
21 $ echo 'aa' >a
21 $ echo 'aa' >a
22 $ hg branch -C
22 $ hg branch -C
23 reset working directory to branch a
23 reset working directory to branch a
24 $ hg commit -d '2 0' -m "Adding to a branch"
24 $ hg commit -d '2 0' -m "Adding to a branch"
25
25
26 $ hg update -C 0
26 $ hg update -C 0
27 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
27 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
28 $ echo 'b' >b
28 $ echo 'b' >b
29 $ hg add b
29 $ hg add b
30 $ hg branch b
30 $ hg branch b
31 marked working directory as branch b
31 marked working directory as branch b
32 $ hg commit -d '2 0' -m "Adding b branch"
32 $ hg commit -d '2 0' -m "Adding b branch"
33
33
34 $ echo 'bh1' >bh1
34 $ echo 'bh1' >bh1
35 $ hg add bh1
35 $ hg add bh1
36 $ hg commit -d '3 0' -m "Adding b branch head 1"
36 $ hg commit -d '3 0' -m "Adding b branch head 1"
37
37
38 $ hg update -C 2
38 $ hg update -C 2
39 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
39 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
40 $ echo 'bh2' >bh2
40 $ echo 'bh2' >bh2
41 $ hg add bh2
41 $ hg add bh2
42 $ hg commit -d '4 0' -m "Adding b branch head 2"
42 $ hg commit -d '4 0' -m "Adding b branch head 2"
43
43
44 $ echo 'c' >c
44 $ echo 'c' >c
45 $ hg add c
45 $ hg add c
46 $ hg branch c
46 $ hg branch c
47 marked working directory as branch c
47 marked working directory as branch c
48 $ hg commit -d '5 0' -m "Adding c branch"
48 $ hg commit -d '5 0' -m "Adding c branch"
49
49
50 reserved names
50 reserved names
51
51
52 $ hg branch tip
52 $ hg branch tip
53 abort: the name 'tip' is reserved
53 abort: the name 'tip' is reserved
54 [255]
54 [255]
55 $ hg branch null
55 $ hg branch null
56 abort: the name 'null' is reserved
56 abort: the name 'null' is reserved
57 [255]
57 [255]
58 $ hg branch .
58 $ hg branch .
59 abort: the name '.' is reserved
59 abort: the name '.' is reserved
60 [255]
60 [255]
61
61
62 invalid characters
62 invalid characters
63
63
64 $ hg branch 'foo:bar'
64 $ hg branch 'foo:bar'
65 abort: ':' cannot be used in a name
65 abort: ':' cannot be used in a name
66 [255]
66 [255]
67
67
68 $ hg branch 'foo
68 $ hg branch 'foo
69 > bar'
69 > bar'
70 abort: '\n' cannot be used in a name
70 abort: '\n' cannot be used in a name
71 [255]
71 [255]
72
72
73 trailing or leading spaces should be stripped before testing duplicates
73 trailing or leading spaces should be stripped before testing duplicates
74
74
75 $ hg branch 'b '
75 $ hg branch 'b '
76 abort: a branch of the same name already exists
76 abort: a branch of the same name already exists
77 (use 'hg update' to switch to it)
77 (use 'hg update' to switch to it)
78 [255]
78 [255]
79
79
80 $ hg branch ' b'
80 $ hg branch ' b'
81 abort: a branch of the same name already exists
81 abort: a branch of the same name already exists
82 (use 'hg update' to switch to it)
82 (use 'hg update' to switch to it)
83 [255]
83 [255]
84
84
85 verify update will accept invalid legacy branch names
85 verify update will accept invalid legacy branch names
86
86
87 $ hg init test-invalid-branch-name
87 $ hg init test-invalid-branch-name
88 $ cd test-invalid-branch-name
88 $ cd test-invalid-branch-name
89 $ hg unbundle -u "$TESTDIR"/bundles/test-invalid-branch-name.hg
89 $ hg unbundle -u "$TESTDIR"/bundles/test-invalid-branch-name.hg
90 adding changesets
90 adding changesets
91 adding manifests
91 adding manifests
92 adding file changes
92 adding file changes
93 added 3 changesets with 3 changes to 2 files
93 added 3 changesets with 3 changes to 2 files
94 new changesets f0e4c7f04036:33c2ceb9310b (3 drafts)
94 new changesets f0e4c7f04036:33c2ceb9310b (3 drafts)
95 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
95 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
96
96
97 $ hg update '"colon:test"'
97 $ hg update '"colon:test"'
98 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 $ cd ..
99 $ cd ..
100
100
101 $ echo 'd' >d
101 $ echo 'd' >d
102 $ hg add d
102 $ hg add d
103 $ hg branch 'a branch name much longer than the default justification used by branches'
103 $ hg branch 'a branch name much longer than the default justification used by branches'
104 marked working directory as branch a branch name much longer than the default justification used by branches
104 marked working directory as branch a branch name much longer than the default justification used by branches
105 $ hg commit -d '6 0' -m "Adding d branch"
105 $ hg commit -d '6 0' -m "Adding d branch"
106
106
107 $ hg branches
107 $ hg branches
108 a branch name much longer than the default justification used by branches 7:10ff5895aa57
108 a branch name much longer than the default justification used by branches 7:10ff5895aa57
109 b 4:aee39cd168d0
109 b 4:aee39cd168d0
110 c 6:589736a22561 (inactive)
110 c 6:589736a22561 (inactive)
111 a 5:d8cbc61dbaa6 (inactive)
111 a 5:d8cbc61dbaa6 (inactive)
112 default 0:19709c5a4e75 (inactive)
112 default 0:19709c5a4e75 (inactive)
113
113
114 -------
114 -------
115
115
116 $ hg branches -a
116 $ hg branches -a
117 a branch name much longer than the default justification used by branches 7:10ff5895aa57
117 a branch name much longer than the default justification used by branches 7:10ff5895aa57
118 b 4:aee39cd168d0
118 b 4:aee39cd168d0
119
119
120 --- Branch a
120 --- Branch a
121
121
122 $ hg log -b a
122 $ hg log -b a
123 changeset: 5:d8cbc61dbaa6
123 changeset: 5:d8cbc61dbaa6
124 branch: a
124 branch: a
125 parent: 2:881fe2b92ad0
125 parent: 2:881fe2b92ad0
126 user: test
126 user: test
127 date: Thu Jan 01 00:00:04 1970 +0000
127 date: Thu Jan 01 00:00:04 1970 +0000
128 summary: Adding b branch head 2
128 summary: Adding b branch head 2
129
129
130 changeset: 2:881fe2b92ad0
130 changeset: 2:881fe2b92ad0
131 branch: a
131 branch: a
132 user: test
132 user: test
133 date: Thu Jan 01 00:00:02 1970 +0000
133 date: Thu Jan 01 00:00:02 1970 +0000
134 summary: Adding to a branch
134 summary: Adding to a branch
135
135
136 changeset: 1:dd6b440dd85a
136 changeset: 1:dd6b440dd85a
137 branch: a
137 branch: a
138 user: test
138 user: test
139 date: Thu Jan 01 00:00:01 1970 +0000
139 date: Thu Jan 01 00:00:01 1970 +0000
140 summary: Adding a branch
140 summary: Adding a branch
141
141
142
142
143 ---- Branch b
143 ---- Branch b
144
144
145 $ hg log -b b
145 $ hg log -b b
146 changeset: 4:aee39cd168d0
146 changeset: 4:aee39cd168d0
147 branch: b
147 branch: b
148 user: test
148 user: test
149 date: Thu Jan 01 00:00:03 1970 +0000
149 date: Thu Jan 01 00:00:03 1970 +0000
150 summary: Adding b branch head 1
150 summary: Adding b branch head 1
151
151
152 changeset: 3:ac22033332d1
152 changeset: 3:ac22033332d1
153 branch: b
153 branch: b
154 parent: 0:19709c5a4e75
154 parent: 0:19709c5a4e75
155 user: test
155 user: test
156 date: Thu Jan 01 00:00:02 1970 +0000
156 date: Thu Jan 01 00:00:02 1970 +0000
157 summary: Adding b branch
157 summary: Adding b branch
158
158
159
159
160 ---- going to test branch listing by rev
161 $ hg branches -r0
162 default 0:19709c5a4e75 (inactive)
163 $ hg branches -qr0
164 default
165 --- now more than one rev
166 $ hg branches -r2:5
167 b 4:aee39cd168d0
168 a 5:d8cbc61dbaa6 (inactive)
169 $ hg branches -qr2:5
170 b
171 a
160 ---- going to test branch closing
172 ---- going to test branch closing
161
173
162 $ hg branches
174 $ hg branches
163 a branch name much longer than the default justification used by branches 7:10ff5895aa57
175 a branch name much longer than the default justification used by branches 7:10ff5895aa57
164 b 4:aee39cd168d0
176 b 4:aee39cd168d0
165 c 6:589736a22561 (inactive)
177 c 6:589736a22561 (inactive)
166 a 5:d8cbc61dbaa6 (inactive)
178 a 5:d8cbc61dbaa6 (inactive)
167 default 0:19709c5a4e75 (inactive)
179 default 0:19709c5a4e75 (inactive)
168 $ hg up -C b
180 $ hg up -C b
169 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
181 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
170 $ echo 'xxx1' >> b
182 $ echo 'xxx1' >> b
171 $ hg commit -d '7 0' -m 'adding cset to branch b'
183 $ hg commit -d '7 0' -m 'adding cset to branch b'
172 $ hg up -C aee39cd168d0
184 $ hg up -C aee39cd168d0
173 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
185 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 $ echo 'xxx2' >> b
186 $ echo 'xxx2' >> b
175 $ hg commit -d '8 0' -m 'adding head to branch b'
187 $ hg commit -d '8 0' -m 'adding head to branch b'
176 created new head
188 created new head
177 $ echo 'xxx3' >> b
189 $ echo 'xxx3' >> b
178 $ hg commit -d '9 0' -m 'adding another cset to branch b'
190 $ hg commit -d '9 0' -m 'adding another cset to branch b'
179 $ hg branches
191 $ hg branches
180 b 10:bfbe841b666e
192 b 10:bfbe841b666e
181 a branch name much longer than the default justification used by branches 7:10ff5895aa57
193 a branch name much longer than the default justification used by branches 7:10ff5895aa57
182 c 6:589736a22561 (inactive)
194 c 6:589736a22561 (inactive)
183 a 5:d8cbc61dbaa6 (inactive)
195 a 5:d8cbc61dbaa6 (inactive)
184 default 0:19709c5a4e75 (inactive)
196 default 0:19709c5a4e75 (inactive)
185 $ hg heads --closed
197 $ hg heads --closed
186 changeset: 10:bfbe841b666e
198 changeset: 10:bfbe841b666e
187 branch: b
199 branch: b
188 tag: tip
200 tag: tip
189 user: test
201 user: test
190 date: Thu Jan 01 00:00:09 1970 +0000
202 date: Thu Jan 01 00:00:09 1970 +0000
191 summary: adding another cset to branch b
203 summary: adding another cset to branch b
192
204
193 changeset: 8:eebb944467c9
205 changeset: 8:eebb944467c9
194 branch: b
206 branch: b
195 parent: 4:aee39cd168d0
207 parent: 4:aee39cd168d0
196 user: test
208 user: test
197 date: Thu Jan 01 00:00:07 1970 +0000
209 date: Thu Jan 01 00:00:07 1970 +0000
198 summary: adding cset to branch b
210 summary: adding cset to branch b
199
211
200 changeset: 7:10ff5895aa57
212 changeset: 7:10ff5895aa57
201 branch: a branch name much longer than the default justification used by branches
213 branch: a branch name much longer than the default justification used by branches
202 user: test
214 user: test
203 date: Thu Jan 01 00:00:06 1970 +0000
215 date: Thu Jan 01 00:00:06 1970 +0000
204 summary: Adding d branch
216 summary: Adding d branch
205
217
206 changeset: 6:589736a22561
218 changeset: 6:589736a22561
207 branch: c
219 branch: c
208 user: test
220 user: test
209 date: Thu Jan 01 00:00:05 1970 +0000
221 date: Thu Jan 01 00:00:05 1970 +0000
210 summary: Adding c branch
222 summary: Adding c branch
211
223
212 changeset: 5:d8cbc61dbaa6
224 changeset: 5:d8cbc61dbaa6
213 branch: a
225 branch: a
214 parent: 2:881fe2b92ad0
226 parent: 2:881fe2b92ad0
215 user: test
227 user: test
216 date: Thu Jan 01 00:00:04 1970 +0000
228 date: Thu Jan 01 00:00:04 1970 +0000
217 summary: Adding b branch head 2
229 summary: Adding b branch head 2
218
230
219 changeset: 0:19709c5a4e75
231 changeset: 0:19709c5a4e75
220 user: test
232 user: test
221 date: Thu Jan 01 00:00:00 1970 +0000
233 date: Thu Jan 01 00:00:00 1970 +0000
222 summary: Adding root node
234 summary: Adding root node
223
235
224 $ hg heads
236 $ hg heads
225 changeset: 10:bfbe841b666e
237 changeset: 10:bfbe841b666e
226 branch: b
238 branch: b
227 tag: tip
239 tag: tip
228 user: test
240 user: test
229 date: Thu Jan 01 00:00:09 1970 +0000
241 date: Thu Jan 01 00:00:09 1970 +0000
230 summary: adding another cset to branch b
242 summary: adding another cset to branch b
231
243
232 changeset: 8:eebb944467c9
244 changeset: 8:eebb944467c9
233 branch: b
245 branch: b
234 parent: 4:aee39cd168d0
246 parent: 4:aee39cd168d0
235 user: test
247 user: test
236 date: Thu Jan 01 00:00:07 1970 +0000
248 date: Thu Jan 01 00:00:07 1970 +0000
237 summary: adding cset to branch b
249 summary: adding cset to branch b
238
250
239 changeset: 7:10ff5895aa57
251 changeset: 7:10ff5895aa57
240 branch: a branch name much longer than the default justification used by branches
252 branch: a branch name much longer than the default justification used by branches
241 user: test
253 user: test
242 date: Thu Jan 01 00:00:06 1970 +0000
254 date: Thu Jan 01 00:00:06 1970 +0000
243 summary: Adding d branch
255 summary: Adding d branch
244
256
245 changeset: 6:589736a22561
257 changeset: 6:589736a22561
246 branch: c
258 branch: c
247 user: test
259 user: test
248 date: Thu Jan 01 00:00:05 1970 +0000
260 date: Thu Jan 01 00:00:05 1970 +0000
249 summary: Adding c branch
261 summary: Adding c branch
250
262
251 changeset: 5:d8cbc61dbaa6
263 changeset: 5:d8cbc61dbaa6
252 branch: a
264 branch: a
253 parent: 2:881fe2b92ad0
265 parent: 2:881fe2b92ad0
254 user: test
266 user: test
255 date: Thu Jan 01 00:00:04 1970 +0000
267 date: Thu Jan 01 00:00:04 1970 +0000
256 summary: Adding b branch head 2
268 summary: Adding b branch head 2
257
269
258 changeset: 0:19709c5a4e75
270 changeset: 0:19709c5a4e75
259 user: test
271 user: test
260 date: Thu Jan 01 00:00:00 1970 +0000
272 date: Thu Jan 01 00:00:00 1970 +0000
261 summary: Adding root node
273 summary: Adding root node
262
274
263 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
275 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
264 $ hg branches -a
276 $ hg branches -a
265 b 8:eebb944467c9
277 b 8:eebb944467c9
266 a branch name much longer than the default justification used by branches 7:10ff5895aa57
278 a branch name much longer than the default justification used by branches 7:10ff5895aa57
267 $ hg up -C b
279 $ hg up -C b
268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
281 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
270 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
282 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
271 abort: can only close branch heads
283 abort: can only close branch heads
272 [255]
284 [255]
273
285
274 $ hg log -r tip --debug
286 $ hg log -r tip --debug
275 changeset: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
287 changeset: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
276 branch: b
288 branch: b
277 tag: tip
289 tag: tip
278 phase: draft
290 phase: draft
279 parent: 8:eebb944467c9fb9651ed232aeaf31b3c0a7fc6c1
291 parent: 8:eebb944467c9fb9651ed232aeaf31b3c0a7fc6c1
280 parent: -1:0000000000000000000000000000000000000000
292 parent: -1:0000000000000000000000000000000000000000
281 manifest: 8:6f9ed32d2b310e391a4f107d5f0f071df785bfee
293 manifest: 8:6f9ed32d2b310e391a4f107d5f0f071df785bfee
282 user: test
294 user: test
283 date: Thu Jan 01 00:00:09 1970 +0000
295 date: Thu Jan 01 00:00:09 1970 +0000
284 extra: branch=b
296 extra: branch=b
285 extra: close=1
297 extra: close=1
286 description:
298 description:
287 close this part branch too
299 close this part branch too
288
300
289
301
290 --- b branch should be inactive
302 --- b branch should be inactive
291
303
292 $ hg branches
304 $ hg branches
293 a branch name much longer than the default justification used by branches 7:10ff5895aa57
305 a branch name much longer than the default justification used by branches 7:10ff5895aa57
294 c 6:589736a22561 (inactive)
306 c 6:589736a22561 (inactive)
295 a 5:d8cbc61dbaa6 (inactive)
307 a 5:d8cbc61dbaa6 (inactive)
296 default 0:19709c5a4e75 (inactive)
308 default 0:19709c5a4e75 (inactive)
297 $ hg branches -c
309 $ hg branches -c
298 a branch name much longer than the default justification used by branches 7:10ff5895aa57
310 a branch name much longer than the default justification used by branches 7:10ff5895aa57
299 b 12:e3d49c0575d8 (closed)
311 b 12:e3d49c0575d8 (closed)
300 c 6:589736a22561 (inactive)
312 c 6:589736a22561 (inactive)
301 a 5:d8cbc61dbaa6 (inactive)
313 a 5:d8cbc61dbaa6 (inactive)
302 default 0:19709c5a4e75 (inactive)
314 default 0:19709c5a4e75 (inactive)
303 $ hg branches -a
315 $ hg branches -a
304 a branch name much longer than the default justification used by branches 7:10ff5895aa57
316 a branch name much longer than the default justification used by branches 7:10ff5895aa57
305 $ hg branches -q
317 $ hg branches -q
306 a branch name much longer than the default justification used by branches
318 a branch name much longer than the default justification used by branches
307 c
319 c
308 a
320 a
309 default
321 default
310 $ hg heads b
322 $ hg heads b
311 no open branch heads found on branches b
323 no open branch heads found on branches b
312 [1]
324 [1]
313 $ hg heads --closed b
325 $ hg heads --closed b
314 changeset: 12:e3d49c0575d8
326 changeset: 12:e3d49c0575d8
315 branch: b
327 branch: b
316 tag: tip
328 tag: tip
317 parent: 8:eebb944467c9
329 parent: 8:eebb944467c9
318 user: test
330 user: test
319 date: Thu Jan 01 00:00:09 1970 +0000
331 date: Thu Jan 01 00:00:09 1970 +0000
320 summary: close this part branch too
332 summary: close this part branch too
321
333
322 changeset: 11:d3f163457ebf
334 changeset: 11:d3f163457ebf
323 branch: b
335 branch: b
324 user: test
336 user: test
325 date: Thu Jan 01 00:00:09 1970 +0000
337 date: Thu Jan 01 00:00:09 1970 +0000
326 summary: prune bad branch
338 summary: prune bad branch
327
339
328 $ echo 'xxx4' >> b
340 $ echo 'xxx4' >> b
329 $ hg commit -d '9 0' -m 'reopen branch with a change'
341 $ hg commit -d '9 0' -m 'reopen branch with a change'
330 reopening closed branch head 12
342 reopening closed branch head 12
331
343
332 --- branch b is back in action
344 --- branch b is back in action
333
345
334 $ hg branches -a
346 $ hg branches -a
335 b 13:e23b5505d1ad
347 b 13:e23b5505d1ad
336 a branch name much longer than the default justification used by branches 7:10ff5895aa57
348 a branch name much longer than the default justification used by branches 7:10ff5895aa57
337
349
338 ---- test heads listings
350 ---- test heads listings
339
351
340 $ hg heads
352 $ hg heads
341 changeset: 13:e23b5505d1ad
353 changeset: 13:e23b5505d1ad
342 branch: b
354 branch: b
343 tag: tip
355 tag: tip
344 user: test
356 user: test
345 date: Thu Jan 01 00:00:09 1970 +0000
357 date: Thu Jan 01 00:00:09 1970 +0000
346 summary: reopen branch with a change
358 summary: reopen branch with a change
347
359
348 changeset: 7:10ff5895aa57
360 changeset: 7:10ff5895aa57
349 branch: a branch name much longer than the default justification used by branches
361 branch: a branch name much longer than the default justification used by branches
350 user: test
362 user: test
351 date: Thu Jan 01 00:00:06 1970 +0000
363 date: Thu Jan 01 00:00:06 1970 +0000
352 summary: Adding d branch
364 summary: Adding d branch
353
365
354 changeset: 6:589736a22561
366 changeset: 6:589736a22561
355 branch: c
367 branch: c
356 user: test
368 user: test
357 date: Thu Jan 01 00:00:05 1970 +0000
369 date: Thu Jan 01 00:00:05 1970 +0000
358 summary: Adding c branch
370 summary: Adding c branch
359
371
360 changeset: 5:d8cbc61dbaa6
372 changeset: 5:d8cbc61dbaa6
361 branch: a
373 branch: a
362 parent: 2:881fe2b92ad0
374 parent: 2:881fe2b92ad0
363 user: test
375 user: test
364 date: Thu Jan 01 00:00:04 1970 +0000
376 date: Thu Jan 01 00:00:04 1970 +0000
365 summary: Adding b branch head 2
377 summary: Adding b branch head 2
366
378
367 changeset: 0:19709c5a4e75
379 changeset: 0:19709c5a4e75
368 user: test
380 user: test
369 date: Thu Jan 01 00:00:00 1970 +0000
381 date: Thu Jan 01 00:00:00 1970 +0000
370 summary: Adding root node
382 summary: Adding root node
371
383
372
384
373 branch default
385 branch default
374
386
375 $ hg heads default
387 $ hg heads default
376 changeset: 0:19709c5a4e75
388 changeset: 0:19709c5a4e75
377 user: test
389 user: test
378 date: Thu Jan 01 00:00:00 1970 +0000
390 date: Thu Jan 01 00:00:00 1970 +0000
379 summary: Adding root node
391 summary: Adding root node
380
392
381
393
382 branch a
394 branch a
383
395
384 $ hg heads a
396 $ hg heads a
385 changeset: 5:d8cbc61dbaa6
397 changeset: 5:d8cbc61dbaa6
386 branch: a
398 branch: a
387 parent: 2:881fe2b92ad0
399 parent: 2:881fe2b92ad0
388 user: test
400 user: test
389 date: Thu Jan 01 00:00:04 1970 +0000
401 date: Thu Jan 01 00:00:04 1970 +0000
390 summary: Adding b branch head 2
402 summary: Adding b branch head 2
391
403
392 $ hg heads --active a
404 $ hg heads --active a
393 no open branch heads found on branches a
405 no open branch heads found on branches a
394 [1]
406 [1]
395
407
396 branch b
408 branch b
397
409
398 $ hg heads b
410 $ hg heads b
399 changeset: 13:e23b5505d1ad
411 changeset: 13:e23b5505d1ad
400 branch: b
412 branch: b
401 tag: tip
413 tag: tip
402 user: test
414 user: test
403 date: Thu Jan 01 00:00:09 1970 +0000
415 date: Thu Jan 01 00:00:09 1970 +0000
404 summary: reopen branch with a change
416 summary: reopen branch with a change
405
417
406 $ hg heads --closed b
418 $ hg heads --closed b
407 changeset: 13:e23b5505d1ad
419 changeset: 13:e23b5505d1ad
408 branch: b
420 branch: b
409 tag: tip
421 tag: tip
410 user: test
422 user: test
411 date: Thu Jan 01 00:00:09 1970 +0000
423 date: Thu Jan 01 00:00:09 1970 +0000
412 summary: reopen branch with a change
424 summary: reopen branch with a change
413
425
414 changeset: 11:d3f163457ebf
426 changeset: 11:d3f163457ebf
415 branch: b
427 branch: b
416 user: test
428 user: test
417 date: Thu Jan 01 00:00:09 1970 +0000
429 date: Thu Jan 01 00:00:09 1970 +0000
418 summary: prune bad branch
430 summary: prune bad branch
419
431
420
432
421 reclose branch
433 reclose branch
422
434
423 $ hg up -C c
435 $ hg up -C c
424 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
436 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
425 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
437 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
426 $ hg branches
438 $ hg branches
427 b 13:e23b5505d1ad
439 b 13:e23b5505d1ad
428 a branch name much longer than the default justification used by branches 7:10ff5895aa57
440 a branch name much longer than the default justification used by branches 7:10ff5895aa57
429 a 5:d8cbc61dbaa6 (inactive)
441 a 5:d8cbc61dbaa6 (inactive)
430 default 0:19709c5a4e75 (inactive)
442 default 0:19709c5a4e75 (inactive)
431 $ hg branches --closed
443 $ hg branches --closed
432 b 13:e23b5505d1ad
444 b 13:e23b5505d1ad
433 a branch name much longer than the default justification used by branches 7:10ff5895aa57
445 a branch name much longer than the default justification used by branches 7:10ff5895aa57
434 c 14:f894c25619d3 (closed)
446 c 14:f894c25619d3 (closed)
435 a 5:d8cbc61dbaa6 (inactive)
447 a 5:d8cbc61dbaa6 (inactive)
436 default 0:19709c5a4e75 (inactive)
448 default 0:19709c5a4e75 (inactive)
437
449
438 multihead branch
450 multihead branch
439
451
440 $ hg up -C default
452 $ hg up -C default
441 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
453 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
442 $ hg branch m
454 $ hg branch m
443 marked working directory as branch m
455 marked working directory as branch m
444 $ touch m
456 $ touch m
445 $ hg add m
457 $ hg add m
446 $ hg commit -d '10 0' -m 'multihead base'
458 $ hg commit -d '10 0' -m 'multihead base'
447 $ echo "m1" >m
459 $ echo "m1" >m
448 $ hg commit -d '10 0' -m 'head 1'
460 $ hg commit -d '10 0' -m 'head 1'
449 $ hg up -C '.^'
461 $ hg up -C '.^'
450 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
451 $ echo "m2" >m
463 $ echo "m2" >m
452 $ hg commit -d '10 0' -m 'head 2'
464 $ hg commit -d '10 0' -m 'head 2'
453 created new head
465 created new head
454 $ hg log -b m
466 $ hg log -b m
455 changeset: 17:df343b0df04f
467 changeset: 17:df343b0df04f
456 branch: m
468 branch: m
457 tag: tip
469 tag: tip
458 parent: 15:f3447637f53e
470 parent: 15:f3447637f53e
459 user: test
471 user: test
460 date: Thu Jan 01 00:00:10 1970 +0000
472 date: Thu Jan 01 00:00:10 1970 +0000
461 summary: head 2
473 summary: head 2
462
474
463 changeset: 16:a58ca5d3bdf3
475 changeset: 16:a58ca5d3bdf3
464 branch: m
476 branch: m
465 user: test
477 user: test
466 date: Thu Jan 01 00:00:10 1970 +0000
478 date: Thu Jan 01 00:00:10 1970 +0000
467 summary: head 1
479 summary: head 1
468
480
469 changeset: 15:f3447637f53e
481 changeset: 15:f3447637f53e
470 branch: m
482 branch: m
471 parent: 0:19709c5a4e75
483 parent: 0:19709c5a4e75
472 user: test
484 user: test
473 date: Thu Jan 01 00:00:10 1970 +0000
485 date: Thu Jan 01 00:00:10 1970 +0000
474 summary: multihead base
486 summary: multihead base
475
487
476 $ hg heads --topo m
488 $ hg heads --topo m
477 changeset: 17:df343b0df04f
489 changeset: 17:df343b0df04f
478 branch: m
490 branch: m
479 tag: tip
491 tag: tip
480 parent: 15:f3447637f53e
492 parent: 15:f3447637f53e
481 user: test
493 user: test
482 date: Thu Jan 01 00:00:10 1970 +0000
494 date: Thu Jan 01 00:00:10 1970 +0000
483 summary: head 2
495 summary: head 2
484
496
485 changeset: 16:a58ca5d3bdf3
497 changeset: 16:a58ca5d3bdf3
486 branch: m
498 branch: m
487 user: test
499 user: test
488 date: Thu Jan 01 00:00:10 1970 +0000
500 date: Thu Jan 01 00:00:10 1970 +0000
489 summary: head 1
501 summary: head 1
490
502
491 $ hg branches
503 $ hg branches
492 m 17:df343b0df04f
504 m 17:df343b0df04f
493 b 13:e23b5505d1ad
505 b 13:e23b5505d1ad
494 a branch name much longer than the default justification used by branches 7:10ff5895aa57
506 a branch name much longer than the default justification used by branches 7:10ff5895aa57
495 a 5:d8cbc61dbaa6 (inactive)
507 a 5:d8cbc61dbaa6 (inactive)
496 default 0:19709c5a4e75 (inactive)
508 default 0:19709c5a4e75 (inactive)
497
509
498 partially merge multihead branch
510 partially merge multihead branch
499
511
500 $ hg up -C default
512 $ hg up -C default
501 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
513 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
502 $ hg branch md
514 $ hg branch md
503 marked working directory as branch md
515 marked working directory as branch md
504 $ hg merge m
516 $ hg merge m
505 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
517 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
506 (branch merge, don't forget to commit)
518 (branch merge, don't forget to commit)
507 $ hg commit -d '11 0' -m 'merge head 2'
519 $ hg commit -d '11 0' -m 'merge head 2'
508 $ hg heads --topo m
520 $ hg heads --topo m
509 changeset: 16:a58ca5d3bdf3
521 changeset: 16:a58ca5d3bdf3
510 branch: m
522 branch: m
511 user: test
523 user: test
512 date: Thu Jan 01 00:00:10 1970 +0000
524 date: Thu Jan 01 00:00:10 1970 +0000
513 summary: head 1
525 summary: head 1
514
526
515 $ hg branches
527 $ hg branches
516 md 18:c914c99f1fbb
528 md 18:c914c99f1fbb
517 m 17:df343b0df04f
529 m 17:df343b0df04f
518 b 13:e23b5505d1ad
530 b 13:e23b5505d1ad
519 a branch name much longer than the default justification used by branches 7:10ff5895aa57
531 a branch name much longer than the default justification used by branches 7:10ff5895aa57
520 a 5:d8cbc61dbaa6 (inactive)
532 a 5:d8cbc61dbaa6 (inactive)
521 default 0:19709c5a4e75 (inactive)
533 default 0:19709c5a4e75 (inactive)
522
534
523 partially close multihead branch
535 partially close multihead branch
524
536
525 $ hg up -C a58ca5d3bdf3
537 $ hg up -C a58ca5d3bdf3
526 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
538 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
527 $ hg commit -d '12 0' -m 'close head 1' --close-branch
539 $ hg commit -d '12 0' -m 'close head 1' --close-branch
528 $ hg heads --topo m
540 $ hg heads --topo m
529 changeset: 19:cd21a80baa3d
541 changeset: 19:cd21a80baa3d
530 branch: m
542 branch: m
531 tag: tip
543 tag: tip
532 parent: 16:a58ca5d3bdf3
544 parent: 16:a58ca5d3bdf3
533 user: test
545 user: test
534 date: Thu Jan 01 00:00:12 1970 +0000
546 date: Thu Jan 01 00:00:12 1970 +0000
535 summary: close head 1
547 summary: close head 1
536
548
537 $ hg branches
549 $ hg branches
538 md 18:c914c99f1fbb
550 md 18:c914c99f1fbb
539 b 13:e23b5505d1ad
551 b 13:e23b5505d1ad
540 a branch name much longer than the default justification used by branches 7:10ff5895aa57
552 a branch name much longer than the default justification used by branches 7:10ff5895aa57
541 m 17:df343b0df04f (inactive)
553 m 17:df343b0df04f (inactive)
542 a 5:d8cbc61dbaa6 (inactive)
554 a 5:d8cbc61dbaa6 (inactive)
543 default 0:19709c5a4e75 (inactive)
555 default 0:19709c5a4e75 (inactive)
544
556
545 default branch colors:
557 default branch colors:
546
558
547 $ cat <<EOF >> $HGRCPATH
559 $ cat <<EOF >> $HGRCPATH
548 > [extensions]
560 > [extensions]
549 > color =
561 > color =
550 > [color]
562 > [color]
551 > mode = ansi
563 > mode = ansi
552 > EOF
564 > EOF
553
565
554 $ hg up -C b
566 $ hg up -C b
555 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
567 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
556 $ hg branches --color=always
568 $ hg branches --color=always
557 \x1b[0;0mmd\x1b[0m\x1b[0;33m 18:c914c99f1fbb\x1b[0m (esc)
569 \x1b[0;0mmd\x1b[0m\x1b[0;33m 18:c914c99f1fbb\x1b[0m (esc)
558 \x1b[0;32mb\x1b[0m\x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
570 \x1b[0;32mb\x1b[0m\x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
559 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;33m 7:10ff5895aa57\x1b[0m (esc)
571 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;33m 7:10ff5895aa57\x1b[0m (esc)
560 \x1b[0;0mm\x1b[0m\x1b[0;33m 17:df343b0df04f\x1b[0m (inactive) (esc)
572 \x1b[0;0mm\x1b[0m\x1b[0;33m 17:df343b0df04f\x1b[0m (inactive) (esc)
561 \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
573 \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
562 \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
574 \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
563
575
564 default closed branch color:
576 default closed branch color:
565
577
566 $ hg branches --color=always --closed
578 $ hg branches --color=always --closed
567 \x1b[0;0mmd\x1b[0m\x1b[0;33m 18:c914c99f1fbb\x1b[0m (esc)
579 \x1b[0;0mmd\x1b[0m\x1b[0;33m 18:c914c99f1fbb\x1b[0m (esc)
568 \x1b[0;32mb\x1b[0m\x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
580 \x1b[0;32mb\x1b[0m\x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
569 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;33m 7:10ff5895aa57\x1b[0m (esc)
581 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;33m 7:10ff5895aa57\x1b[0m (esc)
570 \x1b[0;0mm\x1b[0m\x1b[0;33m 17:df343b0df04f\x1b[0m (inactive) (esc)
582 \x1b[0;0mm\x1b[0m\x1b[0;33m 17:df343b0df04f\x1b[0m (inactive) (esc)
571 \x1b[0;30;1mc\x1b[0m\x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
583 \x1b[0;30;1mc\x1b[0m\x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
572 \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
584 \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
573 \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
585 \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
574
586
575 $ cat <<EOF >> $HGRCPATH
587 $ cat <<EOF >> $HGRCPATH
576 > [extensions]
588 > [extensions]
577 > color =
589 > color =
578 > [color]
590 > [color]
579 > branches.active = green
591 > branches.active = green
580 > branches.closed = blue
592 > branches.closed = blue
581 > branches.current = red
593 > branches.current = red
582 > branches.inactive = magenta
594 > branches.inactive = magenta
583 > log.changeset = cyan
595 > log.changeset = cyan
584 > EOF
596 > EOF
585
597
586 custom branch colors:
598 custom branch colors:
587
599
588 $ hg branches --color=always
600 $ hg branches --color=always
589 \x1b[0;32mmd\x1b[0m\x1b[0;36m 18:c914c99f1fbb\x1b[0m (esc)
601 \x1b[0;32mmd\x1b[0m\x1b[0;36m 18:c914c99f1fbb\x1b[0m (esc)
590 \x1b[0;31mb\x1b[0m\x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
602 \x1b[0;31mb\x1b[0m\x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
591 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;36m 7:10ff5895aa57\x1b[0m (esc)
603 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;36m 7:10ff5895aa57\x1b[0m (esc)
592 \x1b[0;35mm\x1b[0m\x1b[0;36m 17:df343b0df04f\x1b[0m (inactive) (esc)
604 \x1b[0;35mm\x1b[0m\x1b[0;36m 17:df343b0df04f\x1b[0m (inactive) (esc)
593 \x1b[0;35ma\x1b[0m\x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
605 \x1b[0;35ma\x1b[0m\x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
594 \x1b[0;35mdefault\x1b[0m\x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
606 \x1b[0;35mdefault\x1b[0m\x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
595
607
596 custom closed branch color:
608 custom closed branch color:
597
609
598 $ hg branches --color=always --closed
610 $ hg branches --color=always --closed
599 \x1b[0;32mmd\x1b[0m\x1b[0;36m 18:c914c99f1fbb\x1b[0m (esc)
611 \x1b[0;32mmd\x1b[0m\x1b[0;36m 18:c914c99f1fbb\x1b[0m (esc)
600 \x1b[0;31mb\x1b[0m\x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
612 \x1b[0;31mb\x1b[0m\x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
601 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;36m 7:10ff5895aa57\x1b[0m (esc)
613 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;36m 7:10ff5895aa57\x1b[0m (esc)
602 \x1b[0;35mm\x1b[0m\x1b[0;36m 17:df343b0df04f\x1b[0m (inactive) (esc)
614 \x1b[0;35mm\x1b[0m\x1b[0;36m 17:df343b0df04f\x1b[0m (inactive) (esc)
603 \x1b[0;34mc\x1b[0m\x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
615 \x1b[0;34mc\x1b[0m\x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
604 \x1b[0;35ma\x1b[0m\x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
616 \x1b[0;35ma\x1b[0m\x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
605 \x1b[0;35mdefault\x1b[0m\x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
617 \x1b[0;35mdefault\x1b[0m\x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
606
618
607 template output:
619 template output:
608
620
609 $ hg branches -Tjson --closed
621 $ hg branches -Tjson --closed
610 [
622 [
611 {
623 {
612 "active": true,
624 "active": true,
613 "branch": "md",
625 "branch": "md",
614 "closed": false,
626 "closed": false,
615 "current": false,
627 "current": false,
616 "node": "c914c99f1fbb2b1d785a0a939ed3f67275df18e9",
628 "node": "c914c99f1fbb2b1d785a0a939ed3f67275df18e9",
617 "rev": 18
629 "rev": 18
618 },
630 },
619 {
631 {
620 "active": true,
632 "active": true,
621 "branch": "b",
633 "branch": "b",
622 "closed": false,
634 "closed": false,
623 "current": true,
635 "current": true,
624 "node": "e23b5505d1ad24aab6f84fd8c7cb8cd8e5e93be0",
636 "node": "e23b5505d1ad24aab6f84fd8c7cb8cd8e5e93be0",
625 "rev": 13
637 "rev": 13
626 },
638 },
627 {
639 {
628 "active": true,
640 "active": true,
629 "branch": "a branch name much longer than the default justification used by branches",
641 "branch": "a branch name much longer than the default justification used by branches",
630 "closed": false,
642 "closed": false,
631 "current": false,
643 "current": false,
632 "node": "10ff5895aa5793bd378da574af8cec8ea408d831",
644 "node": "10ff5895aa5793bd378da574af8cec8ea408d831",
633 "rev": 7
645 "rev": 7
634 },
646 },
635 {
647 {
636 "active": false,
648 "active": false,
637 "branch": "m",
649 "branch": "m",
638 "closed": false,
650 "closed": false,
639 "current": false,
651 "current": false,
640 "node": "df343b0df04feb2a946cd4b6e9520e552fef14ee",
652 "node": "df343b0df04feb2a946cd4b6e9520e552fef14ee",
641 "rev": 17
653 "rev": 17
642 },
654 },
643 {
655 {
644 "active": false,
656 "active": false,
645 "branch": "c",
657 "branch": "c",
646 "closed": true,
658 "closed": true,
647 "current": false,
659 "current": false,
648 "node": "f894c25619d3f1484639d81be950e0a07bc6f1f6",
660 "node": "f894c25619d3f1484639d81be950e0a07bc6f1f6",
649 "rev": 14
661 "rev": 14
650 },
662 },
651 {
663 {
652 "active": false,
664 "active": false,
653 "branch": "a",
665 "branch": "a",
654 "closed": false,
666 "closed": false,
655 "current": false,
667 "current": false,
656 "node": "d8cbc61dbaa6dc817175d1e301eecb863f280832",
668 "node": "d8cbc61dbaa6dc817175d1e301eecb863f280832",
657 "rev": 5
669 "rev": 5
658 },
670 },
659 {
671 {
660 "active": false,
672 "active": false,
661 "branch": "default",
673 "branch": "default",
662 "closed": false,
674 "closed": false,
663 "current": false,
675 "current": false,
664 "node": "19709c5a4e75bf938f8e349aff97438539bb729e",
676 "node": "19709c5a4e75bf938f8e349aff97438539bb729e",
665 "rev": 0
677 "rev": 0
666 }
678 }
667 ]
679 ]
668
680
669 $ hg branches --closed -T '{if(closed, "{branch}\n")}'
681 $ hg branches --closed -T '{if(closed, "{branch}\n")}'
670 c
682 c
671
683
672 $ hg branches -T '{word(0, branch)}: {desc|firstline}\n'
684 $ hg branches -T '{word(0, branch)}: {desc|firstline}\n'
673 md: merge head 2
685 md: merge head 2
674 b: reopen branch with a change
686 b: reopen branch with a change
675 a: Adding d branch
687 a: Adding d branch
676 m: head 2
688 m: head 2
677 a: Adding b branch head 2
689 a: Adding b branch head 2
678 default: Adding root node
690 default: Adding root node
679
691
680 $ cat <<'EOF' > "$TESTTMP/map-myjson"
692 $ cat <<'EOF' > "$TESTTMP/map-myjson"
681 > docheader = '\{\n'
693 > docheader = '\{\n'
682 > docfooter = '\n}\n'
694 > docfooter = '\n}\n'
683 > separator = ',\n'
695 > separator = ',\n'
684 > branches = ' {dict(branch, node|short)|json}'
696 > branches = ' {dict(branch, node|short)|json}'
685 > EOF
697 > EOF
686 $ hg branches -T "$TESTTMP/map-myjson"
698 $ hg branches -T "$TESTTMP/map-myjson"
687 {
699 {
688 {"branch": "md", "node": "c914c99f1fbb"},
700 {"branch": "md", "node": "c914c99f1fbb"},
689 {"branch": "b", "node": "e23b5505d1ad"},
701 {"branch": "b", "node": "e23b5505d1ad"},
690 {"branch": "a branch *", "node": "10ff5895aa57"}, (glob)
702 {"branch": "a branch *", "node": "10ff5895aa57"}, (glob)
691 {"branch": "m", "node": "df343b0df04f"},
703 {"branch": "m", "node": "df343b0df04f"},
692 {"branch": "a", "node": "d8cbc61dbaa6"},
704 {"branch": "a", "node": "d8cbc61dbaa6"},
693 {"branch": "default", "node": "19709c5a4e75"}
705 {"branch": "default", "node": "19709c5a4e75"}
694 }
706 }
695
707
696 $ cat <<'EOF' >> .hg/hgrc
708 $ cat <<'EOF' >> .hg/hgrc
697 > [templates]
709 > [templates]
698 > myjson = ' {dict(branch, node|short)|json}'
710 > myjson = ' {dict(branch, node|short)|json}'
699 > myjson:docheader = '\{\n'
711 > myjson:docheader = '\{\n'
700 > myjson:docfooter = '\n}\n'
712 > myjson:docfooter = '\n}\n'
701 > myjson:separator = ',\n'
713 > myjson:separator = ',\n'
702 > EOF
714 > EOF
703 $ hg branches -T myjson
715 $ hg branches -T myjson
704 {
716 {
705 {"branch": "md", "node": "c914c99f1fbb"},
717 {"branch": "md", "node": "c914c99f1fbb"},
706 {"branch": "b", "node": "e23b5505d1ad"},
718 {"branch": "b", "node": "e23b5505d1ad"},
707 {"branch": "a branch *", "node": "10ff5895aa57"}, (glob)
719 {"branch": "a branch *", "node": "10ff5895aa57"}, (glob)
708 {"branch": "m", "node": "df343b0df04f"},
720 {"branch": "m", "node": "df343b0df04f"},
709 {"branch": "a", "node": "d8cbc61dbaa6"},
721 {"branch": "a", "node": "d8cbc61dbaa6"},
710 {"branch": "default", "node": "19709c5a4e75"}
722 {"branch": "default", "node": "19709c5a4e75"}
711 }
723 }
712
724
713 $ cat <<'EOF' >> .hg/hgrc
725 $ cat <<'EOF' >> .hg/hgrc
714 > [templates]
726 > [templates]
715 > :docheader = 'should not be selected as a docheader for literal templates\n'
727 > :docheader = 'should not be selected as a docheader for literal templates\n'
716 > EOF
728 > EOF
717 $ hg branches -T '{branch}\n'
729 $ hg branches -T '{branch}\n'
718 md
730 md
719 b
731 b
720 a branch name much longer than the default justification used by branches
732 a branch name much longer than the default justification used by branches
721 m
733 m
722 a
734 a
723 default
735 default
724
736
725 Tests of revision branch name caching
737 Tests of revision branch name caching
726
738
727 We rev branch cache is updated automatically. In these tests we use a trick to
739 We rev branch cache is updated automatically. In these tests we use a trick to
728 trigger rebuilds. We remove the branch head cache and run 'hg head' to cause a
740 trigger rebuilds. We remove the branch head cache and run 'hg head' to cause a
729 rebuild that also will populate the rev branch cache.
741 rebuild that also will populate the rev branch cache.
730
742
731 revision branch cache is created when building the branch head cache
743 revision branch cache is created when building the branch head cache
732 $ rm -rf .hg/cache; hg head a -T '{rev}\n'
744 $ rm -rf .hg/cache; hg head a -T '{rev}\n'
733 5
745 5
734 $ f --hexdump --size .hg/cache/rbc-*
746 $ f --hexdump --size .hg/cache/rbc-*
735 .hg/cache/rbc-names-v1: size=92
747 .hg/cache/rbc-names-v1: size=92
736 0000: 64 65 66 61 75 6c 74 00 61 00 62 00 63 00 61 20 |default.a.b.c.a |
748 0000: 64 65 66 61 75 6c 74 00 61 00 62 00 63 00 61 20 |default.a.b.c.a |
737 0010: 62 72 61 6e 63 68 20 6e 61 6d 65 20 6d 75 63 68 |branch name much|
749 0010: 62 72 61 6e 63 68 20 6e 61 6d 65 20 6d 75 63 68 |branch name much|
738 0020: 20 6c 6f 6e 67 65 72 20 74 68 61 6e 20 74 68 65 | longer than the|
750 0020: 20 6c 6f 6e 67 65 72 20 74 68 61 6e 20 74 68 65 | longer than the|
739 0030: 20 64 65 66 61 75 6c 74 20 6a 75 73 74 69 66 69 | default justifi|
751 0030: 20 64 65 66 61 75 6c 74 20 6a 75 73 74 69 66 69 | default justifi|
740 0040: 63 61 74 69 6f 6e 20 75 73 65 64 20 62 79 20 62 |cation used by b|
752 0040: 63 61 74 69 6f 6e 20 75 73 65 64 20 62 79 20 62 |cation used by b|
741 0050: 72 61 6e 63 68 65 73 00 6d 00 6d 64 |ranches.m.md|
753 0050: 72 61 6e 63 68 65 73 00 6d 00 6d 64 |ranches.m.md|
742 .hg/cache/rbc-revs-v1: size=160
754 .hg/cache/rbc-revs-v1: size=160
743 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
755 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
744 0010: 88 1f e2 b9 00 00 00 01 ac 22 03 33 00 00 00 02 |.........".3....|
756 0010: 88 1f e2 b9 00 00 00 01 ac 22 03 33 00 00 00 02 |.........".3....|
745 0020: ae e3 9c d1 00 00 00 02 d8 cb c6 1d 00 00 00 01 |................|
757 0020: ae e3 9c d1 00 00 00 02 d8 cb c6 1d 00 00 00 01 |................|
746 0030: 58 97 36 a2 00 00 00 03 10 ff 58 95 00 00 00 04 |X.6.......X.....|
758 0030: 58 97 36 a2 00 00 00 03 10 ff 58 95 00 00 00 04 |X.6.......X.....|
747 0040: ee bb 94 44 00 00 00 02 5f 40 61 bb 00 00 00 02 |...D...._@a.....|
759 0040: ee bb 94 44 00 00 00 02 5f 40 61 bb 00 00 00 02 |...D...._@a.....|
748 0050: bf be 84 1b 00 00 00 02 d3 f1 63 45 80 00 00 02 |..........cE....|
760 0050: bf be 84 1b 00 00 00 02 d3 f1 63 45 80 00 00 02 |..........cE....|
749 0060: e3 d4 9c 05 80 00 00 02 e2 3b 55 05 00 00 00 02 |.........;U.....|
761 0060: e3 d4 9c 05 80 00 00 02 e2 3b 55 05 00 00 00 02 |.........;U.....|
750 0070: f8 94 c2 56 80 00 00 03 f3 44 76 37 00 00 00 05 |...V.....Dv7....|
762 0070: f8 94 c2 56 80 00 00 03 f3 44 76 37 00 00 00 05 |...V.....Dv7....|
751 0080: a5 8c a5 d3 00 00 00 05 df 34 3b 0d 00 00 00 05 |.........4;.....|
763 0080: a5 8c a5 d3 00 00 00 05 df 34 3b 0d 00 00 00 05 |.........4;.....|
752 0090: c9 14 c9 9f 00 00 00 06 cd 21 a8 0b 80 00 00 05 |.........!......|
764 0090: c9 14 c9 9f 00 00 00 06 cd 21 a8 0b 80 00 00 05 |.........!......|
753
765
754 no errors when revbranchcache is not writable
766 no errors when revbranchcache is not writable
755
767
756 $ echo >> .hg/cache/rbc-revs-v1
768 $ echo >> .hg/cache/rbc-revs-v1
757 $ mv .hg/cache/rbc-revs-v1 .hg/cache/rbc-revs-v1_
769 $ mv .hg/cache/rbc-revs-v1 .hg/cache/rbc-revs-v1_
758 $ mkdir .hg/cache/rbc-revs-v1
770 $ mkdir .hg/cache/rbc-revs-v1
759 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n'
771 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n'
760 5
772 5
761 $ rmdir .hg/cache/rbc-revs-v1
773 $ rmdir .hg/cache/rbc-revs-v1
762 $ mv .hg/cache/rbc-revs-v1_ .hg/cache/rbc-revs-v1
774 $ mv .hg/cache/rbc-revs-v1_ .hg/cache/rbc-revs-v1
763
775
764 no errors when wlock cannot be acquired
776 no errors when wlock cannot be acquired
765
777
766 #if unix-permissions
778 #if unix-permissions
767 $ mv .hg/cache/rbc-revs-v1 .hg/cache/rbc-revs-v1_
779 $ mv .hg/cache/rbc-revs-v1 .hg/cache/rbc-revs-v1_
768 $ rm -f .hg/cache/branch*
780 $ rm -f .hg/cache/branch*
769 $ chmod 555 .hg
781 $ chmod 555 .hg
770 $ hg head a -T '{rev}\n'
782 $ hg head a -T '{rev}\n'
771 5
783 5
772 $ chmod 755 .hg
784 $ chmod 755 .hg
773 $ mv .hg/cache/rbc-revs-v1_ .hg/cache/rbc-revs-v1
785 $ mv .hg/cache/rbc-revs-v1_ .hg/cache/rbc-revs-v1
774 #endif
786 #endif
775
787
776 recovery from invalid cache revs file with trailing data
788 recovery from invalid cache revs file with trailing data
777 $ echo >> .hg/cache/rbc-revs-v1
789 $ echo >> .hg/cache/rbc-revs-v1
778 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
790 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
779 5
791 5
780 truncating cache/rbc-revs-v1 to 160
792 truncating cache/rbc-revs-v1 to 160
781 $ f --size .hg/cache/rbc-revs*
793 $ f --size .hg/cache/rbc-revs*
782 .hg/cache/rbc-revs-v1: size=160
794 .hg/cache/rbc-revs-v1: size=160
783 recovery from invalid cache file with partial last record
795 recovery from invalid cache file with partial last record
784 $ mv .hg/cache/rbc-revs-v1 .
796 $ mv .hg/cache/rbc-revs-v1 .
785 $ f -qDB 119 rbc-revs-v1 > .hg/cache/rbc-revs-v1
797 $ f -qDB 119 rbc-revs-v1 > .hg/cache/rbc-revs-v1
786 $ f --size .hg/cache/rbc-revs*
798 $ f --size .hg/cache/rbc-revs*
787 .hg/cache/rbc-revs-v1: size=119
799 .hg/cache/rbc-revs-v1: size=119
788 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
800 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
789 5
801 5
790 truncating cache/rbc-revs-v1 to 112
802 truncating cache/rbc-revs-v1 to 112
791 $ f --size .hg/cache/rbc-revs*
803 $ f --size .hg/cache/rbc-revs*
792 .hg/cache/rbc-revs-v1: size=160
804 .hg/cache/rbc-revs-v1: size=160
793 recovery from invalid cache file with missing record - no truncation
805 recovery from invalid cache file with missing record - no truncation
794 $ mv .hg/cache/rbc-revs-v1 .
806 $ mv .hg/cache/rbc-revs-v1 .
795 $ f -qDB 112 rbc-revs-v1 > .hg/cache/rbc-revs-v1
807 $ f -qDB 112 rbc-revs-v1 > .hg/cache/rbc-revs-v1
796 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
808 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
797 5
809 5
798 $ f --size .hg/cache/rbc-revs*
810 $ f --size .hg/cache/rbc-revs*
799 .hg/cache/rbc-revs-v1: size=160
811 .hg/cache/rbc-revs-v1: size=160
800 recovery from invalid cache file with some bad records
812 recovery from invalid cache file with some bad records
801 $ mv .hg/cache/rbc-revs-v1 .
813 $ mv .hg/cache/rbc-revs-v1 .
802 $ f -qDB 8 rbc-revs-v1 > .hg/cache/rbc-revs-v1
814 $ f -qDB 8 rbc-revs-v1 > .hg/cache/rbc-revs-v1
803 $ f --size .hg/cache/rbc-revs*
815 $ f --size .hg/cache/rbc-revs*
804 .hg/cache/rbc-revs-v1: size=8
816 .hg/cache/rbc-revs-v1: size=8
805 $ f -qDB 112 rbc-revs-v1 >> .hg/cache/rbc-revs-v1
817 $ f -qDB 112 rbc-revs-v1 >> .hg/cache/rbc-revs-v1
806 $ f --size .hg/cache/rbc-revs*
818 $ f --size .hg/cache/rbc-revs*
807 .hg/cache/rbc-revs-v1: size=120
819 .hg/cache/rbc-revs-v1: size=120
808 $ hg log -r 'branch(.)' -T '{rev} ' --debug
820 $ hg log -r 'branch(.)' -T '{rev} ' --debug
809 history modification detected - truncating revision branch cache to revision 13
821 history modification detected - truncating revision branch cache to revision 13
810 history modification detected - truncating revision branch cache to revision 1
822 history modification detected - truncating revision branch cache to revision 1
811 3 4 8 9 10 11 12 13 truncating cache/rbc-revs-v1 to 8
823 3 4 8 9 10 11 12 13 truncating cache/rbc-revs-v1 to 8
812 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
824 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
813 5
825 5
814 truncating cache/rbc-revs-v1 to 104
826 truncating cache/rbc-revs-v1 to 104
815 $ f --size --hexdump --bytes=16 .hg/cache/rbc-revs*
827 $ f --size --hexdump --bytes=16 .hg/cache/rbc-revs*
816 .hg/cache/rbc-revs-v1: size=160
828 .hg/cache/rbc-revs-v1: size=160
817 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
829 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
818 cache is updated when committing
830 cache is updated when committing
819 $ hg branch i-will-regret-this
831 $ hg branch i-will-regret-this
820 marked working directory as branch i-will-regret-this
832 marked working directory as branch i-will-regret-this
821 $ hg ci -m regrets
833 $ hg ci -m regrets
822 $ f --size .hg/cache/rbc-*
834 $ f --size .hg/cache/rbc-*
823 .hg/cache/rbc-names-v1: size=111
835 .hg/cache/rbc-names-v1: size=111
824 .hg/cache/rbc-revs-v1: size=168
836 .hg/cache/rbc-revs-v1: size=168
825 update after rollback - the cache will be correct but rbc-names will will still
837 update after rollback - the cache will be correct but rbc-names will will still
826 contain the branch name even though it no longer is used
838 contain the branch name even though it no longer is used
827 $ hg up -qr '.^'
839 $ hg up -qr '.^'
828 $ hg rollback -qf
840 $ hg rollback -qf
829 $ f --size --hexdump .hg/cache/rbc-*
841 $ f --size --hexdump .hg/cache/rbc-*
830 .hg/cache/rbc-names-v1: size=111
842 .hg/cache/rbc-names-v1: size=111
831 0000: 64 65 66 61 75 6c 74 00 61 00 62 00 63 00 61 20 |default.a.b.c.a |
843 0000: 64 65 66 61 75 6c 74 00 61 00 62 00 63 00 61 20 |default.a.b.c.a |
832 0010: 62 72 61 6e 63 68 20 6e 61 6d 65 20 6d 75 63 68 |branch name much|
844 0010: 62 72 61 6e 63 68 20 6e 61 6d 65 20 6d 75 63 68 |branch name much|
833 0020: 20 6c 6f 6e 67 65 72 20 74 68 61 6e 20 74 68 65 | longer than the|
845 0020: 20 6c 6f 6e 67 65 72 20 74 68 61 6e 20 74 68 65 | longer than the|
834 0030: 20 64 65 66 61 75 6c 74 20 6a 75 73 74 69 66 69 | default justifi|
846 0030: 20 64 65 66 61 75 6c 74 20 6a 75 73 74 69 66 69 | default justifi|
835 0040: 63 61 74 69 6f 6e 20 75 73 65 64 20 62 79 20 62 |cation used by b|
847 0040: 63 61 74 69 6f 6e 20 75 73 65 64 20 62 79 20 62 |cation used by b|
836 0050: 72 61 6e 63 68 65 73 00 6d 00 6d 64 00 69 2d 77 |ranches.m.md.i-w|
848 0050: 72 61 6e 63 68 65 73 00 6d 00 6d 64 00 69 2d 77 |ranches.m.md.i-w|
837 0060: 69 6c 6c 2d 72 65 67 72 65 74 2d 74 68 69 73 |ill-regret-this|
849 0060: 69 6c 6c 2d 72 65 67 72 65 74 2d 74 68 69 73 |ill-regret-this|
838 .hg/cache/rbc-revs-v1: size=160
850 .hg/cache/rbc-revs-v1: size=160
839 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
851 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
840 0010: 88 1f e2 b9 00 00 00 01 ac 22 03 33 00 00 00 02 |.........".3....|
852 0010: 88 1f e2 b9 00 00 00 01 ac 22 03 33 00 00 00 02 |.........".3....|
841 0020: ae e3 9c d1 00 00 00 02 d8 cb c6 1d 00 00 00 01 |................|
853 0020: ae e3 9c d1 00 00 00 02 d8 cb c6 1d 00 00 00 01 |................|
842 0030: 58 97 36 a2 00 00 00 03 10 ff 58 95 00 00 00 04 |X.6.......X.....|
854 0030: 58 97 36 a2 00 00 00 03 10 ff 58 95 00 00 00 04 |X.6.......X.....|
843 0040: ee bb 94 44 00 00 00 02 5f 40 61 bb 00 00 00 02 |...D...._@a.....|
855 0040: ee bb 94 44 00 00 00 02 5f 40 61 bb 00 00 00 02 |...D...._@a.....|
844 0050: bf be 84 1b 00 00 00 02 d3 f1 63 45 80 00 00 02 |..........cE....|
856 0050: bf be 84 1b 00 00 00 02 d3 f1 63 45 80 00 00 02 |..........cE....|
845 0060: e3 d4 9c 05 80 00 00 02 e2 3b 55 05 00 00 00 02 |.........;U.....|
857 0060: e3 d4 9c 05 80 00 00 02 e2 3b 55 05 00 00 00 02 |.........;U.....|
846 0070: f8 94 c2 56 80 00 00 03 f3 44 76 37 00 00 00 05 |...V.....Dv7....|
858 0070: f8 94 c2 56 80 00 00 03 f3 44 76 37 00 00 00 05 |...V.....Dv7....|
847 0080: a5 8c a5 d3 00 00 00 05 df 34 3b 0d 00 00 00 05 |.........4;.....|
859 0080: a5 8c a5 d3 00 00 00 05 df 34 3b 0d 00 00 00 05 |.........4;.....|
848 0090: c9 14 c9 9f 00 00 00 06 cd 21 a8 0b 80 00 00 05 |.........!......|
860 0090: c9 14 c9 9f 00 00 00 06 cd 21 a8 0b 80 00 00 05 |.........!......|
849 cache is updated/truncated when stripping - it is thus very hard to get in a
861 cache is updated/truncated when stripping - it is thus very hard to get in a
850 situation where the cache is out of sync and the hash check detects it
862 situation where the cache is out of sync and the hash check detects it
851 $ hg --config extensions.strip= strip -r tip --nob
863 $ hg --config extensions.strip= strip -r tip --nob
852 $ f --size .hg/cache/rbc-revs*
864 $ f --size .hg/cache/rbc-revs*
853 .hg/cache/rbc-revs-v1: size=152
865 .hg/cache/rbc-revs-v1: size=152
854
866
855 cache is rebuilt when corruption is detected
867 cache is rebuilt when corruption is detected
856 $ echo > .hg/cache/rbc-names-v1
868 $ echo > .hg/cache/rbc-names-v1
857 $ hg log -r '5:&branch(.)' -T '{rev} ' --debug
869 $ hg log -r '5:&branch(.)' -T '{rev} ' --debug
858 referenced branch names not found - rebuilding revision branch cache from scratch
870 referenced branch names not found - rebuilding revision branch cache from scratch
859 8 9 10 11 12 13 truncating cache/rbc-revs-v1 to 40
871 8 9 10 11 12 13 truncating cache/rbc-revs-v1 to 40
860 $ f --size --hexdump .hg/cache/rbc-*
872 $ f --size --hexdump .hg/cache/rbc-*
861 .hg/cache/rbc-names-v1: size=84
873 .hg/cache/rbc-names-v1: size=84
862 0000: 62 00 61 00 63 00 61 20 62 72 61 6e 63 68 20 6e |b.a.c.a branch n|
874 0000: 62 00 61 00 63 00 61 20 62 72 61 6e 63 68 20 6e |b.a.c.a branch n|
863 0010: 61 6d 65 20 6d 75 63 68 20 6c 6f 6e 67 65 72 20 |ame much longer |
875 0010: 61 6d 65 20 6d 75 63 68 20 6c 6f 6e 67 65 72 20 |ame much longer |
864 0020: 74 68 61 6e 20 74 68 65 20 64 65 66 61 75 6c 74 |than the default|
876 0020: 74 68 61 6e 20 74 68 65 20 64 65 66 61 75 6c 74 |than the default|
865 0030: 20 6a 75 73 74 69 66 69 63 61 74 69 6f 6e 20 75 | justification u|
877 0030: 20 6a 75 73 74 69 66 69 63 61 74 69 6f 6e 20 75 | justification u|
866 0040: 73 65 64 20 62 79 20 62 72 61 6e 63 68 65 73 00 |sed by branches.|
878 0040: 73 65 64 20 62 79 20 62 72 61 6e 63 68 65 73 00 |sed by branches.|
867 0050: 6d 00 6d 64 |m.md|
879 0050: 6d 00 6d 64 |m.md|
868 .hg/cache/rbc-revs-v1: size=152
880 .hg/cache/rbc-revs-v1: size=152
869 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
881 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
870 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
882 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
871 0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 01 |................|
883 0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 01 |................|
872 0030: 58 97 36 a2 00 00 00 02 10 ff 58 95 00 00 00 03 |X.6.......X.....|
884 0030: 58 97 36 a2 00 00 00 02 10 ff 58 95 00 00 00 03 |X.6.......X.....|
873 0040: ee bb 94 44 00 00 00 00 5f 40 61 bb 00 00 00 00 |...D...._@a.....|
885 0040: ee bb 94 44 00 00 00 00 5f 40 61 bb 00 00 00 00 |...D...._@a.....|
874 0050: bf be 84 1b 00 00 00 00 d3 f1 63 45 80 00 00 00 |..........cE....|
886 0050: bf be 84 1b 00 00 00 00 d3 f1 63 45 80 00 00 00 |..........cE....|
875 0060: e3 d4 9c 05 80 00 00 00 e2 3b 55 05 00 00 00 00 |.........;U.....|
887 0060: e3 d4 9c 05 80 00 00 00 e2 3b 55 05 00 00 00 00 |.........;U.....|
876 0070: f8 94 c2 56 80 00 00 02 f3 44 76 37 00 00 00 04 |...V.....Dv7....|
888 0070: f8 94 c2 56 80 00 00 02 f3 44 76 37 00 00 00 04 |...V.....Dv7....|
877 0080: a5 8c a5 d3 00 00 00 04 df 34 3b 0d 00 00 00 04 |.........4;.....|
889 0080: a5 8c a5 d3 00 00 00 04 df 34 3b 0d 00 00 00 04 |.........4;.....|
878 0090: c9 14 c9 9f 00 00 00 05 |........|
890 0090: c9 14 c9 9f 00 00 00 05 |........|
879
891
880 Test that cache files are created and grows correctly:
892 Test that cache files are created and grows correctly:
881
893
882 $ rm .hg/cache/rbc*
894 $ rm .hg/cache/rbc*
883 $ hg log -r "5 & branch(5)" -T "{rev}\n"
895 $ hg log -r "5 & branch(5)" -T "{rev}\n"
884 5
896 5
885 $ f --size --hexdump .hg/cache/rbc-*
897 $ f --size --hexdump .hg/cache/rbc-*
886 .hg/cache/rbc-names-v1: size=1
898 .hg/cache/rbc-names-v1: size=1
887 0000: 61 |a|
899 0000: 61 |a|
888 .hg/cache/rbc-revs-v1: size=152
900 .hg/cache/rbc-revs-v1: size=152
889 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
901 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
890 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
902 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
891 0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 00 |................|
903 0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 00 |................|
892 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
904 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
893 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
905 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
894 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
906 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
895 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
907 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
896 0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
908 0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
897 0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
909 0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
898 0090: 00 00 00 00 00 00 00 00 |........|
910 0090: 00 00 00 00 00 00 00 00 |........|
899
911
900 $ cd ..
912 $ cd ..
901
913
902 Test for multiple incorrect branch cache entries:
914 Test for multiple incorrect branch cache entries:
903
915
904 $ hg init b
916 $ hg init b
905 $ cd b
917 $ cd b
906 $ touch f
918 $ touch f
907 $ hg ci -Aqmf
919 $ hg ci -Aqmf
908 $ echo >> f
920 $ echo >> f
909 $ hg ci -Amf
921 $ hg ci -Amf
910 $ hg branch -q branch
922 $ hg branch -q branch
911 $ hg ci -Amf
923 $ hg ci -Amf
912
924
913 $ f --size --hexdump .hg/cache/rbc-*
925 $ f --size --hexdump .hg/cache/rbc-*
914 .hg/cache/rbc-names-v1: size=14
926 .hg/cache/rbc-names-v1: size=14
915 0000: 64 65 66 61 75 6c 74 00 62 72 61 6e 63 68 |default.branch|
927 0000: 64 65 66 61 75 6c 74 00 62 72 61 6e 63 68 |default.branch|
916 .hg/cache/rbc-revs-v1: size=24
928 .hg/cache/rbc-revs-v1: size=24
917 0000: 66 e5 f5 aa 00 00 00 00 fa 4c 04 e5 00 00 00 00 |f........L......|
929 0000: 66 e5 f5 aa 00 00 00 00 fa 4c 04 e5 00 00 00 00 |f........L......|
918 0010: 56 46 78 69 00 00 00 01 |VFxi....|
930 0010: 56 46 78 69 00 00 00 01 |VFxi....|
919 $ : > .hg/cache/rbc-revs-v1
931 $ : > .hg/cache/rbc-revs-v1
920
932
921 No superfluous rebuilding of cache:
933 No superfluous rebuilding of cache:
922 $ hg log -r "branch(null)&branch(branch)" --debug
934 $ hg log -r "branch(null)&branch(branch)" --debug
923 $ f --size --hexdump .hg/cache/rbc-*
935 $ f --size --hexdump .hg/cache/rbc-*
924 .hg/cache/rbc-names-v1: size=14
936 .hg/cache/rbc-names-v1: size=14
925 0000: 64 65 66 61 75 6c 74 00 62 72 61 6e 63 68 |default.branch|
937 0000: 64 65 66 61 75 6c 74 00 62 72 61 6e 63 68 |default.branch|
926 .hg/cache/rbc-revs-v1: size=24
938 .hg/cache/rbc-revs-v1: size=24
927 0000: 66 e5 f5 aa 00 00 00 00 fa 4c 04 e5 00 00 00 00 |f........L......|
939 0000: 66 e5 f5 aa 00 00 00 00 fa 4c 04 e5 00 00 00 00 |f........L......|
928 0010: 56 46 78 69 00 00 00 01 |VFxi....|
940 0010: 56 46 78 69 00 00 00 01 |VFxi....|
929
941
930 $ cd ..
942 $ cd ..
@@ -1,408 +1,408 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 config
16 config
17 copy
17 copy
18 diff
18 diff
19 export
19 export
20 files
20 files
21 forget
21 forget
22 graft
22 graft
23 grep
23 grep
24 heads
24 heads
25 help
25 help
26 identify
26 identify
27 import
27 import
28 incoming
28 incoming
29 init
29 init
30 locate
30 locate
31 log
31 log
32 manifest
32 manifest
33 merge
33 merge
34 outgoing
34 outgoing
35 parents
35 parents
36 paths
36 paths
37 phase
37 phase
38 pull
38 pull
39 push
39 push
40 recover
40 recover
41 remove
41 remove
42 rename
42 rename
43 resolve
43 resolve
44 revert
44 revert
45 rollback
45 rollback
46 root
46 root
47 serve
47 serve
48 status
48 status
49 summary
49 summary
50 tag
50 tag
51 tags
51 tags
52 tip
52 tip
53 unbundle
53 unbundle
54 update
54 update
55 verify
55 verify
56 version
56 version
57
57
58 Show all commands that start with "a"
58 Show all commands that start with "a"
59 $ hg debugcomplete a
59 $ hg debugcomplete a
60 add
60 add
61 addremove
61 addremove
62 annotate
62 annotate
63 archive
63 archive
64
64
65 Do not show debug commands if there are other candidates
65 Do not show debug commands if there are other candidates
66 $ hg debugcomplete d
66 $ hg debugcomplete d
67 diff
67 diff
68
68
69 Show debug commands if there are no other candidates
69 Show debug commands if there are no other candidates
70 $ hg debugcomplete debug
70 $ hg debugcomplete debug
71 debugancestor
71 debugancestor
72 debugapplystreamclonebundle
72 debugapplystreamclonebundle
73 debugbuilddag
73 debugbuilddag
74 debugbundle
74 debugbundle
75 debugcapabilities
75 debugcapabilities
76 debugcheckstate
76 debugcheckstate
77 debugcolor
77 debugcolor
78 debugcommands
78 debugcommands
79 debugcomplete
79 debugcomplete
80 debugconfig
80 debugconfig
81 debugcreatestreamclonebundle
81 debugcreatestreamclonebundle
82 debugdag
82 debugdag
83 debugdata
83 debugdata
84 debugdate
84 debugdate
85 debugdeltachain
85 debugdeltachain
86 debugdirstate
86 debugdirstate
87 debugdiscovery
87 debugdiscovery
88 debugdownload
88 debugdownload
89 debugextensions
89 debugextensions
90 debugfileset
90 debugfileset
91 debugformat
91 debugformat
92 debugfsinfo
92 debugfsinfo
93 debuggetbundle
93 debuggetbundle
94 debugignore
94 debugignore
95 debugindex
95 debugindex
96 debugindexdot
96 debugindexdot
97 debugindexstats
97 debugindexstats
98 debuginstall
98 debuginstall
99 debugknown
99 debugknown
100 debuglabelcomplete
100 debuglabelcomplete
101 debuglocks
101 debuglocks
102 debugmanifestfulltextcache
102 debugmanifestfulltextcache
103 debugmergestate
103 debugmergestate
104 debugnamecomplete
104 debugnamecomplete
105 debugobsolete
105 debugobsolete
106 debugpathcomplete
106 debugpathcomplete
107 debugpeer
107 debugpeer
108 debugpickmergetool
108 debugpickmergetool
109 debugpushkey
109 debugpushkey
110 debugpvec
110 debugpvec
111 debugrebuilddirstate
111 debugrebuilddirstate
112 debugrebuildfncache
112 debugrebuildfncache
113 debugrename
113 debugrename
114 debugrevlog
114 debugrevlog
115 debugrevlogindex
115 debugrevlogindex
116 debugrevspec
116 debugrevspec
117 debugserve
117 debugserve
118 debugsetparents
118 debugsetparents
119 debugssl
119 debugssl
120 debugsub
120 debugsub
121 debugsuccessorssets
121 debugsuccessorssets
122 debugtemplate
122 debugtemplate
123 debuguigetpass
123 debuguigetpass
124 debuguiprompt
124 debuguiprompt
125 debugupdatecaches
125 debugupdatecaches
126 debugupgraderepo
126 debugupgraderepo
127 debugwalk
127 debugwalk
128 debugwhyunstable
128 debugwhyunstable
129 debugwireargs
129 debugwireargs
130 debugwireproto
130 debugwireproto
131
131
132 Do not show the alias of a debug command if there are other candidates
132 Do not show the alias of a debug command if there are other candidates
133 (this should hide rawcommit)
133 (this should hide rawcommit)
134 $ hg debugcomplete r
134 $ hg debugcomplete r
135 recover
135 recover
136 remove
136 remove
137 rename
137 rename
138 resolve
138 resolve
139 revert
139 revert
140 rollback
140 rollback
141 root
141 root
142 Show the alias of a debug command if there are no other candidates
142 Show the alias of a debug command if there are no other candidates
143 $ hg debugcomplete rawc
143 $ hg debugcomplete rawc
144
144
145
145
146 Show the global options
146 Show the global options
147 $ hg debugcomplete --options | sort
147 $ hg debugcomplete --options | sort
148 --color
148 --color
149 --config
149 --config
150 --cwd
150 --cwd
151 --debug
151 --debug
152 --debugger
152 --debugger
153 --encoding
153 --encoding
154 --encodingmode
154 --encodingmode
155 --help
155 --help
156 --hidden
156 --hidden
157 --noninteractive
157 --noninteractive
158 --pager
158 --pager
159 --profile
159 --profile
160 --quiet
160 --quiet
161 --repository
161 --repository
162 --time
162 --time
163 --traceback
163 --traceback
164 --verbose
164 --verbose
165 --version
165 --version
166 -R
166 -R
167 -h
167 -h
168 -q
168 -q
169 -v
169 -v
170 -y
170 -y
171
171
172 Show the options for the "serve" command
172 Show the options for the "serve" command
173 $ hg debugcomplete --options serve | sort
173 $ hg debugcomplete --options serve | sort
174 --accesslog
174 --accesslog
175 --address
175 --address
176 --certificate
176 --certificate
177 --cmdserver
177 --cmdserver
178 --color
178 --color
179 --config
179 --config
180 --cwd
180 --cwd
181 --daemon
181 --daemon
182 --daemon-postexec
182 --daemon-postexec
183 --debug
183 --debug
184 --debugger
184 --debugger
185 --encoding
185 --encoding
186 --encodingmode
186 --encodingmode
187 --errorlog
187 --errorlog
188 --help
188 --help
189 --hidden
189 --hidden
190 --ipv6
190 --ipv6
191 --name
191 --name
192 --noninteractive
192 --noninteractive
193 --pager
193 --pager
194 --pid-file
194 --pid-file
195 --port
195 --port
196 --prefix
196 --prefix
197 --print-url
197 --print-url
198 --profile
198 --profile
199 --quiet
199 --quiet
200 --repository
200 --repository
201 --stdio
201 --stdio
202 --style
202 --style
203 --subrepos
203 --subrepos
204 --templates
204 --templates
205 --time
205 --time
206 --traceback
206 --traceback
207 --verbose
207 --verbose
208 --version
208 --version
209 --web-conf
209 --web-conf
210 -6
210 -6
211 -A
211 -A
212 -E
212 -E
213 -R
213 -R
214 -S
214 -S
215 -a
215 -a
216 -d
216 -d
217 -h
217 -h
218 -n
218 -n
219 -p
219 -p
220 -q
220 -q
221 -t
221 -t
222 -v
222 -v
223 -y
223 -y
224
224
225 Show an error if we use --options with an ambiguous abbreviation
225 Show an error if we use --options with an ambiguous abbreviation
226 $ hg debugcomplete --options s
226 $ hg debugcomplete --options s
227 hg: command 's' is ambiguous:
227 hg: command 's' is ambiguous:
228 serve showconfig status summary
228 serve showconfig status summary
229 [255]
229 [255]
230
230
231 Show all commands + options
231 Show all commands + options
232 $ hg debugcommands
232 $ hg debugcommands
233 add: include, exclude, subrepos, dry-run
233 add: include, exclude, subrepos, dry-run
234 addremove: similarity, subrepos, include, exclude, dry-run
234 addremove: similarity, subrepos, include, exclude, dry-run
235 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
235 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
236 archive: no-decode, prefix, rev, type, subrepos, include, exclude
236 archive: no-decode, prefix, rev, type, subrepos, include, exclude
237 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
237 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
238 bisect: reset, good, bad, skip, extend, command, noupdate
238 bisect: reset, good, bad, skip, extend, command, noupdate
239 bookmarks: force, rev, delete, rename, inactive, list, template
239 bookmarks: force, rev, delete, rename, inactive, list, template
240 branch: force, clean, rev
240 branch: force, clean, rev
241 branches: active, closed, template
241 branches: active, closed, rev, template
242 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
242 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
243 cat: output, rev, decode, include, exclude, template
243 cat: output, rev, decode, include, exclude, template
244 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
244 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
245 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
245 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
246 config: untrusted, edit, local, global, template
246 config: untrusted, edit, local, global, template
247 copy: after, force, include, exclude, dry-run
247 copy: after, force, include, exclude, dry-run
248 debugancestor:
248 debugancestor:
249 debugapplystreamclonebundle:
249 debugapplystreamclonebundle:
250 debugbuilddag: mergeable-file, overwritten-file, new-file
250 debugbuilddag: mergeable-file, overwritten-file, new-file
251 debugbundle: all, part-type, spec
251 debugbundle: all, part-type, spec
252 debugcapabilities:
252 debugcapabilities:
253 debugcheckstate:
253 debugcheckstate:
254 debugcolor: style
254 debugcolor: style
255 debugcommands:
255 debugcommands:
256 debugcomplete: options
256 debugcomplete: options
257 debugcreatestreamclonebundle:
257 debugcreatestreamclonebundle:
258 debugdag: tags, branches, dots, spaces
258 debugdag: tags, branches, dots, spaces
259 debugdata: changelog, manifest, dir
259 debugdata: changelog, manifest, dir
260 debugdate: extended
260 debugdate: extended
261 debugdeltachain: changelog, manifest, dir, template
261 debugdeltachain: changelog, manifest, dir, template
262 debugdirstate: nodates, dates, datesort
262 debugdirstate: nodates, dates, datesort
263 debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure
263 debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure
264 debugdownload: output
264 debugdownload: output
265 debugextensions: template
265 debugextensions: template
266 debugfileset: rev, all-files, show-matcher, show-stage
266 debugfileset: rev, all-files, show-matcher, show-stage
267 debugformat: template
267 debugformat: template
268 debugfsinfo:
268 debugfsinfo:
269 debuggetbundle: head, common, type
269 debuggetbundle: head, common, type
270 debugignore:
270 debugignore:
271 debugindex: changelog, manifest, dir, template
271 debugindex: changelog, manifest, dir, template
272 debugindexdot: changelog, manifest, dir
272 debugindexdot: changelog, manifest, dir
273 debugindexstats:
273 debugindexstats:
274 debuginstall: template
274 debuginstall: template
275 debugknown:
275 debugknown:
276 debuglabelcomplete:
276 debuglabelcomplete:
277 debuglocks: force-lock, force-wlock, set-lock, set-wlock
277 debuglocks: force-lock, force-wlock, set-lock, set-wlock
278 debugmanifestfulltextcache: clear, add
278 debugmanifestfulltextcache: clear, add
279 debugmergestate:
279 debugmergestate:
280 debugnamecomplete:
280 debugnamecomplete:
281 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
281 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
282 debugpathcomplete: full, normal, added, removed
282 debugpathcomplete: full, normal, added, removed
283 debugpeer:
283 debugpeer:
284 debugpickmergetool: rev, changedelete, include, exclude, tool
284 debugpickmergetool: rev, changedelete, include, exclude, tool
285 debugpushkey:
285 debugpushkey:
286 debugpvec:
286 debugpvec:
287 debugrebuilddirstate: rev, minimal
287 debugrebuilddirstate: rev, minimal
288 debugrebuildfncache:
288 debugrebuildfncache:
289 debugrename: rev
289 debugrename: rev
290 debugrevlog: changelog, manifest, dir, dump
290 debugrevlog: changelog, manifest, dir, dump
291 debugrevlogindex: changelog, manifest, dir, format
291 debugrevlogindex: changelog, manifest, dir, format
292 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
292 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
293 debugserve: sshstdio, logiofd, logiofile
293 debugserve: sshstdio, logiofd, logiofile
294 debugsetparents:
294 debugsetparents:
295 debugssl:
295 debugssl:
296 debugsub: rev
296 debugsub: rev
297 debugsuccessorssets: closest
297 debugsuccessorssets: closest
298 debugtemplate: rev, define
298 debugtemplate: rev, define
299 debuguigetpass: prompt
299 debuguigetpass: prompt
300 debuguiprompt: prompt
300 debuguiprompt: prompt
301 debugupdatecaches:
301 debugupdatecaches:
302 debugupgraderepo: optimize, run
302 debugupgraderepo: optimize, run
303 debugwalk: include, exclude
303 debugwalk: include, exclude
304 debugwhyunstable:
304 debugwhyunstable:
305 debugwireargs: three, four, five, ssh, remotecmd, insecure
305 debugwireargs: three, four, five, ssh, remotecmd, insecure
306 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
306 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
307 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
307 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
308 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
308 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
309 files: rev, print0, include, exclude, template, subrepos
309 files: rev, print0, include, exclude, template, subrepos
310 forget: interactive, include, exclude, dry-run
310 forget: interactive, include, exclude, dry-run
311 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
311 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
312 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
312 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
313 heads: rev, topo, active, closed, style, template
313 heads: rev, topo, active, closed, style, template
314 help: extension, command, keyword, system
314 help: extension, command, keyword, system
315 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
315 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
316 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
316 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
317 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
317 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
318 init: ssh, remotecmd, insecure
318 init: ssh, remotecmd, insecure
319 locate: rev, print0, fullpath, include, exclude
319 locate: rev, print0, fullpath, include, exclude
320 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
320 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
321 manifest: rev, all, template
321 manifest: rev, all, template
322 merge: force, rev, preview, abort, tool
322 merge: force, rev, preview, abort, tool
323 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
323 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
324 parents: rev, style, template
324 parents: rev, style, template
325 paths: template
325 paths: template
326 phase: public, draft, secret, force, rev
326 phase: public, draft, secret, force, rev
327 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
327 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
328 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
328 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
329 recover:
329 recover:
330 remove: after, force, subrepos, include, exclude, dry-run
330 remove: after, force, subrepos, include, exclude, dry-run
331 rename: after, force, include, exclude, dry-run
331 rename: after, force, include, exclude, dry-run
332 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
332 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
333 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
333 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
334 rollback: dry-run, force
334 rollback: dry-run, force
335 root:
335 root:
336 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
336 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
337 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
337 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
338 summary: remote
338 summary: remote
339 tag: force, local, rev, remove, edit, message, date, user
339 tag: force, local, rev, remove, edit, message, date, user
340 tags: template
340 tags: template
341 tip: patch, git, style, template
341 tip: patch, git, style, template
342 unbundle: update
342 unbundle: update
343 update: clean, check, merge, date, rev, tool
343 update: clean, check, merge, date, rev, tool
344 verify:
344 verify:
345 version: template
345 version: template
346
346
347 $ hg init a
347 $ hg init a
348 $ cd a
348 $ cd a
349 $ echo fee > fee
349 $ echo fee > fee
350 $ hg ci -q -Amfee
350 $ hg ci -q -Amfee
351 $ hg tag fee
351 $ hg tag fee
352 $ mkdir fie
352 $ mkdir fie
353 $ echo dead > fie/dead
353 $ echo dead > fie/dead
354 $ echo live > fie/live
354 $ echo live > fie/live
355 $ hg bookmark fo
355 $ hg bookmark fo
356 $ hg branch -q fie
356 $ hg branch -q fie
357 $ hg ci -q -Amfie
357 $ hg ci -q -Amfie
358 $ echo fo > fo
358 $ echo fo > fo
359 $ hg branch -qf default
359 $ hg branch -qf default
360 $ hg ci -q -Amfo
360 $ hg ci -q -Amfo
361 $ echo Fum > Fum
361 $ echo Fum > Fum
362 $ hg ci -q -AmFum
362 $ hg ci -q -AmFum
363 $ hg bookmark Fum
363 $ hg bookmark Fum
364
364
365 Test debugpathcomplete
365 Test debugpathcomplete
366
366
367 $ hg debugpathcomplete f
367 $ hg debugpathcomplete f
368 fee
368 fee
369 fie
369 fie
370 fo
370 fo
371 $ hg debugpathcomplete -f f
371 $ hg debugpathcomplete -f f
372 fee
372 fee
373 fie/dead
373 fie/dead
374 fie/live
374 fie/live
375 fo
375 fo
376
376
377 $ hg rm Fum
377 $ hg rm Fum
378 $ hg debugpathcomplete -r F
378 $ hg debugpathcomplete -r F
379 Fum
379 Fum
380
380
381 Test debugnamecomplete
381 Test debugnamecomplete
382
382
383 $ hg debugnamecomplete
383 $ hg debugnamecomplete
384 Fum
384 Fum
385 default
385 default
386 fee
386 fee
387 fie
387 fie
388 fo
388 fo
389 tip
389 tip
390 $ hg debugnamecomplete f
390 $ hg debugnamecomplete f
391 fee
391 fee
392 fie
392 fie
393 fo
393 fo
394
394
395 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
395 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
396 used for completions in some shells.
396 used for completions in some shells.
397
397
398 $ hg debuglabelcomplete
398 $ hg debuglabelcomplete
399 Fum
399 Fum
400 default
400 default
401 fee
401 fee
402 fie
402 fie
403 fo
403 fo
404 tip
404 tip
405 $ hg debuglabelcomplete f
405 $ hg debuglabelcomplete f
406 fee
406 fee
407 fie
407 fie
408 fo
408 fo
General Comments 0
You need to be logged in to leave comments. Login now